// Near Infinity - An Infinity Engine Browser and Editor // Copyright (C) 2001 - 2005 Jon Olav Hauglid // See LICENSE.txt for license information package org.infinity.search; import java.awt.Component; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.infinity.datatype.Song2daBitmap; import org.infinity.datatype.ResourceBitmap.RefEntry; import org.infinity.resource.AbstractStruct; import org.infinity.resource.Profile; import org.infinity.resource.Resource; import org.infinity.resource.ResourceFactory; import org.infinity.resource.StructEntry; import org.infinity.resource.are.AreResource; import org.infinity.resource.are.Song; import org.infinity.resource.bcs.BcsResource; import org.infinity.resource.bcs.Decompiler; import org.infinity.resource.dlg.AbstractCode; import org.infinity.resource.dlg.DlgResource; import org.infinity.resource.key.ResourceEntry; import org.infinity.util.IdsMap; import org.infinity.util.IdsMapCache; import org.infinity.util.io.StreamUtils; public class SongReferenceSearcher extends AbstractReferenceSearcher { private final List<Pattern> scriptActions = new ArrayList<Pattern>(); private long songId; private ResourceEntry songEntry; public SongReferenceSearcher(ResourceEntry targetEntry, Component parent) { super(targetEntry, new String[]{"ARE", "BCS", "BS", "DLG"}, new boolean[]{true, true, false, true}, parent); init(targetEntry); } @Override protected void search(ResourceEntry entry, Resource resource) { if (resource instanceof AreResource) { searchAre(entry, (AreResource)resource); } else if (resource instanceof BcsResource) { searchBcs(entry, (BcsResource)resource); } else if (resource instanceof DlgResource) { searchDlg(entry, (DlgResource)resource); } else if (resource instanceof AbstractStruct) { searchStruct(entry, (AbstractStruct)resource); } } private void searchBcs(ResourceEntry entry, BcsResource bcs) { Decompiler decompiler = new Decompiler(bcs.getCode(), true); String text = decompiler.decompile(); searchText(entry, null, text); } private void searchDlg(ResourceEntry entry, DlgResource dlg) { List<StructEntry> list = dlg.getList(); for (final StructEntry e: list) { if (e instanceof AbstractCode) { String text = ((AbstractCode)e).getText(); searchText(entry, e, text); } } } private void searchText(ResourceEntry entry, StructEntry res, String text) { for (final Pattern pattern: scriptActions) { Matcher matcher = pattern.matcher(text); if (matcher.find()) { addHit(entry, matcher.group(), res); } } } private void searchAre(ResourceEntry entry, AreResource are) { StructEntry se = are.getAttribute(Song.ARE_SONGS); if (se instanceof AbstractStruct) { searchStruct(entry, (AbstractStruct)se); } } private void searchStruct(ResourceEntry entry, AbstractStruct struct) { List<StructEntry> list = struct.getFlatList(); for (final StructEntry e: list) { if (e instanceof Song2daBitmap) { int v = ((Song2daBitmap)e).getValue(); if (v == songId) { addHit(entry, String.format("%s (%d)", songEntry.getResourceName(), songId), e); } } } } private void init(ResourceEntry targetEntry) { songEntry = targetEntry; songId = -1L; Song2daBitmap songBitmap = new Song2daBitmap(StreamUtils.getByteBuffer(4), 0, 4); List<RefEntry> resList = songBitmap.getResourceList(); for (final RefEntry refEntry: resList) { ResourceEntry entry = refEntry.getResourceEntry(); if (entry != null && entry.equals(targetEntry)) { songId = refEntry.getValue(); break; } } if (songId >= 0) { if (Profile.getGame() != Profile.Game.PST) { scriptActions.add(Pattern.compile("StartMusic\\(" + Long.toString(songId) + ",.+\\)")); IdsMap map = null; if (ResourceFactory.resourceExists("SONGLIST.IDS")) { map = IdsMapCache.get("SONGLIST.IDS"); } else if (Profile.getGame() == Profile.Game.IWD2) { map = IdsMapCache.get("MUSIC.IDS"); } if (map != null && map.getMap().containsKey(Long.valueOf(songId))) { String musicId = map.getMap().get(Long.valueOf(songId)).getString(); scriptActions.add(Pattern.compile("SetMusic\\(.+?," + Long.toString(songId) + "\\)")); if (musicId != null && !musicId.isEmpty()) { scriptActions.add(Pattern.compile("SetMusic\\(.+?," + musicId + "\\)")); } } } } } }