Skip to content

Commit

Permalink
Extracts shared code in client and server to a base abstract class
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkSuckerberg committed Nov 2, 2023
1 parent fbadb57 commit 8a81ee0
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 198 deletions.
139 changes: 35 additions & 104 deletions Blocktest/Code/Networking/Client.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Net;
using Blocktest.Rendering;
using Blocktest.Scenes;
using Blocktest.UI;
Expand All @@ -10,50 +9,27 @@
using Shared.Code.Packets;
namespace Blocktest.Networking;

public sealed class Client {
public sealed class Client : NetworkInterface {
private readonly Camera _camera;
private readonly EventBasedNetListener _listener;
private readonly NetManager _manager;
private readonly Dictionary<int, Renderable> _playerRenderables = new();

private readonly WorldState _worldState;
public TickBuffer ClientTickBuffer;

private readonly BlocktestGame _game;
private readonly Dictionary<int, Renderable> _playerRenderables = new();
private bool _initialized;

public Client(WorldState worldState, Camera camera, BlocktestGame game) {
_worldState = worldState;
public Client(WorldState worldState, Camera camera, BlocktestGame game) : base(worldState) {
_camera = camera;
_game = game;
ClientTickBuffer = new TickBuffer(0, _worldState);
_listener = new EventBasedNetListener();
_manager = new NetManager(_listener);
_listener.NetworkReceiveEvent += NetworkReceiveEvent;
_listener.PeerConnectedEvent += PeerConnected;
_listener.PeerDisconnectedEvent += PeerDisconnected;
_manager.Start();
}

public NetPeer? Server { get; private set; }

public void Start(IPEndPoint ipEndPoint, string key) {
_manager.Connect(ipEndPoint, key);
}

public void Stop() {
_manager.Stop();
}

public void Update() {
_manager.PollEvents();
Listener.PeerConnectedEvent += PeerConnected;
Listener.PeerDisconnectedEvent += PeerDisconnected;
}

private void PeerConnected(NetPeer peer) {
Console.WriteLine("Connected to server");
Console.WriteLine($"Connected to server {peer.EndPoint} as {peer.RemoteId}");

Transform newTransform = new(new Vector2Int(256, 128));
Renderable newRenderable = new(newTransform, Layer.Player, Drawable.ErrorDrawable, Color.Orange);
_worldState.PlayerPositions.Add(peer.RemoteId, newTransform);
LocalWorldState.PlayerPositions.Add(peer.RemoteId, newTransform);
_playerRenderables.Add(peer.RemoteId, newRenderable);
_camera.RenderedComponents.Add(newRenderable);
}
Expand All @@ -65,88 +41,54 @@ private void PeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) {
new DialogueWindow("Disconnected from server.", $"{disconnectInfo.Reason}")));
}

/// <summary>
/// Recieve network events from LiteNetLib
/// </summary>
/// <param name="peer">The server the packet is coming from.</param>
/// <param name="packetReader">Contains the packet from the server.</param>
/// <param name="channelNumber"></param>
/// <param name="deliveryMethod">The delivery method used to deliver this packet.</param>
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader packetReader, byte channelNumber,
DeliveryMethod deliveryMethod) {
if (Server == null) {
Server = peer;

PacketType packetType = (PacketType)packetReader.GetByte();
if (packetType != PacketType.WorldDownload) {
Console.WriteLine("Bad packet!!!");
return;
}

int sourceId = packetReader.GetInt();

WorldDownload worldPacket = HandlePacket<WorldDownload>(packetReader, sourceId);
worldPacket.Process(_worldState);
ClientTickBuffer = new TickBuffer(worldPacket.TickNum, _worldState);

SendPacket(new PeerEvent {
SourceId = Server.RemoteId,
TickNum = worldPacket.TickNum,
Type = PeerEvent.PeerEventType.PlayerList
});
} else {
HandlePackets(packetReader);
}
}

