-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.py
132 lines (94 loc) · 3.93 KB
/
player.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Simply represents the player and their inventory.
Stack represents an item and an amount of that item.
Most of the player's behavior actually happens in `craft.py`,
which I may move in the future.
A player is simply an `Entity` with a few extra attributes, so there's
not that much too this module.
"""
from entity import Entity
from typing import List, Optional, Tuple, Literal, overload
from dataclasses import dataclass
from util import ItemId, BlockPos
from nbt import nbt
from inventory import Stack, Slot
import copy
class Player(Entity):
reach: float
hotbarIdx: int = 0
creative: bool
flying: bool
inventory: List[Slot]
dimension: str
def __init__(self, app, creative: bool = False, tag: Optional[nbt.TAG_Compound] = None):
self.dimension = 'minecraft:overworld'
# FIXME: ID
super().__init__(app, 1, 'player', 0.0, 0.0, 0.0, nbt=tag)
self.reach = 4.0
self.creative = creative
self.flying = False
self.portalCooldown = 80
if self.creative:
if len(app.itemTextures) > 36:
# TODO:
1 / 0
self.inventory = [Slot(stack=Stack(name, -1)) for name in app.itemTextures]
while len(self.inventory) < 36:
self.inventory.append(Slot(stack=Stack('', 0)))
else:
self.inventory = [Slot() for _ in range(36)]
if tag is not None:
for stackTag in tag["Inventory"]:
(stack, slotIdx) = Stack.fromNbt(stackTag, getSlot=True)
self.inventory[slotIdx].stack = stack
gameMode = tag['playerGameType'].value
if gameMode == 0:
self.creative = False
elif gameMode == 1:
self.creative = True
else:
raise Exception(f'Invalid game mode {gameMode}')
self.flying = tag['abilities']['flying'].value != 0
self.dimension = tag['dimension'].value
def toNbt(self) -> nbt.TAG_Compound:
tag = super().toNbt()
inventory = nbt.TAG_List(type=nbt.TAG_Compound, name='Inventory')
for (slotIdx, item) in enumerate(self.inventory):
stackTag = item.stack.toNbt(slotIdx)
if stackTag is not None:
inventory.append(stackTag)
tag.tags.append(inventory)
gameMode = 1 if self.creative else 0
tag.tags.append(nbt.TAG_Int(gameMode, 'playerGameType'))
abilities = nbt.TAG_Compound()
abilities.name = 'abilities'
abilities.tags.append(nbt.TAG_Byte(int(self.flying), 'flying'))
tag.tags.append(abilities)
tag.tags.append(nbt.TAG_String(self.dimension, 'dimension'))
return tag
def tick(self, app, world, entities, playerX, playerZ):
if self.immunity > 0:
self.immunity -= 1
if self.portalCooldown > 0:
self.portalCooldown -= 1
def pickUpItem(self, app, newItem: Stack):
"""Adds an item to the player's inventory."""
if newItem.isEmpty(): return
# Prioritize existing stacks of the item first
for (i, slot) in enumerate(self.inventory):
stack = slot.stack
if stack.isInfinite() and stack.item == newItem.item:
# It just stacks into an infinite slot, so no change
return
elif newItem.isInfinite() and stack.item == newItem.item:
# ditto
return
elif stack.amount > 0 and stack.item == newItem.item:
self.inventory[i].stack.amount += newItem.amount
return
# If that fails, then just add the item to the next open space
for (i, slot) in enumerate(self.inventory):
if slot.isEmpty():
self.inventory[i].stack = newItem
return
# TODO: Full inventory??
1 / 0