Commit 14886082e2460b6d77205a1681580949d6be3ba3

Authored by Mumfrey
1 parent 71a4ac62

LiteLoader 1.3.2_03

+ Added plugin channels support
 + small changes to exception/throwable logging
 + added some comments to uncommented interfaces
java/com/mumfrey/liteloader/InitCompleteListener.java
... ... @@ -4,7 +4,19 @@ import net.minecraft.client.Minecraft;
4 4  
5 5 import com.mumfrey.liteloader.core.LiteLoader;
6 6  
  7 +/**
  8 + * Interface for mods which need to initialise stuff once the game initialisation is completed,
  9 + * for example mods which need to register new renderers.
  10 + *
  11 + * @author Adam Mummery-Smith
  12 + */
7 13 public interface InitCompleteListener extends Tickable
8 14 {
  15 + /**
  16 + * Called as soon as the game is initialised and the main game loop is running
  17 + *
  18 + * @param minecraft Minecraft instance
  19 + * @param loader LiteLoader instance
  20 + */
9 21 public abstract void onInitCompleted(Minecraft minecraft, LiteLoader loader);
10 22 }
... ...
java/com/mumfrey/liteloader/PluginChannelListener.java 0 → 100644
  1 +package com.mumfrey.liteloader;
  2 +
  3 +import java.util.List;
  4 +
  5 +/**
  6 + * Interface for mods which want to use plugin channels
  7 + *
  8 + * @author Adam Mummery-Smith
  9 + */
  10 +public interface PluginChannelListener extends LoginListener
  11 +{
  12 + /**
  13 + * Return a list of the plugin channels the mod wants to register
  14 + *
  15 + * @return
  16 + */
  17 + public abstract List<String> getChannels();
  18 +
  19 + /**
  20 + * Called when a custom payload packet arrives on a channel this mod has registered
  21 + *
  22 + * @param channel Channel on which the custom payload was received
  23 + * @param length Length of the custom payload data
  24 + * @param data Custom payload data
  25 + */
  26 + public abstract void onCustomPayload(String channel, int length, byte[] data);
  27 +}
... ...
java/com/mumfrey/liteloader/core/HookChat.java
... ... @@ -3,6 +3,7 @@ package com.mumfrey.liteloader.core;
3 3 import java.io.DataInputStream;
4 4 import java.io.DataOutputStream;
5 5 import java.io.IOException;
  6 +import java.lang.reflect.Constructor;
6 7 import java.util.Map;
7 8  
8 9 import net.minecraft.src.IntHashMap;
... ... @@ -53,7 +54,7 @@ public class HookChat extends Packet3Chat
53 54 {
54 55 if (proxyClass != null)
55 56 {
56   - proxyPacket = (Packet)proxyClass.newInstance();
  57 + proxyPacket = proxyClass.newInstance();
57 58 }
58 59 }
59 60 catch (Exception ex) {}
... ... @@ -71,7 +72,12 @@ public class HookChat extends Packet3Chat
71 72 {
72 73 if (proxyClass != null)
73 74 {
74   - proxyPacket = (Packet)proxyClass.newInstance();
  75 + proxyPacket = proxyClass.newInstance();
  76 +
  77 + if (proxyPacket instanceof Packet3Chat)
  78 + {
  79 + ((Packet3Chat)proxyPacket).message = this.message;
  80 + }
75 81 }
76 82 }
77 83 catch (Exception ex) {}
... ... @@ -142,15 +148,15 @@ public class HookChat extends Packet3Chat
142 148 *
143 149 * @param force Force registration even if registration was already performed previously.
144 150 */
145   - public static void Register(boolean force)
  151 + @SuppressWarnings("unchecked")
  152 + public static void Register(boolean force)
