diff options
Diffstat (limited to 'utils/validate_config.rb')
| -rw-r--r-- | utils/validate_config.rb | 329 |
1 files changed, 329 insertions, 0 deletions
| diff --git a/utils/validate_config.rb b/utils/validate_config.rb new file mode 100644 index 0000000..ed2e905 --- /dev/null +++ b/utils/validate_config.rb | |||
| @@ -0,0 +1,329 @@ | |||
| 1 | # Script to validate a level config file. This checks that the names used within | ||
| 2 | # the file are consistent. It also checks that the panel and door IDs mentioned | ||
| 3 | # all exist in the map file. | ||
| 4 | # | ||
| 5 | # Usage: validate_config.rb [config file] [map file] | ||
| 6 | |||
| 7 | require 'set' | ||
| 8 | require 'yaml' | ||
| 9 | |||
| 10 | configpath = ARGV[0] | ||
| 11 | mappath = ARGV[1] | ||
| 12 | |||
| 13 | panels = Set["Countdown Panels/Panel_1234567890_wanderlust"] | ||
| 14 | doors = Set["Naps Room Doors/Door_hider_new1", "Tower Room Area Doors/Door_wanderer_entrance"] | ||
| 15 | paintings = Set[] | ||
| 16 | |||
| 17 | File.readlines(mappath).each do |line| | ||
| 18 | line.match(/node name=\"(.*)\" parent=\"Panels\/(.*)\" instance/) do |m| | ||
| 19 | panels.add(m[2] + "/" + m[1]) | ||
| 20 | end | ||
| 21 | line.match(/node name=\"(.*)\" parent=\"Doors\/(.*)\" instance/) do |m| | ||
| 22 | doors.add(m[2] + "/" + m[1]) | ||
| 23 | end | ||
| 24 | line.match(/node name=\"(.*)\" parent=\"Decorations\/Paintings\" instance/) do |m| | ||
| 25 | paintings.add(m[1]) | ||
| 26 | end | ||
| 27 | line.match(/node name=\"(.*)\" parent=\"Decorations\/EndPanel\" instance/) do |m| | ||
| 28 | panels.add("EndPanel/" + m[1]) | ||
| 29 | end | ||
| 30 | end | ||
| 31 | |||
| 32 | configured_rooms = Set["Menu"] | ||
| 33 | configured_doors = Set[] | ||
| 34 | configured_panels = Set[] | ||
| 35 | |||
| 36 | mentioned_rooms = Set[] | ||
| 37 | mentioned_doors = Set[] | ||
| 38 | mentioned_panels = Set[] | ||
| 39 | |||
| 40 | door_groups = {} | ||
| 41 | |||
| 42 | directives = Set["entrances", "panels", "doors", "paintings", "progression"] | ||
| 43 | panel_directives = Set["id", "required_room", "required_door", "required_panel", "colors", "check", "exclude_reduce", "tag", "link", "subtag", "achievement", "copy_to_sign", "non_counting"] | ||
| 44 | door_directives = Set["id", "painting_id", "panels", "item_name", "location_name", "skip_location", "skip_item", "group", "include_reduce", "junk_item", "event"] | ||
| 45 | painting_directives = Set["id", "enter_only", "exit_only", "orientation", "required_door", "required", "required_when_no_doors", "move"] | ||
| 46 | |||
| 47 | non_counting = 0 | ||
| 48 | |||
| 49 | config = YAML.load_file(configpath) | ||
| 50 | config.each do |room_name, room| | ||
| 51 | configured_rooms.add(room_name) | ||
| 52 | |||
| 53 | used_directives = Set[] | ||
| 54 | room.each_key do |key| | ||
| 55 | used_directives.add(key) | ||
| 56 | end | ||
| 57 | diff_directives = used_directives - directives | ||
| 58 | unless diff_directives.empty? then | ||
| 59 | puts("#{room_name} has the following invalid top-level directives: #{diff_directives.to_s}") | ||
| 60 | end | ||
| 61 | |||
| 62 | (room["entrances"] || {}).each do |source_room, entrance| | ||
| 63 | mentioned_rooms.add(source_room) | ||
| 64 | |||
| 65 | entrances = [] | ||
| 66 | if entrance.kind_of? Hash | ||
| 67 | if entrance.keys() != ["painting"] then | ||
| 68 | entrances = [entrance] | ||
| 69 | end | ||
| 70 | elsif entrance.kind_of? Array | ||
| 71 | entrances = entrance | ||
| 72 | end | ||
| 73 | |||
| 74 | entrances.each do |e| | ||
| 75 | entrance_room = e.include?("room") ? e["room"] : room_name | ||
| 76 | mentioned_rooms.add(entrance_room) | ||
| 77 | mentioned_doors.add(entrance_room + " - " + e["door"]) | ||
| 78 | end | ||
| 79 | end | ||
| 80 | |||
| 81 | (room["panels"] || {}).each do |panel_name, panel| | ||
| 82 | unless panel_name.kind_of? String then | ||
| 83 | puts "#{room_name} has an invalid panel name" | ||
| 84 | end | ||
| 85 | |||
| 86 | configured_panels.add(room_name + " - " + panel_name) | ||
| 87 | |||
| 88 | if panel.include?("id") | ||
| 89 | panel_ids = [] | ||
| 90 | if panel["id"].kind_of? Array | ||
| 91 | panel_ids = panel["id"] | ||
| 92 | else | ||
| 93 | panel_ids = [panel["id"]] | ||
| 94 | end | ||
| 95 | |||
| 96 | panel_ids.each do |panel_id| | ||
| 97 | unless panels.include? panel_id then | ||
| 98 | puts "#{room_name} - #{panel_name} :::: Invalid Panel ID #{panel_id}" | ||
| 99 | end | ||
| 100 | end | ||
| 101 | else | ||
| 102 | puts "#{room_name} - #{panel_name} :::: Panel is missing an ID" | ||
| 103 | end | ||
| 104 | |||
| 105 | if panel.include?("required_room") | ||
| 106 | required_rooms = [] | ||
| 107 | if panel["required_room"].kind_of? Array | ||
| 108 | required_rooms = panel["required_room"] | ||
| 109 | else | ||
| 110 | required_rooms = [panel["required_room"]] | ||
| 111 | end | ||
| 112 | |||
| 113 | required_rooms.each do |required_room| | ||
| 114 | mentioned_rooms.add(required_room) | ||
| 115 | end | ||
| 116 | end | ||
| 117 | |||
| 118 | if panel.include?("required_door") | ||
| 119 | required_doors = [] | ||
| 120 | if panel["required_door"].kind_of? Array | ||
| 121 | required_doors = panel["required_door"] | ||
| 122 | else | ||
| 123 | required_doors = [panel["required_door"]] | ||
| 124 | end | ||
| 125 | |||
| 126 | required_doors.each do |required_door| | ||
| 127 | other_room = required_door.include?("room") ? required_door["room"] : room_name | ||
| 128 | mentioned_rooms.add(other_room) | ||
| 129 | mentioned_doors.add("#{other_room} - #{required_door["door"]}") | ||
| 130 | end | ||
| 131 | end | ||
| 132 | |||
| 133 | if panel.include?("required_panel") | ||
| 134 | required_panels = [] | ||
| 135 | if panel["required_panel"].kind_of? Array | ||
| 136 | required_panels = panel["required_panel"] | ||
| 137 | else | ||
| 138 | required_panels = [panel["required_panel"]] | ||
| 139 | end | ||
| 140 | |||
| 141 | required_panels.each do |required_panel| | ||
| 142 | other_room = required_panel.include?("room") ? required_panel["room"] : room_name | ||
| 143 | mentioned_rooms.add(other_room) | ||
| 144 | mentioned_panels.add("#{other_room} - #{required_panel["panel"]}") | ||
| 145 | end | ||
| 146 | end | ||
| 147 | |||
| 148 | unless panel.include?("tag") then | ||
| 149 | puts "#{room_name} - #{panel_name} :::: Panel is missing a tag" | ||
| 150 | end | ||
| 151 | |||
| 152 | if panel.include?("non_counting") then | ||
| 153 | non_counting += 1 | ||
| 154 | end | ||
| 155 | |||
| 156 | bad_subdirectives = [] | ||
| 157 | panel.keys.each do |key| | ||
| 158 | unless panel_directives.include?(key) then | ||
| 159 | bad_subdirectives << key | ||
| 160 | end | ||
| 161 | end | ||
| 162 | unless bad_subdirectives.empty? then | ||
| 163 | puts "#{room_name} - #{panel_name} :::: Panel has the following invalid subdirectives: #{bad_subdirectives.join(", ")}" | ||
| 164 | end | ||
| 165 | end | ||
| 166 | |||
| 167 | (room["doors"] || {}).each do |door_name, door| | ||
| 168 | configured_doors.add("#{room_name} - #{door_name}") | ||
| 169 | |||
| 170 | if door.include?("id") | ||
| 171 | door_ids = [] | ||
| 172 | if door["id"].kind_of? Array | ||
| 173 | door_ids = door["id"] | ||
| 174 | else | ||
| 175 | door_ids = [door["id"]] | ||
| 176 | end | ||
| 177 | |||
| 178 | door_ids.each do |door_id| | ||
| 179 | unless doors.include? door_id then | ||
| 180 | puts "#{room_name} - #{door_name} :::: Invalid Door ID #{door_id}" | ||
| 181 | end | ||
| 182 | end | ||
| 183 | end | ||
| 184 | |||
| 185 | if door.include?("painting_id") | ||
| 186 | painting_ids = [] | ||
| 187 | if door["painting_id"].kind_of? Array | ||
| 188 | painting_ids = door["painting_id"] | ||
| 189 | else | ||
| 190 | painting_ids = [door["painting_id"]] | ||
| 191 | end | ||
| 192 | |||
| 193 | painting_ids.each do |painting_id| | ||
| 194 | unless paintings.include? painting_id then | ||
| 195 | puts "#{room_name} - #{door_name} :::: Invalid Painting ID #{painting_id}" | ||
| 196 | end | ||
| 197 | end | ||
| 198 | end | ||
| 199 | |||
| 200 | if not door.include?("id") and not door.include?("painting_id") and not door["skip_item"] and not door["event"] then | ||
| 201 | puts "#{room_name} - #{door_name} :::: Should be marked skip_item or event if there are no doors or paintings" | ||
| 202 | end | ||
| 203 | |||
| 204 | if door.include?("panels") | ||
| 205 | door["panels"].each do |panel| | ||
| 206 | if panel.kind_of? Hash then | ||
| 207 | other_room = panel.include?("room") ? panel["room"] : room_name | ||
| 208 | mentioned_panels.add("#{other_room} - #{panel["panel"]}") | ||
| 209 | else | ||
| 210 | other_room = panel.include?("room") ? panel["room"] : room_name | ||
| 211 | mentioned_panels.add("#{room_name} - #{panel}") | ||
| 212 | end | ||
| 213 | end | ||
| 214 | elsif not door["skip_location"] | ||
| 215 | puts "#{room_name} - #{door_name} :::: Should be marked skip_location if there are no panels" | ||
| 216 | end | ||
| 217 | |||
| 218 | if door.include?("group") | ||
| 219 | door_groups[door["group"]] ||= 0 | ||
| 220 | door_groups[door["group"]] += 1 | ||
| 221 | end | ||
| 222 | |||
| 223 | bad_subdirectives = [] | ||
| 224 | door.keys.each do |key| | ||
| 225 | unless door_directives.include?(key) then | ||
| 226 | bad_subdirectives << key | ||
| 227 | end | ||
| 228 | end | ||
| 229 | unless bad_subdirectives.empty? then | ||
| 230 | puts "#{room_name} - #{door_name} :::: Door has the following invalid subdirectives: #{bad_subdirectives.join(", ")}" | ||
| 231 | end | ||
| 232 | end | ||
| 233 | |||
| 234 | (room["paintings"] || []).each do |painting| | ||
| 235 | if painting.include?("id") and painting["id"].kind_of? String then | ||
| 236 | unless paintings.include? painting["id"] then | ||
| 237 | puts "#{room_name} :::: Invalid Painting ID #{painting["id"]}" | ||
| 238 | end | ||
| 239 | else | ||
| 240 | puts "#{room_name} :::: Painting is missing an ID" | ||
| 241 | end | ||
| 242 | |||
| 243 | if painting["disable"] then | ||
| 244 | # We're good. | ||
| 245 | next | ||
| 246 | end | ||
| 247 | |||
| 248 | if painting.include?("orientation") then | ||
| 249 | unless ["north", "south", "east", "west"].include? painting["orientation"] then | ||
| 250 | puts "#{room_name} - #{painting["id"] || "painting"} :::: Invalid orientation #{painting["orientation"]}" | ||
| 251 | end | ||
| 252 | else | ||
| 253 | puts "#{room_name} :::: Painting is missing an orientation" | ||
| 254 | end | ||
| 255 | |||
| 256 | if painting.include?("required_door") | ||
| 257 | other_room = painting["required_door"].include?("room") ? painting["required_door"]["room"] : room_name | ||
| 258 | mentioned_doors.add("#{other_room} - #{painting["required_door"]["door"]}") | ||
| 259 | |||
| 260 | unless painting["enter_only"] then | ||
| 261 | puts "#{room_name} - #{painting["id"] || "painting"} :::: Should be marked enter_only if there is a required_door" | ||
| 262 | end | ||
| 263 | end | ||
| 264 | |||
| 265 | bad_subdirectives = [] | ||
| 266 | painting.keys.each do |key| | ||
| 267 | unless painting_directives.include?(key) then | ||
| 268 | bad_subdirectives << key | ||
| 269 | end | ||
| 270 | end | ||
| 271 | unless bad_subdirectives.empty? then | ||
| 272 | puts "#{room_name} - #{painting["id"] || "painting"} :::: Painting has the following invalid subdirectives: #{bad_subdirectives.join(", ")}" | ||
| 273 | end | ||
| 274 | end | ||
| 275 | |||
| 276 | (room["progression"] || {}).each do |progression_name, door_list| | ||
| 277 | door_list.each do |door| | ||
| 278 | if door.kind_of? Hash then | ||
| 279 | mentioned_doors.add("#{door["room"]} - #{door["door"]}") | ||
| 280 | else | ||
| 281 | mentioned_doors.add("#{room_name} - #{door}") | ||
| 282 | end | ||
| 283 | end | ||
| 284 | end | ||
| 285 | end | ||
| 286 | |||
| 287 | errored_rooms = mentioned_rooms - configured_rooms | ||
| 288 | unless errored_rooms.empty? then | ||
| 289 | puts "The folloring rooms are mentioned but do not exist: " + errored_rooms.to_s | ||
| 290 | end | ||
| 291 | |||
| 292 | errored_panels = mentioned_panels - configured_panels | ||
| 293 | unless errored_panels.empty? then | ||
| 294 | puts "The folloring panels are mentioned but do not exist: " + errored_panels.to_s | ||
| 295 | end | ||
| 296 | |||
| 297 | errored_doors = mentioned_doors - configured_doors | ||
| 298 | unless errored_doors.empty? then | ||
| 299 | puts "The folloring doors are mentioned but do not exist: " + errored_doors.to_s | ||
| 300 | end | ||
| 301 | |||
| 302 | door_groups.each do |group,num| | ||
| 303 | if num == 1 then | ||
| 304 | puts "Door group \"#{group}\" only has one door in it" | ||
| 305 | end | ||
| 306 | end | ||
| 307 | |||
| 308 | slashed_rooms = configured_rooms.select do |room| | ||
| 309 | room.include? "/" | ||
| 310 | end | ||
| 311 | unless slashed_rooms.empty? then | ||
| 312 | puts "The following rooms have slashes in their names: " + slashed_rooms.to_s | ||
| 313 | end | ||
| 314 | |||
| 315 | slashed_panels = configured_panels.select do |panel| | ||
| 316 | panel.include? "/" | ||
| 317 | end | ||
| 318 | unless slashed_panels.empty? then | ||
| 319 | puts "The following panels have slashes in their names: " + slashed_panels.to_s | ||
| 320 | end | ||
| 321 | |||
| 322 | slashed_doors = configured_doors.select do |door| | ||
| 323 | door.include? "/" | ||
| 324 | end | ||
| 325 | unless slashed_doors.empty? then | ||
| 326 | puts "The following doors have slashes in their names: " + slashed_doors.to_s | ||
| 327 | end | ||
| 328 | |||
| 329 | puts "#{configured_panels.size} panels (#{non_counting} non counting)" | ||
