diff --git a/project.clj b/project.clj index 1c62f32..c68a4d3 100644 --- a/project.clj +++ b/project.clj @@ -6,6 +6,7 @@ :jvm-opts ["-Djava.library.path=native"] :dependencies [[org.clojure/clojure "1.5.0"] [ns-tracker "0.2.1"] + [org.clojure/tools.nrepl "0.2.2"] [org.clojars.jyaan/slick "247.1"] [org.clojars.jyaan/slick-native "247.1"] [org.clojars.jyaan/slick-lwjgl "247.1"]]) diff --git a/src/hottub/core.clj b/src/hottub/core.clj index 1466f80..4a6cbaa 100644 --- a/src/hottub/core.clj +++ b/src/hottub/core.clj @@ -3,3 +3,9 @@ (defn -main [& args] (slick/start-game "test-game" :game)) + +(defmethod slick/update-game :game [state delta]) +(def ^:dynamic g nil) +(def ^:dynamic s nil) +(defmethod slick/eval-with-bindings :game [state game f] + (binding [g game s state] (f))) \ No newline at end of file diff --git a/src/hottub/slick.clj b/src/hottub/slick.clj index e885fcf..4fa43ab 100644 --- a/src/hottub/slick.clj +++ b/src/hottub/slick.clj @@ -1,9 +1,16 @@ (ns hottub.slick (:import [org.newdawn.slick AppGameContainer]) - (:use ns-tracker.core)) + (:use ns-tracker.core) + (:require (clojure.tools.nrepl [server :as server] + [middleware :as middleware]) + (clojure.tools.nrepl.middleware interruptible-eval + pr-values + session + load-file))) (defmulti update-game (fn [state delta] (:state state))) (defmulti render-game (fn [state graphics] (:state state))) +(defmulti eval-with-bindings (fn [state game f] (:state state))) (def modified-namespaces (ns-tracker ["src" "test"])) @@ -16,24 +23,65 @@ :extends org.newdawn.slick.BasicGame) (defn game-create [title startstate value] - [[title] (ref (assoc (or value {}) :state startstate))]) + [[title] + (let [evalqueueatom (atom []) + executor (reify java.util.concurrent.Executor + (execute [this f] (swap! evalqueueatom #(conj % f)))) + server (server/start-server :handler + (-> server/unknown-op + clojure.tools.nrepl.middleware/wrap-describe + (clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval :executor executor) + clojure.tools.nrepl.middleware.load-file/wrap-load-file + clojure.tools.nrepl.middleware.pr-values/pr-values + clojure.tools.nrepl.middleware.session/add-stdin + clojure.tools.nrepl.middleware.session/session + ; ((fn [h] (fn [val] (prn val) (h val))))))] + ))] + (prn "nrepl started on port " (:port server) server) + {:state (ref (assoc (or value {}) :state startstate)) + :evalqueue evalqueueatom + :server server})]) +(defn game-state-ref [this] (:state (.state this))) + (defn game-init [this container]) +(defn clear-and-get-evalqueue [this] + (let [evalqueueatom (:evalqueue (.state this))] + (loop [evalqueue @evalqueueatom] + (if (compare-and-set! evalqueueatom evalqueue []) + evalqueue + (recur @evalqueueatom))))) + (defn game-update [this container delta] (doseq [ns-sym (modified-namespaces)] - (require ns-sym :reload)) + (try + (require ns-sym :reload) + (catch Exception e (prn "Couldn't load" ns-sym (.getMessage e))))) + (doseq [f (clear-and-get-evalqueue this)] + (try + (eval-with-bindings @(game-state-ref this) this f) + (catch Exception e (prn "couldn't eval" f (.getMessage e))))) (dosync - (if-let [statenew (update-game @(.state this) delta)] - (ref-set (.state this) (assoc @(.state this) :state statenew))))) + (try + (if-let [statenew (update-game @(game-state-ref this) delta)] + (ref-set (game-state-ref this) statenew)) + (catch Exception e (prn "Couldn't update" (:state @(game-state-ref this)) (.getMessage e)))))) (defn game-render [this container graphics] - (render-game @(.state this) graphics)) + (try + (render-game @(game-state-ref this) graphics) + (catch Exception e (prn "Couldn't render" (:state @(game-state-ref this)) (.getMessage e))))) + +(defn game-setstate [this statenew] + (dosync (ref-set (game-state-ref this) statenew))) (defmethod update-game :default [state delta]) (defmethod render-game :default [state graphics]) +(defmethod eval-with-bindings :default [state game f] (f)) (defn start-game [title startstate & [value]] (let [game (hottub.slick.Game. title startstate value) container (AppGameContainer. game 640 480 false)] - (.start container))) + (.start container) + game))