--- a/src/clojurecraft/core.clj Thu Jul 21 18:59:53 2011 -0400
+++ b/src/clojurecraft/core.clj Thu Jul 21 20:14:53 2011 -0400
@@ -3,6 +3,7 @@
(:use [clojurecraft.in])
(:use [clojurecraft.out])
(:use [clojurecraft.util])
+ (:use [clojurecraft.data])
(:use [clojure.contrib.pprint :only (pprint)])
(:require [clojurecraft.actions :as act])
(:import (java.net Socket)
@@ -14,6 +15,19 @@
(declare conn-handler)
(declare login)
+; Connections ----------------------------------------------------------------------
+(def *worlds* (ref {}))
+(defn get-world [server]
+ (dosync
+ (ensure *worlds*)
+ (let [world (@*worlds* server)]
+ (if world
+ world
+ (do
+ (alter *worlds* assoc server (World. server (ref {}) (ref {}) (ref 0)))
+ (@*worlds* server))))))
+
+
(defn login [bot username]
; Send handshake
(write-packet bot :handshake {:username username})
@@ -57,9 +71,10 @@
out (DataOutputStream. (.getOutputStream socket))
conn (ref {:in in :out out})
outqueue (LinkedBlockingQueue.)
+
+ world (get-world server)
player (ref {:location {:onground false, :pitch 0.0, :yaw 0.0, :z 240.0,
:y 85.0, :stance 60.0, :x -120.0}})
- world (ref {})
bot {:connection conn, :outqueue outqueue, :player player, :world world,
:packet-counts-in (atom {}), :packet-counts-out (atom {})}]
@@ -86,10 +101,11 @@
(dosync (alter (:connection bot) merge {:exit true})))
+; Utility functions ----------------------------------------------------------------
; Scratch --------------------------------------------------------------------------
-(def bot (connect minecraft-local "Honeydew"))
-(act/move bot 0 -1 0)
+;(def bot (connect minecraft-local "Honeydew"))
+;(act/move bot 0 -1 0)
;(pprint @(:packet-counts-in bot))
;(pprint @(:packet-counts-out bot))
;(pprint (:player bot))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/clojurecraft/data.clj Thu Jul 21 20:14:53 2011 -0400
@@ -0,0 +1,92 @@
+(ns clojurecraft.data)
+
+; Location
+;
+; The location of an entity in the world.
+;
+; x -> double
+; y -> double
+; z -> double
+; pitch -> double
+; yaw -> double
+; stance -> double
+; onground -> boolean
+(defrecord Location [x y z pitch yaw stance onground])
+
+; Entity
+;
+; A single entity in the world.
+;
+; eid -> integer
+; loc -> Location
+;
+; despawned -> boolean
+; True if the entity has been despawned.
+;
+; This exists to notify transactions coordinating on this ref that
+; 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])
+
+; Chunk
+;
+; A single chunk in the world.
+(defrecord Chunk [])
+
+; Block
+;
+; A representation of a single block.
+; This may be removed in the future if the overhead is too great.
+;
+; loc -> [x y z]
+; A simple vector of three coordinates, NOT a Location (for performance).
+;
+; kind -> TODO
+(defrecord Block [loc kind])
+
+; Bot
+;
+; A single bot, connected to a server.
+;
+; connection -> (ref {:in DataInputStream :out :DataOutputStream})
+; The input and output streams.
+;
+; Don't ever touch this -- the writing thread will handle it.
+;
+; outqueue -> LinkedBlockingQueue
+; A queue of packets to write, so we can coordinate the writes
+; to avoid mixing packets together.
+;
+; Don't ever touch this. Use out/-write-packet-* instead.
+;
+; player -> (ref Entity)
+; A ref to the Entity representing the bot's player in the world.
+;
+; world -> World
+; The world the bot is connected to.
+;
+; NOT a ref. Coordinating the entire world would be too much of a performance
+; hit. Instead the individual pieces of the world are refs.
+;
+; Worlds themselves should never need to be updated after creation -- instead the
+; various refs inside them are updated.
+;
+; packet-counts-in -> integer
+; packet-counts-out -> integer
+(defrecord Bot [connection outqueue player world
+ packet-counts-in packet-counts-out])
+
+; World
+;
+; A representation of a single world/server, shared by all bots connected to it.
+;
+; server -> {:name hostname :port port}
+; entities -> (ref {eid (ref Entity) ...})
+; A map of all the entities in the world.
+; chunks -> (ref {[x y z] [(ref Chunk) ...] ...})
+; A map of all the chunks in the world.
+; time -> (ref integer)
+; The current world time.
+(defrecord World [server entities chunks time])
+
--- a/todo.org Thu Jul 21 18:59:53 2011 -0400
+++ b/todo.org Thu Jul 21 20:14:53 2011 -0400
@@ -1,5 +1,3 @@
-* DONE Wrap all IO in io!.
-* TODO Wrap class mutations in io!?
* TODO Use Clojure's ugly keyword arguments.
(defn dothreads! [f & {thread-count :threads exec-count :times
@@ -7,60 +5,3 @@
...)
* TODO Use some pre/post conditions.
-* TODO Make records for common pieces of data.
-** TODO Locations
-** TODO Entities
-** TODO Chunks
-* TODO Relayout the data structures.
-** TODO Servers
-
- { 'localhost' world1,
- '222.222.111.232' world2,
- ... }
-
-** TODO World
-
- { :entities {},
- :chunks {}, }
-
-** TODO Entities
-
- { 123 {},
- 234 {},
- ... }
-
-** TODO Entity (ref)
-
- { :eid 123,
- :location location,
- ...? }
-
-** TODO Location
-
- { :x 100.0,
- :y 100.1,
- :z 80.3,
- :stance 101.0,
- :yaw 11.0,
- :pitch 81.0,
- :onground true }
-
-** TODO Chunks
-
- { [1,23,12] (ref? chunk),
- ... }
-
-** TODO Chunk (ref?)
-
- { ? }
-
-** TODO Bot
-
- { :world world,
- :eid 123,
- :connections { :in in-conn,
- :out out-conn },
- :packet-counts { :in (atom 123),
- :out (atom 234) },
- ...? }
-