You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
6.2 KiB
215 lines
6.2 KiB
import re |
|
import time |
|
import importlib |
|
import random |
|
from itertools import count |
|
from math import 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 = utils.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 = utils.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()
|
|
|