prevent crash using invalid theme

This commit is contained in:
Anthony Calosa
2024-07-19 10:06:07 +08:00
parent 0efa98ee46
commit 8fe5891c61
3 changed files with 167 additions and 112 deletions

View File

@@ -468,18 +468,25 @@ public class FSkin {
x0 = tempCoords[0];
y0 = tempCoords[1];
color = bimPreferredSprite.getData().getBounds().contains(x0, y0) ? getColorFromPixel(bimPreferredSprite.getRGB(x0, y0)) : new Color(0, 0, 0, 0);
try {
color = bimPreferredSprite.getData().getBounds().contains(x0, y0) ? getColorFromPixel(bimPreferredSprite.getRGB(x0, y0)) : new Color(0, 0, 0, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void drawImage(final Graphics g, final SkinImage skinImage, final int x, final int y) {
skinImage.draw(g, x, y);
if (skinImage != null)
skinImage.draw(g, x, y);
}
public static void drawImage(final Graphics g, final SkinImage skinImage, final int x, final int y, final int w, final int h) {
skinImage.draw(g, x, y, w, h);
if (skinImage != null)
skinImage.draw(g, x, y, w, h);
}
public static void drawImage(final Graphics g, final SkinImage skinImage, final int dx1, final int dy1, final int dx2, final int dy2, final int sx1, final int sy1, final int sx2, final int sy2) {
skinImage.draw(g, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
if (skinImage != null)
skinImage.draw(g, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
}
/**
@@ -558,13 +565,18 @@ public class FSkin {
newW = (tempCoords.length == 6 ? tempCoords[4] : 0);
newH = (tempCoords.length == 6 ? tempCoords[5] : 0);
final BufferedImage img = testPreferredSprite(s0);
final BufferedImage bi0 = img.getSubimage(x0, y0, w0, h0);
if (img == null)
return;
try {
final BufferedImage bi0 = img.getSubimage(x0, y0, w0, h0);
if (scale && newW != 0) {
setImage(s0, bi0.getScaledInstance(newW, newH, Image.SCALE_SMOOTH));
}
else {
setImage(s0, bi0);
if (scale && newW != 0) {
setImage(s0, bi0.getScaledInstance(newW, newH, Image.SCALE_SMOOTH));
} else {
setImage(s0, bi0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@@ -775,8 +787,13 @@ public class FSkin {
h0 = tempCoords[3];
final BufferedImage img = testPreferredSprite(s0);
setIcon(s0, new ImageIcon(img.getSubimage(x0, y0, w0, h0)));
if (img == null)
return;
try {
setIcon(s0, new ImageIcon(img.getSubimage(x0, y0, w0, h0)));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
@@ -1055,7 +1072,11 @@ public class FSkin {
}
private void updateFont() {
this.font = baseFont.deriveFont(this.style, this.size);
try {
this.font = baseFont.deriveFont(this.style, this.size);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1154,7 +1175,7 @@ public class FSkin {
// Non-default (preferred) skin name and dir.
preferredName = skinName.toLowerCase().replace(' ', '_');
preferredDir = preferredName.equals("default") ? ForgeConstants.DEFAULT_SKINS_DIR : ForgeConstants.CACHE_SKINS_DIR + preferredName + "/";
preferredDir = preferredName.equalsIgnoreCase("default") || preferredName.isEmpty() ? ForgeConstants.DEFAULT_SKINS_DIR : ForgeConstants.CACHE_SKINS_DIR + preferredName + "/";
if (onInit) {
final File f = new File(preferredDir + ForgeConstants.SPLASH_BG_FILE);
@@ -1496,8 +1517,12 @@ public class FSkin {
h0 = tempCoords[3];
if (s0.equals(FSkinProp.IMG_QUEST_DRAFT_DECK)) {
final Color c = getColorFromPixel(bimQuestDraftDeck.getRGB((x0 + w0 / 2), (y0 + h0 / 2)));
if (c.getAlpha() != 0) { return bimQuestDraftDeck; }
if (bimQuestDraftDeck != null) {
final Color c = getColorFromPixel(bimQuestDraftDeck.getRGB((x0 + w0 / 2), (y0 + h0 / 2)));
if (c.getAlpha() != 0) { return bimQuestDraftDeck; }
} else {
return null;
}
}
// Test if requested sub-image in inside bounds of preferred sprite.
@@ -1512,28 +1537,30 @@ public class FSkin {
int x, y;
Color c;
// Center
x = (x0 + w0 / 2);
y = (y0 + h0 / 2);
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
if (bimPreferredSprite != null) {
// Center
x = (x0 + w0 / 2);
y = (y0 + h0 / 2);
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x += 2;
y += 2;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x += 2;
y += 2;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x -= 4;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x -= 4;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
y -= 4;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
y -= 4;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x += 4;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
x += 4;
c = getColorFromPixel(bimPreferredSprite.getRGB(x, y));
if (c.getAlpha() != 0) { return bimPreferredSprite; }
}
return bimDefaultSprite;
}
@@ -1569,7 +1596,11 @@ public class FSkin {
if (pxTest.getAlpha() == 0) {
continue;
}
avatars.put(counter++, new SkinImage(bimDefaultAvatars.getSubimage(i, j, 100, 100)));
try {
avatars.put(counter++, new SkinImage(bimDefaultAvatars.getSubimage(i, j, 100, 100)));
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
}
@@ -1580,25 +1611,31 @@ public class FSkin {
int counter = 0;
Color pxTest;
final int pw = bimDefaultSleeve.getWidth();
final int ph = bimDefaultSleeve.getHeight();
if (bimDefaultSleeve != null) {
final int pw = bimDefaultSleeve.getWidth();
final int ph = bimDefaultSleeve.getHeight();
for (int j = 0; j < ph; j += 500) {
for (int i = 0; i < pw; i += 360) {
pxTest = getColorFromPixel(bimDefaultSleeve.getRGB(i + 180, j + 250));
if (pxTest.getAlpha() == 0) { continue; }
sleeves.put(counter++, new SkinImage(bimDefaultSleeve.getSubimage(i, j, 360, 500)));
for (int j = 0; j < ph; j += 500) {
for (int i = 0; i < pw; i += 360) {
pxTest = getColorFromPixel(bimDefaultSleeve.getRGB(i + 180, j + 250));
if (pxTest.getAlpha() == 0) {
continue;
}
sleeves.put(counter++, new SkinImage(bimDefaultSleeve.getSubimage(i, j, 360, 500)));
}
}
}
//2nd set
final int aw = bimDefaultSleeve2.getWidth();
final int ah = bimDefaultSleeve2.getHeight();
if (bimDefaultSleeve2 != null) {
//2nd set
final int aw = bimDefaultSleeve2.getWidth();
final int ah = bimDefaultSleeve2.getHeight();
for (int j = 0; j < ah; j += 500) {
for (int i = 0; i < aw; i += 360) {
pxTest = getColorFromPixel(bimDefaultSleeve2.getRGB(i + 180, j + 250));
if (pxTest.getAlpha() == 0) { continue; }
sleeves.put(counter++, new SkinImage(bimDefaultSleeve2.getSubimage(i, j, 360, 500)));
for (int j = 0; j < ah; j += 500) {
for (int i = 0; i < aw; i += 360) {
pxTest = getColorFromPixel(bimDefaultSleeve2.getRGB(i + 180, j + 250));
if (pxTest.getAlpha() == 0) { continue; }
sleeves.put(counter++, new SkinImage(bimDefaultSleeve2.getSubimage(i, j, 360, 500)));
}
}
}
}

View File

@@ -434,7 +434,7 @@ public class Assets implements Disposable {
}
@SuppressWarnings("unchecked")
private int calculateTextureSize(AssetManager assetManager, String fileName, Class type) {
private int calculateTextureSize(AssetManager assetManager, String fileName, Class<?> type) {
if (!Forge.showFPS)
return 0;
Texture texture = (Texture) assetManager.get(fileName, type);
@@ -442,21 +442,7 @@ public class Assets implements Disposable {
int textureSize = textureData.getWidth() * textureData.getHeight();
if (Forge.isTextureFilteringEnabled())
textureSize = textureSize + (textureSize / 3);
switch (textureData.getFormat()) {
case RGB565:
textureSize *= 2;
break;
case RGB888:
textureSize *= 3;
break;
case RGBA4444:
textureSize *= 2;
break;
case RGBA8888:
textureSize *= 4;
break;
}
memoryPerFile.put(fileName, textureSize);
memoryPerFile.put(fileName, calcTextureDataSize(textureSize, textureData.getFormat()));
return memoryPerFile.values().stream().mapToInt(Integer::intValue).sum() + calcFonts() + calcCounterFonts()
+ calculateObjectMaps(generatedCards()) + calculateObjectMaps(fallback_skins()) + calculateObjectMaps(tmxMap());
@@ -492,21 +478,7 @@ public class Assets implements Disposable {
int textureSize = textureData.getWidth() * textureData.getHeight();
if (Forge.isTextureFilteringEnabled())
textureSize = textureSize + (textureSize / 3);
switch (textureData.getFormat()) {
case RGB565:
textureSize *= 2;
break;
case RGB888:
textureSize *= 3;
break;
case RGBA4444:
textureSize *= 2;
break;
case RGBA8888:
textureSize *= 4;
break;
}
sum += textureSize;
sum += calcTextureDataSize(textureSize, textureData.getFormat());
}
if (objectMap == generatedCards)
cGenVal = sum;
@@ -559,6 +531,20 @@ public class Assets implements Disposable {
return val;
}
private int calcTextureDataSize(int textureSize, Pixmap.Format format) {
switch (format) {
case RGB565:
case RGBA4444:
return textureSize * 2;
case RGB888:
return textureSize * 3;
case RGBA8888:
return textureSize * 4;
default: //assume plain RGB888
return textureSize * 3;
}
}
@SuppressWarnings("unchecked")
@Override
public synchronized <T> void load(String fileName, Class<T> type, AssetLoaderParameters<T> parameter) {
@@ -583,10 +569,8 @@ public class Assets implements Disposable {
public synchronized void unload(String fileName) {
if (isLoaded(fileName))
super.unload(fileName);
if (memoryPerFile.containsKey(fileName)) {
memoryPerFile.remove(fileName);
cardArtCache().clear();
}
memoryPerFile.remove(fileName);
cardArtCache().clear();
}
@Override

View File

@@ -37,13 +37,17 @@ public class FSkin {
return Forge.getAssets().getTexture(getSkinFile("hd_logo.png"), false);
}
public static void saveSkinName(ForgePreferences prefs, String skinName) {
prefs.setPref(FPref.UI_SKIN, skinName);
prefs.save();
}
public static void changeSkin(final String skinName) {
final ForgePreferences prefs = FModel.getPreferences();
if (skinName.equals(prefs.getPref(FPref.UI_SKIN))) { return; }
//save skin preference
prefs.setPref(FPref.UI_SKIN, skinName);
prefs.save();
saveSkinName(prefs, skinName);
Forge.setTransitionScreen(new TransitionScreen(() -> FThreads.invokeInBackgroundThread(() -> FThreads.invokeInEdtLater(() -> {
final LoadingOverlay loader = new LoadingOverlay(Forge.getLocalizer().getMessageorUseDefault("lblRestartInFewSeconds", "Forge will restart after a few seconds..."), true);
@@ -52,24 +56,58 @@ public class FSkin {
FSkinFont.deleteCachedFiles(); //delete cached font files so font can be update for new skin
FThreads.delayInEDT(2000, () -> {
Forge.clearTransitionScreen();
FThreads.invokeInEdtLater(() -> {
Forge.restart(true);
});
FThreads.invokeInEdtLater(() -> Forge.restart(true));
});
});
})), null, false, true));
}
private static boolean isValidDirectory(FileHandle fileHandle) {
if (fileHandle == null)
return false;
if (!fileHandle.exists())
return false;
if (!fileHandle.isDirectory())
return false;
String[] lists = fileHandle.file().list();
if (lists == null)
return false;
return lists.length > 0;
public static boolean isThemeValid(FileHandle themeDir, String themeName, boolean silent) {
int missing = 0;
if (!themeDir.child("bg_splash.png").exists()) {
if (!silent)
System.err.println(themeDir + themeName + "/bg_splash.png not found.");
missing++;
}
if (!themeDir.child("bg_match.jpg").exists()) {
if (!silent)
System.err.println(themeDir + themeName + "/bg_match.jpg not found.");
missing++;
}
if (!themeDir.child("bg_texture.jpg").exists()) {
if (!silent)
System.err.println(themeDir + themeName + "/bg_texture.jpg not found.");
missing++;
}
if (!themeDir.child("sprite_icons.png").exists()) {
if (!silent)
System.err.println(themeDir + themeName + "/sprite_icons.png not found.");
missing++;
}
if (!themeDir.child("font1.ttf").exists()) {
if (!silent)
System.err.println(themeDir + themeName + "/font1.ttf not found.");
missing++;
}
return missing == 0;
}
private static void checkThemeDir(FileHandle themeDir, String themeName) {
if (themeDir == null || !themeDir.exists() || !themeDir.isDirectory()) {
System.err.println("Skin not found. Defaulting to fallback_skin.");
useFallbackDir();
} else {
if (!isThemeValid(themeDir, themeName, false)) {
System.err.println(themeName + " theme is missing some files to work properly.");
final FileHandle def = Gdx.files.absolute(ForgeConstants.DEFAULT_SKINS_DIR);
if (def.exists() && def.isDirectory() && isThemeValid(def, "", true)) {
FSkinFont.deleteCachedFiles();
//use default skin if valid
preferredDir = def;
saveSkinName(GuiBase.getForgePrefs(), "Default");
} else {
useFallbackDir();
}
}
}
}
private static void useFallbackDir() {
preferredDir = GuiBase.isAndroid() ? Gdx.files.internal("fallback_skin") : Gdx.files.classpath("fallback_skin");
@@ -97,12 +135,9 @@ public class FSkin {
final FileHandle dir = Gdx.files.absolute(ForgeConstants.CACHE_SKINS_DIR);
if(preferredDir == null)
{
if (!isValidDirectory(dir)) {
final FileHandle def = Gdx.files.absolute(ForgeConstants.DEFAULT_SKINS_DIR);
if (def.exists() && def.isDirectory()) //if default skin exists
preferredDir = def;
else //if skins directory doesn't exist, point to internal assets/skin directory instead for the sake of the splash screen
useFallbackDir();
if (!dir.exists() || !dir.isDirectory()) {
//if skins directory doesn't exist, point to internal assets/skin directory instead for the sake of the splash screen
useFallbackDir();
} else {
if (splashScreen != null) {
if (allSkins == null) { //initialize
@@ -123,11 +158,8 @@ public class FSkin {
}
}
}
//check preferredDir
if (!isValidDirectory(preferredDir)) {
useFallbackDir();
}
//check theme
checkThemeDir(preferredDir, preferredName);
FSkinTexture.BG_TEXTURE.load(); //load background texture early for splash screen
@@ -543,6 +575,8 @@ public class FSkin {
String skinName = skinFile.name();
if (skinName.equalsIgnoreCase(".svn")) { continue; }
if (skinName.equalsIgnoreCase(".DS_Store")) { continue; }
if (!skinFile.isDirectory()) { continue; }
if (!isThemeValid(skinFile, skinName, true)) { continue; }
mySkins.add(skinName);
}