--- a/project.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/project.clj Thu Aug 04 00:22:22 2011 -0400
@@ -1,4 +1,5 @@
(defproject clojurecraft "0.0.1-SNAPSHOT"
:description "TODO: add summary of your project"
:dependencies [[clojure "1.2.0"]
- [clojure-contrib "1.2.0"]])
+ [clojure-contrib "1.2.0"]]
+ :jvm-opts ["-Xmx1g"])
--- a/src/clojurecraft/actions.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/src/clojurecraft/actions.clj Thu Aug 04 00:22:22 2011 -0400
@@ -12,5 +12,5 @@
:z (+ z-change (:z location))
:stance (+ y-change (:stance location))})]
(alter player merge {:loc new-location}))))
- bot)
+ nil)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/clojurecraft/chunks.clj Thu Aug 04 00:22:22 2011 -0400
@@ -0,0 +1,54 @@
+(ns clojurecraft.chunks
+ (:use [clojurecraft.mappings])
+ (:use [clojurecraft.util])
+ (:require [clojurecraft.data])
+ (:import [clojurecraft.data Block]))
+
+(defn coords-of-chunk-containing [x z]
+ [(bit-shift-right x 4)
+ (bit-shift-right z 4)])
+
+(defn block-index-in-chunk [x y z]
+ [(bit-and x 15)
+ (bit-and y 127)
+ (bit-and z 15)])
+
+(defn block-from-chunk [x y z chunk]
+ (let [[ix iy iz] (block-index-in-chunk x y z)
+ i (+ y (* z 128) (* x 128 16))
+ block-type (get (:types chunk) i)
+ block-meta (get (:metadata chunk) i)
+ block-light (get (:light chunk) i)
+ block-sky-light (get (:sky-light chunk) i)]
+ (Block. [x y z]
+ (block-types (int block-type))
+ block-meta
+ block-light
+ block-sky-light)))
+
+(defn chunk-containing [x z chunks]
+ (chunks (coords-of-chunk-containing x z)))
+
+(defn -block [x y z chunks]
+ (block-from-chunk x y z (chunk-containing x z chunks)))
+
+(defn block [bot x y z]
+ (-block x y z (:chunks (:world bot))))
+
+(defn block-rel [bot x y z]
+ (block bot
+ (int (+ (:x (:loc @(:player bot))) x))
+ (int (+ (:y (:loc @(:player bot))) y))
+ (int (+ (:z (:loc @(:player bot))) z))))
+
+(defn block-standing [bot]
+ (block bot
+ (int (:x (:loc @(:player bot))))
+ (int (- (:y (:loc @(:player bot))) 0))
+ (int (:z (:loc @(:player bot))))))
+
+(defn current [bot]
+ (chunk-containing
+ (int (:x (:loc @(:player bot))))
+ (int (:z (:loc @(:player bot))))
+ @(:chunks (:world bot))))
--- a/src/clojurecraft/core.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/src/clojurecraft/core.clj Thu Aug 04 00:22:22 2011 -0400
@@ -4,6 +4,7 @@
(:use [clojurecraft.out])
(:use [clojurecraft.util])
(:use [clojure.contrib.pprint :only (pprint)])
+ (:require [clojurecraft.chunks :as chunks])
(:require [clojurecraft.actions :as act])
(:require (clojurecraft.data))
(:import [clojurecraft.data Location Entity Block Chunk World Bot])
@@ -51,12 +52,48 @@
(read-packet bot)))
(println "done"))
+
+; TODO: Investigate this. I'm not convinced.
+(def G -9.8) ; meters/second^2
+(def TICK 50/1000) ; seconds
+
+(defn apply-gravity [player]
+ (let [y (:y (:loc player))
+ stance (:stance (:loc player))
+ velocity (:velocity player)
+ new-y (+ y (* velocity TICK))
+ new-stance (+ stance (* velocity TICK))
+ new-velocity (max -4.0 (+ velocity (* G TICK)))]
+ [new-y ; TODO: More research on terminal velocity.
+ new-stance
+ new-velocity]))
+
+(defn should-apply-gravity? [bot]
+ (non-solid-blocks (l :type (chunks/block-standing bot))))
+
+(defn update-location [bot]
+ (when (chunks/current bot)
+ (dosync
+ (let [player (:player bot)]
+ (if (should-apply-gravity? bot)
+ (let [[new-y new-stance new-velocity] (apply-gravity @player)]
+ (alter player assoc :velocity new-velocity)
+ (alter player assoc-in [:loc :y] new-y)
+ (alter player assoc-in [:loc :stance] new-stance)
+ (alter player assoc-in [:loc :onground] false))
+ (do
+ (alter player assoc :velocity 0.0)
+ (alter player assoc-in [:loc :onground] true)))))))
+
(defn location-handler [bot]
(let [conn (:connection bot)
outqueue (:outqueue bot)]
(while (nil? (:exit @conn))
- (let [location (:loc @(:player bot))]
- (.put outqueue [:playerpositionlook location])
+ (let [player (:player bot)
+ location (:loc @player)]
+ (when (not (nil? location))
+ (.put outqueue [:playerpositionlook location])
+ (update-location bot))
(Thread/sleep 50)))))
(defn output-handler [bot]
@@ -83,7 +120,7 @@
; We need to log in to find out our bot's entity ID, so we delay creation of the
; player until then.
(let [player-id (:eid (login bot username))
- player (ref (Entity. player-id STARTING-LOC false))
+ player (ref (Entity. player-id nil false 0.0))
bot (assoc bot :player player)]
; Theoretically another connected bot could fill in the player's entity entry
--- a/src/clojurecraft/data.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/src/clojurecraft/data.clj Thu Aug 04 00:22:22 2011 -0400
@@ -27,7 +27,7 @@
; something has changed, since otherwise there would be no way to tell
; (despawning would simply remove the object from the entity list
; without modifying it).
-(defrecord Entity [eid loc despawned])
+(defrecord Entity [eid loc despawned velocity])
; Block
;
@@ -38,15 +38,21 @@
; A simple vector of three coordinates, NOT a Location (for performance).
;
; kind -> TODO
-(defrecord Block [loc kind])
+(defrecord Block [loc type meta light sky-light])
; Chunk
;
; A single chunk in the world.
;
-; blocks -> [block ...]
-; A vector of the blocks in this chunk.
-(defrecord Chunk [blocks])
+; You should never have to use these directly. clojurecraft.chunks contains helper
+; functions that should give you the block data you need.
+;
+; types -> [int ...]
+; metadata -> byte-array
+; light -> byte-array
+; sky-light -> byte-array
+;
+(defrecord Chunk [types metadata light sky-light])
; World
;
--- a/src/clojurecraft/in.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/src/clojurecraft/in.clj Thu Aug 04 00:22:22 2011 -0400
@@ -3,7 +3,7 @@
(:use [clojurecraft.mappings])
(:use [clojurecraft.chunks])
(:require [clojurecraft.data])
- (:import [clojurecraft.data Location Entity])
+ (:import [clojurecraft.data Location Entity Chunk])
(:import (java.util.zip Inflater)))
; Bytes ----------------------------------------------------------------------------
@@ -299,7 +299,7 @@
entities (:entities (:world bot))
entity (@entities eid)]
(when-not entity
- (alter entities assoc eid (Entity. eid nil false)))))
+ (alter entities assoc eid (Entity. eid nil false 0.0)))))
payload))
(defn- read-packet-entityrelativemove [bot conn]
@@ -376,8 +376,7 @@
(let [[block-metadata data] (-parse-nibbles len data)
[block-light data] (-parse-nibbles len data)
[sky-light data] (-parse-nibbles len data)]
- (map #({:blocktype %1 :blockmeta %2 :blocklight %3 :skylight %4})
- block-types block-metadata block-light sky-light))))
+ [block-types block-metadata block-light sky-light])))
(defn- -read-packet-mapchunk-chunkdata [conn predata]
(let [raw-data (-read-bytearray conn (:compressedsize predata))
@@ -400,8 +399,16 @@
:sizey (+ 1 (-read-byte conn))
:sizez (+ 1 (-read-byte conn))
:compressedsize (-read-int conn))]
- (let [decompressed-data (-read-packet-mapchunk-chunkdata conn predata)]
- (assoc predata :data (-read-packet-mapchunk-decode predata decompressed-data)))))
+ (let [decompressed-data (-read-packet-mapchunk-chunkdata conn predata)
+ decoded-data (-read-packet-mapchunk-decode predata decompressed-data)]
+ (when (and (= (:sizex predata) 16) ; TODO: Handle partial chunks at some point.
+ (= (:sizey predata) 128)
+ (= (:sizez predata) 16))
+ (let [[types meta light sky] decoded-data
+ chunk (Chunk. types meta light sky)
+ chunk-coords (coords-of-chunk-containing (:x predata) (:z predata))]
+ (dosync (alter (:chunks (:world bot)) assoc chunk-coords chunk))))
+ (assoc predata :data decompressed-data))))
(defn- read-packet-multiblockchange [bot conn]
--- a/src/clojurecraft/mappings.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/src/clojurecraft/mappings.clj Thu Aug 04 00:22:22 2011 -0400
@@ -67,7 +67,7 @@
-1 nil
0x00 :air
0x01 :stone
- 0x02 :grass
+ 0x02 :dirt-grassy
0x03 :dirt
0x04 :cobblestone
0x05 :planks
@@ -162,6 +162,7 @@
0x60 :hatch
})
(def block-ids (invert block-types))
+(def non-solid-blocks #{ :air :sign-wall })
(def item-types {
-1 nil
--- a/src/clojurecraft/util.clj Wed Aug 03 21:11:51 2011 -0400
+++ b/src/clojurecraft/util.clj Thu Aug 04 00:22:22 2011 -0400
@@ -5,5 +5,11 @@
(println result#)
result#))
+(defmacro lc [& body]
+ `(let [result# (~@body)]
+ (println result#)
+ (println (class result#))
+ result#))
+
(defn invert [m]
(apply assoc {} (mapcat reverse m)))