Giter Club home page Giter Club logo

chocolatier's Introduction

chocolatier

A work-in-progress web game engine for repl driven game development written in ClojureScript using Pixi.js as a rendering engine.

Demo

Here's the working example game that includes tilesets, collision detection, animation, sprites, and user input.

Alt text

Credit Magiscarf for the tiles

Usage

With figwheel

The following instructions will start a browser connected repl and launch the demo game:

  1. Clone the project and all submodules git clone --recursive https://github.com/alexkehayias/chocolatier
  2. Start the browser REPL server lein figwheel
  3. Navigate your browser to http://127.0.0.1:1223/dev to connect to the REPL and view devcards for the project
  4. Play the example game at http://127.0.0.1:1223/dev#!/chocolatier.examples.action_rpg.core changes to files will automatically restart the game

With figwheel and emacs using cider

Follow the setup instructions from cider documentation here

Compiling with advanced optimizations

  1. Run lein cljsbuild once min
  2. Start figwheel lein figwheel
  3. Navigate your browser to http://127.0.0.1:1223/min and the game will start immediately

Entity Component System

The game engine implemented using a modified entity component system which organizes aspects of a game modularly. Think about it less as a bunch of objects with their own state and methods and more like a database where you query for functionality, state, based on a certain aspect or entity.

Organization:

  1. Scene - collection of system labels to be looked up and called by the game loop (main menu, random encounter, world map, etc)
  2. System - functions that operates on a component or not and returns updated game state. Examples: input, rendering, collision detection
  3. Components - functions that return updated component state per entity and events to emit
  4. Entities - unique IDs that have a list of components to they participate in. Examples: {:player1 [:controllable :moveable :destructable]}

Example

The following example implements a simple game loop, middleware, system, component, and entities to show you how it all fits together. See the rest of the game for a more in-depth example (and graphics).

(ns user.test
  (:require [chocolatier.engine.ecs :as ecs]
            [chocolatier.engine.core :refer [game-loop mk-game-state]]))

(defn test-component-fn
  "Increment the :x value by 1"
  [entity-id component-state inbox]
  (println entity-id component-state)
  (update component-state :x inc))