/// <summary>
/// Handles packets after the first.
/// </summary>
/// <param name="packetReader">Contains the packet sent by the server.</param>
/// ACCEPTS PacketType:SourceID:TickNum:Packet
private void HandlePackets(NetDataReader packetReader) {
byte packetByte = packetReader.GetByte();
PacketType packetType = (PacketType)packetByte;

int sourceId = packetReader.GetInt();

protected override void HandlePackets(NetDataReader packetReader, int sourceId, PacketType packetType,
ushort tickNum, NetPeer peer) {
switch (packetType) {
case PacketType.TileChange:
ClientTickBuffer.AddPacket(HandlePacket<TileChange>(packetReader, sourceId));
LocalTickBuffer.AddPacket(HandlePacket<TileChange>(packetReader, sourceId, tickNum));
break;
case PacketType.BreakTile:
ClientTickBuffer.AddPacket(HandlePacket<BreakTile>(packetReader, sourceId));
LocalTickBuffer.AddPacket(HandlePacket<BreakTile>(packetReader, sourceId, tickNum));
break;
case PacketType.MovePlayer:
ClientTickBuffer.AddPacket(HandlePacket<MovePlayer>(packetReader, sourceId));
LocalTickBuffer.AddPacket(HandlePacket<MovePlayer>(packetReader, sourceId, tickNum));
break;
case PacketType.PlayerList:
ClientTickBuffer.AddPacket(HandlePacket<PlayerList>(packetReader, sourceId));
LocalTickBuffer.AddPacket(HandlePacket<PlayerList>(packetReader, sourceId, tickNum));
break;
case PacketType.PeerEvent:
PeerEvent eventPacket = new() { SourceId = sourceId, TickNum = packetReader.GetUShort() };
eventPacket.Deserialize(packetReader);
HandleEvent(eventPacket);
HandleEvent(HandlePacket<PeerEvent>(packetReader, sourceId, tickNum));
break;
case PacketType.WorldDownload:
if (_initialized) {
Console.WriteLine("Bad packet!!!");
break;
}

WorldDownload worldPacket = HandlePacket<WorldDownload>(packetReader, sourceId, tickNum);
worldPacket.Process(LocalWorldState);
LocalTickBuffer = new TickBuffer(worldPacket.TickNum, LocalWorldState);

SendPacket(new PeerEvent {
SourceId = Server.RemoteId,

Check warning on line 73 in Blocktest/Code/Networking/Client.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
TickNum = worldPacket.TickNum,
Type = PeerEvent.PeerEventType.PlayerList
}, Server);

_initialized = true;
break;
default:
Console.WriteLine("Bad packet!!!");
break;
}
}

private T HandlePacket<T>(NetDataReader packetReader, int sourceId) where T : IPacket, new() {
T packet = new() { SourceId = sourceId, TickNum = packetReader.GetUShort() };
packet.Deserialize(packetReader);
return packet;
}

private void HandleEvent(PeerEvent peerEvent) {
protected override void HandleEvent(PeerEvent peerEvent) {
switch (peerEvent.Type) {
case PeerEvent.PeerEventType.PeerDisconnect:
Console.WriteLine("Player disconnected");

_worldState.PlayerPositions.Remove(peerEvent.SourceId);
LocalWorldState.PlayerPositions.Remove(peerEvent.SourceId);
_camera.RenderedComponents.Remove(_playerRenderables[peerEvent.SourceId]);
_playerRenderables.Remove(peerEvent.SourceId);
break;
Expand All @@ -155,7 +97,7 @@ private void HandleEvent(PeerEvent peerEvent) {

Transform newTransform = new(new Vector2Int(256, 128));
Renderable newRenderable = new(newTransform, Layer.Player, Drawable.ErrorDrawable, Color.Orange);
_worldState.PlayerPositions.Add(peerEvent.SourceId, newTransform);
LocalWorldState.PlayerPositions.Add(peerEvent.SourceId, newTransform);
_playerRenderables.Add(peerEvent.SourceId, newRenderable);
_camera.RenderedComponents.Add(newRenderable);
break;
Expand All @@ -164,15 +106,4 @@ private void HandleEvent(PeerEvent peerEvent) {
throw new ArgumentOutOfRangeException(nameof(peerEvent), peerEvent, null);
}
}

// SENDS PacketType:TickNum:Packet
public void SendPacket(IPacket packet, DeliveryMethod deliveryMethod = DeliveryMethod.ReliableUnordered) {
NetDataWriter writer = new();

writer.Put((byte)packet.GetPacketType());
writer.Put(packet.TickNum);
//ID is not needed for client to server packets
writer.Put(packet);
Server?.Send(writer, deliveryMethod);
}
}
18 changes: 9 additions & 9 deletions Blocktest/Code/Scenes/GameScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Blocktest.Scenes;

public sealed class GameScene : IScene {
private readonly RenderableTilemap _backgroundTilemapSprites;
private readonly string[] _blockStrings;

private readonly Camera _camera;
private readonly bool _connect;
Expand All @@ -23,7 +24,6 @@ public sealed class GameScene : IScene {

private readonly WorldState _worldState = new();
private int _blockSelected = 1; //ID of the block to place
private readonly string[] _blockStrings;

private bool _buildMode = true; //true for build, false for destroy

Expand All @@ -43,7 +43,7 @@ public GameScene(BlocktestGame game, bool doConnect, IPEndPoint? ip) {
_blockStrings = BlockManagerShared.AllBlocks.Keys.ToArray();

if (_connect && ip != null) {
_networkingClient.Start(ip, "testKey");
_networkingClient.Connect(ip);
return;
}

Expand All @@ -58,7 +58,7 @@ public void Update(GameTime gameTime) {

HandleInput();

_networkingClient.ClientTickBuffer.IncrCurrTick(_worldState);
_networkingClient.LocalTickBuffer.IncrCurrTick(_worldState);
}

public void Draw(GameTime gameTime, GraphicsDevice graphicsDevice) {
Expand Down Expand Up @@ -136,11 +136,11 @@ public void HandleInput() {
_camera.Position += moveVector;

MovePlayer movementPacket = new() {
TickNum = _networkingClient.ClientTickBuffer.CurrTick,
TickNum = _networkingClient.LocalTickBuffer.CurrTick,
Position = (Vector2Int)_camera.Position,
SourceId = _networkingClient.Server?.RemoteId ?? 0
};
_networkingClient.ClientTickBuffer.AddPacket(movementPacket);
_networkingClient.LocalTickBuffer.AddPacket(movementPacket);
if (_connect) {
_networkingClient.SendPacket(movementPacket);
}
Expand All @@ -162,26 +162,26 @@ public void HandleInput() {

if (_buildMode) {
TileChange testChange = new() {
TickNum = _networkingClient.ClientTickBuffer.CurrTick,
TickNum = _networkingClient.LocalTickBuffer.CurrTick,
Position = tilePos,
Foreground = foreground,
BlockUid = _blockStrings[_blockSelected],
SourceId = _networkingClient.Server?.RemoteId ?? 0
};

_networkingClient.ClientTickBuffer.AddPacket(testChange);
_networkingClient.LocalTickBuffer.AddPacket(testChange);
if (_connect) {
_networkingClient.SendPacket(testChange);
}
} else {
BreakTile testBreak = new() {
TickNum = _networkingClient.ClientTickBuffer.CurrTick,
TickNum = _networkingClient.LocalTickBuffer.CurrTick,
Position = tilePos,
Foreground = foreground,
SourceId = _networkingClient.Server?.RemoteId ?? 0
};

_networkingClient.ClientTickBuffer.AddPacket(testBreak);
_networkingClient.LocalTickBuffer.AddPacket(testBreak);
if (_connect) {
_networkingClient.SendPacket(testBreak);
}
Expand Down
Loading

0 comments on commit 8a81ee0

Please sign in to comment.