Teil 1 Code: #-------------------------------------------------------------------------- # * Benötigte Methoden #-------------------------------------------------------------------------- class Class #-------------------------------------------------------------------------- # * Erzeugt alternative Namen für eine Methode -KD #-------------------------------------------------------------------------- def link(methode, *namen) namen.each {|n| define_method(n) {|*a| method(methode).call(*a)}} end def link_classmethod(methode, *namen) $methode = methode namen.each {|n| $n = n class << self methode, n = $methode, $n define_method(n) {|*a| self.method(methode).call(*a)} end } $methode = nil $n = nil end end class Array #-------------------------------------------------------------------------- # * Addiert zwei Arrays ohne doppelte o. leere Elemente hinzuzufügen -KD #-------------------------------------------------------------------------- def add(*args) args.each {|e| push(e) unless include?(e) or e.empty?} end end class Hash #-------------------------------------------------------------------------- # * Sucht nach einem passenden Key für einen Value/Suchblock -KD #-------------------------------------------------------------------------- def key_for_value(search_value) key = nil ergebnis = each_pair {|key, value| break if if block_given? then yield(value, search_value) else value == search_value end true } if ergebnis then false else key end end end class Symbol #-------------------------------------------------------------------------- # * Macht ein Symbol zu einem Instanzvariablensymbol -KD #-------------------------------------------------------------------------- def to_isym return ('@' + self.to_s).to_sym end end class Fixnum #-------------------------------------------------------------------------- # * Liefert einen String mit einer n-stellen Zahl. -KD #-------------------------------------------------------------------------- def zu_nstelligen_string(n) vor = "" (n-1).downto(0) {|stelle| vor = vor.concat('0') if self < 10**stelle } vor.concat(self.to_s) end end class Float #-------------------------------------------------------------------------- # * Gibt Datengröße an. -KD #-------------------------------------------------------------------------- EINHEITEN = ["byte", "kb", "mb", "gb"] def datasize size = self; counter = 0 while counter < EINHEITEN.size-1 and (a=size / 1024) >= 0.1 size = a; counter += 1; end size.to_s + ' ' + EINHEITEN[counter] end end class File #-------------------------------------------------------------------------- # * Überprüft, ob der Dateiname auf eine Ressourcendatei zeigt -KD #-------------------------------------------------------------------------- def self.ressource?(pfad, *possible_endings) pfad =~ /.+\.(.+)/ !(possible_endings.find {|e| e == $1}).nil? end #-------------------------------------------------------------------------- # * Erzeugt einen Ordner - WATANABE, Hirofumi (Ruby Standard Library) #-------------------------------------------------------------------------- def self.makedirs(*dirs) verbose = if dirs[-1].is_a? String then false else dirs.pop end mode = 0755 for dir in dirs parent = dirname(dir) next if parent == dir or directory? dir makedirs parent unless directory? parent $stderr.print "mkdir ", dir, "\n" if verbose if basename(dir) != "" begin Dir.mkdir dir, mode rescue SystemCallError raise unless directory? dir end end end end #-------------------------------------------------------------------------- # * Sucht nach Dateien - (Ruby Standard Library) #-------------------------------------------------------------------------- def self.find(*paths) paths.collect!{|d| d.dup} while file = paths.shift catch(:prune) do yield file.dup.taint next unless File.exist? file begin if File.lstat(file).directory? then d = Dir.open(file) begin for f in d next if f == "." or f == ".." if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then f = file + f elsif file == "/" then f = "/" + f else f = File.join(file, f) end paths.unshift f.untaint end ensure d.close end end rescue Errno::ENOENT, Errno::EACCES end end end end def self.prune throw :prune end #-------------------------------------------------------------------------- # * Kopiert Dateien -Ruby Standard Library #-------------------------------------------------------------------------- BUFSIZE = 8 * 1024 def self.catname(from, to) if directory? to join to.sub(%r([/\\]$), ''), basename(from) else to end end def self.syscopy(from, to) to = catname(from, to) fmode = stat(from).mode tpath = to not_exist = !exist?(tpath) from = open(from, "rb") to = open(to, "wb") begin while true do to.syswrite from.sysread(BUFSIZE) end rescue EOFError ret = true rescue ret = false ensure to.close from.close end chmod(fmode, tpath) if not_exist ret end end Teil 2 Code: #============================================================================== # ** Ressourcen - von KD #------------------------------------------------------------------------------ # Diese Klasse speichert Ressourcennamen und liest diese aus Projekten aus #============================================================================== class Ressourcen include(Enumerable) #-------------------------------------------------------------------------- # * Konstanten #-------------------------------------------------------------------------- ORDNER = "Data/" #Ordner wo die Daten sich befinden MAPS = "Map" #Dateiname der Maps ENDUNG = ".rxdata" #Dateiendung der Daten LOGPFAD = "/log/" #Pfad der Logdateien LOGNAME = "ressourcen" #Dateiname der Logdatei LOGENDING = '.log' #Dateiendung der Logdateien LOESCHPFAD = "/nicht_benoetigt/" #Pfad für verschobene Ressourcendateien #Konstanten für den Automatik-Vorgang LOGGEN = true #Genutzte Ressourcen werden geloggt MULTI_FILE = false #Ressourcen werden in mehreren Textdateien geloggt LOG_UNUSED = true #Ungenutzte Ressourcen werden extra geloggt LOESCHEN = false #nicht benötigte Ressourcen werden gelöscht EXIT = true #Nach Ausführen des Vorgangs wird Programm beendet LOG_ORDNER = '/unused/'#Logordner für ungenutzte Ressourcen UNUSEDNAME = 'unused' #Dateiname für ungenutzte-Ressourcenlogdatei #-------------------------------------------------------------------------- # * Attribute #-------------------------------------------------------------------------- METADIRECTORY = Hash.new METADIRECTORY['graphics'] = [:characters, :windowskins, :transitions, :fogs, :battlebacks, :panoramas, :windowskins, :characters, :animations, :autotiles, :battlers, :gameovers, :icons, :pictures, :tilesets, :titles] METADIRECTORY['audio'] = [:se, :bgs, :me, :bgm] TYPEN = METADIRECTORY.values.flatten #Attribut Readers -> Metadirectories, Typen, root METADIRECTORY.each_key {|meta| define_method(meta.to_sym) { result = Array.new METADIRECTORY[meta].each {|m| result << self.method(m).call} result.flatten }} attr_reader(:root, *TYPEN) #============================================================================ # ***Initialisierung der Instanzvariablen*** # root#String : Gibt den Pfad zum Projektordner an #============================================================================ def initialize(root='.') TYPEN.each {|typ| self.instance_variable_set(typ.to_isym, Array.new) } @root = root end #============================================================================ # ***Klassenmethoden*** #============================================================================ #-------------------------------------------------------------------------- # * Definiert Dateiendungen für einen Typ o. Metaordner # klassifizierung#String/Symbol : Metaordner oder Typ der Dateiendung # *extensions#Strings : Name der Dateiendung #-------------------------------------------------------------------------- @@extensions = Hash.new def self.extensions_for(klassifizierung, *extensions) k = klassifizierung.to_s.downcase if @@extensions[k] then @@extensions[k].add(extensions) else @@extensions[k] = extensions end end #-------------------------------------------------------------------------- # * Erzeugt Dateiendungen #-------------------------------------------------------------------------- extensions_for('audio', 'mid', 'ogg', 'wav', 'mp3', 'wma') extensions_for('graphics', 'png', 'bmp', 'jpg') #-------------------------------------------------------------------------- # * Gib Dateiendungen für bestimmten Typ/Metaordner zurück => Array # typ#String/Symbol : Metaordner oder Typ, der gesuchte Dateiendung hat # Standardmäßig werden alle Dateiendungen ausgegeben #-------------------------------------------------------------------------- def self.extensions(typ=true) if (typ==true) then return @@extensions.values.flatten end key = typ.to_s.downcase if @@extensions.has_key?(key) then @@extensions[key] elsif @@extensions.has_key?(n=metadirectory_for(typ).to_s.downcase) @@extensions[n] else [] end end def extensions(t=true); Ressourcen.extensions(t); end #-------------------------------------------------------------------------- # * Gibt den Metaordner für einen Typ aus => nil oder String # typ#Symbol : Typ, dessen Metaordner gesucht wird #-------------------------------------------------------------------------- def self.metadirectory_for(typ) if typ then typ = typ.to_s.downcase.to_sym METADIRECTORY.key_for_value(typ) {|h, s| h.include?(s)} else nil end end def metadirectory_for(typ); Ressourcen.metadirectory_for(typ); end #-------------------------------------------------------------------------- # * Sucht nach Ressourcen, loggt diese und löscht ggf. nicht benötigte #-------------------------------------------------------------------------- def self.automatik() ressourcen = genutzte_ressourcen.sort! if MULTI_FILE then ressourcen.loggen else ressourcen.loggen_one end if LOGGEN if LOG_UNUSED or LOESCHEN then unused = Ressourcen.ungenutzte_ressourcen(ressourcen) end if LOG_UNUSED then if MULTI_FILE then unused.loggen(LOG_ORDNER) else unused.loggen_one(LOGPFAD, UNUSEDNAME) end end if LOESCHEN then unused.verschiebe end exit if EXIT end #-------------------------------------------------------------------------- # * Erzeugt Construktor-Methoden # methode#Symbol : Methode, für die ein Constructor erzeugt wird #-------------------------------------------------------------------------- def self.constructor(methode) $methode = methode class << self; m = $methode; define_method(m) {|*a| root=if a[0].class==String and self.instance_method(m).arity.abs < a.size a.shift else "." end r = self.new(root) r.method(m).call(*a) r } end $methode = nil end #-------------------------------------------------------------------------- # * Erzeugt Constructor und alternative Methodennamen # name#Symbol : Methode, die behandelt wird # *alternatives#Symbole : Alternative Methodennamen #-------------------------------------------------------------------------- def self.constructor_and_alternatives(name, *alternatives) constructor(name) #erzeuge Konstructor für Methode link(name, *alternatives) #alternative namen für Methode link_classmethod(name, *alternatives) #alternative namen für Konstruktor end #============================================================================ # ***Constructor Methoden*** => Ressourcenobjekt # Als Klassenmethoden genutzt erzeugen sie neue Ressourcen-Objekte # root#String : Erzeugt ein Ressourcenobjekt in diesem Projektordner # Als Instanzmethoden genutzt fügen sie dem Objekt neue Ressourcen hinzu #============================================================================ #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus genutzten Ressourcen eines Projektes #-------------------------------------------------------------------------- def genutzte_ressourcen() durchsuche_maps durchsuche_database self end constructor_and_alternatives(:genutzte_ressourcen, :used_ressources) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus importierten Ressourcen eines Projektes #-------------------------------------------------------------------------- def importierte_ressourcen() pfad = @root + '/' #Durchsuche alle Metaordner directories = METADIRECTORY.keys.collect {|e| pfad + e.to_s} dirs = "" METADIRECTORY.keys.each {|d| dirs = dirs.concat('|' + d.to_s)} dirs = dirs.sub('|', '') pfad = ' ' + pfad while a = pfad =~ /[^\\]\./ do pfad[a+1] = '\\.' end while a = pfad =~ /[^\\]\// do pfad[a+1] = '\\/' end pfad[0] = '' regexp = Regexp.new(pfad+"(#{dirs})"+'\/(.+)\/(.+)\..+', true) File.find(*directories) {|pfad| #Wenn gefundene Datei die passende Dateiendung hat.... pfad =~ regexp if File.ressource?(pfad.downcase, *extensions($2)) then #...soll sie in die Liste aufgenommen werden if method(methode=$2.downcase.to_sym) then method(methode).call.add($3) end end } self end constructor_and_alternatives(:importierte_ressourcen, :imported_ressources) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus nichtbenötigten Ressourcen des Projektes # genutzte#Ressourcen : Prozess lässt sich beschleunigen, wenn das # genutzte-Ressourcenobjekt zuvor schon erzeugt wurde #-------------------------------------------------------------------------- def ungenutzte_ressourcen(genutzte=nil) genutzte = Ressourcen.genutzte_ressourcen(@root) unless genutzte importierte_ressourcen() drop(genutzte) end constructor_and_alternatives(:ungenutzte_ressourcen, :unused_ressources) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus einer Map # mapdateiname#String : Pfad zur Mapdatei #-------------------------------------------------------------------------- def durchsuche_map(mappfad) map = load_data(@root+'/'+mappfad) #Suche aus der Map alle Sounddateien heraus bgm.add(map.bgm.name) if map.autoplay_bgm bgm.add(map.bgs.name) if map.autoplay_bgs #Suche aus der Map alle Eventgrafiken heraus events = map.events events.each_value {|event| event.pages.each {|page| characters.add(page.graphic.character_name) #Suche alle Ressourcen aus MoveBefehlen heraus durchsuche_moveroute(page.move_route.list) #Suche alle Ressourcen aus Eventbefehlen heraus durchsuche_eventcommands(page.list) } } self end constructor_and_alternatives(:durchsuche_map, :scan_map) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Mapdaten #-------------------------------------------------------------------------- def durchsuche_maps #Suche in den Maps nach verwendeten Ressourcen i = 1 name = ORDNER + MAPS+i.zu_nstelligen_string(3)+ENDUNG while File.exist?(@root + "/" + name) durchsuche_map(name) i += 1 name = ORDNER + MAPS+i.zu_nstelligen_string(3)+ENDUNG end self end constructor_and_alternatives(:durchsuche_maps, :scan_maps) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Move-Routes # move_list#RPG::MoveCommand-Array : Move-Commands die durchsucht werden #-------------------------------------------------------------------------- def durchsuche_moveroute(move_liste) move_liste.each {|befehl| case befehl.code when 41 characters.add(befehl.parameters[0]) when 44 bgs.add(befehl.parameters[0].name) when 45 durchsuche_script(befehl.parameters[0]) end } self end constructor_and_alternatives(:durchsuche_moveroute, :scan_moveroute) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Event Commands # liste#RPG::EventCommand-Array : EventCommands die durchsucht werden #-------------------------------------------------------------------------- def durchsuche_eventcommands(liste) rubystring = "" messagestring = "" commentstring = "" liste.each {|befehl| case befehl.code when 101, 401 messagestring += "\n" + befehl.parameters[0] when 108, 408 commentstring += "\n" + befehl.parameters[0] when 111 if befehl.parameters[4] == 12 rubystring + "\n" + befehl.parameters[1] end when 131 windowskins.add(befehl.parameters[0]) when 132 bgm.add(befehl.parameters[0].name) when 133 me.add(befehl.parameters[0].name) when 204 case befehl.parameters[0] when 0 then panoramas.add(befehl.parameters[1]) when 1 then fogs.add(befehl.parameters[1]) when 2 then battlebacks.add(befehl.parameters[1]) end when 209 durchsuche_moveroute(befehl.parameters[1].list) when 222 transitions.add(befehl.parameters[0]) when 231 pictures.add(befehl.parameters[1]) when 241 bgm.add(befehl.parameters[0].name) when 245 bgs.add(befehl.parameters[0].name) when 249 me.add(befehl.parameters[0].name) when 250 se.add(befehl.parameters[0].name) when 322 characters.add(befehl.parameters[1]) battlers.add(befehl.parameters[3]) when 355 rubystring.concat(befehl.parameters[0]) when 655 rubystring.concat(befehl.parameters[0]) end } durchsuche_script(rubystring) durchsuche_message(messagestring) durchsuche_comment(commentstring) self end constructor_and_alternatives(:durchsuche_eventcommands, :scan_eventcommands) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Rubyscripts (unvollständig) # string#String : String aus Rubyscripten, der durchsucht wird #-------------------------------------------------------------------------- def durchsuche_script(string) self end constructor_and_alternatives(:durchsuche_script, :scan_script) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Messagescripts (unvollständig) # string#String : String aus Messages, der durchsucht wird #-------------------------------------------------------------------------- def durchsuche_message(string) self end constructor_and_alternatives(:durchsuche_script, :scan_script) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Commentcripts (unvollständig) # string#String : String aus Comments, der durchsucht wird #-------------------------------------------------------------------------- def durchsuche_comment(string) self end constructor_and_alternatives(:durchsuche_script, :scan_script) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Informationen der Database #-------------------------------------------------------------------------- def durchsuche_database #Actors datei = load_data("#{@root}/Data/Actors.rxdata") datei.each {|actor| next unless actor characters.add(actor.character_name) battlers.add(actor.battler_name) } #Skills und Items datei = load_data("#{@root}/Data/Skills.rxdata") + load_data("#{@root}/Data/Items.rxdata") datei.each {|e| next unless e icons.add(e.icon_name) se.add(e.menu_se.name) } #Weapons und armors datei = load_data("#{@root}/Data/Weapons.rxdata") + load_data("#{@root}/Data/Armors.rxdata") datei.each {|e| next unless e icons.add(e.icon_name) } #Enemies datei = load_data("#{@root}/Data/Enemies.rxdata") datei.each {|e| next unless e battlers.add(e.battler_name) } #Battle-Events datei = load_data("#{@root}/Data/Troops.rxdata") datei.each {|e| next unless e e.pages.each {|page| durchsuche_eventcommands(page.list) } } #Animations datei = load_data("#{@root}/Data/Animations.rxdata") datei.each {|e| next unless e animations.add(e.animation_name) e.timings.each {|time| se.add(time.se.name)} } #Tilesets datei = load_data("#{@root}/Data/Tilesets.rxdata") datei.each {|e| next unless e tilesets.add(e.tileset_name) autotiles.add(*e.autotile_names) panoramas.add(e.panorama_name) fogs.add(e.fog_name) battlebacks.add(e.battleback_name) } #CommonEvents datei = load_data("#{@root}/Data/CommonEvents.rxdata") datei.each {|e| next unless e durchsuche_eventcommands(e.list) } #System datei = load_data("#{@root}/Data/System.rxdata") windowskins.add(datei.windowskin_name) titles.add(datei.title_name) gameovers.add(datei.gameover_name) windowskins.add(datei.windowskin_name) transitions.add(datei.battle_transition) bgm.add(datei.title_bgm.name) bgm.add(datei.battle_bgm.name) me.add(datei.battle_end_me.name) me.add(datei.gameover_me.name) se.add(datei.cursor_se.name) se.add(datei.decision_se.name) se.add(datei.cancel_se.name) se.add(datei.buzzer_se.name) se.add(datei.equip_se.name) se.add(datei.shop_se.name) se.add(datei.save_se.name) se.add(datei.load_se.name) se.add(datei.battle_start_se.name) se.add(datei.escape_se.name) se.add(datei.actor_collapse_se.name) se.add(datei.enemy_collapse_se.name) battlebacks.add(datei.battleback_name) battlers.add(datei.battler_name) self end constructor_and_alternatives(:durchsuche_database, :scan_database) #============================================================================ # ***Öffentliche Instanzmethoden*** #============================================================================ #-------------------------------------------------------------------------- # * Sortiert ein Ressourcenobjekt => Ressourcen #-------------------------------------------------------------------------- def sort! TYPEN.each {|typ| array = self.instance_variable_get(typ.to_isym) array.sort! } self end #-------------------------------------------------------------------------- # * Gibt jene Ressourcentypen zurück, die nicht leer sind => Symbol-Array #-------------------------------------------------------------------------- def typen TYPEN.find_all {|t| !self.instance_variable_get(t.to_isym).empty?} end #-------------------------------------------------------------------------- # * Addition zweier Ressourcenobjekte => Ressourcen # other#Ressourcen : Summant, mit dem das Ressourcenobjekt addiert wird #-------------------------------------------------------------------------- def concat(other) TYPEN.each {|typ| typ = typ.to_isym self.instance_variable_get(typ).add(*other.instance_variable_get(typ)) } self end #-------------------------------------------------------------------------- # * Subtraktion zweier Ressourcenobjekte => Ressourcen # other#Ressourcen : Subtrahend , mit dem subtrahiert wird #-------------------------------------------------------------------------- def drop(other) TYPEN.each {|typ| typ = typ.to_isym v = self.instance_variable_get(typ) - other.instance_variable_get(typ) self.instance_variable_set(typ, v) } self end #-------------------------------------------------------------------------- # * Schnittmenge zweier Ressourcenobjekte => Ressourcen # other#Ressourcen : Vergleichsressourcenobjekt #-------------------------------------------------------------------------- def compare(other) ressi = Ressourcen.new(@root) TYPEN.each {|typ| ressi.method(typ).call.add( *method(typ).call & other.method(typ).call) } ressi end #-------------------------------------------------------------------------- # * Loggt die Ressourcen in verschiedenen Textdateien # ordner#String : Pfad zum Log-Ordner # dateiende#String : Dateiende der Logdateien #-------------------------------------------------------------------------- def loggen(ordner=LOGPFAD, dateiende=LOGENDING) File.makedirs(@root + '/' + ordner) TYPEN.each {|typ| liste = self.instance_variable_get(typ.to_isym) next if liste.empty? File.open(path + ordner + typ.to_s + dateiende, 'w+') {|file| liste.each {|name| file.write(name + "\n") } } } end #-------------------------------------------------------------------------- # * Loggt die Ressourcen in einer Textdatei # ordner#String : Pfad zum Log-Ordner # dname#String : Name der Logdatei # dateiende#String : Dateiende der Logdatei #-------------------------------------------------------------------------- def loggen_one(ordner=LOGPFAD, dname=LOGNAME, dateiende=LOGENDING) File.makedirs(@root+'/' + ordner) sortierer = Proc.new {|a,b| a.to_s <=> b.to_s} File.open(@root + '/' + ordner + dname + dateiende, 'w+') {|file| TYPEN.sort(&sortierer).each {|typ| liste = self.instance_variable_get(typ.to_isym) next if liste.empty? file.write(typ.to_s.capitalize + "\n") liste.each {|name| file.write(name + "\n") } file.write("\n") } } end #-------------------------------------------------------------------------- # * Erzeugt die Ordner und ermitteln dest und src Pfade (Privat!) #-------------------------------------------------------------------------- def ordner_erzeugen(path, *args, &block) #Iteriere jeden Metaordner METADIRECTORY.each_pair {|ordner, typen| next if method(ordner.to_sym).call.empty? #Lege einen Ordner für diesen META an, falls noch nicht geschehen File.makedirs(dest_pfad = (path+'/'+ordner.capitalize)) src_pfad = @root + '/' + ordner.capitalize #Iteriere die Typen jedes Metaordners typen.each {|typ| next if (inhalt=method(typ).call).empty? styp = typ.to_s.capitalize #Lege einen Ordner für diesen Typ an, falls noch nicht geschehen File.makedirs(dest_typpfad = dest_pfad + '/' + styp) src_typpfad = src_pfad + '/' + styp #Iteriere die Ressourcen eines Types inhalt.each {|e| #Ermittle vollständigen Dateinamen der Ressource src_name = src_typpfad + "/" + e endung = "" next if Ressourcen.extensions(typ).each {|endung| if File.exist?(src_name + '.' + endung) then break end } src_name = src_name + '.' + endung dest_name = dest_typpfad + '/' + e + '.' + endung #Führe den Proc aus block.call(src_name, dest_name, *args) } } } end private(:ordner_erzeugen) #-------------------------------------------------------------------------- # * Verschiebt Ressourcen in einen extra Ordner # lpfad#String : Pfad zum Ordner, zu dem verschoben wird #-------------------------------------------------------------------------- def verschiebe(lpfad=LOESCHPFAD) lpfad = lpfad.root if lpfad.instance_of?(Ressourcen) ordner_erzeugen(@root + '/' + lpfad) {|src, dest| File.rename(File.expand_path(src), File.expand_path(dest)) } end link(:verschiebe, :move) #-------------------------------------------------------------------------- # * Kopiert Ressourcen in ein anderes Projekt # zielpfad#String/Ressourcen : Zielordner, in das Ressourcen kopiert werden # Ressourcenobjekt, in dessen Root kopiert wird #-------------------------------------------------------------------------- def kopiere(zielpfad) zielpfad = zielpfad.root if zielpfad.instance_of?(Ressourcen) ordner_erzeugen(zielpfad) {|src, dest| File.syscopy(File.expand_path(src), File.expand_path(dest)) } end #-------------------------------------------------------------------------- # * Erhält Größe der Ressourcendateien => String o. Float #-------------------------------------------------------------------------- def size(special=false) #=> gibt Float zurück groesse = 0 self.each(special) {|r| groesse += FileTest.size(path(r)) } groesse.to_f end def printable_size(special=false) #=> gibt einen lesbaren String zurück size(special).datasize end #-------------------------------------------------------------------------- # * Sucht Pfad einer Datei => String # name#String : Name der gesuchten Datei # typ#Symbol : Typ der gesuchten Datei # meta#String : Metaordner, in dem sich die Datei befindet # endung#String : Endung der Datei # Angaben bis auf name können weggelassen werden, verzögern aber den Prozess #-------------------------------------------------------------------------- def path(name, typ=false, meta=false, endung=false) dmeta = if meta then meta elsif typ then meta(typ) else meta(name) end dtyp = (if typ then typ else typ(name) end).to_s return false unless (dmeta and dtyp) path = "#{@root}/#{dmeta}/#{dtyp}/#{name}" dendung = if endung then endung else endung(name, dtyp.to_sym, dmeta) end return false unless dendung path + '.' + dendung end #-------------------------------------------------------------------------- # * Sucht Metaordner einer Datei => String # angabe#String/Symbol: Entweder Dateiname oder Dateityp #-------------------------------------------------------------------------- def meta(angabe) typ = if TYPEN.include?(angabe.to_sym) then angabe else typ(angabe) end Ressourcen.metadirectory_for(typ) end #-------------------------------------------------------------------------- # * Sucht Typ einer Datei => Symbol # name#String: Dateiname #-------------------------------------------------------------------------- def typ(name) typ = nil if (TYPEN.each {|typ| break if method(typ).call.include?(name)}).nil? then typ else nil end end #-------------------------------------------------------------------------- # * Sucht Endung einer Datei => String # name#String : Dateiname # typ#Symbol : Typ der gesuchten Datei # meta#String : Metaordner der Datei # Angaben bis auf name können weggelassen werden, verzögern aber den Prozess #-------------------------------------------------------------------------- def endung(name, typ=false, meta=false) typ = typ(name) unless typ meta = meta(typ) unless meta path = "#{@root}/#{meta}/#{typ}/#{name}" e = nil if (Ressourcen.extensions(typ).each {|e| if File.exist?(path + '.' + e) then break end }) then nil else e end end #-------------------------------------------------------------------------- # * Gibt alle Pfade aus, die den Angaben entsprechen => String-Array # dname#String: Dateiname; dtyp#Symbol : Dateityp; dmeta#String : Metaordner # dendung#String : Endung der Datei # Wenn Angaben weggelassen werden, werden alle Pfade ausgegeben # Wenn Block angegeben, werden die einzelnen Pfade iteriert #-------------------------------------------------------------------------- def paths(dname=false, dtyp=false, dmeta=false, dendung=false) typen = if dtyp then dtyp.to_a elsif dmeta then METADIRECTORY[dmeta] else typen() end result = Array.new typen.each {|typ| method(typ).call.each {|name| if dendung or (dendung = endung(name, typ)) then result << path(name, typ, false, dendung) end } } result.each{|e| yield(e)} if block_given? result end #-------------------------------------------------------------------------- # * Iteriert Ressourcennamen (Enumerable Modul) # special#Symbol/String : Nur Inhalt des Metaordners/Typs wird iteriert # Wenn kein special angegeben, wird jeder Ressourcenname iteriert #-------------------------------------------------------------------------- def each(special=false, &block) if special then self.method(special.to_sym).call.each(&block) else (TYPEN.collect {|typ| self.method(typ).call}).flatten.each(&block) end end end
#-------------------------------------------------------------------------- # * Benötigte Methoden #-------------------------------------------------------------------------- class Class #-------------------------------------------------------------------------- # * Erzeugt alternative Namen für eine Methode -KD #-------------------------------------------------------------------------- def link(methode, *namen) namen.each {|n| define_method(n) {|*a| method(methode).call(*a)}} end def link_classmethod(methode, *namen) $methode = methode namen.each {|n| $n = n class << self methode, n = $methode, $n define_method(n) {|*a| self.method(methode).call(*a)} end } $methode = nil $n = nil end end class Array #-------------------------------------------------------------------------- # * Addiert zwei Arrays ohne doppelte o. leere Elemente hinzuzufügen -KD #-------------------------------------------------------------------------- def add(*args) args.each {|e| push(e) unless include?(e) or e.empty?} end end class Hash #-------------------------------------------------------------------------- # * Sucht nach einem passenden Key für einen Value/Suchblock -KD #-------------------------------------------------------------------------- def key_for_value(search_value) key = nil ergebnis = each_pair {|key, value| break if if block_given? then yield(value, search_value) else value == search_value end true } if ergebnis then false else key end end end class Symbol #-------------------------------------------------------------------------- # * Macht ein Symbol zu einem Instanzvariablensymbol -KD #-------------------------------------------------------------------------- def to_isym return ('@' + self.to_s).to_sym end end class Fixnum #-------------------------------------------------------------------------- # * Liefert einen String mit einer n-stellen Zahl. -KD #-------------------------------------------------------------------------- def zu_nstelligen_string(n) vor = "" (n-1).downto(0) {|stelle| vor = vor.concat('0') if self < 10**stelle } vor.concat(self.to_s) end end class Float #-------------------------------------------------------------------------- # * Gibt Datengröße an. -KD #-------------------------------------------------------------------------- EINHEITEN = ["byte", "kb", "mb", "gb"] def datasize size = self; counter = 0 while counter < EINHEITEN.size-1 and (a=size / 1024) >= 0.1 size = a; counter += 1; end size.to_s + ' ' + EINHEITEN[counter] end end class File #-------------------------------------------------------------------------- # * Überprüft, ob der Dateiname auf eine Ressourcendatei zeigt -KD #-------------------------------------------------------------------------- def self.ressource?(pfad, *possible_endings) pfad =~ /.+\.(.+)/ !(possible_endings.find {|e| e == $1}).nil? end #-------------------------------------------------------------------------- # * Erzeugt einen Ordner - WATANABE, Hirofumi (Ruby Standard Library) #-------------------------------------------------------------------------- def self.makedirs(*dirs) verbose = if dirs[-1].is_a? String then false else dirs.pop end mode = 0755 for dir in dirs parent = dirname(dir) next if parent == dir or directory? dir makedirs parent unless directory? parent $stderr.print "mkdir ", dir, "\n" if verbose if basename(dir) != "" begin Dir.mkdir dir, mode rescue SystemCallError raise unless directory? dir end end end end #-------------------------------------------------------------------------- # * Sucht nach Dateien - (Ruby Standard Library) #-------------------------------------------------------------------------- def self.find(*paths) paths.collect!{|d| d.dup} while file = paths.shift catch(:prune) do yield file.dup.taint next unless File.exist? file begin if File.lstat(file).directory? then d = Dir.open(file) begin for f in d next if f == "." or f == ".." if File::ALT_SEPARATOR and file =~ /^(?:[\/\\]|[A-Za-z]:[\/\\]?)$/ then f = file + f elsif file == "/" then f = "/" + f else f = File.join(file, f) end paths.unshift f.untaint end ensure d.close end end rescue Errno::ENOENT, Errno::EACCES end end end end def self.prune throw :prune end #-------------------------------------------------------------------------- # * Kopiert Dateien -Ruby Standard Library #-------------------------------------------------------------------------- BUFSIZE = 8 * 1024 def self.catname(from, to) if directory? to join to.sub(%r([/\\]$), ''), basename(from) else to end end def self.syscopy(from, to) to = catname(from, to) fmode = stat(from).mode tpath = to not_exist = !exist?(tpath) from = open(from, "rb") to = open(to, "wb") begin while true do to.syswrite from.sysread(BUFSIZE) end rescue EOFError ret = true rescue ret = false ensure to.close from.close end chmod(fmode, tpath) if not_exist ret end end
#============================================================================== # ** Ressourcen - von KD #------------------------------------------------------------------------------ # Diese Klasse speichert Ressourcennamen und liest diese aus Projekten aus #============================================================================== class Ressourcen include(Enumerable) #-------------------------------------------------------------------------- # * Konstanten #-------------------------------------------------------------------------- ORDNER = "Data/" #Ordner wo die Daten sich befinden MAPS = "Map" #Dateiname der Maps ENDUNG = ".rxdata" #Dateiendung der Daten LOGPFAD = "/log/" #Pfad der Logdateien LOGNAME = "ressourcen" #Dateiname der Logdatei LOGENDING = '.log' #Dateiendung der Logdateien LOESCHPFAD = "/nicht_benoetigt/" #Pfad für verschobene Ressourcendateien #Konstanten für den Automatik-Vorgang LOGGEN = true #Genutzte Ressourcen werden geloggt MULTI_FILE = false #Ressourcen werden in mehreren Textdateien geloggt LOG_UNUSED = true #Ungenutzte Ressourcen werden extra geloggt LOESCHEN = false #nicht benötigte Ressourcen werden gelöscht EXIT = true #Nach Ausführen des Vorgangs wird Programm beendet LOG_ORDNER = '/unused/'#Logordner für ungenutzte Ressourcen UNUSEDNAME = 'unused' #Dateiname für ungenutzte-Ressourcenlogdatei #-------------------------------------------------------------------------- # * Attribute #-------------------------------------------------------------------------- METADIRECTORY = Hash.new METADIRECTORY['graphics'] = [:characters, :windowskins, :transitions, :fogs, :battlebacks, :panoramas, :windowskins, :characters, :animations, :autotiles, :battlers, :gameovers, :icons, :pictures, :tilesets, :titles] METADIRECTORY['audio'] = [:se, :bgs, :me, :bgm] TYPEN = METADIRECTORY.values.flatten #Attribut Readers -> Metadirectories, Typen, root METADIRECTORY.each_key {|meta| define_method(meta.to_sym) { result = Array.new METADIRECTORY[meta].each {|m| result << self.method(m).call} result.flatten }} attr_reader(:root, *TYPEN) #============================================================================ # ***Initialisierung der Instanzvariablen*** # root#String : Gibt den Pfad zum Projektordner an #============================================================================ def initialize(root='.') TYPEN.each {|typ| self.instance_variable_set(typ.to_isym, Array.new) } @root = root end #============================================================================ # ***Klassenmethoden*** #============================================================================ #-------------------------------------------------------------------------- # * Definiert Dateiendungen für einen Typ o. Metaordner # klassifizierung#String/Symbol : Metaordner oder Typ der Dateiendung # *extensions#Strings : Name der Dateiendung #-------------------------------------------------------------------------- @@extensions = Hash.new def self.extensions_for(klassifizierung, *extensions) k = klassifizierung.to_s.downcase if @@extensions[k] then @@extensions[k].add(extensions) else @@extensions[k] = extensions end end #-------------------------------------------------------------------------- # * Erzeugt Dateiendungen #-------------------------------------------------------------------------- extensions_for('audio', 'mid', 'ogg', 'wav', 'mp3', 'wma') extensions_for('graphics', 'png', 'bmp', 'jpg') #-------------------------------------------------------------------------- # * Gib Dateiendungen für bestimmten Typ/Metaordner zurück => Array # typ#String/Symbol : Metaordner oder Typ, der gesuchte Dateiendung hat # Standardmäßig werden alle Dateiendungen ausgegeben #-------------------------------------------------------------------------- def self.extensions(typ=true) if (typ==true) then return @@extensions.values.flatten end key = typ.to_s.downcase if @@extensions.has_key?(key) then @@extensions[key] elsif @@extensions.has_key?(n=metadirectory_for(typ).to_s.downcase) @@extensions[n] else [] end end def extensions(t=true); Ressourcen.extensions(t); end #-------------------------------------------------------------------------- # * Gibt den Metaordner für einen Typ aus => nil oder String # typ#Symbol : Typ, dessen Metaordner gesucht wird #-------------------------------------------------------------------------- def self.metadirectory_for(typ) if typ then typ = typ.to_s.downcase.to_sym METADIRECTORY.key_for_value(typ) {|h, s| h.include?(s)} else nil end end def metadirectory_for(typ); Ressourcen.metadirectory_for(typ); end #-------------------------------------------------------------------------- # * Sucht nach Ressourcen, loggt diese und löscht ggf. nicht benötigte #-------------------------------------------------------------------------- def self.automatik() ressourcen = genutzte_ressourcen.sort! if MULTI_FILE then ressourcen.loggen else ressourcen.loggen_one end if LOGGEN if LOG_UNUSED or LOESCHEN then unused = Ressourcen.ungenutzte_ressourcen(ressourcen) end if LOG_UNUSED then if MULTI_FILE then unused.loggen(LOG_ORDNER) else unused.loggen_one(LOGPFAD, UNUSEDNAME) end end if LOESCHEN then unused.verschiebe end exit if EXIT end #-------------------------------------------------------------------------- # * Erzeugt Construktor-Methoden # methode#Symbol : Methode, für die ein Constructor erzeugt wird #-------------------------------------------------------------------------- def self.constructor(methode) $methode = methode class << self; m = $methode; define_method(m) {|*a| root=if a[0].class==String and self.instance_method(m).arity.abs < a.size a.shift else "." end r = self.new(root) r.method(m).call(*a) r } end $methode = nil end #-------------------------------------------------------------------------- # * Erzeugt Constructor und alternative Methodennamen # name#Symbol : Methode, die behandelt wird # *alternatives#Symbole : Alternative Methodennamen #-------------------------------------------------------------------------- def self.constructor_and_alternatives(name, *alternatives) constructor(name) #erzeuge Konstructor für Methode link(name, *alternatives) #alternative namen für Methode link_classmethod(name, *alternatives) #alternative namen für Konstruktor end #============================================================================ # ***Constructor Methoden*** => Ressourcenobjekt # Als Klassenmethoden genutzt erzeugen sie neue Ressourcen-Objekte # root#String : Erzeugt ein Ressourcenobjekt in diesem Projektordner # Als Instanzmethoden genutzt fügen sie dem Objekt neue Ressourcen hinzu #============================================================================ #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus genutzten Ressourcen eines Projektes #-------------------------------------------------------------------------- def genutzte_ressourcen() durchsuche_maps durchsuche_database self end constructor_and_alternatives(:genutzte_ressourcen, :used_ressources) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus importierten Ressourcen eines Projektes #-------------------------------------------------------------------------- def importierte_ressourcen() pfad = @root + '/' #Durchsuche alle Metaordner directories = METADIRECTORY.keys.collect {|e| pfad + e.to_s} dirs = "" METADIRECTORY.keys.each {|d| dirs = dirs.concat('|' + d.to_s)} dirs = dirs.sub('|', '') pfad = ' ' + pfad while a = pfad =~ /[^\\]\./ do pfad[a+1] = '\\.' end while a = pfad =~ /[^\\]\// do pfad[a+1] = '\\/' end pfad[0] = '' regexp = Regexp.new(pfad+"(#{dirs})"+'\/(.+)\/(.+)\..+', true) File.find(*directories) {|pfad| #Wenn gefundene Datei die passende Dateiendung hat.... pfad =~ regexp if File.ressource?(pfad.downcase, *extensions($2)) then #...soll sie in die Liste aufgenommen werden if method(methode=$2.downcase.to_sym) then method(methode).call.add($3) end end } self end constructor_and_alternatives(:importierte_ressourcen, :imported_ressources) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus nichtbenötigten Ressourcen des Projektes # genutzte#Ressourcen : Prozess lässt sich beschleunigen, wenn das # genutzte-Ressourcenobjekt zuvor schon erzeugt wurde #-------------------------------------------------------------------------- def ungenutzte_ressourcen(genutzte=nil) genutzte = Ressourcen.genutzte_ressourcen(@root) unless genutzte importierte_ressourcen() drop(genutzte) end constructor_and_alternatives(:ungenutzte_ressourcen, :unused_ressources) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus einer Map # mapdateiname#String : Pfad zur Mapdatei #-------------------------------------------------------------------------- def durchsuche_map(mappfad) map = load_data(@root+'/'+mappfad) #Suche aus der Map alle Sounddateien heraus bgm.add(map.bgm.name) if map.autoplay_bgm bgm.add(map.bgs.name) if map.autoplay_bgs #Suche aus der Map alle Eventgrafiken heraus events = map.events events.each_value {|event| event.pages.each {|page| characters.add(page.graphic.character_name) #Suche alle Ressourcen aus MoveBefehlen heraus durchsuche_moveroute(page.move_route.list) #Suche alle Ressourcen aus Eventbefehlen heraus durchsuche_eventcommands(page.list) } } self end constructor_and_alternatives(:durchsuche_map, :scan_map) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Mapdaten #-------------------------------------------------------------------------- def durchsuche_maps #Suche in den Maps nach verwendeten Ressourcen i = 1 name = ORDNER + MAPS+i.zu_nstelligen_string(3)+ENDUNG while File.exist?(@root + "/" + name) durchsuche_map(name) i += 1 name = ORDNER + MAPS+i.zu_nstelligen_string(3)+ENDUNG end self end constructor_and_alternatives(:durchsuche_maps, :scan_maps) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Move-Routes # move_list#RPG::MoveCommand-Array : Move-Commands die durchsucht werden #-------------------------------------------------------------------------- def durchsuche_moveroute(move_liste) move_liste.each {|befehl| case befehl.code when 41 characters.add(befehl.parameters[0]) when 44 bgs.add(befehl.parameters[0].name) when 45 durchsuche_script(befehl.parameters[0]) end } self end constructor_and_alternatives(:durchsuche_moveroute, :scan_moveroute) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Event Commands # liste#RPG::EventCommand-Array : EventCommands die durchsucht werden #-------------------------------------------------------------------------- def durchsuche_eventcommands(liste) rubystring = "" messagestring = "" commentstring = "" liste.each {|befehl| case befehl.code when 101, 401 messagestring += "\n" + befehl.parameters[0] when 108, 408 commentstring += "\n" + befehl.parameters[0] when 111 if befehl.parameters[4] == 12 rubystring + "\n" + befehl.parameters[1] end when 131 windowskins.add(befehl.parameters[0]) when 132 bgm.add(befehl.parameters[0].name) when 133 me.add(befehl.parameters[0].name) when 204 case befehl.parameters[0] when 0 then panoramas.add(befehl.parameters[1]) when 1 then fogs.add(befehl.parameters[1]) when 2 then battlebacks.add(befehl.parameters[1]) end when 209 durchsuche_moveroute(befehl.parameters[1].list) when 222 transitions.add(befehl.parameters[0]) when 231 pictures.add(befehl.parameters[1]) when 241 bgm.add(befehl.parameters[0].name) when 245 bgs.add(befehl.parameters[0].name) when 249 me.add(befehl.parameters[0].name) when 250 se.add(befehl.parameters[0].name) when 322 characters.add(befehl.parameters[1]) battlers.add(befehl.parameters[3]) when 355 rubystring.concat(befehl.parameters[0]) when 655 rubystring.concat(befehl.parameters[0]) end } durchsuche_script(rubystring) durchsuche_message(messagestring) durchsuche_comment(commentstring) self end constructor_and_alternatives(:durchsuche_eventcommands, :scan_eventcommands) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Rubyscripts (unvollständig) # string#String : String aus Rubyscripten, der durchsucht wird #-------------------------------------------------------------------------- def durchsuche_script(string) self end constructor_and_alternatives(:durchsuche_script, :scan_script) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Messagescripts (unvollständig) # string#String : String aus Messages, der durchsucht wird #-------------------------------------------------------------------------- def durchsuche_message(string) self end constructor_and_alternatives(:durchsuche_script, :scan_script) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Commentcripts (unvollständig) # string#String : String aus Comments, der durchsucht wird #-------------------------------------------------------------------------- def durchsuche_comment(string) self end constructor_and_alternatives(:durchsuche_script, :scan_script) #-------------------------------------------------------------------------- # * Erzeugt ein Ressourcenobjekt aus den Informationen der Database #-------------------------------------------------------------------------- def durchsuche_database #Actors datei = load_data("#{@root}/Data/Actors.rxdata") datei.each {|actor| next unless actor characters.add(actor.character_name) battlers.add(actor.battler_name) } #Skills und Items datei = load_data("#{@root}/Data/Skills.rxdata") + load_data("#{@root}/Data/Items.rxdata") datei.each {|e| next unless e icons.add(e.icon_name) se.add(e.menu_se.name) } #Weapons und armors datei = load_data("#{@root}/Data/Weapons.rxdata") + load_data("#{@root}/Data/Armors.rxdata") datei.each {|e| next unless e icons.add(e.icon_name) } #Enemies datei = load_data("#{@root}/Data/Enemies.rxdata") datei.each {|e| next unless e battlers.add(e.battler_name) } #Battle-Events datei = load_data("#{@root}/Data/Troops.rxdata") datei.each {|e| next unless e e.pages.each {|page| durchsuche_eventcommands(page.list) } } #Animations datei = load_data("#{@root}/Data/Animations.rxdata") datei.each {|e| next unless e animations.add(e.animation_name) e.timings.each {|time| se.add(time.se.name)} } #Tilesets datei = load_data("#{@root}/Data/Tilesets.rxdata") datei.each {|e| next unless e tilesets.add(e.tileset_name) autotiles.add(*e.autotile_names) panoramas.add(e.panorama_name) fogs.add(e.fog_name) battlebacks.add(e.battleback_name) } #CommonEvents datei = load_data("#{@root}/Data/CommonEvents.rxdata") datei.each {|e| next unless e durchsuche_eventcommands(e.list) } #System datei = load_data("#{@root}/Data/System.rxdata") windowskins.add(datei.windowskin_name) titles.add(datei.title_name) gameovers.add(datei.gameover_name) windowskins.add(datei.windowskin_name) transitions.add(datei.battle_transition) bgm.add(datei.title_bgm.name) bgm.add(datei.battle_bgm.name) me.add(datei.battle_end_me.name) me.add(datei.gameover_me.name) se.add(datei.cursor_se.name) se.add(datei.decision_se.name) se.add(datei.cancel_se.name) se.add(datei.buzzer_se.name) se.add(datei.equip_se.name) se.add(datei.shop_se.name) se.add(datei.save_se.name) se.add(datei.load_se.name) se.add(datei.battle_start_se.name) se.add(datei.escape_se.name) se.add(datei.actor_collapse_se.name) se.add(datei.enemy_collapse_se.name) battlebacks.add(datei.battleback_name) battlers.add(datei.battler_name) self end constructor_and_alternatives(:durchsuche_database, :scan_database) #============================================================================ # ***Öffentliche Instanzmethoden*** #============================================================================ #-------------------------------------------------------------------------- # * Sortiert ein Ressourcenobjekt => Ressourcen #-------------------------------------------------------------------------- def sort! TYPEN.each {|typ| array = self.instance_variable_get(typ.to_isym) array.sort! } self end #-------------------------------------------------------------------------- # * Gibt jene Ressourcentypen zurück, die nicht leer sind => Symbol-Array #-------------------------------------------------------------------------- def typen TYPEN.find_all {|t| !self.instance_variable_get(t.to_isym).empty?} end #-------------------------------------------------------------------------- # * Addition zweier Ressourcenobjekte => Ressourcen # other#Ressourcen : Summant, mit dem das Ressourcenobjekt addiert wird #-------------------------------------------------------------------------- def concat(other) TYPEN.each {|typ| typ = typ.to_isym self.instance_variable_get(typ).add(*other.instance_variable_get(typ)) } self end #-------------------------------------------------------------------------- # * Subtraktion zweier Ressourcenobjekte => Ressourcen # other#Ressourcen : Subtrahend , mit dem subtrahiert wird #-------------------------------------------------------------------------- def drop(other) TYPEN.each {|typ| typ = typ.to_isym v = self.instance_variable_get(typ) - other.instance_variable_get(typ) self.instance_variable_set(typ, v) } self end #-------------------------------------------------------------------------- # * Schnittmenge zweier Ressourcenobjekte => Ressourcen # other#Ressourcen : Vergleichsressourcenobjekt #-------------------------------------------------------------------------- def compare(other) ressi = Ressourcen.new(@root) TYPEN.each {|typ| ressi.method(typ).call.add( *method(typ).call & other.method(typ).call) } ressi end #-------------------------------------------------------------------------- # * Loggt die Ressourcen in verschiedenen Textdateien # ordner#String : Pfad zum Log-Ordner # dateiende#String : Dateiende der Logdateien #-------------------------------------------------------------------------- def loggen(ordner=LOGPFAD, dateiende=LOGENDING) File.makedirs(@root + '/' + ordner) TYPEN.each {|typ| liste = self.instance_variable_get(typ.to_isym) next if liste.empty? File.open(path + ordner + typ.to_s + dateiende, 'w+') {|file| liste.each {|name| file.write(name + "\n") } } } end #-------------------------------------------------------------------------- # * Loggt die Ressourcen in einer Textdatei # ordner#String : Pfad zum Log-Ordner # dname#String : Name der Logdatei # dateiende#String : Dateiende der Logdatei #-------------------------------------------------------------------------- def loggen_one(ordner=LOGPFAD, dname=LOGNAME, dateiende=LOGENDING) File.makedirs(@root+'/' + ordner) sortierer = Proc.new {|a,b| a.to_s <=> b.to_s} File.open(@root + '/' + ordner + dname + dateiende, 'w+') {|file| TYPEN.sort(&sortierer).each {|typ| liste = self.instance_variable_get(typ.to_isym) next if liste.empty? file.write(typ.to_s.capitalize + "\n") liste.each {|name| file.write(name + "\n") } file.write("\n") } } end #-------------------------------------------------------------------------- # * Erzeugt die Ordner und ermitteln dest und src Pfade (Privat!) #-------------------------------------------------------------------------- def ordner_erzeugen(path, *args, &block) #Iteriere jeden Metaordner METADIRECTORY.each_pair {|ordner, typen| next if method(ordner.to_sym).call.empty? #Lege einen Ordner für diesen META an, falls noch nicht geschehen File.makedirs(dest_pfad = (path+'/'+ordner.capitalize)) src_pfad = @root + '/' + ordner.capitalize #Iteriere die Typen jedes Metaordners typen.each {|typ| next if (inhalt=method(typ).call).empty? styp = typ.to_s.capitalize #Lege einen Ordner für diesen Typ an, falls noch nicht geschehen File.makedirs(dest_typpfad = dest_pfad + '/' + styp) src_typpfad = src_pfad + '/' + styp #Iteriere die Ressourcen eines Types inhalt.each {|e| #Ermittle vollständigen Dateinamen der Ressource src_name = src_typpfad + "/" + e endung = "" next if Ressourcen.extensions(typ).each {|endung| if File.exist?(src_name + '.' + endung) then break end } src_name = src_name + '.' + endung dest_name = dest_typpfad + '/' + e + '.' + endung #Führe den Proc aus block.call(src_name, dest_name, *args) } } } end private(:ordner_erzeugen) #-------------------------------------------------------------------------- # * Verschiebt Ressourcen in einen extra Ordner # lpfad#String : Pfad zum Ordner, zu dem verschoben wird #-------------------------------------------------------------------------- def verschiebe(lpfad=LOESCHPFAD) lpfad = lpfad.root if lpfad.instance_of?(Ressourcen) ordner_erzeugen(@root + '/' + lpfad) {|src, dest| File.rename(File.expand_path(src), File.expand_path(dest)) } end link(:verschiebe, :move) #-------------------------------------------------------------------------- # * Kopiert Ressourcen in ein anderes Projekt # zielpfad#String/Ressourcen : Zielordner, in das Ressourcen kopiert werden # Ressourcenobjekt, in dessen Root kopiert wird #-------------------------------------------------------------------------- def kopiere(zielpfad) zielpfad = zielpfad.root if zielpfad.instance_of?(Ressourcen) ordner_erzeugen(zielpfad) {|src, dest| File.syscopy(File.expand_path(src), File.expand_path(dest)) } end #-------------------------------------------------------------------------- # * Erhält Größe der Ressourcendateien => String o. Float #-------------------------------------------------------------------------- def size(special=false) #=> gibt Float zurück groesse = 0 self.each(special) {|r| groesse += FileTest.size(path(r)) } groesse.to_f end def printable_size(special=false) #=> gibt einen lesbaren String zurück size(special).datasize end #-------------------------------------------------------------------------- # * Sucht Pfad einer Datei => String # name#String : Name der gesuchten Datei # typ#Symbol : Typ der gesuchten Datei # meta#String : Metaordner, in dem sich die Datei befindet # endung#String : Endung der Datei # Angaben bis auf name können weggelassen werden, verzögern aber den Prozess #-------------------------------------------------------------------------- def path(name, typ=false, meta=false, endung=false) dmeta = if meta then meta elsif typ then meta(typ) else meta(name) end dtyp = (if typ then typ else typ(name) end).to_s return false unless (dmeta and dtyp) path = "#{@root}/#{dmeta}/#{dtyp}/#{name}" dendung = if endung then endung else endung(name, dtyp.to_sym, dmeta) end return false unless dendung path + '.' + dendung end #-------------------------------------------------------------------------- # * Sucht Metaordner einer Datei => String # angabe#String/Symbol: Entweder Dateiname oder Dateityp #-------------------------------------------------------------------------- def meta(angabe) typ = if TYPEN.include?(angabe.to_sym) then angabe else typ(angabe) end Ressourcen.metadirectory_for(typ) end #-------------------------------------------------------------------------- # * Sucht Typ einer Datei => Symbol # name#String: Dateiname #-------------------------------------------------------------------------- def typ(name) typ = nil if (TYPEN.each {|typ| break if method(typ).call.include?(name)}).nil? then typ else nil end end #-------------------------------------------------------------------------- # * Sucht Endung einer Datei => String # name#String : Dateiname # typ#Symbol : Typ der gesuchten Datei # meta#String : Metaordner der Datei # Angaben bis auf name können weggelassen werden, verzögern aber den Prozess #-------------------------------------------------------------------------- def endung(name, typ=false, meta=false) typ = typ(name) unless typ meta = meta(typ) unless meta path = "#{@root}/#{meta}/#{typ}/#{name}" e = nil if (Ressourcen.extensions(typ).each {|e| if File.exist?(path + '.' + e) then break end }) then nil else e end end #-------------------------------------------------------------------------- # * Gibt alle Pfade aus, die den Angaben entsprechen => String-Array # dname#String: Dateiname; dtyp#Symbol : Dateityp; dmeta#String : Metaordner # dendung#String : Endung der Datei # Wenn Angaben weggelassen werden, werden alle Pfade ausgegeben # Wenn Block angegeben, werden die einzelnen Pfade iteriert #-------------------------------------------------------------------------- def paths(dname=false, dtyp=false, dmeta=false, dendung=false) typen = if dtyp then dtyp.to_a elsif dmeta then METADIRECTORY[dmeta] else typen() end result = Array.new typen.each {|typ| method(typ).call.each {|name| if dendung or (dendung = endung(name, typ)) then result << path(name, typ, false, dendung) end } } result.each{|e| yield(e)} if block_given? result end #-------------------------------------------------------------------------- # * Iteriert Ressourcennamen (Enumerable Modul) # special#Symbol/String : Nur Inhalt des Metaordners/Typs wird iteriert # Wenn kein special angegeben, wird jeder Ressourcenname iteriert #-------------------------------------------------------------------------- def each(special=false, &block) if special then self.method(special.to_sym).call.each(&block) else (TYPEN.collect {|typ| self.method(typ).call}).flatten.each(&block) end end end
--Ruby/RGSS-Kurs
Foren-Regeln