Advertisement
M3rein

Plugin Manager

Jun 28th, 2020
1,852
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 7.61 KB | None | 0 0
  1. module PluginManager
  2.   MBOX = Win32API.new('user32', 'MessageBox', ['I','P','P','I'], 'I')
  3.  
  4.   @@Plugins = {}
  5.  
  6.   def self.register(options)
  7.     name = nil
  8.     version = nil
  9.     link = nil
  10.     dependencies = nil
  11.     order = [:name, :version, :link, :dependencies, :incompatibilities]
  12.     keys = options.keys.sort { |a, b| order.index(a) || order.size <=> order.index(b) || order.size }
  13.     for key in keys
  14.       value = options[key]
  15.       case key
  16.       when :name
  17.         if nil_or_empty(value)
  18.           self.error "Plugin name must be a non-empty string."
  19.         end
  20.         if !@@Plugins[value].nil?
  21.           self.error "Plugin by the name of '#{value}' already exists."
  22.         end
  23.         name = value
  24.       when :version
  25.         if nil_or_empty(value)
  26.           self.error "Plugin version must be a string."
  27.         end
  28.         version = value
  29.       when :link
  30.         if nil_or_empty(value)
  31.           self.error "Plugin link must be a string."
  32.         end
  33.         link = value
  34.       when :dependencies
  35.         dependencies = value
  36.         dependencies = [dependencies] if !dependencies.is_a?(Array) || !dependencies[0].is_a?(Array)
  37.         for dep in value
  38.           if dep.is_a?(String)
  39.             if !self.installed?(dep)
  40.               self.error "Plugin '#{name}' requires plugin '#{dep}' to be installed."
  41.             end
  42.           elsif dep.is_a?(Array)
  43.             if dep.size == 1
  44.               if dep[0].is_a?(String)
  45.                 dep_name = dep[0]
  46.                 if !self.installed?(dep_name)
  47.                   self.error "Plugin '#{name}' requires plugin '#{dep_name}' to be installed."
  48.                 end
  49.               else
  50.                 self.error "Expected the plugin name as a string, but got #{dep[0].inspect}."
  51.               end
  52.             elsif dep.size == 2
  53.               if dep[0].is_a?(Symbol)
  54.                 self.error "Cannot specify dependency version check modifier without specifying a version."
  55.               elsif dep[0].is_a?(String) && dep[1].is_a?(String)
  56.                 dep_name = dep[0]
  57.                 dep_version = dep[1]
  58.                 if self.installed?(dep_name, dep_version)
  59.                 elsif self.installed?(dep_name)
  60.                   msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or later, " +
  61.                       "but the installed version is #{self.version(dep_name)}."
  62.                   if dep_link = self.link(dep_name)
  63.                     msg += "\n\nThe plugin may be updated from: #{dep_link}"
  64.                   end
  65.                   self.error msg
  66.                 else
  67.                   self.error "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} or later " +
  68.                       "to be installed."
  69.                 end
  70.               end
  71.             elsif dep.size == 3
  72.               if !dep[0].is_a?(Symbol)
  73.                 self.error "Expected first dependency argument to be a symbol, but got #{dep[0].inspect}."
  74.               end
  75.               if !dep[1].is_a?(String)
  76.                 self.error "Expected second dependency argument to be a plugin name, but got #{dep[1].inspect}."
  77.               end
  78.               if !dep[2].is_a?(String)
  79.                 self.error "Expected third dependency argument to be the plugin version, but got #{dep[2].inspect}."
  80.               end
  81.               dep_arg = dep[0]
  82.               dep_name = dep[1]
  83.               dep_version = dep[2]
  84.               optional = false
  85.               exact = false
  86.               if dep_arg == :optional || dep_arg == :exact || dep_arg == :optional_exact
  87.                 optional = dep_arg == :optional || dep_arg == :optional_exact
  88.                 exact = dep_arg == :exact || dep_arg == :optional_exact
  89.               else
  90.                 self.error "Expected first dependency argument to be one of :optional, :exact or :optional_exact, "  +
  91.                     "but got #{dep_arg.inspect}."
  92.               end
  93.               type = :gteq
  94.               type = :eq if exact
  95.               if optional
  96.                 if self.installed?(dep_name) && !self.installed?(dep_name, dep_version, type)
  97.                   msg = "Plugin '#{name}' requires plugin '#{dep_name}', if installed, to be version #{dep_version}"
  98.                   msg << " or later " if !exact
  99.                   msg << ", but the installed version was #{self.version(dep_name)}."
  100.                   if dep_link = self.link(dep_name)
  101.                     msg << "\n\nThe plugin may be updated from: #{dep_link}"
  102.                   end
  103.                   self.error msg
  104.                 end
  105.               else
  106.                 if self.installed?(dep_name, dep_version, type)
  107.                 elsif self.installed?(dep_name)
  108.                   msg = "Plugin '#{name}' requires plugin '#{dep_name}' to be version #{dep_version}"
  109.                   msg << " or later " if !exact
  110.                   msg << ", but the installed version was #{self.version(dep_name)}."
  111.                   if dep_link = self.link(dep_name)
  112.                     msg << "\n\nThe plugin may be updated from: #{dep_link}"
  113.                   end
  114.                   self.error msg
  115.                 else
  116.                   msg = "Plugin '#{name}' requires plugin '#{dep_name}' version #{dep_version} "
  117.                   msg << "or later " if !exact
  118.                   msg << "to be installed."
  119.                   self.error msg
  120.                 end
  121.               end
  122.             end
  123.           end
  124.         end
  125.       when :incompatibilities
  126.         incompats = value
  127.         incompats = [incompats] if !incompats.is_a?(Array)
  128.         for incompat in incompats
  129.           if self.installed?(incompat)
  130.             self.error "Plugin '#{name}' is incompatible with '#{incompat}'. They cannot both be used at the same time."
  131.           end
  132.         end
  133.       else
  134.         self.error "Invalid plugin registry key '#{key}'."
  135.       end
  136.     end
  137.     @@Plugins[name] = {
  138.       :name => name,
  139.       :version => version,
  140.       :link => link,
  141.       :dependencies => dependencies
  142.     }
  143.   end
  144.  
  145.   def self.error(msg)
  146.     Graphics.update
  147.     t = Thread.new do
  148.       MBOX.call(Win32API.pbFindRgssWindow, msg, "Plugin Error", 0x10)
  149.       Thread.exit
  150.     end
  151.     while t.status
  152.       Graphics.update
  153.     end
  154.     Kernel.exit! true
  155.   end
  156.  
  157.   def self.installed?(plugin_name, plugin_version = nil, compare_type = :gteq)
  158.     plugin = @@Plugins[plugin_name]
  159.     return false if plugin.nil?
  160.     return true if plugin_version.nil?
  161.     comparison = compare_versions(plugin[:version], plugin_version)
  162.     return true if compare_type == :gteq && comparison >= 0
  163.     return true if compare_type == :eq && comparison == 0
  164.   end
  165.  
  166.   def self.version(plugin_name)
  167.     return if !installed?(plugin_name)
  168.     return @@Plugins[plugin_name][:version]
  169.   end
  170.  
  171.   def self.link(plugin_name)
  172.     return if !installed?(plugin_name)
  173.     return @@Plugins[plugin_name][:link]
  174.   end
  175.  
  176.   def self.nil_or_empty(string)
  177.     return string.nil? || !string.is_a?(String) || string.size == 0
  178.   end
  179.  
  180.   def self.compare_versions(v1, v2)
  181.     d1 = v1.split("")
  182.     d1.insert(0, "0") if d1[0] == "."
  183.     while d1[-1] == "."; d1 = d1[0..-2]; end
  184.     d2 = v2.split("")
  185.     d2.insert(0, "0") if d2[0] == "."
  186.     while d2[-1] == "."; d2 = d2[0..-2]; end
  187.     for i in 0...[d1.size, d2.size].max
  188.       c1 = d1[i]
  189.       c2 = d2[i]
  190.       if c1
  191.         if c2
  192.           if c1.to_i(16) > c2.to_i(16)
  193.             return 1
  194.           elsif c1.to_i(16) < c2.to_i(16)
  195.             return -1
  196.           end
  197.         else
  198.           return 1
  199.         end
  200.       else
  201.         if c2
  202.           return -1
  203.         end
  204.       end
  205.     end
  206.     return 0
  207.   end
  208. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement