-
Notifications
You must be signed in to change notification settings - Fork 35
World generation
(:require [cljminecraft.blocks :as bl])
Source: blocks.clj
Bukkit Docs: http://wiki.bukkit.org/Plugin_Tutorial#Block_Manipulation
The world generation API of cljminecraft tries to make defining structures, landscapes and world manipulation more declarative and takes a similar approach to that of something reminiscent of Logo:
;; Draw a hollow box from the first online player's location
(def ctx (setup-context (first (.getOnlinePlayers (bk/server)))))
(run-actions
ctx
(extrude :up 5
(forward 8) (right 8) (back 8) (left 8)))
First, you need to setup a context to provide run-actions with a starting point and state - see the setup-context
function as an example of such a context. This is a helper function to setup a context from a given player's name.
Then, you simply use run-actions
, providing the context and an arbitrary list of actions. The actions can themselves be composed of sub-lists of actions to make composing actions straightforward, eg:
(defn box []
[(forward 8) (right 8) (back 8) (left 8)])
(run-actions ctx (extend :up 5 (box)))
To generate structures especially from a different thread from the main UI thread, I recommend using bk/ui-sync
, see [Bukkit Utilities](Bukkit Utilities)
(bk/ui-sync plugin #(run-actions ctx ...))
Possible actions include forward
, back
, left
, right
, up
, down
. Each supports a distance to move.
When turning, you are adjusting the relative direction of further actions so that:
(run-actions ctx (forward 8) (turn-left) (forward 8))
has almost the same effect as just (forward 8) (left 8)
. This lets you define structures purely in relative space which means that rotating it involves a simple turn-left
, turn-right
or turn-around
before executing it.
There are pen-up
, pen-down
and pen-toggle
commands that let you move without painting any blocks along the way.
There is also a material
function that lets you set the current material your pen should be painting :
(run-actions ctx (material :stone) (forward 2) (material [:wood :jungle]) (up 2))
A mark is a little bit like a clipboard - it can store stuff like the current location, relative angle and copied blocks.
Use mark
to create a mark, jump
to put the pointer back to that mark..
You can use the function gen-mark
to create yourself a unique marker name to refer to in your functions. This is recommended so that you don't clash within a context:
(let [m (gen-mark)]
(run-actions ctx (mark m) (forward 10) (left 8) (jump m)))
There are other functions that work with marks, like copy
, cut
, paste
, copy-to-mark
, cut-to-mark
, clear-mark
, line-to-mark
- play around with them and get a feel for how they work
extrude
lets you quickly repeat a set of actions in a given direction a certain number of times. See the example near the top
If you want to run a set of actions, but not affect your current point - simply call fork
with those actions.
(run-actions ctx
(fork (forward 8))
(fork (left 10) (up 5))
(fork (down 5) (left 3)))