示例#1
0
def findPortalNear(world: World, blockPos: BlockPos,
                   maxHeight: int) -> Optional[BlockPos]:
    for totalDist in range(32):
        for xDist in range(totalDist):
            zDist = totalDist - xDist

            for y in range(maxHeight):
                if world.getBlock(
                        BlockPos(blockPos.x + xDist, y,
                                 blockPos.z + zDist)) == 'nether_portal':
                    return BlockPos(blockPos.x + xDist, y, blockPos.z + zDist)
                if world.getBlock(
                        BlockPos(blockPos.x + xDist, y,
                                 blockPos.z - zDist)) == 'nether_portal':
                    return BlockPos(blockPos.x + xDist, y, blockPos.z + zDist)
                if world.getBlock(
                        BlockPos(blockPos.x - xDist, y,
                                 blockPos.z + zDist)) == 'nether_portal':
                    return BlockPos(blockPos.x + xDist, y, blockPos.z + zDist)
                if world.getBlock(
                        BlockPos(blockPos.x - xDist, y,
                                 blockPos.z - zDist)) == 'nether_portal':
                    return BlockPos(blockPos.x + xDist, y, blockPos.z + zDist)

    return None
示例#2
0
def isValidSpawnLocation(app, dim: Dimension, pos: BlockPos):
    server: ServerState = app.server

    floor = BlockPos(pos.x, pos.y - 1, pos.z)
    feet = pos
    head = BlockPos(pos.x, pos.y + 1, pos.z)

    light = dim.world.getTotalLight(server.time, pos)

    isOk = (dim.world.coordsOccupied(floor)
            and not dim.world.coordsOccupied(feet)
            and not dim.world.coordsOccupied(head) and light < 8)

    return isOk
示例#3
0
def _decodeMultiBlockEntry(long):
    stateId = long >> 12
    x = (long >> 8) & 0xF
    z = (long >> 4) & 0xF
    y = long & 0xF

    return (stateId, BlockPos(x, y, 15-z))
示例#4
0
    def tick(self, app, entity: Entity, world, entities):
        wanderFreq = 0.01
        wanderDist = 3
        pos = entity.getBlockPos()
        if entity.path == [] and random.random() < wanderFreq:
            x = pos.x + random.randint(-wanderDist, wanderDist)
            y = pos.y + random.randint(-2, 2)
            z = pos.z + random.randint(-wanderDist, wanderDist)

            if (not world.coordsOccupied(BlockPos(x, y, z))
                    and world.coordsOccupied(BlockPos(x, y - 1, z))):

                path = findPath(pos, BlockPos(x, y, z), world)
                if path is not None:
                    entity.path = path

        return False
示例#5
0
def getDestination(app, world: World, searchPos: BlockPos,
                   maxHeight: int) -> BlockPos:
    existing = findPortalNear(world, searchPos, maxHeight)
    if existing is not None:
        print(f'Found existing portal at {existing}')
        return existing

    spot = findSpaceForPortal(world, searchPos, maxHeight)

    if spot is not None:
        print(f'Found space for portal at {spot}')
        createPortalAt(app, world, spot, clearNearby=False)
        return BlockPos(spot.x, spot.y + 1, spot.z)

    forcedPos = BlockPos(searchPos.x, maxHeight - 20, searchPos.z)

    createPortalAt(app, world, forcedPos, clearNearby=True)
    return BlockPos(forcedPos.x, forcedPos.y + 1, forcedPos.z)
示例#6
0
def destinations(start: BlockPos, world):
    for dx in (-1, 0, 1):
        for dz in (-1, 0, 1):
            if dx == 0 and dz == 0: continue

            dy = isValidDir(start, dx, dz, world)

            if dy is not None:
                pos = BlockPos(start.x + dx, start.y + dy, start.z + dz)
                yield (pos)
示例#7
0
    def fromBuf(cls, buf):
        x, y, z = buf.unpack_position()
        location = BlockPos(x, y, -(z+1))

        block = buf.unpack_varint()

        status = DiggingAction((buf.unpack_varint(),))

        successful = buf.unpack('?')

        return cls(location, block, status, successful)
