001 package cpw.mods.fml.common.network; 002 003 import java.lang.reflect.Method; 004 import java.util.Set; 005 import java.util.logging.Level; 006 007 import com.google.common.base.Strings; 008 009 import cpw.mods.fml.common.FMLCommonHandler; 010 import cpw.mods.fml.common.FMLLog; 011 import cpw.mods.fml.common.ModContainer; 012 import cpw.mods.fml.common.Side; 013 import cpw.mods.fml.common.discovery.ASMDataTable; 014 import cpw.mods.fml.common.discovery.ASMDataTable.ASMData; 015 import cpw.mods.fml.common.versioning.DefaultArtifactVersion; 016 import cpw.mods.fml.common.versioning.InvalidVersionSpecificationException; 017 import cpw.mods.fml.common.versioning.VersionRange; 018 019 public class NetworkModHandler 020 { 021 private static Object connectionHandlerDefaultValue; 022 private static Object packetHandlerDefaultValue; 023 private static Object clientHandlerDefaultValue; 024 private static Object serverHandlerDefaultValue; 025 026 private static int assignedIds = 1; 027 028 private int localId; 029 private int networkId; 030 031 private ModContainer container; 032 private NetworkMod mod; 033 private Method checkHandler; 034 035 private VersionRange acceptableRange; 036 037 public NetworkModHandler(ModContainer container, NetworkMod modAnnotation) 038 { 039 this.container = container; 040 this.mod = modAnnotation; 041 this.localId = assignedIds++; 042 this.networkId = this.localId; 043 } 044 public NetworkModHandler(ModContainer container, Class<?> networkModClass, ASMDataTable table) 045 { 046 this(container, networkModClass.getAnnotation(NetworkMod.class)); 047 if (this.mod == null) 048 { 049 return; 050 } 051 052 Set<ASMData> versionCheckHandlers = table.getAnnotationsFor(container).get(NetworkMod.VersionCheckHandler.class.getName()); 053 String versionCheckHandlerMethod = null; 054 for (ASMData vch : versionCheckHandlers) 055 { 056 if (vch.getClassName().equals(networkModClass.getName())) 057 { 058 versionCheckHandlerMethod = vch.getObjectName(); 059 break; 060 } 061 } 062 if (versionCheckHandlerMethod != null) 063 { 064 try 065 { 066 Method checkHandlerMethod = networkModClass.getDeclaredMethod(versionCheckHandlerMethod, String.class); 067 if (checkHandlerMethod.isAnnotationPresent(NetworkMod.VersionCheckHandler.class)) 068 { 069 this.checkHandler = checkHandlerMethod; 070 } 071 } 072 catch (Exception e) 073 { 074 FMLLog.log(Level.WARNING, e, "The declared version check handler method %s on network mod id %s is not accessible", versionCheckHandlerMethod, container.getModId()); 075 } 076 } 077 078 if (this.checkHandler == null) 079 { 080 String versionBounds = mod.versionBounds(); 081 if (!Strings.isNullOrEmpty(versionBounds)) 082 { 083 try 084 { 085 this.acceptableRange = VersionRange.createFromVersionSpec(versionBounds); 086 } 087 catch (InvalidVersionSpecificationException e) 088 { 089 FMLLog.log(Level.WARNING, e, "Invalid bounded range %s specified for network mod id %s", versionBounds, container.getModId()); 090 } 091 } 092 } 093 094 tryCreatingPacketHandler(container, mod.packetHandler(), mod.channels(), null); 095 if (FMLCommonHandler.instance().getSide().isClient()) 096 { 097 if (mod.clientPacketHandlerSpec() != getClientHandlerSpecDefaultValue()) 098 { 099 tryCreatingPacketHandler(container, mod.clientPacketHandlerSpec().packetHandler(), mod.clientPacketHandlerSpec().channels(), Side.CLIENT); 100 } 101 } 102 if (mod.serverPacketHandlerSpec() != getServerHandlerSpecDefaultValue()) 103 { 104 tryCreatingPacketHandler(container, mod.serverPacketHandlerSpec().packetHandler(), mod.serverPacketHandlerSpec().channels(), Side.SERVER); 105 } 106 107 if (mod.connectionHandler() != getConnectionHandlerDefaultValue()) 108 { 109 IConnectionHandler instance; 110 try 111 { 112 instance = mod.connectionHandler().newInstance(); 113 } 114 catch (Exception e) 115 { 116 FMLLog.log(Level.SEVERE, e, "Unable to create connection handler instance %s", mod.connectionHandler().getName()); 117 throw new FMLNetworkException(e); 118 } 119 120 NetworkRegistry.instance().registerConnectionHandler(instance); 121 } 122 } 123 /** 124 * @param container 125 */ 126 private void tryCreatingPacketHandler(ModContainer container, Class<? extends IPacketHandler> clazz, String[] channels, Side side) 127 { 128 if (side!=null && side.isClient() && ! FMLCommonHandler.instance().getSide().isClient()) 129 { 130 return; 131 } 132 if (clazz!=getPacketHandlerDefaultValue()) 133 { 134 if (channels.length==0) 135 { 136 FMLLog.log(Level.WARNING, "The mod id %s attempted to register a packet handler without specifying channels for it", container.getModId()); 137 } 138 else 139 { 140 IPacketHandler instance; 141 try 142 { 143 instance = clazz.newInstance(); 144 } 145 catch (Exception e) 146 { 147 FMLLog.log(Level.SEVERE, e, "Unable to create a packet handler instance %s for mod %s", clazz.getName(), container.getModId()); 148 throw new FMLNetworkException(e); 149 } 150 151 for (String channel : channels) 152 { 153 NetworkRegistry.instance().registerChannel(instance, channel, side); 154 } 155 } 156 } 157 else if (channels.length > 0) 158 { 159 FMLLog.warning("The mod id %s attempted to register channels without specifying a packet handler", container.getModId()); 160 } 161 } 162 /** 163 * @return 164 */ 165 private Object getConnectionHandlerDefaultValue() 166 { 167 try { 168 if (connectionHandlerDefaultValue == null) 169 { 170 connectionHandlerDefaultValue = NetworkMod.class.getMethod("connectionHandler").getDefaultValue(); 171 } 172 return connectionHandlerDefaultValue; 173 } 174 catch (NoSuchMethodException e) 175 { 176 throw new RuntimeException("Derp?", e); 177 } 178 } 179 180 /** 181 * @return 182 */ 183 private Object getPacketHandlerDefaultValue() 184 { 185 try { 186 if (packetHandlerDefaultValue == null) 187 { 188 packetHandlerDefaultValue = NetworkMod.class.getMethod("packetHandler").getDefaultValue(); 189 } 190 return packetHandlerDefaultValue; 191 } 192 catch (NoSuchMethodException e) 193 { 194 throw new RuntimeException("Derp?", e); 195 } 196 } 197 198 /** 199 * @return 200 */ 201 private Object getClientHandlerSpecDefaultValue() 202 { 203 try { 204 if (clientHandlerDefaultValue == null) 205 { 206 clientHandlerDefaultValue = NetworkMod.class.getMethod("clientPacketHandlerSpec").getDefaultValue(); 207 } 208 return clientHandlerDefaultValue; 209 } 210 catch (NoSuchMethodException e) 211 { 212 throw new RuntimeException("Derp?", e); 213 } 214 } 215 /** 216 * @return 217 */ 218 private Object getServerHandlerSpecDefaultValue() 219 { 220 try { 221 if (serverHandlerDefaultValue == null) 222 { 223 serverHandlerDefaultValue = NetworkMod.class.getMethod("serverPacketHandlerSpec").getDefaultValue(); 224 } 225 return serverHandlerDefaultValue; 226 } 227 catch (NoSuchMethodException e) 228 { 229 throw new RuntimeException("Derp?", e); 230 } 231 } 232 public boolean requiresClientSide() 233 { 234 return mod.clientSideRequired(); 235 } 236 237 public boolean requiresServerSide() 238 { 239 return mod.serverSideRequired(); 240 } 241 242 public boolean acceptVersion(String version) 243 { 244 if (checkHandler != null) 245 { 246 try 247 { 248 return (Boolean)checkHandler.invoke(container.getMod(), version); 249 } 250 catch (Exception e) 251 { 252 FMLLog.log(Level.WARNING, e, "There was a problem invoking the checkhandler method %s for network mod id %s", checkHandler.getName(), container.getModId()); 253 return false; 254 } 255 } 256 257 if (acceptableRange!=null) 258 { 259 return acceptableRange.containsVersion(new DefaultArtifactVersion(version)); 260 } 261 262 return container.getVersion().equals(version); 263 } 264 265 public int getLocalId() 266 { 267 return localId; 268 } 269 270 public int getNetworkId() 271 { 272 return networkId; 273 } 274 275 public ModContainer getContainer() 276 { 277 return container; 278 } 279 280 public NetworkMod getMod() 281 { 282 return mod; 283 } 284 285 public boolean isNetworkMod() 286 { 287 return mod != null; 288 } 289 290 public void setNetworkId(int value) 291 { 292 this.networkId = value; 293 } 294 }