(defn init-state
  "Initial game state with our example system, component, and a few entities"
  []
  (mk-game-state {}
   ;; Lists which systems and what order to run them in
   {:type :scene
    :opts {:uid :default
           :systems [:test-system]}}
   ;; Sets the current scene to the above
   {:type :current-scene
    :opts {:uid :default}}
   ;; Create our test system that operates on the :testable component
   {:type :system
    :opts {:uid :test-system
           :component {:uid :testable
                       :fn test-component-fn}}}
   ;; Create an entity with some initial component state
   {:type :entity
    :opts {:uid :player1
           :components [{:uid :testable :state {:x 0 :y 0}}]}
   {:type :entity
    :opts {:uid :player2
           :components [{:uid :testable :state {:x 0 :y 0}}]}))

(defn run-n-frames
  "Middleware to count the number of frames and return nil to indicate
  the game loop should exit after n frames"
  [f n]
  (fn [state]
    (when (<= (:frame-count state 0) 10)
      (update (f state) :frame-count inc))))

(defn run
  "Defines the function that is called each time the game loop runs.
  You can add additional middleware here similar to ring handlers."
  [handler]
  (-> handler
      (run-n-frames 10)))

;; Run the game loop 10 times and print the component-state each frame
(game-loop (init-state) run)

State

The game is represented as a hashmap and a collection of functions that transform the state. This makes it easy to test game logic by calling functions with mocked data (since it's just a hashmap). You should be able to test any system, component, etc with data only.

Browser Connected Repl (Brepl)

A browser repl is automatically available when the server is started when using lein figwheel. This allows you to dynamically re-evaluate the code running in the browser without a page refresh. Static files can also watched and reload the game when changed. See the figwheel documentation for more.

Cross-component communication

A global pub-sub event queue is available for any component enabling cross component communication without coupling the state of any of the components. For example, suppose the render component needs to update the screen position of the player sprite. The render component needs information from the input component, but we don't want to couple the state of either components together. Instead of directly accessing the input component's state from the render component we subscribe to messages about player movement and update based on that. We can broadcast that information without any knowledge of who is listening to it and no one can change the component state from another component.

Events

By default, component functions created with ecs/mk-component can output a single value, representing component state, or two values, component state and a collection of events to emit.

For example, the following component will emit a single event called :my-event with the message {:foo :bar}:

(defn component-a [entity-id component-state inbox]
  [component-state [(ev/mk-event {:foo :bar} [:my-event entity-id])]]])

Subscriptions

Any component can subscribe to events by creating a component with a :subscriptions key in the options hashmap where each subscription is a vector of selectors:

(mk-component state [component-f {:subscriptions [:action :movement]}])

The subscribed component will receive the event in a hashmap in the :inbox key in the context argument (third argument) to the component function. Messages that are sent are available immediately to the subscriber which allows for events to be sent and received within the same frame and are therefore order dependent.

Tilemaps

The game engine supports tilemaps generated from the Tiled map editor http://www.mapeditor.org. Export the map as json and include the tileset image in the resources/public/static/images directory.

Tilemaps require all assets to be loaded (tileset images) to prevent any race conditions with loading a tilemap see chocolatier.engine.systems.tiles/load-assets. Tilemaps are loaded asynchronously from the server via chocolatier.engine.systems.tiles/load-tilemap which takes a callback.

Middleware

The game loop can be wrapped in middleware similar to ring middleware. This provides a way of accessing the running game state, ending the game loop, introspection, and other side effects.

Here's an example of a middleware that makes a running game's state queryable in the repl:

(defn wrap-copy-state-to-atom
  "Copy the latest game state to the copy-atom so it can be inspected outside
   the game loop."
  [f copy-atom]
  (fn [state]
    (let [next-state (f state)]
      (reset! copy-atom next-state)
      next-state)))

Usage:

(def *state* (atom nil))

(game-loop state (fn [handler]
                   (-> handler
                       (wrap-copy-state-to-atom *state*))))

(println (-> *state* deref keys))

Running Tests

View the tests using the devcards at http://127.0.0.1:1223/dev

Performance

The game engine is being tested to get to 100 "game objects" with meaningful functionality, tilemaps, sound, etc at 60 FPS. Performance tuning is an ongoing process and the project is still being thoroughly optimized. ClojureScript presents challenges for optimization including garbage collection, persistent data structures, and functional paradigms that js engines may have difficulty optimizing.

Tips

Here are some tips for optimizing performance of game loops:

  • Use the Chrome dev tools to do a CPU profile and trace where time is being spent
  • Don't use partial or apply as they are slow
  • Always specify each arrity of a function instead of using (fn [& args] ...)
  • Don't use multimethod, use cond or condp and manually dispatch
  • Use array when you need to quickly append items to a collection (mutable)
  • Use loop instead of for or into with transients or arrays as the accumulator
  • Avoid boxing and unboxing i.e multiple maps/fors over a collection, use transducers, reducers or loops
  • Don't make multiple calls to get the same data, put it in a let
  • Avoid heavily nested closures as the lookup tree becomes very long and slow
  • Favor eager operations over lazy operations i.e reduce instead of for
  • Don't use concat or mapcat as they can be slow and generate lots of garbage
  • Don't use last as it will need to traverse the whole sequence, use nth instead if you know how many elements are in the collection
  • Don't use hashmaps as functions ({:a 1} :a), instead use get or keywords as functions
  • Always return the same type from a function (V8 can then optimize it)

Advanced Compilation

The min build uses advanced compilation with static function inlining which can nearly substantially increase the framerate in most instances.

Benchmarks

Naive frames per second benchmarks are available at chocolatier.engine.benchmarks for measuring the performance of the framework.

License

Copyright © 2019 Alex Kehayias

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

chocolatier's People

Contributors

alexkehayias avatar phelanm avatar radix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chocolatier's Issues

Still Alive?

Looks great, ClojureScript, game engine - super.

But no commits in years.

What did people move on to?

I need to dev a game in ClojureScript. Thx

Figwheel times out and crashes browser tab when dereferencing *state* from REPL

Figwheel times out and crashes the Chrome browser tab when dereferencing state from REPL while the chocolatier demo game is running.

In the terminal:

➜  chocolatier git:(dev) ✗ rlwrap lein figwheel

(Connect browser to running figwheel process...)

cljs.user=> (in-ns 'chocolatier.engine.core)
nil
chocolatier.engine.core=> *state*
Eval timed out!

The browser tab becomes unresponsive and Chrome must be "force shutdown"ed from Activity Monitor.

won't compile

I've tried to compile it both with the original project.clj and the one updated to the latest cljsbuild version. The result is always the same:

> lein cljsbuild once Compiling ClojureScript. Compiling "resources/public/scripts/app.js" from ["src/cljs"]... WARNING: unsigned-bit-shift-right already refers to: #'clojure.core/unsigned-bit-shift-right in namespace: cljs.core, being replaced by: #'cljs.core/unsigned-bit-shift-right WARNING: No such namespace: chocolatier.engine.watchers at line 1 /Users/Nek/Projects/Clojure/chocolatier/src/cljs/chocolatier/engine/state.cljs WARNING: Referred var chocolatier.engine.watchers/hashmap-watcher does not exist at line 1 /Users/Nek/Projects/Clojure/chocolatier/src/cljs/chocolatier/engine/state.cljs WARNING: Referred var chocolatier.engine.watchers/entity-watcher does not exist at line 1 /Users/Nek/Projects/Clojure/chocolatier/src/cljs/chocolatier/engine/state.cljs WARNING: No such namespace: chocolatier.engine.watchers at line 1 src/cljs/chocolatier/engine/state.cljs WARNING: Referred var chocolatier.engine.watchers/hashmap-watcher does not exist at line 1 src/cljs/chocolatier/engine/state.cljs WARNING: Referred var chocolatier.engine.watchers/entity-watcher does not exist at line 1 src/cljs/chocolatier/engine/state.cljs Compiling "resources/public/scripts/app.js" failed. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at clojure.lang.PersistentVector.assocN(PersistentVector.java:130) at clojure.lang.PersistentVector.assocN(PersistentVector.java:20) at clojure.lang.APersistentVector.assoc(APersistentVector.java:333) at clojure.lang.APersistentVector.assoc(APersistentVector.java:18) at clojure.lang.RT.assoc(RT.java:702) at clojure.core$assoc.invoke(core.clj:187) at clojure.core$update_in.doInvoke(core.clj:5698) at clojure.lang.RestFn.invoke(RestFn.java:467) at cljs.source_map$encode$encode_cols__1922$fn__1929.invoke(source_map.clj:209) at clojure.lang.Atom.swap(Atom.java:37) at clojure.core$swap_BANG_.invoke(core.clj:2232) at cljs.source_map$encode$encode_cols__1922.invoke(source_map.clj:207) at cljs.source_map$encode.invoke(source_map.clj:213) at cljs.closure$optimize.doInvoke(closure.clj:627) at clojure.lang.RestFn.applyTo(RestFn.java:139) at clojure.core$apply.invoke(core.clj:626) at cljs.closure$build.invoke(closure.clj:963) at cljs.closure$build.invoke(closure.clj:909) at cljsbuild.compiler$compile_cljs$fn__3130.invoke(compiler.clj:58) at cljsbuild.compiler$compile_cljs.invoke(compiler.clj:57) at cljsbuild.compiler$run_compiler.invoke(compiler.clj:159) at user$eval3256$iter__3274__3278$fn__3279$fn__3291.invoke(NO_SOURCE_FILE:1) at user$eval3256$iter__3274__3278$fn__3279.invoke(NO_SOURCE_FILE:1) at clojure.lang.LazySeq.sval(LazySeq.java:40) at clojure.lang.LazySeq.seq(LazySeq.java:49) at clojure.lang.RT.seq(RT.java:484) at clojure.core$seq.invoke(core.clj:133) at clojure.core$dorun.invoke(core.clj:2855) at clojure.core$doall.invoke(core.clj:2871) at user$eval3256.invoke(NO_SOURCE_FILE:1) at clojure.lang.Compiler.eval(Compiler.java:6703) at clojure.lang.Compiler.eval(Compiler.java:6693) Subprocess failed

Failure on Step #1 (2nd step) of "With Figwheel" instructions

Are there are dependencies I may need to install from somewhere else?

I poked around on google for instructions that would put nrepl/cider stuff on the classpath, but I didn't find results related to that.

I am new to clojure and clojurescript, and hence a little over my head here... I have only lein and emacs/spacemacs installed. Other Figwheel lein templates work fine on my machine (Reagent, etc.).

Figwheel: Cutting some fruit, just a sec ...
Figwheel: Validating the configuration found in project.clj
Figwheel: Configuration Valid :)
Figwheel: Starting server at http://0.0.0.0:1223
Figwheel: Watching build - dev
Figwheel: Cleaning build - dev
Compiling "resources/public/js/compiled/chocolatier.js" from ["src/cljs" "test/cljs"]...
WARNING: Use of undeclared Var chocolatier.engine.benchmarks/e1 at line 37 /Users/tfenney/stuff/chocolatier/test/cljs/chocolatier/engine/benchmarks.cljs
Successfully compiled "resources/public/js/compiled/chocolatier.js" in 15.775 seconds.
Figwheel: Starting CSS Watcher for paths  ["resources/public/css"]
Figwheel: Starting nREPL server on port: 8999
Could not locate cider/nrepl__init.class or cider/nrepl.clj on classpath.
java.io.FileNotFoundException: Could not locate cider/nrepl__init.class or cider/nrepl.clj on classpath.
	at clojure.lang.RT.load(RT.java:456)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.core$load$fn__5677.invoke(core.clj:5893)
	at clojure.core$load.invokeStatic(core.clj:5892)
	at clojure.core$load.doInvoke(core.clj:5876)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5697)
	at clojure.core$load_one.invoke(core.clj:5692)
	at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
	at clojure.core$load_lib.invokeStatic(core.clj:5736)
	at clojure.core$load_lib.doInvoke(core.clj:5717)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$load_libs.invokeStatic(core.clj:5774)
	at clojure.core$load_libs.doInvoke(core.clj:5758)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$require.invokeStatic(core.clj:5796)
	at clojure.core$require.doInvoke(core.clj:5796)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at figwheel_sidecar.utils$require_QMARK_.invokeStatic(utils.clj:38)
	at figwheel_sidecar.utils$require_QMARK_.invoke(utils.clj:36)
	at figwheel_sidecar.components.nrepl_server$start_nrepl_server$resolve_mw__23415.invoke(nrepl_server.clj:17)
	at clojure.core$map$fn__4785.invoke(core.clj:2644)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.RT.seq(RT.java:521)
	at clojure.core$seq__4357.invokeStatic(core.clj:137)
	at clojure.core$apply.invokeStatic(core.clj:641)
	at clojure.core$mapcat.invokeStatic(core.clj:2674)
	at clojure.core$mapcat.doInvoke(core.clj:2674)
	at clojure.lang.RestFn.invoke(RestFn.java:423)
	at figwheel_sidecar.components.nrepl_server$start_nrepl_server.invokeStatic(nrepl_server.clj:25)
	at figwheel_sidecar.components.nrepl_server$start_nrepl_server.invoke(nrepl_server.clj:7)
	at figwheel_sidecar.components.nrepl_server.NreplComponent.start(nrepl_server.clj:37)
	at com.stuartsierra.component$eval22659$fn__22660$G__22649__22662.invoke(component.cljc:5)
	at com.stuartsierra.component$eval22659$fn__22660$G__22648__22665.invoke(component.cljc:5)
	at clojure.lang.Var.invoke(Var.java:379)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$apply.invoke(core.clj:641)
	at com.stuartsierra.component$try_action.invokeStatic(component.cljc:117)
	at com.stuartsierra.component$try_action.invoke(component.cljc:116)
	at com.stuartsierra.component$update_system$fn__22718.invoke(component.cljc:139)
	at clojure.lang.ArraySeq.reduce(ArraySeq.java:114)
	at clojure.core$reduce.invokeStatic(core.clj:6544)
	at clojure.core$reduce.invoke(core.clj:6527)
	at com.stuartsierra.component$update_system.invokeStatic(component.cljc:135)
	at com.stuartsierra.component$update_system.doInvoke(component.cljc:129)
	at clojure.lang.RestFn.invoke(RestFn.java:445)
	at com.stuartsierra.component$start_system.invokeStatic(component.cljc:163)
	at com.stuartsierra.component$start_system.invoke(component.cljc:155)
	at com.stuartsierra.component$start_system.invokeStatic(component.cljc:161)
	at com.stuartsierra.component$start_system.invoke(component.cljc:155)
	at com.stuartsierra.component.SystemMap.start(component.cljc:178)
	at figwheel_sidecar.system$start_figwheel_system$fn__24460.invoke(system.clj:656)
	at figwheel_sidecar.system$dispatch_system_component_errors.invokeStatic(system.clj:642)
	at figwheel_sidecar.system$dispatch_system_component_errors.invoke(system.clj:640)
	at figwheel_sidecar.system$start_figwheel_system.invokeStatic(system.clj:656)
	at figwheel_sidecar.system$start_figwheel_system.invoke(system.clj:654)
	at figwheel_sidecar.system$start_figwheel_BANG__STAR_.invokeStatic(system.clj:691)
	at figwheel_sidecar.system$start_figwheel_BANG__STAR_.invoke(system.clj:677)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:646)
	at clojure.core$apply.invoke(core.clj:641)
	at figwheel_sidecar.system$start_figwheel_BANG_.invokeStatic(system.clj:735)
	at figwheel_sidecar.system$start_figwheel_BANG_.doInvoke(system.clj:693)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at figwheel_sidecar.repl_api$start_figwheel_from_lein.invokeStatic(repl_api.clj:150)
	at figwheel_sidecar.repl_api$start_figwheel_from_lein.invoke(repl_api.clj:146)
	at figwheel_sidecar.repl_api$launch_from_lein.invokeStatic(repl_api.clj:192)
	at figwheel_sidecar.repl_api$launch_from_lein.invoke(repl_api.clj:189)
	at user$eval24523.invokeStatic(form-init2319528866261437468.clj:1)
	at user$eval24523.invoke(form-init2319528866261437468.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:6927)
	at clojure.lang.Compiler.eval(Compiler.java:6917)
	at clojure.lang.Compiler.load(Compiler.java:7379)
	at clojure.lang.Compiler.loadFile(Compiler.java:7317)
	at clojure.main$load_script.invokeStatic(main.clj:275)
	at clojure.main$init_opt.invokeStatic(main.clj:277)
	at clojure.main$init_opt.invoke(main.clj:277)
	at clojure.main$initialize.invokeStatic(main.clj:308)
	at clojure.main$null_opt.invokeStatic(main.clj:342)
	at clojure.main$null_opt.invoke(main.clj:339)
	at clojure.main$main.invokeStatic(main.clj:421)
	at clojure.main$main.doInvoke(main.clj:384)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
