From e5b6d99bef90dbc3513ad91ec2691d5eb70d6ff4 Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Sun, 25 Jun 2017 20:23:34 +0100 Subject: [PATCH] Added ServerInit class, changed how servers are initialized --- Facepunch.Steamworks.Test/Client/Inventory.cs | 2 +- Facepunch.Steamworks.Test/Server/Server.cs | 14 ++- Facepunch.Steamworks.Test/Server/Stats.cs | 2 +- Facepunch.Steamworks/Server.cs | 115 +++++++++--------- Facepunch.Steamworks/Server/ServerInit.cs | 67 ++++++++++ 5 files changed, 138 insertions(+), 62 deletions(-) create mode 100644 Facepunch.Steamworks/Server/ServerInit.cs diff --git a/Facepunch.Steamworks.Test/Client/Inventory.cs b/Facepunch.Steamworks.Test/Client/Inventory.cs index b076046..73e47da 100644 --- a/Facepunch.Steamworks.Test/Client/Inventory.cs +++ b/Facepunch.Steamworks.Test/Client/Inventory.cs @@ -134,7 +134,7 @@ public void Deserialize() Assert.IsNotNull( client.Inventory.SerializedItems ); Assert.IsTrue( client.Inventory.SerializedItems.Length > 4 ); - using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) ) + using ( var server = new Facepunch.Steamworks.Server( 252490, new ServerInit( "rust", "Rust" ) ) ) { server.LogOnAnonymous(); Assert.IsTrue( server.IsValid ); diff --git a/Facepunch.Steamworks.Test/Server/Server.cs b/Facepunch.Steamworks.Test/Server/Server.cs index 6e48df2..3fcd49e 100644 --- a/Facepunch.Steamworks.Test/Server/Server.cs +++ b/Facepunch.Steamworks.Test/Server/Server.cs @@ -18,8 +18,16 @@ public partial class Server [TestMethod] public void Init() { - using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30003, 30004, 30005, false, "VersionString" ) ) + var serverInit = new ServerInit( "rust", "Rust" ); + serverInit.GamePort = 28015; + serverInit.Secure = true; + serverInit.QueryPort = 28016; + + using ( var server = new Facepunch.Steamworks.Server( 252490, serverInit ) ) { + server.ServerName = "My Test Server"; + server.LogOnAnonymous(); + Assert.IsTrue( server.IsValid ); } } @@ -27,7 +35,7 @@ public void Init() [TestMethod] public void PublicIp() { - using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30003, 30004, 30005, false, "VersionString" ) ) + using ( var server = new Facepunch.Steamworks.Server( 252490, new ServerInit( "rust", "Rust" ) ) ) { server.LogOnAnonymous(); @@ -61,7 +69,7 @@ public void AuthCallback() var ticket = client.Auth.GetAuthSessionTicket(); var ticketBinary = ticket.Data; - using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, 30003, 30004, true, "VersionString" ) ) + using ( var server = new Facepunch.Steamworks.Server( 252490, new ServerInit( "rust", "Rust" ) ) ) { server.LogOnAnonymous(); diff --git a/Facepunch.Steamworks.Test/Server/Stats.cs b/Facepunch.Steamworks.Test/Server/Stats.cs index a064fe7..a877f82 100644 --- a/Facepunch.Steamworks.Test/Server/Stats.cs +++ b/Facepunch.Steamworks.Test/Server/Stats.cs @@ -10,7 +10,7 @@ public partial class Server [TestMethod] public void StatsGet() { - using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30003, 30004, 30005, true, "VersionString" ) ) + using ( var server = new Facepunch.Steamworks.Server( 252490, new ServerInit( "rust", "Rust" ) ) ) { Assert.IsTrue( server.IsValid ); server.LogOnAnonymous(); diff --git a/Facepunch.Steamworks/Server.cs b/Facepunch.Steamworks/Server.cs index 715a2b2..3119bf6 100644 --- a/Facepunch.Steamworks/Server.cs +++ b/Facepunch.Steamworks/Server.cs @@ -1,8 +1,5 @@ - - -using System; +using System; using System.Collections.Generic; -using System.Runtime.InteropServices; namespace Facepunch.Steamworks { @@ -27,31 +24,17 @@ public partial class Server : BaseSteamworks /// /// Initialize a Steam Server instance /// - /// You game's AppId - /// The IP Address to bind to. Can be 0 to mean "any". - /// Port to talk to steam on, can be anything as long as it's not used.". - /// The port you game listens to for connections. - /// The port Steam should use for server queries. - /// True if you want to use VAC - /// A string defining version, ie "1001" - public Server( uint appId, uint IpAddress, ushort SteamPort, ushort GamePort, ushort QueryPort, bool Secure, string VersionString ) + public Server( uint appId, ServerInit init ) { Instance = this; native = new Interop.NativeInterface(); - // - // If we don't have a SteamPort defined, choose one at 'random' - // - if ( SteamPort == 0 ) - { - SteamPort = (ushort) new Random().Next( 10000, 60000 ); - } - + if ( init.SteamPort == 0 ) init.RandomSteamPort(); // // Get other interfaces // - if ( !native.InitServer( this, IpAddress, SteamPort, GamePort, QueryPort, Secure ? 3 : 2, VersionString ) ) + if ( !native.InitServer( this, init.IpAddress, init.SteamPort, init.GamePort, init.QueryPort, init.Secure ? 3 : 2, init.VersionString ) ) { native.Dispose(); native = null; @@ -74,7 +57,11 @@ public Server( uint appId, uint IpAddress, ushort SteamPort, ushort GamePort, us native.gameServer.EnableHeartbeats( true ); MaxPlayers = 32; BotCount = 0; - MapName = "unset"; + Product = $"{AppId}"; + ModDir = init.ModDir; + GameDescription = init.GameDescription; + Passworded = false; + DedicatedServer = true; // // Child classes @@ -89,29 +76,6 @@ public Server( uint appId, uint IpAddress, ushort SteamPort, ushort GamePort, us Update(); } - /// - /// Initialize a Steam Server instance - /// - /// You game's AppId - /// The IP Address to bind to. Can be 0 to mean "any". - /// The port you game listens to for connections. - /// The port Steam should use for server queries. - /// True if you want to use VAC - /// A string defining version, ie "1001" - public Server( uint appId, uint IpAddress, ushort GamePort, ushort QueryPort, bool Secure, string VersionString ) : this( appId, IpAddress, 0, GamePort, QueryPort, Secure, VersionString ) - { - - } - - /// - /// Initialize a server - query port will use the same as GamePort (MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE) - /// This means you'll need to detect and manually process and reply to server queries. - /// - public Server( uint appId, uint IpAddress, ushort GamePort, bool Secure, string VersionString ) : this( appId, IpAddress, GamePort, 0xFFFF, Secure, VersionString ) - { - - } - /// /// Should be called at least once every frame /// @@ -125,6 +89,17 @@ public override void Update() base.Update(); } + /// + /// Sets whether this should be marked as a dedicated server. + /// If not, it is assumed to be a listen server. + /// + public bool DedicatedServer + { + get { return _dedicatedServer; } + set { if ( _dedicatedServer == value ) return; native.gameServer.SetDedicatedServer( value ); _dedicatedServer = value; } + } + private bool _dedicatedServer; + /// /// Gets or sets the current MaxPlayers. /// This doesn't enforce any kind of limit, it just updates the master server. @@ -163,17 +138,17 @@ public string MapName public string ModDir { get { return _modDir; } - set { if ( _modDir == value ) return; native.gameServer.SetModDir( value ); _modDir = value; } + internal set { if ( _modDir == value ) return; native.gameServer.SetModDir( value ); _modDir = value; } } private string _modDir = ""; /// - /// Gets or sets the current product. This isn't really used. + /// Gets the current product /// public string Product { get { return _product; } - set { if ( _product == value ) return; native.gameServer.SetProduct( value ); _product = value; } + internal set { if ( _product == value ) return; native.gameServer.SetProduct( value ); _product = value; } } private string _product = ""; @@ -183,7 +158,7 @@ public string Product public string GameDescription { get { return _gameDescription; } - set { if ( _gameDescription == value ) return; native.gameServer.SetGameDescription( value ); _gameDescription = value; } + internal set { if ( _gameDescription == value ) return; native.gameServer.SetGameDescription( value ); _gameDescription = value; } } private string _gameDescription = ""; @@ -224,8 +199,15 @@ public string GameTags public void LogOnAnonymous() { native.gameServer.LogOnAnonymous(); + ForceHeartbeat(); } + /// + /// Returns true if the server is connected and registered with the Steam master server + /// You should have called LogOnAnonymous etc on startup. + /// + public bool LoggedOn => native.gameServer.BLoggedOn(); + Dictionary KeyValue = new Dictionary(); /// @@ -261,14 +243,6 @@ public void UpdatePlayer( ulong steamid, string name, int score ) native.gameServer.BUpdateUserData( steamid, name, (uint) score ); } - /// - /// Returns true if the server is connected and registered with the Steam master server - /// You should have called LogOnAnonymous etc on startup. - /// - public bool LoggedOn - { - get { return native.gameServer.BLoggedOn(); } - } /// /// Shutdown interface, disconnect from Steam @@ -314,6 +288,33 @@ public System.Net.IPAddress PublicIp } } + /// + /// Enable or disable heartbeats, which are sent regularly to the master server. + /// Enabled by default. + /// + public bool AutomaticHeartbeats + { + set { native.gameServer.EnableHeartbeats( value ); } + } + + /// + /// Set heartbeat interval, if automatic heartbeats are enabled. + /// You can leave this at the default. + /// + public int AutomaticHeartbeatRate + { + set { native.gameServer.SetHeartbeatInterval( value ); } + } + + /// + /// Force send a heartbeat to the master server instead of waiting + /// for the next automatic update (if you've left them enabled) + /// + public void ForceHeartbeat() + { + native.gameServer.ForceHeartbeat(); + } + } } diff --git a/Facepunch.Steamworks/Server/ServerInit.cs b/Facepunch.Steamworks/Server/ServerInit.cs new file mode 100644 index 0000000..b4787a2 --- /dev/null +++ b/Facepunch.Steamworks/Server/ServerInit.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Facepunch.Steamworks +{ + /// + /// Used to set up the server. + /// The variables in here are all required to be set, and can't be changed once the server is created. + /// + public class ServerInit + { + public uint IpAddress = 0; + public ushort SteamPort; + public ushort GamePort = 27015; + public ushort QueryPort = 27016; + public bool Secure = true; + + /// + /// The version string is usually in the form x.x.x.x, and is used by the master server to detect when the server is out of date. + /// If you go into the dedicated server tab on steamworks you'll be able to server the latest version. If this version number is + /// less than that latest version then your server won't show. + /// + public string VersionString = "2.0.0.0"; + + /// + /// This should be the same directory game where gets installed into. Just the folder name, not the whole path. I.e. "Rust", "Garrysmod". + /// + public string ModDir = "unset"; + + /// + /// The game description. Setting this to the full name of your game is recommended. + /// + public string GameDescription = "unset"; + + + public ServerInit( string modDir, string gameDesc ) + { + ModDir = modDir; + GameDescription = gameDesc; + } + + /// + /// Set the Steam quert port + /// + public ServerInit RandomSteamPort() + { + SteamPort = (ushort)new Random().Next( 10000, 60000 ); + return this; + } + + /// + /// If you pass MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE into usQueryPort, then it causes the game server API to use + /// "GameSocketShare" mode, which means that the game is responsible for sending and receiving UDP packets for the master + /// server updater. + /// + /// More info about this here: https://partner.steamgames.com/doc/api/ISteamGameServer#HandleIncomingPacket + /// + public ServerInit QueryShareGamePort() + { + QueryPort = 0xFFFF; + return this; + } + } +}