public NetConnectionConfiguration(NetConnection forConnection)
		{
			if (forConnection == null)
				throw new ArgumentNullException("forConnection");

			m_forConnection = forConnection;
			forConnection.Configuration = this;

			ConnectionTimeOut = NetConnectionConfiguration.DefaultConnectionTimeOut;
			AveragePingSamples = 5;
			PingFrequency = NetConnectionConfiguration.DefaultPingFrequency;
            m_currentOptimization = NetOptimization.EmphasizeBandwidth;
			ThrottleBytesPerSecond = NetConnectionConfiguration.DefaultThrottleBytesPerSecond;

			// default lag/loss/dupe settings
			SimulateLagLoss = false;
			LossChance = 0.05f;
			LagDelayChance = 1.0f;
			LagDelayMinimum = 0.1f;
			LagDelayVariance = 0.05f;
			DuplicatedPacketChance = 0.01f;

			// reliability
			OptimizeSettings(m_currentOptimization, 0.1f, true); // assume 100ms roundtrip for starters
		}
Exemplo n.º 2
0
		public NetPing(NetConnection forConnection)
		{
			m_connection = forConnection;
			m_samples = new float[6];
			Initialize(20.0f); // 50 ms

			m_lastSentPing = NetTime.Now;
		}
Exemplo n.º 3
0
        public void AddPlayer(PlayerCarac carac, ActorRTInfo info, NetConnection co)
        {
            // Container creation
            Player player = new Player();
            player.Carac = carac;
            player.Info = info;

            if (co != null)
            {
                player.Connection = co;
                co.Tag = carac.ActorID;
            }

            player.score = new PlayerScore();

            // And finally add it to our list
            List.Add(player.Carac.ActorID, player);
        }
Exemplo n.º 4
0
        // Create a player from a partially constructed PlayerCarac and return its ID
        public int CreatePlayer(PlayerCarac carac, NetConnection co)
        {
            carac.AssignID();
            ActorRTInfo info = new ActorRTInfo();
            
            // Set Physical infos
            info.Health = carac.HealthCap = 100;
            info.Mana = carac.ManaCap = 100;
            info.Weapon = 1;

            // Set position info
            info.Position = 1.0f;
            info.Velocity = 0.0f;

            // And add the player
            AddPlayer(carac, info, co);

            return carac.ActorID;
        }
Exemplo n.º 5
0
		internal static int SendDisconnected(NetBase netBase, string reason, NetConnection connection)
		{
			NetMessage bye = new NetMessage(NetMessageType.Handshake, reason.Length + 3);
			bye.Write((byte)NetHandshakeType.Disconnected);
			bye.Write(reason);
			return netBase.SendSingleMessageAtOnce(bye, connection, connection.RemoteEndpoint);
		}
Exemplo n.º 6
0
		internal static int SendConnectResponse(NetBase netBase, NetConnection clientConnection, IPEndPoint remoteEndpoint)
		{
			double now = NetTime.Now;
			ushort nowEnc = NetTime.Encoded(now);
			NetMessage response = new NetMessage(NetMessageType.Handshake, 3);
			response.Write((byte)NetHandshakeType.ConnectResponse);
			response.Write(nowEnc);
			clientConnection.m_firstSentHandshake = now;
			clientConnection.m_lastSentHandshake = now;
			return netBase.SendSingleMessageAtOnce(response, clientConnection, remoteEndpoint);
		}
Exemplo n.º 7
0
 public static int GetPlayerID(NetConnection co)
 {
     return (int)co.Tag;
 }
Exemplo n.º 8
0
        private void SendGameState(NetConnection Conn)
        {
            GameState++;
            NetMessage msg = new NetMessage();
            string Message = "P" + Player.Location.X + "," + Player.Location.Y;
            Message = Message + "P";

            foreach (Zombie Zombie in Zombies)
            {
                Message = Message + "Z" + Zombie.Location.X + "," + Zombie.Location.Y;
            }
            Message = Message + "P";

            foreach (Bullet Bullet in Bullets)
            {
                Message = Message + "B" + Bullet.Location.X + "," + Bullet.Location.Y;
            }
            msg.Write(Message);

            //Sending the packet in Reliable is okay for this because its
            //one packet, When sending lots and lots of data you need to
            //set this to Unreliable. This will garentee it arrives but
            //not in a sepcific order.

            server.SendMessage(msg, Conn, NetChannel.Unreliable);
        }
