pyncraft 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pyncraft/__init__.py ADDED
File without changes
pyncraft/block.py ADDED
@@ -0,0 +1,103 @@
1
+ '''
2
+ This isn't tested (and isn't that useful since the 1.13/FruitJuice update),
3
+ but has been modified with the intent of maintaining backward compatibility
4
+ with mcpi-developed programs, and may be extended as a list of allowed blocks.
5
+ NOTE: See data/blocks_1.19.csv for many more available blocks
6
+ '''
7
+ class Block:
8
+ """Minecraft PI block description. Can be sent to Minecraft.setBlock/s"""
9
+ def __init__(self, id, data=0):
10
+ self.id = id
11
+ self.data = data
12
+
13
+ def __cmp__(self, rhs):
14
+ return hash(self) - hash(rhs)
15
+
16
+ def __eq__(self, rhs):
17
+ return self.id == rhs.id and self.data == rhs.data
18
+
19
+ def __hash__(self):
20
+ return (self.id << 8) + self.data
21
+
22
+ def withData(self, data):
23
+ return Block(self.id, data)
24
+
25
+ def __iter__(self):
26
+ """Allows a Block to be sent whenever id [and data] is needed"""
27
+ return iter((self.id, self.data))
28
+
29
+ def __repr__(self):
30
+ return "Block(%d, %d)"%(self.id, self.data)
31
+
32
+ AIR = Block("AIR")
33
+ STONE = Block("STONE")
34
+ GRASS = Block("GRASS_BLOCK")
35
+ DIRT = Block("DIRT")
36
+ COBBLESTONE = Block("COBBLESTONE")
37
+ WOOD_PLANKS = Block("OAK_PLANKS")
38
+ SAPLING = Block("OAK_SAPLING")
39
+ BEDROCK = Block("BEDROCK")
40
+ WATER_FLOWING = Block("WATER")
41
+ WATER = WATER_FLOWING
42
+ WATER_STATIONARY = Block("WATER")
43
+ LAVA_FLOWING = Block("LAVA")
44
+ LAVA = LAVA_FLOWING
45
+ LAVA_STATIONARY = Block("LAVA")
46
+ SAND = Block("SAND")
47
+ GRAVEL = Block("GRAVEL")
48
+ GOLD_ORE = Block("GOLD_ORE")
49
+ IRON_ORE = Block("IRON_ORE")
50
+ COAL_ORE = Block("COAL_ORE")
51
+ WOOD = Block("OAK_LOG")
52
+ LEAVES = Block("OAK_LEAVES")
53
+ GLASS = Block("GLASS")
54
+ LAPIS_LAZULI_ORE = Block("LAPIS_ORE")
55
+ LAPIS_LAZULI_BLOCK = Block("LAPIS_BLOCK")
56
+ SANDSTONE = Block("SANDSTONE")
57
+ BED = Block("WHITE_BED") # NOTE: this doesn't really work (2-block piece needs special handling)
58
+ COBWEB = Block("COBWEB")
59
+ GRASS_TALL = Block("TALL_GRASS")
60
+ WOOL = Block("WHITE_WOOL")
61
+ FLOWER_YELLOW = Block("DANDELION")
62
+ FLOWER_CYAN = Block(38)
63
+ MUSHROOM_BROWN = Block("BROWN_MUSHROOM")
64
+ MUSHROOM_RED = Block("RED_MUSHROOM")
65
+ GOLD_BLOCK = Block("GOLD_BLOCK")
66
+ IRON_BLOCK = Block("IRON_BLOCK")
67
+ STONE_SLAB_DOUBLE = Block(43)
68
+ STONE_SLAB = Block("STONE_SLAB")
69
+ BRICK_BLOCK = Block("BRICKS")
70
+ TNT = Block("TNT")
71
+ BOOKSHELF = Block("BOOKSHELF")
72
+ MOSS_STONE = Block("MOSS_STONE")
73
+ OBSIDIAN = Block("OBSIDIAN")
74
+ TORCH = Block("TORCH")
75
+ FIRE = Block("FIRE")
76
+ STAIRS_WOOD = Block("OAK_STAIRS")
77
+ CHEST = Block("CHEST")
78
+ DIAMOND_ORE = Block("DIAMOND_ORE")
79
+ DIAMOND_BLOCK = Block("DIAMOND_BLOCK")
80
+ CRAFTING_TABLE = Block("CRAFTING_TABLE")
81
+ FARMLAND = Block("FARMLAND")
82
+ FURNACE_INACTIVE = Block("FURNACE_INACTIVE")
83
+ FURNACE_ACTIVE = Block("FURNACE_ACTIVE")
84
+ DOOR_WOOD = Block("OAK_DOOR") # NOTE: this doesn't really work (2-block piece needs special handling)
85
+ LADDER = Block("LADDER")
86
+ STAIRS_COBBLESTONE = Block("COBBLESTONE_STAIRS")
87
+ DOOR_IRON = Block("IRON_DOOR")
88
+ REDSTONE_ORE = Block("REDSTONE_ORE")
89
+ SNOW = Block("SNOW")
90
+ ICE = Block("ICE")
91
+ SNOW_BLOCK = Block("SNOW_BLOCK")
92
+ CACTUS = Block("CACTUS")
93
+ CLAY = Block("CLAY")
94
+ SUGAR_CANE = Block("SUGAR_CANE")
95
+ FENCE = Block("OAK_FENCE")
96
+ GLOWSTONE_BLOCK = Block("GLOWSTONE")
97
+ BEDROCK_INVISIBLE = Block("BEDROCK")
98
+ STONE_BRICK = Block("STONE_BRICKS")
99
+ GLASS_PANE = Block("GLASS_PANE")
100
+ MELON = Block("MELON")
101
+ FENCE_GATE = Block("OAK_FENCE_GATE")
102
+ GLOWING_OBSIDIAN = Block("GLOWING_OBSIDIAN")
103
+ NETHER_REACTOR_CORE = Block(247)
pyncraft/connection.py ADDED
@@ -0,0 +1,75 @@
1
+ import socket
2
+ import select
3
+ import sys
4
+ from .util import flatten_parameters_to_bytestring
5
+
6
+ """ @author: Aron Nieminen, Mojang AB"""
7
+
8
+ class RequestError(Exception):
9
+ pass
10
+
11
+ class ConnectionClosed(Exception):
12
+ """The server closed the TCP connection.
13
+
14
+ Deliberately not named ConnectionError: that has been a Python builtin
15
+ since 3.3, and shadowing it here would mean any except ConnectionError
16
+ in this module silently stops catching real socket errors.
17
+ """
18
+ pass
19
+
20
+ class Connection:
21
+ """Connection to a Minecraft Pi game"""
22
+ RequestFailed = "Fail"
23
+
24
+ def __init__(self, address, port):
25
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
26
+ self.socket.connect((address, port))
27
+ self.lastSent = ""
28
+
29
+ def drain(self):
30
+ """Drains the socket of incoming data"""
31
+ while True:
32
+ readable, _, _ = select.select([self.socket], [], [], 0.0)
33
+ if not readable:
34
+ break
35
+ data = self.socket.recv(1500)
36
+ if len(data) == 0:
37
+ raise ConnectionClosed("%s failed! Cause: connection closed" % self.lastSent.strip())
38
+ e = "Drained Data: <%s>\n"%data.strip().decode('cp437')
39
+ e += "Last Message: <%s>\n"%self.lastSent.strip().decode('cp437')
40
+ sys.stderr.write(e)
41
+
42
+ def send(self, f, *data):
43
+ """
44
+ Sends data. Note that a trailing newline '\n' is added here
45
+
46
+ The protocol uses CP437 encoding - https://en.wikipedia.org/wiki/Code_page_437
47
+ which is mildly distressing as it can't encode all of Unicode.
48
+ """
49
+
50
+ s = b"".join([f, b"(", flatten_parameters_to_bytestring(data), b")", b"\n"])
51
+ self._send(s)
52
+
53
+ def _send(self, s):
54
+ """
55
+ The actual socket interaction from self.send, extracted for easier mocking
56
+ and testing
57
+ """
58
+ self.drain()
59
+ self.lastSent = s
60
+ self.socket.sendall(s)
61
+
62
+ def receive(self):
63
+ """Receives data. Note that the trailing newline '\n' is trimmed"""
64
+ s = self.socket.makefile("r").readline().rstrip("\n")
65
+ checkFail = s.split(",")
66
+ if checkFail[0] == Connection.RequestFailed:
67
+ # clear anything still queued, or the next call reads this failure's tail
68
+ self.drain()
69
+ raise RequestError("%s failed! Cause: %s" % (self.lastSent.strip(),checkFail[-1]))
70
+ return s
71
+
72
+ def sendReceive(self, *data):
73
+ """Sends and receive data"""
74
+ self.send(*data)
75
+ return self.receive()
pyncraft/coord.py ADDED
@@ -0,0 +1,289 @@
1
+ from typing import Callable, Iterable, Union, Optional
2
+
3
+ import numpy as np
4
+
5
+
6
+
7
+ class Coord(np.ndarray):
8
+ """
9
+ Implement 3D coordinates as a 3-element (x, y, z) numpy array subclass.
10
+
11
+ This avoids having to reinvent the wheel for basic vector operations.
12
+ You can pass in a Vec3, list, tuple, pd.Series or individual x, y, z values.
13
+ They must be numeric (int or float).
14
+
15
+ Parameters
16
+ ----------
17
+ x : int, float, Iterable
18
+ The x coordinate or a 3-element iterable containing x, y, z coordinates.
19
+ Positive x is east, negative x is west.
20
+ y : int, float, None
21
+ The y coordinate (vertical position). Positive y is up, negative y is
22
+ down. Unused if `x` is an iterable.
23
+ z : int, float, None
24
+ The z coordinate. Positive z is south, negative z is north. Unused if
25
+ `x` is an iterable.
26
+ """
27
+
28
+ __int_types__ = (int, np.int32, np.int64)
29
+ __float_types__ = (float, np.float32, np.float64)
30
+ __numeric__ = __int_types__ + __float_types__
31
+
32
+ def __new__(cls,
33
+ x: Union[int, float, Iterable],
34
+ y: Union[int, float, None] = None,
35
+ z: Union[int, float, None] = None
36
+ ):
37
+ if isinstance(x, Iterable):
38
+ x = [v for i, v in enumerate(x) if i < 4]
39
+ if len(x) != 3:
40
+ raise ValueError(f"Expected 3 coordinates, got {len(x)}: {x}")
41
+ x, y, z = tuple(x)
42
+ else:
43
+ if not isinstance(x, cls.__numeric__):
44
+ raise TypeError(f"x must be int or float, got {type(x)}: {x}")
45
+ if not isinstance(y, cls.__numeric__):
46
+ raise TypeError(f"y must be int or float, got {type(y)}: {y}")
47
+ if not isinstance(z, cls.__numeric__):
48
+ raise TypeError(f"z must be int or float, got {type(z)}: {z}")
49
+
50
+ # float64 always: an int array would silently truncate a later
51
+ # fractional assignment, and minecraft positions are fractional.
52
+ # Use block() when you want whole-number block coordinates.
53
+ obj = np.asarray([x, y, z], dtype=float).view(cls)
54
+ return obj
55
+
56
+ # accessor methods convert numpy int/float to Python int/float
57
+ @property
58
+ def x(self):
59
+ return int(self[0]) if isinstance(self[0], self.__int_types__) else float(self[0])
60
+
61
+ @x.setter
62
+ def x(self, value):
63
+ self[0] = value
64
+
65
+ @property
66
+ def y(self):
67
+ return int(self[1]) if isinstance(self[1], self.__int_types__) else float(self[1])
68
+
69
+ @y.setter
70
+ def y(self, value):
71
+ self[1] = value
72
+
73
+ @property
74
+ def z(self):
75
+ return int(self[2]) if isinstance(self[2], self.__int_types__) else float(self[2])
76
+
77
+ @z.setter
78
+ def z(self, value):
79
+ self[2] = value
80
+
81
+
82
+ def adjust(self, axis: str, delta: Union[int, float]) -> 'Coord':
83
+ """
84
+ Copy Coord and adjust one axis (x, y or z) by delta
85
+ """
86
+ axis = {'x': 0, 'y': 1, 'z': 2}.get(str(axis).lower())
87
+ if axis is None:
88
+ # without this, coord[None] += delta broadcasts across every axis
89
+ raise ValueError("axis must be one of 'x', 'y' or 'z'")
90
+ coord = self.copy()
91
+ coord[axis] += delta
92
+ return coord
93
+
94
+
95
+ def block(self, as_int: bool = True) -> 'Coord':
96
+ """
97
+ Get the whole-number block coordinates as Coord object By Flooring.
98
+
99
+ If as_int is True, returns the block coordinate as an integer.
100
+ Otherwise, float.
101
+ """
102
+ block = np.floor(self)
103
+ if as_int:
104
+ block = block.astype(int)
105
+ return block
106
+
107
+
108
+ def midblock(self) -> 'Coord':
109
+ return self.block(as_int=False) + Coord(0.5, 0.0, 0.5)
110
+
111
+
112
+ def coplane(self, c2: 'Coord') -> bool:
113
+ """
114
+ Check whether the second coordinate shares a plane with this one.
115
+
116
+ Use Vec3D(c1, c2).coplane() if you want to know which plane.
117
+ """
118
+
119
+ return bool(Vec3D(self, c2).coplane())
120
+
121
+
122
+ def direction(self, c2: 'Coord') -> 'Vec3D':
123
+ """
124
+ Get the unit vector from c1 to c2 (normalized to length 1).
125
+ """
126
+ return Vec3D(self, c2).direction()
127
+
128
+
129
+ def cardinal_direction(self, c2: 'Coord', *args, **kwargs) -> Union[str, 'Coord']:
130
+ """
131
+ Get the Cardinal Direction of a Second Coordinate.
132
+
133
+ See help for Vec3D.cardinal_direction() for details.
134
+ """
135
+ return Vec3D(self, c2).cardinal_direction(*args, **kwargs)
136
+
137
+
138
+ def distance(self, c2: 'Coord') -> float:
139
+ """
140
+ Calculate the distance between two coordinates.
141
+ """
142
+ return float(np.sqrt(((self - c2) ** 2).sum()))
143
+
144
+
145
+
146
+ class Vec3D(Coord):
147
+ """
148
+ A 3D vector class that takes one or two Coord objects as input.
149
+ """
150
+
151
+ def __init__(self, c1: Coord, c2: Coord = None):
152
+
153
+ v = c1 if c2 is None else c2 - c1
154
+
155
+ self.x = v.x
156
+ self.y = v.y
157
+ self.z = v.z
158
+
159
+
160
+ def rotateLeft(self): self.x, self.z = self.z, -self.x
161
+
162
+ def rotateRight(self): self.x, self.z = -self.z, self.x
163
+
164
+
165
+ def is_unit(self):
166
+ """Test if the vector is a unit vector (normalized to length 1)."""
167
+ return np.isclose(np.linalg.norm(self), 1.0)
168
+
169
+
170
+ def direction(self) -> Coord:
171
+ """
172
+ Get the unit vector from c1 to c2 (normalized to length 1).
173
+ """
174
+ return (self) / np.linalg.norm(self)
175
+
176
+
177
+ def coplane(self) -> str:
178
+ """
179
+ Which plane, if any, this vector lies in.
180
+
181
+ Returns the axes the vector does not move along: 'y' means it stays at
182
+ one height, 'xz' means it only moves up and down, '' means it moves in
183
+ all three. Falsy when the vector is in no plane.
184
+ """
185
+
186
+ plane = ''
187
+ if np.isclose(self.x, 0.0):
188
+ plane += 'x'
189
+ if np.isclose(self.y, 0.0):
190
+ plane += 'y'
191
+ if np.isclose(self.z, 0.0):
192
+ plane += 'z'
193
+
194
+ return plane
195
+
196
+
197
+ def cardinal_direction(
198
+ self,
199
+ returns: str = 'string',
200
+ compass_points: int = 4
201
+ ) -> Union[str, int, Coord]:
202
+ """
203
+ Get the Cardinal Direction Of The Vector In The XY Plane.
204
+
205
+ Uses the x and z components only, and returns the closest direction
206
+ based on the number fo compass points. Direction may be returned
207
+ as a string ("north"), minecraft rotation value (0-15), degrees (0-360),
208
+ radians (0-2pi), or a Vec3D/Coord unit vector with y==0.
209
+
210
+ Note that when there is a tie (like x=1 and z=-1 with 4 compass points),
211
+ I'm not doing anything specific to resolve (north or east in this case).
212
+ Could return 'indeteminate', None/np.nan or raise an exception. Also
213
+ leaving it up to the user whether to convert Coords to integer.
214
+
215
+ Parameters
216
+ ----------
217
+ returns : str
218
+ The type of return value. Can be 'string', 'rotation', 'coord', or
219
+ 'degrees'. Default is 'string'.
220
+ compass_points : int
221
+ The number of compass points to use for the direction.
222
+ Default is 4 (north, east, south, west). If set to 8, it will also
223
+ return northeast, southeast, southwest, and northwest. If set
224
+ to 16, it will return all 16 compass points ('northnortheast',
225
+ 'northeast', 'eastnortheast', 'east', etc).
226
+
227
+ Returns
228
+ -------
229
+ Union[str, int, Coord]:
230
+ If returns is string: 'north', 'south', 'east', 'west',.
231
+ """
232
+ ok = {'string', 'rotation', 'coord', 'degrees', 'radians'}
233
+ invalid = {returns} - ok
234
+ if invalid:
235
+ raise ValueError(
236
+ f'Invalid returns argument "{returns}"; must be one of:\n '
237
+ + ', '.join(list(ok)))
238
+
239
+ if self.x == 0 and self.z == 0:
240
+ raise ValueError('Vector point straight up or down; indeterminate.')
241
+
242
+ # drop the y component and normalize the xz vector (z -> y)
243
+ xz = np.delete(self, 1)
244
+ xz = xz / np.linalg.norm(xz)
245
+
246
+ # atan2 returns angle from x-axis (east), so swap arguments and invert z
247
+ # calculate fraction of a turn [0, 1) from North = 0 degrees
248
+ frac360 = (np.arctan2(xz.x, -xz.y) / (np.pi * 2)) % 1.0
249
+
250
+ bearings = ['north', 'northnortheast', 'northeast', 'eastnortheast',
251
+ 'east', 'eastsoutheast', 'southeast', 'southsoutheast',
252
+ 'south', 'southsouthwest', 'southwest', 'westsouthwest',
253
+ 'west', 'westnorthwest', 'northwest', 'northnorthwest',
254
+ 'north']
255
+
256
+ if compass_points > 0:
257
+ # convert to a rotation value, rounded to the nearest compass point
258
+ rotation = int(
259
+ np.round(frac360 * compass_points) * 16 / compass_points)
260
+
261
+ if returns == 'rotation':
262
+ return rotation
263
+ elif returns == 'degrees':
264
+ return rotation * 360 / 16
265
+ elif returns == 'string':
266
+ return bearings[rotation]
267
+ else:
268
+ radians = rotation * 2 * np.pi / 16
269
+ if returns == 'radians':
270
+ return radians
271
+ else:
272
+ # rounded unit vector in the xz plane
273
+ coord = Coord(np.sin(radians), 0, -np.cos(radians))
274
+ if compass_points == 4:
275
+ coord = coord.astype(int)
276
+ return coord
277
+ elif returns in ('string', 'rotation'):
278
+ raise ValueError(
279
+ f'Must set compass_points > 0 for returns "string" or "rotation"')
280
+ else:
281
+ # return results without rounding
282
+ radians = frac360 * 2 * np.pi
283
+ if returns == 'degrees':
284
+ return frac360 * 360
285
+ else:
286
+ if returns == 'radians':
287
+ return radians
288
+ else:
289
+ return Coord(np.sin(radians), 0,-np.cos(radians))
pyncraft/entity.py ADDED
@@ -0,0 +1,102 @@
1
+ class Entity:
2
+ '''Minecraft PI entity description. Can be sent to Minecraft.spawnEntity'''
3
+
4
+ def __init__(self, id, name = None):
5
+ self.id = id
6
+ self.name = name
7
+
8
+ def __cmp__(self, rhs):
9
+ return hash(self) - hash(rhs)
10
+
11
+ def __eq__(self, rhs):
12
+ return self.id == rhs.id
13
+
14
+ def __hash__(self):
15
+ return self.id
16
+
17
+ def __iter__(self):
18
+ '''Allows an Entity to be sent whenever id is needed'''
19
+ return iter((self.id,))
20
+
21
+ def __repr__(self):
22
+ return 'Entity(%d)'%(self.id)
23
+
24
+ EXPERIENCE_ORB = Entity(2, "EXPERIENCE_ORB")
25
+ AREA_EFFECT_CLOUD = Entity(3, "AREA_EFFECT_CLOUD")
26
+ ELDER_GUARDIAN = Entity(4, "ELDER_GUARDIAN")
27
+ WITHER_SKELETON = Entity(5, "WITHER_SKELETON")
28
+ STRAY = Entity(6, "STRAY")
29
+ EGG = Entity(7, "EGG")
30
+ LEASH_HITCH = Entity(8, "LEASH_HITCH")
31
+ PAINTING = Entity(9, "PAINTING")
32
+ ARROW = Entity(10, "ARROW")
33
+ SNOWBALL = Entity(11, "SNOWBALL")
34
+ FIREBALL = Entity(12, "FIREBALL")
35
+ SMALL_FIREBALL = Entity(13, "SMALL_FIREBALL")
36
+ ENDER_PEARL = Entity(14, "ENDER_PEARL")
37
+ ENDER_SIGNAL = Entity(15, "ENDER_SIGNAL")
38
+ THROWN_EXP_BOTTLE = Entity(17, "THROWN_EXP_BOTTLE")
39
+ ITEM_FRAME = Entity(18, "ITEM_FRAME")
40
+ WITHER_SKULL = Entity(19, "WITHER_SKULL")
41
+ PRIMED_TNT = Entity(20, "PRIMED_TNT")
42
+ HUSK = Entity(23, "HUSK")
43
+ SPECTRAL_ARROW = Entity(24, "SPECTRAL_ARROW")
44
+ SHULKER_BULLET = Entity(25, "SHULKER_BULLET")
45
+ DRAGON_FIREBALL = Entity(26, "DRAGON_FIREBALL")
46
+ ZOMBIE_VILLAGER = Entity(27, "ZOMBIE_VILLAGER")
47
+ SKELETON_HORSE = Entity(28, "SKELETON_HORSE")
48
+ ZOMBIE_HORSE = Entity(29, "ZOMBIE_HORSE")
49
+ ARMOR_STAND = Entity(30, "ARMOR_STAND")
50
+ DONKEY = Entity(31, "DONKEY")
51
+ MULE = Entity(32, "MULE")
52
+ EVOKER_FANGS = Entity(33, "EVOKER_FANGS")
53
+ EVOKER = Entity(34, "EVOKER")
54
+ VEX = Entity(35, "VEX")
55
+ VINDICATOR = Entity(36, "VINDICATOR")
56
+ ILLUSIONER = Entity(37, "ILLUSIONER")
57
+ MINECART_COMMAND = Entity(40, "MINECART_COMMAND")
58
+ BOAT = Entity(41, "BOAT")
59
+ MINECART = Entity(42, "MINECART")
60
+ MINECART_CHEST = Entity(43, "MINECART_CHEST")
61
+ MINECART_FURNACE = Entity(44, "MINECART_FURNACE")
62
+ MINECART_TNT = Entity(45, "MINECART_TNT")
63
+ MINECART_HOPPER = Entity(46, "MINECART_HOPPER")
64
+ MINECART_MOB_SPAWNER = Entity(47, "MINECART_MOB_SPAWNER")
65
+ CREEPER = Entity(50, "CREEPER")
66
+ SKELETON = Entity(51, "SKELETON")
67
+ SPIDER = Entity(52, "SPIDER")
68
+ GIANT = Entity(53, "GIANT")
69
+ ZOMBIE = Entity(54, "ZOMBIE")
70
+ SLIME = Entity(55, "SLIME")
71
+ GHAST = Entity(56, "GHAST")
72
+ PIG_ZOMBIE = Entity(57, "PIG_ZOMBIE")
73
+ ENDERMAN = Entity(58, "ENDERMAN")
74
+ CAVE_SPIDER = Entity(59, "CAVE_SPIDER")
75
+ SILVERFISH = Entity(60, "SILVERFISH")
76
+ BLAZE = Entity(61, "BLAZE")
77
+ MAGMA_CUBE = Entity(62, "MAGMA_CUBE")
78
+ ENDER_DRAGON = Entity(63, "ENDER_DRAGON")
79
+ WITHER = Entity(64, "WITHER")
80
+ BAT = Entity(65, "BAT")
81
+ WITCH = Entity(66, "WITCH")
82
+ ENDERMITE = Entity(67, "ENDERMITE")
83
+ GUARDIAN = Entity(68, "GUARDIAN")
84
+ SHULKER = Entity(69, "SHULKER")
85
+ PIG = Entity(90, "PIG")
86
+ SHEEP = Entity(91, "SHEEP")
87
+ COW = Entity(92, "COW")
88
+ CHICKEN = Entity(93, "CHICKEN")
89
+ SQUID = Entity(94, "SQUID")
90
+ WOLF = Entity(95, "WOLF")
91
+ MUSHROOM_COW = Entity(96, "MUSHROOM_COW")
92
+ SNOWMAN = Entity(97, "SNOWMAN")
93
+ OCELOT = Entity(98, "OCELOT")
94
+ IRON_GOLEM = Entity(99, "IRON_GOLEM")
95
+ HORSE = Entity(100, "HORSE")
96
+ RABBIT = Entity(101, "RABBIT")
97
+ POLAR_BEAR = Entity(102, "POLAR_BEAR")
98
+ LLAMA = Entity(103, "LLAMA")
99
+ LLAMA_SPIT = Entity(104, "LLAMA_SPIT")
100
+ PARROT = Entity(105, "PARROT")
101
+ VILLAGER = Entity(120, "VILLAGER")
102
+ ENDER_CRYSTAL = Entity(200, "ENDER_CRYSTAL")
pyncraft/event.py ADDED
@@ -0,0 +1,65 @@
1
+ from .vec3 import Vec3
2
+
3
+ class BlockEvent:
4
+ """An Event related to blocks (e.g. placed, removed, hit)"""
5
+ HIT = 0
6
+
7
+ def __init__(self, type, x, y, z, face, entityId):
8
+ self.type = type
9
+ self.pos = Vec3(x, y, z)
10
+ self.face = face
11
+ self.entityId = entityId
12
+
13
+ def __repr__(self):
14
+ sType = {
15
+ BlockEvent.HIT: "BlockEvent.HIT"
16
+ }.get(self.type, "???")
17
+
18
+ return "BlockEvent(%s, %d, %d, %d, %d, %d)"%(
19
+ sType,self.pos.x,self.pos.y,self.pos.z,self.face,self.entityId);
20
+
21
+ @staticmethod
22
+ def Hit(x, y, z, face, entityId):
23
+ return BlockEvent(BlockEvent.HIT, x, y, z, face, entityId)
24
+
25
+ class ArrowHitEvent:
26
+ """An Event related to blocks (e.g. placed, removed, hit)"""
27
+ HIT = 0
28
+
29
+ def __init__(self, type, x, y, z, entityId):
30
+ self.type = type
31
+ self.pos = Vec3(x, y, z)
32
+ self.entityId = entityId
33
+
34
+ def __repr__(self):
35
+ sType = {
36
+ ArrowHitEvent.HIT: "ArrowHitEvent.HIT"
37
+ }.get(self.type, "???")
38
+
39
+ return "BlockEvent(%s, %d, %d, %d, %d)"%(
40
+ sType,self.pos.x,self.pos.y,self.pos.z,self.entityId);
41
+
42
+ @staticmethod
43
+ def Hit(x, y, z, entityId):
44
+ return ArrowHitEvent(ArrowHitEvent.HIT, x, y, z, entityId)
45
+
46
+ class ChatEvent:
47
+ """An Event related to chat (e.g. posts)"""
48
+ POST = 0
49
+
50
+ def __init__(self, type, entityId, message):
51
+ self.type = type
52
+ self.entityId = entityId
53
+ self.message = message
54
+
55
+ def __repr__(self):
56
+ sType = {
57
+ ChatEvent.POST: "ChatEvent.POST"
58
+ }.get(self.type, "???")
59
+
60
+ return "ChatEvent(%s, %d, %s)"%(
61
+ sType,self.entityId,self.message);
62
+
63
+ @staticmethod
64
+ def Post(entityId, message):
65
+ return ChatEvent(ChatEvent.POST, entityId, message)
pyncraft/logger.py ADDED
@@ -0,0 +1,33 @@
1
+ import pyncraft.settings as settings
2
+
3
+ class BColors:
4
+
5
+ TWHITE = '\033[32m'
6
+ TGREY = '\033[90m'
7
+ TRED = '\033[31m'
8
+ HEADER = '\033[95m'
9
+ OKBLUE = '\033[94m'
10
+ OKGREEN = '\033[92m'
11
+ LOG ='\033[96m'
12
+ WARNING = '\033[45m'
13
+ FAIL = '\033[91m'
14
+ ENDC = '\033[0m'
15
+ BOLD = '\033[1m'
16
+ UNDERLINE = '\033[4m'
17
+ def disable(self):
18
+ self.HEADER = ''
19
+ self.OKBLUE = ''
20
+ self.OKGREEN = ''
21
+ self.WARNING = ''
22
+ self.FAIL = ''
23
+ self.ENDC = ''
24
+
25
+ def debug(*msg):
26
+ if(settings.SHOW_DEBUG):
27
+ print(BColors.TGREY,msg,BColors.ENDC)
28
+
29
+ def log(*msg):
30
+ if(settings.SHOW_Log):
31
+ print(BColors.LOG,msg,BColors.ENDC)
32
+ def warn(*msg):
33
+ print(BColors.WARNING,msg,BColors.ENDC)