mirror of https://github.com/FreeCol/freecol.git
Resource loading with mods has now been fixed. Resources are reloaded when changing the active mods. Added a debug option for reloading resources from disk (great for testing new ingame graphics).
This commit is contained in:
parent
368d8518d7
commit
752845c44f
|
@ -270,6 +270,7 @@ menuBar.view=View
|
|||
menuBar.statusLine=Score: %score% | Gold: %gold% | Tax: %tax%% | Year: %year%
|
||||
|
||||
menuBar.debug=Debug
|
||||
menuBar.debug.reloadResources=Reload resources
|
||||
menuBar.debug.addBuilding=Add building to each colony
|
||||
menuBar.debug.addFoundingFather=Add Founding Father
|
||||
menuBar.debug.addGold=Add Gold
|
||||
|
|
|
@ -210,10 +210,10 @@ public final class FreeColClient {
|
|||
// Not so easy, since the ActionManager also creates tile
|
||||
// improvement actions, which depend on the specification.
|
||||
// However, this step could probably be delayed.
|
||||
ResourceManager.addMapping("base", baseData.getResourceMapping());
|
||||
ResourceManager.setBaseData(baseData);
|
||||
|
||||
FreeColTcFile tcData = FreeColTcFile.getFreeColTcFile("classic");
|
||||
ResourceManager.addMapping("tc", tcData.getResourceMapping());
|
||||
ResourceManager.setTcData(tcData);
|
||||
|
||||
actionManager = new ActionManager(this);
|
||||
actionManager.initializeActions(inGameController, connectController);
|
||||
|
@ -224,10 +224,7 @@ public final class FreeColClient {
|
|||
this.clientOptions.fixClientOptions();
|
||||
|
||||
// Reset the mod resources as a result of the client option update.
|
||||
for (FreeColModFile f : this.clientOptions.getActiveMods()) {
|
||||
ResourceManager.addMapping("mod " + f.getId(),
|
||||
f.getResourceMapping());
|
||||
}
|
||||
ResourceManager.setMods(this.clientOptions.getActiveMods());
|
||||
|
||||
/*
|
||||
* All mods are loaded, so the GUI can safely be created.
|
||||
|
@ -884,7 +881,7 @@ public final class FreeColClient {
|
|||
setFreeColServer(fcs);
|
||||
setSinglePlayer(singlePlayer);
|
||||
this.inGameController.setGameConnected();
|
||||
ResourceManager.addMapping("game", fsg.getResourceMapping());
|
||||
ResourceManager.setSavegameFile(fsg);
|
||||
return fcs;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ import net.sf.freecol.common.model.Player;
|
|||
import net.sf.freecol.common.model.Specification;
|
||||
import net.sf.freecol.common.model.StringTemplate;
|
||||
import net.sf.freecol.common.model.Unit;
|
||||
import net.sf.freecol.common.resources.ResourceManager;
|
||||
import net.sf.freecol.common.util.Utils;
|
||||
import net.sf.freecol.server.FreeColServer;
|
||||
import net.sf.freecol.server.FreeColServer.ServerState;
|
||||
|
@ -442,6 +443,11 @@ public final class ConnectController extends FreeColClientHolder {
|
|||
port, serverName);
|
||||
if (fcs == null) return false;
|
||||
|
||||
/*
|
||||
* TODO: The choice of active mods with a specification should be stored in the savegame.
|
||||
* These mods should also be loaded in the ResourceManager (after global mods without
|
||||
* a specification).
|
||||
*/
|
||||
fcs.getGame().getSpecification().loadMods(options.getActiveMods());
|
||||
|
||||
fcc.setFreeColServer(fcs);
|
||||
|
|
|
@ -2483,4 +2483,11 @@ public class GUI extends FreeColClientHolder {
|
|||
* @return The panel shown.
|
||||
*/
|
||||
public FreeColPanel showWorkProductionPanel(Unit unit) { return null; }
|
||||
|
||||
/**
|
||||
* Reloads all images managed by {@code ResourceManager}.
|
||||
*/
|
||||
public void reloadResources() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import javax.swing.ImageIcon;
|
|||
import javax.swing.JLabel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
import net.sf.freecol.FreeCol;
|
||||
|
@ -115,6 +116,7 @@ import net.sf.freecol.common.option.LanguageOption.Language;
|
|||
import net.sf.freecol.common.option.Option;
|
||||
import net.sf.freecol.common.option.OptionGroup;
|
||||
import net.sf.freecol.common.resources.ImageCache;
|
||||
import net.sf.freecol.common.resources.ResourceManager;
|
||||
import net.sf.freecol.common.util.Introspector;
|
||||
import net.sf.freecol.common.util.Utils;
|
||||
|
||||
|
@ -1357,6 +1359,22 @@ public class SwingGUI extends GUI {
|
|||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void reloadResources() {
|
||||
ResourceManager.reload();
|
||||
imageCache.clear();
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void prepareResources() {
|
||||
ResourceManager.prepare();
|
||||
imageCache.clear();
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
||||
// Highest level panel and dialog handling
|
||||
|
@ -1707,6 +1725,9 @@ public class SwingGUI extends GUI {
|
|||
|
||||
FreeColImageBorder.setScaleFactor(scaleFactor);
|
||||
|
||||
ResourceManager.setMods(getClientOptions().getActiveMods());
|
||||
prepareResources();
|
||||
|
||||
final int fontSize = determineMainFontSizeUsingClientOptions(dpi);
|
||||
FontLibrary.setMainFontSize(fontSize);
|
||||
|
||||
|
|
|
@ -87,6 +87,15 @@ public class DebugMenu extends JMenu {
|
|||
this.setOpaque(false);
|
||||
this.setMnemonic(KeyEvent.VK_D);
|
||||
add(this);
|
||||
|
||||
final JMenuItem reload = Utility.localizedMenuItem("menuBar.debug.reloadResources");
|
||||
reload.setOpaque(false);
|
||||
reload.addActionListener((event) -> {
|
||||
freeColClient.getGUI().reloadResources();
|
||||
});
|
||||
this.add(reload);
|
||||
|
||||
addSeparator();
|
||||
|
||||
final JCheckBoxMenuItem sc
|
||||
= Utility.localizedCheckBoxMenuItem("menuBar.debug.showCoordinates",
|
||||
|
|
|
@ -203,8 +203,9 @@ public class FreeColDataFile {
|
|||
* data files.
|
||||
*/
|
||||
private List<String> handleResources(final Properties properties, ResourceMapping rc) {
|
||||
List<String> virtualResources = new ArrayList<>();
|
||||
Enumeration<?> pn = properties.propertyNames();
|
||||
final ResourceFactory resourceFactory = new ResourceFactory();
|
||||
final List<String> virtualResources = new ArrayList<>();
|
||||
final Enumeration<?> pn = properties.propertyNames();
|
||||
while (pn.hasMoreElements()) {
|
||||
final String key = (String) pn.nextElement();
|
||||
|
||||
|
@ -219,18 +220,18 @@ public class FreeColDataFile {
|
|||
if (value.startsWith(resourceScheme)) {
|
||||
virtualResources.add(updatedKey);
|
||||
} else {
|
||||
handleNormalResource(rc, key, value);
|
||||
handleNormalResource(resourceFactory, rc, key, value);
|
||||
}
|
||||
}
|
||||
return virtualResources;
|
||||
}
|
||||
|
||||
private void handleNormalResource(ResourceMapping rc, final String key, final String value) {
|
||||
private void handleNormalResource(ResourceFactory resourceFactory, ResourceMapping rc, final String key, final String value) {
|
||||
final URI uri = getURI(value);
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
final Resource resource = ResourceFactory.createResource(key, uri);
|
||||
final Resource resource = resourceFactory.createResource(key, uri);
|
||||
|
||||
/*
|
||||
* Rivers need new keys in order to support variations.
|
||||
|
@ -239,7 +240,7 @@ public class FreeColDataFile {
|
|||
|
||||
if (resource instanceof ImageResource && supportsVariations) {
|
||||
final ImageResource imageResource = (ImageResource) resource;
|
||||
extendWithAdditionalSizesAndVariations(imageResource, value);
|
||||
extendWithAdditionalSizesAndVariations(resourceFactory, imageResource, value);
|
||||
}
|
||||
|
||||
if (resource != null) {
|
||||
|
@ -309,7 +310,7 @@ public class FreeColDataFile {
|
|||
return (key.endsWith(ending)) ? key.substring(0, key.length() - 3) : key;
|
||||
}
|
||||
|
||||
private void extendWithAdditionalSizesAndVariations(ImageResource imageResource, String value) {
|
||||
private void extendWithAdditionalSizesAndVariations(ResourceFactory resourceFactory, ImageResource imageResource, String value) {
|
||||
Map<URI, List<URI>> variationsWithAlternateSizes = findVariationsWithAlternateSizes(value);
|
||||
imageResource.addAlternativeResourceLocators(variationsWithAlternateSizes.get(null));
|
||||
|
||||
|
@ -317,7 +318,7 @@ public class FreeColDataFile {
|
|||
.stream()
|
||||
.filter(entry -> entry.getKey() != null)
|
||||
.forEach(entry -> {
|
||||
final ImageResource variationResource = (ImageResource) ResourceFactory.createResource(imageResource.getPrimaryKey(), entry.getKey());
|
||||
final ImageResource variationResource = (ImageResource) resourceFactory.createResource(imageResource.getPrimaryKey(), entry.getKey());
|
||||
if (variationResource != null) {
|
||||
variationResource.addAlternativeResourceLocators(entry.getValue());
|
||||
imageResource.addVariation(variationResource);
|
||||
|
|
|
@ -43,12 +43,14 @@ import java.util.logging.Logger;
|
|||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import net.sf.freecol.common.resources.Resource.Cleanable;
|
||||
|
||||
|
||||
/**
|
||||
* A {@code Resource} wrapping an {@code Image}.
|
||||
* @see Resource
|
||||
*/
|
||||
public class ImageResource extends Resource {
|
||||
public class ImageResource extends Resource implements Cleanable {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ImageResource.class.getName());
|
||||
|
||||
|
@ -295,6 +297,16 @@ public class ImageResource extends Resource {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clean() {
|
||||
image = null;
|
||||
if (loadedImages != null) {
|
||||
loadedImages.clear();
|
||||
}
|
||||
if (variations != null) {
|
||||
variations.stream().forEach(v -> v.clean());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean canUseBitmask(URI uri) {
|
||||
/* TODO: Better method for determining images that can use a bitmask. */
|
||||
|
|
|
@ -35,19 +35,11 @@ public class ResourceFactory {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(ResourceFactory.class.getName());
|
||||
|
||||
/**
|
||||
* Takes a newly produced Resource.
|
||||
*/
|
||||
public interface ResourceSink {
|
||||
|
||||
void add(Resource r);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that only one {@code Resource} is created given the same {@code URI}.
|
||||
*/
|
||||
private static final Map<URI, Resource> resources = new HashMap<>();
|
||||
private final Map<URI, Resource> resources = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
|
@ -58,7 +50,7 @@ public class ResourceFactory {
|
|||
* instance.
|
||||
* @return The <code>Resource</code> if created.
|
||||
*/
|
||||
public static Resource createResource(String primaryKey, URI uri) {
|
||||
public Resource createResource(String primaryKey, URI uri) {
|
||||
final Resource r = resources.get(uri);
|
||||
if (r != null) {
|
||||
return r;
|
||||
|
|
|
@ -27,13 +27,17 @@ import java.awt.Dimension;
|
|||
import java.awt.Font;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.sf.freecol.FreeCol;
|
||||
import net.sf.freecol.common.io.FreeColDataFile;
|
||||
import net.sf.freecol.common.io.FreeColSavegameFile;
|
||||
import net.sf.freecol.common.io.sza.SimpleZippedAnimation;
|
||||
|
||||
|
||||
|
@ -53,23 +57,76 @@ public class ResourceManager {
|
|||
/**
|
||||
* All the mappings are merged in order into this single ResourceMapping.
|
||||
*/
|
||||
private static final ResourceMapping mergedContainer
|
||||
= new ResourceMapping();
|
||||
private static ResourceMapping mergedContainer = new ResourceMapping();
|
||||
|
||||
private static FreeColDataFile baseDataFile = null;
|
||||
private static ResourceMapping baseResourceMapping = new ResourceMapping();
|
||||
private static FreeColDataFile tcDataFile = null;
|
||||
private static ResourceMapping tcResourceMapping = new ResourceMapping();
|
||||
private static List<? extends FreeColDataFile> mods = new ArrayList<>();
|
||||
private static List<ResourceMapping> modResourceMappings = new ArrayList<>();
|
||||
private static FreeColSavegameFile savegameFile = null;
|
||||
private static ResourceMapping savegameResourceMapping = new ResourceMapping();
|
||||
|
||||
|
||||
public static void setBaseData(FreeColDataFile baseDataFile) {
|
||||
ResourceManager.baseDataFile = baseDataFile;
|
||||
baseResourceMapping = baseDataFile.getResourceMapping();
|
||||
}
|
||||
|
||||
public static void setTcData(FreeColDataFile tcDataFile) {
|
||||
ResourceManager.tcDataFile = tcDataFile;
|
||||
tcResourceMapping = (tcDataFile != null) ? tcDataFile.getResourceMapping() : new ResourceMapping();
|
||||
prepare();
|
||||
}
|
||||
|
||||
public static <T extends FreeColDataFile> void setMods(List<T> mods) {
|
||||
ResourceManager.mods = mods;
|
||||
modResourceMappings = mods.stream().map(FreeColDataFile::getResourceMapping).collect(Collectors.toList());
|
||||
prepare();
|
||||
}
|
||||
|
||||
public static void setSavegameFile(FreeColSavegameFile savegameFile) {
|
||||
ResourceManager.savegameFile = savegameFile;
|
||||
savegameResourceMapping = (savegameFile != null) ? savegameFile.getResourceMapping() : new ResourceMapping();
|
||||
prepare();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mappings specified in the date/base-directory.
|
||||
* Do not access the mapping after the call.
|
||||
*
|
||||
* @param name The name of the mapping, for logging purposes.
|
||||
* @param mapping The mapping between IDs and files.
|
||||
*/
|
||||
public static void addMapping(String name, ResourceMapping mapping) {
|
||||
if (preloadThread != null) {
|
||||
throw new IllegalStateException("New mappings should not be added while preloading is running.");
|
||||
public static void prepare() {
|
||||
finishPreloading();
|
||||
|
||||
final ResourceMapping newMergedContainer = new ResourceMapping();
|
||||
newMergedContainer.addAll(baseResourceMapping);
|
||||
newMergedContainer.addAll(tcResourceMapping);
|
||||
for (ResourceMapping modResourceMapping : modResourceMappings) {
|
||||
newMergedContainer.addAll(modResourceMapping);
|
||||
}
|
||||
newMergedContainer.addAll(savegameResourceMapping);
|
||||
|
||||
waitForPreloadingToStop();
|
||||
mergedContainer = newMergedContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all caches and
|
||||
*/
|
||||
public static void reload() {
|
||||
baseResourceMapping = baseDataFile.getResourceMapping();
|
||||
tcResourceMapping = (tcDataFile != null) ? tcDataFile.getResourceMapping() : new ResourceMapping();
|
||||
modResourceMappings = mods.stream().map(FreeColDataFile::getResourceMapping).collect(Collectors.toList());
|
||||
savegameResourceMapping = (savegameFile != null) ? savegameFile.getResourceMapping() : new ResourceMapping();
|
||||
|
||||
prepare();
|
||||
}
|
||||
|
||||
private static void waitForPreloadingToStop() {
|
||||
try {
|
||||
while (preloadThread != null) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
logger.warning(e.getMessage());
|
||||
}
|
||||
logger.info("Resource manager adding mapping " + name);
|
||||
mergedContainer.addAll(mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -292,6 +292,10 @@ public final class ResourceMapping {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public void clearCaches() {
|
||||
imageResources.values().stream().forEach(r -> r.clean());
|
||||
}
|
||||
|
||||
public interface PreloadController {
|
||||
boolean shouldContinue();
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@ public class SoundTest extends FreeColTestCase {
|
|||
} catch (Exception e) {
|
||||
fail("Could not load base data: " + e.getMessage());
|
||||
}
|
||||
ResourceManager.addMapping("testbase", baseData.getResourceMapping());
|
||||
ResourceManager.setBaseData(baseData);
|
||||
ResourceManager.prepare();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,7 +87,8 @@ public class SoundTest extends FreeColTestCase {
|
|||
|
||||
public void testClassic() {
|
||||
FreeColTcFile tcData = FreeColTcFile.getFreeColTcFile("classic");
|
||||
ResourceManager.addMapping("testtc", tcData.getResourceMapping());
|
||||
ResourceManager.setTcData(tcData);
|
||||
ResourceManager.prepare();
|
||||
|
||||
playSound("sound.intro.model.nation.english");
|
||||
playSound("sound.intro.model.nation.dutch");
|
||||
|
|
Loading…
Reference in New Issue