PageRenderTime 73ms CodeModel.GetById 41ms RepoModel.GetById 0ms app.codeStats 1ms

/src/minecraft/com/mumfrey/liteloader/core/LiteLoader.java

https://bitbucket.org/codelore/xclient
Java | 1184 lines | 977 code | 207 blank | 0 comment | 193 complexity | 000888f7af5f40679a59e9784736fafa MD5 | raw file
  1. package com.mumfrey.liteloader.core;
  2. import com.mumfrey.liteloader.*;
  3. import com.mumfrey.liteloader.gui.GuiControlsPaginated;
  4. import com.mumfrey.liteloader.util.ModUtilities;
  5. import com.mumfrey.liteloader.util.PrivateFields;
  6. import net.minecraft.client.Minecraft;
  7. import net.minecraft.client.gui.GuiControls;
  8. import net.minecraft.client.gui.GuiNewChat;
  9. import net.minecraft.client.gui.GuiScreen;
  10. import net.minecraft.client.gui.ScaledResolution;
  11. import net.minecraft.logging.ILogAgent;
  12. import net.minecraft.network.packet.NetHandler;
  13. import net.minecraft.network.packet.Packet1Login;
  14. import net.minecraft.network.packet.Packet3Chat;
  15. import net.minecraft.profiler.IPlayerUsage;
  16. import net.minecraft.profiler.PlayerUsageSnooper;
  17. import net.minecraft.profiler.Profiler;
  18. import net.minecraft.util.Timer;
  19. import javax.activity.InvalidActivityException;
  20. import java.io.*;
  21. import java.lang.reflect.Method;
  22. import java.net.URL;
  23. import java.net.URLClassLoader;
  24. import java.net.URLDecoder;
  25. import java.nio.charset.Charset;
  26. import java.util.*;
  27. import java.util.logging.*;
  28. import java.util.logging.Formatter;
  29. import java.util.zip.ZipEntry;
  30. import java.util.zip.ZipFile;
  31. import java.util.zip.ZipInputStream;
  32. public final class LiteLoader
  33. implements FilenameFilter, IPlayerUsage
  34. {
  35. private static final String LOADER_VERSION = "1.5.2";
  36. private static final int LOADER_REVISION = 9;
  37. private static final String[] SUPPORTED_VERSIONS = { "1.5.2", "1.5.r1" };
  38. private static final int MAX_DISCOVERY_DEPTH = 16;
  39. private static LiteLoader instance;
  40. public static Logger logger = Logger.getLogger("liteloader");
  41. private static boolean useStdOut = false;
  42. private File modsFolder;
  43. private Minecraft minecraft = Minecraft.getMinecraft();
  44. private File propertiesFile = new File(Minecraft.getMinecraftDir(), "liteloader.properties");
  45. private Properties internalProperties = new Properties();
  46. private Properties localProperties = new Properties();
  47. private String branding = null;
  48. private boolean paginateControls = true;
  49. private Timer minecraftTimer;
  50. private String loadedModsList = "none";
  51. private Collection<LiteMod> mods = new LinkedList();
  52. private LinkedList tickListeners = new LinkedList();
  53. private LinkedList loopListeners = new LinkedList();
  54. private LinkedList initListeners = new LinkedList();
  55. private LinkedList renderListeners = new LinkedList();
  56. private LinkedList postRenderListeners = new LinkedList();
  57. private LinkedList chatRenderListeners = new LinkedList();
  58. private LinkedList chatListeners = new LinkedList();
  59. private LinkedList chatFilters = new LinkedList();
  60. private LinkedList loginListeners = new LinkedList();
  61. private LinkedList preLoginListeners = new LinkedList();
  62. private LinkedList pluginChannelListeners = new LinkedList();
  63. private HashMap pluginChannels = new HashMap();
  64. private Method mAddUrl;
  65. private boolean loaderStartupDone;
  66. private boolean loaderStartupComplete;
  67. private boolean lateInitDone;
  68. private boolean chatHooked;
  69. private boolean loginHooked;
  70. private boolean pluginChannelHooked;
  71. private boolean tickHooked;
  72. private HookProfiler profilerHook = new HookProfiler(this, logger);
  73. private ScaledResolution currentResolution;
  74. public static final LiteLoader getInstance()
  75. {
  76. if (instance == null)
  77. {
  78. instance = new LiteLoader();
  79. instance.initLoader();
  80. }
  81. return instance;
  82. }
  83. public static final Logger getLogger()
  84. {
  85. return logger;
  86. }
  87. public static final PrintStream getConsoleStream()
  88. {
  89. return useStdOut ? System.out : System.err;
  90. }
  91. public static final String getVersion()
  92. {
  93. return "1.5.2";
  94. }
  95. public static final int getRevision()
  96. {
  97. return 9;
  98. }
  99. private void initLoader()
  100. {
  101. if (this.loaderStartupDone) return;
  102. this.loaderStartupDone = true;
  103. prepareClassOverrides();
  104. if (prepareLoader())
  105. {
  106. logger.info(String.format("LiteLoader %s starting up...", new Object[] { "1.5.2" }));
  107. if (this.branding != null)
  108. {
  109. logger.info(String.format("Active Pack: %s", new Object[] { this.branding }));
  110. }
  111. logger.info(String.format("Java reports OS=\"%s\"", new Object[] { System.getProperty("os.name").toLowerCase() }));
  112. boolean searchMods = this.localProperties.getProperty("search.mods", "true").equalsIgnoreCase("true");
  113. boolean searchProtectionDomain = this.localProperties.getProperty("search.jar", "true").equalsIgnoreCase("true");
  114. boolean searchClassPath = this.localProperties.getProperty("search.classpath", "true").equalsIgnoreCase("true");
  115. if ((!searchMods) && (!searchProtectionDomain) && (!searchClassPath))
  116. {
  117. logger.warning("Invalid configuration, no search locations defined. Enabling all search locations.");
  118. this.localProperties.setProperty("search.mods", "true");
  119. this.localProperties.setProperty("search.jar", "true");
  120. this.localProperties.setProperty("search.classpath", "true");
  121. searchMods = true;
  122. searchProtectionDomain = true;
  123. searchClassPath = true;
  124. }
  125. prepareMods(searchMods, searchProtectionDomain, searchClassPath);
  126. initMods();
  127. initHooks();
  128. this.loaderStartupComplete = true;
  129. writeProperties();
  130. }
  131. }
  132. private void prepareClassOverrides()
  133. {
  134. registerBaseClassOverride(ModUtilities.getObfuscatedFieldName("net.minecraft.src.CallableJVMFlags", "h", "h"), "h");
  135. }
  136. private void registerBaseClassOverride(String binaryClassName, String fileName)
  137. {
  138. try
  139. {
  140. Method mDefineClass = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, Integer.TYPE, Integer.TYPE });
  141. mDefineClass.setAccessible(true);
  142. InputStream resourceInputStream = LiteLoader.class.getResourceAsStream("/classes/" + fileName + ".bin");
  143. if (resourceInputStream != null)
  144. {
  145. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  146. for (int readBytes = resourceInputStream.read(); readBytes >= 0; readBytes = resourceInputStream.read())
  147. {
  148. outputStream.write(readBytes);
  149. }
  150. byte[] data = outputStream.toByteArray();
  151. outputStream.close();
  152. resourceInputStream.close();
  153. logger.info("Defining class override for " + binaryClassName);
  154. mDefineClass.invoke(Minecraft.class.getClassLoader(), new Object[] { binaryClassName, data, Integer.valueOf(0), Integer.valueOf(data.length) });
  155. }
  156. else
  157. {
  158. logger.info("Error defining class override for " + binaryClassName + ", file not found");
  159. }
  160. }
  161. catch (Throwable th)
  162. {
  163. logger.log(Level.WARNING, "Error defining class override for " + binaryClassName, th);
  164. }
  165. }
  166. private boolean prepareLoader()
  167. {
  168. try
  169. {
  170. this.mAddUrl = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
  171. this.mAddUrl.setAccessible(true);
  172. prepareProperties();
  173. prepareLogger();
  174. this.paginateControls = this.localProperties.getProperty("controls.pages", "true").equalsIgnoreCase("true");
  175. this.localProperties.setProperty("controls.pages", String.valueOf(this.paginateControls));
  176. this.branding = this.internalProperties.getProperty("brand", null);
  177. if ((this.branding != null) && (this.branding.length() < 1)) this.branding = null;
  178. if (this.branding != null)
  179. this.localProperties.setProperty("brand", this.branding);
  180. else {
  181. this.localProperties.remove("brand");
  182. }
  183. }
  184. catch (Throwable th)
  185. {
  186. logger.log(Level.SEVERE, "Error initialising LiteLoader", th);
  187. return false;
  188. }
  189. return true;
  190. }
  191. private void prepareLogger()
  192. throws SecurityException, IOException
  193. {
  194. Formatter logFormatter = new LiteLoaderLogFormatter();
  195. logger.setUseParentHandlers(false);
  196. useStdOut = (System.getProperty("liteloader.log", "stderr").equalsIgnoreCase("stdout")) || (this.localProperties.getProperty("log", "stderr").equalsIgnoreCase("stdout"));
  197. StreamHandler consoleHandler = useStdOut ? new com.mumfrey.liteloader.util.log.ConsoleHandler() : new java.util.logging.ConsoleHandler();
  198. consoleHandler.setFormatter(logFormatter);
  199. logger.addHandler(consoleHandler);
  200. FileHandler logFileHandler = new FileHandler(new File(Minecraft.getMinecraftDir(), "LiteLoader.txt").getAbsolutePath());
  201. logFileHandler.setFormatter(logFormatter);
  202. logger.addHandler(logFileHandler);
  203. }
  204. private void prepareProperties()
  205. {
  206. try
  207. {
  208. InputStream propertiesStream = LiteLoader.class.getResourceAsStream("/liteloader.properties");
  209. if (propertiesStream != null)
  210. {
  211. this.internalProperties.load(propertiesStream);
  212. propertiesStream.close();
  213. }
  214. }
  215. catch (Throwable th)
  216. {
  217. this.internalProperties = new Properties();
  218. }
  219. try
  220. {
  221. this.localProperties = new Properties(this.internalProperties);
  222. InputStream localPropertiesStream = getLocalPropertiesStream();
  223. if (localPropertiesStream != null)
  224. {
  225. this.localProperties.load(localPropertiesStream);
  226. localPropertiesStream.close();
  227. }
  228. }
  229. catch (Throwable th)
  230. {
  231. this.localProperties = new Properties(this.internalProperties);
  232. }
  233. }
  234. private InputStream getLocalPropertiesStream()
  235. throws FileNotFoundException
  236. {
  237. if (this.propertiesFile.exists())
  238. {
  239. return new FileInputStream(this.propertiesFile);
  240. }
  241. return LiteLoader.class.getResourceAsStream("/liteloader.properties");
  242. }
  243. private void writeProperties()
  244. {
  245. try
  246. {
  247. this.localProperties.store(new FileWriter(this.propertiesFile), String.format("Properties for LiteLoader %s", new Object[] { "1.5.2" }));
  248. }
  249. catch (Throwable th)
  250. {
  251. logger.log(Level.WARNING, "Error writing liteloader properties", th);
  252. }
  253. }
  254. public File getModsFolder()
  255. {
  256. if (this.modsFolder == null)
  257. {
  258. this.modsFolder = new File(Minecraft.getMinecraftDir(), "mods");
  259. if ((!this.modsFolder.exists()) || (!this.modsFolder.isDirectory()))
  260. {
  261. try
  262. {
  263. this.modsFolder.mkdirs();
  264. }
  265. catch (Exception ex) {
  266. }
  267. }
  268. }
  269. return this.modsFolder;
  270. }
  271. public String getLoadedModsList()
  272. {
  273. return this.loadedModsList;
  274. }
  275. public String getBranding()
  276. {
  277. return this.branding;
  278. }
  279. public LiteMod getMod(String modName)
  280. throws InvalidActivityException, IllegalArgumentException
  281. {
  282. if (!this.loaderStartupComplete)
  283. {
  284. throw new InvalidActivityException("Attempted to get a reference to a mod before loader startup is complete");
  285. }
  286. if (modName == null)
  287. {
  288. throw new IllegalArgumentException("Attempted to get a reference to a mod without specifying a mod name");
  289. }
  290. for (LiteMod mod : this.mods)
  291. {
  292. if ((modName.equalsIgnoreCase(mod.getName())) || (modName.equalsIgnoreCase(mod.getClass().getSimpleName()))) return mod;
  293. }
  294. return null;
  295. }
  296. private void prepareMods(boolean searchMods, boolean searchProtectionDomain, boolean searchClassPath)
  297. {
  298. LinkedList modFiles = new LinkedList();
  299. if (searchMods)
  300. {
  301. File modFolder = getModsFolder();
  302. if ((modFolder.exists()) && (modFolder.isDirectory()))
  303. {
  304. logger.info("Mods folder found, searching " + modFolder.getPath());
  305. findModFiles(modFolder, modFiles);
  306. logger.info("Found " + modFiles.size() + " mod file(s)");
  307. }
  308. }
  309. HashMap modsToLoad = null;
  310. try
  311. {
  312. logger.info("Enumerating class path...");
  313. String classPath = System.getProperty("java.class.path");
  314. String classPathSeparator = System.getProperty("path.separator");
  315. String[] classPathEntries = classPath.split(classPathSeparator);
  316. logger.info(String.format("Class path separator=\"%s\"", new Object[] { classPathSeparator }));
  317. logger.info(String.format("Class path entries=(\n classpathEntry=%s\n)", new Object[] { classPath.replace(classPathSeparator, "\n classpathEntry=") }));
  318. if ((searchProtectionDomain) || (searchClassPath)) logger.info("Discovering mods on class path...");
  319. modsToLoad = findModClasses(classPathEntries, modFiles, searchProtectionDomain, searchClassPath);
  320. logger.info("Mod class discovery completed");
  321. }
  322. catch (Throwable th)
  323. {
  324. logger.log(Level.WARNING, "Mod class discovery failed", th);
  325. return;
  326. }
  327. loadMods(modsToLoad);
  328. }
  329. protected void findModFiles(File modFolder, LinkedList modFiles)
  330. {
  331. List supportedVerions = Arrays.asList(SUPPORTED_VERSIONS);
  332. for (File modFile : modFolder.listFiles(this))
  333. {
  334. try
  335. {
  336. ZipFile modZip = new ZipFile(modFile);
  337. ZipEntry version = modZip.getEntry("version.txt");
  338. if (version != null)
  339. {
  340. InputStream versionStream = modZip.getInputStream(version);
  341. BufferedReader versionReader = new BufferedReader(new InputStreamReader(versionStream));
  342. String strVersion = versionReader.readLine();
  343. versionReader.close();
  344. if ((supportedVerions.contains(strVersion)) && (addURLToClassPath(modFile.toURI().toURL())))
  345. {
  346. modFiles.add(modFile);
  347. }
  348. else
  349. {
  350. logger.info("Not adding invalid or outdated mod file: " + modFile.getAbsolutePath());
  351. }
  352. }
  353. modZip.close();
  354. }
  355. catch (Exception ex)
  356. {
  357. logger.warning("Error enumerating '" + modFile.getAbsolutePath() + "': Invalid zip file or error reading file");
  358. }
  359. }
  360. }
  361. public boolean accept(File dir, String fileName)
  362. {
  363. return fileName.toLowerCase().endsWith(".litemod");
  364. }
  365. private HashMap findModClasses(String[] classPathEntries, LinkedList modFiles, boolean searchProtectionDomain, boolean searchClassPath)
  366. {
  367. HashMap modsToLoad = new HashMap();
  368. if (searchProtectionDomain)
  369. {
  370. try
  371. {
  372. logger.info("Searching protection domain code source...");
  373. File packagePath = null;
  374. URL protectionDomainLocation = LiteLoader.class.getProtectionDomain().getCodeSource().getLocation();
  375. if (protectionDomainLocation != null)
  376. {
  377. if ((protectionDomainLocation.toString().indexOf('!') > -1) && (protectionDomainLocation.toString().startsWith("jar:")))
  378. {
  379. protectionDomainLocation = new URL(protectionDomainLocation.toString().substring(4, protectionDomainLocation.toString().indexOf('!')));
  380. }
  381. packagePath = new File(protectionDomainLocation.toURI());
  382. }
  383. else
  384. {
  385. String reflectionClassPath = LiteLoader.class.getResource("/com/mumfrey/liteloader/core/LiteLoader.class").getPath();
  386. if (reflectionClassPath.indexOf('!') > -1)
  387. {
  388. reflectionClassPath = URLDecoder.decode(reflectionClassPath, "UTF-8");
  389. packagePath = new File(reflectionClassPath.substring(5, reflectionClassPath.indexOf('!')));
  390. }
  391. }
  392. if (packagePath != null)
  393. {
  394. LinkedList modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");
  395. for (Class mod : (Collection<Class>)modClasses)
  396. {
  397. if (modsToLoad.containsKey(mod.getSimpleName()))
  398. {
  399. logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");
  400. }
  401. modsToLoad.put(mod.getSimpleName(), mod);
  402. }
  403. if (modClasses.size() > 0) logger.info(String.format("Found %s potential matches", new Object[] { Integer.valueOf(modClasses.size()) }));
  404. }
  405. }
  406. catch (Throwable th)
  407. {
  408. logger.warning("Error loading from local class path: " + th.getMessage());
  409. }
  410. }
  411. if (searchClassPath)
  412. {
  413. for (String classPathPart : classPathEntries)
  414. {
  415. logger.info(String.format("Searching %s...", new Object[] { classPathPart }));
  416. File packagePath = new File(classPathPart);
  417. LinkedList modClasses = getSubclassesFor(packagePath, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");
  418. for (Class mod : (Collection<Class>)modClasses)
  419. {
  420. if (modsToLoad.containsKey(mod.getSimpleName()))
  421. {
  422. logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");
  423. }
  424. modsToLoad.put(mod.getSimpleName(), mod);
  425. }
  426. if (modClasses.size() <= 0) continue; logger.info(String.format("Found %s potential matches", new Object[] { Integer.valueOf(modClasses.size()) }));
  427. }
  428. }
  429. for (File modFile : (Collection<File>)modFiles)
  430. {
  431. logger.info(String.format("Searching %s...", new Object[] { modFile.getAbsolutePath() }));
  432. LinkedList modClasses = getSubclassesFor(modFile, Minecraft.class.getClassLoader(), LiteMod.class, "LiteMod");
  433. for (Class mod : (Collection<Class>)modClasses)
  434. {
  435. if (modsToLoad.containsKey(mod.getSimpleName()))
  436. {
  437. logger.warning("Mod name collision for mod with class '" + mod.getSimpleName() + "', maybe you have more than one copy?");
  438. }
  439. modsToLoad.put(mod.getSimpleName(), mod);
  440. }
  441. if (modClasses.size() > 0) logger.info(String.format("Found %s potential matches", new Object[] { Integer.valueOf(modClasses.size()) }));
  442. }
  443. return modsToLoad;
  444. }
  445. private void loadMods(HashMap modsToLoad)
  446. {
  447. if (modsToLoad == null)
  448. {
  449. logger.info("Mod class discovery failed. Not loading any mods!");
  450. return;
  451. }
  452. logger.info("Discovered " + modsToLoad.size() + " total mod(s)");
  453. for (Class mod : (Collection<Class>)modsToLoad.values())
  454. {
  455. try
  456. {
  457. logger.info("Loading mod from " + mod.getName());
  458. LiteMod newMod = (LiteMod)mod.newInstance();
  459. this.mods.add(newMod);
  460. logger.info("Successfully added mod " + newMod.getName() + " version " + newMod.getVersion());
  461. }
  462. catch (Throwable th)
  463. {
  464. logger.warning(th.toString());
  465. th.printStackTrace();
  466. }
  467. }
  468. }
  469. private void initMods()
  470. {
  471. this.loadedModsList = "";
  472. int loadedModsCount = 0;
  473. for (Iterator iter = this.mods.iterator(); iter.hasNext(); )
  474. {
  475. LiteMod mod = (LiteMod)iter.next();
  476. try
  477. {
  478. logger.info("Initialising mod " + mod.getName() + " version " + mod.getVersion());
  479. mod.init();
  480. if ((mod instanceof Tickable))
  481. {
  482. addTickListener((Tickable)mod);
  483. }
  484. if ((mod instanceof GameLoopListener))
  485. {
  486. addLoopListener((GameLoopListener)mod);
  487. }
  488. if ((mod instanceof InitCompleteListener))
  489. {
  490. addInitListener((InitCompleteListener)mod);
  491. }
  492. if ((mod instanceof RenderListener))
  493. {
  494. addRenderListener((RenderListener)mod);
  495. }
  496. if ((mod instanceof PostRenderListener))
  497. {
  498. addPostRenderListener((PostRenderListener)mod);
  499. }
  500. if ((mod instanceof ChatFilter))
  501. {
  502. addChatFilter((ChatFilter)mod);
  503. }
  504. if ((mod instanceof ChatListener))
  505. {
  506. if ((mod instanceof ChatFilter))
  507. {
  508. logger.warning(String.format("Interface error initialising mod '%1s'. A mod implementing ChatFilter and ChatListener is not supported! Remove one of these interfaces", new Object[] { mod.getName() }));
  509. }
  510. else
  511. {
  512. addChatListener((ChatListener)mod);
  513. }
  514. }
  515. if ((mod instanceof ChatRenderListener))
  516. {
  517. addChatRenderListener((ChatRenderListener)mod);
  518. }
  519. if ((mod instanceof PreLoginListener))
  520. {
  521. addPreLoginListener((PreLoginListener)mod);
  522. }
  523. if ((mod instanceof LoginListener))
  524. {
  525. addLoginListener((LoginListener)mod);
  526. }
  527. if ((mod instanceof PluginChannelListener))
  528. {
  529. addPluginChannelListener((PluginChannelListener)mod);
  530. }
  531. this.loadedModsList += String.format("\n - %s version %s", new Object[] { mod.getName(), mod.getVersion() });
  532. loadedModsCount++;
  533. }
  534. catch (Throwable th)
  535. {
  536. logger.log(Level.WARNING, "Error initialising mod '" + mod.getName(), th);
  537. iter.remove();
  538. }
  539. }
  540. this.loadedModsList = String.format("%s loaded mod(s)%s", new Object[] { Integer.valueOf(loadedModsCount), this.loadedModsList });
  541. }
  542. private void initHooks()
  543. {
  544. try
  545. {
  546. if (((this.chatListeners.size() > 0) || (this.chatFilters.size() > 0)) && (!this.chatHooked))
  547. {
  548. this.chatHooked = true;
  549. HookChat.register();
  550. HookChat.registerPacketHandler(this);
  551. }
  552. if (((this.preLoginListeners.size() > 0) || (this.loginListeners.size() > 0)) && (!this.loginHooked))
  553. {
  554. this.loginHooked = true;
  555. ModUtilities.registerPacketOverride(1, HookLogin.class);
  556. HookLogin.loader = this;
  557. }
  558. if ((this.pluginChannelListeners.size() > 0) && (!this.pluginChannelHooked))
  559. {
  560. this.pluginChannelHooked = true;
  561. HookPluginChannels.register();
  562. HookPluginChannels.registerPacketHandler(this);
  563. }
  564. if (!this.tickHooked)
  565. {
  566. this.tickHooked = true;
  567. PrivateFields.minecraftProfiler.setFinal(this.minecraft, this.profilerHook);
  568. }
  569. PlayerUsageSnooper snooper = this.minecraft.getPlayerUsageSnooper();
  570. PrivateFields.playerStatsCollector.setFinal(snooper, this);
  571. }
  572. catch (Exception ex)
  573. {
  574. logger.log(Level.WARNING, "Error creating hooks", ex);
  575. ex.printStackTrace();
  576. }
  577. }
  578. public void addTickListener(Tickable tickable)
  579. {
  580. if (!this.tickListeners.contains(tickable))
  581. {
  582. this.tickListeners.add(tickable);
  583. if (this.loaderStartupComplete) initHooks();
  584. }
  585. }
  586. public void addLoopListener(GameLoopListener loopListener)
  587. {
  588. if (!this.loopListeners.contains(loopListener))
  589. {
  590. this.loopListeners.add(loopListener);
  591. if (this.loaderStartupComplete) initHooks();
  592. }
  593. }
  594. public void addInitListener(InitCompleteListener initCompleteListener)
  595. {
  596. if (!this.initListeners.contains(initCompleteListener))
  597. {
  598. this.initListeners.add(initCompleteListener);
  599. if (this.loaderStartupComplete) initHooks();
  600. }
  601. }
  602. public void addRenderListener(RenderListener tickable)
  603. {
  604. if (!this.renderListeners.contains(tickable))
  605. {
  606. this.renderListeners.add(tickable);
  607. if (this.loaderStartupComplete) initHooks();
  608. }
  609. }
  610. public void addPostRenderListener(PostRenderListener tickable)
  611. {
  612. if (!this.postRenderListeners.contains(tickable))
  613. {
  614. this.postRenderListeners.add(tickable);
  615. if (this.loaderStartupComplete) initHooks();
  616. }
  617. }
  618. public void addChatFilter(ChatFilter chatFilter)
  619. {
  620. if (!this.chatFilters.contains(chatFilter))
  621. {
  622. this.chatFilters.add(chatFilter);
  623. if (this.loaderStartupComplete) initHooks();
  624. }
  625. }
  626. public void addChatListener(ChatListener chatListener)
  627. {
  628. if (!this.chatListeners.contains(chatListener))
  629. {
  630. this.chatListeners.add(chatListener);
  631. if (this.loaderStartupComplete) initHooks();
  632. }
  633. }
  634. public void addChatRenderListener(ChatRenderListener chatRenderListener)
  635. {
  636. if (!this.chatRenderListeners.contains(chatRenderListener))
  637. {
  638. this.chatRenderListeners.add(chatRenderListener);
  639. if (this.loaderStartupComplete) initHooks();
  640. }
  641. }
  642. public void addPreLoginListener(PreLoginListener loginListener)
  643. {
  644. if (!this.preLoginListeners.contains(loginListener))
  645. {
  646. this.preLoginListeners.add(loginListener);
  647. if (this.loaderStartupComplete) initHooks();
  648. }
  649. }
  650. public void addLoginListener(LoginListener loginListener)
  651. {
  652. if (!this.loginListeners.contains(loginListener))
  653. {
  654. this.loginListeners.add(loginListener);
  655. if (this.loaderStartupComplete) initHooks();
  656. }
  657. }
  658. public void addPluginChannelListener(PluginChannelListener pluginChannelListener)
  659. {
  660. if (!this.pluginChannelListeners.contains(pluginChannelListener))
  661. {
  662. this.pluginChannelListeners.add(pluginChannelListener);
  663. if (this.loaderStartupComplete) initHooks();
  664. }
  665. }
  666. private static LinkedList getSubclassesFor(File packagePath, ClassLoader classloader, Class superClass, String prefix)
  667. {
  668. LinkedList classes = new LinkedList();
  669. try
  670. {
  671. if (packagePath.isDirectory())
  672. {
  673. enumerateDirectory(prefix, superClass, classloader, classes, packagePath);
  674. }
  675. else if ((packagePath.isFile()) && ((packagePath.getName().endsWith(".jar")) || (packagePath.getName().endsWith(".zip")) || (packagePath.getName().endsWith(".litemod"))))
  676. {
  677. enumerateCompressedPackage(prefix, superClass, classloader, classes, packagePath);
  678. }
  679. }
  680. catch (Throwable th)
  681. {
  682. logger.log(Level.WARNING, "Enumeration error", th);
  683. }
  684. return classes;
  685. }
  686. private static void enumerateCompressedPackage(String prefix, Class superClass, ClassLoader classloader, LinkedList classes, File packagePath)
  687. throws IOException, FileNotFoundException
  688. {
  689. FileInputStream fileinputstream = new FileInputStream(packagePath);
  690. ZipInputStream zipinputstream = new ZipInputStream(fileinputstream);
  691. ZipEntry zipentry = null;
  692. do
  693. {
  694. zipentry = zipinputstream.getNextEntry();
  695. if ((zipentry == null) || (!zipentry.getName().endsWith(".class")))
  696. continue;
  697. String classFileName = zipentry.getName();
  698. String className = classFileName.lastIndexOf('/') > -1 ? classFileName.substring(classFileName.lastIndexOf('/') + 1) : classFileName;
  699. if ((prefix != null) && (!className.startsWith(prefix)))
  700. continue;
  701. try
  702. {
  703. String fullClassName = classFileName.substring(0, classFileName.length() - 6).replaceAll("/", ".");
  704. checkAndAddClass(classloader, superClass, classes, fullClassName);
  705. }
  706. catch (Exception ex)
  707. {
  708. }
  709. }
  710. while (zipentry != null);
  711. fileinputstream.close();
  712. }
  713. private static void enumerateDirectory(String prefix, Class superClass, ClassLoader classloader, LinkedList classes, File packagePath)
  714. {
  715. enumerateDirectory(prefix, superClass, classloader, classes, packagePath, "", 0);
  716. }
  717. private static void enumerateDirectory(String prefix, Class superClass, ClassLoader classloader, LinkedList classes, File packagePath, String packageName, int depth)
  718. {
  719. if (depth > 16) return;
  720. File[] classFiles = packagePath.listFiles();
  721. for (File classFile : classFiles)
  722. {
  723. if (classFile.isDirectory())
  724. {
  725. enumerateDirectory(prefix, superClass, classloader, classes, classFile, packageName + classFile.getName() + ".", depth + 1);
  726. }
  727. else
  728. {
  729. if ((!classFile.getName().endsWith(".class")) || ((prefix != null) && (!classFile.getName().startsWith(prefix))))
  730. continue;
  731. String classFileName = classFile.getName();
  732. String className = packageName + classFileName.substring(0, classFileName.length() - 6);
  733. checkAndAddClass(classloader, superClass, classes, className);
  734. }
  735. }
  736. }
  737. private static void checkAndAddClass(ClassLoader classloader, Class superClass, LinkedList classes, String className)
  738. {
  739. if (className.indexOf('$') > -1) {
  740. return;
  741. }
  742. try
  743. {
  744. Class subClass = classloader.loadClass(className);
  745. if ((subClass != null) && (!superClass.equals(subClass)) && (superClass.isAssignableFrom(subClass)) && (!subClass.isInterface()) && (!classes.contains(subClass)))
  746. {
  747. classes.add(subClass);
  748. }
  749. }
  750. catch (Throwable th)
  751. {
  752. logger.log(Level.WARNING, "checkAndAddClass error", th);
  753. }
  754. }
  755. private boolean addURLToClassPath(URL classUrl)
  756. {
  757. try
  758. {
  759. if (((Minecraft.class.getClassLoader() instanceof URLClassLoader)) && (this.mAddUrl != null) && (this.mAddUrl.isAccessible()))
  760. {
  761. URLClassLoader classLoader = (URLClassLoader)Minecraft.class.getClassLoader();
  762. this.mAddUrl.invoke(classLoader, new Object[] { classUrl });
  763. return true;
  764. }
  765. }
  766. catch (Throwable th)
  767. {
  768. logger.log(Level.WARNING, "Error adding class path entry", th);
  769. }
  770. return false;
  771. }
  772. public void onInit()
  773. {
  774. if (!this.lateInitDone)
  775. {
  776. this.lateInitDone = true;
  777. for (InitCompleteListener initMod : (Collection<InitCompleteListener>)this.initListeners)
  778. {
  779. try
  780. {
  781. logger.info("Calling late init for mod " + initMod.getName());
  782. initMod.onInitCompleted(this.minecraft, this);
  783. }
  784. catch (Throwable th)
  785. {
  786. logger.log(Level.WARNING, "Error initialising mod " + initMod.getName(), th);
  787. }
  788. }
  789. }
  790. }
  791. public void onRender()
  792. {
  793. if ((this.paginateControls) && (this.minecraft.currentScreen != null) && (this.minecraft.currentScreen.getClass().equals(GuiControls.class)))
  794. {
  795. try
  796. {
  797. GuiScreen parentScreen = (GuiScreen)PrivateFields.guiControlsParentScreen.get((GuiControls)this.minecraft.currentScreen);
  798. this.minecraft.displayGuiScreen(new GuiControlsPaginated(parentScreen, this.minecraft.gameSettings));
  799. }
  800. catch (Exception ex) {
  801. }
  802. }
  803. for (RenderListener renderListener : (Collection<RenderListener>)this.renderListeners)
  804. renderListener.onRender();
  805. }
  806. public void postRenderEntities()
  807. {
  808. float partialTicks = this.minecraftTimer != null ? this.minecraftTimer.elapsedPartialTicks : 0.0F;
  809. for (PostRenderListener renderListener : (Collection<PostRenderListener>)this.postRenderListeners)
  810. renderListener.onPostRenderEntities(partialTicks);
  811. }
  812. public void postRender()
  813. {
  814. float partialTicks = this.minecraftTimer != null ? this.minecraftTimer.elapsedPartialTicks : 0.0F;
  815. for (PostRenderListener renderListener : (Collection<PostRenderListener>)this.postRenderListeners)
  816. renderListener.onPostRender(partialTicks);
  817. }
  818. public void onBeforeGuiRender()
  819. {
  820. for (RenderListener renderListener : (Collection<RenderListener>)this.renderListeners)
  821. renderListener.onRenderGui(this.minecraft.currentScreen);
  822. }
  823. public void onSetupCameraTransform()
  824. {
  825. for (RenderListener renderListener : (Collection<RenderListener>)this.renderListeners)
  826. renderListener.onSetupCameraTransform();
  827. }
  828. public void onBeforeChatRender()
  829. {
  830. this.currentResolution = new ScaledResolution(this.minecraft.gameSettings, this.minecraft.displayWidth, this.minecraft.displayHeight);
  831. int screenWidth = this.currentResolution.getScaledWidth();
  832. int screenHeight = this.currentResolution.getScaledHeight();
  833. GuiNewChat chat = this.minecraft.ingameGUI.getChatGUI();
  834. for (ChatRenderListener chatRenderListener : (Collection<ChatRenderListener>)this.chatRenderListeners)
  835. chatRenderListener.onPreRenderChat(screenWidth, screenHeight, chat);
  836. }
  837. public void onAfterChatRender()
  838. {
  839. int screenWidth = this.currentResolution.getScaledWidth();
  840. int screenHeight = this.currentResolution.getScaledHeight();
  841. GuiNewChat chat = this.minecraft.ingameGUI.getChatGUI();
  842. for (ChatRenderListener chatRenderListener : (Collection<ChatRenderListener>)this.chatRenderListeners)
  843. chatRenderListener.onPostRenderChat(screenWidth, screenHeight, chat);
  844. }
  845. public void onTimerUpdate()
  846. {
  847. for (GameLoopListener loopListener : (Collection<GameLoopListener>)this.loopListeners)
  848. loopListener.onRunGameLoop(this.minecraft);
  849. }
  850. public void onTick(Profiler profiler, boolean tick)
  851. {
  852. float partialTicks = 0.0F;
  853. if ((tick) || (this.minecraftTimer == null))
  854. {
  855. this.minecraftTimer = ((Timer)PrivateFields.minecraftTimer.get(this.minecraft));
  856. }
  857. if (this.minecraftTimer != null)
  858. {
  859. partialTicks = this.minecraftTimer.renderPartialTicks;
  860. tick = this.minecraftTimer.elapsedTicks > 0;
  861. }
  862. boolean inGame = (this.minecraft.renderViewEntity != null) && (this.minecraft.renderViewEntity.worldObj != null);
  863. for (Tickable tickable : (Collection<Tickable>)this.tickListeners)
  864. {
  865. profiler.startSection(tickable.getClass().getSimpleName());
  866. tickable.onTick(this.minecraft, partialTicks, inGame, tick);
  867. profiler.endSection();
  868. }
  869. }
  870. public boolean onChat(Packet3Chat chatPacket)
  871. {
  872. for (ChatFilter chatFilter : (Collection<ChatFilter>)this.chatFilters) {
  873. if (!chatFilter.onChat(chatPacket)) {
  874. return false;
  875. }
  876. }
  877. for (ChatListener chatListener : (Collection<ChatListener>)this.chatListeners) {
  878. chatListener.onChat(chatPacket.message);
  879. }
  880. return true;
  881. }
  882. public boolean onPreLogin(NetHandler netHandler, Packet1Login loginPacket)
  883. {
  884. boolean cancelled = false;
  885. for (PreLoginListener loginListener : (Collection<PreLoginListener>)this.preLoginListeners)
  886. {
  887. cancelled |= !loginListener.onPreLogin(netHandler, loginPacket);
  888. }
  889. return !cancelled;
  890. }
  891. public void onConnectToServer(NetHandler netHandler, Packet1Login loginPacket)
  892. {
  893. for (LoginListener loginListener : (Collection<LoginListener>)this.loginListeners) {
  894. loginListener.onLogin(netHandler, loginPacket);
  895. }
  896. setupPluginChannels();
  897. }
  898. public void onPluginChannelMessage(HookPluginChannels hookPluginChannels)
  899. {
  900. if ((hookPluginChannels != null) && (hookPluginChannels.channel != null) && (this.pluginChannels.containsKey(hookPluginChannels.channel)))
  901. {
  902. for (PluginChannelListener pluginChannelListener : (Collection<PluginChannelListener>)this.pluginChannels.get(hookPluginChannels.channel))
  903. {
  904. try
  905. {
  906. pluginChannelListener.onCustomPayload(hookPluginChannels.channel, hookPluginChannels.length, hookPluginChannels.data);
  907. }
  908. catch (Exception ex)
  909. {
  910. }
  911. }
  912. }
  913. }
  914. public void sendPluginChannelMessage(String channel, byte[] data)
  915. {
  916. ModUtilities.sendPluginChannelMessage(channel, data);
  917. }
  918. protected void setupPluginChannels()
  919. {
  920. this.pluginChannels.clear();
  921. for (PluginChannelListener pluginChannelListener : (Collection<PluginChannelListener>)pluginChannelListeners) {
  922. List channels = pluginChannelListener.getChannels();
  923. if (channels != null)
  924. {
  925. for (String channel : (Collection<String>)channels)
  926. {
  927. if ((channel.length() > 16) || (channel.toUpperCase().equals("REGISTER")) || (channel.toUpperCase().equals("UNREGISTER"))) {
  928. continue;
  929. }
  930. if (!this.pluginChannels.containsKey(channel))
  931. {
  932. this.pluginChannels.put(channel, new LinkedList());
  933. }
  934. ((LinkedList)this.pluginChannels.get(channel)).add(pluginChannelListener);
  935. }
  936. }
  937. }
  938. PluginChannelListener pluginChannelListener;
  939. if (this.pluginChannels.keySet().size() > 0)
  940. {
  941. StringBuilder channelList = new StringBuilder();
  942. boolean separator = false;
  943. for (String channel : (Collection<String>)this.pluginChannels.keySet())
  944. {
  945. if (separator) channelList.append("");
  946. channelList.append(channel);
  947. separator = true;
  948. }
  949. byte[] registrationData = channelList.toString().getBytes(Charset.forName("UTF8"));
  950. sendPluginChannelMessage("REGISTER", registrationData);
  951. }
  952. }
  953. public void addServerStatsToSnooper(PlayerUsageSnooper var1)
  954. {
  955. this.minecraft.addServerStatsToSnooper(var1);
  956. }
  957. public void addServerTypeToSnooper(PlayerUsageSnooper var1)
  958. {
  959. sanityCheck();
  960. this.minecraft.addServerTypeToSnooper(var1);
  961. }
  962. public boolean isSnooperEnabled()
  963. {
  964. return this.minecraft.isSnooperEnabled();
  965. }
  966. public ILogAgent getLogAgent()
  967. {
  968. return this.minecraft.getLogAgent();
  969. }
  970. private void sanityCheck()
  971. {
  972. if ((this.tickHooked) && (this.minecraft.mcProfiler != this.profilerHook))
  973. {
  974. PrivateFields.minecraftProfiler.setFinal(this.minecraft, this.profilerHook);
  975. }
  976. }
  977. }