d8fa70c91585

Delay and force chunks.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Thu, 18 Aug 2011 23:15:13 -0400
parents b1007d01decd
children 98dc76fd1032
branches/tags (none)
files src/clojurecraft/chunks.clj src/clojurecraft/core.clj src/clojurecraft/in.clj src/clojurecraft/physics.clj src/clojurecraft/util.clj

Changes

--- a/src/clojurecraft/chunks.clj	Tue Aug 16 20:22:42 2011 -0400
+++ b/src/clojurecraft/chunks.clj	Thu Aug 18 23:15:13 2011 -0400
@@ -4,6 +4,14 @@
   (:require [clojurecraft.data])
   (:import [clojurecraft.data Block]))
 
+(defn- get-chunk
+  "Get a chunk, making sure it has been forced."
+  [chunks coords]
+  (let [possible-chunk (@chunks coords)]
+    (when possible-chunk
+      (force @possible-chunk)
+      possible-chunk)))
+
 (defn coords-of-chunk-containing [x z]
   [(bit-shift-right x 4)
    (bit-shift-right z 4)])
@@ -18,10 +26,10 @@
 
 (defn block-from-chunk [x y z chunk]
   (let [i (block-index-in-chunk x y z)
-        block-type (aget (:types @chunk) i)
-        block-meta (aget (:metadata @chunk) i)
-        block-light (aget (:light @chunk) i)
-        block-sky-light (aget (:sky-light @chunk) i)]
+        block-type (aget ^bytes (:types (force @chunk)) i)
+        block-meta (aget ^bytes (:metadata (force @chunk)) i)
+        block-light (aget ^bytes (:light (force @chunk)) i)
+        block-sky-light (aget ^bytes (:sky-light (force @chunk)) i)]
     (Block. [x y z]
             (block-types (int block-type))
             block-meta
@@ -29,7 +37,7 @@
             block-sky-light)))
 
 (defn chunk-containing [x z chunks]
-  (@chunks (coords-of-chunk-containing x z)))
+  (get-chunk chunks (coords-of-chunk-containing x z)))
 
 (defn- -block [x y z chunks]
   (block-from-chunk x y z (chunk-containing x z chunks)))
--- a/src/clojurecraft/core.clj	Tue Aug 16 20:22:42 2011 -0400
+++ b/src/clojurecraft/core.clj	Thu Aug 18 23:15:13 2011 -0400
@@ -52,7 +52,8 @@
     (loop [prevs [nil nil nil]]
       (when (nil? (:exit @conn))
         (recur (read-packet bot (get prevs 0) (get prevs 1) (get prevs 2))))))
-  (println "done - input handler"))
+  (println "done - input handler")
+  (println "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"))
 
 
 (defn update-location [bot]
@@ -78,7 +79,8 @@
           (.put outqueue [:playerpositionlook location])
           (update-location bot))
         (Thread/sleep 50))))
-  (println "done - location handler"))
+  (println "done - location handler")
+  (println "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"))
 
 (defn output-handler [bot]
   (let [conn (:connection bot)
@@ -88,7 +90,8 @@
         (when packet
           (let [[packet-type, payload] packet]
             (write-packet bot packet-type payload))))))
-  (println "done - output handler"))
+  (println "done - output handler")
+  (println "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"))
 
 (defn action-handler [bot]
   (let [conn (:connection bot)
@@ -97,7 +100,8 @@
       (let [action (.poll actionqueue 1 TimeUnit/SECONDS)]
         (when action
           (force action)))))
-  (println "done - action handler"))
+  (println "done - action handler")
+  (println "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"))
 
 
 (defn connect [server username]
--- a/src/clojurecraft/in.clj	Tue Aug 16 20:22:42 2011 -0400
+++ b/src/clojurecraft/in.clj	Thu Aug 18 23:15:13 2011 -0400
@@ -8,6 +8,9 @@
   (:import [clojurecraft.data Location Entity Chunk])
   (:import (java.util.zip Inflater)))
 
+(def FULL-CHUNK (* 16 16 128))
+(def BLANK-CHUNK-ARRAY (byte-array FULL-CHUNK))
+
 ; Reading Data ---------------------------------------------------------------------
 (defn- -read-byte-bare [conn]
   (io!
@@ -367,31 +370,6 @@
                (conj nibbles bottom-byte top-byte)
                (subvec data 1))))))
 
