PageRenderTime 29ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/newcode/src/com/prupe/mcpatcher/mal/tile/TileLoader.java

https://bitbucket.org/prupe/mcpatcher
Java | 334 lines | 296 code | 36 blank | 2 comment | 63 complexity | ba78a5fc71f6c79440b54b2eae7999d2 MD5 | raw file
  1. package com.prupe.mcpatcher.mal.tile;
  2. import com.prupe.mcpatcher.Config;
  3. import com.prupe.mcpatcher.MCLogger;
  4. import com.prupe.mcpatcher.MCPatcherUtils;
  5. import com.prupe.mcpatcher.mal.resource.BlendMethod;
  6. import com.prupe.mcpatcher.mal.resource.TexturePackAPI;
  7. import com.prupe.mcpatcher.mal.resource.TexturePackChangeHandler;
  8. import net.minecraft.src.*;
  9. import java.awt.*;
  10. import java.awt.image.BufferedImage;
  11. import java.io.File;
  12. import java.util.*;
  13. import java.util.List;
  14. public class TileLoader {
  15. private static final MCLogger logger = MCLogger.getLogger("Tilesheet");
  16. private static final List<TileLoader> loaders = new ArrayList<TileLoader>();
  17. private static final boolean debugTextures = Config.getBoolean(MCPatcherUtils.CONNECTED_TEXTURES, "debugTextures", false);
  18. private static final Map<String, String> specialTextures = new HashMap<String, String>();
  19. private static final TexturePackChangeHandler changeHandler;
  20. private static boolean changeHandlerCalled;
  21. private static boolean useFullPath;
  22. private static final long MAX_TILESHEET_SIZE;
  23. protected final String mapName;
  24. protected final MCLogger subLogger;
  25. private TextureAtlas baseTextureMap;
  26. private final Map<String, TextureAtlasSprite> baseTexturesByName = new HashMap<String, TextureAtlasSprite>();
  27. private final Set<ResourceLocation> tilesToRegister = new HashSet<ResourceLocation>();
  28. private final Map<ResourceLocation, BufferedImage> tileImages = new HashMap<ResourceLocation, BufferedImage>();
  29. private final Map<String, Icon> iconMap = new HashMap<String, Icon>();
  30. static {
  31. long maxSize = 4096L;
  32. try {
  33. maxSize = Minecraft.getMaxTextureSize();
  34. } catch (NoSuchMethodError e) {
  35. } catch (Throwable e) {
  36. e.printStackTrace();
  37. }
  38. MAX_TILESHEET_SIZE = (maxSize * maxSize * 4) * 7 / 8;
  39. logger.config("max texture size is %dx%d (%.1fMB)", maxSize, maxSize, MAX_TILESHEET_SIZE / 1048576.0f);
  40. changeHandler = new TexturePackChangeHandler("Tilesheet API", 2) {
  41. @Override
  42. public void initialize() {
  43. }
  44. @Override
  45. public void beforeChange() {
  46. changeHandlerCalled = true;
  47. loaders.clear();
  48. specialTextures.clear();
  49. try {
  50. FaceInfo.clear();
  51. } catch (NoClassDefFoundError e) {
  52. // nothing
  53. } catch (Throwable e) {
  54. e.printStackTrace();
  55. }
  56. }
  57. @Override
  58. public void afterChange() {
  59. for (TileLoader loader : loaders) {
  60. if (!loader.tilesToRegister.isEmpty()) {
  61. loader.subLogger.warning("could not load all %s tiles (%d remaining)", loader.mapName, loader.tilesToRegister.size());
  62. loader.tilesToRegister.clear();
  63. }
  64. }
  65. changeHandlerCalled = false;
  66. }
  67. @Override
  68. public void afterChange2() {
  69. for (TileLoader loader : loaders) {
  70. loader.finish();
  71. }
  72. }
  73. };
  74. TexturePackChangeHandler.register(changeHandler);
  75. }
  76. public static void registerIcons(TextureAtlas textureMap, String mapName, Map<String, TextureAtlasSprite> map) {
  77. mapName = mapName.replaceFirst("/$", "");
  78. logger.fine("before registerIcons(%s) %d icons", mapName, map.size());
  79. if (!changeHandlerCalled) {
  80. logger.severe("beforeChange was not called, invoking directly");
  81. changeHandler.beforeChange();
  82. }
  83. for (TileLoader loader : loaders) {
  84. if (loader.isForThisMap(mapName)) {
  85. if (loader.baseTextureMap == null) {
  86. loader.baseTextureMap = textureMap;
  87. loader.baseTexturesByName.putAll(map);
  88. }
  89. if (!loader.tilesToRegister.isEmpty()) {
  90. loader.subLogger.fine("adding icons to %s (%d remaining)", mapName, loader.tilesToRegister.size(), mapName);
  91. while (!loader.tilesToRegister.isEmpty() && loader.registerOneIcon(textureMap, mapName, map)) {
  92. // nothing
  93. }
  94. loader.subLogger.fine("done adding icons to %s (%d remaining)", mapName, loader.tilesToRegister.size(), mapName);
  95. }
  96. }
  97. }
  98. logger.fine("after registerIcons(%s) %d icons", mapName, map.size());
  99. }
  100. public static String getOverridePath(String prefix, String basePath, String name, String ext) {
  101. String path;
  102. if (name.endsWith(".png")) {
  103. path = name.replaceFirst("^/", "").replaceFirst("\\.[^.]+$", "") + ext;
  104. useFullPath = true;
  105. } else {
  106. path = basePath;
  107. if (!basePath.endsWith("/")) {
  108. path += "/";
  109. }
  110. path += name;
  111. path += ext;
  112. useFullPath = false;
  113. }
  114. path = prefix + path;
  115. logger.finer("getOverridePath(%s, %s, %s, %s) -> %s", prefix, basePath, name, ext, path);
  116. return path;
  117. }
  118. public static String getOverrideBasename(Object o, String path) {
  119. if (useFullPath) {
  120. useFullPath = false;
  121. return "/" + path;
  122. } else {
  123. File file = new File(path);
  124. return file.getName().substring(0, file.getName().lastIndexOf('.'));
  125. }
  126. }
  127. public static boolean isSpecialTexture(TextureAtlas map, String texture, String special) {
  128. return special.equals(texture) || special.equals(specialTextures.get(texture));
  129. }
  130. public static BufferedImage generateDebugTexture(String text, int width, int height, boolean alternate) {
  131. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
  132. Graphics graphics = image.getGraphics();
  133. graphics.setColor(alternate ? new Color(0, 255, 255, 128) : Color.WHITE);
  134. graphics.fillRect(0, 0, width, height);
  135. graphics.setColor(alternate ? Color.RED : Color.BLACK);
  136. int ypos = 10;
  137. if (alternate) {
  138. ypos += height / 2;
  139. }
  140. int charsPerRow = width / 8;
  141. if (charsPerRow <= 0) {
  142. return image;
  143. }
  144. while (text.length() % charsPerRow != 0) {
  145. text += " ";
  146. }
  147. while (ypos < height && !text.equals("")) {
  148. graphics.drawString(text.substring(0, charsPerRow), 1, ypos);
  149. ypos += graphics.getFont().getSize();
  150. text = text.substring(charsPerRow);
  151. }
  152. return image;
  153. }
  154. static void init() {
  155. }
  156. public static ResourceLocation getBlocksAtlas() {
  157. return TextureAtlas.blocksAtlas;
  158. }
  159. public static ResourceLocation getItemsAtlas() {
  160. return TextureAtlas.itemsAtlas;
  161. }
  162. public TileLoader(String mapName, MCLogger logger) {
  163. this.mapName = mapName;
  164. subLogger = logger;
  165. loaders.add(this);
  166. }
  167. private static long getTextureSize(TextureAtlasSprite texture) {
  168. return texture == null ? 0 : 4 * IconAPI.getIconWidth(texture) * IconAPI.getIconHeight(texture);
  169. }
  170. private static long getTextureSize(Collection<TextureAtlasSprite> textures) {
  171. long size = 0;
  172. for (TextureAtlasSprite texture : textures) {
  173. size += getTextureSize(texture);
  174. }
  175. return size;
  176. }
  177. public static ResourceLocation getDefaultAddress(ResourceLocation propertiesAddress) {
  178. return TexturePackAPI.transformResourceLocation(propertiesAddress, ".properties", ".png");
  179. }
  180. public static ResourceLocation parseTileAddress(ResourceLocation propertiesAddress, String value) {
  181. return parseTileAddress(propertiesAddress, value, BlendMethod.ALPHA.getBlankResource());
  182. }
  183. public static ResourceLocation parseTileAddress(ResourceLocation propertiesAddress, String value, ResourceLocation blankResource) {
  184. if (value == null) {
  185. return null;
  186. }
  187. if (value.equals("blank")) {
  188. return blankResource;
  189. }
  190. if (value.equals("null") || value.equals("none") || value.equals("default") || value.equals("")) {
  191. return null;
  192. }
  193. if (!value.endsWith(".png")) {
  194. value += ".png";
  195. }
  196. return TexturePackAPI.parseResourceLocation(propertiesAddress, value);
  197. }
  198. public boolean preloadTile(ResourceLocation resource, boolean alternate, String special) {
  199. if (tileImages.containsKey(resource)) {
  200. return true;
  201. }
  202. BufferedImage image = null;
  203. if (!debugTextures) {
  204. image = TexturePackAPI.getImage(resource);
  205. if (image == null) {
  206. subLogger.warning("missing %s", resource);
  207. }
  208. }
  209. if (image == null) {
  210. image = generateDebugTexture(resource.getPath(), 64, 64, alternate);
  211. }
  212. tilesToRegister.add(resource);
  213. tileImages.put(resource, image);
  214. if (special != null) {
  215. specialTextures.put(resource.toString(), special);
  216. }
  217. return true;
  218. }
  219. public boolean preloadTile(ResourceLocation resource, boolean alternate) {
  220. return preloadTile(resource, alternate, null);
  221. }
  222. protected boolean isForThisMap(String mapName) {
  223. return mapName.equals("textures") || mapName.startsWith(this.mapName);
  224. }
  225. private boolean registerDefaultIcon(String name) {
  226. if (name.startsWith(mapName) && name.endsWith(".png") && baseTextureMap != null) {
  227. String defaultName = name.substring(mapName.length()).replaceFirst("\\.png$", "");
  228. TextureAtlasSprite texture = baseTexturesByName.get(defaultName);
  229. if (texture != null) {
  230. subLogger.finer("%s -> existing icon %s", name, defaultName);
  231. iconMap.put(name, texture);
  232. return true;
  233. }
  234. }
  235. return false;
  236. }
  237. private boolean registerOneIcon(TextureAtlas textureMap, String mapName, Map<String, TextureAtlasSprite> map) {
  238. ResourceLocation resource = tilesToRegister.iterator().next();
  239. String name = resource.toString();
  240. if (registerDefaultIcon(name)) {
  241. tilesToRegister.remove(resource);
  242. return true;
  243. }
  244. BufferedImage image = tileImages.get(resource);
  245. if (image == null) {
  246. subLogger.error("tile for %s unexpectedly missing", resource);
  247. tilesToRegister.remove(resource);
  248. return true;
  249. }
  250. int width = image.getWidth();
  251. int height = image.getHeight();
  252. long currentSize = getTextureSize(map.values());
  253. long newSize = 4 * width * width;
  254. if (newSize + currentSize > MAX_TILESHEET_SIZE) {
  255. float sizeMB = (float) currentSize / 1048576.0f;
  256. if (currentSize <= 0) {
  257. subLogger.error("%s too big for any tilesheet (%.1fMB), dropping", name, sizeMB);
  258. tilesToRegister.remove(resource);
  259. return true;
  260. } else {
  261. subLogger.warning("%s nearly full (%.1fMB), will start a new tilesheet", mapName, sizeMB);
  262. return false;
  263. }
  264. }
  265. Icon icon;
  266. if (mapName.equals("textures")) { // 1.8
  267. icon = map.get(name);
  268. if (icon == null) {
  269. icon = TextureAtlasSprite.createSprite(resource);
  270. }
  271. } else {
  272. icon = textureMap.registerIcon(name);
  273. }
  274. map.put(name, (TextureAtlasSprite) icon);
  275. iconMap.put(name, icon);
  276. String extra = (width == height ? "" : ", " + (height / width) + " frames");
  277. subLogger.finer("%s -> %s icon %dx%d%s", name, mapName, width, width, extra);
  278. tilesToRegister.remove(resource);
  279. return true;
  280. }
  281. public void finish() {
  282. tilesToRegister.clear();
  283. tileImages.clear();
  284. }
  285. public Icon getIcon(String name) {
  286. if (MCPatcherUtils.isNullOrEmpty(name)) {
  287. return null;
  288. }
  289. Icon icon = iconMap.get(name);
  290. if (icon == null) {
  291. icon = baseTexturesByName.get(name);
  292. }
  293. return icon;
  294. }
  295. public Icon getIcon(ResourceLocation resource) {
  296. return resource == null ? null : getIcon(resource.toString());
  297. }
  298. }