Exemplo n.º 9
0
		internal void Encode(NetConnection connection, NetBuffer intoBuffer)
		{
			if (m_type == NetMessageType.None)
				m_type = NetMessageType.User;
			intoBuffer.Write((byte)m_type, 3);
			switch(m_type)
			{
				case NetMessageType.UserFragmented:
				case NetMessageType.User:
				case NetMessageType.Acknowledge:
				case NetMessageType.AcknowledgeBitField:
					intoBuffer.Write((byte)m_sequenceChannel, 5); // encode channel
					intoBuffer.Write(m_sequenceNumber, 12); // encode sequence number
					break;
			}

			int byteLen = (m_buffer == null ? 0 : m_buffer.LengthBytes);

			if (m_type == NetMessageType.UserFragmented || m_type == NetMessageType.User || m_type == NetMessageType.Discovery || m_type == NetMessageType.Handshake)
				intoBuffer.Write(byteLen, 12); // encode length

			// encode payload
			if (byteLen > 0)
				intoBuffer.Write(m_buffer.Data, 0, byteLen);

			return;
		}
Exemplo n.º 10
0
      protected void HdlMsgReBroadcast(BBMessage msg, NetConnection sender)
      {
         int id = PlayerList.GetPlayerID(sender);

         //if (msg.MsgType == BBMsgType.CHAT)
         //   Log.Info("Chat " + id + " : " + msg.Param1);

         // Set the id of the message sender
         msg.ActorInfo = new ActorRTInfo();
         msg.ActorInfo.Id = id;

         // And broadcast this message
         Server.Broadcast(msg.GetNetMessage(), NetChannel.ReliableUnordered);
      }
Exemplo n.º 11
0
      private void HdlMsgShoot(BBMessage msg, NetConnection sender)
      {
         int id = PlayerList.GetPlayerID(sender);

         if (msg.MsgType == BBMsgType.ACTOR_SHOOT)
         {
            Log.Info("Shoot from " + id + " to " + msg.Shoot.Cible_ID);
            ++PList.GetPlayer(id).score.Shots;
         }
         else if (msg.MsgType == BBMsgType.ACTOR_SHOOT_RESPONSE)
         {
            Log.Info("Shoot response from " + id + " - shooter: " + msg.Resp.SenderID + ". result : " + msg.Resp.ShootResponse.ToString());

            if (msg.Resp.ShootResponse == ShootResponseDesc.Response.AVOIDED || msg.Resp.ShootResponse == ShootResponseDesc.Response.COUNTERED)
            {
               ++PList.GetPlayer(id).score.Hit;
            }
            else if (msg.Resp.ShootResponse == ShootResponseDesc.Response.TAKEN)
            {
               ++PList.GetPlayer(id).score.Hit;
               ++PList.GetPlayer(id).score.Deaths;
               ++PList.GetPlayer(msg.Resp.SenderID).score.Kills;
            }
         }

         // Set the id of the message sender
         msg.ActorInfo = new ActorRTInfo();
         msg.ActorInfo.Id = id;

         // And broadcast this message
         Server.Broadcast(msg.GetNetMessage(), NetChannel.ReliableUnordered);
      }
Exemplo n.º 12
0
		/// <summary>
		/// Remove connection from Connections list(s)
		/// </summary>
		internal void RemoveConnection(NetConnection conn)
		{
			if (conn == null)
				return;

			Log.Debug("Removing connection " + conn);
			for(int i=0;i<Connections.Length;i++)
				if (Connections[i] == conn)
					Connections[i] = null;

			// also remove lookup entry
			int hash = conn.RemoteEndpoint.GetHashCode();
			if (m_connectionsLookUpTable.ContainsKey(hash))
				m_connectionsLookUpTable.Remove(hash);
		}