WARNING: unable to load "cider.nrepl/cider-middleware" middleware
java.io.FileNotFoundException: Could not locate cider/nrepl/middleware/util/misc__init.class or cider/nrepl/middleware/util/misc.clj on classpath., compiling:(refactor_nrepl/middleware.clj:1:1)
java.io.FileNotFoundException: Could not locate cider/nrepl/middleware/util/misc__init.class or cider/nrepl/middleware/util/misc.clj on classpath., compiling:(refactor_nrepl/middleware.clj:1:1)
	at clojure.lang.Compiler.load(Compiler.java:7391)
	at clojure.lang.RT.loadResourceScript(RT.java:372)
	at clojure.lang.RT.loadResourceScript(RT.java:363)
	at clojure.lang.RT.load(RT.java:453)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.core$load$fn__5677.invoke(core.clj:5893)
	at clojure.core$load.invokeStatic(core.clj:5892)
	at clojure.core$load.doInvoke(core.clj:5876)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5697)
	at clojure.core$load_one.invoke(core.clj:5692)
	at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
	at clojure.core$load_lib.invokeStatic(core.clj:5736)
	at clojure.core$load_lib.doInvoke(core.clj:5717)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$load_libs.invokeStatic(core.clj:5774)
	at clojure.core$load_libs.doInvoke(core.clj:5758)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$require.invokeStatic(core.clj:5796)
	at clojure.core$require.doInvoke(core.clj:5796)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at figwheel_sidecar.utils$require_QMARK_.invokeStatic(utils.clj:38)
	at figwheel_sidecar.utils$require_QMARK_.invoke(utils.clj:36)
	at figwheel_sidecar.components.nrepl_server$start_nrepl_server$resolve_mw__23415.invoke(nrepl_server.clj:17)
	at clojure.core$map$fn__4785.invoke(core.clj:2644)
	at clojure.lang.LazySeq.sval(LazySeq.java:40)
	at clojure.lang.LazySeq.seq(LazySeq.java:49)
	at clojure.lang.RT.seq(RT.java:521)
	at clojure.core$seq__4357.invokeStatic(core.clj:137)
	at clojure.core$apply.invokeStatic(core.clj:641)
	at clojure.core$mapcat.invokeStatic(core.clj:2674)
	at clojure.core$mapcat.doInvoke(core.clj:2674)
	at clojure.lang.RestFn.invoke(RestFn.java:423)
	at figwheel_sidecar.components.nrepl_server$start_nrepl_server.invokeStatic(nrepl_server.clj:25)
	at figwheel_sidecar.components.nrepl_server$start_nrepl_server.invoke(nrepl_server.clj:7)
	at figwheel_sidecar.components.nrepl_server.NreplComponent.start(nrepl_server.clj:37)
	at com.stuartsierra.component$eval22659$fn__22660$G__22649__22662.invoke(component.cljc:5)
	at com.stuartsierra.component$eval22659$fn__22660$G__22648__22665.invoke(component.cljc:5)
	at clojure.lang.Var.invoke(Var.java:379)
	at clojure.lang.AFn.applyToHelper(AFn.java:154)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$apply.invoke(core.clj:641)
	at com.stuartsierra.component$try_action.invokeStatic(component.cljc:117)
	at com.stuartsierra.component$try_action.invoke(component.cljc:116)
	at com.stuartsierra.component$update_system$fn__22718.invoke(component.cljc:139)
	at clojure.lang.ArraySeq.reduce(ArraySeq.java:114)
	at clojure.core$reduce.invokeStatic(core.clj:6544)
	at clojure.core$reduce.invoke(core.clj:6527)
	at com.stuartsierra.component$update_system.invokeStatic(component.cljc:135)
	at com.stuartsierra.component$update_system.doInvoke(component.cljc:129)
	at clojure.lang.RestFn.invoke(RestFn.java:445)
	at com.stuartsierra.component$start_system.invokeStatic(component.cljc:163)
	at com.stuartsierra.component$start_system.invoke(component.cljc:155)
	at com.stuartsierra.component$start_system.invokeStatic(component.cljc:161)
	at com.stuartsierra.component$start_system.invoke(component.cljc:155)
	at com.stuartsierra.component.SystemMap.start(component.cljc:178)
	at figwheel_sidecar.system$start_figwheel_system$fn__24460.invoke(system.clj:656)
	at figwheel_sidecar.system$dispatch_system_component_errors.invokeStatic(system.clj:642)
	at figwheel_sidecar.system$dispatch_system_component_errors.invoke(system.clj:640)
	at figwheel_sidecar.system$start_figwheel_system.invokeStatic(system.clj:656)
	at figwheel_sidecar.system$start_figwheel_system.invoke(system.clj:654)
	at figwheel_sidecar.system$start_figwheel_BANG__STAR_.invokeStatic(system.clj:691)
	at figwheel_sidecar.system$start_figwheel_BANG__STAR_.invoke(system.clj:677)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:646)
	at clojure.core$apply.invoke(core.clj:641)
	at figwheel_sidecar.system$start_figwheel_BANG_.invokeStatic(system.clj:735)
	at figwheel_sidecar.system$start_figwheel_BANG_.doInvoke(system.clj:693)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at figwheel_sidecar.repl_api$start_figwheel_from_lein.invokeStatic(repl_api.clj:150)
	at figwheel_sidecar.repl_api$start_figwheel_from_lein.invoke(repl_api.clj:146)
	at figwheel_sidecar.repl_api$launch_from_lein.invokeStatic(repl_api.clj:192)
	at figwheel_sidecar.repl_api$launch_from_lein.invoke(repl_api.clj:189)
	at user$eval24523.invokeStatic(form-init2319528866261437468.clj:1)
	at user$eval24523.invoke(form-init2319528866261437468.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:6927)
	at clojure.lang.Compiler.eval(Compiler.java:6917)
	at clojure.lang.Compiler.load(Compiler.java:7379)
	at clojure.lang.Compiler.loadFile(Compiler.java:7317)
	at clojure.main$load_script.invokeStatic(main.clj:275)
	at clojure.main$init_opt.invokeStatic(main.clj:277)
	at clojure.main$init_opt.invoke(main.clj:277)
	at clojure.main$initialize.invokeStatic(main.clj:308)
	at clojure.main$null_opt.invokeStatic(main.clj:342)
	at clojure.main$null_opt.invoke(main.clj:339)
	at clojure.main$main.invokeStatic(main.clj:421)
	at clojure.main$main.doInvoke(main.clj:384)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