-(defn- -read-packet-mapchunk-decode [predata data-ba]
-  (let [len (* (:sizex predata) (:sizey predata) (:sizez predata))
-        data (into (vector-of :byte) data-ba) ; Make the data a vector for easier parsing.
-        block-types (byte-array (subvec data 0 len))
-        data (subvec data len)]
-    (let [[block-metadata data] (-parse-nibbles len data)
-          [block-light data] (-parse-nibbles len data)
-          [sky-light data] (-parse-nibbles len data)]
-      [block-types block-metadata block-light sky-light])))
-
-(defn- -read-packet-mapchunk-chunkdata [conn predata]
-  (let [raw-data (-read-bytearray-bare conn (:compressedsize predata))
-        buffer (byte-array (/ (* 5
-                                 (:sizex predata)
-                                 (:sizey predata)
-                                 (:sizez predata)) 2))
-        decompressor (Inflater.)]
-    (.setInput decompressor raw-data 0 (:compressedsize predata))
-    (.inflate decompressor buffer)
-    (.end decompressor)
-    buffer))
-
-
-(def FULL-CHUNK (* 16 16 128))
-(def BLANK-CHUNK-ARRAY (byte-array FULL-CHUNK))
 (defn- -get-or-make-chunk [chunks coords]
   (or (@chunks coords)
       (let [chunk (ref (Chunk. BLANK-CHUNK-ARRAY
@@ -401,47 +379,82 @@
         (alter chunks assoc coords chunk)
         chunk)))
 
-(defn- -update-world-with-data [{{chunks :chunks} :world} x y z ^bytes types meta light sky]
-  (dosync (let [chunk-coords (coords-of-chunk-containing x z)
-                chunk (-get-or-make-chunk chunks chunk-coords)
-                start-index (block-index-in-chunk x y z)]
-            (if (= (alength types) FULL-CHUNK)
-              (alter chunk assoc ; Short-circuit for speed if we have a full chunk.
-                     :types types
-                     :metadata meta
-                     :light light
-                     :skylight sky)
-              (alter chunk assoc ; Otherwise: sadness.
-                     :types (replace-array-slice (:types @chunk) start-index types)
-                     :metadata (replace-array-slice (:metadata @chunk) start-index meta)
-                     :light (replace-array-slice (:light @chunk) start-index light)
-                     :skylight (replace-array-slice (:sky-light @chunk) start-index sky))))))
+(defn- -decode-mapchunk [postdata data-ba]
+  (let [len (* (:sizex postdata) (:sizey postdata) (:sizez postdata))
+        data (into (vector-of :byte) data-ba) ; Make the data a vector for easier parsing.
+        block-types (byte-array (subvec data 0 len))
+        data (subvec data len)]
+    (let [[block-metadata data] (-parse-nibbles len data)
+          [block-light data] (-parse-nibbles len data)
+          [sky-light data] (-parse-nibbles len data)]
+      [block-types block-metadata block-light sky-light])))
+
+(defn- -decompress-mapchunk [postdata]
+  (let [buffer (byte-array (/ (* 5
+                                 (:sizex postdata)
+                                 (:sizey postdata)
+                                 (:sizez postdata)) 2))
+        decompressor (Inflater.)]
+    (.setInput decompressor (:raw-data postdata) 0 (:compressedsize postdata))
+    (.inflate decompressor buffer)
+    (.end decompressor)
+    buffer))
+
+(defn- -read-mapchunk-predata [conn]
+  (assoc {}
+         :x (-read-int conn)
+         :y (-read-short conn)
+         :z (-read-int conn)
+         :sizex (+ 1 (-read-byte conn))
+         :sizey (+ 1 (-read-byte conn))
+         :sizez (+ 1 (-read-byte conn))
+         :compressedsize (-read-int conn)))
+
+
+(defn- -chunk-from-full-data [postdata]
+  (let [decompressed-data (-decompress-mapchunk postdata)
+        [types meta light sky] (-decode-mapchunk postdata decompressed-data)] ; Note: These are all byte-array's!
+    (Chunk. types meta light sky)))
+
+(defn- -chunk-from-partial-data [{{chunks :chunks} :world} postdata]
+  (let [x (:x postdata)
+        y (:y postdata)
+        z (:z postdata)
+        decompressed-data (-decompress-mapchunk postdata)
+        [types meta light sky] (-decode-mapchunk postdata decompressed-data)  ; Note: These are all byte-array's!
+        chunk-coords (coords-of-chunk-containing x z)
+        chunk (force (-get-or-make-chunk chunks chunk-coords))
+        start-index (block-index-in-chunk x y z)]
+    (Chunk. (replace-array-slice (:types (force @chunk)) start-index types)
+            (replace-array-slice (:metadata (force @chunk)) start-index meta)
+            (replace-array-slice (:light (force @chunk)) start-index light)
+            (replace-array-slice (:sky-light (force @chunk)) start-index sky))))
 
 (defn- read-packet-mapchunk [bot conn]
-  (time (let [predata (assoc {}
-                       :x (-read-int conn)
-                       :y (-read-short conn)
-                       :z (-read-int conn)
-                       :sizex (+ 1 (-read-byte conn))
-                       :sizey (+ 1 (-read-byte conn))
-                       :sizez (+ 1 (-read-byte conn))
-                       :compressedsize (-read-int conn))]
-    (let [decompressed-data (-read-packet-mapchunk-chunkdata conn predata)
-          decoded-data (-read-packet-mapchunk-decode predata decompressed-data)
-          [types meta light sky] decoded-data] ; Note: These are all byte-array's!
-      (-update-world-with-data bot
-                               (:x predata) (:y predata) (:z predata)
-                               types meta light sky)
-      (assoc predata :data decompressed-data)))))
+  (time (let [predata (-read-mapchunk-predata conn)
+              postdata (assoc predata :raw-data (-read-bytearray-bare conn (:compressedsize predata)))
+              chunk-size (* (:sizex postdata) (:sizey postdata) (:sizez postdata))
+              is-full-chunk (= FULL-CHUNK chunk-size)
+              chunk-coords (coords-of-chunk-containing (:x postdata) (:z postdata))]
+          (dosync (alter (:chunks (:world bot))
+                         assoc chunk-coords (if is-full-chunk
+                                              (ref (delay (-chunk-from-full-data postdata)))
+                                              (ref (-chunk-from-partial-data bot postdata))))))))
+
 
 
+(defn update-delayed [chunk index type meta]
+  (let [chunk (force chunk)]
+    (assoc chunk
+           :types (replace-array-index (:types chunk) index type)
+           :metadata (replace-array-index (:metadata chunk) index meta))))
+
 (defn -update-single-block [bot x y z type meta]
-  (dosync (let [chunk (chunk-containing x z (:chunks (:world bot)))
-                i (block-index-in-chunk x y z)]
-            (when chunk
-              (alter chunk assoc
-                     :types (replace-array-index (:types @chunk) i type)
-                     :metadata (replace-array-index (:metadata @chunk) i meta))))))
+  (dosync
+    (let [chunk (chunk-containing x z (:chunks (:world bot)))
+          i (block-index-in-chunk x y z)]
+      (when chunk
+        (alter chunk update-delayed i type meta)))))
 
 (defn- read-packet-blockchange [bot conn]
   (let [data (assoc {}
--- a/src/clojurecraft/physics.clj	Tue Aug 16 20:22:42 2011 -0400
+++ b/src/clojurecraft/physics.clj	Thu Aug 18 23:15:13 2011 -0400
@@ -17,7 +17,7 @@
 
 
 (defn player-bounds [{x :x y :y z :z}]
-  [(map floorint [(- x CHAR-RADIUS) y (- z CHAR-RADIUS)]) 
+  [(map floorint [(- x CHAR-RADIUS) y (- z CHAR-RADIUS)])
    (map floorint [(+ x CHAR-RADIUS) (+ y CHAR-HEIGHT-TOP) (+ z CHAR-RADIUS)])])
 
 
@@ -32,14 +32,15 @@
     (max velocity (* -1 MAX-HORIZONTAL-VELOCITY))))
 
 
+(def is-solid (comp not non-solid-blocks :type))
+(defn coords-are-solid [bot [x y z]]
+  (is-solid (chunks/block bot x y z)))
+
 (defn collision [bot [min-x min-y min-z] [max-x max-y max-z]]
   (let [block-coords (cartesian-product (range min-x (+ 1 max-x))
                                         (range min-y (+ 1 max-y))
-                                        (range min-z (+ 1 max-z)))
-        is-solid (comp not non-solid-blocks :type)
-        coords-are-solid (fn [[x y z]]
-                           (is-solid (chunks/block bot x y z)))]
-    (any? (map coords-are-solid block-coords))))
+                                        (range min-z (+ 1 max-z)))]
+    (any? (map coords-are-solid (cycle [bot]) block-coords))))
 
 
 (defn resolve-collision-y [y velocity]
--- a/src/clojurecraft/util.clj	Tue Aug 16 20:22:42 2011 -0400
+++ b/src/clojurecraft/util.clj	Thu Aug 18 23:15:13 2011 -0400
@@ -3,13 +3,18 @@
 ; Logging---------------------------------------------------------------------------
 (defmacro l [& body]
   `(let [result# (~@body)]
+     (println "=====================================================")
      (println result#)
+     (println "=====================================================")
      result#))
 
 (defmacro lc [& body]
   `(let [result# (~@body)]
+     (println "=====================================================")
      (println result#)
+     (println "-----------------------------------------------------")
      (println (class result#))
+     (println "=====================================================")
      result#))
 
 
@@ -40,7 +45,7 @@
   (int (Math/floor f)))
 
 (defn any? [s]
-  (not (empty? (filter identity s))))
+  (seq (filter identity s)))
 
 
 ; Bytes ----------------------------------------------------------------------------