minehaxore
Posts: 10
Joined: Sun Mar 25, 2018 11:51 am

MCPI: Delete a user defined area

Sun Mar 25, 2018 12:08 pm

Hi there,

I'm totally new to MCPI (and to programming in general) and as such I've been having all kinds of problems.

Generally speaking, the results of said problems tend to manifest as unseemly junk lying around my beautiful Minecraft world. I'm quite a tidy sort of person and as such I've been dreaming of a piece of code that would allow me to delete an area (defined by me at run time) within my Minecraft world.

The code I've been imagining would allow me to "record" two different block locations - perhaps on hit?
So hitting the first block would store its coordinates (x1, y1, z1) and hitting a second block would store its coordinates (x2, y2, z2)
And the last step is to use the pair of coords to define a cuboid area and to turn that area into air blocks

Does anyone have any pointers on how I might achieve that effect?
Last edited by minehaxore on Sun Mar 25, 2018 9:40 pm, edited 1 time in total.

scotty101
Posts: 3723
Joined: Fri Jun 08, 2012 6:03 pm

Re: MCPI: Delete a user defined area

Sun Mar 25, 2018 5:37 pm

This is pretty easy in MCPI.
Have you been able to detect where the player 'hits' the landscape? This is well documented in the many tutorials out there.
If you can share some code that prints out where the user hits, I'll help you with some code ideas to do what you want.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

minehaxore
Posts: 10
Joined: Sun Mar 25, 2018 11:51 am

Re: MCPI: Delete a user defined area

Sun Mar 25, 2018 9:39 pm

Hey thank you for kindly offering your help. It's very frustrating knowing what I want my program to do, without fully understanding the language or even the basic principles of programming. I imagine that is what a child feels like when they have something to say but only have a limited vocabulary. I'm not asking you to do all the work for me - but some pointers at this early stage would be hugely appreciated and would likely help me a lot.

Here's what I've been looking at...

1. import mcpi.minecraft as minecraft
2. import mcpi.block as block

3. mc = minecraft.Minecraft.create()

4. mc.events.pollBlockHits():
5. mc.setBlocks()

-----------------------------------------------------------------------------------------------

1. I guess this is some kind of library? (is that the correct term?) If it is, I have no idea how idle / python knows it's location (there's no path!?)

2. Again another library? This seems important for doing stuff with blocks

3. I think this is pointing to the Minecraft game, I think I read somewhere that an ip address and port number can be defined here

4. This seems like a crucial function to achieve my desired result - but how will I store the values? Or rather, where are the values stored and how can I manipulate them or add them them to another part of my code along with the second set of values from the second block hit?

Can I store the value in an array? (not entirely sure what an array is btw) I also need some way to reset the program once the second block has been defined and the defined area has been turned to AIR. To achieve that I guess I'll need a way to count the block hits - no clue how I'll do that but I think I would need to store a variable "hit_count" and add each hit to that. (Maybe once "hit_count" > 2 then "hit_count" = 1)

5. I guess this is the function call that I will use to change the defined area to AIR.

scotty101
Posts: 3723
Joined: Fri Jun 08, 2012 6:03 pm

Re: MCPI: Delete a user defined area

Mon Mar 26, 2018 8:29 am

1/2. Yep these are both part of the MCPI library. Python doesn't need an exact path because the MCPI library is stored in a known location where python looks for libraries.
3. Yes this connects to the Minecraft Pi game itself.
4. Well found. This function returns a list of items hit since the last time you checked. See example code below for an example of its usage.
5. Yep! That's the function to use.

Code: Select all

import time
import mcpi.minecraft as minecraft

mc = minecraft.Minecraft.create()

hitCounter = 0
hitList = []

