Merge pull request #87 from progtime-net/NetworkManagerRDPProtocolImplementation

Network manager rdp protocol implementation
This commit is contained in:
SergoDobro 2024-08-20 11:43:41 +03:00 committed by GitHub
commit d2187b223a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 444 additions and 200 deletions

View file

@ -22,8 +22,10 @@ using System.Linq;
using System.Web;
using ZoFo.GameCore.GUI;
using ZoFo.GameCore.GameObjects.Entities.Interactables.Collectables;
using ZoFo.GameCore.GameObjects.MapObjects.StopObjects;
using ZoFo.GameCore.Graphics;
using ZoFo.GameCore.GameObjects.MapObjects.StopObjects;
using ZoFo.GameCore.GameObjects.Entities.LivingEntities.Enemies;
using ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO;
using ZoFo.GameCore.Graphics;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using ZoFo.GameCore.GameManagers.CollisionManager;
@ -41,7 +43,6 @@ namespace ZoFo.GameCore
public Client()
{
networkManager = new ClientNetworkManager();
networkManager.GetDataSent += OnDataSend;
// Подписка на действия инпутменеджера.
// Отправляются данные апдейтса с обновлением инпута
@ -139,6 +140,10 @@ namespace ZoFo.GameCore
) )
.ToPoint();
}
public void SendData()
{
networkManager.SendData();
}
internal void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < mapObjects.Count; i++)
@ -160,8 +165,9 @@ namespace ZoFo.GameCore
}
internal void GotData(UpdateData update)
internal void GotData(List<UpdateData> updates)
{
if (update is UpdateTileCreated)
{
mapObjects.Add(
@ -274,8 +280,9 @@ namespace ZoFo.GameCore
if (ent != null)
{
(ent as Player).health = (update as UpdatePlayerParametrs).health;
(ent as Player).rad = (update as UpdatePlayerParametrs).radiatoin;
(ent as Player).rad = (update as UpdatePlayerParametrs).radiatoin;
}
}

View file

@ -41,11 +41,11 @@ public class SelectModeMenu : AbstractGUI
// single
Server server = new Server();
Client client = new Client();
server.CreateRoom(1);
client.JoinYourself(server.MyIp.Port);
AppManager.Instance.SetServer(server);
AppManager.Instance.SetClient(client);
AppManager.Instance.ChangeState(GameState.HostPlaying);
server.CreateRoom(false);
client.JoinYourself(server.MyIp.Port);
//AppManager.Instance.ChangeState(GameState.HostPlaying);
AppManager.Instance.SetGUI(new HUD());
//server.CreateRoom(1);

View file

@ -74,6 +74,7 @@ public class SelectingServerGUI : AbstractGUI
{
if (int.TryParse(endpoint[1], out port))
{
client.JoinRoom(endpoint[0], port);
AppManager.Instance.SetClient(client);
AppManager.Instance.SetGUI(new WaitingForPlayersGUI(false));
@ -103,10 +104,10 @@ public class SelectingServerGUI : AbstractGUI
// host
Server server = new Server(); //Server Logic MultiPlayer
Client client = new Client();
server.CreateRoom(2);
client.JoinYourself(server.MyIp.Port);
AppManager.Instance.SetServer(server);
AppManager.Instance.SetClient(client);
server.CreateRoom(true);
client.JoinYourself(server.MyIp.Port);
string key = server.MyIp.ToString();
AppManager.Instance.debugHud.Set(key, "MultiPlayer");
// ваш код здесь

View file

@ -34,8 +34,8 @@ public class WaitingForPlayersGUI : AbstractGUI
// string pcIp =
// string pcIp =
ip = new Label(Manager) { rectangle = new Rectangle(width / 2 - (int)(width / 8), height / 7, (int)(width / 4), (int)(height / 20)), text = AppManager.Instance.server.MyIp.ToString(), fontColor = Color.White, mainColor = Color.Transparent, scale = 0.9f, fontName = "Fonts/Font3" };
Elements.Add(ip);
// ip = new Label(Manager) { rectangle = new Rectangle(width / 2 - (int)(width / 8), height / 7, (int)(width / 4), (int)(height / 20)), text = AppManager.Instance.server.MyIp.ToString(), fontColor = Color.White, mainColor = Color.Transparent, scale = 0.9f, fontName = "Fonts/Font3" };
// Elements.Add(ip);
if (isHost)
{
ip = new Label(Manager) { rectangle = new Rectangle(width / 2 - (int)(width / 8), height / 7, (int)(width / 4), (int)(height / 20)), text = AppManager.Instance.server.MyIp.ToString(), fontColor = Color.White, mainColor = Color.Transparent, scale = 0.9f, fontName = "Fonts\\Font3" };
@ -52,7 +52,7 @@ public class WaitingForPlayersGUI : AbstractGUI
startButton.LeftButtonPressed += () =>
{
// start
AppManager.Instance.ChangeState(GameState.HostPlaying);
AppManager.Instance.server.StartGame();
// ваш код здесь
};
Elements.Add(startButton);
@ -72,7 +72,6 @@ public class WaitingForPlayersGUI : AbstractGUI
waitButton.LeftButtonPressed += () =>
{
// start
AppManager.Instance.ChangeState(GameState.ClientPlaying);
// ваш код здесь
};
Elements.Add(waitButton);

View file

@ -103,8 +103,8 @@ namespace ZoFo.GameCore.GameManagers
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape)) { server?.CloseConnection(); Exit(); }
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape)) { Exit(); }
// debugHud.Set("key", "value");

View file

@ -11,8 +11,9 @@ using ZoFo.GameCore.GameManagers.MapManager.MapElements;
using ZoFo.GameCore.GameObjects.Entities;
using ZoFo.GameCore.GameObjects.Entities.LivingEntities;
using ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient;
using ZoFo.GameCore.Graphics;
using ZoFo.GameCore.GameObjects.Entities.LivingEntities.Player;
using ZoFo.GameCore.Graphics;
using ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO;
using ZoFo.GameCore.GameObjects.Entities.LivingEntities.Player;
namespace ZoFo.GameCore.GameManagers.CollisionManager
{
@ -124,7 +125,7 @@ namespace ZoFo.GameCore.GameManagers.CollisionManager
entity.graphicsComponent.ObjectDrawRectangle.X = (int)entity.position.X;
entity.graphicsComponent.ObjectDrawRectangle.Y = (int)entity.position.Y;
AppManager.Instance.server.AddData(new UpdatePosition() { NewPosition = entity.position, IdEntity = entity.Id });
AppManager.Instance.server.AddData(new UpdatePosition() { NewPosition = new SerializableVector2(entity.position), IdEntity = entity.Id });
AppManager.Instance.debugHud.Set("testPos", entity.position.ToString()); //TODO remove
}

View file

@ -94,6 +94,7 @@ namespace ZoFo.GameCore.GameManagers.MapManager
switch (tile.Type)
{
case "Tile":
AppManager.Instance.server.RegisterGameObject(new MapObject(position,
new Vector2(tileSet.TileWidth, tileSet.TileHeight),
@ -111,7 +112,7 @@ namespace ZoFo.GameCore.GameManagers.MapManager
collisionRectangles.ToArray()));
break;
default:
default:
break;
}
break;

View file

@ -1,3 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
@ -10,47 +12,51 @@ using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using ZoFo.GameCore.GameManagers.NetworkManager.Updates;
using ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient;
using ZoFo.GameCore.GUI;
namespace ZoFo.GameCore.GameManagers.NetworkManager
{
public class ClientNetworkManager
{
private int port = 0;
private int PlayerId;
private IPEndPoint endPoint;
private IPEndPoint sendingEP;
private Socket socket;
List<UpdateData> updates = new List<UpdateData>();
private List<Datagramm> waitingDatagramm = new List<Datagramm>();
private int currentServerDatagrammId = 0;
public delegate void OnDataSent(string Data);
public event OnDataSent GetDataSent; // event
public bool IsConnected { get { return socket.Connected; } }
public IPEndPoint InfoConnect => (IPEndPoint)socket.LocalEndPoint ?? endPoint;
public ClientNetworkManager()
{
Init();
}
public bool SocketConnected()
{
return socket.Connected;
}
public void Init() //create endPoint, socket
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
GetDataSent += AnalyzeData;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
endPoint = new IPEndPoint(GetIp(), 8081);
socket.Bind(endPoint);
Thread thread = new Thread(StartListening);
thread.IsBackground = true;
thread.Start();
}
public void SendData()
{
for (int i = 0; i < updates.Count; i++)
if (updates != null)
{
AppManager.Instance.server.ProcessIUpdateData(updates[i]);
Datagramm Datagramm = new Datagramm();
Datagramm.updateDatas = updates;
byte[] bytes = Encoding.UTF8.GetBytes(System.Text.Json.JsonSerializer.Serialize(Datagramm)); //нужно сериализовать
socket.SendTo(bytes, sendingEP);
}
updates.Clear();
return;// TODO remove
byte[] bytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(updates)); //нужно сериализовать
socket.Send(bytes);
}
public void AddData(UpdateData UpdateData)
@ -58,12 +64,142 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
updates.Add(UpdateData);
}
public void StopConnection()
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
#region Working With Data RDP
public void AnalyzeData(string data)
{
JObject jObj = JsonConvert.DeserializeObject(data) as JObject;
JToken token = JToken.FromObject(jObj);
JToken updateDatas = token["updateDatas"];
if (updateDatas.HasValues)
{
Datagramm Dgramm = new Datagramm();
Dgramm.isImportant = token["isImportant"].ToObject<bool>();
Dgramm.DatagrammId = token["DatagrammId"].ToObject<int>();
if (PlayerId == 0)
{
PlayerId = token["PlayerId"].ToObject<int>();
if (AppManager.Instance.gamestate != GameState.HostPlaying)
{
AppManager.Instance.ChangeState(GameState.ClientPlaying);
AppManager.Instance.SetGUI(new HUD());
}
}
if (Dgramm.isImportant)
{
if (Dgramm.DatagrammId == currentServerDatagrammId + 1)
{
currentServerDatagrammId++;
Dgramm.updateDatas = GetSentUpdates(token["updateDatas"]);
ExecuteDatagramm(Dgramm);
CheckDatagramm();
}
else if (Dgramm.DatagrammId > currentServerDatagrammId + 1 &&
waitingDatagramm.Find(x => x.DatagrammId == Dgramm.DatagrammId) == null)
{
Dgramm.updateDatas = GetSentUpdates(token["updateDatas"]);
waitingDatagramm.Add(Dgramm);
}
SendAcknowledgement(Dgramm.DatagrammId);
}
else
{
Dgramm.updateDatas = GetSentUpdates(token["updateDatas"]);
ExecuteDatagramm(Dgramm);
}
}
}
public List<UpdateData> GetSentUpdates(JToken updatesToken)
{
List<UpdateData> data = new List<UpdateData>();
JArray updateDatas = updatesToken as JArray;
UpdateData update = new UpdateData();
foreach (JObject token in updateDatas.Children())
{
switch (token["UpdateType"].ToObject<string>())
{
case "UpdateAnimation":
update = token.ToObject<UpdateAnimation>();
data.Add(update);
break;
case "UpdateEntityHealth":
update = token.ToObject<UpdateEntityHealth>();
data.Add(update);
break;
case "UpdateGameEnded":
update = token.ToObject<UpdateGameEnded>();
data.Add(update);
break;
case "UpdateGameObjectCreated":
update = token.ToObject<UpdateGameObjectCreated>();
data.Add(update);
break;
case "UpdateGameObjectDeleted":
update = token.ToObject<UpdateGameObjectDeleted>();
data.Add(update);
break;
case "UpdateInteraction":
update = token.ToObject<UpdateInteraction>();
data.Add(update);
break;
case "UpdateInteractionReady":
update = token.ToObject<UpdateInteractionReady>();
data.Add(update);
break;
case "UpdateLoot":
update = token.ToObject<UpdateLoot>();
data.Add(update);
break;
case "UpdatePlayerParametrs":
update = token.ToObject<UpdatePlayerParametrs>();
data.Add(update);
break;
case "UpdatePosition":
update = token.ToObject<UpdatePosition>();
data.Add(update);
break;
case "UpdateTileCreated":
update = token.ToObject<UpdateTileCreated>();
data.Add(update);
break;
}
}
return data;
}
public void SendAcknowledgement(int DatagrammId)
{
Datagramm Dgramm = new Datagramm() { DatagrammId = DatagrammId, PlayerId = PlayerId };
string data = System.Text.Json.JsonSerializer.Serialize(Dgramm);
byte[] buffer = Encoding.UTF8.GetBytes(data);
socket.SendTo(buffer, sendingEP);
}
void CheckDatagramm()
{
Datagramm orderedDgramm = waitingDatagramm.Find(x => x.DatagrammId == currentServerDatagrammId + 1);
while (orderedDgramm != null)
{
currentServerDatagrammId++;
ExecuteDatagramm(orderedDgramm);
waitingDatagramm.Remove(orderedDgramm);
orderedDgramm = waitingDatagramm.Find(x => x.DatagrammId == currentServerDatagrammId + 1);
}
}
void ExecuteDatagramm(Datagramm Dgramm)
{
AppManager.Instance.client.GotData(Dgramm.updateDatas);
//Достаёт Update и передает в ивент
}
#endregion
#region Join
/// <summary>
/// приложение пытается подключиться к комнате
/// </summary>
@ -71,19 +207,8 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
/// <param name="port"></param>
public void JoinRoom(string ip, int port) // multyplayer
{
endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
socket.Connect(endPoint);
SendData();
Thread listen = new Thread(StartListening);
listen.IsBackground = true;
listen.Start();
}
public void JoinRoom(IPEndPoint endPoint) // multyplayer
{
this.endPoint = endPoint;
socket.Connect(endPoint);
sendingEP = new IPEndPoint(IPAddress.Parse(ip), port);
AppManager.Instance.ChangeState(GameState.ClientPlaying);
SendData();
Thread listen = new Thread(StartListening);
listen.IsBackground = true;
@ -95,38 +220,45 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
/// </summary>
public void JoinYourself(int port) // single player
{
endPoint = new IPEndPoint(GetIp(), port);
socket.Connect(endPoint);
sendingEP = AppManager.Instance.server.MyIp;
SendData();
Thread listen = new Thread(StartListening);
listen.IsBackground = true;
listen.Start();
}
#endregion
public static IPAddress GetIp()
{
/*string hostName = Dns.GetHostName(); // Retrive the Name of HOST
var ipList = Dns.GetHostByName(hostName).AddressList;
{
string hostName = Dns.GetHostName(); // Retrive the Name of HOST
var ipList = Dns.GetHostEntry(hostName).AddressList;
var ipV4List = new List<IPAddress>();
foreach (var ip in ipList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip;
}
}*/
return IPAddress.Parse("127.0.0.1");
ipV4List.Add(ip);
}
}
if (ipV4List.Count>0)
{
return ipV4List[ipV4List.Count - 1];
}
return IPAddress.Loopback;
}
//поток 2
public void StartListening()
{
while(socket.Connected)
{
byte[] bytes = new byte[65535];
var countAnsw = socket.Receive(bytes); //Вылетает если кто то закрыл
string update = Encoding.UTF8.GetString(bytes, 0, countAnsw); // обновление отосланные сервером
GetDataSent(update);
byte[] buffer = new byte[65535];
string data;
while (socket != null)
{
EndPoint senderRemote = new IPEndPoint(IPAddress.Any, 0);
int size = socket.ReceiveFrom(buffer, buffer.Length, SocketFlags.None, ref senderRemote);
byte[] correctedBuffer = new byte[size];
Array.Copy(buffer, correctedBuffer, size);
data = Encoding.UTF8.GetString(correctedBuffer);
GetDataSent(data);
}
}
}

