diff --git a/README.md b/README.md index 9820a1f..7814c8e 100644 --- a/README.md +++ b/README.md @@ -90,5 +90,5 @@ getTile() # return a tuple of integers (x, y, z), for the tile on which the pla setTile(pos::Tuple{Real, Real, Real}) # move the player to the tile specified by the integer coordinates getPos() # return a tuple of floats (x, y, z) with the player's position setPos(pos::Tuple{Real, Real, Real}) # move the player to the specified coordinates - +pollBlockHits() #Return an Array of hit events. ((x,y,z), faceId, entityId) ``` diff --git a/example/safeFeet.jl b/example/safeFeet.jl index b8452aa..6f915ec 100644 --- a/example/safeFeet.jl +++ b/example/safeFeet.jl @@ -1,10 +1,20 @@ +# Walk over water and air by replacing it with Dimaond Blocks +# Usage: +# t = now() +# while (now() - t).value/1000 < time_period +# safeFeet() +# end + +using PiCraft function safeFeet() - x,y,z = player.getTile() - b = world.getBlock(x,y-1, z) - if b == PiCraft.AIR || b == PiCraft.WATER_STATIONARY || b == PiCraft.WATER_FLOWING - world.setBlock(x, y-1, z, PiCraft.DIAMOND_BLOCK, 1) - end + b = getTile() .+ (0, -1, 0) #Get the Block coordinates on which the player is standing + if getBlock(b) ∈ [PiCraft.AIR, PiCraft.WATER_STATIONARY, PiCraft.WATER_FLOWING, PiCraft.LAVA, PiCraft.LAVA_STATIONARY] #Check if the block is + setBlock(b, PiCraft.DIAMOND_BLOCK) + end + sleep(0.05) #Pause as to not spam the API, results in a smoother experience end - - + +# Challenge: Use a queue to remove blocks such that the maximum bridge length is 10. +# Your script should automatically remove blocks which had too far behind. +# Enter "\py bridge" for a demonstration diff --git a/example/skyscraperBasic.jl b/example/skyscraperBasic.jl new file mode 100644 index 0000000..0f15068 --- /dev/null +++ b/example/skyscraperBasic.jl @@ -0,0 +1,90 @@ +# Construct a skyscraper + +using PiCraft + +# Let's first define a few basic parameters for our building +p = getPos() .+ (0, -1, 0) +floors = 5 +#length will go in the +ve x direction and width in the +ve z direction +length = 10 +width = 15 +height = 6 + +# We're first going to write code to construct a single floor relative to a point +# Then we will use a loop to create a skyscraper +# pseudocode: +# x = start_position +# for i in 1:floors +# buildFloor(x) +# increase x's height by floor's height +# end +# Build a ceiling for the top floor +# +# Now to build a floor +# 1) Make all the walls out of glass panes +# 2) Set the bottom level as floor +# 3) Get Pillars on the corners + +function buildFloor(p) + # Set all walls to glass panes + setBlocks(p .+ (1, 0, 1), p .+ (1, height, width), PiCraft.GLASS_PANE) + setBlocks(p .+ (1, 0, 1), p .+ (length, height, 1), PiCraft.GLASS_PANE) + setBlocks(p .+ (1, height, width), p .+(length, 0, width), PiCraft.GLASS_PANE) + setBlocks(p .+ (length, height, width), p .+ (length, 0, 1), PiCraft.GLASS_PANE) + + #Set entire floor to Stone Brick + setBlocks(p .+ (1, 0, 1), p .+ (length, 0, width), PiCraft.STONE_BRICK) + + #Set 4 Pillars to the corners + setBlocks(p .+ (1, 0, 1), p .+ (1, height, 1), PiCraft.STONE_BRICK) + setBlocks(p .+ (1, 0, width), p .+ (1, height, width), PiCraft.STONE_BRICK) + setBlocks(p .+ (length, 0, 1), p .+ (length, height, 1), PiCraft.STONE_BRICK) + setBlocks(p .+ (length, 0 , width), p .+ (length, height, width), PiCraft.STONE_BRICK) +end + +function makeSkyscraper() + for i in 1:floors + buildFloor(p .+ (0, height*i - height, 0)) + end + setBlocks(p .+ (1, height*floors, 1), p .+ (length, height*floors, width), PiCraft.IRON_BLOCK) # Set Roof to Iron Block +end + +# This building isn't particularly nice and has too much glass. Let's have another go. +# When we use programming to solve a problem there can be multiple solutions to the same +# problem. + +# This time let's make the building first and then add windows later + +function makeSkyscraper2() + # Make a filled cuboid of Blocks filling the entire building space + setBlocks(p .+ (1, 0, 1), p .+ (length, height*floors + 1, width),Block(251, 0)) + + # Hollow out the inside of the building + setBlocks(p .+ (2, 1, 2), p .+ (length - 1, height*floors, width - 1), PiCraft.AIR) + + # Add wooden flooring + for i in 0:floors + setBlocks(p .+ (2, height*i, 2), p .+ (length - 1, height*i, width - 1), PiCraft.WOOD_PLANKS) + end + # Add window Panes, careful if you change the given building dimensions, the change in coordinates may result + # in unintended consequences. + for i in 0:(floors - 1) + setBlocks(p .+ (1, height*i + 2, floor.((width + 1)/2 - 2)), + p .+ (1, height*i + 4, floor.((width + 1)/2 + 2)), PiCraft.GLASS_PANE) + setBlocks(p .+ (1, height*i + 2, floor.((width + 1)/2 - 2)), + p .+ (1, height*i + 4, floor.((width + 1)/2 + 2)), PiCraft.GLASS_PANE) + end +end + +# In our second iteration we made the building better, the code is easier to +# follow through and is less in comparison. +# Now, experiment around writing your own code architecturing your own designs. +# Check out the challenges listed below +# Challenges : +# 1) Make the building well lit with torches +# 2) Add a balcony to each floor. +# 3) A common ladder access for all floors. +# 4) Add randomness to your design +# Hint: for all blocks in building +# if block is cobblestone and rand() < 0.1 +# set block to Mossy Cobblestone diff --git a/example/turnToGold.jl b/example/turnToGold.jl new file mode 100644 index 0000000..047b03e --- /dev/null +++ b/example/turnToGold.jl @@ -0,0 +1,22 @@ +# Turn blocks to gold by hitting them +# Demonstration of pollBlockHits() +# the function pollBlockHits() returns an Array of hit Events +# A hit event is a tuple, say ((5, 4, 5), 2, 17) +# (5, 4, 5) are the coordinates to the block which was hit +# 2 is the face of the block which was hit +# 17 is the entityId of the Entity which was responsible for the hit + +using PiCraft + +clearEvents() # Clear all previous events +t = now() # Mark the current time + +post("60 seconds to turn blocks to gold.") + +while (now() - t).value/1000 < 60.0 # Continue the loop if 60 seconds has not elapsed + for hit in pollBlockHits() + setBlock(hit[1], Block(41)) # hit[1] are the coordinates to the Block which was hit + end +end + +post("Time Over!") diff --git a/src/PiCraft.jl b/src/PiCraft.jl index ee57e5b..d946450 100644 --- a/src/PiCraft.jl +++ b/src/PiCraft.jl @@ -62,8 +62,10 @@ function setBlock(pos::Tuple{Real, Real, Real}, block::Block) end "Set an entire region to the specified block type" -function setBlocks(pos::Tuple{UnitRange{Int}, UnitRange{Int}, UnitRange{Int}}, block::Block) - PiCraft.mc_send("world.setBlocks($(pos[1][1]),$(pos[2][1]),$(pos[3][1]),$(pos[1][end]),$(pos[2][end]),$(pos[3][end]),$(block.id),$(block.data))", false) +function setBlocks(p1::Tuple{Real, Real, Real}, p2::Tuple{Real, Real, Real}, block::Block) + p1 = round.(Int, p1) + p2 = round.(Int, p2) + PiCraft.mc_send("world.setBlocks($(p1[1]),$(p1[2]),$(p1[3]),$(p2[1]),$(p2[2]),$(p2[3]),$(block.id),$(block.data))", false) end "Get the height of the world at the specified `x` and `z` coordinates." @@ -133,7 +135,7 @@ end pollBlockHits() Returns an array of all the events which have occurred since the last time the function was called. -Each event is described with a tuple `(x, y, z, face, entityId)`. `x`, `y` and `z` are the coordinates of the block. +Each event is described with a tuple `((x, y, z), face, entityId)`. `x`, `y` and `z` are the coordinates of the block. `face` is the block's face number which was hit and `entityId` identifies the player who hit the block using a sword. """ @@ -141,12 +143,12 @@ function pollBlockHits() rawEvents = [] for s in PiCraft.mc_send("events.block.hits()", true) for j in split(s, "|") - push!(rawEvents, parse(Int,j)) + length(j) > 0 && push!(rawEvents, parse(Int,j)) end end Events = [] for i in 0:(Int(length(rawEvents)/5) - 1) - push!(Events, (rawEvents[1 + 5*i], rawEvents[2 + 5*i], rawEvents[3 + 5*i], rawEvents[4 + 5*i], rawEvents[5 + 5*i])) + push!(Events, ( (rawEvents[1 + 5*i], rawEvents[2 + 5*i], rawEvents[3 + 5*i]) , rawEvents[4 + 5*i], rawEvents[5 + 5*i])) end return Events end