while True:
    for hit in mc.events.pollBlockHits():
        #Process each hit in turn, get the x,y,z position of each.
        x = hit.pos.x
        y = hit.pos.y
        z = hit.pos.z
        mc.postToChat('You hit block ({},{},{})'.format(x,y,z))
        #Record how many blocks have been hit in total
        hitCounter += 1

        #if the total number of hits is less than two, add the position to a list
        if hitCounter < 2:
            hitList.append((x,y,z))

    time.sleep(1)
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

minehaxore
Posts: 10
Joined: Sun Mar 25, 2018 11:51 am

Re: MCPI: Delete a user defined area

Mon Mar 26, 2018 11:47 am

Thank you so much for the help! You've given me excellent code to work with and I'm going to have great fun trying to complete it.

After a bit of reading I realise that I don't need an array... The "hitList = []" part of your program is presumably a "list" and it's the "hitList.append((x,y,z))" part of the code that is writing my block hits to the list. Now I just have to figure out how to read the contents of the list into the mc.setBlocks() function.

Fun times! Thanks again for all the help - I'll post my finished code tonight if I get the time to tinker with it :D

minehaxore
Posts: 10
Joined: Sun Mar 25, 2018 11:51 am

Re: MCPI: Delete a user defined area

Tue Mar 27, 2018 4:45 pm

Hi I've been experimenting with the code but unfortunately I've not gotten very far. I'm not entirely sure what's going on with the list; I added a line of code to interrogate it...

Code: Select all

if hitCounter == 2:
           print (hitList [0:5])
... But after the second block hit, the python shell just returns the first block hit value. I'm not sure if the second block value has actually been appended to the list, or if I'm just doing something wrong with the formatting of my print function. I used [0:5] under the presumption that it would return the expected six values in the list (x, y, z, x, y, z). Is there some other syntax I could use to print the entire list to the python shell window?

scotty101
Posts: 3723
Joined: Fri Jun 08, 2012 6:03 pm

Re: MCPI: Delete a user defined area

Tue Mar 27, 2018 5:59 pm

Can you share all the code you've written?

hitList[0:5] would return the elements 0 to 5 of the list. Each entry in the list contains a tuple containing (x,y,z) coordinates.

I'm on my phone so apologies if this doesn't work but try this to get your start/end coords for the set_blocks function.

Code: Select all

x1,y1,z1 = hitList[0]
x2,y2,z3 = hitList[1]
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

yfpiLiker
Posts: 32
Joined: Sat Mar 24, 2018 7:46 am

Re: MCPI: Delete a user defined area

Thu Mar 29, 2018 5:44 am

Hi,
Yes, that should work.
And at the end you write:

Code: Select all

mc.setBlocks(x1, y1, z1, x2, y2, z2, 0)
You don't Need to import mcpi.blocks.
In my programs, I give the method the number of the blocks.
0 is Air
You can look up the other names and numbers in the library.
It is located /opt/minecraft-pi/api/python/minecraft , i think. Ist in the file block.py.

Kinds Regards

yfpiLiker
Not English. But Pythish.

minehaxore
Posts: 10
Joined: Sun Mar 25, 2018 11:51 am

Re: MCPI: Delete a user defined area

Fri Mar 30, 2018 12:21 pm

Thanks again for all the help guys. I'll return shortly and post my completed code, but for now I've decided to put Minecraft / mcpi to one side - I think it was just confusing me.

Instead I'm working through the book "Invent Your Own Computer Games With Python" which I'm finding very clear and helpful as it reviews each piece of code and explains things like what constitutes a statement, expression, function, block, variable etc.

I think I just need to quickly gain a grasp of all of the basics and then the above mcpi program will virtually write itself. Currently I'm just too confused about where those values are stored, what format they're stored in and how I can manipulate the values (ie. use the coords in function calls) and how I correctly define the formatting of the coordinate values.

I thought Minecraft would be the best intro to learning python because its fun and simple - but as it turns out, it just adds a layer of complexity and abstraction that isn't helpful to me right now. I'm a slow methodical learner and generally need a reasonable holistic overview of a subject before I can sythesize something new with that knowledge.

