# HG changeset patch # User Steve Losh # Date 1312431742 14400 # Node ID c41de2845803065ec9f400799ebb33fd731c96c2 # Parent 085e63240d4f8907b986dbabb375beee2a76856b Start working on chunks and gravity. diff -r 085e63240d4f -r c41de2845803 project.clj --- 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"]) diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/actions.clj --- 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) diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/chunks.clj --- /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)))) diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/core.clj --- 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 diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/data.clj --- 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 ; diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/in.clj --- 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] diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/mappings.clj --- 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 diff -r 085e63240d4f -r c41de2845803 src/clojurecraft/util.clj --- 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)))