Class: ElderScrollsPlugin
- Inherits:
-
Object
- Object
- ElderScrollsPlugin
- Defined in:
- lib/elder_scrolls_plugin.rb,
lib/elder_scrolls_plugin/version.rb
Defined Under Namespace
Modules: Data, Headers Classes: Door, FormId, IslandNavMesh, Label, RoundedFloat, Triangle, Vertex
Constant Summary collapse
- KNOWN_GRUP_RECORDS_WITHOUT_FIELDS =
%w( NAVM CELL LAND NPC_ )
- KNOWN_GRUP_RECORDS_WITH_FIELDS =
%w( AACT ACHR ACTI ADDN ALCH AMMO ANIO APPA ARMA ARMO ARTO ASPC ASTP AVIF BOOK BPTD CAMS CLAS CLDC CLFM CLMT COBJ COLL CONT CPTH CSTY DEBR DIAL DLBR DLVW DOBJ DOOR DUAL ECZN EFSH ENCH EQUP EXPL EYES FACT FLOR FLST FSTP FSTS FURN GLOB GMST GRAS HAIR HAZD HDPT IDLE IDLM IMAD IMGS INFO INGR IPCT IPDS KEYM KYWD LCRT LCTN LGTM LIGH LSCR LTEX LVLI LVLN LVSP MATO MATT MESG MGEF MISC MOVT MSTT MUSC MUST NAVI OTFT PACK PERK PROJ PWAT QUST RACE REFR REGN RELA REVB RFCT RGDL SCEN SCOL SCPT SCRL SHOU SLGM SMBN SMEN SMQN SNCT SNDR SOPM SOUN SPEL SPGD STAT TACT TREE TXST VTYP WATR WEAP WOOP WRLD WTHR )
- KNOWN_FIELDS =
%w( 00TX 10TX 20TX 30TX 40TX 50TX 60TX 70TX 80TX 90TX :0TX ;0TX <0TX =0TX >0TX ?0TX @0TX A0TX ACEC ACEP ACID ACPR ACSR ACUN AHCF AHCM ALCA ALCL ALCO ALDN ALEA ALED ALEQ ALFA ALFC ALFD ALFE ALFI ALFL ALFR ALID ALLS ALNA ALNT ALPC ALRT ALSP ALST ALUA ANAM ATKD ATKE AVSK B0TX BAMT BIDS BNAM BOD2 BPND BPNI BPNN BPNT BPTN C0TX CIS1 CIS2 CITC CNAM CNTO COCT COED CRDT CRVA CTDA D0TX DALC DATA DEMO DESC DEST DEVA DFTF DFTM DMAX DMDL DMDS DMDT DMIN DNAM DODT DSTD DSTF E0TX EAMT ECOR EDID EFID EFIT EITM ENAM ENIT EPF2 EPF3 EPFD EPFT ETYP F0TX FLMV FLTR FLTV FNAM FNPR FTSF FTSM FULL G0TX GNAM H0TX HCLF HEAD HEDR HNAM HTID ICO2 ICON IDLA IDLC IDLF IDLT IMSP INAM INCC INDX INTV ITXT JNAM K0TX KNAM KSIZ KWDA L0TX LLCT LNAM LTMP LVLD LVLF LVLG LVLI LVLO MDOB MHDT MNAM MO2S MO2T MO3S MO3T MO4S MO4T MO5T MOD2 MOD3 MOD4 MOD5 MODL MODS MODT MPAI MPAV MTNM NAM0 NAM1 NAM2 NAM3 NAM4 NAM5 NAM7 NAM8 NAM9 LCEC LCEP LCID LCPR LCSR LCUN NAMA NAME NEXT NNAM NVER NVMI NVPP OBND OCOR ONAM PDTO PFIG PFPC PHTN PHWT PKC2 PKCU PKDT PLDT PLVD PNAM POBA POCA POEA PRCB PRKC PRKE PRKF PSDT PTDA QNAM QOBJ QSDT QSTA QTGL RCEC RCLR RCPR RCSR RCUN RDAT RDMO RDSA RDWT RNAM RNMV RPLD RPLI RPRF RPRM SDSC SLCP SNAM SNDD SNMV SOUL SPCT SPIT SPLO SPMV SWMV TCLT TIFC TINC TIND TINI TINL TINP TINT TINV TIRS TNAM TPIC TRDT TWAT TX00 TX01 TX02 TX03 TX04 TX05 TX07 UNAM UNES VENC VEND VENV VMAD VNAM VTCK WBDT WCTR WKMV WNAM XACT XALP XAPD XAPR XCNT XEMI XESP XEZN XIS2 XLCM XLCN XLIB XLIG XLKR XLOC XLRL XLRM XLRT XLTW XMBO XMBR XMRK XNAM XNDP XOCP XOWN XPOD XPPA XPRD XPRM XRDS XRGB XRGD XRMR XSCL XTEL XTNM XTRI XWCN XWCU XWEM XXXX YNAM ZNAM )
- VERSION =
'0.0.2'
Instance Attribute Summary collapse
-
#chunks_tree ⇒ Object
readonly
Hash< Chunk or nil, Array<Chunk> >: The chunks tree, with nil being the root node.
-
#masters ⇒ Object
readonly
Array<String>: Ordered list of masters.
-
#unknown_chunks ⇒ Object
readonly
Array<Riffola::Chunk>: Unknown chunks encountered.
Class Method Summary collapse
-
.current_esp ⇒ Object
Get the current esp being read (useful for BinData decoding types that depend on the esp).
-
.current_esp=(esp) ⇒ Object
Set the current esp being read (useful for BinData decoding types that depend on the esp).
Instance Method Summary collapse
-
#absolute_form_id(form_id) ⇒ Object
Convert a Form ID into its absolute form.
-
#dump(chunk = nil, output_prefix = '') ⇒ Object
Output a node of the chunks tree.
-
#dump_absolute_form_ids ⇒ Object
Dump absolute Form IDs.
-
#dump_masters ⇒ Object
Dump masters.
-
#initialize(file_name, decode_only_tes4: false, ignore_unknown_chunks: false, decode_fields: true, warnings: true, debug: false) ⇒ ElderScrollsPlugin
constructor
Constructor.
-
#to_json(chunk = nil) ⇒ Object
Return the esp content as JSON.
Constructor Details
#initialize(file_name, decode_only_tes4: false, ignore_unknown_chunks: false, decode_fields: true, warnings: true, debug: false) ⇒ ElderScrollsPlugin
Constructor
- Parameters
-
file_name (String): ESP file name
-
decode_only_tes4 (Boolean): Do we decode only the TES4 header? [default: false]
-
ignore_unknown_chunks (Boolean): Do we ignore unknown chunks? [default: false]
-
decode_fields (Boolean): Do we decode fields content? [default: true]
-
warnings (Boolean): Do we activate warnings? [default: true]
-
debug (Boolean): Do we activate debugging logs? [default: false]
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
# File 'lib/elder_scrolls_plugin.rb', line 672 def initialize(file_name, decode_only_tes4: false, ignore_unknown_chunks: false, decode_fields: true, warnings: true, debug: false) @file_name = file_name @decode_only_tes4 = decode_only_tes4 @ignore_unknown_chunks = ignore_unknown_chunks @decode_fields = decode_fields @warnings = warnings @debug = debug # Get the list of masters @masters = [] # Internal mapping of first 2 digits of a FormID to the corresponding master name @master_ids = {} # List of form ids being defined @form_ids = [] # Unknown chunks encountered during decoding @unknown_chunks = [] # Configure the current parser ElderScrollsPlugin.current_esp = self # Tree of chunks (nil for root) # Hash< Chunk or nil, Array<Chunk> > @chunks_tree = {} chunks = Riffola.read(@file_name, chunks_format: { '*' => { header_size: 8 }, 'TES4' => { header_size: 16 }, 'GRUP' => { data_size_correction: -24, header_size: 16 } }, debug: @debug, warnings: @warnings) do |chunk| # Decode the TES4 to get the masters read_chunk(chunk) if chunk.name == 'TES4' !decode_only_tes4 || chunk.name != 'TES4' end # We just finished parsing TES4, update the masters index @master_ids.merge!(sprintf('%.2x', @master_ids.size) => File.basename(@file_name)) @chunks_tree[nil] = chunks unless decode_only_tes4 chunks.each do |chunk| # Don't read TES4 twice, especially because we already have our master IDs parsed read_chunk(chunk) unless chunk.name == 'TES4' end end end |
Instance Attribute Details
#chunks_tree ⇒ Object (readonly)
Hash< Chunk or nil, Array<Chunk> >: The chunks tree, with nil being the root node
24 25 26 |
# File 'lib/elder_scrolls_plugin.rb', line 24 def chunks_tree @chunks_tree end |
#masters ⇒ Object (readonly)
Array<String>: Ordered list of masters
27 28 29 |
# File 'lib/elder_scrolls_plugin.rb', line 27 def masters @masters end |
#unknown_chunks ⇒ Object (readonly)
Array<Riffola::Chunk>: Unknown chunks encountered
30 31 32 |
# File 'lib/elder_scrolls_plugin.rb', line 30 def unknown_chunks @unknown_chunks end |
Class Method Details
.current_esp ⇒ Object
Get the current esp being read (useful for BinData decoding types that depend on the esp)
- Result
-
ElderScrollsPlugin: The current esp
19 20 21 |
# File 'lib/elder_scrolls_plugin.rb', line 19 def self.current_esp @esp end |
.current_esp=(esp) ⇒ Object
Set the current esp being read (useful for BinData decoding types that depend on the esp)
- Parameters
-
esp (ElderScrollsPlugin): The current esp
11 12 13 |
# File 'lib/elder_scrolls_plugin.rb', line 11 def self.current_esp=(esp) @esp = esp end |
Instance Method Details
#absolute_form_id(form_id) ⇒ Object
Convert a Form ID into its absolute form. An absolute form ID is not dependent on the order of the masters and includes the master name.
- Parameters
-
form_id (String): The original form ID
- Result
-
String: The absolute Form ID
778 779 780 |
# File 'lib/elder_scrolls_plugin.rb', line 778 def absolute_form_id(form_id) "#{@master_ids.key?(form_id[0..1]) ? @master_ids[form_id[0..1]] : "!!!#{form_id[0..1]}"}/#{form_id[2..7]}" end |
#dump(chunk = nil, output_prefix = '') ⇒ Object
Output a node of the chunks tree
- Parameters
-
chunk (Riffola::Chunk or nil): The node to be dumped, or nil for root [default = nil]
-
output_prefix (String): Output prefix [default = ”]
717 718 719 720 721 722 723 724 |
# File 'lib/elder_scrolls_plugin.rb', line 717 def dump(chunk = nil, output_prefix = '') esp_info = chunk.nil? ? nil : chunk.instance_variable_get(:@esp_info) sub_chunks = @chunks_tree[chunk] puts "#{output_prefix}+- #{chunk.nil? ? 'ROOT' : "#{chunk.name}#{esp_info[:description].nil? ? '' : " - #{esp_info[:description]}"}"}#{sub_chunks.empty? ? '' : " (#{sub_chunks.size} sub-chunks)"}" sub_chunks.each.with_index do |sub_chunk, idx_sub_chunk| dump(sub_chunk, "#{output_prefix}#{idx_sub_chunk == sub_chunks.size - 1 ? ' ' : '|'} ") end end |
#dump_absolute_form_ids ⇒ Object
Dump absolute Form IDs
734 735 736 737 738 |
# File 'lib/elder_scrolls_plugin.rb', line 734 def dump_absolute_form_ids @form_ids.sort.each do |form_id| puts "* [#{form_id}] - #{absolute_form_id(form_id)}" end end |
#dump_masters ⇒ Object
Dump masters
727 728 729 730 731 |
# File 'lib/elder_scrolls_plugin.rb', line 727 def dump_masters @masters.each.with_index do |master, idx| puts "* [#{sprintf('%.2x', idx)}] - #{master}" end end |
#to_json(chunk = nil) ⇒ Object
Return the esp content as JSON
- Parameters
-
chunk (Riffola::Chunk or nil): The node to be dumped, or nil for root [default = nil]
- Result
-
Hash: JSON object
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 |
# File 'lib/elder_scrolls_plugin.rb', line 746 def to_json(chunk = nil) esp_info = chunk.nil? ? { type: :root, description: 'root' } : chunk.instance_variable_get(:@esp_info) json = { name: chunk.nil? ? 'ROOT' : chunk.name } json[:type] = esp_info[:type] unless esp_info[:type].nil? json[:description] = esp_info[:description] unless esp_info[:description].nil? json[:decoded_data] = esp_info[:decoded_data] unless esp_info[:decoded_data].nil? json[:decoded_header] = esp_info[:decoded_header] unless esp_info[:decoded_header].nil? unless chunk.nil? if esp_info[:decoded_header].nil? header = chunk.header json[:header] = (header.ascii_only? ? header : Base64.encode64(header)) unless header.empty? end if esp_info[:type] == :field && esp_info[:decoded_data].nil? data = chunk.data json[:data] = (data.ascii_only? ? data : Base64.encode64(data)) end end json[:sub_chunks] = @chunks_tree[chunk]. map { |sub_chunk| to_json(sub_chunk) }. sort_by { |chunk_json| [chunk_json[:name], chunk_json[:description], chunk_json[:data]] } if @chunks_tree[chunk].size > 0 json end |