PageRenderTime 67ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/newcode/src/com/prupe/mcpatcher/mal/resource/TexturePackAPI.java

https://bitbucket.org/prupe/mcpatcher
Java | 556 lines | 464 code | 77 blank | 15 comment | 103 complexity | 91ee9fbce7a7e8bb0dd271dee47c3e49 MD5 | raw file
  1. package com.prupe.mcpatcher.mal.resource;
  2. import com.prupe.mcpatcher.MAL;
  3. import com.prupe.mcpatcher.MCLogger;
  4. import com.prupe.mcpatcher.MCPatcherUtils;
  5. import net.minecraft.src.*;
  6. import javax.imageio.ImageIO;
  7. import java.awt.image.BufferedImage;
  8. import java.io.File;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.lang.reflect.Field;
  12. import java.util.*;
  13. import java.util.regex.Pattern;
  14. abstract public class TexturePackAPI {
  15. private static final MCLogger logger = MCLogger.getLogger("Texture Pack");
  16. public static final String DEFAULT_NAMESPACE = "minecraft";
  17. private static final TexturePackAPI instance = MAL.newInstance(TexturePackAPI.class, "texturepack");
  18. public static final String MCPATCHER_SUBDIR = TexturePackAPI.select("/", "mcpatcher/");
  19. public static final ResourceLocation ITEMS_PNG = new ResourceLocation(TexturePackAPI.select("/gui/items.png", GLAPI.select("textures/atlas/items.png", "textures/atlas/blocks.png")));
  20. public static final ResourceLocation BLOCKS_PNG = new ResourceLocation(TexturePackAPI.select("terrain.png", "textures/atlas/blocks.png"));
  21. public static boolean isInitialized() {
  22. return instance != null && instance.isInitialized_Impl();
  23. }
  24. public static void scheduleTexturePackRefresh() {
  25. Minecraft.getInstance().scheduleTexturePackRefresh();
  26. }
  27. public static List<ResourcePack> getResourcePacks(String namespace) {
  28. List<ResourcePack> list = new ArrayList<ResourcePack>();
  29. instance.getResourcePacks_Impl(namespace, list);
  30. return list;
  31. }
  32. public static Set<String> getNamespaces() {
  33. Set<String> set = new HashSet<String>();
  34. set.add(DEFAULT_NAMESPACE);
  35. instance.getNamespaces_Impl(set);
  36. return set;
  37. }
  38. public static boolean isDefaultTexturePack() {
  39. return instance.isDefaultResourcePack_Impl();
  40. }
  41. public static InputStream getInputStream(ResourceLocation resource) {
  42. try {
  43. if (resource instanceof ResourceLocationWithSource) {
  44. try {
  45. return instance.getInputStream_Impl(((ResourceLocationWithSource) resource).getSource(), resource);
  46. } catch (IOException e) {
  47. }
  48. }
  49. return resource == null ? null : instance.getInputStream_Impl(resource);
  50. } catch (IOException e) {
  51. return null;
  52. }
  53. }
  54. public static boolean hasResource(ResourceLocation resource) {
  55. if (resource == null) {
  56. return false;
  57. } else if (resource.getPath().endsWith(".png")) {
  58. return getImage(resource) != null;
  59. } else if (resource.getPath().endsWith(".properties")) {
  60. return getProperties(resource) != null;
  61. } else {
  62. InputStream is = getInputStream(resource);
  63. MCPatcherUtils.close(is);
  64. return is != null;
  65. }
  66. }
  67. public static boolean hasCustomResource(ResourceLocation resource) {
  68. InputStream jar = null;
  69. InputStream pack = null;
  70. try {
  71. String path = instance.getFullPath_Impl(resource);
  72. pack = getInputStream(resource);
  73. if (pack == null) {
  74. return false;
  75. }
  76. jar = Minecraft.class.getResourceAsStream(path);
  77. if (jar == null) {
  78. return true;
  79. }
  80. byte[] buffer1 = new byte[4096];
  81. byte[] buffer2 = new byte[4096];
  82. int read1;
  83. int read2;
  84. while ((read1 = pack.read(buffer1)) > 0) {
  85. read2 = jar.read(buffer2);
  86. if (read1 != read2) {
  87. return true;
  88. }
  89. for (int i = 0; i < read1; i++) {
  90. if (buffer1[i] != buffer2[i]) {
  91. return true;
  92. }
  93. }
  94. }
  95. } catch (IOException e) {
  96. e.printStackTrace();
  97. } finally {
  98. MCPatcherUtils.close(jar);
  99. MCPatcherUtils.close(pack);
  100. }
  101. return false;
  102. }
  103. public static BufferedImage getImage(ResourceLocation resource) {
  104. if (resource == null) {
  105. return null;
  106. }
  107. InputStream input = getInputStream(resource);
  108. BufferedImage image = null;
  109. if (input != null) {
  110. try {
  111. image = ImageIO.read(input);
  112. } catch (IOException e) {
  113. logger.error("could not read %s", resource);
  114. e.printStackTrace();
  115. } finally {
  116. MCPatcherUtils.close(input);
  117. }
  118. }
  119. return image;
  120. }
  121. public static Properties getProperties(ResourceLocation resource) {
  122. Properties properties = new Properties();
  123. if (getProperties(resource, properties)) {
  124. return properties;
  125. } else {
  126. return null;
  127. }
  128. }
  129. public static boolean getProperties(ResourceLocation resource, Properties properties) {
  130. if (properties != null) {
  131. InputStream input = getInputStream(resource);
  132. try {
  133. if (input != null) {
  134. properties.load(input);
  135. return true;
  136. }
  137. } catch (IOException e) {
  138. logger.error("could not read %s", resource);
  139. e.printStackTrace();
  140. } finally {
  141. MCPatcherUtils.close(input);
  142. }
  143. }
  144. return false;
  145. }
  146. public static ResourceLocation transformResourceLocation(ResourceLocation resource, String oldExt, String newExt) {
  147. return new ResourceLocation(resource.getNamespace(), resource.getPath().replaceFirst(Pattern.quote(oldExt) + "$", newExt));
  148. }
  149. public static ResourceLocation parsePath(String path) {
  150. return MCPatcherUtils.isNullOrEmpty(path) ? null : instance.parsePath_Impl(path.replace(File.separatorChar, '/'));
  151. }
  152. public static ResourceLocation parseResourceLocation(String path) {
  153. return parseResourceLocation(new ResourceLocation(DEFAULT_NAMESPACE, "a"), path);
  154. }
  155. public static ResourceLocation parseResourceLocation(ResourceLocation baseResource, String path) {
  156. return MCPatcherUtils.isNullOrEmpty(path) ? null : instance.parseResourceLocation_Impl(baseResource, path);
  157. }
  158. public static <T> T select(T v1, T v2) {
  159. return instance.select_Impl(v1, v2);
  160. }
  161. public static ResourceLocation newMCPatcherResourceLocation(String v1Path, String v2Path) {
  162. return new ResourceLocation(MCPATCHER_SUBDIR + select(v1Path, v2Path).replaceFirst("^/+", ""));
  163. }
  164. public static ResourceLocation newMCPatcherResourceLocation(String path) {
  165. return newMCPatcherResourceLocation(path, path);
  166. }
  167. public static int getTextureIfLoaded(ResourceLocation resource) {
  168. return resource == null ? -1 : instance.getTextureIfLoaded_Impl(resource);
  169. }
  170. public static boolean isTextureLoaded(ResourceLocation resource) {
  171. return getTextureIfLoaded(resource) >= 0;
  172. }
  173. public static TextureObject getTextureObject(ResourceLocation resource) {
  174. return Minecraft.getInstance().getTextureManager().getTexture(resource);
  175. }
  176. public static void bindTexture(ResourceLocation resource) {
  177. if (resource != null) {
  178. instance.bindTexture_Impl(resource);
  179. }
  180. }
  181. public static void unloadTexture(ResourceLocation resource) {
  182. if (resource != null) {
  183. instance.unloadTexture_Impl(resource);
  184. }
  185. }
  186. public static void flushUnusedTextures() {
  187. instance.flushUnusedTextures_Impl();
  188. }
  189. abstract protected boolean isInitialized_Impl();
  190. abstract protected void getResourcePacks_Impl(String namespace, List<ResourcePack> resourcePacks);
  191. abstract protected void getNamespaces_Impl(Set<String> namespaces);
  192. abstract protected InputStream getInputStream_Impl(ResourceLocation resource) throws IOException;
  193. abstract protected InputStream getInputStream_Impl(ResourcePack resourcePack, ResourceLocation resource) throws IOException;
  194. abstract protected String getFullPath_Impl(ResourceLocation resource);
  195. abstract protected ResourceLocation parsePath_Impl(String path);
  196. abstract protected ResourceLocation parseResourceLocation_Impl(ResourceLocation baseResource, String path);
  197. abstract protected <T> T select_Impl(T v1, T v2);
  198. abstract protected boolean isDefaultResourcePack_Impl();
  199. abstract protected int getTextureIfLoaded_Impl(ResourceLocation resource);
  200. abstract protected void bindTexture_Impl(ResourceLocation resource);
  201. abstract protected void unloadTexture_Impl(ResourceLocation resource);
  202. abstract protected void flushUnusedTextures_Impl();
  203. final private static class V1 extends TexturePackAPI {
  204. private final List<Field> textureMapFields = new ArrayList<Field>();
  205. V1() {
  206. try {
  207. for (Field field : RenderEngine.class.getDeclaredFields()) {
  208. if (HashMap.class.isAssignableFrom(field.getType())) {
  209. field.setAccessible(true);
  210. textureMapFields.add(field);
  211. }
  212. }
  213. } catch (Throwable e) {
  214. e.printStackTrace();
  215. }
  216. }
  217. private ResourcePack getTexturePack() {
  218. Minecraft minecraft = Minecraft.getInstance();
  219. if (minecraft == null) {
  220. return null;
  221. }
  222. ResourcePackRepository texturePackList = minecraft.texturePackList;
  223. if (texturePackList == null) {
  224. return null;
  225. }
  226. return texturePackList.getSelectedTexturePack();
  227. }
  228. @Override
  229. protected boolean isInitialized_Impl() {
  230. return Minecraft.getInstance().texturePackList != null;
  231. }
  232. @Override
  233. protected void getResourcePacks_Impl(String namespace, List<ResourcePack> resourcePacks) {
  234. ResourcePack resourcePack = getTexturePack();
  235. if (resourcePack != null) {
  236. resourcePacks.add(resourcePack);
  237. }
  238. }
  239. @Override
  240. protected void getNamespaces_Impl(Set<String> namespaces) {
  241. }
  242. @Override
  243. protected InputStream getInputStream_Impl(ResourceLocation resource) throws IOException {
  244. return getInputStream_Impl(getTexturePack(), resource);
  245. }
  246. @Override
  247. protected InputStream getInputStream_Impl(ResourcePack resourcePack, ResourceLocation resource) throws IOException {
  248. return resourcePack == null ? null : resourcePack.getInputStream(resource.getPath());
  249. }
  250. @Override
  251. protected String getFullPath_Impl(ResourceLocation resource) {
  252. return resource.getPath();
  253. }
  254. @Override
  255. protected ResourceLocation parsePath_Impl(String path) {
  256. return new ResourceLocation(path);
  257. }
  258. @Override
  259. protected ResourceLocation parseResourceLocation_Impl(ResourceLocation baseResource, String path) {
  260. if (path.startsWith("~/")) {
  261. // Relative to namespace mcpatcher dir:
  262. // ~/path -> /path
  263. path = path.substring(1);
  264. }
  265. if (path.startsWith("./")) {
  266. // Relative to properties file:
  267. // ./path -> (dir of base file)/path
  268. return new ResourceLocation(baseResource.getNamespace(), baseResource.getPath().replaceFirst("[^/]+$", "") + path.substring(2));
  269. } else if (path.startsWith("/")) {
  270. return new ResourceLocation(path);
  271. } else {
  272. return new ResourceLocation(baseResource.getNamespace(), baseResource.getPath().replaceFirst("[^/]+$", "") + path);
  273. }
  274. }
  275. @Override
  276. protected <T> T select_Impl(T v1, T v2) {
  277. return v1;
  278. }
  279. @Override
  280. protected boolean isDefaultResourcePack_Impl() {
  281. ResourcePack texturePack = getTexturePack();
  282. return texturePack == null || texturePack instanceof DefaultResourcePack;
  283. }
  284. @Override
  285. protected int getTextureIfLoaded_Impl(ResourceLocation resource) {
  286. RenderEngine renderEngine = Minecraft.getInstance().renderEngine;
  287. String path = resource.getPath();
  288. if (path.equals("/terrain.png") || path.equals("/gui/items.png")) {
  289. return renderEngine.getTexture(path);
  290. }
  291. for (Field field : textureMapFields) {
  292. try {
  293. HashMap map = (HashMap) field.get(renderEngine);
  294. if (map != null) {
  295. Object value = map.get(resource.toString());
  296. if (value instanceof Integer) {
  297. return (Integer) value;
  298. }
  299. }
  300. } catch (IllegalAccessException e) {
  301. }
  302. }
  303. return -1;
  304. }
  305. @Override
  306. protected void bindTexture_Impl(ResourceLocation resource) {
  307. Minecraft.getInstance().renderEngine.bindTextureByName(resource.toString());
  308. }
  309. @Override
  310. protected void unloadTexture_Impl(ResourceLocation resource) {
  311. int texture = getTextureIfLoaded(resource);
  312. if (texture >= 0) {
  313. logger.finest("unloading texture %s", resource);
  314. RenderEngine renderEngine = Minecraft.getInstance().renderEngine;
  315. renderEngine.deleteTexture(texture);
  316. for (Field field : textureMapFields) {
  317. try {
  318. HashMap map = (HashMap) field.get(renderEngine);
  319. if (map != null) {
  320. map.remove(resource.toString());
  321. }
  322. } catch (IllegalAccessException e) {
  323. }
  324. }
  325. }
  326. }
  327. @Override
  328. protected void flushUnusedTextures_Impl() {
  329. // switching packs is so hopelessly broken in 1.5 that there's no point
  330. }
  331. }
  332. final private static class V2 extends TexturePackAPI {
  333. private static final String ASSETS = "assets/";
  334. private ResourceManager getResourceManager() {
  335. return Minecraft.getInstance().getResourceManager();
  336. }
  337. @Override
  338. protected boolean isInitialized_Impl() {
  339. return getResourceManager() != null;
  340. }
  341. @Override
  342. protected void getResourcePacks_Impl(String namespace, List<ResourcePack> resourcePacks) {
  343. ResourceManager resourceManager = getResourceManager();
  344. if (resourceManager instanceof SimpleReloadableResourceManager) {
  345. for (Map.Entry<String, FallbackResourceManager> entry : ((SimpleReloadableResourceManager) resourceManager).namespaceMap.entrySet()) {
  346. if (namespace == null || namespace.equals(entry.getKey())) {
  347. List<ResourcePack> packs = entry.getValue().resourcePacks;
  348. if (packs != null) {
  349. resourcePacks.removeAll(packs);
  350. resourcePacks.addAll(packs);
  351. }
  352. }
  353. }
  354. }
  355. }
  356. @Override
  357. protected void getNamespaces_Impl(Set<String> namespaces) {
  358. ResourceManager resourceManager = getResourceManager();
  359. if (resourceManager instanceof SimpleReloadableResourceManager) {
  360. namespaces.addAll(((SimpleReloadableResourceManager) resourceManager).namespaceMap.keySet());
  361. }
  362. }
  363. @Override
  364. protected InputStream getInputStream_Impl(ResourceLocation resource) throws IOException {
  365. return Minecraft.getInstance().getResourceManager().getResource(resource).getInputStream();
  366. }
  367. @Override
  368. protected InputStream getInputStream_Impl(ResourcePack resourcePack, ResourceLocation resource) throws IOException {
  369. return resourcePack.getInputStream(resource);
  370. }
  371. @Override
  372. protected String getFullPath_Impl(ResourceLocation resource) {
  373. return ASSETS + resource.getNamespace() + "/" + resource.getPath();
  374. }
  375. @Override
  376. protected ResourceLocation parsePath_Impl(String path) {
  377. if (path.startsWith(ASSETS)) {
  378. path = path.substring(ASSETS.length());
  379. int slash = path.indexOf('/');
  380. if (slash > 0 && slash + 1 < path.length()) {
  381. return new ResourceLocation(path.substring(0, slash), path.substring(slash + 1));
  382. }
  383. }
  384. return null;
  385. }
  386. @Override
  387. protected ResourceLocation parseResourceLocation_Impl(ResourceLocation baseResource, String path) {
  388. boolean absolute = false;
  389. if (path.startsWith("%blur%")) {
  390. path = path.substring(6);
  391. }
  392. if (path.startsWith("%clamp%")) {
  393. path = path.substring(7);
  394. }
  395. if (path.startsWith("/")) {
  396. path = path.substring(1);
  397. absolute = true;
  398. }
  399. if (path.startsWith("assets/minecraft/")) {
  400. path = path.substring(17);
  401. absolute = true;
  402. }
  403. // Absolute path, including namespace:
  404. // namespace:path/filename -> assets/namespace/path/filename
  405. int colon = path.indexOf(':');
  406. if (colon >= 0) {
  407. return new ResourceLocation(path.substring(0, colon), path.substring(colon + 1));
  408. }
  409. ResourceLocation resource;
  410. if (path.startsWith("~/")) {
  411. // Relative to namespace mcpatcher dir:
  412. // ~/path -> assets/(namespace of base file)/mcpatcher/path
  413. resource = new ResourceLocation(baseResource.getNamespace(), MCPATCHER_SUBDIR + path.substring(2));
  414. } else if (path.startsWith("./")) {
  415. // Relative to properties file:
  416. // ./path -> (dir of base file)/path
  417. resource = new ResourceLocation(baseResource.getNamespace(), baseResource.getPath().replaceFirst("[^/]+$", "") + path.substring(2));
  418. } else if (!absolute && !path.contains("/")) {
  419. // Relative to properties file:
  420. // filename -> (dir of base file)/filename
  421. resource = new ResourceLocation(baseResource.getNamespace(), baseResource.getPath().replaceFirst("[^/]+$", "") + path);
  422. } else {
  423. // Absolute path, w/o namespace:
  424. // path/filename -> assets/(namespace of base file)/path/filename
  425. resource = new ResourceLocation(baseResource.getNamespace(), path);
  426. }
  427. if (baseResource instanceof ResourceLocationWithSource) {
  428. resource = new ResourceLocationWithSource(((ResourceLocationWithSource) baseResource).getSource(), resource);
  429. }
  430. return resource;
  431. }
  432. @Override
  433. protected <T> T select_Impl(T v1, T v2) {
  434. return v2;
  435. }
  436. @Override
  437. protected boolean isDefaultResourcePack_Impl() {
  438. return getResourcePacks(DEFAULT_NAMESPACE).size() <= 1;
  439. }
  440. @Override
  441. protected int getTextureIfLoaded_Impl(ResourceLocation resource) {
  442. TextureObject texture = Minecraft.getInstance().getTextureManager().getTexture(resource);
  443. return texture instanceof AbstractTexture ? ((AbstractTexture) texture).glTextureId : -1;
  444. }
  445. @Override
  446. protected void bindTexture_Impl(ResourceLocation resource) {
  447. Minecraft.getInstance().getTextureManager().bindTexture(resource);
  448. }
  449. @Override
  450. protected void unloadTexture_Impl(ResourceLocation resource) {
  451. TextureManager textureManager = Minecraft.getInstance().getTextureManager();
  452. TextureObject texture = textureManager.getTexture(resource);
  453. if (texture != null && !(texture instanceof TextureAtlas) && !(texture instanceof DynamicTexture)) {
  454. if (texture instanceof AbstractTexture) {
  455. ((AbstractTexture) texture).unloadGLTexture();
  456. }
  457. logger.finer("unloading texture %s", resource);
  458. textureManager.texturesByName.remove(resource);
  459. }
  460. }
  461. @Override
  462. protected void flushUnusedTextures_Impl() {
  463. TextureManager textureManager = Minecraft.getInstance().getTextureManager();
  464. if (textureManager != null) {
  465. Set<ResourceLocation> texturesToUnload = new HashSet<ResourceLocation>();
  466. for (Map.Entry<ResourceLocation, TextureObject> entry : textureManager.texturesByName.entrySet()) {
  467. ResourceLocation resource = entry.getKey();
  468. TextureObject texture = entry.getValue();
  469. if (texture instanceof SimpleTexture && !(texture instanceof ThreadDownloadImageData) && !TexturePackAPI.hasResource(resource)) {
  470. texturesToUnload.add(resource);
  471. }
  472. }
  473. for (ResourceLocation resource : texturesToUnload) {
  474. unloadTexture(resource);
  475. }
  476. }
  477. }
  478. }
  479. }