Squashed commit of the following:
[xonotic/xonotic-maps.pk3dir.git] / maps / entmerge.rb
1 #!/usr/bin/ruby
2
3 require 'yaml'
4
5 def preprocess(s)
6         return s.split(/\r?\n/).find_all() do |l| l[0, 2] != '//' end
7 end
8
9 base = ARGV[0]
10
11 mapstr = File.read("#{base}.map")
12 entstr = File.read("#{base}.ent")
13
14 # backup
15 File.open("#{base}.map~", "w") do |fh|
16         fh.write(mapstr)
17 end
18 File.open("#{base}.ent~", "w") do |fh|
19         fh.write(entstr)
20 end
21
22 def brushparse(l, index)
23         brush = []
24         nest = 0
25         while index < l.length()
26                 case l[index]
27                         when '}'
28                                 nest -= 1
29                                 if nest < 0
30                                         break
31                                 else
32                                         brush << '}'
33                                 end
34                         when '{'
35                                 nest += 1
36                                 brush << '{'
37                         when %r{^(.*)$}
38                                 brush << $1
39                         when ''
40                                 true
41                         else
42                                 raise SyntaxError, "in brush: " + l[index]
43                 end
44                 index += 1
45         end
46         return index, brush
47 end
48
49 def entparse(l, index)
50         entity = {}
51         brushes = []
52         while index < l.length()
53                 case l[index]
54                         when '}'
55                                 break
56                         when '{'
57                                 index, brush = brushparse(l, index + 1)
58                                 brushes << brush
59                         when %r{^"([^"]*)" "(.*)"$}
60                                 entity[$1] = $2
61                         when ''
62                                 true
63                         else
64                                 raise SyntaxError, "in entity: " + l[index]
65                 end
66                 index += 1
67         end
68         if brushes != []
69                 entity[:brushes] = brushes
70         end
71         return index, entity
72 end
73
74 def mapparse(l)
75         allents = []
76         index = 0
77         while index < l.length()
78                 case l[index]
79                         when '{'
80                                 index, entity = entparse(l, index + 1)
81                                 allents << entity
82                         when ''
83                                 true
84                         else
85                                 raise SyntaxError, "in map: " + l[index]
86                 end
87                 index += 1
88         end
89         return allents
90 end
91
92
93
94 def brushout(b)
95         yield '{'
96         b.each() do |l|
97                 yield l
98         end
99         yield '}'
100 end
101
102 def entout(e)
103         yield '{'
104         e.each() do |k, v|
105                 next if k == :brushes
106                 yield '"%s" "%s"' % [k, v]
107         end
108         if e[:brushes]
109                 e[:brushes].each() do |b|
110                         brushout(b) do |l|
111                                 yield l
112                         end
113                 end
114         end
115         yield '}'
116 end
117
118 def mapout(entities)
119         entities.each() do |e|
120                 entout(e) do |l|
121                         yield l
122                 end
123         end
124 end
125
126 map = mapparse(preprocess(mapstr))
127 ent = mapparse(preprocess(entstr))
128
129 submodels = []
130 unchanged = []
131
132 map.each() do |e|
133         case
134                 when e['classname'] == 'light'
135                         unchanged << e
136                 when e['classname'] == 'func_group'
137                         unchanged << e
138                 when e[:brushes]
139                         submodels << e[:brushes]
140         end
141 end
142
143 ent.each() do |e|
144         case
145                 when (e['classname'] == 'worldspawn') || (e['model'] && e['model'][0, 1] == '*')
146                         e.delete('model')
147                         e[:brushes] = submodels.shift()
148         end
149 end
150
151 File.open("#{base}.map", "w") do |fh|
152         mapout(ent + unchanged) do |l|
153                 fh.puts(l)
154         end
155 end
156
157 File.unlink("#{base}.ent")