feat:完善提前中端结果展示

This commit is contained in:
max
2024-05-31 16:13:20 +08:00
parent 126215949f
commit a6f5b24a6d
13 changed files with 168 additions and 72 deletions

View File

@@ -14,7 +14,7 @@ import com.chwl.app.base.BaseViewBindingActivity
import com.chwl.app.common.widget.dialog.DialogManager
import com.chwl.app.game.core.engine.GameEngineAbility
import com.chwl.app.game.data.bean.GameInfoUiState
import com.chwl.app.game.data.bean.GameResultBean
import com.chwl.core.bean.game.GameResultBean
import com.chwl.app.game.ui.game.GameViewModel
import com.chwl.app.game.ui.result.GameResultDialog
import com.chwl.app.ui.pay.ChargeActivity
@@ -24,7 +24,6 @@ import com.chwl.core.support.room.RoomWidget
import com.chwl.core.utils.net.BalanceNotEnoughExeption
import com.chwl.core.utils.net.ServerException
import com.chwl.library.utils.ResUtil
import com.chwl.library.utils.SingleToastUtil
import com.netease.nim.uikit.StatusBarUtil
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.zip
@@ -87,6 +86,12 @@ abstract class BaseGameActivity<T : ViewBinding> : BaseViewBindingActivity<T>(),
onMatchFailed()
}
}
lifecycleScope.launch {
it.gameResultFlow.collectLatest { list ->
onGameResult(list)
}
}
}
initGameEngine(gameContext)
}
@@ -103,6 +108,7 @@ abstract class BaseGameActivity<T : ViewBinding> : BaseViewBindingActivity<T>(),
}
is GameInfoUiState.Success -> {
matchFailedDialogManager?.dismissDialog()
dialogManager?.dismissDialog()
resultDialog?.dismissAllowingStateLoss()
gameInfoDialogManager?.dismissDialog()
@@ -150,11 +156,6 @@ abstract class BaseGameActivity<T : ViewBinding> : BaseViewBindingActivity<T>(),
}
}
}
lifecycleScope.launch {
gameEngineAbility?.gameResultFlow?.collectLatest {
onGameResult(it)
}
}
lifecycleScope.launch {
gameEngineAbility?.gameViewFlow?.collectLatest {
onGameViewChanged(it)

View File

@@ -3,8 +3,10 @@ package com.chwl.app.game.core
import com.chwl.app.game.data.GameModel2
import com.chwl.app.game.data.bean.GameInfoUiState
import com.chwl.app.game.ui.game.GameIntent
import com.chwl.core.bean.game.GameResultBean
import com.chwl.core.bean.game.GameRoomInfo
import com.chwl.core.im.custom.bean.CustomAttachment
import com.chwl.core.im.custom.bean.GameForcedEndAttachment
import com.chwl.core.im.custom.bean.GameQueueChangedAttachment
import com.chwl.core.support.room.RoomAbility
import com.chwl.core.support.room.RoomContext
@@ -46,6 +48,8 @@ class GameStateAbility : RoomAbility(), GameIMEngineAbility.Listener {
val scoresFlow = MutableStateFlow<List<Double>?>(null)
val gameConfigFlow = MutableStateFlow<String?>(null)
@Deprecated("里面的属性有可能不是最新的建议通过具体属性flow获取数据")
val gameInfoFlow = MutableStateFlow<GameRoomInfo?>(null)
@@ -53,6 +57,8 @@ class GameStateAbility : RoomAbility(), GameIMEngineAbility.Listener {
val matchFailedFlow = MutableSharedFlow<Boolean>()
val gameResultFlow = MutableSharedFlow<List<GameResultBean>?>()
private val queueAbility get() = roomContext?.findAbility<GameQueueAbility>(GameQueueAbility::class.java.simpleName)
override fun onStart(context: RoomContext) {
@@ -90,13 +96,14 @@ class GameStateAbility : RoomAbility(), GameIMEngineAbility.Listener {
}
private suspend fun syncRoomInfo(info: GameRoomInfo) {
roomContext?.roomId = info.chatRoomId ?: 0
roomContext?.roomId = info.roomId ?: 0
gameInfoFlow.value = info
roomIdFlow.value = info.chatRoomId
roomIdFlow.value = info.roomId
imIdFlow.value = info.roomId
gameIdFlow.value = info.data?.mgId
gameIconFlow.value = info.data?.gameRoomIcon
scoresFlow.value = info.data?.scores
gameConfigFlow.value = info.data?.configJson
syncGameState(info.data?.matchStatus)
syncQueue(info)
}
@@ -112,38 +119,45 @@ class GameStateAbility : RoomAbility(), GameIMEngineAbility.Listener {
override fun onReceiveMessage(messages: List<ChatRoomMessage>) {
messages.forEach {
onReceiveMessage(it)
if (it.msgType == MsgTypeEnum.custom) {
val attachment: CustomAttachment = (it.attachment as? CustomAttachment) ?: return
onReceiveCustomMessage(it, attachment)
}
}
}
private fun onReceiveMessage(message: ChatRoomMessage) {
if (message.msgType == MsgTypeEnum.custom) {
val attachment: CustomAttachment = (message.attachment as? CustomAttachment) ?: return
when (attachment.first) {
CustomAttachment.CUSTOM_MSG_MINI_GAME -> {
when (attachment.second) {
// 麦位变更
CustomAttachment.CUSTOM_MSG_MINI_GAME_QUEUE_CHANGED -> {
val gameInfo =
(attachment as? GameQueueChangedAttachment)?.gameInfo ?: return
safeLaunch {
syncQueue(gameInfo)
}
private fun onReceiveCustomMessage(message: ChatRoomMessage, attachment: CustomAttachment) {
when (attachment.first) {
CustomAttachment.CUSTOM_MSG_MINI_GAME -> {
when (attachment.second) {
// 麦位变更
CustomAttachment.CUSTOM_MSG_MINI_GAME_QUEUE_CHANGED -> {
logD("onReceiveMessage 麦位变更")
val gameInfo =
(attachment as? GameQueueChangedAttachment)?.gameInfo ?: return
safeLaunch {
syncQueue(gameInfo)
}
}
// 匹配失败
CustomAttachment.CUSTOM_MSG_MINI_GAME_MATCH_FAILED -> {
safeLaunch {
gameStateFlow.value = 3
matchFailedFlow.emit(true)
}
// 匹配失败
CustomAttachment.CUSTOM_MSG_MINI_GAME_MATCH_FAILED -> {
logD("onReceiveMessage 匹配失败")
safeLaunch {
syncGameState(STATE_MATCH_FAILED)
matchFailedFlow.emit(true)
}
}
// 提前结束
CustomAttachment.CUSTOM_MSG_MINI_GAME_FORCED_END -> {
safeLaunch {
gameStateFlow.value = 2
}
// 提前结束
CustomAttachment.CUSTOM_MSG_MINI_GAME_FORCED_END -> {
logD("onReceiveMessage 提前结束")
val data =
(attachment as? GameForcedEndAttachment)?.msgData ?: return
val results = data.results
safeLaunch {
gameResultFlow.emit(results)
syncGameState(data.matchStatus)
}
}
}

View File

@@ -2,19 +2,27 @@ package com.chwl.app.game.core.engine
import com.chwl.app.game.core.GameQueueAbility
import com.chwl.app.game.core.GameStateAbility
import com.chwl.app.game.data.bean.GameResultBean
import com.chwl.core.bean.game.GameResultBean
import com.chwl.core.bean.game.SudGameConfigBean
import com.chwl.core.sud.state.SudMGPMGState
import com.chwl.core.support.room.RoomContext
import com.chwl.library.utils.json.JsonUtils
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
import tech.sud.mgp.core.ISudFSMStateHandle
class GameEngineAbility : SudEngineAbility() {
val gameResultFlow = MutableSharedFlow<List<GameResultBean>?>()
private val stateAbility get() = roomContext?.findAbility<GameStateAbility>(GameStateAbility::class.java.simpleName)
private var gameConfig: SudGameConfigBean? = null
override fun onStart(context: RoomContext) {
super.onStart(context)
safeLaunch {
stateAbility?.gameConfigFlow?.collectLatest {
parseGameConfig(it)
}
}
safeLaunch {
stateAbility?.gameStateFlow?.collectLatest {
logD("GameEngineAbility gameStateFlow state:${it}")
@@ -42,6 +50,14 @@ class GameEngineAbility : SudEngineAbility() {
private fun tryStopGame() {
}
private fun parseGameConfig(json: String?) {
if (json != null) {
gameConfig = JsonUtils.fromJson(json, SudGameConfigBean::class.java)
} else {
gameConfig = null
}
}
private fun autoPlayGame() {
val stateAbility = stateAbility ?: return
logD("autoPlayGame state:${stateAbility.gameStateFlow.value}")
@@ -69,6 +85,14 @@ class GameEngineAbility : SudEngineAbility() {
override fun onGameStarted() {
super.onGameStarted()
autoJoinGame()
updateGameSettingSelectConfig()
}
private fun updateGameSettingSelectConfig() {
val configStr = gameConfig?.getGameSettingSelectConfigStr()
if (!configStr.isNullOrEmpty()) {
sudFSTAPP.notifyStateChange("app_common_game_setting_select_info", configStr)
}
}
override fun onPlayerMGCommonPlayerReady(
@@ -96,17 +120,29 @@ class GameEngineAbility : SudEngineAbility() {
val queueItem = queueAbility?.findQueueItem(uid)
val scores = scoresList?.getOrNull(index)
val item = GameResultBean().apply {
this.uid = it.uid
this.uid = it.uid.toLongOrNull()
this.rank = it.rank
this.score = it.score
this.nick = queueItem?.micUser?.nick
this.avatar = queueItem?.micUser?.avatar
this.coins = scores
this.winNum = scores
// 目前1v1第一名成功后面需要调整这个逻辑
this.isWin = index == 0
this.isEscaped = it.isEscaped == 1
}
list.add(item)
}
safeLaunch {
gameResultFlow.emit(list)
stateAbility?.gameResultFlow?.emit(list)
}
}
override fun onGetGameCfg(handle: ISudFSMStateHandle, p1: String?) {
val configStr = gameConfig?.getGameConfigStr()
logD("onGetGameCfg() configStr:$configStr")
if (configStr.isNullOrEmpty()) {
super.onGetGameCfg(handle, p1)
} else {
handle.success(configStr)
}
}
}

View File

@@ -14,6 +14,7 @@ import com.chwl.core.room.game.bean.GameCfg
import com.chwl.core.sud.decorator.SudFSMMGDecorator
import com.chwl.core.sud.decorator.SudFSMMGListener
import com.chwl.core.sud.decorator.SudFSTAPPDecorator
import com.chwl.core.sud.model.GameConfigModel
import com.chwl.core.sud.model.GameViewInfoModel
import com.chwl.core.sud.state.MGStateResponse
import com.chwl.core.sud.state.SudMGPMGState
@@ -192,7 +193,7 @@ open class SudEngineAbility : RoomAbility(), SudFSMMGListener, ILog {
}
override fun onGetGameCfg(handle: ISudFSMStateHandle, p1: String?) {
handle.success(JsonUtils.toJson(GameCfg()))
handle.success(JsonUtils.toJson(GameConfigModel()))
}
override fun onGameMGCommonSelfClickJoinBtn(

View File

@@ -6,32 +6,39 @@ import android.widget.TextView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseViewHolder
import com.chwl.app.R
import com.chwl.app.game.data.bean.GameResultBean
import com.chwl.core.bean.game.GameResultBean
import com.chwl.app.ui.utils.loadAvatar
class GameResultAdapter :
BaseQuickAdapter<GameResultBean, BaseViewHolder>(R.layout.game_result_item) {
override fun convert(helper: BaseViewHolder, item: GameResultBean?) {
helper.setText(R.id.tv_name, item?.nick ?: "")
helper.setText(R.id.tv_coins, item?.getCoinsStr() ?: "0")
helper.setText(R.id.tv_coins, item?.getScoreStr() ?: "0")
helper.getView<ImageView>(R.id.iv_user_avatar).loadAvatar(item?.avatar)
val rank = helper.bindingAdapterPosition
val rank = item?.rank ?: (helper.bindingAdapterPosition + 1)
val rankView = helper.getView<TextView>(R.id.tv_rank)
val rootView = helper.getView<View>(R.id.layout_root)
if (rank == 0) {
val coinsBgView = helper.getView<View>(R.id.iv_coins_bg)
val avatarBorderView = helper.getView<View>(R.id.iv_user_avatar_border)
if (rank == 1) {
avatarBorderView.setBackgroundResource(R.drawable.game_result_avatar_border_top_1)
rankView.setBackgroundResource(R.drawable.game_result_ic_top1)
rankView.text = ""
} else if (rank == 1) {
} else if (rank == 2) {
avatarBorderView.setBackgroundResource(R.drawable.game_result_avatar_border_top_2)
rankView.setBackgroundResource(R.drawable.game_result_ic_top2)
rankView.text = ""
} else {
avatarBorderView.background = null
rankView.background = null
rankView.text = "${(rank + 1)}"
rankView.text = "$rank"
}
if (rank % 2 == 0) {
if (rank % 2 == 1) {
rootView.setBackgroundResource(R.drawable.game_result_item_bg_top1)
coinsBgView.setBackgroundResource(R.drawable.game_result_coins_top1)
} else {
rootView.setBackgroundResource(R.drawable.game_result_item_bg_top2)
coinsBgView.setBackgroundResource(R.drawable.game_result_coins_top2)
}
}
}

View File

@@ -9,7 +9,7 @@ import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import com.chwl.app.R
import com.chwl.app.databinding.GameResultDialogBinding
import com.chwl.app.game.data.bean.GameResultBean
import com.chwl.core.bean.game.GameResultBean
import com.chwl.app.ui.widget.recyclerview.decoration.SpacingDecoration
import com.chwl.core.auth.AuthModel
import com.chwl.library.common.util.Utils
@@ -28,12 +28,11 @@ class GameResultDialog(
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
adapter.setNewData(list)
var isSuccess = false
if (list.firstOrNull()?.uid?.toLongOrNull() == AuthModel.get().currentUid) {
isSuccess = true
}
if (isSuccess) {
adapter.setNewData(list.sortedBy { it.rank })
val isWin = list.firstOrNull {
it.uid == AuthModel.get().currentUid
}?.isWin
if (isWin == true) {
binding?.ivState?.setBackgroundResource(R.drawable.game_result_bg_win)
} else {
binding?.ivState?.setBackgroundResource(R.drawable.game_result_bg_lose)

View File

@@ -1,4 +1,4 @@
package com.chwl.app.game.data.bean
package com.chwl.core.bean.game
import androidx.annotation.Keep
import java.io.Serializable
@@ -7,23 +7,24 @@ import java.math.BigDecimal
@Keep
class GameResultBean : Serializable {
var rank: Int? = null
var uid: String? = null
var uid: Long? = null
var avatar: String? = null
var nick: String? = null
var score: Int? = null
var coins: Double? = null
var winNum: Double? = null
var isWin: Boolean? = null
var isEscaped: Boolean? = null
fun getCoinsStr(): String {
val coinsValue = coins ?: return "0"
fun getScoreStr(): String {
val number = winNum ?: return "0"
try {
val bigDecimal = BigDecimal.valueOf(coinsValue)
val bigDecimal = BigDecimal.valueOf(number)
val coinsStr = bigDecimal.stripTrailingZeros().toPlainString()
if (coinsValue > 0) {
if (number > 0) {
return "+$coinsStr"
}
return coinsStr
} catch (e: Exception) {
return coins?.toString() ?: "0"
return number.toString()
}
}
}

View File

@@ -8,7 +8,6 @@ class GameRoomData : Serializable {
val mgId: String? = null
val gameRoomIcon: String? = null
val configJson: String? = null
val gameSelectCfg: String? = null
val scores: MutableList<Double>? = null
// 匹配状态0:匹配中、1:匹配成功、2:游戏结束、3:匹配失败)

View File

@@ -0,0 +1,26 @@
package com.chwl.core.bean.game
import androidx.annotation.Keep
import com.chwl.library.utils.json.JsonUtils
@Keep
class SudGameConfigBean {
private val app_common_game_setting_select_info: HashMap<String, Any>? = null
private val ui: HashMap<String, Any>? = null
fun getGameSettingSelectConfigStr(): String? {
return JsonUtils.toJson(app_common_game_setting_select_info)
}
fun getGameConfigStr(): String? {
val uiMap = ui
if (uiMap.isNullOrEmpty()) {
return null
}
return JsonUtils.toJson(ConfigModel(uiMap))
}
@Keep
private data class ConfigModel(var ui: HashMap<String, Any>)
}

View File

@@ -11,7 +11,6 @@ abstract class BaseRoomInfo<T> : Serializable {
val chatRoomId: Long? = null
// 云信ID
val roomId: Long? = null
val roomMics: MutableList<RoomMicBean>? = null

View File

@@ -2,13 +2,19 @@ package com.chwl.core.im.custom.bean
import androidx.annotation.Keep
import com.alibaba.fastjson.JSONObject
import com.chwl.core.bean.game.GameRoomInfo
import com.chwl.library.utils.json.JsonUtils
import com.google.gson.Gson
@Keep
class GameForcedEndAttachment : CustomAttachment {
var msgData: GameForcedEndMsgBean? = null
constructor() : super()
constructor(first: Int, second: Int) : super(first, second)
override fun parseData(data: JSONObject?) {
msgData = JsonUtils.fromJson(data?.toJSONString(), GameForcedEndMsgBean::class.java)
}
}

View File

@@ -0,0 +1,10 @@
package com.chwl.core.im.custom.bean
import androidx.annotation.Keep
import com.chwl.core.bean.game.GameResultBean
@Keep
class GameForcedEndMsgBean {
val results: List<GameResultBean>? = null
val matchStatus: Int? = null
}

View File

@@ -3,6 +3,7 @@ package com.chwl.core.im.custom.bean
import androidx.annotation.Keep
import com.alibaba.fastjson.JSONObject
import com.chwl.core.bean.game.GameRoomInfo
import com.chwl.library.utils.json.JsonUtils
import com.google.gson.Gson
@Keep
@@ -13,10 +14,6 @@ class GameQueueChangedAttachment : CustomAttachment {
constructor(first: Int, second: Int) : super(first, second)
override fun parseData(data: JSONObject?) {
try {
gameInfo = Gson().fromJson(data?.toJSONString(), GameRoomInfo::class.java)
} catch (e: Exception) {
e.printStackTrace()
}
gameInfo = JsonUtils.fromJson(data?.toJSONString(), GameRoomInfo::class.java)
}
}