示例#8
0
def isValidDir(start: BlockPos, dx: int, dz: int, world) -> Optional[int]:
    # These are in order of most to least common, for efficiency
    for dy in (0, 1, -1, -2, -3):
        dest = BlockPos(start.x + dx, start.y + dy, start.z + dz)

        if not canStandAt(dest, world):
            continue

        if dy == 0:
            if dx != 0 and dz != 0:
                # This is a simple, flat, diagonal path

                corner1 = BlockPos(start.x + dx, start.y, start.z)
                corner2 = BlockPos(start.x, start.y, start.z + dz)

                if (not canStandAt(corner1, world, needsFloor=False)
                        or not canStandAt(corner2, world, needsFloor=False)):

                    continue
            else:
                # This is a straight path
                return dy
        elif dx != 0 and dz != 0:
            # TODO:
            continue
        elif dy < 0:
            corner = BlockPos(start.x + dx, start.y, start.z + dz)

            if not canStandAt(corner, world, needsFloor=False):
                continue

            return dy
        elif dy > 0:
            corner = BlockPos(start.x, start.y + 1, start.z)

            if not canStandAt(corner, world, needsFloor=False):
                continue

            return dy

    return None
示例#9
0
def canStandAt(pos: BlockPos, world, needsFloor=True):
    # FIXME: Height

    if world.coordsOccupied(pos):
        return False
    elif not world.coordsOccupied(BlockPos(pos.x, pos.y - 1, pos.z)):
        if needsFloor:
            return False
        else:
            return True
    else:
        return True
示例#10
0
    def isValidPos(pos: BlockPos):
        for dy in range(0, 4):
            for dx in range(-1, 4):
                blockId = world.getBlock(
                    BlockPos(pos.x + dx, pos.y + dy, pos.z))
                if dy == 0:
                    if not isSolid(blockId):
                        return False
                else:
                    if blockId != 'air':
                        return False

        return True
示例#11
0
def doMobSpawning(app, server: ServerState, dim: Dimension):
    mobCap = len(dim.world.chunks) / 4

    random.seed(time.time())

    # HACK:
    player = server.players[0]

    for (chunkPos, chunk) in dim.world.chunks.items():
        chunk: world.Chunk
        if chunk.isTicking:
            if len(dim.entities) > mobCap:
                return

            # FIXME: Random tick speed?
            x = random.randrange(0, 16) + chunkPos.x * 16
            y = random.randrange(
                0, world.CHUNK_HEIGHT) + chunkPos.y * world.CHUNK_HEIGHT
            z = random.randrange(0, 16) + chunkPos.z * 16

            dist = math.sqrt((x - player.pos[0])**2 + (y - player.pos[1])**2 +
                             (z - player.pos[2])**2)

            minSpawnDist = 24.0

            if dist < minSpawnDist:
                continue

            if not isValidSpawnLocation(app, dim, BlockPos(x, y, z)): continue

            mob = random.choice(['creeper', 'zombie', 'skeleton'])

            packSize = 4
            for _ in range(packSize):
                x += random.randint(-2, 2)
                z += random.randint(-2, 2)
                if isValidSpawnLocation(app, dim, BlockPos(x, y, z)):
                    dim.entities.append(
                        Entity(app, server.getEntityId(), mob, x, y, z))
示例#12
0
def findSpaceForPortal(world: World, blockPos: BlockPos,
                       maxHeight: int) -> Optional[BlockPos]:
    def isValidPos(pos: BlockPos):
        for dy in range(0, 4):
            for dx in range(-1, 4):
                blockId = world.getBlock(
                    BlockPos(pos.x + dx, pos.y + dy, pos.z))
                if dy == 0:
                    if not isSolid(blockId):
                        return False
                else:
                    if blockId != 'air':
                        return False

        return True

    for totalDist in range(16):
        for xDist in range(totalDist):
            zDist = totalDist - xDist

            for y in range(10, maxHeight - 4):
                if isValidPos(
                        BlockPos(blockPos.x + xDist, y, blockPos.z + zDist)):
                    return BlockPos(blockPos.x + xDist, y, blockPos.z + zDist)

                if isValidPos(
                        BlockPos(blockPos.x + xDist, y, blockPos.z - zDist)):
                    return BlockPos(blockPos.x + xDist, y, blockPos.z - zDist)

                if isValidPos(
                        BlockPos(blockPos.x - xDist, y, blockPos.z + zDist)):
                    return BlockPos(blockPos.x - xDist, y, blockPos.z + zDist)

                if isValidPos(
                        BlockPos(blockPos.x - xDist, y, blockPos.z - zDist)):
                    return BlockPos(blockPos.x - xDist, y, blockPos.z - zDist)

    return None
