diff --git a/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java b/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java index d63ef19d50..3131c91ce5 100644 --- a/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java +++ b/src/main/java/cpw/mods/fml/common/launcher/FMLTweaker.java @@ -21,9 +21,6 @@ import com.google.common.collect.Maps; import cpw.mods.fml.relauncher.FMLLaunchHandler; public class FMLTweaker implements ITweaker { - private List args; - private File assetsDir; - private String profile; private File gameDir; private Map launchArgs; private List standaloneArgs; @@ -34,9 +31,6 @@ public class FMLTweaker implements ITweaker { public void acceptOptions(List args, File gameDir, File assetsDir, String profile) { this.gameDir = (gameDir == null ? new File(".") : gameDir); - this.assetsDir = assetsDir; - this.profile = profile; - this.args = args; this.launchArgs = (Map)Launch.blackboard.get("launchArgs"); diff --git a/src/main/java/cpw/mods/fml/common/launcher/Yggdrasil.java b/src/main/java/cpw/mods/fml/common/launcher/Yggdrasil.java index 3e5e757604..a8975e36fc 100644 --- a/src/main/java/cpw/mods/fml/common/launcher/Yggdrasil.java +++ b/src/main/java/cpw/mods/fml/common/launcher/Yggdrasil.java @@ -20,6 +20,7 @@ import com.google.gson.GsonBuilder; * Basic implementation of Mojang's 'Yggdrasil' login system, purely intended as a dev time bare bones login. * Login errors are not handled. */ +@SuppressWarnings("unused") public class Yggdrasil { private static class Request { Agent agent = new Agent(); @@ -88,7 +89,7 @@ public class Yggdrasil { OutputStream out = null; InputStream in = null; - try + try { HttpURLConnection con = (HttpURLConnection)(new URL("https://authserver.mojang.com/authenticate")).openConnection(); con.setConnectTimeout(15000); diff --git a/src/main/java/cpw/mods/fml/common/network/simpleimpl/IMessage.java b/src/main/java/cpw/mods/fml/common/network/simpleimpl/IMessage.java new file mode 100644 index 0000000000..24ee2c3f92 --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/network/simpleimpl/IMessage.java @@ -0,0 +1,24 @@ +package cpw.mods.fml.common.network.simpleimpl; + +import io.netty.buffer.ByteBuf; + +/** + * Implement this interface for each message you wish to define. + * + * @author cpw + * + */ +public interface IMessage { + /** + * Convert from the supplied buffer into your specific message type + * + * @param buf + */ + public void fromBytes(ByteBuf buf); + + /** + * Deconstruct your message into the supplied byte buffer + * @param buf + */ + public void toBytes(ByteBuf buf); +} diff --git a/src/main/java/cpw/mods/fml/common/network/simpleimpl/IMessageHandler.java b/src/main/java/cpw/mods/fml/common/network/simpleimpl/IMessageHandler.java new file mode 100644 index 0000000000..11d9126417 --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/network/simpleimpl/IMessageHandler.java @@ -0,0 +1,24 @@ +package cpw.mods.fml.common.network.simpleimpl; + + +/** + * A message handler based on {@link IMessage}. Implement and override {@link #onMessage(IMessage)} to + * process your packet. Supply the class to {@link SimpleNetworkWrapper#registerMessage(Class, Class, byte, cpw.mods.fml.relauncher.Side)} + * to register both the message type and it's associated handler. + * + * @author cpw + * + * @param This is the request type - it is the message you expect to receive from remote. + * @param This is the reply type - it is the message you expect to send in reply. You can use IMessage as the type here + * if you don't anticipate sending a reply. + */ +public interface IMessageHandler { + /** + * Called when a message is received of the appropriate type. You can optionally return a reply message, or null if no reply + * is needed. + * + * @param message The message + * @return an optional return message + */ + public REPLY onMessage(REQ message, MessageContext ctx); +} diff --git a/src/main/java/cpw/mods/fml/common/network/simpleimpl/MessageContext.java b/src/main/java/cpw/mods/fml/common/network/simpleimpl/MessageContext.java new file mode 100644 index 0000000000..d9dd88302e --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/network/simpleimpl/MessageContext.java @@ -0,0 +1,43 @@ +package cpw.mods.fml.common.network.simpleimpl; + +import cpw.mods.fml.relauncher.Side; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.INetHandler; +import net.minecraft.network.NetHandlerPlayServer; + +/** + * Context for the {@link IMessageHandler} + * + * @author cpw + * + */ +public class MessageContext { + /** + * The {@link INetHandler} for this message. It could be a client or server handler, depending + * on the {@link #side} recieved. + */ + public final INetHandler netHandler; + + /** + * The Side this message has been received on + */ + public final Side side; + /** + * @param netHandler + */ + MessageContext(INetHandler netHandler, Side side) + { + this.netHandler = netHandler; + this.side = side; + } + + public NetHandlerPlayServer getServerHandler() + { + return (NetHandlerPlayServer) netHandler; + } + + public NetHandlerPlayClient getClientHandler() + { + return (NetHandlerPlayClient) netHandler; + } +} diff --git a/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleChannelHandlerWrapper.java b/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleChannelHandlerWrapper.java new file mode 100644 index 0000000000..593a4700b2 --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleChannelHandlerWrapper.java @@ -0,0 +1,36 @@ +package cpw.mods.fml.common.network.simpleimpl; + +import net.minecraft.network.INetHandler; +import com.google.common.base.Throwables; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.relauncher.Side; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +public class SimpleChannelHandlerWrapper extends SimpleChannelInboundHandler { + private IMessageHandler messageHandler; + private Side side; + public SimpleChannelHandlerWrapper(Class> handler, Side side) + { + try + { + messageHandler = handler.newInstance(); + } catch (Exception e) + { + Throwables.propagate(e); + } + this.side = side; + } + @Override + protected void channelRead0(ChannelHandlerContext ctx, REQ msg) throws Exception + { + INetHandler iNetHandler = ctx.attr(NetworkRegistry.NET_HANDLER).get(); + MessageContext context = new MessageContext(iNetHandler, side); + REPLY result = messageHandler.onMessage(msg, context); + if (result != null) + { + ctx.writeAndFlush(result); + } + } + +} diff --git a/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleIndexedCodec.java b/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleIndexedCodec.java new file mode 100644 index 0000000000..ce502a36ca --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleIndexedCodec.java @@ -0,0 +1,20 @@ +package cpw.mods.fml.common.network.simpleimpl; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec; + +public class SimpleIndexedCodec extends FMLIndexedMessageToMessageCodec { + @Override + public void encodeInto(ChannelHandlerContext ctx, IMessage msg, ByteBuf target) throws Exception + { + msg.toBytes(target); + } + + @Override + public void decodeInto(ChannelHandlerContext ctx, ByteBuf source, IMessage msg) + { + msg.fromBytes(source); + } + +} diff --git a/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleNetworkWrapper.java b/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleNetworkWrapper.java new file mode 100644 index 0000000000..d290e181f1 --- /dev/null +++ b/src/main/java/cpw/mods/fml/common/network/simpleimpl/SimpleNetworkWrapper.java @@ -0,0 +1,164 @@ +package cpw.mods.fml.common.network.simpleimpl; + +import java.util.EnumMap; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetHandler; +import net.minecraft.network.Packet; +import net.minecraft.tileentity.TileEntity; +import cpw.mods.fml.common.network.FMLEmbeddedChannel; +import cpw.mods.fml.common.network.FMLOutboundHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; +import cpw.mods.fml.relauncher.Side; + +/** + * This class is a simplified netty wrapper for those not wishing to deal with the full power of netty. + * It provides a simple message driven system, based on a discriminator byte over the custom packet channel. + * + * Usage is simple:
    + *
  • construct, and store, an instance of this class. It will automatically register and configure your underlying netty channel. + * + *
  • Then, call {@link #registerMessage(Class, Class, byte, Side)} for each message type you want to exchange + * providing an {@link IMessageHandler} implementation class as well as an {@link IMessage} implementation class. The side parameter + * to that method indicates which side (server or client) the message processing will occur on. The discriminator byte + * should be unique for this channelName - it is used to discriminate between different types of message that might + * occur on this channel (a simple form of message channel multiplexing, if you will). + *
  • To get a packet suitable for presenting to the rest of minecraft, you can call {@link #getPacketFrom(IMessage)}. The return result + * is suitable for returning from things like {@link TileEntity#func_145844_m()} for example. + *
  • Finally, use the sendXXX to send unsolicited messages to various classes of recipients. + *
+ * + * + * + * @author cpw + * + */ +public class SimpleNetworkWrapper { + private EnumMap channels; + private SimpleIndexedCodec packetCodec; + + public SimpleNetworkWrapper(String channelName) + { + packetCodec = new SimpleIndexedCodec(); + channels = NetworkRegistry.INSTANCE.newChannel(channelName, packetCodec); + } + + /** + * Register a message and it's associated handler. The message will have the supplied discriminator byte. The message handler will + * be registered on the supplied side (this is the side where you want the message to be processed and acted upon). + * + * @param messageHandler the message handler type + * @param message the message type + * @param discriminator a discriminator byte + * @param side the side for the handler + */ + public void registerMessage(Class> messageHandler, Class message, int discriminator, Side side) + { + packetCodec.addDiscriminator(discriminator, message); + FMLEmbeddedChannel channel = channels.get(side); + String type = channel.findChannelHandlerNameForType(SimpleIndexedCodec.class); + if (side == Side.SERVER) + { + addServerHandlerAfter(channel, type, messageHandler); + } + else + { + addClientHandlerAfter(channel, type, messageHandler); + } + } + + private void addServerHandlerAfter(FMLEmbeddedChannel channel, String type, Class> messageHandler) + { + SimpleChannelHandlerWrapper handler = getHandlerWrapper(messageHandler, Side.SERVER); + channel.pipeline().addAfter(type, messageHandler.getName(), handler); + } + + private void addClientHandlerAfter(FMLEmbeddedChannel channel, String type, Class> messageHandler) + { + SimpleChannelHandlerWrapper handler = getHandlerWrapper(messageHandler, Side.CLIENT); + channel.pipeline().addAfter(type, messageHandler.getName(), handler); + } + + private SimpleChannelHandlerWrapper getHandlerWrapper(Class> messageHandler, Side side) + { + return new SimpleChannelHandlerWrapper(messageHandler, side); + } + + /** + * Construct a minecraft packet from the supplied message. Can be used where minecraft packets are required, such as + * {@link TileEntity#func_145844_m()}. + * + * @param message The message to translate into packet form + * @return A minecraft {@link Packet} suitable for use in minecraft APIs + */ + public Packet getPacketFrom(IMessage message) + { + return channels.get(Side.SERVER).generatePacketFrom(message); + } + + /** + * Send this message to everyone. + * The {@link IMessageHandler} for this message type should be on the CLIENT side. + * + * @param message The message to send + */ + public void sendToAll(IMessage message) + { + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL); + channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to the specified player. + * The {@link IMessageHandler} for this message type should be on the CLIENT side. + * + * @param message The message to send + * @param player The player to send it to + */ + public void sendTo(IMessage message, EntityPlayerMP player) + { + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER); + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player); + channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to everyone within a certain range of a point. + * The {@link IMessageHandler} for this message type should be on the CLIENT side. + * + * @param message The message to send + * @param point The {@link TargetPoint} around which to send + */ + public void sendToAllAround(IMessage message, NetworkRegistry.TargetPoint point) + { + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT); + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point); + channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to everyone within the supplied dimension. + * The {@link IMessageHandler} for this message type should be on the CLIENT side. + * + * @param message The message to send + * @param dimensionId The dimension id to target + */ + public void sendToDimension(IMessage message, int dimensionId) + { + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION); + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId); + channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to the server. + * The {@link IMessageHandler} for this message type should be on the SERVER side. + * + * @param message The message to send + */ + public void sendToServer(IMessage message) + { + channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER); + channels.get(Side.CLIENT).writeAndFlush(message); + } +}