def move_collisions(self, b_obj, vx, vy, vz): zero_vels = False if self.is_in_web(b_obj): vx *= 0.25 vy *= 0.05000000074505806 vz *= 0.25 b_obj.velocities[0] = 0 b_obj.velocities[1] = 0 b_obj.velocities[2] = 0 aabbs = self.world.grid.aabbs_in(b_obj.aabb.extend_to(vx, vy, vz)) b_bb = b_obj.aabb dy = vy for bb in aabbs: dy = b_bb.calculate_axis_offset(bb, dy, 1) b_bb = b_bb.offset(dy=dy) dx = vx for bb in aabbs: dx = b_bb.calculate_axis_offset(bb, dx, 0) b_bb = b_bb.offset(dx=dx) dz = vz for bb in aabbs: dz = b_bb.calculate_axis_offset(bb, dz, 2) b_bb = b_bb.offset(dz=dz) if vy != dy and vy < 0 and (dx != vx or dz != vz): st = config.MAX_STEP_HEIGHT aabbs = self.world.grid.aabbs_in(b_obj.aabb.extend_to(vx, st, vz)) b_bbs = b_obj.aabb dys = st for bb in aabbs: dys = b_bbs.calculate_axis_offset(bb, dys, 1) b_bbs = b_bbs.offset(dy=dys) dxs = vx for bb in aabbs: dxs = b_bbs.calculate_axis_offset(bb, dxs, 0) b_bbs = b_bbs.offset(dx=dxs) dzs = vz for bb in aabbs: dzs = b_bbs.calculate_axis_offset(bb, dzs, 2) b_bbs = b_bbs.offset(dz=dzs) if fops.gt(dxs * dxs + dzs * dzs, dx * dx + dz * dz): dx = dxs dy = dys dz = dzs b_bb = b_bbs b_obj.on_ground = vy != dy and vy < 0 b_obj.is_collided_horizontally = dx != vx or dz != vz b_obj.horizontally_blocked = not fops.eq(dx, vx) and not fops.eq(dz, vz) if not fops.eq(vx, dx): b_obj.velocities[0] = 0 if not fops.eq(vy, dy): b_obj.velocities[1] = 0 if not fops.eq(vz, dz): b_obj.velocities[2] = 0 b_obj.x = b_bb.posx b_obj.y = b_bb.min_y b_obj.z = b_bb.posz self.do_block_collision(b_obj)
def standing_on_solidblock(self, bb): standing_on = None for col_bb in self.collision_aabbs_in(bb): if fops.eq(col_bb.max_y, bb.min_y): standing_on = self.get_block(col_bb.grid_x, col_bb.grid_y, col_bb.grid_z) if standing_on.x == bb.gridpos_x and standing_on.z == bb.gridpos_z: break if standing_on is not None: if not fops.eq(bb.grid_y, standing_on.y): standing_on = self.get_block(standing_on.x, standing_on.y + 1, standing_on.z) return standing_on
def move_collisions(self, b_obj, vx, vy, vz): if self.is_in_web(b_obj): vx *= 0.25 vy *= 0.05000000074505806 vz *= 0.25 b_obj.velocities.x = 0 b_obj.velocities.y = 0 b_obj.velocities.z = 0 aabbs = self.world.grid.collision_aabbs_in( b_obj.aabb.extend_to(vx, vy, vz)) b_bb = b_obj.aabb dy = vy if not fops.eq(vy, 0): for bb in aabbs: dy = b_bb.calculate_axis_offset(bb, dy, 1) b_bb = b_bb.offset(dy=dy) dx = vx if not fops.eq(vx, 0): for bb in aabbs: dx = b_bb.calculate_axis_offset(bb, dx, 0) b_bb = b_bb.offset(dx=dx) dz = vz if not fops.eq(vz, 0): for bb in aabbs: dz = b_bb.calculate_axis_offset(bb, dz, 2) b_bb = b_bb.offset(dz=dz) if vy != dy and vy < 0 and (dx != vx or dz != vz): st = config.MAX_STEP_HEIGHT aabbs = self.world.grid.collision_aabbs_in( b_obj.aabb.extend_to(vx, st, vz)) b_bbs = b_obj.aabb dys = st for bb in aabbs: dys = b_bbs.calculate_axis_offset(bb, dys, 1) b_bbs = b_bbs.offset(dy=dys) dxs = vx for bb in aabbs: dxs = b_bbs.calculate_axis_offset(bb, dxs, 0) b_bbs = b_bbs.offset(dx=dxs) dzs = vz for bb in aabbs: dzs = b_bbs.calculate_axis_offset(bb, dzs, 2) b_bbs = b_bbs.offset(dz=dzs) if fops.gt(dxs * dxs + dzs * dzs, dx * dx + dz * dz): dx = dxs dy = dys dz = dzs b_bb = b_bbs b_obj.on_ground = vy != dy and vy < 0 b_obj.is_collided_horizontally = dx != vx or dz != vz b_obj.horizontally_blocked = not fops.eq(dx, vx) and not fops.eq( dz, vz) if not fops.eq(vx, dx): b_obj.velocities.x = 0 if not fops.eq(vy, dy): b_obj.velocities.y = 0 if not fops.eq(vz, dz): b_obj.velocities.z = 0 b_obj.set_xyz(b_bb.posx, b_bb.min_y, b_bb.posz) self.do_block_collision(b_obj)
def is_standing(self, b_obj): col_d, _ = self.world.grid.min_collision_between( b_obj.aabb, b_obj.aabb - (0, 1, 0)) if col_d is None: stand = False else: stand = fops.eq(col_d, 0) return stand
def collision_distance(self, collidee, axis=None, direction=None): for i in xrange(3): if i == axis: continue if fops.lte(self.maxs[i], collidee.mins[i]) or \ fops.gte(self.mins[i], collidee.maxs[i]): return None p = None if direction < 0: if fops.eq(self.mins[axis], collidee.maxs[axis]): p = 0 elif fops.gt(self.mins[axis], collidee.maxs[axis]): p = self.mins[axis] - collidee.maxs[axis] else: if fops.eq(collidee.mins[axis], self.maxs[axis]): p = 0 elif fops.gt(collidee.mins[axis], self.maxs[axis]): p = collidee.mins[axis] - self.maxs[axis] return p
def standing_on_solidblock(self, bb): standing_on = None blocks = self.blocks_in_aabb(bb.extend_to(dy=-1)) dvect = (0, -1, 0) for blk in blocks: col, rel_d, _ = blk.sweep_collision(bb, dvect) if col and fops.eq(rel_d, 0): standing_on = blk if standing_on.x == bb.grid_x and standing_on.z == bb.grid_z: break return standing_on
def sweep_collision(self, collidee, v, debug=False): """ self moving by v, collidee stationery based on http://bit.ly/3grWzs """ u_0 = [2, 2, 2] u_1 = [1, 1, 1] dists = [None, None, None] for i in xrange(3): if fops.lte(self.maxs[i], collidee.mins[i]) and fops.gt(v[i], 0): d = collidee.mins[i] - self.maxs[i] dists[i] = d u_0[i] = d / v[i] elif fops.lte(collidee.maxs[i], self.mins[i]) and fops.lt(v[i], 0): d = collidee.maxs[i] - self.mins[i] dists[i] = d u_0[i] = d / v[i] elif fops.eq(v[i], 0) and \ not(fops.lte(self.maxs[i], collidee.mins[i]) or fops.gte(self.mins[i], collidee.maxs[i])): u_0[i] = 0 elif not(fops.lte(self.maxs[i], collidee.mins[i]) or fops.gte(self.mins[i], collidee.maxs[i])): u_0[i] = 0 if fops.gte(collidee.maxs[i], self.mins[i]) and fops.gt(v[i], 0): d = collidee.maxs[i] - self.mins[i] u_1[i] = d / v[i] elif fops.gte(self.maxs[i], collidee.mins[i]) and fops.lt(v[i], 0): d = collidee.mins[i] - self.maxs[i] u_1[i] = d / v[i] if max(u_0) == 2: u0 = None col = False else: u0 = max(u_0) u1 = min(u_1) if fops.gte(u0, 1.0): col = False else: col = fops.lte(u0, u1) return col, u0
def sweep_collision(self, bb, vect, debug=False, max_height=False): boxes = self.grid_bounding_box if len(boxes) == 0: raise Exception( "0 bounding boxes from block %s, cannot handle that" % self) elif len(boxes) == 1: col, rel_d = bb.sweep_collision(boxes[0], vect, debug=debug) return col, rel_d, boxes[0] else: col_rel_d = 1.1 col_bb = None for box in boxes: col, rel_d = bb.sweep_collision(box, vect, debug=debug) if max_height and col and fops.eq(col_rel_d, rel_d): if fops.lt(col_bb.max_y, bb.max_y): col_bb = bb if col and fops.lt(rel_d, col_rel_d): col_rel_d = rel_d col_bb = bb return col_bb is not None, col_rel_d, col_bb
def min_collision_between(self, bb1, bb2, horizontal=False, max_height=False): ubb = bb1.extend_to(dy=-1).union(bb2.extend_to(dy=-1)) blcks = self.blocks_in_aabb(ubb) dvect = bb1.vector_to(bb2) if horizontal: dvect = (dvect[0], 0, dvect[2]) col_rel_d = 1.1 col_bb = None for blk in blcks: col, rel_d, bb = blk.sweep_collision( bb1, dvect, max_height=max_height) if col and fops.eq(col_rel_d, rel_d): if max_height: if fops.lt(col_bb.max_y, bb.max_y): col_bb = bb if col and fops.lt(rel_d, col_rel_d): col_rel_d = rel_d col_bb = bb if col_bb is not None: return col_rel_d * tools.vector_size(dvect), col_bb else: return None, None
def check_status(self, b_obj): bb_stand = self.target_space.bb_stand elev = bb_stand.min_y - b_obj.aabb.min_y gs = GridSpace(self.world.grid, bb=b_obj.aabb) if not self.target_space._can_stand_on(): self.world.grid.navgrid.delete_node(self.target_space.coords) log.msg('CANNOT STAND ON %s' % self.target_space) return Status.failure if b_obj.horizontally_blocked and not gs.can_go_between(self.target_space, debug=True): log.msg('CANNOT GO BETWEEN %s AND %s' % (b_obj.aabb, self.target_space)) return Status.failure if self.bot.is_on_ladder(b_obj) or self.bot.is_in_water(b_obj): if b_obj.position_grid == self.target_space.coords: return Status.success if b_obj.aabb.horizontal_distance(bb_stand) < self.bot.current_motion(b_obj): self.was_at_target = True if fops.eq(elev, 0): return Status.success if b_obj.horizontally_blocked and b_obj.on_ground: if not gs.can_go(self.target_space): log.msg("I am stuck, let's try again? vels %s" % str(b_obj.velocities)) return Status.failure return Status.running
def raycast_to_block(self, position, direction, max_distance=40): g_position = position.grid_shift() gx = g_position.x gy = g_position.y gz = g_position.z if fops.eq(0, direction.x): stepx = 0 tdx = sys.float_info.max else: stepx = int(math.copysign(1, direction.x)) tdx = abs(1 / direction.x) if fops.eq(0, direction.y): stepy = 0 tdy = sys.float_info.max else: stepy = int(math.copysign(1, direction.y)) tdy = abs(1 / direction.y) if fops.eq(0, direction.z): stepz = 0 tdz = sys.float_info.max else: stepz = int(math.copysign(1, direction.z)) tdz = abs(1 / direction.z) if stepx == 0: tmaxx = tdx elif stepx > 0: tmaxx = (math.floor(position.x) + 1 - position.x) * tdx else: tmaxx = (position.x - math.floor(position.x)) * tdx if stepy == 0: tmaxy = tdy elif stepy > 0: tmaxy = (math.floor(position.y) + 1 - position.y) * tdy else: tmaxy = (position.y - math.floor(position.y)) * tdy if stepz == 0: tmaxz = tdz elif stepz > 0: tmaxz = (math.floor(position.z) + 1 - position.z) * tdz else: tmaxz = (position.z - math.floor(position.z)) * tdz sqr_max_distance = max_distance * max_distance while True: if tmaxx < tmaxy: if tmaxx < tmaxz: gx = gx + stepx tmaxx = tmaxx + tdx else: gz = gz + stepz tmaxz = tmaxz + tdz else: if tmaxy < tmaxz: gy = gy + stepy tmaxy = tmaxy + tdy else: gz = gz + stepz tmaxz = tmaxz + tdz blk = self.get_block(gx, gy, gz) if blk.number != blocks.Air.number: return blk if (g_position.x - gx) ** 2 + (g_position.y - gy) ** 2 + (g_position.z - gz) ** 2 > sqr_max_distance: return blocks.Air(self, 0, 0, 0, 0)
def has_point(self, p): return fops.eq(abs(self.a), abs(self.a1 - p[0])) and \ fops.eq(abs(self.b), abs(self.b1 - p[1]))
def touch_platform(self, center): if self.can_stand: return fops.eq(center.y, self.y) elif self.can_hold: return self.y < center.y and center.y < (self.y + 1)
def raycast_to_block(self, position, direction, max_distance=40): g_position = position.grid_shift() gx = g_position.x gy = g_position.y gz = g_position.z if fops.eq(0, direction.x): stepx = 0 tdx = sys.float_info.max else: stepx = int(math.copysign(1, direction.x)) tdx = abs(1 / direction.x) if fops.eq(0, direction.y): stepy = 0 tdy = sys.float_info.max else: stepy = int(math.copysign(1, direction.y)) tdy = abs(1 / direction.y) if fops.eq(0, direction.z): stepz = 0 tdz = sys.float_info.max else: stepz = int(math.copysign(1, direction.z)) tdz = abs(1 / direction.z) if stepx == 0: tmaxx = tdx elif stepx > 0: tmaxx = (math.floor(position.x) + 1 - position.x) * tdx else: tmaxx = (position.x - math.floor(position.x)) * tdx if stepy == 0: tmaxy = tdy elif stepy > 0: tmaxy = (math.floor(position.y) + 1 - position.y) * tdy else: tmaxy = (position.y - math.floor(position.y)) * tdy if stepz == 0: tmaxz = tdz elif stepz > 0: tmaxz = (math.floor(position.z) + 1 - position.z) * tdz else: tmaxz = (position.z - math.floor(position.z)) * tdz sqr_max_distance = max_distance * max_distance while True: if tmaxx < tmaxy: if tmaxx < tmaxz: gx = gx + stepx tmaxx = tmaxx + tdx else: gz = gz + stepz tmaxz = tmaxz + tdz else: if tmaxy < tmaxz: gy = gy + stepy tmaxy = tmaxy + tdy else: gz = gz + stepz tmaxz = tmaxz + tdz blk = self.get_block(gx, gy, gz) if blk.number != blocks.Air.number: return blk if (g_position.x - gx)**2 + (g_position.y - gy)**2 + ( g_position.z - gz)**2 > sqr_max_distance: return blocks.Air(self, 0, 0, 0, 0)
def horizontal_direction_to(self, bb): x, _, z = self.vector_to(bb) size = math.hypot(x, z) if fops.eq(size, 0): return (0, 0) return (x / size, z / size)
def move(self, b_obj): self.clip_abs_velocities(b_obj) is_in_water = self.handle_water_movement(b_obj) is_in_lava = self.handle_lava_movement(b_obj) if b_obj.is_jumping: if is_in_water or is_in_lava: b_obj.velocities[1] += config.SPEED_LIQUID_JUMP elif b_obj.on_ground: b_obj.velocities[1] = config.SPEED_JUMP elif self.is_on_ladder(b_obj): b_obj.velocities[1] = config.SPEED_CLIMB b_obj.is_jumping = False if is_in_water: if b_obj.floating_flag: if self.head_inside_water(b_obj): b_obj.velocities[1] += config.SPEED_LIQUID_JUMP else: x, y, z = b_obj.aabb.grid_bottom_center b_up = self.world.grid.get_block(x, y + 1, z) b_down = self.world.grid.get_block(x, y - 1, z) b_cent = self.world.grid.get_block(x, y, z) no_up = not b_up.is_water and b_down.collidable and fops.eq(b_down.max_y, y) if (not no_up and b_cent.is_water and fops.gt(b_cent.y + 0.5, b_obj.aabb.min_y)) or isinstance(b_up, blocks.StillWater): b_obj.velocities[1] += config.SPEED_LIQUID_JUMP orig_y = b_obj.y self.update_directional_speed(b_obj, 0.02, balance=True) self.move_collisions(b_obj, b_obj.velocities[0], b_obj.velocities[1], b_obj.velocities[2]) b_obj.velocities[0] *= 0.800000011920929 b_obj.velocities[1] *= 0.800000011920929 b_obj.velocities[2] *= 0.800000011920929 b_obj.velocities[1] -= 0.02 if b_obj.is_collided_horizontally and \ self.is_offset_in_liquid(b_obj, b_obj.velocities[0], b_obj.velocities[1] + 0.6 - b_obj.y + orig_y, b_obj.velocities[2]): b_obj.velocities[1] = 0.30000001192092896 elif is_in_lava: orig_y = self.y self.update_directional_speed(b_obj, 0.02) self.move_collisions(b_obj, b_obj.velocities[0], b_obj.velocities[1], b_obj.velocities[2]) b_obj.velocities[0] *= 0.5 b_obj.velocities[1] *= 0.5 b_obj.velocities[2] *= 0.5 b_obj.velocities[1] -= 0.02 if b_obj.is_collided_horizontally and \ self.is_offset_in_liquid(b_obj, self.velocities[0], self.velocities[1] + 0.6 - self.y + orig_y, self.velocities[2]): self.velocities[1] = 0.30000001192092896 else: slowdown = self.current_slowdown(b_obj) self.update_directional_speed(b_obj, self.current_speed_factor(b_obj)) self.clip_ladder_velocities(b_obj) self.move_collisions(b_obj, b_obj.velocities[0], b_obj.velocities[1], b_obj.velocities[2]) if b_obj.is_collided_horizontally and self.is_on_ladder(b_obj): b_obj.velocities[1] = 0.2 b_obj.velocities[1] -= config.BLOCK_FALL b_obj.velocities[1] *= config.DRAG b_obj.velocities[0] *= slowdown b_obj.velocities[2] *= slowdown