scotty101
Posts: 3723
Joined: Fri Jun 08, 2012 6:03 pm

Re: MCPI: Delete a user defined area

Fri Mar 30, 2018 3:00 pm

You can learn python and Minecraft pi at the same time with the downloadable material at the below link

https://www.raspberrypi.org/blog/learni ... odecademy/
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

minehaxore
Posts: 10
Joined: Sun Mar 25, 2018 11:51 am

Re: MCPI: Delete a user defined area

Sat Mar 31, 2018 9:41 pm

I tried the following code today, to no avail....

Code: Select all

import mcpi.minecraft as minecraft
import mcpi.block as block

mc = minecraft.Minecraft.create()

hitCounter = 0
hitList = [] * 2

while True:
    for hit in mc.events.pollBlockHits in range(2):
        x = hit.pos.x
        y = hot.pos.y
        z = hit.pos.z

    hitCounter += 1
        
    hitList.append((x, y, z))

    x1,y1,z1 = hitList[0]
    x2,y2,z2 = hitList[1]
        
    if hitCounter == 2:
        mc.setBlocks(x1, y1, z1, x2, y2, z2, 0)
It returned the following error...

Traceback (most recent call last):
File "/home/pi/Documents/python scripts/mcpi scripts/Delete Area 2.py", line 10, in <module>
for hit in mc.events.pollBlockHits in range(2):
TypeError: 'bool' object is not iterable

I'm starting to think a modified version of the following code might work better - but i'm still struggling to work out how to pass values from BlockHits to my setBlocks function.

Code: Select all

from mcpi.minecraft import Minecraft
mc = Minecraft.create()


def sortPair(val1, val2):
    if val1 > val2:
        return val2, val1
    else:
        return val1, val2


def copyStructure(x1, y1, z1, x2, y2, z2):
    x1, x2 = sortPair(x1, x2)
    y1, y2 = sortPair(y1, y2)
    z1, z2 = sortPair(z1, z2)

    width = x2 - x1
    height = y2 - y1
    length = z2 - z1

    structure = []

    print("Please wait...")

    # Copy the structure
    for row in range(height):
        structure.append([])
        for column in range(width):
            structure[row].append([])
            for depth in range(length):
                block = mc.getBlock(x1 + column, y1 + row, z1 + depth)
                structure[row][column].append(block)

    return structure


def buildStructure(x, y, z, structure):
    xStart = x
    yStart = y
    for row in structure:
        for column in row:
            for block in column:
                mc.setBlock(x, y, z, block)
                z += 1
            x += 1
            z = yStart
        y += 1
        x = xStart


# get the position of the first corner
input("Move to the first corner and press enter in this window")
pos = mc.player.getTilePos()
x1, y1, z1 = pos.x, pos.y, pos.z

# get the position of the second corner
input("Move to the opposite corner and press enter in this window")
pos = mc.player.getTilePos()
x2, y2, z2 = pos.x, pos.y, pos.z

# copy the building
structure = copyStructure(x1, y1, z1, x2, y2, z2)

# get the position for the copy
input("Move to the position you want to create the structure and press ENTER in this window")
pos = mc.player.getTilePos()
x, y, z = pos.x, pos.y, pos.z
buildStructure(x, y, z, structure)

scotty101
Posts: 3723
Joined: Fri Jun 08, 2012 6:03 pm

Re: MCPI: Delete a user defined area

Sun Apr 01, 2018 10:18 am

With the following line

Code: Select all

for hit in mc.events.pollBlockHits in range(2):
I can see what you are trying to do but this won't work. pollBlockHits is missing the () at the end and you can't just add the range(2) on the end.

Here is some psuedo code.

Code: Select all

While loop
    For each block hit
        Add the position of the block hit to the list
        If there are two positions in the list
            Get the start x,y,z coords
            Get the end x,y,z coords
            Set blocks between start and end to air
            Empty list for next time
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

Return to “Python”