Files
wnmj/Servers/游戏组件/诈金花/游戏服务器/TableFrameSink.cpp
2026-02-13 14:34:15 +08:00

1086 lines
31 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StdAfx.h"
#include "TableFrameSink.h"
const WORD CTableFrameSink::m_wPlayerCount = GAME_PLAYER;
CTableFrameSink::CTableFrameSink()
: m_pITableFrame(nullptr)
, m_pGameServiceOption(nullptr)
{
m_wFirstChairID = INVALID_CHAIR;
m_wBankerUser = INVALID_CHAIR;
m_wCurrentUser = INVALID_CHAIR;
m_wFirstOperateUser = INVALID_CHAIR;
m_lCurChipScore = 0;
m_dwOperateCode = 0;
m_cbCurPlayRound = 0;
m_cbGamingUserCount = 0;
m_cbPlayTimes = 0;
m_cbMasterCtrlType = 0;
m_wMasterChairID = INVALID_CHAIR;
ZeroMemory(m_cbUserResponse, sizeof(m_cbUserResponse));
ZeroMemory(m_cbHandCardData, sizeof(m_cbHandCardData));
ZeroMemory(m_lUserChipScore, sizeof(m_lUserChipScore));
ZeroMemory(m_cbGamingStatus, sizeof(m_cbGamingStatus));
ZeroMemory(&m_PrivateEndInfo, sizeof(CMD_S_Private_End_Info));
ZeroMemory(m_cbHideCardRound, sizeof(m_cbHideCardRound));
}
CTableFrameSink::~CTableFrameSink(void)
{
}
void * CTableFrameSink::QueryInterface(const IID & Guid, DWORD dwQueryVer)
{
QUERYINTERFACE(ITableFrameSink, Guid, dwQueryVer);
QUERYINTERFACE(ITableUserAction, Guid, dwQueryVer);
QUERYINTERFACE_IUNKNOWNEX(ITableFrameSink, Guid, dwQueryVer);
return nullptr;
}
bool CTableFrameSink::Initialization(IUnknownEx * pIUnknownEx)
{
ASSERT(nullptr != pIUnknownEx);
m_pITableFrame = QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx, ITableFrame);
ASSERT(nullptr != m_pITableFrame);
if (nullptr == m_pITableFrame) return false;
m_pGameServiceOption = m_pITableFrame->GetGameServiceOption();
ASSERT(nullptr != m_pGameServiceOption);
if (nullptr == m_pGameServiceOption) return false;
//开始模式;
m_pITableFrame->SetStartMode(START_MODE_ALL_READY);
//自定规则;
ASSERT(m_pITableFrame->GetCustomRule() != NULL);
m_pGameCustomRule = (tagCustomRule *)m_pITableFrame->GetCustomRule();
//默认最小可下注;
m_lCfgMinChipScore = m_pGameCustomRule->lMinChipScore;
//默认最大可下注;
m_lCfgMaxChipScore = m_pGameCustomRule->lMaxChipScore;
//默认开牌轮数;
m_cbCfgMaxPlayRound = m_pGameCustomRule->cbMaxPlayRound;
//默认最小比牌人数;
m_cbCfgMinCompareUser = m_pGameCustomRule->cbMinCompareUser;
//默认看牌轮数;
m_cbCfgMinLookRound = m_pGameCustomRule->cbMinLookRound;
//默认比牌轮数;
m_cbCfgMinCompareRound = m_pGameCustomRule->cbMinCompareRound;
// 测试;
//BYTE cbFirstCardData[MAX_COUNT] = { 0x2b, 0x0a, 0x39 };
//BYTE cbNextCardData[MAX_COUNT] = {0x3b, 0x1a, 0x19};
//BYTE cbFirstCardData[MAX_COUNT] = { 0x2b, 0x0b, 0x39 };
//BYTE cbNextCardData[MAX_COUNT] = { 0x3b, 0x1b, 0x19 };
//BYTE cbFirstCardData[MAX_COUNT] = { 0x2b, 0x2a, 0x29 };
//BYTE cbNextCardData[MAX_COUNT] = { 0x3b, 0x3a, 0x39 };
//if (m_GameLogic.AutoCompareCard(cbFirstCardData, cbNextCardData, MAX_COUNT))
//{
// ASSERT(true);
//}
//else
//{
// ASSERT(false);
//}
//
return true;
}
bool CTableFrameSink::IsUserPlaying(WORD wChairID)
{
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
return (ST_GAMING_NULL!=m_cbGamingStatus[wChairID]) ? true : false;
}
bool CTableFrameSink::OnActionUserSitDown(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
{
if (!bLookonUser && INVALID_CHAIR == m_wFirstChairID)
{
m_wFirstChairID = wChairID;
}
return true;
}
bool CTableFrameSink::OnActionUserStandUp(WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser)
{
//变量定义;
WORD wUserCount = 0;
//数目统计;
for (WORD i = 0; i < GAME_PLAYER; i++)
{
if (i == wChairID) continue;
if (m_pITableFrame->GetTableUserItem(i) != nullptr)
{
wUserCount++;
}
}
if (!bLookonUser && (0 == wUserCount))
{
m_wFirstChairID = INVALID_CHAIR;
}
return true;
}
void CTableFrameSink::RepositionSink()
{
m_wCurrentUser = INVALID_CHAIR;
m_wFirstOperateUser = INVALID_CHAIR;
m_lCurChipScore = 0;
m_dwOperateCode = 0;
m_cbCurPlayRound = 0;
m_cbGamingUserCount = 0;
ZeroMemory(m_cbUserResponse, sizeof(m_cbUserResponse));
ZeroMemory(m_cbHandCardData, sizeof(m_cbHandCardData));
ZeroMemory(m_lUserChipScore, sizeof(m_lUserChipScore));
ZeroMemory(m_cbGamingStatus, sizeof(m_cbGamingStatus));
ZeroMemory(m_cbHideCardRound, sizeof(m_cbHideCardRound));
}
bool CTableFrameSink::OnEventSendGameScene(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbGameStatus, bool bSendSecret)
{
switch (cbGameStatus)
{
case GS_ZJH_FREE:
{
CMD_S_StatusFree free = { 0 };
free.lCellScore = m_pITableFrame->GetCellScore();
free.cbCurRound = m_cbCurPlayRound;
free.cbMaxRound = m_cbCfgMaxPlayRound;
free.lCurChipScore = m_lCurChipScore;
free.lMaxChipScore = m_lCfgMaxChipScore;
free.wOperTimeOut = IDT_WAIT_OPERATE / 1000;
return m_pITableFrame->SendGameScene(pIServerUserItem, &free, sizeof(free));
}
case GS_ZJH_SEND_CARD:
{
CMD_S_StatusSendCard send = { 0 };
send.stBase.lCellScore = m_pITableFrame->GetCellScore();
send.stBase.cbCurRound = m_cbCurPlayRound;
send.stBase.cbMaxRound = m_cbCfgMaxPlayRound;
send.stBase.lCurChipScore = m_lCurChipScore;
send.stBase.lMaxChipScore = m_lCfgMaxChipScore;
send.stBase.wOperTimeOut = IDT_WAIT_OPERATE / 1000;
send.bSendOver = m_cbUserResponse[wChairID];
send.wBankerUser = m_wBankerUser;
CopyMemory(send.lUserChipScore, m_lUserChipScore, sizeof(m_lUserChipScore));
CopyMemory(send.cbGamingStatus, m_cbGamingStatus, sizeof(m_cbGamingStatus));
return m_pITableFrame->SendGameScene(pIServerUserItem, &send, sizeof(send));
}
case GS_ZJH_PLAYING:
{
CMD_S_StatusPlay play = { 0 };
play.stBase.lCellScore = m_pITableFrame->GetCellScore();
play.stBase.cbCurRound = m_cbCurPlayRound;
play.stBase.cbMaxRound = m_cbCfgMaxPlayRound;
play.stBase.lCurChipScore = m_lCurChipScore;
play.stBase.lMaxChipScore = m_lCfgMaxChipScore;
play.stBase.wOperTimeOut = IDT_WAIT_OPERATE / 1000;
play.wBankerUser = m_wBankerUser;
play.wCurrentUser = m_wCurrentUser;
if (m_wCurrentUser == wChairID) play.dwOperateCode = m_dwOperateCode;
CopyMemory(play.lUserChipScore, m_lUserChipScore, sizeof(m_lUserChipScore));
CopyMemory(play.cbGamingStatus, m_cbGamingStatus, sizeof(m_cbGamingStatus));
if (ST_GAMING_LOOK == m_cbGamingStatus[wChairID])
{
CopyMemory(play.cbHandCardData, m_cbHandCardData[wChairID], sizeof(m_cbHandCardData[wChairID]));
}
return m_pITableFrame->SendGameScene(pIServerUserItem, &play, sizeof(play));
}
}
return false;
}
bool CTableFrameSink::OnEventGameStart()
{
tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo();
if (pPrivateFrame!=nullptr)
{
SetPrivateInfo(pPrivateFrame->cbGameTypeIdex, pPrivateFrame->dwGameRule);
}
m_cbCurPlayRound++;
m_lCurChipScore = m_lCfgMinChipScore;
m_GameLogic.RandCardList(reinterpret_cast<BYTE *>(m_cbHandCardData), sizeof(m_cbHandCardData));
if (m_cbMasterCtrlType > 0 && m_cbMasterCtrlType<3 && m_wMasterChairID!=INVALID_CHAIR)
{
//找出赢家ID;
WORD wWinnerIndex = 0;
for (WORD j = 1; j < m_wPlayerCount; j++)
{
//对比扑克;
if (m_GameLogic.CompareCard(m_cbHandCardData[j], m_cbHandCardData[wWinnerIndex], MAX_COUNT) == true)
{
wWinnerIndex = j;
}
}
//赢家交换扑克;
if (1==m_cbMasterCtrlType && wWinnerIndex!=m_wMasterChairID)
{
BYTE cbTempCardData[MAX_COUNT] = {0};
CopyMemory(cbTempCardData, m_cbHandCardData[m_wMasterChairID], MAX_COUNT*sizeof(BYTE));
CopyMemory(m_cbHandCardData[m_wMasterChairID], m_cbHandCardData[wWinnerIndex], MAX_COUNT*sizeof(BYTE));
CopyMemory(m_cbHandCardData[wWinnerIndex], cbTempCardData, MAX_COUNT*sizeof(BYTE));
}
//输家交换扑克;
if (2 == m_cbMasterCtrlType && wWinnerIndex == m_wMasterChairID)
{
//输家ID;
WORD wLoserIndex = (wWinnerIndex+1)%GAME_PLAYER;
BYTE cbTempCardData[MAX_COUNT] = { 0 };
CopyMemory(cbTempCardData, m_cbHandCardData[m_wMasterChairID], MAX_COUNT*sizeof(BYTE));
CopyMemory(m_cbHandCardData[m_wMasterChairID], m_cbHandCardData[wLoserIndex], MAX_COUNT*sizeof(BYTE));
CopyMemory(m_cbHandCardData[wLoserIndex], cbTempCardData, MAX_COUNT*sizeof(BYTE));
}
}
for (WORD i=0; i<m_wPlayerCount; ++i)
{
IServerUserItem *pIUserItem = m_pITableFrame->GetTableUserItem(i);
if (nullptr == pIUserItem) continue;
BYTE cbUserStatus = pIUserItem->GetUserStatus();
BYTE cbReUserStatus = pIUserItem->GetReUserStatus();
if (cbUserStatus == US_PLAYING || (US_OFFLINE == cbUserStatus && cbReUserStatus == US_PLAYING))
{
m_cbGamingUserCount++;
m_lUserChipScore[i] = m_lCurChipScore;
m_cbGamingStatus[i] = ST_GAMING_HIDDEN;
m_GameLogic.SortCardList(m_cbHandCardData[i], MAX_COUNT);
}
}
ASSERT(m_cbGamingUserCount>=2);
if (INVALID_CHAIR==m_wBankerUser)
{
m_wBankerUser = m_wFirstChairID;
ASSERT(INVALID_CHAIR != m_wBankerUser);
if (INVALID_CHAIR == m_wBankerUser || m_pITableFrame->GetTableUserItem(m_wBankerUser)==nullptr)
{
m_wBankerUser = 0;
}
}
m_cbPlayTimes++;
//#ifdef _DEBUG
// if (m_cbPlayTimes == 1)
// {
// m_cbHandCardData[m_wBankerUser][0] = 0x01;
// m_cbHandCardData[m_wBankerUser][1] = 0x11;
// m_cbHandCardData[m_wBankerUser][2] = 0x21;
// }
// else if (m_cbPlayTimes == 2)
// {
// m_cbHandCardData[m_wBankerUser][0] = 0x06;
// m_cbHandCardData[m_wBankerUser][1] = 0x16;
// m_cbHandCardData[m_wBankerUser][2] = 0x26;
// }
// else if (m_cbPlayTimes == 3)
// {
// m_cbHandCardData[m_wBankerUser][0] = 0x0a;
// m_cbHandCardData[m_wBankerUser][1] = 0x0b;
// m_cbHandCardData[m_wBankerUser][2] = 0x0c;
// }
//#endif
CMD_S_GameStart gs = { 0 };
gs.wBankerUser = m_wBankerUser;
gs.cbCurRound = m_cbCurPlayRound;
gs.lCurChipScore = m_lCurChipScore;
CopyMemory(gs.cbGamingStatus, m_cbGamingStatus, sizeof(m_cbGamingStatus));
CopyMemory(gs.lUserChipScore, m_lUserChipScore, sizeof(m_lUserChipScore));
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_START, &gs, sizeof(gs));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_START, &gs, sizeof(gs));
m_pITableFrame->SetGameStatus(GS_ZJH_SEND_CARD);
m_pITableFrame->SetGameTimer(IDI_SEND_CARD, IDT_SEND_CARD, 1, 0);
return true;
}
bool CTableFrameSink::OnTimerMessage(DWORD wTimerID, WPARAM wBindParam)
{
switch (wTimerID)
{
case IDI_SEND_CARD: return OnSendCardOver(INVALID_CHAIR);
case IDI_WAIT_OPERATE: return true;//OnUserGiveUp(m_wCurrentUser);//万年客户要求不需要自动处理;
}
return true;
}
bool CTableFrameSink::OnGameMessage(WORD wSubCmdID, VOID * pDataBuffer, WORD wDataSize, IServerUserItem * pIServerUserItem)
{
switch (wSubCmdID)
{
case SUB_C_SEND_OVER:
{
ASSERT(pIServerUserItem->GetUserStatus() == US_PLAYING);
if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true;
return OnSendCardOver(pIServerUserItem->GetChairID());
}
case SUB_C_USER_OPERATE:
{
ASSERT(sizeof(CMD_C_UserOperate) == wDataSize);
if (sizeof(CMD_C_UserOperate) != wDataSize) return false;
ASSERT(pIServerUserItem->GetUserStatus() == US_PLAYING);
if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true;
WORD wChairID = pIServerUserItem->GetChairID();
CMD_C_UserOperate *pOperate = (CMD_C_UserOperate *)pDataBuffer;
return OnUserOperate(wChairID, pOperate->dwCode, pOperate->lData);
}
case SUB_C_MASTER_CONTROL:
{
ASSERT(sizeof(BYTE) == wDataSize);
if (sizeof(BYTE) != wDataSize) return false;
if (CUserRight::CanGetCard(pIServerUserItem->GetUserRight()))
{
BYTE cbMasterType = *(BYTE*)pDataBuffer;
if (0 == cbMasterType)
{
m_wMasterChairID = INVALID_CHAIR;
m_cbMasterCtrlType = cbMasterType;
}
else if ((1 == cbMasterType) || (2 == cbMasterType))
{
m_wMasterChairID = pIServerUserItem->GetChairID();
m_cbMasterCtrlType = cbMasterType;
}
else if (3 == cbMasterType)
{
ASSERT(pIServerUserItem->GetUserStatus() == US_PLAYING);
if (pIServerUserItem->GetUserStatus() != US_PLAYING) return true;
CMD_S_CheatCardInfo mCheatInfo = {0};
CopyMemory(mCheatInfo.cbGamingStatus, m_cbGamingStatus, sizeof(m_cbGamingStatus));
CopyMemory(mCheatInfo.cbHandCardData, m_cbHandCardData, sizeof(m_cbHandCardData));
m_pITableFrame->SendTableData(pIServerUserItem->GetChairID(), SUB_S_CHEAT_CARD, &mCheatInfo, sizeof(mCheatInfo));
}
return true;
}
return false;
}
}
ASSERT(0);
return false;
}
//框架消息处理;
bool CTableFrameSink::OnFrameMessage(WORD wSubCmdID, VOID * pData, WORD wDataSize, IServerUserItem * pIServerUserItem)
{
return false;
}
bool CTableFrameSink::OnSendCardOver(WORD wChairID)
{
ASSERT(GS_ZJH_SEND_CARD == m_pITableFrame->GetGameStatus());
if (GS_ZJH_SEND_CARD != m_pITableFrame->GetGameStatus()) return true;
if (INVALID_CHAIR != wChairID)
{
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
ASSERT(IsUserPlaying(wChairID));
if (!IsUserPlaying(wChairID)) return true;
ASSERT(!m_cbUserResponse[wChairID]);
if (m_cbUserResponse[wChairID]) return true;
m_cbUserResponse[wChairID] = true;
for (int i=0; i<m_wPlayerCount; ++i)
{
if (IsUserPlaying(i) && !m_cbUserResponse[i])
{
return true;
}
}
}
m_pITableFrame->KillGameTimer(IDI_SEND_CARD);
memset(m_cbUserResponse, 1, sizeof(m_cbUserResponse));
ASSERT(1 == m_cbCurPlayRound);
ASSERT(m_wCurrentUser == INVALID_CHAIR);
ASSERT(m_wFirstOperateUser == INVALID_CHAIR);
ASSERT(m_lCurChipScore == m_lCfgMinChipScore);
m_wCurrentUser = m_wBankerUser;
m_wFirstOperateUser = m_wBankerUser;
m_dwOperateCode = MakeOperateCode(m_wCurrentUser);
CMD_S_StartChip sc = { 0 };
sc.cbCurRound = m_cbCurPlayRound;
sc.wCurrentUser = m_wCurrentUser;
sc.dwOperateCode = m_dwOperateCode;
sc.lCurChipScore = m_lCurChipScore;
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_START_CHIP, &sc, sizeof(sc));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_START_CHIP, &sc, sizeof(sc));
m_pITableFrame->SetGameStatus(GS_ZJH_PLAYING);
m_pITableFrame->SetGameTimer(IDI_WAIT_OPERATE, IDT_WAIT_OPERATE, 1, m_wCurrentUser);
return true;
}
bool CTableFrameSink::OnUserOperate(WORD wChairID, DWORD dwOperateCode, LONG lOperateData)
{
ASSERT(GS_ZJH_PLAYING == m_pITableFrame->GetGameStatus());
if (GS_ZJH_PLAYING != m_pITableFrame->GetGameStatus()) return true;
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
ASSERT(IsGamingUser(wChairID));
if (!IsGamingUser(wChairID)) return true;
if (OPERATE_LOOK != dwOperateCode)
{
ASSERT(wChairID == m_wCurrentUser);
if (wChairID != m_wCurrentUser) return true;
ASSERT((m_dwOperateCode&dwOperateCode) != 0);
if (0 == (m_dwOperateCode&dwOperateCode)) return true;
}
switch (dwOperateCode)
{
case OPERATE_GIVEUP:
return OnUserGiveUp(wChairID);
case OPERATE_LOOK:
return OnUserLookCard(wChairID);
case OPERATE_FOLLOW:
case OPERATE_ADD_CHIP:
return OnUserChipScore(wChairID, dwOperateCode, lOperateData);
case OPERATE_COMPARE_CARD:
return OnUserCompareCard(wChairID, dwOperateCode, static_cast<WORD>(lOperateData));
}
ASSERT(0);
return false;
}
bool CTableFrameSink::OnUserGiveUp(WORD wChairID)
{
ASSERT(GS_ZJH_PLAYING == m_pITableFrame->GetGameStatus());
if (GS_ZJH_PLAYING != m_pITableFrame->GetGameStatus()) return true;
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
ASSERT(IsGamingUser(wChairID));
if (!IsGamingUser(wChairID)) return true;
ASSERT(wChairID == m_wCurrentUser);
if (wChairID != m_wCurrentUser) return true;
m_pITableFrame->KillGameTimer(IDI_WAIT_OPERATE);
m_cbGamingUserCount--;
m_cbGamingStatus[wChairID] = ST_GAMING_GIVEUP;
SwitchNextGamingUser(wChairID);
ASSERT(m_wCurrentUser!=INVALID_CHAIR || 1==m_cbGamingUserCount);
CMD_S_GiveUp gu = { 0 };
gu.wGiveUpUser = wChairID;
gu.stChipInfo.cbCurRound = m_cbCurPlayRound;
gu.stChipInfo.wCurrentUser = m_wCurrentUser;
gu.stChipInfo.dwOperateCode = m_dwOperateCode;
gu.stChipInfo.lCurChipScore = m_lCurChipScore;
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GIVE_UP, &gu, sizeof(gu));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GIVE_UP, &gu, sizeof(gu));
if (INVALID_CHAIR == m_wCurrentUser)
{
OnEventGameConclude(INVALID_CHAIR, nullptr, GER_NORMAL);
}
else
{
m_pITableFrame->SetGameTimer(IDI_WAIT_OPERATE, IDT_WAIT_OPERATE, 1, m_wCurrentUser);
}
return true;
}
bool CTableFrameSink::OnUserLookCard(WORD wChairID)
{
ASSERT(GS_ZJH_PLAYING == m_pITableFrame->GetGameStatus());
if (GS_ZJH_PLAYING != m_pITableFrame->GetGameStatus()) return true;
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
ASSERT(IsGamingUser(wChairID));
if (!IsGamingUser(wChairID)) return true;
// 闷牌状态;
ASSERT(ST_GAMING_HIDDEN == m_cbGamingStatus[wChairID]);
if (ST_GAMING_HIDDEN != m_cbGamingStatus[wChairID])
{
return true;
}
// 闷牌轮数限制;
ASSERT(m_cbCurPlayRound >= m_cbCfgMinLookRound);
if (m_cbCurPlayRound < m_cbCfgMinLookRound)
{
return true;
}
m_cbGamingStatus[wChairID] = ST_GAMING_LOOK;
CMD_S_LookCard lc = { 0 };
lc.wLookUser = wChairID;
lc.stChipInfo.wCurrentUser = m_wCurrentUser;
for (int i = 0; i < m_wPlayerCount; ++i)
{
if (i!=wChairID)
{
m_pITableFrame->SendTableData(i, SUB_S_LOOK_CARD, &lc, sizeof(lc));
}
}
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_LOOK_CARD, &lc, sizeof(lc));
CopyMemory(lc.cbCardData, m_cbHandCardData[wChairID], sizeof(lc.cbCardData));
if (wChairID == m_wCurrentUser)
{
m_pITableFrame->KillGameTimer(IDI_WAIT_OPERATE);
m_dwOperateCode = MakeOperateCode(m_wCurrentUser);
lc.stChipInfo.cbCurRound = m_cbCurPlayRound;
lc.stChipInfo.wCurrentUser = m_wCurrentUser;
lc.stChipInfo.dwOperateCode = m_dwOperateCode;
lc.stChipInfo.lCurChipScore = m_lCurChipScore;
}
m_pITableFrame->SendTableData(wChairID, SUB_S_LOOK_CARD, &lc, sizeof(lc));
if (wChairID == m_wCurrentUser)
{
m_pITableFrame->SetGameTimer(IDI_WAIT_OPERATE, IDT_WAIT_OPERATE, 1, m_wCurrentUser);
}
return true;
}
bool CTableFrameSink::OnUserChipScore(WORD wChairID, DWORD dwOperateCode, LONG lUserChip)
{
ASSERT(GS_ZJH_PLAYING == m_pITableFrame->GetGameStatus());
if (GS_ZJH_PLAYING != m_pITableFrame->GetGameStatus()) return true;
ASSERT(wChairID >= 0 && wChairID < GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
ASSERT(IsGamingUser(wChairID));
if (!IsGamingUser(wChairID)) return true;
ASSERT(wChairID == m_wCurrentUser);
if (wChairID != m_wCurrentUser) return true;
ASSERT((m_dwOperateCode&dwOperateCode) != 0);
if (0 == (m_dwOperateCode&dwOperateCode)) return true;
ASSERT(OPERATE_FOLLOW==dwOperateCode || OPERATE_ADD_CHIP==dwOperateCode);
if (OPERATE_FOLLOW!=dwOperateCode && OPERATE_ADD_CHIP!=dwOperateCode) return true;
m_pITableFrame->KillGameTimer(IDI_WAIT_OPERATE);
LONG lChipScore = m_lCurChipScore;
if (OPERATE_ADD_CHIP == dwOperateCode)
{
ASSERT(lUserChip > m_lCurChipScore);
lChipScore = lUserChip;
m_lCurChipScore = lUserChip;
}
lChipScore = IsCardHidden(wChairID) ? lChipScore : lChipScore<<1;
m_lUserChipScore[wChairID] += lChipScore;
SwitchNextGamingUser(wChairID);
CMD_S_ChipScore cs = { 0 };
cs.wChipUser = wChairID;
cs.lChipScore = lChipScore;
cs.lTtlChipScore = m_lUserChipScore[wChairID];
cs.dwOperateCode = dwOperateCode;
cs.stChipInfo.cbCurRound = m_cbCurPlayRound;
cs.stChipInfo.wCurrentUser = m_wCurrentUser;
cs.stChipInfo.dwOperateCode = m_dwOperateCode;
cs.stChipInfo.lCurChipScore = m_lCurChipScore;
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_USER_CHIP, &cs, sizeof(cs));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_USER_CHIP, &cs, sizeof(cs));
if (INVALID_CHAIR == m_wCurrentUser)
{
OnEventGameConclude(INVALID_CHAIR, nullptr, GER_NORMAL);
}
else
{
m_pITableFrame->SetGameTimer(IDI_WAIT_OPERATE, IDT_WAIT_OPERATE, 1, m_wCurrentUser);
}
return true;
}
bool CTableFrameSink::OnUserCompareCard(WORD wChairID, DWORD dwOperateCode, WORD wCompareUser)
{
ASSERT(GS_ZJH_PLAYING == m_pITableFrame->GetGameStatus());
if (GS_ZJH_PLAYING != m_pITableFrame->GetGameStatus()) return true;
ASSERT(wChairID >= 0 && wChairID < GAME_PLAYER);
if (wChairID >= GAME_PLAYER) return false;
ASSERT(IsGamingUser(wChairID));
if (!IsGamingUser(wChairID)) return true;
ASSERT(wChairID == m_wCurrentUser);
if (wChairID != m_wCurrentUser) return true;
ASSERT((m_dwOperateCode&OPERATE_COMPARE_CARD) != 0);
if (0 == (m_dwOperateCode&OPERATE_COMPARE_CARD)) return true;
ASSERT(wCompareUser>=0 && wCompareUser<GAME_PLAYER);
ASSERT(IsUserPlaying(wCompareUser));
ASSERT(wChairID != wCompareUser);
m_pITableFrame->KillGameTimer(IDI_WAIT_OPERATE);
LONG lAddScore = IsCardHidden(wChairID) ? m_lCurChipScore : m_lCurChipScore<<1;
m_lUserChipScore[wChairID] += lAddScore;
bool bWin = m_GameLogic.CompareCard(m_cbHandCardData[wChairID],m_cbHandCardData[wCompareUser],MAX_COUNT);
if (bWin)
{
m_cbGamingStatus[wCompareUser] = ST_GAMING_LOSE;
}
else
{
m_cbGamingStatus[wChairID] = ST_GAMING_LOSE;
}
ASSERT(0 != m_cbGamingUserCount);
m_cbGamingUserCount--;
SwitchNextGamingUser(wChairID);
CMD_S_CompareCard cc = { 0 };
cc.bWin = bWin;
cc.wChairID = wChairID;
cc.wCompareUser = wCompareUser;
cc.lChipScore = lAddScore;
cc.lTtlChipScore = m_lUserChipScore[wChairID];
cc.stChipInfo.cbCurRound = m_cbCurPlayRound;
cc.stChipInfo.wCurrentUser = m_wCurrentUser;
cc.stChipInfo.dwOperateCode = m_dwOperateCode;
cc.stChipInfo.lCurChipScore = m_lCurChipScore;
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_COMPARE_CARD, &cc, sizeof(cc));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_COMPARE_CARD, &cc, sizeof(cc));
if (INVALID_CHAIR == m_wCurrentUser)
{
OnEventGameConclude(INVALID_CHAIR, nullptr, GER_NORMAL);
}
else
{
m_pITableFrame->SetGameTimer(IDI_WAIT_OPERATE, IDT_WAIT_OPERATE, 1, m_wCurrentUser);
}
return true;
}
bool CTableFrameSink::OnEventGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason)
{
m_pITableFrame->KillGameTimer(IDI_SEND_CARD);
m_pITableFrame->KillGameTimer(IDI_WAIT_OPERATE);
switch (cbReason)
{
case GER_DISMISS:
{
CMD_S_GameEnd ge = { 0 };
ge.isPrivateEnd = true;
CopyMemory(ge.cbGamingStatus, m_cbGamingStatus, sizeof(m_cbGamingStatus));
CopyMemory(ge.cbHandCardData, m_cbHandCardData, sizeof(m_cbHandCardData));
for (int i = 0; i < m_wPlayerCount; ++i)
{
if (!IsUserPlaying(i)) continue;
ge.cbCardType[i] = m_GameLogic.GetCardType(m_cbHandCardData[i], MAX_COUNT);
m_PrivateEndInfo.aryActiveStatus[i] = m_cbGamingStatus[i];
}
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &ge, sizeof(ge));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &ge, sizeof(ge));
return m_pITableFrame->ConcludeGame(GAME_STATUS_FREE, cbReason);
}
case GER_NORMAL:
{
/********************************私人场统计****************************************/
m_pITableFrame->addPrivatePlayCout(1);
/********************************私人场统计****************************************/
CMD_S_GameEnd ge = { 0 };
ge.isPrivateEnd = IsPrivateEnd();
WORD wWinUser = (1 == m_cbGamingUserCount ? CountLastWinUser() : INVALID_CHAIR);
WORD wNextRoundBanker = CountGameScore(wWinUser, ge.lGameScore);
CopyMemory(ge.cbGamingStatus, m_cbGamingStatus, sizeof(m_cbGamingStatus));
CopyMemory(ge.cbHandCardData, m_cbHandCardData, sizeof(m_cbHandCardData));
LONG lRevenue[GAME_PLAYER] = { 0 };
for (int i = 0; i < m_wPlayerCount; ++i)
{
if (!IsUserPlaying(i)) continue;
ge.cbCardType[i] = m_GameLogic.GetCardType(m_cbHandCardData[i], MAX_COUNT);
lRevenue[i] = static_cast<LONG>(m_pITableFrame->CalculateRevenue(i, ge.lGameScore[i]));
ge.lGameScore[i] -= lRevenue[i];
// 放弃没有喜金闷牌次数要大于1;
if ((ST_GAMING_GIVEUP==m_cbGamingStatus[i]) || (m_cbHideCardRound[i]<1)) continue;
int nXiScore = m_GameLogic.GetXiScore(ge.cbCardType[i], m_cbHandCardData[i][0]);
if (nXiScore>0)
{
for (int j = 0; j < m_wPlayerCount; ++j)
{
if (!IsUserPlaying(j)) continue;
if (j!=i)
{
ge.lXiScore[j] -= nXiScore;
ge.lXiScore[i] += nXiScore;
}
}
}
}
m_pITableFrame->SendTableData(INVALID_CHAIR, SUB_S_GAME_END, &ge, sizeof(ge));
m_pITableFrame->SendLookonData(INVALID_CHAIR, SUB_S_GAME_END, &ge, sizeof(ge));
//修改积分;
tagScoreInfo ScoreInfoArray[GAME_PLAYER];
ZeroMemory(ScoreInfoArray, sizeof(ScoreInfoArray));
for (int i = 0; i < m_wPlayerCount; ++i)
{
if (!IsUserPlaying(i)) continue;
m_PrivateEndInfo.aryActiveStatus[i] = m_cbGamingStatus[i];
m_PrivateEndInfo.aryWinScore[i] += ge.lGameScore[i];
m_PrivateEndInfo.aryXiScore[i] += ge.lXiScore[i];
m_PrivateEndInfo.aryTotalScore[i] += ge.lGameScore[i] + ge.lXiScore[i];
ScoreInfoArray[i].cbType = (IsGamingUser(i)) ? SCORE_TYPE_WIN : SCORE_TYPE_LOSE;
ScoreInfoArray[i].lRevenue = lRevenue[i];
ScoreInfoArray[i].lScore = ge.lGameScore[i] + ge.lXiScore[i];
}
//牌局结束后,每8局增加一点经验值;
if (IsPrivateEnd())
{
//tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo();
//SCORE lGrade = pPrivateFrame->dwPlayCost;
ScoreInfoArray[0].lGrade = 2; //房主2倍;
for (WORD i = 1; i < GAME_PLAYER; i++)
{
ScoreInfoArray[i].lGrade = 1;
}
}
m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray));
//下一轮庄家;
if (INVALID_CHAIR != wNextRoundBanker)
{
m_wBankerUser = wNextRoundBanker;
}
else
{
ASSERT(m_cbGamingUserCount > 1);
m_wBankerUser = FindNextGamingUser(m_wBankerUser);
}
m_pITableFrame->ConcludeGame(GAME_STATUS_FREE, cbReason);
return true;
}
case GER_USER_LEAVE:
case GER_NETWORK_ERROR:
{
ASSERT(0);
return true;
}
}
ASSERT(0);
return false;
}
DWORD CTableFrameSink::MakeOperateCode(WORD wChairID)
{
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
ASSERT(wChairID == m_wCurrentUser);
ASSERT(IsGamingUser(wChairID));
if (!IsGamingUser(wChairID)) return OPERATE_NULL;
IServerUserItem *pIServerUserItem = m_pITableFrame->GetTableUserItem(wChairID);
ASSERT(nullptr != pIServerUserItem);
if (nullptr == pIServerUserItem) return OPERATE_NULL;
DWORD dwOperateCode = OPERATE_GIVEUP | OPERATE_FOLLOW;
//// 是否可以看牌;
//if ((m_cbCurPlayRound > m_cbCfgMinLookRound) && (ST_GAMING_HIDDEN == m_cbGamingStatus[wChairID]))
//{
// dwOperateCode |= OPERATE_LOOK;
//}
// 是否可以加注;
if ((m_lCfgMinChipScore != m_lCfgMaxChipScore) && (m_lCurChipScore<m_lCfgMaxChipScore))
{
dwOperateCode |= OPERATE_ADD_CHIP;
}
// 是否可以比牌;
if ((m_cbCurPlayRound >= m_cbCfgMinCompareRound) && (m_cbGamingUserCount >= m_cbCfgMinCompareUser))
{
dwOperateCode |= OPERATE_COMPARE_CARD;
}
return dwOperateCode;
}
WORD CTableFrameSink::FindNextGamingUser(WORD wChairID)
{
ASSERT(wChairID>=0 && wChairID<GAME_PLAYER);
ASSERT(0 != m_cbGamingUserCount);
if (1 == m_cbGamingUserCount)
{
return IsGamingUser(wChairID) ? wChairID : INVALID_CHAIR;
}
WORD wNextUser = wChairID;
for (WORD i=0; i<m_wPlayerCount; ++i)
{
if (++wNextUser == m_wPlayerCount)
{
wNextUser = 0;
}
if (IsGamingUser(wNextUser))
{
return wNextUser;
}
}
return INVALID_CHAIR;
}
void CTableFrameSink::SwitchNextGamingUser(WORD wChairID)
{
ASSERT(0 != m_cbGamingUserCount);
ASSERT(wChairID == m_wCurrentUser);
m_dwOperateCode = 0;
m_wCurrentUser = INVALID_CHAIR;
if (1 == m_cbGamingUserCount) return;
m_wCurrentUser = FindNextGamingUser(wChairID);
ASSERT(m_wCurrentUser>=0 && m_wCurrentUser<GAME_PLAYER);
ASSERT(IsGamingUser(m_wCurrentUser));
if (m_wCurrentUser == m_wFirstOperateUser)
{
if ((0 != m_cbCfgMaxPlayRound) && (m_cbCurPlayRound >= m_cbCfgMaxPlayRound))
{
m_wCurrentUser = INVALID_CHAIR;
return;
}
else
{
m_cbCurPlayRound++;
for (WORD i = 0; i<m_wPlayerCount; ++i)
{
if (ST_GAMING_HIDDEN == m_cbGamingStatus[i])
{
m_cbHideCardRound[i]++;
}
}
}
}
//切换轮首;
if (!IsGamingUser(m_wFirstOperateUser))
{
m_wFirstOperateUser = FindNextGamingUser(m_wFirstOperateUser);
ASSERT(INVALID_CHAIR != m_wFirstOperateUser);
}
m_dwOperateCode = MakeOperateCode(m_wCurrentUser);
ASSERT(0 != m_dwOperateCode);
}
WORD CTableFrameSink::CountLastWinUser()
{
ASSERT(1 == m_cbGamingUserCount);
for (WORD i = 0; i < m_wPlayerCount; ++i)
{
if (IsGamingUser(i))
{
return i;
}
}
ASSERT(0);
return INVALID_CHAIR;
}
WORD CTableFrameSink::CountGameScore(WORD wWinner, LONG lGameScore[GAME_PLAYER])
{
if (INVALID_CHAIR != wWinner)
{
ASSERT(1 == m_cbGamingUserCount);
ASSERT(wWinner == CountLastWinUser());
}
else
{
ASSERT(m_cbGamingUserCount > 1);
}
if (INVALID_CHAIR != wWinner)
{
for (WORD i=0; i<m_wPlayerCount; ++i)
{
if (i == wWinner) continue;
lGameScore[i] = -m_lUserChipScore[i];
lGameScore[wWinner] += m_lUserChipScore[i];
}
return wWinner;
}
else
{
LONG lTotalScore = 0;
WORD wWinnerCount = 0;
WORD wWinUser = INVALID_CHAIR;
for (WORD i=0; i<m_wPlayerCount; ++i)
{
lTotalScore += m_lUserChipScore[i];
if (!IsGamingUser(i)) continue;
for (WORD j=i+1; j<m_wPlayerCount; ++j)
{
if (!IsGamingUser(j)) continue;
//if (m_GameLogic.CompareCard(m_cbHandCardData[j],m_cbHandCardData[i],MAX_COUNT))
if (m_GameLogic.AutoCompareCard(m_cbHandCardData[j], m_cbHandCardData[i], MAX_COUNT))
{
wWinUser = j;
m_cbGamingStatus[i] = ST_GAMING_LOSE;
break;
}
else
{
wWinUser = i;
m_cbGamingStatus[j] = ST_GAMING_LOSE;
}
}
if (IsGamingUser(i))
{
wWinnerCount++;
}
}
ASSERT(lTotalScore > 0);
ASSERT(wWinUser>=0 && wWinUser<GAME_PLAYER);
ASSERT(0 != wWinnerCount);
LONG lWinScore = lTotalScore / wWinnerCount;
for (WORD i=0; i<m_wPlayerCount; i++)
{
if (IsGamingUser(i))
{
ASSERT(i == wWinUser);
lGameScore[i] = lTotalScore - m_lUserChipScore[i];
}
else
{
lGameScore[i] = -m_lUserChipScore[i];
}
}
return wWinUser;
}
ASSERT(0);
return INVALID_CHAIR;
}
////////////////////////////// 私人场 ////////////////////////////////////////////
void CTableFrameSink::SetPrivateInfo(BYTE cbGameTypeIndex, DWORD dwGameRule)
{
// 比牌轮数;
if ((dwGameRule&eZJHGameRuleCompareRound2)>0)
{
m_cbCfgMinCompareRound = 2;
}
else if ((dwGameRule&eZJHGameRuleCompareRound3)>0)
{
m_cbCfgMinCompareRound = 3;
}
else
{
m_cbCfgMinCompareRound = 1;
}
// 开牌轮数;
if ((dwGameRule&eZJHGameRuleOpenCardRound10) > 0)
{
m_cbCfgMaxPlayRound = 10;
}
else if ((dwGameRule&eZJHGameRuleOpenCardRound15) > 0)
{
m_cbCfgMaxPlayRound = 15;
}
else
{
m_cbCfgMaxPlayRound = 5;
}
// 看牌轮数;
if ((dwGameRule&eZJHGameRuleLookCardRound2) > 0)
{
m_cbCfgMinLookRound = 2;
}
else if ((dwGameRule&eZJHGameRuleLookCardRound3) > 0)
{
m_cbCfgMinLookRound = 3;
}
else
{
m_cbCfgMinLookRound = 0;
}
}
void CTableFrameSink::ResetPrivateEndInfo()
{
ZeroMemory(&m_PrivateEndInfo, sizeof(CMD_S_Private_End_Info));
m_wBankerUser = INVALID_CHAIR;
m_cbPlayTimes = 0;
m_cbMasterCtrlType = 0;
m_wMasterChairID = INVALID_CHAIR;
}
//获得私人场结束信息流;
void CTableFrameSink::GetPrivateEndInfo(DataStream &kDataStream, bool bSend)
{
m_PrivateEndInfo.StreamValue(kDataStream, bSend);
}
//判断私人场是否结束;
bool CTableFrameSink::IsPrivateEnd()
{
if (m_pITableFrame == nullptr) return false;
tagPrivateFrameParameter* pPrivateFrame = m_pITableFrame->GetPrivateFrameInfo();
tagPrivateFrameRecordInfo* pPrivateRecord = m_pITableFrame->GetPrivateFrameRecord();
if ((pPrivateFrame == nullptr) || (pPrivateRecord == nullptr)) return false;
if (pPrivateFrame->cbGameCout <= pPrivateRecord->cbFinishCout)
{
return true;
}
return false;
}