Caused by: java.io.FileNotFoundException: Could not locate cider/nrepl/middleware/util/misc__init.class or cider/nrepl/middleware/util/misc.clj on classpath.
	at clojure.lang.RT.load(RT.java:456)
	at clojure.lang.RT.load(RT.java:419)
	at clojure.core$load$fn__5677.invoke(core.clj:5893)
	at clojure.core$load.invokeStatic(core.clj:5892)
	at clojure.core$load.doInvoke(core.clj:5876)
	at clojure.lang.RestFn.invoke(RestFn.java:408)
	at clojure.core$load_one.invokeStatic(core.clj:5697)
	at clojure.core$load_one.invoke(core.clj:5692)
	at clojure.core$load_lib$fn__5626.invoke(core.clj:5737)
	at clojure.core$load_lib.invokeStatic(core.clj:5736)
	at clojure.core$load_lib.doInvoke(core.clj:5717)
	at clojure.lang.RestFn.applyTo(RestFn.java:142)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$load_libs.invokeStatic(core.clj:5774)
	at clojure.core$load_libs.doInvoke(core.clj:5758)
	at clojure.lang.RestFn.applyTo(RestFn.java:137)
	at clojure.core$apply.invokeStatic(core.clj:648)
	at clojure.core$require.invokeStatic(core.clj:5796)
	at clojure.core$require.doInvoke(core.clj:5796)
	at clojure.lang.RestFn.invoke(RestFn.java:457)
	at refactor_nrepl.middleware$eval41152$loading__5569__auto____41153.invoke(middleware.clj:1)
	at refactor_nrepl.middleware$eval41152.invokeStatic(middleware.clj:1)
	at refactor_nrepl.middleware$eval41152.invoke(middleware.clj:1)
	at clojure.lang.Compiler.eval(Compiler.java:6927)
	at clojure.lang.Compiler.eval(Compiler.java:6916)
	at clojure.lang.Compiler.load(Compiler.java:7379)
	... 95 more