Exemplo n.º 13
0
		/// <summary>
		/// Broadcasts a message to all connections except specified; should NOT be used for
		/// messages which uses the string table read/write methods!
		/// </summary>
		public int Broadcast(NetMessage msg, NetChannel channel, NetConnection except)
		{
			int numSentTo = 0;
			bool originalSent = false;
			foreach (NetConnection conn in Connections)
			{
				if (conn == null || conn == except || (conn.Status != NetConnectionStatus.Connected && conn.Status != NetConnectionStatus.Reconnecting))
					continue;

				numSentTo++;

				if (!originalSent)
				{
					// send original
					conn.SendMessage(msg, channel);
					originalSent = true;
				}
				else
				{
					// send refcloned message
					NetMessage clone = NetMessage.CreateReferenceClone(msg);
					conn.SendMessage(clone, channel);
					numSentTo++;
				}
			}

			return numSentTo;
		}
Exemplo n.º 14
0
		/// <summary>
		/// Sends a message to a certain connection using the channel specified
		/// </summary>
		public bool SendMessage(NetMessage msg, NetConnection connection, NetChannel channel)
		{
			if (connection == null)
				throw new ArgumentNullException("connection");

			if (connection.Status == NetConnectionStatus.Disconnected)
			{
				Log.Warning("SendMessage failed - Connection is Disconnected!");
				return false;
			}

			connection.SendMessage(msg, channel);
			return true;
		}
Exemplo n.º 15
0
		internal NetConnection AddConnection(IPEndPoint remoteEndpoint, int remoteClockOffset)
		{
			// find empty slot
			for (int i = 0; i < Connections.Length; i++)
			{
				if (Connections[i] == null)
				{
					NetConnection conn = new NetConnection(this, remoteEndpoint);

					conn.RemoteClockOffset = remoteClockOffset;
					Log.Verbose("Initializing remote clock offset to " + remoteClockOffset + " ms");

					conn.m_firstSentHandshake = NetTime.Now;
					conn.m_lastSentHandshake = conn.m_firstSentHandshake;

					int hash = remoteEndpoint.GetHashCode();
					NetConnection existingConn;
					if (m_connectionsLookUpTable.TryGetValue(hash, out existingConn))
					{
						if (existingConn.Status != NetConnectionStatus.Disconnected)
							throw new NetException("Ack thphth; Connections lookup hash value taken!");

						// disconnected; just remove it
						RemoveConnection(existingConn);
					}

					Connections[i] = conn;

					m_connectionsLookUpTable[hash] = conn;

					conn.SetStatus(NetConnectionStatus.Connecting, "Connecting from " + remoteEndpoint);
					return conn;
				}
			}

			Log.Warning("Failed to add new connection!");
			return null;
		}
Exemplo n.º 16
0
 private NetPlayer GetPlayer(NetConnection nc)
 {
     for (int i = 0; i < m_players.Count; i++)
     {
         NetPlayer tmp = m_players[i];
         if (nc == tmp.PlayerConnection)
             return tmp;
     }
     return null;
 }