View file

@ -9,10 +9,11 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO
{
public class SerializablePoint
{
public int X;
public int Y;
public int X { get; set; }
public int Y { get; set; }
public SerializablePoint(Point point) { X = point.X; Y = point.Y;}
public SerializablePoint() { }
public Point GetPoint() { return new Point(X, Y);}
}
}

View file

@ -10,24 +10,20 @@ using ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO;
namespace ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO
{
[Serializable]
[JsonSerializable(typeof(SerializableRectangle))]
public class SerializableRectangle
{
public SerializablePoint Size { get; set; }
public SerializablePoint Location { get; set; }
public int X { get; set; }
public int Y { get; set; }
public SerializableRectangle()
{
}
public SerializableRectangle(Rectangle rectangle) { X = rectangle.X; Y = rectangle.Y;
Size = new SerializablePoint(rectangle.Size); Location = new SerializablePoint(rectangle.Location); }
public SerializableRectangle(Rectangle rectangle) { Size = new SerializablePoint(rectangle.Size); Location = new SerializablePoint(rectangle.Location); }
public Rectangle GetRectangle()
{
return new Rectangle() { X = X, Y = Y, Size = Size.GetPoint(), Location = Location.GetPoint() };
return new Rectangle(Location.GetPoint(), Size.GetPoint());
}
}
}

