using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using GameServer;
namespace SCdll
{
    public partial class Form1 : Form
    {
        private Server server;
        public Form1()
        {
            InitializeComponent();
            statusLabel.ForeColor = Color.Red;
            statusLabel.Text = "Stoped.";
            Thread.Sleep(2000);
            btnStart_Click(this,new EventArgs());
        }
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (server == null || !server.IsRunning)
            {
                rtbSystemMessage.Clear();
                server = new Server(int.Parse(tbPort.Text),int.Parse(tbUDPport.Text),this);
                server.Start();
                statusLabel.Text = "Running...";
                statusLabel.ForeColor = Color.GreenYellow;
            }
        }
        private void btnStop_Click(object sender, EventArgs e)
        {
            if (server.IsRunning)
            {
                server.Stop();
                statusLabel.ForeColor = Color.Red;
                statusLabel.Text = "Stoped.";
            }
        }
        private void btnCheckClienCount_Click(object sender, EventArgs e)
        {
            server.checkClientCount();
        }
        private void tbPort_TextChanged(object sender, EventArgs e)
        {
        }
        private void dasdasdaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2(this);
            form2.Show();
        }
        public void CreateMob(List<int[]> coors)
        {
            
        }
    }
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using MySql.Data.MySqlClient;
using ProtoBuf;
using SCdll;
using SCdll.GServer;
using SCdll.NSClient;
using SCdll.NSClient.ClientInterface;
using SCdll.NSServer;
using SCdll.NSServer.ServerInterface;
using Sdll;
namespace GameServer
{
    public class Server
    {
        private delegate void Del();
        private delegate void DelError(string s);
        private MyTimer timer;
        private int _port;
        private int _UDPport;
        private Socket _socket;
        private Socket _UDPsocket;
        private MySqlConnection _mySqlConnection;
        private string _db_connect;
        private List<Client> clients;
        private Form1 form;
        private bool serverStatus;
        private int lineCount;
        private byte[] UDPbuffer;
        private UdpClient UdpServer;
        private ushort[,] map;
        public bool IsRunning
        {
            get { return serverStatus; }
            set { serverStatus = value; }
        }
        public Server(int port, int UDPport, Form1 form)
        {
            lineCount = 1;
            serverStatus = false;
            _port = port;
            _UDPport = UDPport;
            clients = new List<Client>();
            Config.Initialize(new Action<string>(SystemMessage));
            timer = new MyTimer();
            this.form = form;
            UDPbuffer=new byte[1024];
            UdpServer=new UdpClient(_UDPport);
        }
        public void Start()
        {
            LoadMap();
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _UDPsocket = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
            EndPoint _endPoint = new IPEndPoint(IPAddress.Any, _port);
            _socket.Bind(_endPoint);
            _socket.Listen((int)SocketOptionName.MaxConnections);
            _socket.BeginAccept(new AsyncCallback(AcceptCallback), _socket);
            EndPoint _udpEndPoint = new IPEndPoint(IPAddress.Any,_UDPport);
            timer.AddHandler(ShowTimer);
            timer.Interval = 50;
            timer.Start();
            IsRunning = true;
        }
        private void LoadMap()
        {
            byte[] buff = File.ReadAllBytes(Directory.GetCurrentDirectory() + "\\map.map");
            map = new ushort[400, 400];
            int count1 = 0;
            ushort[] map1 = new ushort[160000];
            for (int i = 0; i < buff.Length; i += 2)
            {
                map1[i / 2] = BitConverter.ToUInt16(buff, i);
            }
            for (int i = 0; i < 400; i++)
            {
                for (int j = 0; j < 400; j++)
                {
                    map[i, j] = map1[count1];
                    count1++;
                }
            }
            SystemMessage("Map has been loaded");
        }        
        private void UDPReceiveCallback(IAsyncResult ar)
        {
            UdpClient client = (UdpClient) ar.AsyncState;
            IPEndPoint IPendPoint = new IPEndPoint(IPAddress.Any, 0);
            byte[] data = client.EndReceive(ar, ref IPendPoint);
            SystemMessage("UDP: receive "+data.Length+" bytes");
            byte[] hashByte = new byte[data.Length-sizeof(ushort)];
            Array.Copy(data,sizeof(ushort),hashByte,0,data.Length-sizeof(ushort));
            ushort hash = GetHash(hashByte);
            if (hash == BitConverter.ToUInt16(data, 0))
            {
                SystemMessage("hash is good");
                ushort id = BitConverter.ToUInt16(data, 2);
                Client cl = clients.Find(
                    delegate(Client c)
                    {
                        return c.userId == id;
                    });
                if (cl!=null)
                {
                    cl.IPendPoint = IPendPoint;
                    SystemMessage("client is exist");
                    ushort messageID = BitConverter.ToUInt16(data, 4);
                    if (messageID > cl.messageID)
                    {
                        foreach (var client1 in clients)
                        {
                            if (client1.IPendPoint != null && client1.userId != id)
                            {
                                client1.lastData = data;
                                UdpServer.BeginSend(data,data.Length,client1.IPendPoint,UDPSendCallback,UdpServer);
                                SystemMessage("UDP: sent ");
                            }
                        }
                    }
                }
            }
            else
            {
                SystemMessage("Hash is bad "+hash);
            }
            client.BeginReceive(UDPReceiveCallback, UdpServer);
        }
        private void UDPSendCallback(IAsyncResult ar)
        {
            UdpClient udpClient = (UdpClient) ar.AsyncState;
            int n = udpClient.EndSend(ar);
            SystemMessage("UDP: sent "+n+" bytes");
        }
        static ushort GetHash(byte[] data)
        {
            int lenght = data.Length;
            byte[] buff;
            if (lenght % 2 == 1)
            {
                buff = new byte[lenght + 1];
                Array.Copy(data, buff, lenght);
                buff[lenght] = 0;
            }
            else
            {
                buff = data;
            }
            ushort hash = 0;
            for (int i = 0; i < lenght; i += 2)
            {
                hash ^= (ushort)BitConverter.ToInt16(buff, i);
            }
            return hash;
        }
        public void Stop()
        {
            foreach (var client in clients)
            {
                client.socket.Shutdown(SocketShutdown.Both);
                client.socket.Disconnect(false);
                client.socket.Close();
            }
            clients.Clear();
            _socket.Dispose();
            UdpServer.Close();
            timer.Stop();
            IsRunning = false;
        }
        private void AcceptCallback(IAsyncResult result)
        {
            try
            {
                Socket acceptSocket = (Socket)result.AsyncState;
                Client client = new Client();
                client.socket = (Socket)acceptSocket.EndAccept(result);
                if (!clients.Contains(client))
                {
                    lock (clients)
                    {
                        clients.Add(client);
                    }
                    SystemMessage("New client has been added");
                    client.socket.BeginReceive(client.bufferReceive, 0, client.bufferReceive.Length, SocketFlags.None,
                    new AsyncCallback(ReceiveCallback), client);
                }
                UdpServer.BeginReceive(UDPReceiveCallback, UdpServer);
                _socket.BeginAccept(new AsyncCallback(AcceptCallback), _socket);
            }
            catch (Exception e)
            {
                SystemMessage(e.Message + " | AcceptCallback");
            }
        }
        private void ReceiveCallback(IAsyncResult result)
        {
            try
            {
                Client client = (Client)result.AsyncState;
                int nBytes = client.socket.EndReceive(result);
                SystemMessage("Received: " + nBytes + " bytes");
                if (nBytes > 0)
                {
                    lock (clients)
                    {
                        int fullLength = 0, dataLength = 0;
                        int startIndex = 0;
                        do
                        {
                            dataLength = BitConverter.ToUInt16(client.bufferReceive, startIndex);
                            byte[] arr = new byte[dataLength];
                            Buffer.BlockCopy(client.bufferReceive, startIndex + 2, arr, 0, dataLength);
                            ClientData command = Serializer.Deserialize<ClientData>(new MemoryStream(arr));
                            ServerData result1 = new SuperExecutor(clients, client, timer).Executor(command);
                            switch (result1.SendingMode())
                            {
                                case SelectSending.SendToSelf:
                                    SendToSelf(client, result1);
                                    break;
                                case SelectSending.SendToOthers:
                                    SendToOthers(client, result1);
                                    break;
                                case SelectSending.SendToClient:
                                    SendToClient(result1);
                                    break;
                                case SelectSending.NoSend:
                                    break;
                            }
                            fullLength = dataLength + 2;
                            startIndex += fullLength;
                            SystemMessage("length: " + dataLength + "  full length: " + fullLength + "  start index: " + startIndex);
                        } while (startIndex < nBytes);
                    }
                }
                if (nBytes == 0)
                {
                    client.socket.Close();
                    lock (clients)
                    {
                        clients.Remove(client);
                        SystemMessage("Client has been removed");
                    }
                }
                if (clients.Contains(client))
                    client.socket.BeginReceive(client.bufferReceive, 0, client.bufferReceive.Length, SocketFlags.None,
                        new AsyncCallback(ReceiveCallback), client);
            }
            catch (SocketException e)
            {
                SystemMessage(e.Message + " ErrorCode: " + e.ErrorCode);
            }
            catch (Exception e)
            {
                SystemMessage(e.Message + " | ReceiveCallback");
            }
        }
        public void checkClientCount()
        {
            SystemMessage(clients.Count.ToString());
        }
        private void ShowTimer(object src, ElapsedEventArgs args)
        {
            form.timerTB.BeginInvoke(new Del(() => form.timerTB.Text = timer.CurrentTime.ToString()));
        }
        public void SystemMessage(string message)
        {
            form.rtbSystemMessage.Invoke(new Del(() => form.rtbSystemMessage.AppendText(lineCount + ") " + message + "\n")));
            lineCount++;
        }
        private void SendToSelf(Client client, ServerData data)
        {
            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, data);
            client.bufferSend = ms.ToArray();
            client.socket.Send(client.bufferSend, 0, client.bufferSend.Length, SocketFlags.None);
            SystemMessage("данные отправилися");
        }
        private void SendToOthers(Client client, ServerData data)
        {
            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, data);
            foreach (var client1 in clients)
            {
                if (client1 != client && client1.isInWorld)
                {
                    client1.bufferSend = ms.ToArray();
                    client1.socket.Send(client1.bufferSend, 0, client1.bufferSend.Length, SocketFlags.None);
                }
            }
        }
        private void SendToClient(ServerData data)
        {
            MemoryStream ms = new MemoryStream();
            Serializer.Serialize(ms, data);
            data.client.bufferSend = ms.ToArray();
            data.client.socket.Send(data.client.bufferSend, 0, data.client.bufferSend.Length, SocketFlags.None);
        }
    }
}