示例#13
0
    def __init__(self):
        self.nextTeleportId = 1
        self.nextEntityId = 2
        self.nextWindowId = 1
        self.breakingBlock = 0.0
        self.breakingBlockPos = BlockPos(0, 0, 0)

        self.openWindows = {}
        self.heldItems = {}
        self.craftSlots = {}

        self.tickTimes = [0.0] * 10
        self.tickTimeIdx = 0

        self.time = 0

        self.gravity = 0.10

        self.preloadProgress = 0

        self.players = []
示例#14
0
def collideY(wld: World, entity: Entity, ticks=1.0, useGravity=True):
    entity.pos[1] += entity.velocity[1] * ticks

    if entity.onGround:
        if not wld.hasBlockBeneath(entity):
            entity.onGround = False
    else:
        #if not hasattr(entity, 'flying') or not entity.flying: #type:ignore
        if useGravity:
            entity.velocity[1] -= GRAVITY * ticks
        [_, yPos, _] = entity.pos
        #yPos -= entity.height
        yPos -= 0.1
        feetPos = roundHalfUp(yPos)
        if wld.hasBlockBeneath(entity):
            entity.onGround = True
            if hasattr(entity, 'flying'): entity.flying = False  #type:ignore
            entity.velocity[1] = 0.0
            #app.cameraPos[1] = (feetPos + 0.5) + entity.height
            entity.pos[1] = feetPos + 0.5

    if not entity.onGround:
        for x in [
                entity.pos[0] - entity.radius * 0.99,
                entity.pos[0] + entity.radius * 0.99
        ]:
            for z in [
                    entity.pos[2] - entity.radius * 0.99,
                    entity.pos[2] + entity.radius * 0.99
            ]:
                hiYCoord = roundHalfUp(entity.pos[1] + entity.height)

                if wld.coordsOccupied(BlockPos(round(x), hiYCoord, round(z)),
                                      world.isSolid):
                    yEdge = hiYCoord - 0.55
                    entity.pos[1] = yEdge - entity.height
                    if entity.velocity[1] > 0.0:
                        entity.velocity[1] = 0.0
示例#15
0
def createPortalAt(app, world: World, blockPos: BlockPos, clearNearby: bool):
    instData = (app.textures, app.cube, app.textureIndices)

    for dx in (-1, 0, 1, 2):
        world.setBlock(instData,
                       BlockPos(blockPos.x + dx, blockPos.y, blockPos.z),
                       'obsidian', {})
        world.setBlock(instData,
                       BlockPos(blockPos.x + dx, blockPos.y + 4, blockPos.z),
                       'obsidian', {})

    for dy in (1, 2, 3):
        world.setBlock(instData,
                       BlockPos(blockPos.x - 1, blockPos.y + dy, blockPos.z),
                       'obsidian', {})
        world.setBlock(instData,
                       BlockPos(blockPos.x + 2, blockPos.y + dy, blockPos.z),
                       'obsidian', {})

    for dx in (0, 1):
        for dy in (1, 2, 3):
            world.setBlock(instData,
                           BlockPos(blockPos.x + dx, blockPos.y + dy,
                                    blockPos.z),
                           'nether_portal', {'axis': 'x'},
                           doBlockUpdates=False)

    if clearNearby:
        for dz in (-1, 1):
            for dx in (-1, 0, 1, 2):
                for dy in (0, 1, 2, 3):
                    if dx in (0, 1) and dy == 0:
                        blockId = 'obsidian'
                        blockState = {}
                    else:
                        blockId = 'air'
                        blockState = {}

                    world.setBlock(
                        instData,
                        BlockPos(blockPos.x + dx, blockPos.y + dy,
                                 blockPos.z + dz), blockId, blockState)
示例#16
0
 def getBlockPos(self) -> BlockPos:
     bx = roundHalfUp(self.pos[0])
     by = roundHalfUp(self.pos[1])
     bz = roundHalfUp(self.pos[2])
     return BlockPos(bx, by, bz)