WARNING: unable to load "refactor-nrepl.middleware/wrap-refactor" middleware
Launching ClojureScript REPL for build: dev
Figwheel Controls:
          (stop-autobuild)                ;; stops Figwheel autobuilder
          (start-autobuild [id ...])      ;; starts autobuilder focused on optional ids
          (switch-to-build id ...)        ;; switches autobuilder to different build
          (reset-autobuild)               ;; stops, cleans, and starts autobuilder
          (reload-config)                 ;; reloads build config and resets autobuild
          (build-once [id ...])           ;; builds source one time
          (clean-builds [id ..])          ;; deletes compiled cljs target files
          (print-config [id ...])         ;; prints out build configurations
          (fig-status)                    ;; displays current state of system
  Switch REPL build focus:
          :cljs/quit                      ;; allows you to switch REPL to another build
    Docs: (doc function-name-here)
    Exit: Control+C or :cljs/quit
 Results: Stored in vars *1, *2, *3, *e holds last exception object
Prompt will show when Figwheel connects to your application

Make chocolatier usable as a dependency

Hi!

I'm trying to use chocolatier as a dependency in another project, but it's not working, and I'm not sure why since I'm pretty new to the whole lein/clojure/clojurescript ecosystem.

Basically, I can "lein install" the chocolatier library, and it creates a .jar in my ~/.m2/repository, but for some reason when I add it as a dependency to my project the compiled javascript is not being copied into my output-dir like it is for other dependencies I have.

I realize chocolatier is early on in development, and I don't expect it to be stable, but I'd like to try it out so that I can give feedback.

Cannot load chocolatier.core namespace

Maybe I'm doing something wrong (I am fairly new to ClojureScript), but I can't seem to properly load chocolatier.core namespace after the browser repl loads.

cljs.user=> (load "chocolatier/core")
WARNING: Use of undeclared Var cljs.user/load at line 1

<TypeError: undefined is not an object (evaluating 'cljs.user.load.call')>

eval code
eval@[native code]
http://127.0.0.1:9000/app:2018:317
evaluate_javascript@http://127.0.0.1:9000/app:2019:236
http://127.0.0.1:9000/app:2027:113
deliver@http://127.0.0.1:9000/app:1883:278
xpcDeliver@http://127.0.0.1:9000/app:1950:366
messageReceived_@http://127.0.0.1:9000/app:1906:408
fireListener@http://127.0.0.1:9000/app:1523:130
handleBrowserEvent_@http://127.0.0.1:9000/app:1526:198
http://127.0.0.1:9000/app:1515:401
nil

The browser repl functions normally as I have tested it by sending (js/alert 'test'). I just can't seem to get past the last step where I can call (restart-game!).

Excessive warning when starting brepl

When starting the browser repl (automatically happens on chocolatier.server/restart-server!) a ton of warning come up as mentioned in issue #5. This appears to have happened when updating to the later versions of ClojureScript and Austin.

Todos needed

Hi.

It would be nice to have list of features that should be implemented in order to get chocolatier out of WIP state. Probably they should be listed in README or github issue should be opened for each missing feature.

What do you think about this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.