View file

@ -0,0 +1,26 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.JavaScript;
using System.Text;
using System.Threading.Tasks;
namespace ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO
{
[Serializable]
public class SerializableVector2
{
public float X { get; set; }
public float Y { get; set; }
public SerializableVector2(Vector2 vector)
{
X = vector.X;
Y = vector.Y;
}
public Vector2 GetVector2()
{
return new Vector2(X, Y);
}
}
}

View file

@ -13,22 +13,27 @@ using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using ZoFo.GameCore.GameManagers.NetworkManager.Updates;
using ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO;
using ZoFo.GameCore.GUI;
namespace ZoFo.GameCore.GameManagers.NetworkManager
{
public class ServerNetworkManager
{
private IPAddress ip = IPAddress.Parse("127.0.0.1");
private const int port = 0;
private IPEndPoint endPoint;
private Socket socket;
private List<Socket> clients;
public List<UpdateData> updates;
private IPAddress ip;
private bool isMultiplayer;
//Player Id to Player endPoint
private List<IPEndPoint> clientsEP;
public IPEndPoint endPoint;
private List<UpdateData> commonUpdates;
private List<UpdateData> importantUpdates;
private List<Datagramm> sendedData;
private List<Datagramm> arrivingDataId;
private int currentDatagrammId = 0;
public delegate void OnDataSend(string data);
public event OnDataSend GetDataSend; // event
Dictionary<Socket, Thread> managerThread;
Thread serverTheread;
public IPEndPoint InfoConnect => (IPEndPoint)socket.LocalEndPoint ?? endPoint;
Thread serverThread;
public ServerNetworkManager() { Init(); }
@ -37,31 +42,46 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
/// </summary>
private void Init()
{
endPoint = new IPEndPoint(GetIp(), port);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
managerThread = new Dictionary<Socket, Thread>();
clients = new List<Socket>();
updates = new List<UpdateData>();
managerThread = new Dictionary<Socket, Thread>();
endPoint = new IPEndPoint(GetIp(), 8080);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
clientsEP = new List<IPEndPoint>();
commonUpdates = new List<UpdateData>();
importantUpdates = new List<UpdateData>();
sendedData = new List<Datagramm>();
arrivingDataId = new List<Datagramm>();
GetDataSend += AnalyzeData;
socket.Bind(endPoint);
}
/// <summary>
/// Получает IP устройства
/// </summary>
/// <returns></returns>
public static IPAddress GetIp()
{
/*string hostName = Dns.GetHostName(); // Retrive the Name of HOST
var ipList = Dns.GetHostByName(hostName).AddressList;
public static IPAddress GetIp()
{
string hostName = Dns.GetHostName(); // Retrive the Name of HOST
var ipList = Dns.GetHostEntry(hostName).AddressList;
var ipV4List = new List<IPAddress>();
foreach (var ip in ipList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip;
}
}*/
return IPAddress.Parse("127.0.0.1");
{
ipV4List.Add(ip);
}
}
if (ipV4List.Count > 0)
{
return ipV4List[ipV4List.Count - 1];
}
return IPAddress.Loopback;
}
public void SetIsMultiplayer(bool isMultiplayer)
{
this.isMultiplayer = isMultiplayer;
}
/// <summary>
@ -69,26 +89,68 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
/// </summary>
public void SendData()
{
for (int i = 0; i < updates.Count; i++)
{
#region Network Sending SinglePlayerFix
//for (int i = 0; i < updates.Count; i++)
//{
AppManager.Instance.client.GotData(updates[i]);
}
updates.Clear();
return; //TODO TODO REMOVE TO ADD NETWORK TODO REMOVE TO ADD NETWORK TODO REMOVE TO ADD NETWORK TODO REMOVE TO ADD NETWORK
// AppManager.Instance.client.GotData(updates[i]);
//}
//updates.Clear();
//return; //TODO TODO REMOVE TO ADD NETWORK TODO REMOVE TO ADD NETWORK TODO REMOVE TO ADD NETWORK TODO REMOVE TO ADD NETWORK
//Что это?
//по 10 паков за раз TODO FIXITFIXITFIXITFIXITFIXITFIXITFIXITFIXITFIXITFIXITFIXITFIXIT
List<UpdateData> datasToSend = new List<UpdateData>();
for (int i = 0; i < 200 && i<updates.Count; i++)
datasToSend.Add(updates[i]);
string data = JsonSerializer.Serialize(datasToSend);
var databytes = Encoding.UTF8.GetBytes(data);
foreach (Socket socket in clients)
#endregion
if (arrivingDataId.Count != 0)
{
clients[0].SendAsync(databytes);
List<Datagramm> actualArrivingId = arrivingDataId;
for (int i = 0; i < actualArrivingId.Count; i++)
{
sendedData.Remove(sendedData.Find(x => x.DatagrammId == actualArrivingId[i].DatagrammId
&& x.PlayerId == actualArrivingId[i].PlayerId));
}
arrivingDataId.Clear();
}
for (int i = 0; i < 200 && i< datasToSend.Count; i++)
updates.RemoveAt(0);
List<UpdateData> dataToSend;
if (importantUpdates.Count != 0 || sendedData.Count != 0)
{
dataToSend = new List<UpdateData>();
for (int i = 0; i < 200 && i < importantUpdates.Count; i++)
dataToSend.Add(importantUpdates[i]);
for (int i = 0; i < clientsEP.Count; i++)
{
Datagramm impDgramm = new Datagramm();
impDgramm.DatagrammId = currentDatagrammId;
impDgramm.updateDatas = dataToSend;
impDgramm.isImportant = true;
impDgramm.PlayerId = i + 1;
sendedData.Add(impDgramm);
foreach (Datagramm Dgramm in sendedData.Where(x => x.PlayerId == i+1))
{
string impData = JsonSerializer.Serialize(Dgramm);
byte[] impBuffer = Encoding.UTF8.GetBytes(impData);
socket.SendTo(impBuffer, clientsEP[i]);
}
}
currentDatagrammId++;
for (int i = 0; i < 200 && i < dataToSend.Count; i++)
importantUpdates.RemoveAt(0);
}
Datagramm unImpDgramm = new Datagramm();
dataToSend = new List<UpdateData>();
for (int i = 0; i < 200 && i < commonUpdates.Count; i++)
dataToSend.Add(commonUpdates[i]);
unImpDgramm.updateDatas = dataToSend;
string data = JsonSerializer.Serialize(unImpDgramm);
byte[] buffer = Encoding.UTF8.GetBytes(data);
foreach (EndPoint sendingEP in clientsEP)
{
socket.SendTo(buffer, sendingEP);
}
for (int i = 0; i < 200 && i < dataToSend.Count; i++)
commonUpdates.RemoveAt(0);
}
/// <summary>
@ -97,42 +159,41 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
/// <param name="data"></param>
public void AddData(UpdateData data)
{
updates.Add(data);
}
/// <summary>
/// По сути конец игры и отключение игроков
/// </summary>
public void CloseConnection()
{
foreach (var item in clients)
if (data.isImportant)
{
//Закрывает сокеты клиентов
item.Shutdown(SocketShutdown.Both);
item.Close();
importantUpdates.Add(data);
}
foreach (var item in managerThread)
{
foreach (var socket in clients)
{
//Закрывает потоки клиентов
managerThread[socket].Interrupt();
}
else {
commonUpdates.Add(data);
}
//очищает листы
managerThread.Clear();
clients.Clear();
}
/// <summary>
/// Начинает работу сервера (Ожидает подключений)
/// </summary>
/// <param name="players"></param>
public void Start(object players)
public void Start()
{
serverTheread = new Thread(StartWaitingForPlayers);
serverTheread.IsBackground = true;
serverTheread.Start(players);
serverThread = new Thread(StartWaitingForPlayers);
serverThread.IsBackground = true;
serverThread.Start();
}
public void StartGame()
{
for (int i = 0; i < clientsEP.Count; i++)
{
Datagramm initDgramm = new Datagramm();
initDgramm.isImportant = true;
initDgramm.DatagrammId = currentDatagrammId;
initDgramm.PlayerId = i + 1;
sendedData.Add(initDgramm);
string data = JsonSerializer.Serialize(initDgramm);
byte[] buffer = Encoding.UTF8.GetBytes(data);
socket.SendTo(buffer, clientsEP[i]);
}
currentDatagrammId++;
AppManager.Instance.ChangeState(GameState.HostPlaying);
AppManager.Instance.SetGUI(new HUD());////
}
//Потоки Клиентов
@ -140,42 +201,42 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager
/// Слушает игроков, которые хотят подключиться
/// </summary>
/// <param name="players"></param>
public void StartWaitingForPlayers(object players)
public void StartWaitingForPlayers()
{
int playNumber = (int)players;
socket.Listen(playNumber);
for (int i = 0; i < playNumber; i++)
byte[] buffer = new byte[65535];
string data;
while (socket != null)
{
Socket client = socket.Accept();
AppManager.Instance.debugHud.Log($"Connect {client.LocalEndPoint.ToString()}");
Thread thread = new Thread(StartListening);
thread.IsBackground = true;
thread.Start(client);
managerThread.Add(client, thread);
clients.Add(client);
//AppManager.Instance.ChangeState(GameState.HostPlaying);
//добавляем клиентов в лист
EndPoint senderRemote = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
int size = socket.ReceiveFrom(buffer, buffer.Length, SocketFlags.None, ref senderRemote);
if (AppManager.Instance.gamestate != GameState.HostPlaying && !clientsEP.Contains(senderRemote) &&
senderRemote != new IPEndPoint(IPAddress.Any, 0))
{
clientsEP.Add((IPEndPoint)senderRemote);
AppManager.Instance.debugHud.Log($"Connect {senderRemote.ToString()}");
if (!isMultiplayer) AppManager.Instance.ChangeState(GameState.HostPlaying);
// Отправлять Init апдейт с информацией об ID игрока и ID датаграмма на сервере
//Можно добавить bool isInit для Датаграммов
}
byte[] correctedBuffer = new byte[size];
Array.Copy(buffer, correctedBuffer, size);
data = Encoding.UTF8.GetString(correctedBuffer);
GetDataSend(data);
}
AppManager.Instance.ChangeState(GameState.HostPlaying);
}
/// <summary>
/// начать слушать клиентов в самой игре активируют Ивент
/// </summary>
/// <param name="socket"></param>
private void StartListening(object socket)
public void AnalyzeData(string data)
{
// obj to Socket
Socket client = (Socket)socket;
while (client.Connected)
Datagramm Dgramm = JsonSerializer.Deserialize<Datagramm>(data);
if (Dgramm.updateDatas == null)
{
var buff = new byte[65535];
var answ = client.Receive(buff);
string response = Encoding.UTF8.GetString(buff, 0, answ);
GetDataSend(response);
//Обработка acknowledgement
arrivingDataId.Add(Dgramm);
}
else
{
//Настроить десериализацию и применять неважные апдейты
}
Task.Delay(-1);
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates
{
public class Datagramm
{
public int DatagrammId { get; set; }
public bool isImportant { get; set; }
public List<UpdateData> updateDatas { get; set; }
public int PlayerId { get; set; }
}
}

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO;
namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient
{
@ -12,9 +13,12 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient
/// </summary>
public class UpdateGameObjectCreated : UpdateData
{
public UpdateGameObjectCreated() { UpdateType = "UpdateGameObjectCreated"; }
public string GameObjectType;
public string GameObjectId;
public Vector2 position;
public UpdateGameObjectCreated() { UpdateType = "UpdateGameObjectCreated"; isImportant = true; }
public string GameObjectType { get; set; }
public string GameObjectId { get; set; }
public SerializableVector2 position { get; set; }
}
}

View file

@ -11,7 +11,7 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient
/// </summary>
public class UpdateGameObjectDeleted : UpdateData
{
public UpdateGameObjectDeleted() { UpdateType = "UpdateGameObjectDeleted"; }
public UpdateGameObjectDeleted() { UpdateType = "UpdateGameObjectDeleted"; isImportant = false; }
public string GameObjectType;
}
}

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoFo.GameCore.GameManagers.NetworkManager.SerializableDTO;
using ZoFo.GameCore.GameObjects.Entities.LivingEntities;
namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient
@ -15,6 +16,6 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient
{
public UpdatePosition() { UpdateType = "UpdatePosition"; }
public Vector2 NewPosition { get; set; }
public SerializableVector2 NewPosition { get; set; }
}
}

View file

@ -17,9 +17,9 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates.ServerToClient
/// </summary>
public class UpdateTileCreated : UpdateData
{
public UpdateTileCreated() { UpdateType = "UpdateTileCreated"; }
public Texture2D TextureTile { get; set; }
public Vector2 Position { get; set; }
public UpdateTileCreated() { UpdateType = "UpdateTileCreated"; isImportant = true; }
[JsonInclude]
public SerializableVector2 Position { get; set; }
public SerializablePoint Size { get; set; }
public SerializableRectangle sourceRectangle { get; set; }
public string tileSetName { get; set; }

View file

@ -27,7 +27,8 @@ namespace ZoFo.GameCore.GameManagers.NetworkManager.Updates
public class UpdateData
{
public int IdEntity { get; set; } //Id объекта
public string UpdateType { get; protected set; } //тип обновления
public string UpdateType { get; set; } //тип обновления
public bool isImportant { get; set; }
public UpdateData()
{

View file

@ -13,10 +13,10 @@ using ZoFo.GameCore.GUI;
namespace ZoFo.GameCore.GameObjects
{
class Ammo : Collectable
{
class Ammo : Collectable
{
public override StaticGraphicsComponent graphicsComponent { get; } = new(_path + "Ammo");
public Ammo(Vector2 position) : base(position) { }
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
@ -37,7 +38,7 @@ namespace ZoFo.GameCore.Graphics
return;
}
texture = AppManager.Instance.Content.Load<Texture2D>(_textureName);
texture = AppManager.Instance.Content.Load<Texture2D>(Path.Combine(AppContext.BaseDirectory, _textureName));
}
public override void Update()

View file

@ -29,12 +29,11 @@ namespace ZoFo.GameCore
public class Server
{
private ServerNetworkManager networkManager;
private int ticks = 0;
public IPEndPoint MyIp { get { return networkManager.InfoConnect; } }
private int ticks = 0;
public IPEndPoint MyIp { get { return networkManager.endPoint; } }
public Server()
{
networkManager = new ServerNetworkManager();
networkManager.GetDataSend += OnDataSend;
collisionManager = new CollisionManager();
}
@ -96,10 +95,6 @@ namespace ZoFo.GameCore
}
}
public void CloseConnection()
{
networkManager.CloseConnection();
}
/// <summary>
/// Для красоты) Отдел Серверов
@ -115,9 +110,10 @@ namespace ZoFo.GameCore
/// Создает комнату и запускает ожидание подключений
/// </summary>
/// <param name="players"></param>
public void CreateRoom(int players)
public void CreateRoom(bool isMultiplayer)
{
networkManager.Start(players);
networkManager.SetIsMultiplayer(isMultiplayer);
networkManager.Start();
}
#endregion
@ -136,6 +132,7 @@ namespace ZoFo.GameCore
gameObjects = new List<GameObject>();
entities = new List<Entity>();
players = new List<Player>();
networkManager.StartGame();
new MapManager().LoadMap();
//AppManager.Instance.server.RegisterGameObject(new EntittyForAnimationTests(new Vector2(0, 0)));
@ -155,10 +152,9 @@ namespace ZoFo.GameCore
{
UpdateGameEnded gameEnded = new UpdateGameEnded();
networkManager.AddData(gameEnded);
networkManager.CloseConnection();
}
public List<GameObject> gameObjects;
public List<GameObject> gameObjects = new List<GameObject>();
public List<Entity> entities; //entity
public List<Player> players;
public void Update(GameTime gameTime)
@ -208,7 +204,7 @@ namespace ZoFo.GameCore
{
AddData(new UpdateTileCreated()
{
Position = (gameObject as MapObject).position,
Position = new SerializableVector2((gameObject as MapObject).position),
sourceRectangle = new SerializableRectangle((gameObject as MapObject).sourceRectangle),
Size = new SerializablePoint((gameObject as MapObject).graphicsComponent.ObjectDrawRectangle.Size),
tileSetName = ((gameObject as MapObject).graphicsComponent as StaticGraphicsComponent)._textureName
@ -228,21 +224,21 @@ namespace ZoFo.GameCore
}
if (gameObject is Entity entity)
{
{
AddData(new UpdateGameObjectCreated()
{
GameObjectType = gameObject.GetType().Name,
IdEntity = entity.Id,
position = gameObject.position
});
});
collisionManager.Register(entity.collisionComponent);
entities.Add(entity);
}
else
else
AddData(new UpdateGameObjectCreated()
{
GameObjectType = gameObject.GetType().Name,
position = gameObject.position
position = gameObject.position
});