From 005c300d8f2b23062c13e2f43d80df3658b50fc2 Mon Sep 17 00:00:00 2001 From: bdew Date: Wed, 12 Feb 2014 17:03:34 +0200 Subject: [PATCH] Added experimental network stuff --- .../network/NBTMessageToMessageCodec.scala | 40 ++++++++++ src/net/bdew/lib/network/NetChannel.scala | 73 +++++++++++++++++++ .../lib/network/NetChannelClientHandler.scala | 24 ++++++ .../lib/network/NetChannelServerHandler.scala | 27 +++++++ src/net/bdew/lib/recipes/RecipeLoader.scala | 8 +- 5 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 src/net/bdew/lib/network/NBTMessageToMessageCodec.scala create mode 100644 src/net/bdew/lib/network/NetChannel.scala create mode 100644 src/net/bdew/lib/network/NetChannelClientHandler.scala create mode 100644 src/net/bdew/lib/network/NetChannelServerHandler.scala diff --git a/src/net/bdew/lib/network/NBTMessageToMessageCodec.scala b/src/net/bdew/lib/network/NBTMessageToMessageCodec.scala new file mode 100644 index 0000000..91a0174 --- /dev/null +++ b/src/net/bdew/lib/network/NBTMessageToMessageCodec.scala @@ -0,0 +1,40 @@ +/* + * Copyright (c) bdew, 2014 + * https://github.com/bdew/teleporter + * + * This mod is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * https://raw.github.com/bdew/teleporter/master/MMPL-1.0.txt + */ + +package net.bdew.lib.network + +import io.netty.handler.codec.MessageToMessageCodec +import cpw.mods.fml.common.network.internal.FMLProxyPacket +import net.minecraft.nbt.{CompressedStreamTools, NBTTagCompound} +import io.netty.channel.ChannelHandlerContext +import java.util +import java.io.{DataInputStream, DataOutputStream} +import io.netty.buffer.{ByteBufInputStream, ByteBufOutputStream, Unpooled} +import cpw.mods.fml.common.network.NetworkRegistry +import io.netty.channel.ChannelHandler.Sharable +import net.bdew.lib.BdLib + +@Sharable +class NBTMessageToMessageCodec extends MessageToMessageCodec[FMLProxyPacket, NBTTagCompound] { + def encode(ctx: ChannelHandlerContext, msg: NBTTagCompound, out: util.List[AnyRef]) { + val buff = Unpooled.buffer() + val writer = new DataOutputStream(new ByteBufOutputStream(buff)) + CompressedStreamTools.write(msg, writer) + val pkt = new FMLProxyPacket(buff, ctx.channel.attr(NetworkRegistry.FML_CHANNEL).get) + out.add(pkt) + } + def decode(ctx: ChannelHandlerContext, msg: FMLProxyPacket, out: util.List[AnyRef]) { + try { + val stream = new DataInputStream(new ByteBufInputStream(msg.payload())) + out.add(CompressedStreamTools.read(stream)) + } catch { + case e: Throwable => BdLib.log.error("Error decoding packet", e) + } + } +} diff --git a/src/net/bdew/lib/network/NetChannel.scala b/src/net/bdew/lib/network/NetChannel.scala new file mode 100644 index 0000000..60e47c6 --- /dev/null +++ b/src/net/bdew/lib/network/NetChannel.scala @@ -0,0 +1,73 @@ +/* + * Copyright (c) bdew, 2014 + * https://github.com/bdew/teleporter + * + * This mod is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * https://raw.github.com/bdew/teleporter/master/MMPL-1.0.txt + */ + +package net.bdew.lib.network + +import cpw.mods.fml.common.network.{FMLOutboundHandler, NetworkRegistry} +import cpw.mods.fml.relauncher.Side +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.entity.player.EntityPlayerMP +import io.netty.channel.{ChannelHandler, ChannelFutureListener} + +class NetChannel(val name: String) { + val channels = NetworkRegistry.INSTANCE.newChannel(name, new NBTMessageToMessageCodec) + + var serverHandlers = Map.empty[String, (NBTTagCompound, EntityPlayerMP) => Unit] + var clientHandlers = Map.empty[String, (NBTTagCompound) => Unit] + + def regServerHandler(id: String, callable: (NBTTagCompound, EntityPlayerMP) => Unit) = + if (serverHandlers.contains(id)) + sys.error("Command name already in use: %s".format(name)) + else + serverHandlers += (id -> callable) + + def regClientHandler(id: String, callable: (NBTTagCompound) => Unit) = + if (clientHandlers.contains(id)) + sys.error("Command name already in use: %s".format(name)) + else + clientHandlers += (id -> callable) + + addHandler(Side.SERVER, new NetChannelServerHandler(this)) + addHandler(Side.CLIENT, new NetChannelClientHandler(this)) + + def addHandler(side: Side, handler: ChannelHandler) { + val ch = channels.get(side) + val name = ch.findChannelHandlerNameForType(classOf[NBTMessageToMessageCodec]) + ch.pipeline().addAfter(name, side + "Handler", handler) + } + + def sendToAll(message: NBTTagCompound) { + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL) + channels.get(Side.SERVER).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE) + } + + def sendTo(message: NBTTagCompound, player: EntityPlayerMP) { + 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).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE) + } + + def sendToAllAround(message: NBTTagCompound, point: NetworkRegistry.TargetPoint) { + 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).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE) + } + + def sendToDimension(message: NBTTagCompound, dimensionId: Int) { + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION) + channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(new Integer(dimensionId)) + channels.get(Side.SERVER).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE) + } + + def sendToServer(message: NBTTagCompound) { + channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER) + channels.get(Side.CLIENT).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE) + } + +} diff --git a/src/net/bdew/lib/network/NetChannelClientHandler.scala b/src/net/bdew/lib/network/NetChannelClientHandler.scala new file mode 100644 index 0000000..da9bfb5 --- /dev/null +++ b/src/net/bdew/lib/network/NetChannelClientHandler.scala @@ -0,0 +1,24 @@ +/* + * Copyright (c) bdew, 2014 + * https://github.com/bdew/teleporter + * + * This mod is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * https://raw.github.com/bdew/teleporter/master/MMPL-1.0.txt + */ + +package net.bdew.lib.network + +import io.netty.channel.{ChannelHandlerContext, SimpleChannelInboundHandler} +import net.minecraft.nbt.NBTTagCompound +import net.bdew.lib.BdLib + +class NetChannelClientHandler(ch: NetChannel) extends SimpleChannelInboundHandler[NBTTagCompound] { + def channelRead0(ctx: ChannelHandlerContext, msg: NBTTagCompound) { + val cmd = msg.getString("_cmd") + ch.clientHandlers.getOrElse(cmd, { + BdLib.log.error("Unknown command: '%s' from server".format(cmd)) + return + })(msg) + } +} diff --git a/src/net/bdew/lib/network/NetChannelServerHandler.scala b/src/net/bdew/lib/network/NetChannelServerHandler.scala new file mode 100644 index 0000000..fa7d62a --- /dev/null +++ b/src/net/bdew/lib/network/NetChannelServerHandler.scala @@ -0,0 +1,27 @@ +/* + * Copyright (c) bdew, 2014 + * https://github.com/bdew/teleporter + * + * This mod is distributed under the terms of the Minecraft Mod Public + * License 1.0, or MMPL. Please check the contents of the license located in + * https://raw.github.com/bdew/teleporter/master/MMPL-1.0.txt + */ + +package net.bdew.lib.network + +import io.netty.channel.{ChannelHandlerContext, SimpleChannelInboundHandler} +import net.minecraft.nbt.NBTTagCompound +import cpw.mods.fml.common.network.NetworkRegistry +import net.minecraft.network.NetHandlerPlayServer +import net.bdew.lib.BdLib + +class NetChannelServerHandler(ch: NetChannel) extends SimpleChannelInboundHandler[NBTTagCompound] { + def channelRead0(ctx: ChannelHandlerContext, msg: NBTTagCompound) { + val cmd = msg.getString("_cmd") + val nh = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get.asInstanceOf[NetHandlerPlayServer].playerEntity + ch.serverHandlers.getOrElse(cmd, { + BdLib.log.error("Unknown command: '%s' from '%s'".format(cmd, nh.getCommandSenderName)) + return + })(msg, nh) + } +} diff --git a/src/net/bdew/lib/recipes/RecipeLoader.scala b/src/net/bdew/lib/recipes/RecipeLoader.scala index 5d484bc..3ef06b6 100644 --- a/src/net/bdew/lib/recipes/RecipeLoader.scala +++ b/src/net/bdew/lib/recipes/RecipeLoader.scala @@ -159,7 +159,7 @@ class RecipeLoader { case _ => Seq(getConcreteStack(s)) } - def notNull[T](v:T, err: => String) = if (v == null) error(err) else v + def notNull[T](v: T, err: => String) = if (v == null) error(err) else v /** * Returns an ItemStack that match a reference @@ -178,11 +178,11 @@ class RecipeLoader { return s case StackMacro(ch) => getConcreteStack(currCharMap(ch), cnt) case StackGeneric(mod, id) => - notNull(GameRegistry.findItemStack(mod, id, 1),"Stack not found %s:%s".format(mod, id)) + notNull(GameRegistry.findItemStack(mod, id, 1), "Stack not found %s:%s".format(mod, id)) case StackBlock(mod, id, meta) => - new ItemStack(notNull(GameRegistry.findBlock(mod, id),"Block not found %s:%s".format(mod, id)), 1, meta) + new ItemStack(notNull(GameRegistry.findBlock(mod, id), "Block not found %s:%s".format(mod, id)), 1, meta) case StackItem(mod, id, meta) => - new ItemStack(notNull(GameRegistry.findItem(mod, id),"Item not found %s:%s".format(mod, id)), 1, meta) + new ItemStack(notNull(GameRegistry.findItem(mod, id), "Item not found %s:%s".format(mod, id)), 1, meta) case StackReflect(cls, field, meta) => reflectStack(cls, field, meta, cnt) case StackGetter(cls, method, param, meta) => reflectStackGetter(cls, method, param, meta, cnt) }