@ -3,6 +3,8 @@ using AxibugEmuOnline.Server.Manager;
using AxibugEmuOnline.Server.NetWork ;
using AxibugProtobuf ;
using MySql.Data.MySqlClient ;
using Org.BouncyCastle.Crypto.Parameters ;
using System.Data ;
using System.Net.Sockets ;
using System.Runtime.InteropServices ;
using System.Security.Policy ;
@ -25,6 +27,7 @@ namespace AxibugEmuOnline.Server
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomCreate , OnCmdRoomCreate ) ;
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomJoin , OnCmdRoomJoin ) ;
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomLeave , OnCmdRoomLeave ) ;
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomChangePlayerWithJoy , OnCmdRoomChangePlayerWithJoy ) ;
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomHostPlayerUpdateStateRaw , OnHostPlayerUpdateStateRaw ) ;
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomPlayerReady , OnRoomPlayerReady ) ;
NetMsg . Instance . RegNetMsgEvent ( ( int ) CommandID . CmdRoomSingelPlayerInput , OnSingelPlayerInput ) ;
@ -148,23 +151,21 @@ namespace AxibugEmuOnline.Server
HostPlayerUID = room . HostUID ,
GameState = room . GameState ,
ObsUserCount = 0 , //TODO
Player1UID = room . Player1_UID ,
Player2UID = room . Player2_UID ,
Player3UID = room . Player3_UID ,
Player4UID = room . Player4_UID ,
} ;
if ( result . Player1UID > = 0 & & AppSrv . g_ClientMgr . GetClientByUID ( result . Player1UID , out ClientInfo _c1 ) )
result . Player1NickName = _c1 . NickName ;
if ( result . Player2UID > = 0 & & AppSrv . g_ClientMgr . GetClientByUID ( result . Player2UID , out ClientInfo _c2 ) )
result . Player2NickName = _c2 . NickName ;
if ( result . Player3UID > = 0 & & AppSrv . g_ClientMgr . GetClientByUID ( result . Player1UID , out ClientInfo _c3 ) )
result . Player3NickName = _c3 . NickName ;
if ( result . Player4UID > = 0 & & AppSrv . g_ClientMgr . GetClientByUID ( result . Player2UID , out ClientInfo _c4 ) )
result . Player4NickName = _c4 . NickName ;
for ( byte i = 0 ; i < room . PlayerSlot . Count ( ) ; i + + )
{
Protobuf_Room_GamePlaySlot pbSlot = new Protobuf_Room_GamePlaySlot ( ) ;
Data_RoomSlot slot = room . PlayerSlot [ i ] ;
if ( slot . UID > 0 )
{
pbSlot . PlayerUID = slot . UID ;
pbSlot . PlayerLocalJoyIdx = ( int ) slot . LocalJoyIdx ;
if ( AppSrv . g_ClientMgr . GetClientByUID ( pbSlot . PlayerUID , out ClientInfo _client ) )
pbSlot . PlayerNickName = _client . NickName ;
}
result . GamePlaySlotList . Add ( pbSlot ) ;
}
return result ;
}
@ -234,7 +235,7 @@ namespace AxibugEmuOnline.Server
AddRoom ( newRoom ) ;
ErrorCode joinErrcode = ErrorCode . ErrorOk ;
//加入
if ( newRoom . Join ( msg . JoinPlayer Idx, _c , out joinErrcode , out bool bHadRoomStateChange ) )
if ( newRoom . Join ( ( uint ) msg . PlayerSlotIdx , ( uint ) msg . PlayerLocalJoy Idx, _c , out joinErrcode , out bool bHadRoomStateChange ) )
{
//创建成功下行
resp . RoomMiniInfo = GetProtoDataRoom ( newRoom ) ;
@ -254,7 +255,7 @@ namespace AxibugEmuOnline.Server
AppSrv . g_Log . DebugCmd ( $"OnCmdRoomJoin" ) ;
ClientInfo _c = AppSrv . g_ClientMgr . GetClientForSocket ( sk ) ;
Protobuf_Room_Join msg = ProtoBufHelper . DeSerizlize < Protobuf_Room_Join > ( reqData ) ;
Protobuf_Room_Create_RESP resp = new Protobuf_Room_Create _RESP( ) ;
Protobuf_Room_Join_RESP resp = new Protobuf_Room_Join _RESP( ) ;
ErrorCode joinErrcode ;
Data_RoomData room = GetRoomData ( msg . RoomID ) ;
bool bHadRoomStateChange = false ;
@ -268,7 +269,7 @@ namespace AxibugEmuOnline.Server
lock ( room )
{
//加入
if ( room . Join ( msg . PlayerNum , _c , out joinErrcode , out bHadRoomStateChange ) )
if ( room . Join ( ( uint ) msg . PlayerSlotIdx , ( uint ) msg . PlayerLocalJoyIdx , _c , out joinErrcode , out bHadRoomStateChange ) )
{
Data_RoomData roomData = GetRoomData ( msg . RoomID ) ;
resp . RoomMiniInfo = GetProtoDataRoom ( roomData ) ;
@ -316,7 +317,6 @@ namespace AxibugEmuOnline.Server
//if (room.GetPlayerCount() < 1)
// RemoveRoom(room.RoomID);
}
public void LeaveRoom ( ClientInfo _c , int RoomID )
{
AppSrv . g_Log . Debug ( $"LeaveRoom" ) ;
@ -354,6 +354,40 @@ namespace AxibugEmuOnline.Server
RoomLog ( _c . UID , 1 , room . RoomID , room . GameRomID , RoomLogType . Leave ) ;
}
public void OnCmdRoomChangePlayerWithJoy ( Socket sk , byte [ ] reqData )
{
AppSrv . g_Log . DebugCmd ( $"OnCmdRoomChangePlayerjoySlot" ) ;
ClientInfo _c = AppSrv . g_ClientMgr . GetClientForSocket ( sk ) ;
Protobuf_Room_Change_PlaySlotWithJoy msg = ProtoBufHelper . DeSerizlize < Protobuf_Room_Change_PlaySlotWithJoy > ( reqData ) ;
Protobuf_Room_Change_PlaySlotWithJoy_RESP resp = new Protobuf_Room_Change_PlaySlotWithJoy_RESP ( ) ;
ErrorCode errcode = ErrorCode . ErrorOk ;
Data_RoomData room = GetRoomData ( _c . RoomState . RoomID ) ;
if ( room = = null )
errcode = ErrorCode . ErrorRoomNotFound ;
if ( errcode = = ErrorCode . ErrorOk )
{
Dictionary < uint , uint > newSlotIdx2JoyIdx = new Dictionary < uint , uint > ( ) ;
foreach ( var slotinfo in msg . SlotWithJoy )
{
//如果有任意一个槽位有人
if ( room . GetPlayerUIDByIdx ( ( uint ) slotinfo . PlayerSlotIdx , out long UID ) )
{
//且人不是自己,则不允许换位
if ( UID ! = _c . UID )
errcode = ErrorCode . ErrorRoomSlotAlreadlyHadPlayer ; break ;
}
newSlotIdx2JoyIdx [ ( uint ) slotinfo . PlayerSlotIdx ] = ( uint ) slotinfo . PlayerLocalJoyIdx ;
}
room . SetPlayerSlotData ( _c , ref newSlotIdx2JoyIdx ) ;
}
AppSrv . g_ClientMgr . ClientSend ( _c , ( int ) CommandID . CmdRoomMyRoomStateChanged , ( int ) errcode , ProtoBufHelper . Serizlize ( resp ) ) ;
}
public void OnHostPlayerUpdateStateRaw ( Socket sk , byte [ ] reqData )
{
ClientInfo _c = AppSrv . g_ClientMgr . GetClientForSocket ( sk ) ;
@ -388,8 +422,8 @@ namespace AxibugEmuOnline.Server
return ;
lock ( room )
{
AppSrv . g_Log . Debug ( $"SetRePlayerReady RoomID->{room.RoomID},UID->{_c.UID }, PlayerIdx->{_c.RoomState.PlayerIdx }") ;
room . SetRePlayerReady ( _c . RoomState . PlayerIdx , out errcode , out bool bHadRoomStateChange ) ;
AppSrv . g_Log . Debug ( $"SetRePlayerReady RoomID->{room.RoomID},UID->{_c.UID }") ;
room . SetRePlayerReady ( _c . UID , out errcode , out bool bHadRoomStateChange ) ;
if ( bHadRoomStateChange )
{
SendRoomStepChange ( room ) ;
@ -422,7 +456,7 @@ namespace AxibugEmuOnline.Server
// room.SynInputData();
//推帧过程中,最后一帧才写入操作
room . SetPlayerInput ( _c . RoomState . PlayerIdx , msg . FrameID , temp ) ;
room . SetPlayerInput ( _c . UID , msg . FrameID , temp ) ;
}
//推帧
room . TakeFrame ( ) ;
@ -431,7 +465,7 @@ namespace AxibugEmuOnline.Server
else //不需要推帧
{
//虽然不推帧, 但是存入Input
room . SetPlayerInput ( _c . RoomState . PlayerIdx , msg . FrameID , temp ) ;
room . SetPlayerInput ( _c . UID , msg . FrameID , temp ) ;
}
if ( room . LastTestRecv ! = room . mCurrInputData . all )
@ -550,13 +584,14 @@ namespace AxibugEmuOnline.Server
public string RomHash { get ; private set ; }
public long HostUID { get ; private set ; }
public long ScreenProviderUID { get ; private set ; }
public long Player1_UID { get ; private set ; }
public long Player2_UID { get ; private set ; }
public long Player3_UID { get ; private set ; }
public long Player4_UID { get ; private set ; }
public Data_RoomSlot [ ] PlayerSlot ;
public long Player1_UID = > PlayerSlot [ 0 ] . UID ;
public long Player2_UID = > PlayerSlot [ 1 ] . UID ;
public long Player3_UID = > PlayerSlot [ 2 ] . UID ;
public long Player4_UID = > PlayerSlot [ 3 ] . UID ;
public Google . Protobuf . ByteString ? NextStateRaw { get ; private set ; }
public Google . Protobuf . ByteString ? ScreenRaw { get ; private set ; }
public bool [ ] PlayerReadyState { get ; private set ; }
//public bool[] PlayerReadyState { get; private set; }
public List < long > SynUIDs ;
//public RoomPlayerState PlayerState => getPlayerState();
private RoomGameState mGameState ;
@ -580,7 +615,7 @@ namespace AxibugEmuOnline.Server
NextStateRaw = null ;
break ;
case RoomGameState . WaitReady :
Array . Fill < bool > ( PlayerReadyState , false ) ;
ClearAllSlotReadyState ( ) ; //清理玩家所有准备状态
break ;
}
}
@ -590,23 +625,6 @@ namespace AxibugEmuOnline.Server
/// 服务器提前帧数
/// </summary>
public uint SrvForwardFrames { get ; set ; }
bool IsAllReady ( )
{
bool Ready = true ;
if (
( Player1_UID > 0 & & ! PlayerReadyState [ 0 ] )
| |
( Player2_UID > 0 & & ! PlayerReadyState [ 1 ] )
| |
( Player3_UID > 0 & & ! PlayerReadyState [ 2 ] )
| |
( Player4_UID > 0 & & ! PlayerReadyState [ 3 ] )
)
{
Ready = false ;
}
return Ready ;
}
public void Init ( int roomID , int gameRomID , string roomHash , long hostUId , bool bloadState = false )
{
RoomID = roomID ;
@ -614,54 +632,193 @@ namespace AxibugEmuOnline.Server
RomHash = roomHash ;
HostUID = hostUId ;
ScreenProviderUID = hostUId ;
Player1_UID = - 1 ;
Player2_UID = - 1 ;
Player3_UID = - 1 ;
Player4_UID = - 1 ;
PlayerReadyState = new bool [ 4 ] ;
if ( PlayerSlot = = null )
PlayerSlot = new Data_RoomSlot [ 4 ] ;
for ( uint i = 0 ; i < PlayerSlot . Length ; i + + )
PlayerSlot [ i ] . Init ( i ) ;
//PlayerReadyState = new bool[4];
SynUIDs = new List < long > ( ) ; //广播角色列表
GameState = RoomGameState . NoneGameState ;
mCurrInputData = new ServerInputSnapShot ( ) ;
mInputQueue = new Queue < ( uint , ServerInputSnapShot ) > ( ) ;
mDictPlayerIdx2SendQueue = new Dictionary < int , Queue < byte [ ] > > ( ) ;
}
public void SetPlayerUID ( int PlayerIdx , ClientInfo _c )
public Dictionary < uint , uint > GetSlotDataByUID ( long uid )
{
long oldUID = - 1 ;
switch ( PlayerIdx )
{
case 0 : oldUID = Player1_UID ; Player1_UID = _c . UID ; break ;
case 1 : oldUID = Player2_UID ; Player2_UID = _c . UID ; break ;
case 2 : oldUID = Player3_UID ; Player3_UID = _c . UID ; break ;
case 3 : oldUID = Player4_UID ; Player4_UID = _c . UID ; break ;
Dictionary < uint , uint > slotIdx2JoyIdx = new Dictionary < uint , uint > ( ) ;
var dataarr = PlayerSlot . Where ( w = > w . UID = = uid ) . ToArray ( ) ;
foreach ( var slot in dataarr )
slotIdx2JoyIdx [ slot . SlotIdx ] = slot . LocalJoyIdx ;
return slotIdx2JoyIdx ;
}
if ( oldUID > = 0 )
SynUIDs . Remove ( oldUID ) ;
SynUIDs . Add ( _c . UID ) ;
AppSrv . g_Log . Debug ( $"SetPlayerUID RoomID->{RoomID} _c.UID->{_c.UID} PlayerIdx->{PlayerIdx}" ) ;
_c . RoomState . SetRoomData ( this . RoomID , PlayerIdx ) ;
/// <summary>
/// 按照SlotIdx设置Input
/// </summary>
/// <param name="slotIdx"></param>
void SetInputDataBySlotIdx ( uint slotIdx , byte val )
{
switch ( slotIdx )
{
case 0 : mCurrInputData . p1_byte = val ; break ;
case 1 : mCurrInputData . p2_byte = val ; break ;
case 2 : mCurrInputData . p3_byte = val ; break ;
case 4 : mCurrInputData . p3_byte = val ; break ;
}
}
/// <summary>
/// 按照UID清理SlotData
/// </summary>
/// <param name="uid"></param>
void ClearSlotDataByUid ( long uid )
{
var dataarr = PlayerSlot . Where ( w = > w . UID = = uid ) . ToArray ( ) ;
foreach ( var slot in dataarr )
{
dataarr [ slot . SlotIdx ] . Init ( slot . SlotIdx ) ;
ClearInputDataBySlotIdx ( slot . SlotIdx ) ;
}
}
/// <summary>
/// 按照SlotIdx清理SlotData
/// </summary>
/// <param name="slotIdx"></param>
void ClearSlotDataBySlotIdx ( uint slotIdx )
{
PlayerSlot [ slotIdx ] . Init ( slotIdx ) ;
ClearInputDataBySlotIdx ( slotIdx ) ;
}
/// <summary>
/// 按照SlotIdx清理Input
/// </summary>
/// <param name="slotIdx"></param>
void ClearInputDataBySlotIdx ( uint slotIdx )
{
switch ( slotIdx )
{
case 0 : mCurrInputData . p1_byte = 0 ; break ;
case 1 : mCurrInputData . p2_byte = 0 ; break ;
case 2 : mCurrInputData . p3_byte = 0 ; break ;
case 4 : mCurrInputData . p3_byte = 0 ; break ;
}
}
/// <summary>
/// 更新同步名单
/// </summary>
void UpdateSynUIDs ( )
{
for ( int i = SynUIDs . Count - 1 ; i > = 0 ; i - - )
{
long uid = SynUIDs [ i ] ;
bool bHad = false ;
if ( Player1_UID = = uid ) bHad = true ;
else if ( Player2_UID = = uid ) bHad = true ;
else if ( Player3_UID = = uid ) bHad = true ;
else if ( Player4_UID = = uid ) bHad = true ;
if ( bHad )
SynUIDs . RemoveAt ( i ) ;
}
if ( ! SynUIDs . Contains ( Player1_UID ) ) SynUIDs . Add ( Player1_UID ) ;
if ( ! SynUIDs . Contains ( Player2_UID ) ) SynUIDs . Add ( Player2_UID ) ;
if ( ! SynUIDs . Contains ( Player3_UID ) ) SynUIDs . Add ( Player3_UID ) ;
if ( ! SynUIDs . Contains ( Player4_UID ) ) SynUIDs . Add ( Player4_UID ) ;
}
#region 准 备 状 态 管 理
bool IsAllReady ( )
{
bool Ready = true ;
if (
( Player1_UID > 0 & & ! PlayerSlot [ 0 ] . Ready )
| |
( Player2_UID > 0 & & ! PlayerSlot [ 1 ] . Ready )
| |
( Player3_UID > 0 & & ! PlayerSlot [ 2 ] . Ready )
| |
( Player4_UID > 0 & & ! PlayerSlot [ 3 ] . Ready )
)
{
Ready = false ;
}
return Ready ;
}
/// <summary>
/// 清除所有槽位准备状态
/// </summary>
void ClearAllSlotReadyState ( )
{
for ( var i = 0 ; i < PlayerSlot . Length ; i + + )
{
PlayerSlot [ i ] . Ready = false ;
}
}
/// <summary>
/// 按照UID设置Ready信息
/// </summary>
/// <param name="uid"></param>
void SetReadyByUid ( long uid )
{
for ( var i = 0 ; i < PlayerSlot . Length ; i + + )
{
if ( PlayerSlot [ i ] . UID = = uid )
PlayerSlot [ i ] . Ready = true ;
}
}
#endregion
public void SetPlayerSlotData ( ClientInfo _c , ref readonly Dictionary < uint , uint > newSlotIdx2JoyIdx )
{
Dictionary < uint , uint > oldSlotIdx2JoyIdx = GetSlotDataByUID ( _c . UID ) ;
HashSet < uint > diffSlotIdxs = new HashSet < uint > ( ) ;
foreach ( var old in oldSlotIdx2JoyIdx )
{
uint old_slotIdx = old . Key ;
//如果旧位置已经不存在于新位置, 则需要算作diff
if ( ! newSlotIdx2JoyIdx . ContainsKey ( old_slotIdx ) )
{
diffSlotIdxs . Add ( old_slotIdx ) ; continue ;
}
uint old_slotjoyIdx = old . Value ;
//如果旧位置不变, 但客户端本地JoyIdx变化则算作diff
if ( old_slotjoyIdx ! = newSlotIdx2JoyIdx [ old_slotIdx ] )
{
diffSlotIdxs . Add ( old_slotIdx ) ; continue ;
}
}
//如果是在旧数据中不存在的位置, 则算作diff
foreach ( var newdata in newSlotIdx2JoyIdx )
{
uint new_slotIdx = newdata . Key ;
if ( ! oldSlotIdx2JoyIdx . ContainsKey ( new_slotIdx ) )
{
diffSlotIdxs . Add ( new_slotIdx ) ; continue ;
}
}
//必要的diff slot 清理键值数据
foreach ( var diffSlotIdx in diffSlotIdxs )
{
ClearSlotDataBySlotIdx ( diffSlotIdx ) ;
}
//设置新的槽位
foreach ( var slotdata in newSlotIdx2JoyIdx )
{
PlayerSlot [ slotdata . Key ] . LocalJoyIdx = slotdata . Value ;
AppSrv . g_Log . Debug ( $"SetPlayerUID RoomID->{RoomID} _c.UID->{_c.UID} PlayerSlotIdx->{slotdata.Key} LocalJoyIdx->{slotdata.Value}" ) ;
}
//更新需要同步的UID
UpdateSynUIDs ( ) ;
_c . RoomState . SetRoomData ( this . RoomID ) ;
}
public void RemovePlayer ( ClientInfo _c )
{
int PlayerIdx = GetPlayerIdx ( _c ) ;
switch ( PlayerIdx )
{
case 0 : Player1_UID = - 1 ; SynUIDs . Remove ( _c . UID ) ; break ;
case 1 : Player2_UID = - 1 ; SynUIDs . Remove ( _c . UID ) ; break ;
case 2 : Player3_UID = - 1 ; SynUIDs . Remove ( _c . UID ) ; break ;
case 3 : Player4_UID = - 1 ; SynUIDs . Remove ( _c . UID ) ; break ;
}
ClearSlotDataByUid ( _c . UID ) ;
UpdateSynUIDs ( ) ;
_c . RoomState . ClearRoomData ( ) ;
}
int GetPlayerIdx ( ClientInfo _c )
{
if ( Player1_UID = = _c . UID ) return 0 ;
if ( Player2_UID = = _c . UID ) return 1 ;
if ( Player3_UID = = _c . UID ) return 2 ;
if ( Player4_UID = = _c . UID ) return 3 ;
return - 1 ;
}
public bool GetPlayerUIDByIdx ( int Idx , out long UID )
public bool GetPlayerUIDByIdx ( uint Idx , out long UID )
{
switch ( Idx )
{
@ -673,7 +830,7 @@ namespace AxibugEmuOnline.Server
}
return UID > 0 ;
}
public bool GetPlayerClientByIdx ( int Idx , out ClientInfo _c )
public bool GetPlayerClientByIdx ( u int Idx , out ClientInfo _c )
{
_c = null ;
if ( ! GetPlayerUIDByIdx ( Idx , out long UID ) )
@ -684,61 +841,50 @@ namespace AxibugEmuOnline.Server
return true ;
}
public List < long > GetAllPlayerUIDs ( )
{
List < long > list = new List < long > ( ) ;
if ( Player1_UID > 0 ) list . Add ( Player1_UID ) ;
if ( Player2_UID > 0 ) list . Add ( Player2_UID ) ;
if ( Player3_UID > 0 ) list . Add ( Player3_UID ) ;
if ( Player4_UID > 0 ) list . Add ( Player4_UID ) ;
return list ;
}
public List < ClientInfo > GetAllPlayerClientList ( )
{
List < ClientInfo > list = new List < ClientInfo > ( ) ;
List < long > Uids = GetAllPlayerUIDs ( ) ;
List < long > Uids = SynUIDs ;
foreach ( long uid in Uids )
{
if ( ! AppSrv . g_ClientMgr . GetClientByUID ( uid , out ClientInfo _c , true ) )
continue ;
list . Add ( _c ) ;
}
return list ;
}
public void SetPlayerInput ( int PlayerIdx , long mFrameID , ServerInputSnapShot allinput )
void SetInputBySlotIdxJoyIdx ( uint SlotIdx , uint LocalJoyIdx , ServerInputSnapShot clieninput )
{
switch ( Player Idx)
switch ( LocalJoy Idx)
{
case 0 : mCurrInputData . p1_byte = allinput . p1_byte ; break ;
case 1 : mCurrInputData . p2_byte = allinput . p1_byte ; break ;
case 2 : mCurrInputData . p3_byte = allinput . p1_byte ; break ;
case 3 : mCurrInputData . p4_byte = allinput . p1_byte ; break ;
}
}
public void ClearPlayerInput ( ClientInfo _c )
{
int PlayerIdx = GetPlayerIdx ( _c ) ;
switch ( PlayerIdx )
{
case 0 : mCurrInputData . p1_byte = 0 ; break ;
case 1 : mCurrInputData . p2_byte = 0 ; break ;
case 2 : mCurrInputData . p3_byte = 0 ; break ;
case 3 : mCurrInputData . p4_byte = 0 ; break ;
case 0 : SetInputDataBySlotIdx ( SlotIdx , clieninput . p1_byte ) ; break ;
case 1 : SetInputDataBySlotIdx ( SlotIdx , clieninput . p2_byte ) ; break ;
case 2 : SetInputDataBySlotIdx ( SlotIdx , clieninput . p3_byte ) ; break ;
case 3 : SetInputDataBySlotIdx ( SlotIdx , clieninput . p4_byte ) ; break ;
}
}
public int GetPlayerCount ( )
{
int count = 0 ;
if ( Player1_UID > 0 ) count + + ;
if ( Player2_UID > 0 ) count + + ;
if ( Player3_UID > 0 ) count + + ;
if ( Player4_UID > 0 ) count + + ;
return count ;
return SynUIDs . Count ;
}
public void UpdateRoomForwardNum ( )
{
List < ClientInfo > playerlist = GetAllPlayerClientList ( ) ;
double maxNetDelay = 0 ;
for ( int i = 0 ; i < playerlist . Count ; i + + )
{
ClientInfo player = playerlist [ i ] ;
maxNetDelay = Math . Max ( maxNetDelay , player . AveNetDelay ) ;
}
float MustTaskFrame = 1 ;
SrvForwardFrames = ( uint ) ( ( maxNetDelay / 0.016f ) + MustTaskFrame ) ;
if ( SrvForwardFrames < 2 )
SrvForwardFrames = 2 ;
//AppSrv.g_Log.Debug($"服务器提前跑帧数: Max(2,({maxNetDelay} / {0.016f}) + {MustTaskFrame}) = {SrvForwardFrames}");
}
#region 帧 相 关
void StartNewTick ( )
{
mInputQueue . Clear ( ) ;
@ -756,23 +902,6 @@ namespace AxibugEmuOnline.Server
TakeFrame ( ) ;
AppSrv . g_Log . Info ( $"房间初始提前量=>{StartForwardFrames},当前延迟提前量=>{SrvForwardFrames}" ) ;
}
public void UpdateRoomForwardNum ( )
{
List < ClientInfo > playerlist = GetAllPlayerClientList ( ) ;
double maxNetDelay = 0 ;
for ( int i = 0 ; i < playerlist . Count ; i + + )
{
ClientInfo player = playerlist [ i ] ;
maxNetDelay = Math . Max ( maxNetDelay , player . AveNetDelay ) ;
}
float MustTaskFrame = 1 ;
SrvForwardFrames = ( uint ) ( ( maxNetDelay / 0.016f ) + MustTaskFrame ) ;
if ( SrvForwardFrames < 2 )
SrvForwardFrames = 2 ;
//AppSrv.g_Log.Debug($"服务器提前跑帧数: Max(2,({maxNetDelay} / {0.016f}) + {MustTaskFrame}) = {SrvForwardFrames}");
}
public void TakeFrame ( )
{
lock ( synInputLock )
@ -785,6 +914,7 @@ namespace AxibugEmuOnline.Server
}
}
}
#endregion
ulong LastTestSend = 0 ;
internal ulong LastTestRecv ;
@ -850,62 +980,6 @@ namespace AxibugEmuOnline.Server
}
}
#region 房 间 进 出
/// <summary>
/// 进入房间
/// </summary>
/// <param name="RoomID"></param>
/// <param name="PlayerNum"></param>
/// <param name="_c"></param>
/// <param name="errcode"></param>
/// <returns></returns>
public bool Join ( int PlayerNum , ClientInfo _c , out ErrorCode errcode , out bool bHadRoomStateChange )
{
bHadRoomStateChange = false ;
int oldPlayerCount = GetPlayerCount ( ) ;
if ( GetPlayerUIDByIdx ( PlayerNum , out long hadUID ) )
{
errcode = ErrorCode . ErrorRoomSlotAlreadlyHadPlayer ;
return false ;
}
AppSrv . g_Log . Debug ( $"Join _c.UID->{_c.UID} RoomID->{RoomID}" ) ;
SetPlayerUID ( PlayerNum , _c ) ;
int newPlayerCount = GetPlayerCount ( ) ;
errcode = ErrorCode . ErrorOk ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
return true ;
}
/// <summary>
/// 离开房间
/// </summary>
/// <param name="RoomID"></param>
/// <param name="_c"></param>
/// <param name="errcode"></param>
/// <returns></returns>
public bool Leave ( ClientInfo _c , out ErrorCode errcode , out bool bHadRoomStateChange )
{
int oldPlayerCount = GetPlayerCount ( ) ;
RemovePlayer ( _c ) ;
ClearPlayerInput ( _c ) ;
int newPlayerCount = GetPlayerCount ( ) ;
errcode = ErrorCode . ErrorOk ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
return true ;
}
#endregion
public bool SetRePlayerReady ( int PlayerIdx , out ErrorCode errcode , out bool bHadRoomStateChange )
{
int oldPlayerCount = GetPlayerCount ( ) ;
PlayerReadyState [ PlayerIdx ] = true ;
int newPlayerCount = GetPlayerCount ( ) ;
errcode = ErrorCode . ErrorOk ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
return true ;
}
bool CheckRoomStateChange ( int oldPlayerCount , int newPlayerCount )
{
bool bChanged = false ;
@ -980,6 +1054,73 @@ namespace AxibugEmuOnline.Server
return bChanged ;
}
#region 对 外 开 放 函 数
#region 房 间 进 出
/// <summary>
/// 进入房间
/// </summary>
/// <param name="RoomID"></param>
/// <param name="PlayerNum"></param>
/// <param name="_c"></param>
/// <param name="errcode"></param>
/// <returns></returns>
public bool Join ( uint slotIdx , uint joyIdx , ClientInfo _c , out ErrorCode errcode , out bool bHadRoomStateChange )
{
bHadRoomStateChange = false ;
int oldPlayerCount = GetPlayerCount ( ) ;
if ( GetPlayerUIDByIdx ( slotIdx , out long hadUID ) )
{
errcode = ErrorCode . ErrorRoomSlotAlreadlyHadPlayer ;
return false ;
}
AppSrv . g_Log . Debug ( $"Join _c.UID->{_c.UID} RoomID->{RoomID}" ) ;
Dictionary < uint , uint > slotInfo = new Dictionary < uint , uint > ( ) ;
slotInfo [ slotIdx ] = joyIdx ;
SetPlayerSlotData ( _c , ref slotInfo ) ;
int newPlayerCount = GetPlayerCount ( ) ;
errcode = ErrorCode . ErrorOk ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
return true ;
}
/// <summary>
/// 离开房间
/// </summary>
/// <param name="RoomID"></param>
/// <param name="_c"></param>
/// <param name="errcode"></param>
/// <returns></returns>
public bool Leave ( ClientInfo _c , out ErrorCode errcode , out bool bHadRoomStateChange )
{
int oldPlayerCount = GetPlayerCount ( ) ;
RemovePlayer ( _c ) ;
int newPlayerCount = GetPlayerCount ( ) ;
errcode = ErrorCode . ErrorOk ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
return true ;
}
#endregion
public void SetPlayerInput ( long UID , uint LocalJoyIdx , ServerInputSnapShot clieninput )
{
for ( uint i = 0 ; i < PlayerSlot . Count ( ) ; i + + )
{
Data_RoomSlot slotData = PlayerSlot [ i ] ;
if ( slotData . UID ! = UID )
continue ;
SetInputBySlotIdxJoyIdx ( slotData . SlotIdx , slotData . LocalJoyIdx , clieninput ) ;
}
}
public bool SetRePlayerReady ( long UID , out ErrorCode errcode , out bool bHadRoomStateChange )
{
int oldPlayerCount = GetPlayerCount ( ) ;
SetReadyByUid ( UID ) ;
int newPlayerCount = GetPlayerCount ( ) ;
errcode = ErrorCode . ErrorOk ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
return true ;
}
public void SetLoadRaw ( Google . Protobuf . ByteString NextStateRaw , out bool bHadRoomStateChange )
{
int oldPlayerCount = GetPlayerCount ( ) ;
@ -988,12 +1129,10 @@ namespace AxibugEmuOnline.Server
int newPlayerCount = GetPlayerCount ( ) ;
bHadRoomStateChange = CheckRoomStateChange ( oldPlayerCount , newPlayerCount ) ;
}
public void InputScreenData ( Google . Protobuf . ByteString screenRaw )
{
this . ScreenRaw = NextStateRaw ;
}
public bool GetNeedForwardTick ( uint clientFrame , out long forwaFrame )
{
forwaFrame = 0 ;
@ -1003,6 +1142,22 @@ namespace AxibugEmuOnline.Server
forwaFrame = targetFrame - mCurrServerFrameId ;
return forwaFrame > 0 ;
}
#endregion
}
public class Data_RoomSlot
{
public uint SlotIdx { get ; set ; }
public long UID { get ; set ; }
public uint LocalJoyIdx { get ; set ; }
public bool Ready = false ;
public void Init ( uint SlotIdx )
{
this . SlotIdx = SlotIdx ;
UID = - 1 ;
LocalJoyIdx = 0 ;
Ready = false ;
}
}
[StructLayout(LayoutKind.Explicit, Size = 8)]