minecraft mod programming part iii of minecraft: pi edition october 31, 2015
Post on 14-Dec-2015
228 Views
Preview:
TRANSCRIPT
Outlines• Programming Python on the Pi• Installing the Minecraft Pi Edition• A “Hello, Minecraft!” demo• 2D list (or array), how to use it?• Using Minecraft modules• Coding and testing a 2D board game• Putting the board game into Minecraft
Programming Python on the Pi• What are available on the Pi?
• Raspbian is a Debian-based free operating system optimized for the Raspberry Pi hardware (while Debian GNU/Linux is one of the most popular Linux distributions for personal computers and network servers.)
• Midori is a lightweight WebKit browser with support for HTML5 and JavaScript
• Scratch programming environment
• Python is installed on the Raspberry Pi • Python 2 & 3• Shell & IDLE
4
Setting up Minecraft on Raspberry Pi• Open a web browser on Raspberry Pi• Visit http://pi.minecraft.net• Go to the Download page• Download the latest version of the game• Save the file in the /home/pi directory• Open a fresh terminal and enter the
following command:• tar –zxvf minecraft-pi-<version>.tar.gz• Change directory with cd mcpi• ./minecraft-pi
• a new window should pop up with Minecraft: Pi Edition running inside
Client-Server Setting: how it works?
• Start Minecraft server (app)• Clients are connected to the
server (app) through socket (a fundamental networking mechanism)
Client app (in Python)
Minecraft Server app
Socket connection
command
Let’s start the game• To start Minecraft server (app),
type the following in a console:
• For a client to get connected to the server (app) and chat with other gamers, simply type the following in a fresh console:
cd /home/pi/mcpi./minecraft-pi
cd /home/pi/mcpi/api/python/mcpipython>>>import minecraft>>>mc = minecraft.Minecraft.create()>>>mc.postToChat("Hello, world!")
command
Minecraft Programming Interface• Codenamed mcpi, this API (app. prog. interface) define
the ways any mod program should interact with the server• Minecraft Pi Edition server implementation provides a minecraft module (relate topics in Parts I & II)
• An object (mc) in the Minecraft type can be used to• mc.getBlock(x,y,z): query the type
of a block at position (x,y,z)• mc.postToChat(msg): post a message
to the game chatmc.camera.setPos(x,y,z): move thecamera to a particular position
• mc.events.pollBlockHits(): get allblocks got hit since last poll x
y
z
The block module & the Block class
• The block module defines a list of all available blocks• You may use a number or a name to refer
to the type of blocks that you want to use• Simply 3, or• Use block.DIRT• Details (the first few shown to the right) are
at http://minecraft.gamepedia.com/Data_values_%28Pocket_Edition%29
• To add a block to a certain position (x,y,z)
• where 14 represents the color redmc.setBlock(x,y,z,block.WOOL,14)
Our first Minecraft mod project …• Here is our plan:
We are going to • Create a board game mod … • With Reversi game rules, and try to …• Bring it into Minecraft
• Let’s first do some (OO) design (relate topics in Part II)
Board Reversi
ReversiMCInvalideMoveException
our_mod
Block Minecraft
Vec3
minecraft
time
Detailed design for the Board class• We will first see what the Board class needs to do, as
well as the InvalidMoveException class
Board
NO_PLAYER = 0_cols_rows_board
__init__(cols,rows)get(x,y)set(x,y,player)display()
InvalidMoveException
Exception
class InvalidMoveException(Exception): pass
Now it’s time for coding!
class Board: NO_PLAYER = 0
def __init__(self, cols, rows): self._board = [] self._cols = cols self._rows = rows for i in range(rows): self._board.append(cols*[Board.NO_PLAYER])
def set(self, x, y, player): if 0 <= x < self._cols and 0 <= y < self._rows: self._board[int(y)][int(x)] = player else: raise InvalidMoveException("Outside play area")
def get(self, x, y): if 0 <= x < self._cols and 0 <= y < self._rows: return self._board[int(y)][int(x)] else: return Board.NO_PLAYER
def display(self): print("\n".join( [" ".join([str(piece) for piece in row]) for row in self._board]))
Detailed design for the Reversi class
• We will then see what the Reversi class needs to do• Define all 8 directions• Use a Board object to keep track of
game status• Keep track players
• 1 – this player• 2 – opponent
• 0 – no player: defined in Board class
• Get move from the console• Validate a move (by checking if there is
any pieces to flip)• Make the move and flip pieces• Output a message• Start the game
Reversi
DIRECTIONS = […]_board_player_opponent_score
__init__(x,y,player)getMove()validMove(x,y,player)piecesToFlip(x,y, player,direction)makeMove(x,y,player)set(x,y,player)output(message)display()play()
Getting the next move …• From the console, a player should type
the (0-based) column and row indices• For instance, if White is the next player, a
possible move is 6 6
def getMove(self): self.output("Player {0}'s move:".format(self.nextPlayer())) data = raw_input() coords = [int(coords) for coords in data.split()] coords.append(self.nextPlayer()) return coords
Get input from the console Split the two #’s
by the space
Wrap the #’s as a list (or array)Return the list
as [6, 6, 1]Append the list with player Id
Wrap the #’s as a list (or array)
Checking pieces to flip … • Try out 1 of the 8 directions in DIRECTIONS
def piecesToFlip(self,x,y,player,direction): currx = x+direction[0] curry = y+direction[1] curr = self._board.get(currx,curry) print("player = " + str(curr)) pieces = [] while curr != player and curr!= Board.NO_PLAYER: pieces.append((currx,curry)) currx = currx + direction[0] curry = curry + direction[1] curr = self._board.get(currx,curry) print("curr => " + str(curr)) if curr == player: return pieces else: return []
1
2
3
Keep trying until the end of the streak
Add a new pair of (x,y) when found
Return the list of pieces to be flipped
Return an empty list
Making a valid move… • Add and flip pieces, and display resultsdef makeMove(self,x,y,player):
# Check move validity if not self.validMove(x,y,player): raise InvalidMoveException("Invalid move (" + str(x) + "," + str(y) + ")") # Place the piece self.set(x,y,player) self._score[player - 1] += 1 # Flip any appropriate pieces for direction in Reversi.DIRECTIONS: flip = self.piecesToFlip(x,y,player,direction) for x2,y2, in flip: self.set(x2,y2,player) self._score[player-1] += 1 self._score[self._opponent-1] -= 1 self._player, self._opponent = self._opponent, self._player print("Player is: " + str(self._player)) print("Opponent is: " + str(self._opponent))
Raise an exception for an invalid move
Increase its score by 1
Add a new piece for the current player
Adjust pieces and scores for both players
Iterate for all 8 directions
Flip pieces in that direction
Swap player and opponent
Report results
Detailed design for the ReversiMC class
• Lastly, here is what the ReversiMC class needs to do• Inherit features defined in the Reversi class• Define the blocks used for the board
itself: GOLD_BLOCK• Keep track players: blocks and names
• 1 – “White”, white block• 2 – “Black”, black block • 0 – “None”, transparent block (AIR)
• Need the z coord for positioning• Get move from the Minecraft game• Output a message• Display the results through Minecraft
chat
__init__(x,y,player)__init__(x,y,z,cols=8, rows=8) getMove(x,y,z,player)output(message)display()
ReversiMC
BOARD_MATERIAL = GOLD_BLOCKplayers=[AIR, Block(35,
0), Block(35, 15)] playerNames = ["None", "White", "Black"]
Reversi
Initialize the class …
class ReversiMC(Reversi): BOARD_MATERIAL = GOLD_BLOCK players = [AIR, Block(35, 0), Block(35, 15)] playerNames = ["None", "White", "Black"] def __init__(self,x,y,z,cols=8,rows=8): self._pos = Vec3(x,y,z) self._farcorner = Vec3(x+cols,y,z+rows) self._minecraft = Minecraft.create() self._minecraft.setBlocks(x,y-1,z,x+cols-1,y-1,z+rows-1, ReversiMC.BOARD_MATERIAL) self._minecraft.setBlocks(x,y,z,x+cols-1,y,z+rows-1, ReversiMC.players[0]) super(ReversiMC,self).__init__(cols,rows)
Extend the base class
Define global variables
Use 3D library
Choose blocks for players
Connect to Minecraft
Link to super class initialization
Getting move from Minecraft game
def getMove(self): self.output("{0}'s move". format(ReversiMC.playerNames[self.nextPlayer()])) while True: # Note: only handle right-click events for now events = self._minecraft.events.pollBlockHits() for event in events: x,y,z = event.pos.x, event.pos.y, event.pos.z if self._pos.x <= x < self._farcorner.x and self._pos.z <= z < self._farcorner.z: return (x-self._pos.x, z-self._pos.z, self.nextPlayer()) time.sleep(0.1)
Announce next player
Minecraft gamer input
Return as a list
Validate move by checking space range
Detect hit location
Pause once for each game iteration
Game loop until
ended
top related