Exemplo n.º 17
0
        /// <summary>
        /// Sends the given message with the given UDP delivery type to the targetConnection
        /// </summary>
        /// <param name="message">The message to be send</param>
        /// <param name="deliveryType">The UDP delivery type</param>
        /// <param name="targetConnection">The target connection</param>
        public void SendMessage(SpiderMessage message, NetChannel deliveryType, NetConnection targetConnection)
        {
            NetMessage msg = new NetMessage();
            msg.Write(message.ToByteArray());

            spiderNet.SendMessage(msg, targetConnection, deliveryType);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Connects to a server
        /// </summary>
        public bool Connect(IPAddress address, int port, byte[] customData)
        {
            if (m_serverConnection != null && m_serverConnection.Status != NetConnectionStatus.Disconnected)
                m_serverConnection.Disconnect("Reconnecting");

            IPEndPoint remoteIP = new IPEndPoint(address, port);
            m_serverConnection = new NetConnection(this, remoteIP);

            string remoteHost = remoteIP.ToString();
            Log.Info("Connecting to " + remoteHost);

            m_serverConnection.m_firstSentHandshake = NetTime.Now;
            m_serverConnection.m_lastSentHandshake = m_serverConnection.m_firstSentHandshake;
            m_serverConnection.SetStatus(NetConnectionStatus.Connecting, "Connecting");

            // save custom data for repeat connect requests
            if (customData != null)
            {
                m_serverConnection.m_savedConnectCustomData = new byte[customData.Length];
                Array.Copy(customData, m_serverConnection.m_savedConnectCustomData, customData.Length);
            }

            int bytesSent = NetHandshake.SendConnect(this, remoteIP, customData);

            // account for connect packet
            m_serverConnection.Statistics.PacketsSent++;
            m_serverConnection.Statistics.MessagesSent++;
            m_serverConnection.Statistics.BytesSent += bytesSent;

            return true;
        }
Exemplo n.º 19
0
      public void HandleMessage(BBMessage msg, NetConnection sender)
      {
         switch (msg.MsgType)
         {
            case BBMsgType.ASK_LOGIN:
               HdlLogin(msg, sender);
               break;
            case BBMsgType.PRIVATE_MESSAGE:
            case BBMsgType.PRIVATE_CONVERSATION:
            case BBMsgType.JOIN_CONVERSATION:
            case BBMsgType.LEAVE_CONVERSATION:
            case BBMsgType.CHAT:
            case BBMsgType.VDM:
            case BBMsgType.PENDU:
            case BBMsgType.BASH:
            case BBMsgType.TYPING_MSG:
            case BBMsgType.KNOCK:
               HdlMsgReBroadcast(msg, sender);
               break;
            case BBMsgType.COFFEE:
               HdlMsgReBroadcast(msg, sender);
               break;
            case BBMsgType.EAT:
               HdlMsgReBroadcast(msg, sender);
               break;
            case BBMsgType.ACTOR_SHOOT:
               HdlMsgShoot(msg, sender);
               break;

            case BBMsgType.ACTOR_SHOOT_RESPONSE:
               HdlMsgShoot(msg, sender);
               break;

            default:
               Log.Warning("Received unknown message");
               break;
         }
      }
Exemplo n.º 20
0
        internal void NotifyStatusChange(NetConnection conn, NetConnectionStatus previousStatus, string reason)
        {
            if (StatusChanged != null)
            {
                NetStatusEventArgs e = new NetStatusEventArgs();
                e.PreviousStatus = previousStatus;
                e.Connection = conn;
                e.Reason = reason;

                StatusChanged(this, e);
            }
        }
Exemplo n.º 21
0
      protected void HdlLogin(BBMessage msg, NetConnection sender)
      {         
         // Test if login is possible
         if (PList.GetPlayer(msg.PlayerCarac.Nick, null) != null)
         {
            // No : player already exists   
            BBMessage msg_back = new BBMessage();
            msg_back.MsgNoLogin("Player \"" + msg.PlayerCarac.Nick + "\" already exists");
            Server.SendMessage(msg_back.GetNetMessage(), sender, NetChannel.ReliableUnordered);

            // And close the connection
            sender.Disconnect("Player \"" + msg.PlayerCarac.Nick + "\" already exists, Login refused");
         }
         else
         {
            if ((msg.Param1 == null) || (msg.Param1 != BBMessage.Version))
            {
               BBMessage msg_back1 = new BBMessage();
               string str = msg.Param1;
               if (str == null)
                  str = "No version";

               msg_back1.MsgNoLogin("Player \"" + msg.PlayerCarac.Nick + "\" , Login refused. Version Serveur = " + BBMessage.Version + " Version Client = " + str);
               Server.SendMessage(msg_back1.GetNetMessage(), sender, NetChannel.ReliableUnordered);

               //sender.Disconnect("Player \"" + msg.PlayerCarac.Nick + "\" , Login refused. Version Serveur = " + BBMessage.Version + " Version Client = " + msg.Param1.ToString());
            }
            else
            {
               // Yes : Add the player to the list and send OK
               // Now add the player to our list
               int id = PList.CreatePlayer(msg.PlayerCarac, sender);
               Log.Info("Player added : " + msg.PlayerCarac.Nick + ", " + id);

               // Send OK
               msg.MsgOkLogin(id);
               Server.SendMessage(msg.GetNetMessage(), sender, NetChannel.ReliableUnordered);

               // Send connection of other clients to our new client
               IDictionaryEnumerator en = PList.GetPlayerEnum();
               BBMessage msg_notice;
               while (en.MoveNext())
               {
                  if (((Player)en.Value).Carac.ActorID != id)
                  {
                     msg_notice = new BBMessage();
                     msg_notice.MsgAddPlayer((Player)en.Value, false);
                     Server.SendMessage(msg_notice.GetNetMessage(), sender, NetChannel.ReliableUnordered);
                  }

               }

               // Notify other clients
               BBMessage msg_back = new BBMessage();
               msg_back.MsgAddPlayer(PList.GetPlayer(id), true);
               BroadcastMsgExcept(msg_back.GetNetMessage(), NetChannel.ReliableUnordered, id);

               // Notify
               NotifyClientConnected(id);
            }
         }
      }
Exemplo n.º 22
0
 // unsequenced packets only, returns number of bytes sent
 internal int SendSingleMessageAtOnce(NetMessage msg, NetConnection connection, IPEndPoint endpoint)
 {
     m_sendBuffer.ResetWritePointer();
     msg.Encode(connection, m_sendBuffer);
     if (connection != null)
         return ExecuteSend(m_sendBuffer, connection, connection.RemoteEndpoint);
     else
         return ExecuteSend(m_sendBuffer, null, endpoint);
 }
Exemplo n.º 23
0
 internal void NotifyClientDisconnected(NetConnection co)
 {
    if (ClientDisconnected != null)
    {
       ClientDisconnected(this, new ClientConnectEventArgs(PList.GetPlayer(PlayerList.GetPlayerID(co)).Carac));
    }
 }
Exemplo n.º 24
0
		internal static void ReplyPong(NetMessage pingMessage, NetConnection connection)
		{
			byte nr = pingMessage.ReadByte(6);

			NetMessage pong = new NetMessage(NetMessageType.PingPong, 3);
			pong.Write(true); // means pong
			pong.Write(false); // means NOT optimize info
			pong.Write(nr, 6);
			pong.WriteSendStamp();
			connection.Parent.SendSingleMessageAtOnce(pong, connection, connection.RemoteEndpoint);
		}
Exemplo n.º 25
0
 public NetPlayer(NetConnection con, String name)
     : base(name)
 {
     m_connection = con;
 }
Exemplo n.º 26
0
        /// <summary>
        /// Creates a network message by decoding a NetMessage
        /// </summary>
        /// <param name="msg">The NetMessage to be decoded</param>
        public SpiderMessage(NetMessage msg)
        {
            //This is the exception we throw if something goes wrong
            Exception e = new Exception("Could not read message");

            byte[] contents = msg.ReadBytes(msg.Length);
            type = (SpiderMessageType)contents[0];
            int dataOffset = BitConverter.ToInt32(contents, 1);
            label = Encoding.UTF8.GetString(contents, 1 + sizeof(int), dataOffset - 1 - sizeof(int));

            senderIP = msg.Sender.RemoteEndpoint.Address;
            connection = msg.Sender;

            if (type == SpiderMessageType.Bytes) {
                data = new byte[contents.Length - dataOffset];
                for (int i = 0; i < contents.Length - dataOffset; i++) {
                    ((byte[])data)[i] = contents[i + dataOffset];
                }
            }
            else {
                String tempData = Encoding.UTF8.GetString(contents, dataOffset, contents.Length - dataOffset);
                switch (type) {
                    case SpiderMessageType.Double:
                        data = Convert.ToDouble(tempData);
                        break;
                    case SpiderMessageType.Int:
                        data = Convert.ToInt32(tempData);
                        break;
                    default:
                        data = tempData;
                        break;
                }
            }
        }
Exemplo n.º 27
0
        internal int ExecuteSend(NetBuffer buffer, NetConnection connection, IPEndPoint remoteEP)
        {
            if (buffer.LengthBytes < 0)
            {
                Log.Warning("ExecuteSend passed 0 bytes to send");
                return 0;
            }

            #if DEBUG
            if (connection != null)
            {
                if (connection.Configuration.SimulateLagLoss && m_lagLoss != null)
                    return m_lagLoss.ExecuteSend(this, buffer, connection, remoteEP);
            }
            #endif
            // encrypt
            if (connection != null && connection.m_encryption.SymmetricEncryptionKeyBytes != null)
            {
                // Log.Debug("SEND: Encrypting packet using key: " + Convert.ToBase64String(connection.SymmetricEncryptionKey));
                connection.m_encryption.EncryptSymmetric(buffer);
            }

            try
            {
                int bytesSent = m_socket.SendTo(buffer.Data, 0, buffer.LengthBytes, SocketFlags.None, remoteEP);

                Debug.Assert(bytesSent == buffer.LengthBytes, "Ouch, sent partial UDP message?!");

                //Log.Verbose(string.Format(CultureInfo.InvariantCulture, "Sent {0} bytes to {1}", bytesSent, remoteEP));
                return bytesSent;
            }
            catch (SocketException sex)
            {
                if (sex.SocketErrorCode == SocketError.WouldBlock)
                {
                    // send buffer overflow?
            #if DEBUG
                    Log.Error("SocketException.WouldBlock thrown during sending; send buffer overflow? Increase buffer using NetAppConfiguration.SendBufferSize");
                    throw new NetException("SocketException.WouldBlock thrown during sending; send buffer overflow? Increase buffer using NetAppConfiguration.SendBufferSize", sex);
            #else
                    // let reliability handle it, but log warning
                    Log.Warning("Network send buffer overflow");
            #endif
                }

                if (sex.SocketErrorCode == SocketError.ConnectionReset ||
                    sex.SocketErrorCode == SocketError.ConnectionRefused ||
                    sex.SocketErrorCode == SocketError.ConnectionAborted)
                {
                    Log.Warning("Remote socket forcefully closed: " + sex.SocketErrorCode);
                    if (connection != null)
                        connection.Disconnect("Socket forcefully closed: " + sex.SocketErrorCode);
                    return 0;
                }

                Log.Warning("Execute SocketException: " + sex.SocketErrorCode);
                return 0;
            }
        }
Exemplo n.º 28
0
		public NetStatistics(NetConnection forConnection)
		{
			m_forConnection = forConnection;
			Reset();
		}
Exemplo n.º 29
0
		public int ExecuteSend(NetBase netBase, NetBuffer buffer, NetConnection connection, IPEndPoint remoteEP)
		{
			int len = buffer.LengthBytes;
#if DEBUG
			if (connection != null)
			{
				NetConnectionConfiguration config = connection.Configuration;

				if (config.LossChance > 0.0f && NetRandom.Default.Chance(config.LossChance))
				{
					//m_log.Debug("(simulating loss of sent packet)");
					return len;
				}
				
				if (config.LagDelayChance > 0.0f && NetRandom.Default.Chance(config.LagDelayChance))
				{
					float delayAmount = config.LagDelayMinimum + (NetRandom.Default.NextFloat() * config.LagDelayVariance);

					DelayedPacket pk = new DelayedPacket();
					pk.Data = new byte[len];
					Array.Copy(buffer.Data, pk.Data, buffer.LengthBytes);
					pk.DelayAmount = delayAmount;
					pk.DelayedUntil = NetTime.Now + delayAmount;
					pk.RemoteEP = remoteEP;
					m_delayed.Add(pk);

					//m_log.Debug("(queueing packet for " + (int)(pk.DelayAmount * 1000.0f) + " ms)");

					return len;
				}
			}
#endif

			try
			{
				int bytesSent = netBase.m_socket.SendTo(buffer.Data, 0, len, SocketFlags.None, remoteEP);
				m_log.Verbose(string.Format(CultureInfo.InvariantCulture, "Sent {0} bytes to {1}", bytesSent, remoteEP));

#if DEBUG
				if (connection != null)
				{
					NetConnectionConfiguration config = connection.Configuration;
					if (NetRandom.Default.Chance(config.DuplicatedPacketChance))
					{
						m_log.Debug("(simulating send packet duplication)");
						netBase.m_socket.SendTo(buffer.Data, 0, buffer.LengthBytes, SocketFlags.None, remoteEP);
					}
				}
#endif

				return bytesSent;
			}
			catch (SocketException sex)
			{
				if (sex.SocketErrorCode == SocketError.ConnectionReset ||
					sex.SocketErrorCode == SocketError.ConnectionRefused ||
					sex.SocketErrorCode == SocketError.ConnectionAborted)
				{
					m_log.Warning("Remote socket forcefully closed: " + sex.SocketErrorCode);
					if (connection != null)
						connection.Disconnect("Socket forcefully closed: " + sex.SocketErrorCode);
					return 0;
				}

				m_log.Warning("Execute SocketException: " + sex.SocketErrorCode);
				return 0;
			}
		}
Exemplo n.º 30
0
		public void WriteStringTable(NetConnection connection, string val)
		{
			if (connection == null)
				throw new ArgumentNullException("connection");
			connection.m_stringTable.Write(this, val);
		}