8.1. Podstawy mcpi

8.1.1. Połączenie z serwerem

Za pomocą wybranego edytora utwórz pusty plik, umieść w nim podany niżej kod i zapisz w katalogu mcpi-sim pod nazwą mcpi-podst.py:

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import mcpi.minecraft as minecraft  # import modułu minecraft
import mcpi.block as block  # import modułu block

os.environ["USERNAME"] = "Steve"  # nazwa użytkownika
os.environ["COMPUTERNAME"] = "mykomp"  # nazwa komputera

# utworzenie połączenia z minecraftem
mc = minecraft.Minecraft.create("192.168.1.10")  # podaj adres IP Rpi


def main(args):
    mc.postToChat("Czesc! Tak dziala MC chat!")  # wysłanie komunikatu do mc
    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv))

Na początku importujemy moduły do obsługi Minecrafta i za pomocą instrukcji os.environ["ZMIENNA"] ustawiamy wymagane przez mcpi zmienne środowiskowe z nazwami użytkownika i komputera:

Note

Udany import wymaga, aby w katalogu ze skryptem znajdował się katalog mcpi, z którego importujemy wymagane moduły. Jeżeli katalog ten byłby w innym folderze, np. biblioteki, przed instrukcjami importu musielibyśmy wskazać ścieżkę do niego, np: sys.path.append("/home/user/biblioteki").

Po wykonaniu czynności wstępnych tworzymy podstawowy obiekt reprezentujący grę Minecraft: mc = minecraft.Minecraft.create("192.168.1.8").

Tip

Adres IP serwera Minecrafta, czyli minikomputera Raspberry Pi, odczytamy po najechaniu myszą na ikonę połączenia sieciowego w prawym górnym rogu pulpitu (zob. zrzut poniżej). Możemy też wydać w terminalu polecenie ip addr i odczytać adres poprzedzony przedrostkiem inet dla interfejsu eth0 (łącze kablowe) lub wlan0 (łącze radiowe).

../../_images/rasplan-ip.jpg

Na końcu w funkcji main(), czyli głównej, wywołujemy metodę postToChat(), która pozwala wysłać i wyświetlić podaną wiadomość na czacie Minecrafta.

Skrypt uruchamiamy z poziomu edytora, jeśli to możliwe, lub wykonując w terminalu polecenie:

~/mcpi-sim$ python mcpi-podst.py

Note

Omówiony kod (linie 4-14) stanowi niezbędne minimum, które musi znaleźć się w każdym skrypcie lub w sesji interpretera (konsoli), jeżeli chcemy widzieć efekty naszych działań na serwerze. Dla wygody kopiowania podajemy go w skondensowanej formie:

Kod nr
1
2
3
4
5
6
import mcpi.minecraft as minecraft  # import modułu minecraft
import mcpi.block as block  # import modułu block
import os
os.environ["USERNAME"] = "Steve"  # wpisz dowolną nazwę użytkownika
os.environ["COMPUTERNAME"] = "mykomp"  # wpisz dowolną nazwę komputera
mc = minecraft.Minecraft.create("192.168.1.8")

8.1.2. Świat Minecrafta Pi

Świat Minecrafta Pi opisujemy za pomocą trójwymiarowego układu współrzędnych:

../../_images/minecraft-system.png

Obserwując położenie bohatera gry Steve’a zauważymy, że zmiany współrzędnej x (klawisze A i D) i z (klawisze W i S) przesuwają postać w lewo/prawo, do przodu/tyłu, czyli horyzontalnie, natomiast zmiany współrzędnej y do góry/w dół - wertykalnie.

Note

W Pi Edition wartości x i y ograniczono do przedziału [-128, 127].

Ćwiczenie 1

Uruchamiamy rozszerzoną konsolę Pythona i wchodzimy do katalogu mcpi-sim:

    ~$ ipython qtconsole
In [1]: cd /root/mcpi-sim

Tip

Podane polecenie można wpisać również w okienko “Uruchom” wywoływane w środowiskach linuksowych zazwyczaj przez skrót ALT+F2.

Zamiast rozszerzonej konsoli qt możemy użyć zwykłej konsoli ipython lub podstawowego interpretera python uruchamianych w terminalu. Uwaga: jeżeli skorzystamy z interpretera podstawowego kod kopiujemy i wklejamy linia po linii.

Kopiujemy do okna konsoli, uruchamiamy omówiony powyżej “Kod 2”, służący nawiązaniu połączenia z serwerem, i wysyłamy wiadomość na czat:

../../_images/ipython01.png

Poznamy teraz kilka podstawowych metod pozwalających na manipulowanie światem Minecrafta.

8.1.3. Orientuj się Steve!

Wpisz w konsoli poniższy kod:

>>> mc.player.getPos()
>>> x, y, z = mc.player.getPos()
>>> print x, y, z
>>> x, y, z = mc.player.getTilePos()
>>> print x, y, z

Metoda getPos() obiektu player zwraca nam obiekt zawierający współrzędne określające pozycję bohatera. Metoda getTitlePos() zwraca z kolei współrzędne bloku, na którym stoi bohater. Instrukcje typu x, y, z = mc.player.getPos() rozpakowują kolejne współrzędne do zmiennych x, y i z. Możemy wykorzystać je do zmiany położenia bohatera:

>>> mc.player.setPos(x+10, y+20, z)

Powyższy kod przesunie bohatera w bok o 10 bloków i do góry na wysokość 20 bloków. Podobnie zadziała kod mc.player.setTilePos(x+10, y+20, z), który przeniesie postać na blok, którego pozycję podamy.

8.1.3.1. Idź i przesuń się

Zadania takie możemy realizować za pomocą funkcji, które dodatkowo zwrócą nam nową pozycję. W pliku mcpi-podst.py umieszczamy kod:

Kod nr
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def idzDo(x=0, y=0, z=0):
    """Funkcja przenosi gracza w podane miejsce.
    Parametry: x, y, z - współrzędne miejsca
    """
    y = mc.getHeight(x, z)  # ustalenie wysokości podłoża
    mc.player.setPos(x, y, z)
    return mc.player.getPos()


def przesunSie(x1=0, y1=0, z1=0):
    """Funkcja przesuwa gracza o podaną liczbę bloków
    i zwraca nową pozycję.
    Parametry: x1, y1, z1 - ilość bloków, o którą powiększamy
    lub pomniejszamy współrzędne pozycji gracza.
    """

    x, y, z = mc.player.getPos()  # aktualna pozycja
    y = mc.getHeight(x + x1, z + z1)  # ustalenie wysokości podłoża
    mc.player.setPos(x + x1, y + y1, z + z1)
    return mc.player.getPos()

W pierwszej funkcji idzDo() warto zwrócić uwagę na metodę getHeight(), która pozwala ustalić wysokość świata w punkcie x, z, czyli współrzędną y najwyższego bloku nie będącego powietrzem. Dzięki temu umieścimy bohatera zawsze na jakiejś powierzchni, a nie np. pod ziemią ;-). Druga funkcja przesunSie() nie tyle umieszcza, co przesuwa postać, stąd dodatkowe instrukcje.

Dopisz wywołanie print idzDo(50, 0, 50) w funkcji main() przed instrukcją return i przetestuj kod uruchamiając skrypt mcpi-podst.py lub w konsoli. Później dopisz również drugą funkcję print przesunSie(20) i sprawdź jej działanie.

../../_images/ipython02.png

Ćwiczenie 2

Sprawdź, co się stanie, kiedy podasz współrzędne większe niż świat Minecrafta. Zmień kod obydwu funkcji na “bezpieczny dla życia” ;-)

8.1.3.2. Gdzie jestem?

Aby odczytywać i drukować pozycję bohatera dodamy kolejną funkcję do pliku mcpi-podst.py:

Kod nr
38
39
40
41
42
43
44
45
46
def drukujPoz():
    """Drukuje pozycję gracza.
    Wymaga globalnego obiektu połączenia mc.
    """

    pos = mc.player.getPos()
    print pos
    pos_str = map(str, (pos.x, pos.y, pos.z))
    mc.postToChat("Pozycja: " + ", ".join(pos_str))

Funkcja nie tylko drukuje koordynaty w konsoli (print x, y, z), ale również – po przekształceniu ich na listę wartości typu string pos_str = map(str, pos_list) – wysyła jako komunikat na czat Minecrafta. Wywołanie funkcji dopisujemy do funkcji głównej i testujemy kod:

../../_images/ipython03.png

8.1.3.3. Więcej ruchu

Teraz możemy trochę pochodzić, ale będziemy obserwować to z lotu ptaka. Dopiszmy kod poniższej funkcji do pliku mcpi-podst.py:

Kod nr
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def ruszajSie():
    from time import sleep

    krok = 10
    # ustawienie pozycji gracza w środku świata na odpowiedniej wysokości
    przesunSie(0, 0, 0)

    mc.postToChat("Latam...")
    przesunSie(0, krok, 0)  # idź krok bloków do góry - latamy :-)
    sleep(2)

    mc.camera.setFollow()  # ustawienie kamery z góry

    mc.postToChat("Ide w bok...")
    for i in range(krok):
        przesunSie(1)  # idź krok bloków w bok
    sleep(2)

    mc.postToChat("Ide w drugi bok...")
    for i in range(krok):
        przesunSie(-1)  # idź krok bloków w drugi bok
    sleep(2)

    mc.postToChat("Ide do przodu...")
    for i in range(krok):
        przesunSie(0, 0, 1)  # idź krok bloków do przodu
    sleep(2)

    mc.postToChat("Ide do tylu...")
    for i in range(krok):
        przesunSie(0, 0, -1)  # idź krok bloków do tyłu
    sleep(2)

    drukujPoz()
    mc.camera.setNormal()  # ustawienie kamery normalnie

Warto zauważyć, jak pętla for i in range(krok) umożliwia symulowanie ruchu postaci. Wywołanie funkcji dodajemy do funkcji głównej. Kod testujemy uruchamiając skrypt lub w konsoli.

../../_images/ipython04.png

8.1.3.4. Po czym chodzę?

Teraz spróbujemy dowiedzieć się, po jakich blokach chodzimy. Definiujemy jeszcze jedną funkcję:

Kod nr
86
87
88
def jakiBlok():
    x, y, z = mc.player.getPos()
    return mc.getBlock(x, y - 1, z)

Dopisujemy jej wywołanie: print "Typ bloku: ", jakiBlok() – w funkcji głównej i testujemy.

../../_images/ipython05.png

8.1.4. Plac budowy

Skoro orientujemy się już w przestrzeni, możemy zacząć budować. Na początku wykorzystamy symulator. Rozpoczniemy od przygotowania placu budowy. Posłuży nam do tego odpowiednia funkcja, którą umieścimy w pliku mcsim.py:

Kod nr
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import local.minecraft as minecraft  # import modułu minecraft
import local.block as block  # import modułu block

os.environ["USERNAME"] = "Steve"  # nazwa użytkownika
os.environ["COMPUTERNAME"] = "mykomp"  # nazwa komputera

# utworzenie połaczenia z symulatorem
mc = minecraft.Minecraft.create("")


def plac(x, y, z, roz=10, gracz=False):
    """Funkcja wypełnia sześcienny obszar od podanej pozycji
    powietrzem i opcjonalnie umieszcza gracza w środku.
    Parametry: x, y, z - współrzędne pozycji początkowej,
    roz - rozmiar wypełnianej przestrzeni,
    gracz - czy umieścić gracza w środku
    Wymaga: globalnych obiektów mc i block.
    """

    kamien = block.STONE
    powietrze = block.AIR

    # kamienna podłoże
    mc.setBlocks(x, y - 1, z, x + roz, y - 1, z + roz, kamien)
    # czyszczenie
    mc.setBlocks(x, y, z, x + roz, y + roz, z + roz, powietrze)
    # umieść gracza w środku
    if gracz:
        mc.player.setPos(x + roz / 2, y + roz / 2, z + roz / 2)


def main(args):
    mc.postToChat("Cześć! Tak działa MC chat!")  # wysłanie komunikatu do mc
    plac(0, 0, 0, 18)
    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv))

Funkcja plac() korzysta z metody setBlocks(x0,y0,z0,x1,y1,z1,blockType, blockData), która wypełnia obszar w przedziałach [x0-x1], [y0-y1], [z0-z1] blokiem podanego typu o opcjonalnych właściwościach. Na początku tworzymy “podłogę” z kamienia, później wypełniamy sześcian o podanym rozmiarze powietrzem. W symulatorze nie jest to przydatne, ale bardzo przydaje się do “wyczyszczenia” miejsca w świecie Minecrafta. Opcjonalnie możemy umieścić gracza w środku utworzonego obszaru.

Kod testujemy uruchamiając skrypt mcsim.py:

~/mcpi-sim$ python mcsim.py

Warning

Skrypt mcsim.py musi znajdować się w katalogu mcpi-sim ze źródłami symulatora, który wykorzystuje specjalne wersje bibliotek minecraft i block z podkatalogu local.

Klawisze sterujące podglądem symulacji widoczne są w terminalu:

../../_images/mc01.png

8.1.5. Umieszczanie bloków

W pliku mcsim.py przed funkcją główną (main()) umieszczamy funkcję buduj():

Kod nr
37
38
39
40
41
42
def buduj():
    """
    Funkcja do testowania umieszczania bloków.
    Wymaga: globalnych obiektów mc i block.
    """
    mc.setBlock(0, 0, 18, block.CACTUS)

Używamy podstawowej metody setBlock(x, y, z, blockType), która w podanych koordynatach umieszcza określony blok. Wywołanie funkcji buduj() dodajemy do main() po funkcji plac() i testujemy. Ponad “podłogą” powinien znaleźć się zielony blok.

Do rysowania bloków można użyć pętli. Zmieniamy funkcję buduj() następująco:

Kod nr
37
38
39
40
41
42
43
44
45
46
47
48
49
50
def buduj():
    """
    Funkcja do testowania umieszczania bloków.
    Wymaga: globalnych obiektów mc i block.
    """
    for i in range(19):
        mc.setBlock(0 + i, 0, 0, block.WOOD)
        mc.setBlock(0 + i, 1, 0, block.LEAVES)
        mc.setBlock(0 + i, 0, 18, block.WOOD)
        mc.setBlock(0 + i, 1, 18, block.LEAVES)

    for i in range(19):
        mc.setBlock(9, 0, 18 - i, block.BRICK_BLOCK)
        mc.setBlock(9, 1, 18 - i, block.BRICK_BLOCK)

Teraz plac powinien wyglądać, jak poniżej:

../../_images/mcsim.png

Ćwiczenie 3

Odpowiednio modyfikując funkcję buduj() skonstruuj:

  • kwadrat 2D
  • prostokąt 2D
  • słup
  • bramę, czyli prostokąt 3D
  • sześcian

8.1.6. Przykłady

Zapisz skrypt mcsim.py pod nazwą mcpi-test.py i dostosuj go do uruchomienia na serwerze MC Pi. W tym celu zamień ciąg “local” w importach na “mcpi” oraz podaj adres IP serwera MC Pi w poleceniu tworzącym połączenie. Następnie umieść w pliku kody poniższych funkcji i po kolei je przetestuj dodając ich wywołania w funkcji głównej.

8.1.6.1. Zostawiam ślady

Kod nr
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def jakiBlok():
    while True:
        x, y, z = mc.player.getPos()
        blok_pod = mc.getBlock(x, y - 1, z)
        print(blok_pod)
        sleep(1)


def slad(blok=38):
    while True:
        x, y, z = mc.player.getPos()
        mc.setBlock(x, y, z, blok)
        sleep(0.1)


def slad_jezeli(pod=2, blok=38):
    while True:
        x, y, z = mc.player.getPos()
        blok_pod = mc.getBlock(x, y - 1, z)  # blok pod graczem

        if blok_pod == pod:
            mc.setBlock(x, y, z, blok)
        sleep(0.1)

8.1.6.2. Buduję pomnik

Kod nr
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def pomnik():
    """
    Funkcja ustawia blok lawy, nad nim blok wody, a później powietrza.
    """
    x, y, z = mc.player.getPos()

    lawa = 10
    woda = 8
    powietrze = 0

    mc.setBlock(x + 5, y + 3, z, lawa)
    sleep(10)
    mc.setBlock(x + 5, y + 5, z, woda)
    sleep(4)
    mc.setBlock(x + 5, y + 5, z, powietrze)

8.1.6.3. Piramida

Kod nr
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def kwadrat(bok, x, y, z):
    """
    Fukcja buduje kwadrat, którego środek to punkt x, y, z
    """
    pol = bok // 2
    piaskowiec = block.SANDSTONE
    mc.setBlocks(x - pol, y, z - pol, x + pol, y, z + pol, piaskowiec, 2)


def piramida(podstawa, x, y, z):
    """
    Buduje piramidę z piasku, której środek wypada w punkcie x, y, z
    """
    bok = podstawa
    wysokosc = y
    while bok >= 1:
        kwadrat(bok, x, wysokosc, z)
        bok -= 2
        wysokosc += 1

Źródła:


Licencja Creative Commons Materiały Python 101 udostępniane przez Centrum Edukacji Obywatelskiej na licencji Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.

Utworzony:2017-09-08 o 19:38 w Sphinx 1.4.5
Autorzy:Patrz plik “Autorzy”