-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6fe0d83
commit 5370d89
Showing
34 changed files
with
286 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,55 @@ | ||
using System.Reflection; | ||
using System.Text.Json; | ||
|
||
namespace SpaceWar; | ||
|
||
[Serializable] | ||
public class AppSettings | ||
{ | ||
public string LobbyName = "spacewar"; | ||
public string Username = string.Empty; | ||
public int Port = 9000; | ||
public string Username { get; set; } = string.Empty; | ||
public required string LobbyName { get; set; } | ||
public required Uri ServerUrl { get; set; } | ||
public int LocalPort { get; set; } | ||
public int ServerUdpPort { get; set; } | ||
|
||
public void ParseArgs(string[] args) | ||
{ | ||
if (args is []) return; | ||
|
||
var argsDict = args | ||
.Chunk(2) | ||
.Where(a => a[0].StartsWith('-')) | ||
.Select(a => a is [{ } key, { } value] | ||
? (Key: key.TrimStart('-'), Value: value) | ||
: throw new InvalidOperationException("Bad arguments") | ||
).ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase); | ||
|
||
if (argsDict.TryGetValue(nameof(LocalPort), out var portArg) && | ||
int.TryParse(portArg, out var port) && port > 0) | ||
LocalPort = port; | ||
|
||
if (argsDict.TryGetValue(nameof(ServerUdpPort), out var lobbyPortArg) && | ||
int.TryParse(lobbyPortArg, out var lobbyPort) && lobbyPort > 0) | ||
ServerUdpPort = lobbyPort; | ||
|
||
if (argsDict.TryGetValue(nameof(ServerUrl), out var serverUrl) && | ||
Uri.TryCreate(serverUrl, UriKind.Absolute, out var serverUri)) | ||
ServerUrl = serverUri; | ||
|
||
if (argsDict.TryGetValue(nameof(Username), out var usernameArg) && | ||
!string.IsNullOrWhiteSpace(usernameArg)) | ||
Username = usernameArg; | ||
} | ||
|
||
public int LobbyPort = 8888; | ||
public static AppSettings LoadFromJson(string file) | ||
{ | ||
var settingsFile = Path.Combine( | ||
Path.GetDirectoryName(AppContext.BaseDirectory) | ||
?? Directory.GetCurrentDirectory(), | ||
file | ||
); | ||
|
||
public Uri LobbyUrl = new("https://lobby-server.fly.dev"); | ||
// public readonly Uri LobbyUrl = new("http://localhost:9999"); | ||
return JsonSerializer.Deserialize<AppSettings>(File.ReadAllText(settingsFile)) | ||
?? throw new InvalidOperationException($"unable to read {file}"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,7 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using SpaceWar; | ||
|
||
AppSettings settings = new(); | ||
ReadProgramArgs(); | ||
var settings = AppSettings.LoadFromJson("appsettings.json"); | ||
settings.ParseArgs(args); | ||
|
||
using var game = new Game1(settings); | ||
game.Run(); | ||
|
||
|
||
void ReadProgramArgs() | ||
{ | ||
if (TryGetConfig(0, "SPACEWAR_PORT", out var portArg) && | ||
int.TryParse(portArg, out var port)) | ||
settings.Port = port; | ||
|
||
if (TryGetConfig(1, "SPACEWAR_LOBBY_URL", out var serverUrlArg) | ||
&& Uri.TryCreate(serverUrlArg, UriKind.Absolute, out var serverUrl)) | ||
settings.LobbyUrl = serverUrl; | ||
|
||
if (TryGetConfig(2, "SPACEWAR_LOBBY_PORT", out var lobbyPortArg) | ||
&& int.TryParse(lobbyPortArg, out var lobbyPort)) | ||
settings.LobbyPort = lobbyPort; | ||
} | ||
|
||
bool TryGetConfig(int argsIndex, string envName, | ||
[NotNullWhen(true)] out string? argValue) | ||
{ | ||
var tempValue = Environment.GetEnvironmentVariable(envName); | ||
if (!string.IsNullOrWhiteSpace(tempValue)) | ||
{ | ||
argValue = tempValue; | ||
return true; | ||
} | ||
|
||
tempValue = args.ElementAtOrDefault(argsIndex); | ||
if (!string.IsNullOrWhiteSpace(tempValue)) | ||
{ | ||
argValue = tempValue; | ||
return true; | ||
} | ||
|
||
argValue = null; | ||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,86 @@ | ||
# SpaceWar - NetCode Sample | ||
## Running | ||
Run one of the scripts in [/scripts](/samples/SpaceWar/scripts) to start multiple clients of the game. | ||
> On Windows run the `.cmd` [/scripts/windows](/samples/SpaceWar/scripts/windows) | ||
> On Linux/Mac run the `.sh` files [/scripts/linux](/samples/SpaceWar/scripts/linux) | ||
Each script defines a configuration with up to 4 players, some of them with spectators, they are: | ||
- **start_2players**: start 2 game peer instances. | ||
- **start_2players_1spec:** Start 2 game peer instances with a single spectator on player 1. | ||
- **start_2players_2spec:** Start 2 game peer instances with two spectators. each observing one player. | ||
- **start_3players:** Start 3 game peer instances. | ||
- **start_4players:** Start 4 game peer instances. | ||
- **start_4players_2spec:** Start 4 game peer instances with two spectators. one observing player 1 and the other | ||
observing player 2. | ||
# SpaceWar - NetCode Sample with online Lobby | ||
|
||
This shows a basic example of NAT traversal using [UDP hole punching](https://en.wikipedia.org/wiki/UDP_hole_punching) | ||
|
||
# How it works? | ||
|
||
This enable a P2P connection over the internet, this is possible using | ||
a [middle server](https://github.com/lucasteles/Backdash/tree/master/samples/LobbyServer) | ||
which all clients know. | ||
The server catches the IP address and port of a client and send it to the others. | ||
|
||
The current server runs almost as a simple http with json responses. It keeps the lobbies info with sliding expiration | ||
cache. | ||
|
||
When a client enters the lobby the server responds with a token of type `Guid`/`UUID`. It is used a very | ||
basic `Authentication` mechanism. | ||
|
||
The client use http pooling to get updated information of each lobby member/peer. | ||
|
||
When logged-in every client needs to send a `UDP` package with their token to the server. So the | ||
server updates their `IP` and open `Port` using the package headers metadata. | ||
|
||
> ⚠️ UDP Hole punching usually **does not** work witch clients behind the same NAT. To mitigate this the server | ||
> also tracks the clients local IPs and ports. So they can check if the peer is at the same network | ||
## Controls | ||
|
||
- **Arrows**: Move | ||
- **Left Control**: Fire | ||
- **Enter**: Missile | ||
|
||
## Running | ||
|
||
### Server | ||
|
||
On the [server directory](https://github.com/lucasteles/Backdash/tree/master/samples/LobbyServer) run: | ||
|
||
```bash | ||
dotnet run . | ||
``` | ||
|
||
- Default **HTTP**: `9999` | ||
- Default **UDP** : `8888` | ||
|
||
> 💡 Check the swagger `API` docs at http://localhost:9999/swagger | ||
### Clients | ||
|
||
On `SpaceWar.Lobby` project directory run | ||
|
||
```bash | ||
dotnet run . | ||
``` | ||
|
||
The default client configuration is defined in this [JSON file](/appsettings.json): | ||
|
||
```json | ||
{ | ||
"LobbyName": "spacewar", | ||
"LocalPort": 9000, | ||
"ServerUrl": "http://localhost:9999", | ||
"ServerUdpPort": 8888 | ||
} | ||
``` | ||
|
||
You can override the default port via command args: | ||
|
||
```sh | ||
dotnet run --project .\LobbyClient -LocalPort 9001 | ||
``` | ||
|
||
> 💡useful for starting clients in different ports | ||
|
||
You can also override the server URL and UDP Port configs: | ||
|
||
```bash | ||
dotnet run --project .\LobbyClient -ServerUrl "https://lobby-server.fly.dev" -ServerUdpPort 8888 | ||
``` | ||
|
||
Check the the [scripts directory](https://github.com/lucasteles/Backdash/tree/master/samples/SpaceWar.Lobby/scripts) | ||
to run local instances of the server and clients. | ||
|
||
> ⚠️ The default configured server is a remote server. To connect to localhost server | ||
> run: `dotnet run . -ServerUrl "http://localhost:9999"` | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.