class Appsetting < ActiveRecord::Base has_many :sixconfigs six_guid OVERRIDE_MODEL = Appsetting FOLDER = /(.*)\/(.*)/ # Defaults to ArmA2 atm... SPECIFIC = false FRIENDLY_NAME = "ArmA 2 (Any)" DEFAULT_EXE = "arma2.exe" DEFAULT_EXE_PATH = "" DEFAULT_BETA_EXE = "arma2.exe" DEFAULT_BETA_EXE_PATH = "beta" DEFAULT_SERVER_EXE = "arma2server.exe" DEFAULT_SERVER_EXE_PATH = DEFAULT_EXE_PATH # TODO: Auto beta mod even? DEFAULT_PARAMS = "-showScriptErrors -noSplash -noFilePatching" DEFAULT_MODS_PARAM = "-mod=" # TODO DEFAULT_BETA_MODS = ["beta"] STATIC_TYPES = [] GAMESPY_TYPES = ["arma2pc"] GAME_MIN_VERSIONS = ["1.0"] MODS = [] # TODO: Auto enumurate from model properties? # folders: expansion, common, addons # files: arma2.exe, arma2server.exe (-.exe for linux), arma2oa.exe, arma2oaserver.exe, addons/chernarus.pbo FAMILY = Hash.new FAMILY["Arma2"] = [[DEFAULT_EXE, DEFAULT_SERVER_EXE, "#{DEFAULT_BETA_EXE_PATH}/#{DEFAULT_BETA_EXE}"], {"Arma2St" => []}] FAMILY["Arma2Oa"] = [[Arma2OaAppsetting::DEFAULT_EXE, Arma2OaAppsetting::DEFAULT_SERVER_EXE, "#{Arma2OaAppsetting::DEFAULT_BETA_EXE_PATH}/#{Arma2OaAppsetting::DEFAULT_BETA_EXE}"], {"Arma2OaCo" => ["addons/"], "Arma2OaSt" => ["!addons/"]}] # TODO: Windows-only REGKEYS = {"Arma2Oa" => ['SOFTWARE\\Bohemia Interactive Studio\\ArmA 2 OA', 'MAIN'], "Arma2" => ['SOFTWARE\\Bohemia Interactive Studio\\ArmA 2', 'MAIN']} def to_updater_yml hash = Hash.new attribute_names.each do |at| i = at.to_s i = "app_#{i}" value = eval(at) hash[i.to_sym] = value unless value.nil? || value.to_s.size == 0 end hash[:app_path] = self.real_path unless hash[:app_path] hash[:app_exe] = self.real_exe unless hash[:app_exe] hash[:mods] = self.modfolders.join(";").gsub("/", "\\") hash end def label ar = [] return self.name unless self.beta || self.server ar << "Beta" if self.beta ar << "Server" if self.server "#{self.name} (#{ar.join(", ")})" end def self.label #self.to_s.sub("Appsetting", "") self::FRIENDLY_NAME end def self.short self.to_s.sub("Appsetting", "") end def self.types return [Arma2Appsetting] if self == Appsetting t, e = [], self until e.nil? || [Appsetting, ActiveRecord::Base].include?(e) do t << e e = e.superclass end t += self::STATIC_TYPES t.uniq! t end def self.default_path return @mpath unless @mpath.nil? @mpath = nil self::REGKEYS.each_pair do |k, v| @mpath = begin; Win32::Registry.open(Win32::Registry::HKEY_LOCAL_MACHINE, v[0])[v[1]]; rescue; nil; end break if @mpath end @mpath end def edition(force = true) ed = self.detect_edition ed = self.class if ed.nil? && force ed end def explore SixUpdaterWeb.run_program("explorer.exe", SixUpdaterWeb::BASE_PATH, self.real_path) end def nice_edition t = self.edition(false) t ? t.label : "ERROR: None detected" end def found_types t = self.edition(false) t ? t.types : [] end # TODO: Linux auto cut of '.exe' ? def self.beta_server_exe() self::DEFAULT_BETA_EXE_PATH.empty? ? self::DEFAULT_SERVER_EXE : "#{self::DEFAULT_BETA_EXE_PATH}/#{self::DEFAULT_SERVER_EXE}" end def self.server_exe() self::DEFAULT_SERVER_EXE_PATH.empty? ? self::DEFAULT_SERVER_EXE : "#{self::DEFAULT_SERVER_EXE_PATH}/#{self::DEFAULT_SERVER_EXE}" end def self.beta_exe() self::DEFAULT_BETA_EXE_PATH.empty? ? self::DEFAULT_BETA_EXE : "#{self::DEFAULT_BETA_EXE_PATH}/#{self::DEFAULT_BETA_EXE}" end def self.normal_exe() self::DEFAULT_EXE_PATH.empty? ? self::DEFAULT_EXE : "#{self::DEFAULT_EXE_PATH}/#{self::DEFAULT_EXE}" end def any_exe? ed = self.class::SPECIFIC ? self.class : self.edition (!self.exe.nil? && File.exists?(File.join(self.real_path, self.exe))) || File.exists?(File.join(self.real_path, ed.normal_exe)) || File.exists?(File.join(self.real_path, ed.server_exe)) || File.exists?(File.join(self.real_path, ed.beta_exe)) || File.exists?(File.join(self.real_path, ed.beta_server_exe)) end def real_exe return self.exe unless self.exe.nil? return nil unless self.edition() if self.server self.beta ? self.edition.beta_server_exe : self.edition.server_exe else self.beta ? self.edition.beta_exe : self.edition.normal_exe end end def real_path self.path.nil? ? self.class.default_path : self.path end def default_params self.edition.nil? ? nil : self.edition::DEFAULT_PARAMS end def real_params self.params.nil? ? self.default_params : self.params end def real_modpath self.modpath.nil? ? self.real_path : self.modpath end def real_logpath if self.logpath.nil? case RUBY_PLATFORM when /-mingw32$/, /-mswin32$/ "#{File.join(ENV['USERPROFILE'], 'appdata', 'local', 'arma 2')}" else nil end else self.logpath end end def detect_edition # TODO: Read the appsetting.exe to figure out an edition, as a static setting by the user? return @det_ed unless @det_ed.nil? return nil if self.real_path.nil? return nil unless File.directory?(self.real_path) if self.class::SPECIFIC return self.any_exe? ? self.class : nil end game = nil self.class::FAMILY.each_pair do |key, value| found = false # Find game value[0].each do |e| case e when /\/$/ # folder found = File.directory?(File.join(self.real_path, e)) else # file case RUBY_PLATFORM when /-mingw32$/, /-mswin32$/ else e = e.clone e.sub!(/\.exe$/, "") end found = File.exists?(File.join(self.real_path, e)) end break if found end next unless found game = key # Find edition ed, found, cond = nil, nil, true value[1].each_pair do |edition, conditions| ed = edition conditions.each do |condition| c = condition.clone reverse = c.sub!(/^!/, "") case c when /\/$/ # folder found = File.directory?(File.join(self.real_path, c)) else # file case RUBY_PLATFORM when /-mingw32$/, /-mswin32$/ else c = c.clone c.sub!(/\.exe$/, "") end found = File.exists?(File.join(self.real_path, c)) end cond = reverse ? !found : found break if cond end game = ed if cond next unless cond end end return nil unless game @det_ed = Object.const_get("#{game}Appsetting") @det_ed end def allowance(signatures) signatures = signatures.map{|e| e.downcase} allowed, disallowed, garbage = [], [], [] path = self.real_path.gsub("\\", "/") pbos = Dir[File.join(path, "**", "*.pbo")] pbos.each do |p| inter = p.sub("#{path}/", "") unless inter =~ /\/(addons|dta)\//i || inter =~ /^common\//i || inter =~ /^(addons|dta)\//i garbage << inter next end if signatures.empty? allowed << inter next end sigs = Dir["#{p}*.bisign"] found = false sigs.each do |s| sig = s.sub("#{p}.", "").sub(".bisign", "").downcase if signatures.include?(sig) found = true allowed << inter break end end disallowed << inter unless found end [allowed, disallowed, garbage] end def process_name ex = self.real_exe return nil unless ex File.basename(ex) end def full_path rp = self.real_path return nil if rp.nil? File.dirname(File.join(rp, self.real_exe)).gsub("\\", "/") end def processes Six::Appmanager.find_process(self.process_name, self.full_path) end def read_logfile Six::Appmanager.read_logfile logfile unless logfile.nil? end def kill! Six::Appmanager.kill_by_name(self.process_name, self.full_path) end def rpt process_name[/(.*)\./] "#{$1}.rpt" end def logfile if File.directory?(real_logpath) File.join(real_logpath, rpt) if File.exists?(File.join(real_logpath, rpt)) else nil end end def modfolders if self.beta self.edition::DEFAULT_BETA_MODS else [] end end end