-
Notifications
You must be signed in to change notification settings - Fork 17
/
movement.py
211 lines (172 loc) · 7.03 KB
/
movement.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#
# Various functions to deal with blocks, locations and movement
#
import time
from javascript import require
from math import sqrt, atan2, sin, cos
from botlib import *
Vec3 = require('vec3').Vec3
pathfinder = require('mineflayer-pathfinder')
#
# Movement functions for bot
#
class MovementManager:
empty_blocks = [ "Water", "Lava", "Air", "Cave Air", "Void Air"]
def __init__(self):
print('movement ', end='')
# Versatile blockAt, takes 3 coordinates or vector
def blockAt(self, x, y=None, z=None):
if y:
v = Vec3(x,y,z)
else:
v = x
return self.bot.blockAt(v)
def safeWalk(self, toPosition, radius=1):
self.pdebug(f' safeWalk to {toPosition.x} {toPosition.y} {toPosition.z} r={radius}',4)
if not toPosition:
print('*** error: toPosition is not defined.')
return False
if not toPosition.x:
print('*** error: toPosition has no x coordinate. Not a position vector?')
return False
try:
p = self.bot.pathfinder
if p == None:
print(' *** error: pathfinder is None in safeWalk.')
return False
p.setGoal(pathfinder.goals.GoalNear(toPosition.x,toPosition.y,toPosition.z,radius))
except Exception as e:
print(f'*** error in safeWalk {e}')
return False
t = walkTime(toPosition,self.bot.entity.position)
if not self.speedMode:
time.sleep(t)
return True
def walkTo(self,x,y=None,z=None):
if hasattr(x, 'position') and x.position:
v = Vec3(x.position.x,x.position.y,x.position.z)
self.safeWalk(v,1)
elif not y:
self.safeWalk(x,1)
else:
v = Vec3(x,y,z)
self.safeWalk(v,1)
def walkToBlock(self,x,y=None,z=None):
if hasattr(x, 'position') and x.position:
v = Vec3(x.position.x+0.5,x.position.y,x.position.z+0.5)
self.safeWalk(v)
elif not y:
v = Vec3(x.x+0.5,x.y,x.z+0.5)
self.safeWalk(v)
else:
v = Vec3(x+0.5,y,z+0.5)
self.safeWalk(v)
def walkToBlock3(self,x,y=None,z=None):
if hasattr(x, 'position') and x.position:
v = Vec3(x.position.x+0.5,x.position.y,x.position.z+0.5)
self.safeWalk(v,0.3)
elif not y:
v = Vec3(x.x+0.5,x.y,x.z+0.5)
self.safeWalk(v,0.3)
else:
v = Vec3(x+0.5,y,z+0.5)
self.safeWalk(v,0.3)
# Walks on top of this block
def walkOnBlock(self,x,y=None,z=None):
if hasattr(x, 'position') and x.position:
v = Vec3(x.position.x+0.5,x.position.y+1,x.position.z+0.5)
self.safeWalk(v)
elif not y:
v = Vec3(x.x+0.5,x.y+1,x.z+0.5)
self.safeWalk(v)
else:
v = Vec3(x+0.5,y+1,z+0.5)
self.safeWalk(v)
# this will attempt to walk on to block at v, and place a block in the direction d
def safePlaceBlock(self,v,dv):
v_gap = addVec3(v,dv)
b = self.bot.blockAt(v)
b_gap = self.bot.blockAt(v_gap)
if b_gap.displayName not in self.empty_blocks:
self.perror(f'cant place block in space occupied by {b_gap.displayName}.')
self.perror(f'{b_gap.displayName} @{v_gap.x}/{v_gap.y}/{v_gap.z} against {b.displayName} @{v.x}/{v.y}/{v.z}')
return False
if b.displayName in self.empty_blocks:
self.perror(f'place {b_gap.displayName} @{v_gap.x}/{v_gap.y}/{v_gap.z} against {b.displayName} @{v.x}/{v.y}/{v.z}')
return False
try:
self.bot.placeBlock(b,dv)
return True
except Exception as e:
self.pexception(f'{b_gap.displayName} @{v_gap.x}/{v_gap.y}/{v_gap.z} against {b.displayName} @{v.x}/{v.y}/{v.z}',e)
return False
def bridgeBlock(self, v, d):
v_gap = addVec3(v,d)
b = self.bot.blockAt(v)
b_gap = self.bot.blockAt(v_gap)
d_inv = Vec3(-d.x,-d.y,-d.z)
self.pdebug(f' bridging {b_gap.displayName} @{v_gap.x}/{v_gap.y}/{v_gap.z} against {b.displayName} @{v.x}/{v.y}/{v.z}',2)
self.walkToBlock(v.x,v.y+1,v.z)
time.sleep(1)
# Code from mineflayer.pathfinder
# Target viewing direction while approaching edge
# The Bot approaches the edge while looking in the opposite direction from where it needs to go
# The target Pitch angle is roughly the angle the bot has to look down for when it is in the position
# to place the next block
targetYaw = atan2(d.x, d.z)
targetPitch = -1.421
viewVector = getViewVector(targetPitch, targetYaw)
pos = self.bot.entity.position
if not pos:
print("*** error: position is None in bridgeBlock.")
return False
p = pos.offset(viewVector.x, viewVector.y, viewVector.z)
self.bot.lookAt(p, True)
self.bot.setControlState('sneak', True)
time.sleep(0.5)
self.bot.setControlState('back', True)
time.sleep(0.5)
self.bot.setControlState('back',False)
if not self.safePlaceBlock(v,d):
return False
self.walkToBlock(v.x,v.y+1,v.z)
self.bot.setControlState('sneak',False)
time.sleep(0.5)
return
#
# Find closest (taxi geometry) block with specific content
# target can be a list or an item
def findClosestBlock(self,target,xz_radius=2,y_radius=1,metadata=None,spaceabove=False):
best_block = None
best_dist = 999
p = self.bot.entity.position
if type(target) is not list:
target = [target]
# Search larger and larger rectangles
for r in range(0,xz_radius+1):
for dx, dz in rectangleBorder(r,r):
for dy in range(-y_radius,y_radius+1):
b = self.bot.blockAt(Vec3(p.x+dx,p.y+dy,p.z+dz))
#print(dx,dy,dz,b.displayName,target)
if b.displayName in target:
if metadata and b.metadata != metadata:
continue
if spaceabove:
b_above = self.bot.blockAt(Vec3(p.x+dx,p.y+dy+1,p.z+dz))
if not b_above or b_above.type != 0:
continue
dist = sqrt(dx*dx+dy*dy+dz*dz)
# print("Found at ",v," distance ",dist)
if best_block == None or best_dist > dist:
best_block = b
best_dist = dist
if best_block:
return best_block
return False
def gotoLocation(self,l):
if not l in self.myLocations:
print(f'*** error: cant find location {l}')
c = self.myLocations[l]
print(f'moving to {l}')
self.safeWalk(Vec3(c[0], c[1], c[2]), 1 )
print("done.")