Make it easier to make Trait implementation
To implement a Trait in Citizens you subclass the Trait class, and then register the subclass with the TraitFactory. This means you need an actual concrete class, so [[proxy]] doens't cut it.
You can bypass the TraitFactory and addTrait
to an NPC directly, but then
your traits won't survive a server restart. Citizens persists which traits a
given NPC has and restores them on boot, for this to work we have to go
through the Factory.
Note that for this to work the code that defines your traits needs to be
loaded before Citizens restores its state. Adding them in init
namespaces
that you declare in your witchcraft.edn
plugin config should do the trick.
To make this work we gen-class
a concrete subclass, but instead of writing
it out to we just compile and load it in memory (DynamicClassLoader for the
win!). The class itself is just a dummy stub that delegates method calls to
callbacks from a registry (a simple atom), so they are easy to redefine. You
can even use a var directly as a callback, so re-evaluating the defn
is
immediately reflected.
Make it easier to make Trait implementation To implement a Trait in Citizens you subclass the Trait class, and then register the subclass with the TraitFactory. This means you need an actual concrete class, so [[proxy]] doens't cut it. You can bypass the TraitFactory and `addTrait` to an NPC directly, but then your traits won't survive a server restart. Citizens persists which traits a given NPC has and restores them on boot, for this to work we have to go through the Factory. Note that for this to work the code that defines your traits needs to be loaded before Citizens restores its state. Adding them in `init` namespaces that you declare in your `witchcraft.edn` plugin config should do the trick. To make this work we `gen-class` a concrete subclass, but instead of writing it out to we just compile and load it in memory (DynamicClassLoader for the win!). The class itself is just a dummy stub that delegates method calls to callbacks from a registry (a simple atom), so they are easy to redefine. You can even use a var directly as a callback, so re-evaluating the `defn` is immediately reflected.
(datakey->map key)
Decode all hierarchically stored keys/values in the datakey into a nested map with keyword keys.
Decode all hierarchically stored keys/values in the datakey into a nested map with keyword keys.
(demunge-key s)
Convert string to keyword, replacing __
with .
, see also munge-key
.
Convert string to keyword, replacing `__` with `.`, see also [[munge-key]].
(flatten-keys m)
Given a (potentially nested) map with keyword keys, return a flat list of
key/value pairs, with composite string keys that use .
separators to
indicate nesting.
Given a (potentially nested) map with keyword keys, return a flat list of key/value pairs, with composite string keys that use `.` separators to indicate nesting.
(gen-and-load-class options-map)
Generates and immediately loads the bytecode for the specified class. Note that a class generated this way can be loaded only once
Taken from the rich comment section of clojure/genclass.clj
.
Generates and immediately loads the bytecode for the specified class. Note that a class generated this way can be loaded only once - the JVM supports only one class with a given name per classloader. Subsequent to generation you can import it into any desired namespaces just like any other class. See gen-class for a description of the options. Taken from the rich comment section of `clojure/genclass.clj`.
(make-trait trait-name callbacks)
Create a subclass of npcs.citizensapi.trait.Trait, name
is a simple lowercase
identifier of the trait like "sneak"
or "aggressive"
. callbacks
is a
map from keyword to function (or var, IFn). Callbacks receive this
(the
trait) as first arg. :load
and :save
also receive a DataKey
.
Callbacks: :load
, :save
, :on-attach
, :on-copy
, :on-despawn
,
:on-pre-spawn
, :run
, :save
.
Can be called multiple times, subsequent calls will only replace the
callbacks. Returns the trait subclass java.lang.Class
.
Note that adding a :run
callback for a Trait that is already attached to an
NPC will not cause it to be called. Remove the Trait from the NPC and add it
back.
To give your trait state, provide an :init
key (map or function that returns
a map), this will provide your trait's initial state. You can use the trait
instance itself as an atom, e.g. call @this
or (swap! this ...)
to get/set
values. Any state set this way will automatically be persisted by the default
:load
/:save
implementations, unless the value has a :no-persist
metadata.
To initialize the Trait instance after instantiation, use :post-init
.
Create a subclass of npcs.citizensapi.trait.Trait, `name` is a simple lowercase identifier of the trait like `"sneak"` or `"aggressive"`. `callbacks` is a map from keyword to function (or var, IFn). Callbacks receive `this` (the trait) as first arg. `:load` and `:save` also receive a `DataKey`. Callbacks: `:load`, `:save`, `:on-attach`, `:on-copy`, `:on-despawn`, `:on-pre-spawn`, `:run`, `:save`. Can be called multiple times, subsequent calls will only replace the callbacks. Returns the trait subclass `java.lang.Class`. Note that adding a `:run` callback for a Trait that is already attached to an NPC will not cause it to be called. Remove the Trait from the NPC and add it back. To give your trait state, provide an `:init` key (map or function that returns a map), this will provide your trait's initial state. You can use the trait instance itself as an atom, e.g. call `@this` or `(swap! this ...)` to get/set values. Any state set this way will automatically be persisted by the default `:load`/`:save` implementations, unless the value has a `:no-persist` metadata. To initialize the Trait instance after instantiation, use `:post-init`.
(munge-key k)
Convert keyword to string, replace .
with __
, since .
is a separator
character in Bukkit ConfigurationSections.
Convert keyword to string, replace `.` with `__`, since `.` is a separator character in Bukkit ConfigurationSections.
Coerce a value to the right type after loading based on the :witchcraft/tag
.
Coerce a value to the right type after loading based on the `:witchcraft/tag`.
Prepare a value before persistence, should return either the value unchanged, or a map with {:witchcraft/tag ... :value ...}
Prepare a value before persistence, should return either the value unchanged, or a map with {:witchcraft/tag ... :value ...}
Registry from trait name to mape of callbacks
Registry from trait name to mape of callbacks
(trait-swap this f)
(trait-swap this f arg)
(trait-swap this f arg1 arg2)
(trait-swap this f x y args)
(trait-swapVals this f)
(trait-swapVals this f arg)
(trait-swapVals this f arg1 arg2)
(trait-swapVals this f x y args)
(update-datakey key m)
Given a DataKey and a (potentially nested) map, store all values in the map on
the datakey, excluding map values that have the :no-persist
metadata.
Given a DataKey and a (potentially nested) map, store all values in the map on the datakey, excluding map values that have the `:no-persist` metadata.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close