From 3ac0d4a895fa3d12ecd69ae1e4e2ba21d07c88d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 29 Nov 2013 14:16:58 +0100 Subject: [PATCH] sending updates from server to client only when the client is nearby (i.e. we can assume the chunks are loaded on the client). this is somewhat experimental, since we cannot say with 100% certainty that the chunk isn't loaded on the client. will probably send "important" packets to all clients all the time (e.g. robot move) in the long run, but for now let's see how it turns out. --- li/cil/oc/common/PacketBuilder.scala | 42 +++++++++++++++++++++++++++- li/cil/oc/server/PacketSender.scala | 34 +++++++++++----------- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/li/cil/oc/common/PacketBuilder.scala b/li/cil/oc/common/PacketBuilder.scala index cc1b9054c..243147f5c 100644 --- a/li/cil/oc/common/PacketBuilder.scala +++ b/li/cil/oc/common/PacketBuilder.scala @@ -1,14 +1,18 @@ package li.cil.oc.common +import cpw.mods.fml.common.FMLCommonHandler import cpw.mods.fml.common.network.PacketDispatcher import cpw.mods.fml.common.network.Player import java.io.ByteArrayOutputStream import java.io.DataOutputStream import li.cil.oc.common.tileentity.TileEntity +import net.minecraft.entity.player.EntityPlayerMP import net.minecraft.item.ItemStack import net.minecraft.nbt.{NBTTagCompound, NBTBase} import net.minecraft.network.packet.Packet250CustomPayload +import net.minecraft.world.World import net.minecraftforge.common.ForgeDirection +import scala.collection.convert.WrapAsScala._ /** Utility class for packet creation. */ class PacketBuilder(packetType: PacketType.Value, private val stream: ByteArrayOutputStream = new ByteArrayOutputStream) extends DataOutputStream(stream) { @@ -35,7 +39,19 @@ class PacketBuilder(packetType: PacketType.Value, private val stream: ByteArrayO def sendToAllPlayers() = PacketDispatcher.sendPacketToAllPlayers(packet) - def sendToNearbyPlayers(t: TileEntity, range: Double = 64) = PacketDispatcher.sendPacketToAllAround(t.x, t.y, t.z, range, t.world.provider.dimensionId, packet) + def sendToNearbyPlayers(t: TileEntity, range: Double = 64): Unit = sendToNearbyPlayers(t.world, t.x + 0.5, t.y + 0.5, t.z + 0.5, range) + + def sendToNearbyPlayers(world: World, x: Double, y: Double, z: Double, range: Double) { + val dimension = world.provider.dimensionId + val server = FMLCommonHandler.instance.getMinecraftServerInstance + val manager = server.getConfigurationManager + for (player <- manager.playerEntityList.map(_.asInstanceOf[EntityPlayerMP]) if player.dimension == dimension) { + val playerSpecificRange = range min ((manager.getViewDistance min PacketBuilder.tryGetPlayerRenderDistance(player)) * 16) + if (player.getDistanceSq(x, y, z) < playerSpecificRange * playerSpecificRange) { + player.playerNetServerHandler.sendPacketToPlayer(packet) + } + } + } def sendToPlayer(player: Player) = PacketDispatcher.sendPacketToPlayer(packet, player) @@ -48,4 +64,28 @@ class PacketBuilder(packetType: PacketType.Value, private val stream: ByteArrayO p.length = stream.size p } +} + +object PacketBuilder { + private val renderDistanceField = try { + val field = classOf[EntityPlayerMP].getDeclaredField("renderDistance") + field.setAccessible(true) + Some(field) + } + catch { + case _: Throwable => None + } + + private def tryGetPlayerRenderDistance(player: EntityPlayerMP): Int = { + try { + renderDistanceField match { + case Some(field) => return field.get(player).asInstanceOf[Integer] + case _ => + } + } + catch { + case _: Throwable => + } + Int.MaxValue + } } \ No newline at end of file diff --git a/li/cil/oc/server/PacketSender.scala b/li/cil/oc/server/PacketSender.scala index ebf8d6e2c..2624dbf11 100644 --- a/li/cil/oc/server/PacketSender.scala +++ b/li/cil/oc/server/PacketSender.scala @@ -30,7 +30,7 @@ object PacketSender { player match { case Some(p) => pb.sendToPlayer(p) - case _ => pb.sendToAllPlayers() + case _ => pb.sendToNearbyPlayers(t) } } @@ -42,7 +42,7 @@ object PacketSender { player match { case Some(p) => pb.sendToPlayer(p) - case _ => pb.sendToAllPlayers() + case _ => pb.sendToNearbyPlayers(t) } } @@ -67,7 +67,7 @@ object PacketSender { player match { case Some(p) => pb.sendToPlayer(p) - case _ => pb.sendToAllPlayers() + case _ => pb.sendToNearbyPlayers(t) } } @@ -82,7 +82,7 @@ object PacketSender { player match { case Some(p) => pb.sendToPlayer(p) - case _ => pb.sendToAllPlayers() + case _ => pb.sendToNearbyPlayers(t) } } @@ -96,7 +96,7 @@ object PacketSender { pb.writeInt(oz) pb.writeDirection(direction) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendRobotAnimateSwing(t: Robot) { @@ -105,7 +105,7 @@ object PacketSender { pb.writeTileEntity(t.proxy) pb.writeInt(t.animationTicksTotal) - pb.sendToNearbyPlayers(t.proxy) + pb.sendToNearbyPlayers(t) } def sendRobotAnimateTurn(t: Robot) { @@ -115,7 +115,7 @@ object PacketSender { pb.writeByte(t.turnAxis) pb.writeInt(t.animationTicksTotal) - pb.sendToNearbyPlayers(t.proxy) + pb.sendToNearbyPlayers(t) } def sendRobotEquippedItemChange(t: Robot, stack: ItemStack) { @@ -124,7 +124,7 @@ object PacketSender { pb.writeTileEntity(t.proxy) pb.writeItemStack(stack) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendRobotSelectedSlotChange(t: Robot) { @@ -133,7 +133,7 @@ object PacketSender { pb.writeTileEntity(t.proxy) pb.writeInt(t.selectedSlot) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendRotatableState(t: Rotatable, player: Option[Player] = None) { @@ -145,7 +145,7 @@ object PacketSender { player match { case Some(p) => pb.sendToPlayer(p) - case _ => pb.sendToAllPlayers() + case _ => pb.sendToNearbyPlayers(t) } } @@ -156,7 +156,7 @@ object PacketSender { pb.writeInt(foreground) pb.writeInt(background) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendScreenCopy(t: Buffer, col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) { @@ -170,7 +170,7 @@ object PacketSender { pb.writeInt(tx) pb.writeInt(ty) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendScreenDepthChange(t: Buffer, value: PackedColor.Depth.Value) { @@ -179,7 +179,7 @@ object PacketSender { pb.writeTileEntity(t) pb.writeInt(value.id) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendScreenFill(t: Buffer, col: Int, row: Int, w: Int, h: Int, c: Char) { @@ -192,7 +192,7 @@ object PacketSender { pb.writeInt(h) pb.writeChar(c) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendScreenPowerChange(t: Buffer, hasPower: Boolean) { @@ -201,7 +201,7 @@ object PacketSender { pb.writeTileEntity(t) pb.writeBoolean(hasPower) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendScreenResolutionChange(t: Buffer, w: Int, h: Int) { @@ -211,7 +211,7 @@ object PacketSender { pb.writeInt(w) pb.writeInt(h) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } def sendScreenSet(t: Buffer, col: Int, row: Int, s: String) { @@ -222,6 +222,6 @@ object PacketSender { pb.writeInt(row) pb.writeUTF(s) - pb.sendToAllPlayers() + pb.sendToNearbyPlayers(t) } } \ No newline at end of file