146 153 {
147   - System.out.println("LITELOADER REGISTER");
148 154 if (!registered || force)
149 155 {
150 156 try
151 157 {
152 158 IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;
153   - proxyClass = (Class)packetIdToClassMap.lookup(3);
  159 + proxyClass = (Class<? extends Packet>)packetIdToClassMap.lookup(3);
154 160  
155 161 if (proxyClass.equals(Packet3Chat.class))
156 162 {
... ...
java/com/mumfrey/liteloader/core/HookPluginChannels.java 0 → 100644
  1 +package com.mumfrey.liteloader.core;
  2 +
  3 +import java.io.DataInputStream;
  4 +import java.io.DataOutputStream;
  5 +import java.io.IOException;
  6 +import java.lang.reflect.Constructor;
  7 +import java.util.Map;
  8 +
  9 +import com.mumfrey.liteloader.util.PrivateFields;
  10 +
  11 +import net.minecraft.src.IntHashMap;
  12 +import net.minecraft.src.NetHandler;
  13 +import net.minecraft.src.Packet;
  14 +import net.minecraft.src.Packet250CustomPayload;
  15 +import net.minecraft.src.Packet3Chat;
  16 +
  17 +public class HookPluginChannels extends Packet250CustomPayload
  18 +{
  19 + /**
  20 + * True if this class was registered with the base class
  21 + */
  22 + private static boolean registered = false;
  23 +
  24 + /**
  25 + * Handler module which is registered to handle inbound chat packets
  26 + */
  27 + private static LiteLoader packetHandler;
  28 +
  29 + /**
  30 + * Class which was overridden and will be instanced for new packets
  31 + */
  32 + private static Class<? extends Packet> proxyClass;
  33 +
  34 + /**
  35 + * Instance of the proxy packet for this packet instance
  36 + */
  37 + private Packet proxyPacket;
  38 +
  39 + public HookPluginChannels()
  40 + {
  41 + super();
  42 +
  43 + try
  44 + {
  45 + if (proxyClass != null)
  46 + {
  47 + proxyPacket = proxyClass.newInstance();
  48 + }
  49 + }
  50 + catch (Exception ex) {}
  51 + }
  52 +
  53 + public HookPluginChannels(String channel, byte[] data)
  54 + {
  55 + super(channel, data);
  56 +
  57 + try
  58 + {
  59 + if (proxyClass != null)
  60 + {
  61 + proxyPacket = proxyClass.newInstance();
  62 +
  63 + if (proxyPacket instanceof Packet250CustomPayload)
  64 + {
  65 + ((Packet250CustomPayload)proxyPacket).channel = this.channel;
  66 + ((Packet250CustomPayload)proxyPacket).data = this.data;
  67 + ((Packet250CustomPayload)proxyPacket).length = this.length;
  68 + }
  69 + }
  70 + }
  71 + catch (Exception ex) {}
  72 + }
  73 +
  74 +
  75 + @Override
  76 + public void readPacketData(DataInputStream datainputstream) throws IOException
  77 + {
  78 + if (proxyPacket != null)
  79 + {
  80 + proxyPacket.readPacketData(datainputstream);
  81 + this.channel = ((Packet250CustomPayload)proxyPacket).channel;
  82 + this.length = ((Packet250CustomPayload)proxyPacket).length;
  83 + this.data = ((Packet250CustomPayload)proxyPacket).data;
  84 + }
  85 + else
  86 + super.readPacketData(datainputstream);
  87 + }
  88 +
  89 + @Override
  90 + public void writePacketData(DataOutputStream dataoutputstream) throws IOException
  91 + {
  92 + if (proxyPacket != null)
  93 + proxyPacket.writePacketData(dataoutputstream);
  94 + else
  95 + super.writePacketData(dataoutputstream);
  96 + }
  97 +
  98 + @Override
  99 + public void processPacket(NetHandler nethandler)
  100 + {
  101 + if (proxyPacket != null)
  102 + proxyPacket.processPacket(nethandler);
  103 + else
  104 + super.processPacket(nethandler);
  105 +
  106 + if (packetHandler != null)
  107 + {
  108 + packetHandler.onPluginChannelMessage(this);
  109 + }
  110 + }
  111 +
  112 + @Override
  113 + public int getPacketSize()
  114 + {
  115 + if (proxyPacket != null)
  116 + return proxyPacket.getPacketSize();
  117 + else
  118 + return super.getPacketSize();
  119 + }
  120 +
  121 + /**
  122 + * Register the specified handler as the packet handler for this packet
  123 + * @param handler
  124 + */
  125 + public static void RegisterPacketHandler(LiteLoader handler)
  126 + {
  127 + packetHandler = handler;
  128 + }
  129 +
  130 + /**
  131 + * Register this packet as the new packet for packet ID 250
  132 + */
  133 + public static void Register()
  134 + {
  135 + Register(false);
  136 + }
  137 +
  138 + /**
  139 + * Register this packet as the new packet for packet ID 250 and optionally force re-registration even
  140 + * if registration was performed already.
  141 + *
  142 + * @param force Force registration even if registration was already performed previously.
  143 + */
  144 + @SuppressWarnings("unchecked")
  145 + public static void Register(boolean force)
  146 + {
  147 + if (!registered || force)
  148 + {
  149 + try
  150 + {
  151 + IntHashMap packetIdToClassMap = Packet.packetIdToClassMap;
  152 + proxyClass = (Class<? extends Packet>)packetIdToClassMap.lookup(250);
  153 +
  154 + if (proxyClass.equals(Packet250CustomPayload.class))
  155 + {
  156 + proxyClass = null;
  157 + }
  158 +
  159 + packetIdToClassMap.removeObject(250);
  160 + packetIdToClassMap.addKey(250, HookPluginChannels.class);
  161 +
  162 + Map packetClassToIdMap = PrivateFields.StaticFields.packetClassToIdMap.Get();
  163 + packetClassToIdMap.put(HookPluginChannels.class, Integer.valueOf(250));
  164 +
  165 + registered = true;
  166 + }
  167 + catch (Exception ex)
  168 + {
  169 + ex.printStackTrace();
  170 + }
  171 + }
  172 + }
  173 +}
... ...
java/com/mumfrey/liteloader/core/LiteLoader.java
... ... @@ -13,6 +13,7 @@ import java.lang.reflect.Constructor;
13 13 import java.lang.reflect.Method;
14 14 import java.net.URL;
15 15 import java.net.URLClassLoader;
  16 +import java.nio.charset.Charset;
16 17 import java.util.Arrays;
17 18 import java.util.HashMap;
18 19 import java.util.Iterator;
... ... @@ -21,6 +22,7 @@ import java.util.List;
21 22 import java.util.logging.ConsoleHandler;
22 23 import java.util.logging.FileHandler;
23 24 import java.util.logging.Formatter;
  25 +import java.util.logging.Level;
24 26 import java.util.logging.Logger;
25 27 import java.util.logging.StreamHandler;
26 28 import java.util.zip.ZipEntry;
... ... @@ -31,6 +33,7 @@ import net.minecraft.client.Minecraft;
31 33 import net.minecraft.src.ConsoleLogManager;
32 34 import net.minecraft.src.NetHandler;
33 35 import net.minecraft.src.Packet1Login;
  36 +import net.minecraft.src.Packet250CustomPayload;
34 37 import net.minecraft.src.Packet3Chat;
35 38 import net.minecraft.src.Timer;
36 39  
... ... @@ -39,6 +42,7 @@ import com.mumfrey.liteloader.ChatListener;
39 42 import com.mumfrey.liteloader.InitCompleteListener;
40 43 import com.mumfrey.liteloader.LiteMod;
41 44 import com.mumfrey.liteloader.LoginListener;
  45 +import com.mumfrey.liteloader.PluginChannelListener;
42 46 import com.mumfrey.liteloader.Tickable;
43 47 import com.mumfrey.liteloader.util.ModUtilities;
44 48 import com.mumfrey.liteloader.util.PrivateFields;
... ... @@ -47,14 +51,14 @@ import com.mumfrey.liteloader.util.PrivateFields;
47 51 * LiteLoader is a simple loader which provides tick events to loaded mods
48 52 *
49 53 * @author Adam Mummery-Smith
50   - * @version 1.3.2_02
  54 + * @version 1.3.2_03
51 55 */
52 56 public final class LiteLoader implements FilenameFilter
53 57 {
54 58 /**
55 59 * Liteloader version
56 60 */
57   - private static final String LOADER_VERSION = "1.3.2_02";
  61 + private static final String LOADER_VERSION = "1.3.2_03";
58 62  
59 63 /**
60 64 * Minecraft versions that we will load mods for, this will be compared
... ... @@ -122,6 +126,16 @@ public final class LiteLoader implements FilenameFilter
122 126 private LinkedList<LoginListener> loginListeners = new LinkedList<LoginListener>();
123 127  
124 128 /**
  129 + * List of mods which implement PluginChannelListener interface
  130 + */
  131 + private LinkedList<PluginChannelListener> pluginChannelListeners = new LinkedList<PluginChannelListener>();
  132 +
  133 + /**
  134 + * Mapping of plugin channel names to listeners
  135 + */
  136 + private HashMap<String,LinkedList<PluginChannelListener>> pluginChannels = new HashMap<String, LinkedList<PluginChannelListener>>();
  137 +
  138 + /**
125 139 * Reference to the addUrl method on URLClassLoader
126 140 */
127 141 private Method mAddUrl;
... ... @@ -171,6 +185,7 @@ public final class LiteLoader implements FilenameFilter
171 185 /**
172 186 * Set up reflection methods required by the loader
173 187 */
  188 + @SuppressWarnings("unchecked")
174 189 private void prepareLoader()
175 190 {
176 191 try
... ... @@ -183,10 +198,10 @@ public final class LiteLoader implements FilenameFilter
183 198  
184 199 try
185 200 {
186   - Class formatterClass = Minecraft.class.getClassLoader().loadClass(ModUtilities.getObfuscatedFieldName("net.minecraft.src.ConsoleLogFormatter", "em"));
187   - Constructor defaultConstructor = formatterClass.getDeclaredConstructor();
  201 + Class<? extends Formatter> formatterClass = (Class<? extends Formatter>)Minecraft.class.getClassLoader().loadClass(ModUtilities.getObfuscatedFieldName("net.minecraft.src.ConsoleLogFormatter", "em"));
  202 + Constructor<? extends Formatter> defaultConstructor = formatterClass.getDeclaredConstructor();
188 203 defaultConstructor.setAccessible(true);
189   - minecraftLogFormatter = (Formatter)defaultConstructor.newInstance();
  204 + minecraftLogFormatter = defaultConstructor.newInstance();
190 205 }
191 206 catch (Exception ex)
192 207 {
... ... @@ -207,10 +222,8 @@ public final class LiteLoader implements FilenameFilter
207 222 }
208 223 catch (Exception ex)
209 224 {
210   - logger.severe(ex.toString());
211   - logger.severe(ex.getStackTrace().toString());
  225 + logger.log(Level.SEVERE, "Error initialising LiteLoader", ex);
212 226 }
213   -
214 227 }
215 228  
216 229 /**
... ... @@ -446,11 +459,15 @@ public final class LiteLoader implements FilenameFilter
446 459 {
447 460 loginListeners.add((LoginListener)mod);
448 461 }
  462 +
  463 + if (mod instanceof PluginChannelListener)
  464 + {
  465 + pluginChannelListeners.add((PluginChannelListener)mod);
  466 + }
449 467 }
450 468 catch (Throwable th)
451 469 {
452   - logger.warning("Error initialising mod '" + mod.getName() + "': " + th.toString());
453   - th.printStackTrace();
  470 + logger.log(Level.WARNING, "Error initialising mod '" + mod.getName(), th);
454 471 iter.remove();
455 472 }
456 473 }
... ... @@ -477,12 +494,19 @@ public final class LiteLoader implements FilenameFilter
477 494 HookLogin.loader = this;
478 495 }
479 496  
  497 + // Plugin channels hook
  498 + if (pluginChannelListeners.size() > 0)
  499 + {
  500 + HookPluginChannels.Register();
  501 + HookPluginChannels.RegisterPacketHandler(this);
  502 + }
  503 +
480 504 // Tick hook
481 505 PrivateFields.minecraftProfiler.SetFinal(minecraft, new LiteLoaderHook(this, logger));
482 506 }
483 507 catch (Exception ex)
484 508 {
485   - logger.warning("Error creating hooks: " + ex.toString());
  509 + logger.log(Level.WARNING, "Error creating hooks", ex);
486 510 ex.printStackTrace();
487 511 }
488 512 }
... ... @@ -511,8 +535,7 @@ public final class LiteLoader implements FilenameFilter
511 535 }
512 536 catch (Throwable th)
513 537 {
514   - logger.warning(th.toString());
515   - th.printStackTrace();
  538 + logger.log(Level.WARNING, "Enumeration error", th);
516 539 }
517 540  
518 541 return classes;
... ... @@ -626,8 +649,7 @@ public final class LiteLoader implements FilenameFilter
626 649 }
627 650 catch (Throwable th)
628 651 {
629   - logger.warning(th.toString());
630   - th.printStackTrace();
  652 + logger.log(Level.WARNING, "checkAndAddClass error", th);
631 653 }
632 654 }
633 655  
... ... @@ -649,8 +671,7 @@ public final class LiteLoader implements FilenameFilter
649 671 }
650 672 catch (Throwable th)
651 673 {
652   - logger.warning("Error adding class path entry: " + th.toString());
653   - th.printStackTrace();
  674 + logger.log(Level.WARNING, "Error adding class path entry", th);
654 675 }
655 676  
656 677 return false;
... ... @@ -674,7 +695,7 @@ public final class LiteLoader implements FilenameFilter
674 695 }
675 696 catch (Throwable th)
676 697 {
677   - logger.warning("Error initialising mod " + initMod.getName() + ": " + th.getClass().getSimpleName() + " - " + th.getMessage());
  698 + logger.log(Level.WARNING, "Error initialising mod " + initMod.getName(), th);
678 699 }
679 700 }
680 701 }
... ... @@ -741,5 +762,103 @@ public final class LiteLoader implements FilenameFilter
741 762 {
742 763 for (LoginListener loginListener : loginListeners)
743 764 loginListener.onLogin(netHandler, loginPacket);
  765 +
  766 + setupPluginChannels();
  767 + }
  768 +
  769 + /**
  770 + * Callback for the plugin channel hook
  771 + *
  772 + * @param hookPluginChannels
  773 + */
  774 + public void onPluginChannelMessage(HookPluginChannels hookPluginChannels)
  775 + {
  776 + if (hookPluginChannels != null && hookPluginChannels.channel != null && pluginChannels.containsKey(hookPluginChannels.channel))
  777 + {
  778 + for (PluginChannelListener pluginChannelListener : pluginChannels.get(hookPluginChannels.channel))
  779 + {
  780 + try
  781 + {
  782 + pluginChannelListener.onCustomPayload(hookPluginChannels.channel, hookPluginChannels.length, hookPluginChannels.data);
  783 + }
  784 + catch (Exception ex) {}
  785 + }
  786 + }
  787 + }
  788 +
  789 + /**
  790 + * Delegate to ModUtilities.sendPluginChannelMessage
  791 + *
  792 + * @param channel Channel to send data to
  793 + * @param data Data to send
  794 + */
  795 + public void sendPluginChannelMessage(String channel, byte[] data)
  796 + {
  797 + ModUtilities.sendPluginChannelMessage(channel, data);
  798 + }
  799 +
  800 + /**
  801 + * Query loaded mods for registered channels
  802 + */
  803 + protected void setupPluginChannels()
  804 + {
  805 + // Clear any channels from before
  806 + pluginChannels.clear();
  807 +
  808 + // Enumerate mods for plugin channels
  809 + for (PluginChannelListener pluginChannelListener : pluginChannelListeners)
  810 + {
  811 + List<String> channels = pluginChannelListener.getChannels();
  812 +
  813 + if (channels != null)
  814 + {
  815 + for (String channel : channels)
  816 + {
  817 + if (channel.length() > 16 || channel.toUpperCase().equals("REGISTER") || channel.toUpperCase().equals("UNREGISTER"))
  818 + continue;
  819 +
  820 + if (!pluginChannels.containsKey(channel))
  821 + {
  822 + pluginChannels.put(channel, new LinkedList<PluginChannelListener>());
  823 + }
  824 +
  825 + pluginChannels.get(channel).add(pluginChannelListener);
  826 + }
  827 + }
  828 + }
  829 +
  830 + // If any mods have registered channels, send the REGISTER packet
  831 + if (pluginChannels.keySet().size() > 0)
  832 + {
  833 + StringBuilder channelList = new StringBuilder();
  834 + boolean separator = false;
  835 +
  836 + for (String channel : pluginChannels.keySet())
  837 + {
  838 + if (separator) channelList.append("\u0000");
  839 + channelList.append(channel);
  840 + separator = true;
  841 + }
  842 +
  843 + byte[] registrationData = channelList.toString().getBytes(Charset.forName("UTF8"));
  844 +
  845 + sendPluginChannelMessage("REGISTER", registrationData);
  846 + }
744 847 }
745 848 }
  849 +
  850 +
  851 +
  852 +
  853 +
  854 +
  855 +
  856 +
  857 +
  858 +
  859 +
  860 +
  861 +
  862 +
  863 +
  864 +
... ...
java/com/mumfrey/liteloader/util/ModUtilities.java
... ... @@ -9,6 +9,7 @@ import net.minecraft.client.Minecraft;
9 9 import net.minecraft.src.IntHashMap;
10 10 import net.minecraft.src.KeyBinding;
11 11 import net.minecraft.src.Packet;
  12 +import net.minecraft.src.Packet250CustomPayload;
12 13 import net.minecraft.src.Render;
13 14 import net.minecraft.src.RenderManager;
14 15 import net.minecraft.src.Tessellator;
... ... @@ -56,6 +57,30 @@ public abstract class ModUtilities
56 57 return false;
57 58 }
58 59 }
  60 +
  61 + /**
  62 + * Send a plugin channel (custom payload) packet to the server
  63 + *
  64 + * @param channel Channel to send the data
  65 + * @param data
  66 + */
  67 + public static void sendPluginChannelMessage(String channel, byte[] data)
  68 + {
  69 + if (channel == null || channel.length() > 16)
  70 + throw new RuntimeException("Invalid channel name specified");
  71 +
  72 + try
  73 + {
  74 + Minecraft minecraft = Minecraft.getMinecraft();
  75 +
  76 + if (minecraft.thePlayer != null)
  77 + {
  78 + Packet250CustomPayload payload = new Packet250CustomPayload(channel, data);
  79 + minecraft.thePlayer.sendQueue.addToSendQueue(payload);
  80 + }
  81 + }
  82 + catch (Exception ex) {}
  83 + }
59 84  
60 85 /**
61 86 * Abstraction helper function
... ...
java/com/mumfrey/liteloader/util/PrivateFields.java
... ... @@ -84,6 +84,7 @@ public class PrivateFields&lt;P, T&gt;
84 84 * @param instance Class to get the value of
85 85 * @return field value or null if errors occur
86 86 */
  87 + @SuppressWarnings("unchecked")
87 88 public T Get(P instance)
88 89 {
89 90 try
... ...
java/net/minecraft/src/RenderLightningBolt.java
... ... @@ -140,7 +140,8 @@ public class RenderLightningBolt extends Render
140 140 * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
141 141 * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
142 142 */
143   - public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
  143 + @Override
  144 + public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
144 145 {
145 146 this.doRenderLightningBolt((EntityLightningBolt)par1Entity, par2, par4, par6, par8, par9);
146 147 }
... ...