import importlib import collections from math import floor, ceil, sqrt from mosfet.info import blocks from mosfet.info import mcdata TICK = 0.05 def hypot(*coordinates): # python's 3D hypot is too new, so we'll use our own return sqrt(sum(x**2 for x in coordinates)) def padd(p1, p2): return (p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2]) def psub(p1, p2): return (p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]) def pmul(p, s): return (s*p[0], s*p[1], s*p[2]) def phyp(p1, p2): return hypot(p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]) def phyp_bias(p1, p2, origin): origin_distance = phyp(origin, p2) height_diff = p2[1] - p1[1] height_diff = height_diff*8 if height_diff < 0 else height_diff*0.5 return hypot(p1[0] - p2[0], height_diff, p1[2] - p2[2]) + origin_distance*0.5 def phyp_king(p1, p2): # calculates the Chebyshev distance return max(abs(p1[0] - p2[0]), abs(p1[1] - p2[1]), abs(p1[2] - p2[2])) def pint(p): return (floor(p[0]), floor(p[1]), floor(p[2])) def pboundingbox(p1, p2): b1 = (min(p1[0], p2[0]), min(p1[1], p2[1]), min(p1[2], p2[2])) b2 = (max(p1[0], p2[0]), max(p1[1], p2[1]), max(p1[2], p2[2])) return b1, b2 def pvolume(p1, p2): b1, b2 = pboundingbox(p1, p2) box = psub(b2, b1) return (box[0]+1) * (box[1]+1) * (box[2]+1) def cap(x, amount): sign = 1 if x >= 0 else -1 return sign * min(abs(x), amount) def spiral(n): # return x, 0, z coords along a spiral at step n # I forget where I found this n += 1 k = ceil((sqrt(n)-1)/2) t = 2 * k + 1 m = t**2 t = t - 1 if n >= m-t: return k-(m-n), 0, -k else: m = m-t if n >= m-t: return -k, 0, -k+(m-n) else: m = m-t if n >= m-t: return -k+(m-n), 0, k else: return k, 0, k-(m-n-t) def alternate(n, amount): # return 0, y, 0 where y alternates +/- by amount # example: 0, 2, -2, 4, -4, 6, -6 for amount = 2 sign = 1 if n % 2 else -1 return (0, ceil(n/2) * sign * amount, 0) def diffrange(n): # same as range(n+1) but can go negative sign = 1 if n >= 0 else -1 return range(0, n+sign, sign) def break_time(block_id, held_item=0, in_water=False, on_ground=True, enchantments=None, effects=None): """Return vanilla block-breaking duration rounded to whole game ticks.""" held_item = str(held_item) block_data = blocks.get(block_id) hardness = block_data.get('hardness', 0) if hardness < 0: return float('inf') can_harvest = ( 'harvestTools' not in block_data or held_item in block_data['harvestTools']) material = block_data.get('material', 'n/a') tool_multipliers = mcdata.mcd.materials.get(material, {}) speed = tool_multipliers.get(held_item, 1.0) enchantments = enchantments or {} if speed > 1: efficiency = int(enchantments.get( 'efficiency', enchantments.get('minecraft:efficiency', 0)) or 0) if efficiency > 0: speed += efficiency * efficiency + 1 effects = effects or {} haste = int(effects.get('haste', effects.get('minecraft:haste', 0)) or 0) if haste >= 0 and ('haste' in effects or 'minecraft:haste' in effects): speed *= 1 + 0.2 * (haste + 1) fatigue = int(effects.get( 'mining_fatigue', effects.get('minecraft:mining_fatigue', -1))) if fatigue >= 0: speed *= (0.3, 0.09, 0.0027, 0.00081, 0.000243)[min(fatigue, 4)] duration = hardness * (1.5 if can_harvest else 5.0) / speed if in_water: duration *= 5.0 if not on_ground: duration *= 5.0 # Vanilla advances breaking progress in 1/20-second ticks; clients cannot # finish between ticks. Round up, while avoiding floating-point over-round. ticks = max(1, ceil(duration / TICK - 1e-9)) return ticks * TICK def search_2d(distance=0): def get_neighbors(x,y,z): return [ (x+1, y+0, z+0), #(x+1, y+0, z+1), (x+0, y+0, z-1), #(x-1, y+0, z+1), (x-1, y+0, z+0), #(x-1, y+0, z-1), (x+0, y+0, z+1), #(x+1, y+0, z-1), ] to_visit = collections.deque([(0, 0, 0)]) visited = set() while to_visit: cur = to_visit.pop() if cur in visited: continue if distance and hypot(*cur) > distance: continue for neighbor in get_neighbors(*cur): to_visit.appendleft(neighbor) visited.add(cur) yield cur def get_neighbors_3d(x,y,z): return [ #(x+1, y+1, z+0), #(x+1, y-1, z+0), #(x+1, y+1, z+1), #(x+1, y+0, z+1), #(x+1, y-1, z+1), #(x+1, y+1, z-1), #(x+1, y+0, z-1), #(x+1, y-1, z-1), (x+1, y+0, z+0), (x+0, y+1, z+0), (x+0, y-1, z+0), #(x+0, y+1, z+1), (x+0, y+0, z+1), #(x+0, y-1, z+1), #(x+0, y+1, z-1), (x+0, y+0, z-1), #(x+0, y-1, z-1), #(x-1, y+1, z+0), #(x-1, y-1, z+0), #(x-1, y+1, z+1), #(x-1, y+0, z+1), #(x-1, y-1, z+1), #(x-1, y+1, z-1), #(x-1, y+0, z-1), #(x-1, y-1, z-1), (x-1, y+0, z+0), ]