mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2024-12-25 06:05:46 +03:00
GameServer boilerplate
This commit is contained in:
parent
c954ec0ffe
commit
458355b546
@ -4,6 +4,8 @@
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[DeploymentItem( "FacepunchSteamworksApi.dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
[TestClass]
|
||||
public class Friends
|
||||
{
|
||||
|
@ -92,6 +92,7 @@
|
||||
<Compile Include="Client\Networking.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Client\Friends.cs" />
|
||||
<Compile Include="Server\Server.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.csproj">
|
||||
|
23
Facepunch.Steamworks.Test/Server/Server.cs
Normal file
23
Facepunch.Steamworks.Test/Server/Server.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[DeploymentItem( "FacepunchSteamworksApi.dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
[DeploymentItem( "tier0_s.dll" )]
|
||||
[DeploymentItem( "vstdlib_s.dll" )]
|
||||
[DeploymentItem( "steamclient.dll" )]
|
||||
[TestClass]
|
||||
public class Server
|
||||
{
|
||||
[TestMethod]
|
||||
public void Init()
|
||||
{
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 20216, 20816, 20817, false, "VersionString" ) )
|
||||
{
|
||||
Assert.IsTrue( server.Valid );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
Facepunch.Steamworks.Test/bin/Debug/steam_api.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/steam_api.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/steamclient.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/steamclient.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/tier0_s.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/tier0_s.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/vstdlib_s.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/vstdlib_s.dll
Normal file
Binary file not shown.
@ -7,8 +7,6 @@ namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
|
||||
|
||||
internal class Internal : IDisposable
|
||||
{
|
||||
private uint _hpipe;
|
||||
|
@ -131,8 +131,11 @@
|
||||
<Compile Include="Interop\ServerRules.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Interop\steam_api_interop.cs" />
|
||||
<Compile Include="Server.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Server\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
@ -15,6 +15,28 @@ namespace Valve.Interop
|
||||
|
||||
internal class NativeEntrypoints
|
||||
{
|
||||
internal class Extended
|
||||
{
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern bool SteamInternal_GameServer_Init( uint unIP, ushort usSteamPort, ushort usGamePort, ushort usQueryPort, int eServerMode, string pchVersionString );
|
||||
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr SteamInternal_CreateInterface( string ver );
|
||||
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern uint SteamGameServer_GetHSteamUser();
|
||||
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern uint SteamGameServer_GetHSteamPipe();
|
||||
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern void SteamGameServer_Shutdown();
|
||||
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern void SteamGameServer_RunCallbacks();
|
||||
|
||||
}
|
||||
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SteamAPI_ISteamClient_CreateSteamPipe" )]
|
||||
internal static extern uint SteamAPI_ISteamClient_CreateSteamPipe( IntPtr instancePtr );
|
||||
[DllImportAttribute( "FacepunchSteamworksApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SteamAPI_ISteamClient_BReleaseSteamPipe" )]
|
||||
@ -2416,7 +2438,7 @@ internal override ISteamGameServer GetISteamGameServer( uint hSteamUser, uint hS
|
||||
{
|
||||
CheckIfUsable();
|
||||
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamGameServer(m_pSteamClient,hSteamUser,hSteamPipe,pchVersion);
|
||||
return (ISteamGameServer)Marshal.PtrToStructure( result, typeof( ISteamGameServer ) );
|
||||
return new CSteamGameServer( result );
|
||||
}
|
||||
internal override void SetLocalIPBinding( uint unIP, char usPort )
|
||||
{
|
||||
@ -2463,7 +2485,7 @@ internal override ISteamGameServerStats GetISteamGameServerStats( uint hSteamuse
|
||||
{
|
||||
CheckIfUsable();
|
||||
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamGameServerStats(m_pSteamClient,hSteamuser,hSteamPipe,pchVersion);
|
||||
return (ISteamGameServerStats)Marshal.PtrToStructure( result, typeof( ISteamGameServerStats ) );
|
||||
return new CSteamGameServerStats( result );
|
||||
}
|
||||
internal override ISteamApps GetISteamApps( uint hSteamUser, uint hSteamPipe, string pchVersion )
|
||||
{
|
||||
@ -2510,7 +2532,7 @@ internal override ISteamHTTP GetISteamHTTP( uint hSteamuser, uint hSteamPipe, st
|
||||
{
|
||||
CheckIfUsable();
|
||||
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamHTTP(m_pSteamClient,hSteamuser,hSteamPipe,pchVersion);
|
||||
return (ISteamHTTP)Marshal.PtrToStructure( result, typeof( ISteamHTTP ) );
|
||||
return new CSteamHTTP( result );
|
||||
}
|
||||
internal override ISteamUnifiedMessages GetISteamUnifiedMessages( uint hSteamuser, uint hSteamPipe, string pchVersion )
|
||||
{
|
||||
@ -2528,7 +2550,7 @@ internal override ISteamUGC GetISteamUGC( uint hSteamUser, uint hSteamPipe, stri
|
||||
{
|
||||
CheckIfUsable();
|
||||
IntPtr result = NativeEntrypoints.SteamAPI_ISteamClient_GetISteamUGC(m_pSteamClient,hSteamUser,hSteamPipe,pchVersion);
|
||||
return (ISteamUGC)Marshal.PtrToStructure( result, typeof( ISteamUGC ) );
|
||||
return new CSteamUGC( result );
|
||||
}
|
||||
internal override ISteamAppList GetISteamAppList( uint hSteamUser, uint hSteamPipe, string pchVersion )
|
||||
{
|
||||
|
239
Facepunch.Steamworks/Server.cs
Normal file
239
Facepunch.Steamworks/Server.cs
Normal file
@ -0,0 +1,239 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Server : IDisposable
|
||||
{
|
||||
internal class Internal : IDisposable
|
||||
{
|
||||
internal Valve.Steamworks.ISteamClient client;
|
||||
internal Valve.Steamworks.ISteamGameServer gameServer;
|
||||
internal Valve.Steamworks.ISteamUtils utils;
|
||||
internal Valve.Steamworks.ISteamNetworking networking;
|
||||
internal Valve.Steamworks.ISteamGameServerStats stats;
|
||||
internal Valve.Steamworks.ISteamHTTP http;
|
||||
internal Valve.Steamworks.ISteamInventory inventory;
|
||||
internal Valve.Steamworks.ISteamUGC ugc;
|
||||
internal Valve.Steamworks.ISteamApps apps;
|
||||
|
||||
internal bool Init()
|
||||
{
|
||||
var user = Valve.Interop.NativeEntrypoints.Extended.SteamGameServer_GetHSteamUser();
|
||||
var pipe = Valve.Interop.NativeEntrypoints.Extended.SteamGameServer_GetHSteamPipe();
|
||||
if ( pipe == 0 )
|
||||
return false;
|
||||
|
||||
var clientPtr = Valve.Interop.NativeEntrypoints.Extended.SteamInternal_CreateInterface( "SteamClient017" );
|
||||
if ( clientPtr == IntPtr.Zero )
|
||||
{
|
||||
throw new System.Exception( "Steam Server: Couldn't load SteamClient017" );
|
||||
}
|
||||
|
||||
client = new Valve.Steamworks.CSteamClient( clientPtr );
|
||||
|
||||
|
||||
gameServer = client.GetISteamGameServer( user, pipe, "SteamGameServer012" );
|
||||
|
||||
if ( gameServer.GetIntPtr() == IntPtr.Zero )
|
||||
{
|
||||
gameServer = null;
|
||||
throw new System.Exception( "Steam Server: Couldn't load SteamGameServer012" );
|
||||
}
|
||||
|
||||
utils = client.GetISteamUtils( pipe, "SteamUtils008" );
|
||||
networking = client.GetISteamNetworking( user, pipe, "SteamNetworking005" );
|
||||
stats = client.GetISteamGameServerStats( user, pipe, "SteamGameServerStats001" );
|
||||
http = client.GetISteamHTTP( user, pipe, "STEAMHTTP_INTERFACE_VERSION002" );
|
||||
inventory = client.GetISteamInventory( user, pipe, "STEAMINVENTORY_INTERFACE_V001" );
|
||||
ugc = client.GetISteamUGC( user, pipe, "STEAMUGC_INTERFACE_VERSION008" );
|
||||
|
||||
if ( ugc.GetIntPtr() == IntPtr.Zero )
|
||||
throw new System.Exception( "Steam Server: Couldn't load STEAMUGC_INTERFACE_VERSION008" );
|
||||
|
||||
apps = client.GetISteamApps( user, pipe, "STEAMAPPS_INTERFACE_VERSION008" );
|
||||
|
||||
if ( apps.GetIntPtr() == IntPtr.Zero )
|
||||
throw new System.Exception( "Steam Server: Couldn't load STEAMAPPS_INTERFACE_VERSION008" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if ( client != null )
|
||||
{
|
||||
client.BShutdownIfAllPipesClosed();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal Internal native;
|
||||
|
||||
/// <summary>
|
||||
/// Current running program's AppId
|
||||
/// </summary>
|
||||
public uint AppId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current user's Username
|
||||
/// </summary>
|
||||
public string Username { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current user's SteamId
|
||||
/// </summary>
|
||||
public ulong SteamId { get; private set; }
|
||||
|
||||
public enum MessageType : int
|
||||
{
|
||||
Message = 0,
|
||||
Warning = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called with a message from Steam
|
||||
/// </summary>
|
||||
public Action<MessageType, string> OnMessage;
|
||||
|
||||
public Server( uint appId, uint IpAddress, ushort SteamPort, ushort GamePort, ushort QueryPort, bool Secure, string VersionString )
|
||||
{
|
||||
if ( !Valve.Interop.NativeEntrypoints.Extended.SteamInternal_GameServer_Init( IpAddress, SteamPort, GamePort, QueryPort, Secure ? 3 : 2 , VersionString ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Valve.Steamworks.SteamAPI.Init( appId );
|
||||
|
||||
native = new Internal();
|
||||
|
||||
//
|
||||
// Get other interfaces
|
||||
//
|
||||
if ( !native.Init() )
|
||||
{
|
||||
native.Dispose();
|
||||
native = null;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set up warning hook callback
|
||||
//
|
||||
SteamAPIWarningMessageHook ptr = InternalOnWarning;
|
||||
// native.client.SetWarningMessageHook( Marshal.GetFunctionPointerForDelegate( ptr ) );
|
||||
|
||||
//
|
||||
// Cache common, unchanging info
|
||||
//
|
||||
AppId = appId;
|
||||
|
||||
//
|
||||
// Initial settings
|
||||
//
|
||||
native.gameServer.EnableHeartbeats( true );
|
||||
MaxPlayers = 32;
|
||||
BotCount = 0;
|
||||
MapName = "unset";
|
||||
|
||||
//
|
||||
// Run update, first call does some initialization
|
||||
//
|
||||
Update();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if ( native != null)
|
||||
{
|
||||
native.Dispose();
|
||||
native = null;
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
|
||||
public delegate void SteamAPIWarningMessageHook( int nSeverity, System.Text.StringBuilder pchDebugText );
|
||||
|
||||
private void InternalOnWarning( int nSeverity, System.Text.StringBuilder text )
|
||||
{
|
||||
if ( OnMessage != null )
|
||||
{
|
||||
OnMessage( ( MessageType)nSeverity, text.ToString() );
|
||||
}
|
||||
}
|
||||
|
||||
internal event Action OnUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// Should be called at least once every frame
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
if ( native == null )
|
||||
return;
|
||||
|
||||
Valve.Interop.NativeEntrypoints.Extended.SteamGameServer_RunCallbacks();
|
||||
// Voice.Update();
|
||||
// Inventory.Update();
|
||||
// Networking.Update();
|
||||
|
||||
if ( OnUpdate != null )
|
||||
OnUpdate();
|
||||
}
|
||||
|
||||
public bool Valid
|
||||
{
|
||||
get { return native != null; }
|
||||
}
|
||||
|
||||
internal Action InstallCallback( int type, Delegate action )
|
||||
{
|
||||
var del = Marshal.GetFunctionPointerForDelegate( action );
|
||||
|
||||
// var ptr = Marshal.GetFunctionPointerForDelegate( action );
|
||||
// Valve.Steamworks.SteamAPI.RegisterCallback( del, type );
|
||||
|
||||
// Valve.Steamworks.SteamAPI.UnregisterCallback( del );
|
||||
|
||||
//return () => Valve.Steamworks.SteamAPI.UnregisterCallback( ptr );
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current MaxPlayers.
|
||||
/// This doesn't enforce any kind of limit, it just updates the master server.
|
||||
/// </summary>
|
||||
public int MaxPlayers
|
||||
{
|
||||
get { return _maxplayers; }
|
||||
set { if ( _maxplayers == value ) return; native.gameServer.SetMaxPlayerCount( value ); _maxplayers = value; }
|
||||
}
|
||||
private int _maxplayers = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current BotCount.
|
||||
/// This doesn't enforce any kind of limit, it just updates the master server.
|
||||
/// </summary>
|
||||
public int BotCount
|
||||
{
|
||||
get { return _botcount; }
|
||||
set { if ( _botcount == value ) return; native.gameServer.SetBotPlayerCount( value ); _botcount = value; }
|
||||
}
|
||||
private int _botcount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current Map Name.
|
||||
/// </summary>
|
||||
public string MapName
|
||||
{
|
||||
get { return _mapname; }
|
||||
set { if ( _mapname == value ) return; native.gameServer.SetMapName( value ); _mapname = value; }
|
||||
}
|
||||
private string _mapname;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user