示例#17
0
def findPortalFrame(server: ServerState, dim: Dimension,
                    pos: BlockPos) -> Optional[Tuple[List[BlockPos], str]]:
    bottomPos1 = None
    topPos1 = None

    for i in range(1, 4):
        p = BlockPos(pos.x, pos.y - i, pos.z)
        if dim.world.getBlock(p) == 'obsidian':
            bottomPos1 = p
            break

    if bottomPos1 is None:
        return None

    for i in range(1, 4):
        p = BlockPos(pos.x, pos.y + i, pos.z)
        if dim.world.getBlock(p) == 'obsidian':
            topPos1 = p
            break

    if topPos1 is None:
        return None

    if topPos1.y - bottomPos1.y != 4:
        return None

    for dx, dz in ((-1, 0), (1, 0), (0, -1), (0, 1)):
        bottomPos2 = BlockPos(bottomPos1.x + dx, bottomPos1.y,
                              bottomPos1.z + dz)
        topPos2 = BlockPos(topPos1.x + dx, topPos1.y, topPos1.z + dz)

        # Need 2 blocks on top, 2 blocks on bottom
        if dim.world.getBlock(bottomPos2) != 'obsidian':
            continue
        if dim.world.getBlock(topPos2) != 'obsidian':
            continue

        answer = []

        ok = True

        for i in range(3):
            backSidePos = BlockPos(bottomPos1.x - dx, bottomPos1.y + 1 + i,
                                   bottomPos1.z - dz)
            backMidPos = BlockPos(bottomPos1.x, bottomPos1.y + 1 + i,
                                  bottomPos1.z)
            frontMidPos = BlockPos(bottomPos2.x, bottomPos2.y + 1 + i,
                                   bottomPos2.z)
            frontSidePos = BlockPos(bottomPos2.x + dx, bottomPos2.y + 1 + i,
                                    bottomPos2.z + dz)

            if (dim.world.getBlock(backSidePos) != 'obsidian'
                    or dim.world.getBlock(frontSidePos) != 'obsidian'
                    or dim.world.getBlock(backMidPos) != 'air'
                    or dim.world.getBlock(frontMidPos) != 'air'):

                ok = False
                break

            answer.append(backMidPos)
            answer.append(frontMidPos)

        if ok:
            return (answer, 'x' if dx != 0 else 'z')

    return None
示例#18
0
 def fromBuf(cls, buf):
     x, y, z = buf.unpack_position()
     location = BlockPos(x, y, -(z+1))
     blockId = buf.unpack_varint()
     
     return cls(location, blockId)
示例#19
0
def collideXZ(wld: World, entity: Entity, ticks=1.0):
    hitWall = False

    minY = roundHalfUp((entity.pos[1]))
    maxY = roundHalfUp((entity.pos[1] + entity.height))

    lastX = entity.pos[0]
    lastZ = entity.pos[2]

    entity.pos[0] += entity.velocity[0] * ticks

    for y in range(minY, maxY + 1):
        for z in [
                entity.pos[2] - entity.radius * 0.99,
                entity.pos[2] + entity.radius * 0.99
        ]:
            x = entity.pos[0]

            hiXBlockCoord = round((x + entity.radius))
            loXBlockCoord = round((x - entity.radius))

            if wld.coordsOccupied(BlockPos(hiXBlockCoord, y, round(z)),
                                  world.isSolid):
                # Collision on the right, so move to the left
                xEdge = (hiXBlockCoord - 0.5)
                entity.pos[0] = xEdge - entity.radius
                hitWall = True
            elif wld.coordsOccupied(BlockPos(loXBlockCoord, y, round(z)),
                                    world.isSolid):
                # Collision on the left, so move to the right
                xEdge = (loXBlockCoord + 0.5)
                entity.pos[0] = xEdge + entity.radius
                hitWall = True

    entity.pos[2] += entity.velocity[2] * ticks

    for y in range(minY, maxY + 1):
        for x in [
                entity.pos[0] - entity.radius * 0.99,
                entity.pos[0] + entity.radius * 0.99
        ]:
            z = entity.pos[2]

            hiZBlockCoord = round((z + entity.radius))
            loZBlockCoord = round((z - entity.radius))

            if wld.coordsOccupied(BlockPos(round(x), y, hiZBlockCoord),
                                  world.isSolid):
                zEdge = (hiZBlockCoord - 0.5)
                entity.pos[2] = zEdge - entity.radius
                hitWall = True
            elif wld.coordsOccupied(BlockPos(round(x), y, loZBlockCoord),
                                    world.isSolid):
                zEdge = (loZBlockCoord + 0.5)
                entity.pos[2] = zEdge + entity.radius
                hitWall = True

    entity.distanceMoved = math.sqrt((entity.pos[0] - lastX)**2 +
                                     (entity.pos[2] - lastZ)**2)

    return hitWall