fusionpacker 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/gem-push.yml +46 -0
- data/.gitignore +35 -0
- data/Gemfile +4 -0
- data/LICENSE +17 -0
- data/README.md +124 -0
- data/Rakefile +2 -0
- data/bin/fusionpacker +39 -0
- data/fusionpacker.gemspec +26 -0
- data/lib/RGSS/BasicCoder.rb +49 -0
- data/lib/RGSS/psych_mods.rb +129 -0
- data/lib/RGSS/serialize.rb +378 -0
- data/lib/RGSS.rb +336 -0
- data/lib/RPG.rb +57 -0
- data/lib/fusionpacker/version.rb +3 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 16a139ec8eabfb17469f23beae8d71e336e26c3705f9187fed62837aa72f96e2
|
4
|
+
data.tar.gz: 762a7c9c3313cf33585e325e770fc61b5707b4d8af4e99284cd6f1b3ba3a7e19
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b6fb572dd6e9c270d233818d483e194a9af344f879ba647d668362907aae0ef18cd592b7b828f1f518b8811d240d8d7372e8a142eb3f39cd34b1d9e61782c0a2
|
7
|
+
data.tar.gz: 27a4dee1cd302d20a5d16921324f83f11c5fd07e9bf426831f9cb6bb19b0334e82aa83d42e4a91574dbc0bfb978a76652146719f25e87d73b876444176356983
|
@@ -0,0 +1,46 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ "master" ]
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
build:
|
9
|
+
name: Build + Publish
|
10
|
+
runs-on: [self-hosted, ARM64]
|
11
|
+
permissions:
|
12
|
+
contents: read
|
13
|
+
packages: write
|
14
|
+
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v3
|
17
|
+
# - name: Set up Ruby 2.6
|
18
|
+
# # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
19
|
+
# # change this to (see https://github.com/ruby/setup-ruby#versioning):
|
20
|
+
# uses: ruby/setup-ruby@v1
|
21
|
+
# # uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
|
22
|
+
# with:
|
23
|
+
# ruby-version: 3.2.0
|
24
|
+
|
25
|
+
- name: Publish to GPR
|
26
|
+
run: |
|
27
|
+
mkdir -p ${{ runner.temp }}/.gem
|
28
|
+
touch ${{ runner.temp }}/.gem/credentials
|
29
|
+
chmod 0600 ${{ runner.temp }}/.gem/credentials
|
30
|
+
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > ${{ runner.temp }}/.gem/credentials
|
31
|
+
gem build *.gemspec
|
32
|
+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
33
|
+
env:
|
34
|
+
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
35
|
+
OWNER: ${{ github.repository_owner }}
|
36
|
+
|
37
|
+
- name: Publish to RubyGems
|
38
|
+
run: |
|
39
|
+
mkdir -p ${{ runner.temp }}/.gem
|
40
|
+
touch ${{ runner.temp }}/.gem/credentials
|
41
|
+
chmod 0600 ${{ runner.temp }}/.gem/credentials
|
42
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > ${{ runner.temp }}/.gem/credentials
|
43
|
+
gem build *.gemspec
|
44
|
+
gem push *.gem
|
45
|
+
env:
|
46
|
+
GEM_HOST_API_KEY: "${{secrets.EDDIE_RUBY_GEMS}}"
|
data/.gitignore
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
.idea
|
12
|
+
|
13
|
+
## Specific to RubyMotion:
|
14
|
+
.dat*
|
15
|
+
.repl_history
|
16
|
+
build/
|
17
|
+
|
18
|
+
## Documentation cache and generated files:
|
19
|
+
/.yardoc/
|
20
|
+
/_yardoc/
|
21
|
+
/doc/
|
22
|
+
/rdoc/
|
23
|
+
|
24
|
+
## Environment normalisation:
|
25
|
+
/.bundle/
|
26
|
+
/lib/bundler/man/
|
27
|
+
|
28
|
+
# for a library or gem, you might want to ignore these files since the code is
|
29
|
+
# intended to run in multiple environments; otherwise, check them in:
|
30
|
+
Gemfile.lock
|
31
|
+
.ruby-version
|
32
|
+
.ruby-gemset
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Copyright (c) 2013 Howard Jeng
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
4
|
+
software and associated documentation files (the "Software"), to deal in the Software
|
5
|
+
without restriction, including without limitation the rights to use, copy, modify, merge,
|
6
|
+
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
7
|
+
to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or
|
10
|
+
substantial portions of the Software.
|
11
|
+
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
13
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
14
|
+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
15
|
+
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
16
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
17
|
+
DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
rvpacker (fusion mode)
|
2
|
+
======================
|
3
|
+
|
4
|
+
A fork of rvpacker altered to work as an automatic development workflow for infinitefusion18.
|
5
|
+
|
6
|
+
rvpacker consists of 3 parts:
|
7
|
+
|
8
|
+
* RPG library (stub classes for serialization of RPGMaker game data)
|
9
|
+
* RGSS library (some more classes for RPGMaker serialization)
|
10
|
+
* rvpacker (the script you call on the frontend)
|
11
|
+
|
12
|
+
Credit to Solistra
|
13
|
+
=================
|
14
|
+
|
15
|
+
Homie bundled this all into rvpacker 9 years ago... lets hear it for them.
|
16
|
+
|
17
|
+
[Let that mf know](https://github.com/Solistra/rvpacker)
|
18
|
+
|
19
|
+
Credit to SiCrane
|
20
|
+
=================
|
21
|
+
|
22
|
+
The RPG and RGSS libraries were originally taken from SiCrane's YAML importer/exporter on the gamedev forums. I initially just put them in github so I wouldn't lose them, and added the rvpacker script frontend. They are starting to drift a bit, but SiCrane still gets original credit for the grand majority of the work that rvpacker does.
|
23
|
+
|
24
|
+
http://www.gamedev.net/topic/646333-rpg-maker-vx-ace-data-conversion-utility/
|
25
|
+
|
26
|
+
Installation
|
27
|
+
============
|
28
|
+
|
29
|
+
rvpacker is bundled as a rubygem
|
30
|
+
|
31
|
+
$ gem install rvpacker
|
32
|
+
|
33
|
+
... dependencies will be handled automatically.
|
34
|
+
|
35
|
+
**Windows Users:** If `gem install rvpacker` complains about being unable to install psych, try downloading the rvpacker source and doing `bundle install`. That, for some reason, works. (Don't ask me, I think ruby is retarded here.) *Alternatively*, you can [download the Ruby DevKit](http://rubyinstaller.org/downloads) and install it by following [these instructions](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit) - this works for lots of users, but not for me personally, so you may still wind up having to do the bundle install trick.
|
36
|
+
|
37
|
+
Usage
|
38
|
+
=====
|
39
|
+
|
40
|
+
$ rvpacker --help
|
41
|
+
Options:
|
42
|
+
--action, -a <s>: Action to perform on project (unpack|pack)
|
43
|
+
--project, -d <s>: RPG Maker Project directory
|
44
|
+
--force, -f: Update target even when source is older than target
|
45
|
+
--project-type, -t <s>: Project type (vx|ace|xp)
|
46
|
+
--help, -h: Show this message
|
47
|
+
|
48
|
+
For example, to unpack a RPG Maker VX Ace project in ~/Documents/RPGVXAce/Project1:
|
49
|
+
|
50
|
+
rvpacker --action unpack --project ~/Documents/RPGVXAce/Project1 --project-type ace
|
51
|
+
|
52
|
+
... This will expand all Data/* files into (PROJECT)/YAML/ as YAML files (YAML is used because the object serialization data is retained, which ruby's YAML parser is very good at - otherwise I would have changed it to JSON). The Scripts will be unpacked as individual .rb files into (PROJECT)/Scripts/.
|
53
|
+
|
54
|
+
To take a previously unpacked project, and pack it back up:
|
55
|
+
|
56
|
+
rvpacker --action pack --project ~/Documents/RPGVXAce/Project1 --project-type ace
|
57
|
+
|
58
|
+
... This will take all of the yaml files in (PROJECT)/YAML and all the scripts in (PROJECT)/Scripts, and repack all of your (PROJECT)/Data/* files. You can trust this to completely reassemble your Data/ directory, so long as the Scripts/ and YAML/ directories remain intact.
|
59
|
+
|
60
|
+
To convert a specific file or files under `project/Data`:
|
61
|
+
|
62
|
+
`rvpacker --action unpack --project ..\infinitefusion-e18\ -f --project-type xp --verbose -l Map001.rxdata Map002.rxdata`
|
63
|
+
|
64
|
+
... This will convert only Map001.rxdata and Map002.rxdata
|
65
|
+
Workflow : General
|
66
|
+
========
|
67
|
+
|
68
|
+
This is great for teams that are collaborating on an RPG Maker project. Just add a few steps to your existing workflow:
|
69
|
+
|
70
|
+
* Checkout the project from version control
|
71
|
+
* Run 'rvpacker --action pack' on the project to repack it for the RPG Maker tool
|
72
|
+
* Load up RPG Maker and do whatever you're going to do; save the project
|
73
|
+
* Run 'rvpacker --action unpack' on the project
|
74
|
+
* Commit everything to version control (ignore the Data directory since you don't need it anymore; use .gitignore or .hgignore or whatever)
|
75
|
+
|
76
|
+
... Now your project can be forked/merged in a much more safe/sane way, and you don't have to have someone bottlenecking the entire process.
|
77
|
+
|
78
|
+
Workflow : Avoiding Map Collisions
|
79
|
+
=======================
|
80
|
+
|
81
|
+
One thing that rvpacker really can't help you with right now (and, ironically, probably one of the reasons you want it) is map collisions. Consider this situation:
|
82
|
+
|
83
|
+
* The project has 10 maps in it, total.
|
84
|
+
* Developer A makes a new map. It gets saved by the editor as Map011
|
85
|
+
* Developer B makes a new map, in a different branch. It also gets saved by the editor as Map011.
|
86
|
+
* Developer A and Developer B attempt to merge their changes. The merge fails because of the collision on the Map011 file.
|
87
|
+
|
88
|
+
The best way to avoid this that I can see is to use blocks of pre-allocated maps. You appoint one person in your project to be principally responsible for the map assets. It then becomes this person's responsibility to allocate maps in "blocks", so that people can work on maps in a distributed way without clobbering one another. The workflow looks like this:
|
89
|
+
|
90
|
+
* The project has 10 maps in it, total.
|
91
|
+
* Developer A needs to make 4 maps. He sends a request to the "map owner", requesting a block of 4 maps.
|
92
|
+
* The map owner creates 4 default, blank maps, and names them all "Request #12345" for Developer A
|
93
|
+
* Developer A starts working on his maps
|
94
|
+
* Developer B needs to make 6 maps. He sends a request to the "map owner", requesting a block of 6 maps.
|
95
|
+
* The map owner 4 default, blank maps, and names them all "Request #12346" or something similar for Developer B
|
96
|
+
* Developer B starts working on his maps
|
97
|
+
|
98
|
+
Using this workflow, it doesn't matter what order Developers A and B request their map blocks, or what order the map owner creates their map blocks. By giving the map owner the authority to create the map blocks, the individual developers can work freely in their map blocks. They can rename them, reorder them, change all of the map attributes (Size, tileset, whatever), without getting in danger of a map collision.
|
99
|
+
|
100
|
+
While this may seem like unnecessary process, it is a reasonable workaround. For a better explanation of why rvpacker can't do this for you, read the next section.
|
101
|
+
|
102
|
+
Automatic ID generation
|
103
|
+
=======================
|
104
|
+
|
105
|
+
(Removed because that's not how Pokemon Essentials reads scripts)
|
106
|
+
|
107
|
+
Why rvpacker can't help with map collisions
|
108
|
+
===========================================
|
109
|
+
|
110
|
+
If you look at the map collision problem described above, the way out of this situation might seem obvious: "Rename Map011.yaml in one of the branches to Map012.yaml, and problem solved. However, there are several significant problems with this approach:
|
111
|
+
|
112
|
+
* The ID numbers on the map files correspond to ID number entries in MapInfos.yaml (and the corresponding MapInfos.rvdata objects)
|
113
|
+
* The ID numbers are used to specify a parent/child relationship between one or more maps
|
114
|
+
* The ID numbers are used to specify the target of a map transition/warp event in event scripting
|
115
|
+
|
116
|
+
This means that changing the ID number assigned to a map (and, thereby, making it possible to merge 2 maps with the same ID number) becomes very nontrivial. The event scripting portion, especially, presents a difficult problem for rvpacker to overcome. It is simple enough for rvpacker to change the IDs of any new map created, and to change the reference to that ID number from any child maps. However, the events are where it gets sticky. The format of event calls in RPG Maker map files is not terribly well defined, and even if it was, I sincerely doubt that you want rvpacker tearing around in the guts of your map events.
|
117
|
+
|
118
|
+
|
119
|
+
Psych 2.0.0 Dependency
|
120
|
+
======================
|
121
|
+
|
122
|
+
From SiCrane:
|
123
|
+
|
124
|
+
I used cygwin's ruby 1.9.3 and the Psych 2.0.0 ruby gem, which appears to be the most recent version. However, Psych 2.0.0 has some bugs that impacted the generated YAML (one major and one minor) which I monkey patched, and since I was already rewriting the Psych code, I added some functionality to make the generated YAML prettier. Long story short, this code probably won't work with any version of Psych but 2.0.0.
|
data/Rakefile
ADDED
data/bin/fusionpacker
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
|
4
|
+
require 'optimist'
|
5
|
+
require 'RGSS'
|
6
|
+
|
7
|
+
opts = Optimist::options do
|
8
|
+
opt :action, "Action to perform on project (unpack|pack)", :short => "a", :type => String
|
9
|
+
opt :project, "RPG Maker Project directory", :short => "d", :type => String
|
10
|
+
opt :force, "Update target even when source is older than target", :short => "f"
|
11
|
+
opt :project_type, "Project type (vx|ace|xp)", :short => "t", :type => String
|
12
|
+
opt :verbose, "Print verbose information while processing", :short => "V"
|
13
|
+
opt :scripts, "Convert scripts contained in /project/Scripts", :default => false
|
14
|
+
opt :saves, "Convert saves contained in /project", :default => false
|
15
|
+
opt :files, "Array of files to convert instead, delimited by spaces", :short => "l", :type => :strings
|
16
|
+
end
|
17
|
+
|
18
|
+
directions = {
|
19
|
+
"unpack" => :all_bin_to_text,
|
20
|
+
"pack" => :all_text_to_bin
|
21
|
+
}
|
22
|
+
projecttypes = {
|
23
|
+
"vx" => :vx,
|
24
|
+
"ace" => :ace,
|
25
|
+
"xp" => :xp
|
26
|
+
}
|
27
|
+
$VERBOSE = opts[:verbose]
|
28
|
+
|
29
|
+
RGSS.serialize(projecttypes[opts[:project_type]],
|
30
|
+
directions[opts[:action]],
|
31
|
+
opts[:project],
|
32
|
+
{ :force => (opts[:force] ? true : false),
|
33
|
+
:line_width => -1,
|
34
|
+
:table_width => -1,
|
35
|
+
:database => { :saves => opts[:saves], :scripts => opts[:scripts] },
|
36
|
+
:files => opts[:files]
|
37
|
+
}
|
38
|
+
)
|
39
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fusionpacker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'fusionpacker'
|
8
|
+
spec.version = Fusionpacker::VERSION
|
9
|
+
spec.authors = ["Howard Jeng", "Andrew Kesterson", 'Solistra', 'eddperpich']
|
10
|
+
spec.email = ['eddperpich@gmail.com']
|
11
|
+
spec.summary = %q{Pack and unpack RPG Maker data files, for use on pokemon infinite fusion}
|
12
|
+
spec.homepage = "https://github.com/homie-estate/fusionpacker"
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 2.4"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
spec.add_dependency "optimist"
|
23
|
+
spec.add_dependency "scanf"
|
24
|
+
spec.add_dependency "psych", "2.0.0"
|
25
|
+
spec.add_dependency "formatador"
|
26
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RGSS
|
2
|
+
module BasicCoder
|
3
|
+
def encode_with(coder)
|
4
|
+
ivars.each do |var|
|
5
|
+
name = var.to_s.sub(/^@/, '')
|
6
|
+
value = instance_variable_get(var)
|
7
|
+
coder[name] = encode(name, value)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def encode(name, value)
|
12
|
+
return value
|
13
|
+
end
|
14
|
+
|
15
|
+
def init_with(coder)
|
16
|
+
coder.map.each do |key, value|
|
17
|
+
sym = "@#{key}".to_sym
|
18
|
+
instance_variable_set(sym, decode(key, value))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def decode(name, value)
|
23
|
+
return value
|
24
|
+
end
|
25
|
+
|
26
|
+
def ivars
|
27
|
+
return instance_variables
|
28
|
+
end
|
29
|
+
|
30
|
+
INCLUDED_CLASSES = []
|
31
|
+
def self.included(mod)
|
32
|
+
INCLUDED_CLASSES.push(mod)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.set_ivars_methods(version)
|
36
|
+
INCLUDED_CLASSES.each do |c|
|
37
|
+
if version == :ace
|
38
|
+
RGSS::reset_method(c, :ivars, ->{
|
39
|
+
return instance_variables
|
40
|
+
})
|
41
|
+
else
|
42
|
+
RGSS::reset_method(c, :ivars, ->{
|
43
|
+
return instance_variables.sort
|
44
|
+
})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
=begin
|
2
|
+
This file contains significant portions of Psych 2.0.0 to modify behavior and to fix
|
3
|
+
bugs. The license follows:
|
4
|
+
|
5
|
+
Copyright 2009 Aaron Patterson, et al.
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
8
|
+
software and associated documentation files (the 'Software'), to deal in the Software
|
9
|
+
without restriction, including without limitation the rights to use, copy, modify, merge,
|
10
|
+
publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
11
|
+
persons to whom the Software is furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in all copies or
|
14
|
+
substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
17
|
+
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
18
|
+
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
19
|
+
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
20
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
21
|
+
DEALINGS IN THE SOFTWARE.
|
22
|
+
=end
|
23
|
+
|
24
|
+
gem 'psych', '2.0.0'
|
25
|
+
require 'psych'
|
26
|
+
|
27
|
+
if Psych::VERSION == '2.0.0'
|
28
|
+
# Psych bugs:
|
29
|
+
#
|
30
|
+
# 1) Psych has a bug where it stores an anchor to the YAML for an object, but indexes
|
31
|
+
# the reference by object_id. This doesn't keep the object alive, so if it gets garbage
|
32
|
+
# collected, Ruby might generate an object with the same object_id and try to generate a
|
33
|
+
# reference to the stored anchor. This monkey-patches the Registrar to keep the object
|
34
|
+
# alive so incorrect references aren't generated. The bug is also present in Psych 1.3.4
|
35
|
+
# but there isn't a convenient way to patch that.
|
36
|
+
#
|
37
|
+
# 2) Psych also doesn't create references and anchors for classes that implement
|
38
|
+
# encode_with. This modifies dump_coder to handle that situation.
|
39
|
+
#
|
40
|
+
# Added two options:
|
41
|
+
# :sort - sort hashes and instance variables for objects
|
42
|
+
# :flow_classes - array of class types that will automatically emit with flow style
|
43
|
+
# rather than block style
|
44
|
+
module Psych
|
45
|
+
module Visitors
|
46
|
+
class YAMLTree < Psych::Visitors::Visitor
|
47
|
+
class Registrar
|
48
|
+
old_initialize = self.instance_method(:initialize)
|
49
|
+
define_method(:initialize) do
|
50
|
+
old_initialize.bind(self).call
|
51
|
+
@obj_to_obj = {}
|
52
|
+
end
|
53
|
+
|
54
|
+
old_register = self.instance_method(:register)
|
55
|
+
define_method(:register) do |target, node|
|
56
|
+
old_register.bind(self).call(target, node)
|
57
|
+
@obj_to_obj[target.object_id] = target
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
remove_method(:visit_Hash)
|
62
|
+
def visit_Hash o
|
63
|
+
tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}"
|
64
|
+
implicit = !tag
|
65
|
+
|
66
|
+
register(o, @emitter.start_mapping(nil, tag, implicit, Nodes::Mapping::BLOCK))
|
67
|
+
|
68
|
+
keys = o.keys
|
69
|
+
keys = keys.sort if @options[:sort]
|
70
|
+
keys.each do |k|
|
71
|
+
accept k
|
72
|
+
accept o[k]
|
73
|
+
end
|
74
|
+
|
75
|
+
@emitter.end_mapping
|
76
|
+
end
|
77
|
+
|
78
|
+
remove_method(:visit_Object)
|
79
|
+
def visit_Object o
|
80
|
+
tag = Psych.dump_tags[o.class]
|
81
|
+
unless tag
|
82
|
+
klass = o.class == Object ? nil : o.class.name
|
83
|
+
tag = ['!ruby/object', klass].compact.join(':')
|
84
|
+
end
|
85
|
+
|
86
|
+
if @options[:flow_classes] && @options[:flow_classes].include?(o.class)
|
87
|
+
style = Nodes::Mapping::FLOW
|
88
|
+
else
|
89
|
+
style = Nodes::Mapping::BLOCK
|
90
|
+
end
|
91
|
+
|
92
|
+
map = @emitter.start_mapping(nil, tag, false, style)
|
93
|
+
register(o, map)
|
94
|
+
|
95
|
+
dump_ivars o
|
96
|
+
@emitter.end_mapping
|
97
|
+
end
|
98
|
+
|
99
|
+
remove_method(:dump_coder)
|
100
|
+
def dump_coder o
|
101
|
+
@coders << o
|
102
|
+
tag = Psych.dump_tags[o.class]
|
103
|
+
unless tag
|
104
|
+
klass = o.class == Object ? nil : o.class.name
|
105
|
+
tag = ['!ruby/object', klass].compact.join(':')
|
106
|
+
end
|
107
|
+
|
108
|
+
c = Psych::Coder.new(tag)
|
109
|
+
o.encode_with(c)
|
110
|
+
register o, emit_coder(c)
|
111
|
+
end
|
112
|
+
|
113
|
+
remove_method(:dump_ivars)
|
114
|
+
def dump_ivars target
|
115
|
+
ivars = find_ivars target
|
116
|
+
ivars = ivars.sort() if @options[:sort]
|
117
|
+
|
118
|
+
ivars.each do |iv|
|
119
|
+
@emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY)
|
120
|
+
accept target.instance_variable_get(iv)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
else
|
128
|
+
warn "Warning: Psych 2.0.0 not detected" if $VERBOSE
|
129
|
+
end
|