=begin--------------------------------------------------------------------------------Author: Tyler KendrickTitle: Kendrick - CoreVersion: v0.9.2 Language: RGSS3Framework: RPG Maker VX AceGit: [URL="https://github.com/TylerKendrick/rmvxa--------------------------------------------------------------------------------=end%24imported"]https://github.com/TylerKendrick/rmvxa--------------------------------------------------------------------------------=end$imported[/URL] ||= {}$imported['Kendrick::Core'] = 'v0.9.2' # Note: The Kendrick Module will contain all Kendrick scripts and addons as a # namespace prefix.module Kendrick # Note: Simplifies access for registering scripts. def self.require(values = {}) Core.require(values) end # Note: This module exists to build and provide common errors. module Errors class << self def build_errors { missing_method: -> (context, method) { method ||= caller[0][/`.*'/][1..-2] # putting this in an actual Module#method destroys caller values. missing_method(context, method) }, missing_script: method(:missing_script) } end def missing_method(context, method) ::NotImplementedError.new("#{method} must be implemented on #{context}") end def missing_script(*args) name, value, errorNo = args ::ScriptError.new case errorNo when :exact_version then "missing script: #{name} #{value}" when :min_version then "script: #{name} requires minimum version #{value}" when :range_version then "script: #{name} must be between version range #{value.to_s}" when :bool_include then "script: #{name} #{value ? 'should' : 'shouldn\'t'} be included." else "There was an error parsing the dependency: #{name}" end end def [](index) @@errors[index] end end # class << self @@errors = ::Kendrick::Errors.build_errors # This method is called by implemented classes to raise a common error. def error(key, *args) ::Kendrick::Errors[key].call(self, args) end end # Kendrick::Error # Note: This object contains the majority of data structures in use by # derived Kendrick Scripts. module Core include Kendrick::Errors @@scripts = {} Load_Method = :load_resources def self.load_data(path, result) result.tap { |r| result.is_a?(::Array) ? result.compact.each { |x| x.try_method(Load_Method) } : result.try_method(Load_Method) } end # This method is used to ensure dependencies are included before loading # assets and data. def self.preload_database resolve_dependencies { |name, value, errorNo| ::Kendrick::Errors[:missing_script].call(name, value, errorNo) } end # Reserved for aliasing. def self.load_database end # This method is called by implemented classes to register a dependency. def self.require(values = {}) values.each { |key, value| @@scripts[key] ||= [] @@scripts[key] << value unless item.include?(@@scripts[key]) } end # This method is called by Kendrick::Core to handle dependencies. def self.resolve_dependencies(&on_error) @@scripts.all? { |key, values| values.all? { |value| resolve_dependency(key, value, &on_error) } } end # Determines how to handle individual dependencies def self.resolve_dependency(name, value, &on_error) !$imported.has_key?(name).tap { |has_error| on_error.call(name, value) if has_error && on_error } end end # Kendrick::Core # Note: This class simply wraps a method for unsubscription from observables. class Observer def initialize(&method) @method = method end def call(*args, &block) @method.call(*args, &block) end end # Kendrick::Observer # Note: This module allows for notifications to be sent to observers. module Observable def create_observer(&method) Observer.new(&method) end # Provide a method, lambda, anonymous method, proc, or callback. def subscribe(&method) create_observer(&method).tap { |observer| (@observers ||= []) << observer } end # Stops the observer from listening to notifications. def unsubscribe(observer) @observers.delete(observer) end protected # Sends notifications to all registered observers. def notify(*args, &block) notify_all(@observers, *args, &block) end # Iterates through each observer to invoke #notify_observer. def notify_all(observers, *args, &block) @observers.all? { |observer| notify_observer(observer, *args, &block) } end # Invokes the observer with an optional callback that can be overloaded. def notify_observer(observer, *args, &block) observer.call(*args, &block) end end # Kendrick::Observable end # Kendrick # ::Game_BaseItemclass ::Game_BaseItem # This field doesn't have a public accessor. def id() @item_id endend # ::Game_BaseItem # ::Game_Battlerclass ::Game_Battler # Determines if #current_action returns an ::RPG::Item instance. def item? current_action._?(:item)._?(:is_a?, ::RPG::Item) end # Determines if #current_action returns an ::RPG::Skill instance. def skill? current_action._?(:item)._?(:is_a?, ::RPG::Skill) end # Obtains the last used skill. def skill $data_skills[(skill? ? current_action.item : last_skill).id] end # Simplifies accessibility between classes "Game_Actor" and "Game_Enemy". def data if actor? actor elsif enemy? enemy end end end # ::Game_Battler # ::DataManagermodule ::DataManager class << self alias :kendrick_load_database :load_database # Invokes the original #load_database with the new callback idiom. def load_database @callee ||= callee(:kendrick_load_database, { before: -> (*args) { Kendrick::Core.preload_database }, complete: -> (status) { Kendrick::Core.load_database } }) @callee.call end alias :registrar_load_data :load_data # Allows classes generated by #load_data to be intercepted on creation if # they implement #load_resources. This is neccessary because Marshal loaded # objects don't call initialize and, therefore, cannot be overridden. def load_data(path) Kendrick::Core.load_data(path, registrar_load_data(path)) end end # class << selfend # ::DataManager # ::Kernalclass ::Kernal # Tries to invoke a method if the context responsds to the symbol. def self.try_method(context, method, *args, &block) result = false context.respond_to?(method).tap { |c| if c result = context.send(method, *args) block.call(result) if block end } end # Evaluates text and returns the expression as a lambda. def self.eval_method(text, *args) parameters = (args ||= []).join(',') eval "-> (#{parameters}) { #{text} }" end end # ::Kernal # ::Objectclass ::Object # Obtains a method as a new Callee instance. def callee(symbol, hash={}, &callback) method(symbol).to_callee(hash, &callback) end # Allows for safe navigation. Simplifies null coalescing index expressions. def maybe(*args, &block) is_a?(::NilClass) || !respond_to?(args.first) ? nil : send(*args, &block) end alias :_? :maybe # Invokes ::Kernal#try_method with the caller provided as the current context. def try_method(method, *args, &block) ::Kernal.try_method(self, method, *args, &block) end # Invokes ::Boolean#convert with the caller provided as the current context. def to_b ::Boolean.convert(self) end # Simplifies multiple assignment operations as explicit block expressions. def as yield self end end # ::Object # ::Calleeclass ::Callee < ::Kendrick::Observer # Creates and registers a new callback for the target method. def subscribe(hash = {}, &options) @callbacks ||= [] ::Callback.new(hash, &options).tap { |callback| @callbacks << callback } end # Invokes a target method with exception handling provided by an options hash. def call(*args, &block) status = :not_modified if @callbacks.all? { |x| x.before(*args) } begin @callbacks.each { |x| x.success(super(*args, &block)) } status = :success rescue Exception => e @callbacks.each { |x| x.error(e, :error) } status = :error end end @callbacks.each { |x| x.complete(status) } end end # ::Callee # ::Callbackclass Callback def self.options(hash = {}, &block) Options.new(hash).tap { |options| block.call(options) if block } end def initialize(hash = {}, &block) @options = Callback.options(hash, &block) end def before(*args) @options.before.call(*args) end def error(*args) @options.error.call(*args) end def success(*args, &block) @options.success.call(*args) end def complete(*args, &block) @options.complete.call(*args) end end # ::Callback # Provides a common idiom for callback structures.class ::Callback::Options def self.before(*args) true end def self.error(error, type) raise error end def self.success(data = nil) data end def self.complete(status) status end Hash = { before: method(:before), error: method(:error), success: method(:success), complete: method(:complete) } def initialize(options = {}) options = ::Callback::Options::Hash.merge(options || {}) @before = options[:before] @error = options[:error] @success = options[:success] @complete = options[:complete] end def before(&before) @before = before ? before : @before end def error(&error) @error = error ? error : @error end def success(&success) @success = success ? success : @success end def complete(&complete) @complete = complete ? complete : @complete end end module Function def to_callee(hash={}, &options) ::Callee.new(&self).tap { |callee| callee.subscribe(hash, &options) } end end Method.send(:include, Function)Proc.send(:include, Function) class Symbol def to_callee(hash = {}, &options) to_proc.to_callee(hash, &options) end end # This module just makes handling and parsing booleans much easier.module ::Boolean # Be explicit about booleans, 0 isn't false here, don't treat it as such. @@true_strings = %w(true t) @@false_strings = %w(false f) # Attempts a custom, overloadable, conversion of objects to ::Boolean. def self.convert(object) case object when ::Numeric then object != 0 when ::String then @@true_strings.include?(object.downcase) # We can assume others are false else !!object end #case end #self.convert end # ::Boolean TrueClass.send(:include, ::Boolean)FalseClass.send(:include, ::Boolean) # This global method returns evaluated text as an anonymous Proc.def eval_method(text, *args) ::Kernal.eval_method(text, *args)end