216 lines
6.2 KiB
Python
216 lines
6.2 KiB
Python
import re
|
|
import time
|
|
import importlib
|
|
import random
|
|
from itertools import count
|
|
from math import hypot, floor
|
|
|
|
from minecraft.networking.types import BlockFace
|
|
|
|
from mosfet.protocol.managers import ChunkNotLoadedException
|
|
|
|
from mosfet import utils
|
|
from mosfet import path
|
|
from mosfet.info import blocks
|
|
from mosfet.info import items
|
|
from mosfet.info import mcdata
|
|
from mosfet.info import mobs
|
|
|
|
class FillBlocksStates:
|
|
def idle(self):
|
|
return None
|
|
|
|
def init(self):
|
|
f = self.g.filling
|
|
|
|
if not f:
|
|
self.state = self.cleanup
|
|
print('Aborting, nothing to fill')
|
|
return
|
|
|
|
if self.last_block:
|
|
self.state = self.select_item
|
|
else:
|
|
self.state = self.find_last_block
|
|
|
|
def find_last_block(self):
|
|
w = self.g.world
|
|
f = self.g.filling
|
|
print('Finding last block')
|
|
|
|
b1, b2 = utils.pboundingbox(f.coord1, f.coord2)
|
|
box = utils.psub(b2, b1)
|
|
xz_distance = hypot(box[0]+1, box[2]+1)
|
|
y_start = f.coord1[1]
|
|
y_end = f.coord2[1]
|
|
|
|
for y in range(y_start, y_end+1):
|
|
for offset in utils.search_2d(xz_distance):
|
|
check = utils.padd(f.coord1, offset)
|
|
check = (check[0], y, check[2])
|
|
|
|
# ensure block is within fill area
|
|
if check[0] < b1[0] or check[0] > b2[0]:
|
|
continue
|
|
if check[2] < b1[2] or check[2] > b2[2]:
|
|
continue
|
|
|
|
if w.block_at(*check) == blocks.AIR:
|
|
self.state = self.select_item
|
|
return
|
|
|
|
self.last_block = check
|
|
else: # for
|
|
self.state = self.cleanup
|
|
print('Aborting, no air left')
|
|
return
|
|
|
|
def select_item(self):
|
|
f = self.g.filling
|
|
name = blocks.BLOCKS[f.block]
|
|
item = items.ITEMS['minecraft:'+name]['protocol_id']
|
|
|
|
if self.g.game.select_item([item]):
|
|
#self.g.look_at = utils.padd(self.area, path.BLOCK_BELOW)
|
|
self.state = self.find_next_block
|
|
else:
|
|
print('No blocks, aborting')
|
|
self.state = self.cleanup
|
|
|
|
def find_next_block(self):
|
|
w = self.g.world
|
|
f = self.g.filling
|
|
print('Finding next block, last:', self.last_block)
|
|
|
|
b1, b2 = utils.pboundingbox(f.coord1, f.coord2)
|
|
box = utils.psub(b2, b1)
|
|
xz_distance = hypot(box[0]+1, box[2]+1)
|
|
y_start = f.coord1[1]
|
|
y_end = f.coord2[1]
|
|
|
|
for y in range(y_start, y_end+1):
|
|
if y not in self.iterators:
|
|
self.iterators[y] = utils.search_2d(xz_distance)
|
|
|
|
for offset in self.iterators[y]:
|
|
check = utils.padd(f.coord1, offset)
|
|
check = (check[0], y, check[2])
|
|
|
|
# ensure block is within fill area
|
|
if check[0] < b1[0] or check[0] > b2[0]:
|
|
continue
|
|
if check[2] < b1[2] or check[2] > b2[2]:
|
|
continue
|
|
|
|
if w.block_at(*check) == blocks.AIR:
|
|
print('Found next block:', check)
|
|
self.next_block = check
|
|
self.state = self.check_block_distance
|
|
return
|
|
|
|
# if there's nothing left to fill
|
|
self.g.filling = None
|
|
self.state = self.cleanup
|
|
|
|
def check_block_distance(self):
|
|
w = self.g.world
|
|
p = utils.pint(self.g.pos)
|
|
head = utils.padd(p, path.BLOCK_ABOVE)
|
|
|
|
if utils.phyp(head, self.next_block) < 4:
|
|
self.state = self.fill_block
|
|
else:
|
|
self.state = self.nav_to_block
|
|
|
|
def nav_to_block(self):
|
|
w = self.g.world
|
|
p = utils.pint(self.g.pos)
|
|
c = self.g.chunks
|
|
|
|
tmp = c.get_block_at(*self.next_block)
|
|
c.set_block_at(*self.next_block, blocks.STONE)
|
|
pos = utils.padd(self.next_block, path.BLOCK_ABOVE)
|
|
navpath = w.path_to_place(p, pos)
|
|
c.set_block_at(*self.next_block, tmp)
|
|
|
|
if navpath:
|
|
self.g.path = navpath[:-1]
|
|
self.state = self.going_to_block
|
|
else:
|
|
print('Cant get to that block')
|
|
self.state = self.cleanup
|
|
time.sleep(0.1)
|
|
|
|
def going_to_block(self):
|
|
if not len(self.g.path):
|
|
self.state = self.fill_block
|
|
|
|
def fill_block(self):
|
|
print('Filling block', self.next_block)
|
|
|
|
self.g.game.place_block(self.next_block, BlockFace.TOP)
|
|
self.g.look_at = self.next_block
|
|
|
|
self.wait_time = 0.25
|
|
self.state = self.wait_for_block
|
|
|
|
def wait_for_block(self):
|
|
w = self.g.world
|
|
if w.block_at(*self.next_block) != blocks.AIR:
|
|
self.last_block = self.next_block
|
|
self.state = self.check_obstruction
|
|
elif self.wait_time > 0:
|
|
self.wait_time -= utils.TICK
|
|
else:
|
|
print('Block didnt appear')
|
|
self.state = self.check_obstruction
|
|
|
|
def check_obstruction(self):
|
|
p = utils.pint(self.g.pos)
|
|
f = self.g.filling
|
|
print('last', self.last_block)
|
|
print('p', p)
|
|
if self.last_block[1] >= p[1] and f.block not in blocks.NON_SOLID_IDS:
|
|
print('Obstructed, going to last block')
|
|
self.state = self.nav_to_last_block
|
|
else:
|
|
self.state = self.cleanup
|
|
|
|
def nav_to_last_block(self):
|
|
w = self.g.world
|
|
p = utils.pint(self.g.pos)
|
|
c = self.g.chunks
|
|
|
|
pos = utils.padd(self.last_block, path.BLOCK_ABOVE)
|
|
navpath = w.path_to_place(p, pos)
|
|
|
|
if navpath:
|
|
self.g.path = navpath
|
|
self.state = self.going_to_last_block
|
|
else:
|
|
print('Cant get to that block')
|
|
self.state = self.cleanup
|
|
|
|
def going_to_last_block(self):
|
|
if not len(self.g.path):
|
|
self.state = self.cleanup
|
|
|
|
def cleanup(self):
|
|
self.state = self.done
|
|
|
|
def done(self):
|
|
# never gets ran, placeholder
|
|
return None
|
|
|
|
def __init__(self, global_state):
|
|
self.g = global_state
|
|
self.state = self.idle
|
|
|
|
self.iterators = {}
|
|
self.wait_time = 0
|
|
self.last_block = None
|
|
self.next_block = None
|
|
|
|
def run(self):
|
|
self.state()
|