feat:完成部分房间信息获取逻辑对接
This commit is contained in:
@@ -85,6 +85,14 @@ fun ImageView.loadAvatar(url: String?) {
|
||||
.into(this)
|
||||
}
|
||||
|
||||
|
||||
fun ImageView.loadImage(url: String? = "") {
|
||||
if (context.isDestroyed()) return
|
||||
GlideApp.with(context).load(url)
|
||||
.dontAnimate()
|
||||
.into(this)
|
||||
}
|
||||
|
||||
fun Context.isDestroyed(): Boolean {
|
||||
return (getActivityContext(this) as? Activity)?.isDestroyed == true
|
||||
}
|
||||
|
@@ -17,8 +17,11 @@ import com.netease.nim.uikit.StatusBarUtil
|
||||
abstract class BaseGameActivity<T : ViewBinding> : BaseViewBindingActivity<T>(), RoomView {
|
||||
|
||||
protected val viewModel: GameViewModel by viewModels()
|
||||
protected val gameViewModel: GameEngineViewModel by viewModels()
|
||||
protected val gameEngineViewModel: GameEngineViewModel by viewModels()
|
||||
protected var widgets: HashMap<String, RoomWidget> = HashMap()
|
||||
protected val gameContext get() = viewModel.gameContextLiveData.value
|
||||
|
||||
protected val stateAbility get() = gameContext?.findAbility<GameStateAbility>(GameStateAbility::class.java.simpleName)
|
||||
|
||||
override fun init() {
|
||||
initView()
|
||||
|
@@ -7,8 +7,13 @@ class GameContext(roomId: Long) : RoomContext(roomId) {
|
||||
|
||||
override fun loadAbility(list: MutableMap<String, RoomAbility>) {
|
||||
super.loadAbility(list)
|
||||
list.put(GameStateAbility::class.java.simpleName, GameStateAbility())
|
||||
list.put(GameIMEngineAbility::class.java.simpleName, GameIMEngineAbility())
|
||||
list.put(GameQueueAbility::class.java.simpleName, GameQueueAbility())
|
||||
list.put(GameMessageAbility::class.java.simpleName, GameMessageAbility())
|
||||
}
|
||||
|
||||
override fun performStart() {
|
||||
super.performStart()
|
||||
}
|
||||
}
|
@@ -12,20 +12,38 @@ import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder
|
||||
import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
class GameIMEngineAbility(private val listenerOwner: ListenerOwner<GameIMEngineAbility.Listener> = SafeListenerOwner()) :
|
||||
RoomAbility(), ListenerStore<GameIMEngineAbility.Listener> by listenerOwner {
|
||||
|
||||
private var chatRoomClient: ChatRoomClient? = null
|
||||
|
||||
val stateFlow = MutableStateFlow<StatusCode>(StatusCode.INVALID)
|
||||
|
||||
fun enterRoom(sessionId: String) {
|
||||
private var chatRoomClient: ChatRoomClient? = null
|
||||
|
||||
private val stateAbility: GameStateAbility?
|
||||
get() = roomContext?.findAbility<GameStateAbility>(
|
||||
GameStateAbility::class.java.simpleName
|
||||
)
|
||||
|
||||
override fun onStart(context: RoomContext) {
|
||||
super.onStart(context)
|
||||
safeLaunch {
|
||||
stateAbility?.imIdFlow?.collectLatest {
|
||||
loadIM(it?.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadIM(sessionId: String?) {
|
||||
if (chatRoomClient != null && chatRoomClient?.sessionId != sessionId) {
|
||||
chatRoomClient?.onCleared()
|
||||
chatRoomClient = null
|
||||
}
|
||||
if (sessionId != null) {
|
||||
initClient(sessionId)
|
||||
}
|
||||
initClient(sessionId)
|
||||
}
|
||||
|
||||
private fun initClient(sessionId: String) {
|
||||
@@ -69,6 +87,7 @@ class GameIMEngineAbility(private val listenerOwner: ListenerOwner<GameIMEngineA
|
||||
super.onStop(context)
|
||||
listenerOwner.removeAllListener()
|
||||
chatRoomClient?.onCleared()
|
||||
chatRoomClient = null
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
@@ -1,16 +1,56 @@
|
||||
package com.chwl.app.game.core
|
||||
|
||||
import com.chwl.app.game.data.GameModel2
|
||||
import com.chwl.app.game.data.bean.GameRoomInfo
|
||||
import com.chwl.core.support.room.RoomAbility
|
||||
import com.chwl.core.support.room.RoomContext
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class GameStateAbility : RoomAbility() {
|
||||
|
||||
val gameState: MutableStateFlow<Int> = MutableStateFlow(0)
|
||||
/**
|
||||
* 游戏状态: 本地定义状态+匹配状态
|
||||
* 本地定义状态:(NULL:不合法状态)
|
||||
* 匹配状态(服务端定义):(0:匹配中、1:匹配成功、2:游戏结束、3:匹配失败)
|
||||
*/
|
||||
val gameStateFlow: MutableStateFlow<Int?> = MutableStateFlow(0)
|
||||
|
||||
fun requestRoomInfo() {
|
||||
val gameIconFlow = MutableStateFlow<String?>(null)
|
||||
|
||||
val gameIdFlow = MutableStateFlow<String?>(null)
|
||||
|
||||
val roomIdFlow = MutableStateFlow<Long?>(null)
|
||||
|
||||
val imIdFlow = MutableStateFlow<Long?>(null)
|
||||
|
||||
val scoresFlow = MutableStateFlow<List<Double>?>(null)
|
||||
|
||||
override fun onStart(context: RoomContext) {
|
||||
super.onStart(context)
|
||||
requestRoomInfo()
|
||||
}
|
||||
|
||||
private fun requestRoomInfo() {
|
||||
safeLaunch {
|
||||
val info = GameModel2.getGameRoomInfo()
|
||||
if (info != null) {
|
||||
syncRoomInfo(info)
|
||||
} else {
|
||||
syncGameState(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun syncRoomInfo(info: GameRoomInfo) {
|
||||
roomIdFlow.value = info.chatRoomId
|
||||
imIdFlow.value = info.roomId
|
||||
gameIdFlow.value = info.data?.mgId
|
||||
gameIconFlow.value = info.data?.gameRoomIcon
|
||||
scoresFlow.value = info.data?.scores
|
||||
syncGameState(info.data?.matchStatus)
|
||||
}
|
||||
|
||||
private fun syncGameState(matchStatus: Int?) {
|
||||
gameStateFlow.value = matchStatus
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ import com.chwl.app.game.data.bean.GameConfigBean
|
||||
import com.chwl.app.game.data.bean.GameRoomInfo
|
||||
import com.chwl.core.base.BaseModel
|
||||
import com.chwl.core.bean.response.ServiceResult
|
||||
import com.chwl.core.bean.room.BaseRoomInfo
|
||||
import com.chwl.core.home.bean.*
|
||||
import com.chwl.core.utils.net.launchRequest
|
||||
import com.chwl.library.net.rxnet.RxNet
|
||||
@@ -11,6 +12,7 @@ import retrofit2.http.Field
|
||||
import retrofit2.http.FormUrlEncoded
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Query
|
||||
|
||||
object GameModel2 : BaseModel() {
|
||||
|
||||
@@ -23,22 +25,20 @@ object GameModel2 : BaseModel() {
|
||||
|
||||
suspend fun getGameRoomInfo(): GameRoomInfo? =
|
||||
launchRequest {
|
||||
api.getGameRoomInfo()
|
||||
api.getChatRoomInfo(BaseRoomInfo.ROOM_TYPE_GAME)
|
||||
}
|
||||
|
||||
suspend fun startGame(gameId: String, gameMode: Int): String? =
|
||||
suspend fun startGame(gameId: String, gameMode: Int): Long? =
|
||||
launchRequest {
|
||||
api.startGame(gameId, gameMode)
|
||||
}
|
||||
|
||||
private interface Api {
|
||||
/**
|
||||
* 游戏房信息
|
||||
*
|
||||
* @return -
|
||||
* 房间信息
|
||||
*/
|
||||
@GET("resource/")
|
||||
suspend fun getGameRoomInfo(): ServiceResult<GameRoomInfo>
|
||||
@GET("chatRoom/get")
|
||||
suspend fun getChatRoomInfo(@Query("roomType") roomType: Int): ServiceResult<GameRoomInfo>
|
||||
|
||||
/**
|
||||
* 首页游戏配置
|
||||
@@ -54,7 +54,7 @@ object GameModel2 : BaseModel() {
|
||||
suspend fun startGame(
|
||||
@Field("mgId") mgId: String,
|
||||
@Field("gameMode") gameMode: Int
|
||||
): ServiceResult<String>
|
||||
): ServiceResult<Long>
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.chwl.app.game.data.bean
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import java.io.Serializable
|
||||
|
||||
@Keep
|
||||
class GameRoomData : Serializable {
|
||||
val mgId: String? = null
|
||||
val gameRoomIcon: String? = null
|
||||
val configJson: String? = null
|
||||
val scores: MutableList<Double>? = null
|
||||
|
||||
// 匹配状态(0:匹配中、1:匹配成功、2:游戏结束、3:匹配失败)
|
||||
val matchStatus: Int? = null
|
||||
|
||||
// 轮次状态(0:进行中、1:结束)
|
||||
val roundStatus: Int? = null
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
package com.chwl.app.game.data.bean
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import java.io.Serializable
|
||||
import com.chwl.core.bean.room.BaseRoomInfo
|
||||
|
||||
@Keep
|
||||
class GameRoomInfo : Serializable {
|
||||
class GameRoomInfo : BaseRoomInfo<GameRoomData>() {
|
||||
}
|
@@ -63,7 +63,7 @@ class GameBuyDialog(private val gameConfig: GameConfigBean, private val gameMode
|
||||
if (it.isSuccess) {
|
||||
dismissAllowingStateLoss()
|
||||
val intent =
|
||||
GameIntent(1, gameConfig.mgId ?: 0L, gameMode.gameMode ?: -1)
|
||||
GameIntent(it.data ?: 0, gameConfig.mgId ?: 0L, gameMode.gameMode ?: -1)
|
||||
GameActivity.start(requireContext(), intent)
|
||||
} else {
|
||||
if (it.code == BalanceNotEnoughExeption.code) {
|
||||
|
@@ -2,17 +2,26 @@ package com.chwl.app.game.ui.game
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.chwl.app.R
|
||||
import com.chwl.app.common.widget.dialog.DialogManager.OkCancelDialogListener
|
||||
import com.chwl.app.databinding.GameActivityBinding
|
||||
import com.chwl.app.game.core.BaseGameActivity
|
||||
import com.chwl.app.game.core.GameContext
|
||||
import com.chwl.app.game.core.GameStateAbility
|
||||
import com.chwl.app.game.core.engine.model.GameViewInfoModel.GameViewRectModel
|
||||
import com.chwl.app.game.ui.game.widgets.bottom.GameBottomWidget
|
||||
import com.chwl.app.game.ui.game.widgets.message.GameMessageWidget
|
||||
import com.chwl.app.game.ui.game.widgets.queue.GameQueueWidget
|
||||
import com.chwl.app.ui.utils.ImageLoadUtilsV2
|
||||
import com.chwl.app.ui.utils.load
|
||||
import com.chwl.app.ui.utils.loadImage
|
||||
import com.chwl.core.support.room.RoomView
|
||||
import com.example.lib_utils.ktx.singleClick
|
||||
import com.example.lib_utils.log.ILog
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.zip
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class GameActivity : BaseGameActivity<GameActivityBinding>(), RoomView, ILog {
|
||||
|
||||
@@ -32,12 +41,12 @@ class GameActivity : BaseGameActivity<GameActivityBinding>(), RoomView, ILog {
|
||||
return
|
||||
}
|
||||
super.init()
|
||||
initGameEngine()
|
||||
viewModel.init(intentData)
|
||||
initGameEngine(intentData)
|
||||
}
|
||||
|
||||
private fun initGameEngine(intentData: GameIntent) {
|
||||
gameViewModel.init(lifecycle, binding.layoutGame)
|
||||
private fun initGameEngine() {
|
||||
gameEngineViewModel.init(lifecycle, binding.layoutGame)
|
||||
binding.spaceGameRect.post {
|
||||
val rect = GameViewRectModel().apply {
|
||||
top = binding.spaceGameRect.top
|
||||
@@ -45,8 +54,7 @@ class GameActivity : BaseGameActivity<GameActivityBinding>(), RoomView, ILog {
|
||||
}
|
||||
logD("initGameEngine() height:${binding.root.height}")
|
||||
logD("initGameEngine() top:${rect.top} bottom:${rect.bottom}")
|
||||
gameViewModel.setGameViewRect(rect)
|
||||
gameViewModel.loadGame(this, intentData.roomId.toString(), intentData.gameId)
|
||||
gameEngineViewModel.setGameViewRect(rect)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +67,45 @@ class GameActivity : BaseGameActivity<GameActivityBinding>(), RoomView, ILog {
|
||||
|
||||
override fun initObserver() {
|
||||
super.initObserver()
|
||||
viewModel.gameContextLiveData.observe(this) {
|
||||
updateGameContext(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateGameContext(gameContext: GameContext) {
|
||||
val stateAbility =
|
||||
gameContext.findAbility<GameStateAbility>(GameStateAbility::class.java.simpleName)
|
||||
?: return
|
||||
lifecycleScope.launch {
|
||||
stateAbility.gameIconFlow.collectLatest {
|
||||
binding.ivLogo.loadImage(it)
|
||||
}
|
||||
|
||||
stateAbility.scoresFlow.collectLatest {
|
||||
val number = it?.first()?.toString() ?: ""
|
||||
binding.tvAwardValue.text = number
|
||||
binding.tvAwardTips.text = getString(R.string.game_award_tips_format, number)
|
||||
}
|
||||
updateGameEngine(stateAbility)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateGameEngine(stateAbility: GameStateAbility) {
|
||||
stateAbility.imIdFlow.zip(stateAbility.roomIdFlow) { imId, roomId ->
|
||||
if (imId != null && roomId != null) {
|
||||
Pair(imId, roomId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.collectLatest {
|
||||
if (it != null) {
|
||||
gameEngineViewModel.loadGame(
|
||||
this@GameActivity,
|
||||
it.second.toString(),
|
||||
it.first
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun initWidgets() {
|
||||
|
@@ -3,9 +3,6 @@ package com.chwl.app.game.ui.game
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.chwl.app.base.BaseViewModel
|
||||
import com.chwl.app.game.core.GameContext
|
||||
import com.chwl.app.game.core.GameIMEngineAbility
|
||||
import com.chwl.app.public_chat.core.ChatRoomClientManager
|
||||
import com.chwl.core.initial.InitialModel
|
||||
|
||||
class GameViewModel : BaseViewModel() {
|
||||
|
||||
@@ -15,8 +12,6 @@ class GameViewModel : BaseViewModel() {
|
||||
val gameContext = GameContext(intent.roomId)
|
||||
gameContext.performStart()
|
||||
gameContextLiveData.value = gameContext
|
||||
gameContext.findAbility<GameIMEngineAbility>(GameIMEngineAbility::class.java.simpleName)?.enterRoom(
|
||||
InitialModel.get().publicChatSessionId)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
@@ -10,7 +10,9 @@ import com.chwl.app.support.FragmentVisibleStateHelper
|
||||
import com.chwl.app.ui.pay.ChargeActivity
|
||||
import com.chwl.app.ui.utils.load
|
||||
import com.chwl.app.ui.utils.loadAvatar
|
||||
import com.chwl.app.ui.webview.CommonWebViewActivity
|
||||
import com.chwl.app.ui.widget.recyclerview.decoration.GridSpacingItemNewDecoration
|
||||
import com.chwl.core.UriProvider
|
||||
import com.chwl.core.pay.PayModel
|
||||
import com.chwl.core.pay.event.GetWalletInfoEvent
|
||||
import com.chwl.core.pay.event.UpdateWalletInfoEvent
|
||||
@@ -55,7 +57,7 @@ class GameHomeFragment : BaseViewBindingFragment<GameHomeFragmentBinding>(), Mai
|
||||
ChargeActivity.start(context)
|
||||
}
|
||||
binding.ivRank.singleClick {
|
||||
toast("RANK")
|
||||
CommonWebViewActivity.start(requireContext(), UriProvider.getGameRank())
|
||||
}
|
||||
adapter.setOnItemClickListener { _, view, position ->
|
||||
val config = viewModel.gameConfigLiveData.value?.data
|
||||
|
@@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
class GameHomeViewModel : BaseViewModel() {
|
||||
val gameConfigLiveData = MutableLiveData<BeanResult<GameConfigBean>?>()
|
||||
|
||||
val startGameFlow = MutableSharedFlow<BeanResult<String>>()
|
||||
val startGameFlow = MutableSharedFlow<BeanResult<Long>>()
|
||||
|
||||
fun getGameList() {
|
||||
safeLaunch(onError = {
|
||||
|
@@ -25,6 +25,7 @@
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_logo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="@dimen/dp_11"
|
||||
|
@@ -303,6 +303,15 @@ public class UriProvider {
|
||||
return JAVA_WEB_URL.concat("/molistar/modules/rule/luckyGiftRule.html?giftID=" + giftID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 游戏排行榜
|
||||
*/
|
||||
public static String getGameRank() {
|
||||
return JAVA_WEB_URL.concat("/molistar/modules/gameRank/index.html");
|
||||
}
|
||||
|
||||
|
||||
public static String toFullUrl(String shortUrl) {
|
||||
if (shortUrl == null) {
|
||||
return null;
|
||||
|
23
core/src/main/java/com/chwl/core/bean/room/BaseRoomInfo.kt
Normal file
23
core/src/main/java/com/chwl/core/bean/room/BaseRoomInfo.kt
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.chwl.core.bean.room
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import java.io.Serializable
|
||||
|
||||
@Keep
|
||||
abstract class BaseRoomInfo<T> : Serializable {
|
||||
companion object {
|
||||
const val ROOM_TYPE_GAME = 0
|
||||
}
|
||||
|
||||
val chatRoomId: Long? = null
|
||||
|
||||
// 云信ID
|
||||
val roomId: Long? = null
|
||||
|
||||
val roomMics: MutableList<RoomMicBean>? = null
|
||||
|
||||
val data: T? = null
|
||||
|
||||
// 房间类型(0:小游戏)
|
||||
val roomType: Int? = null
|
||||
}
|
16
core/src/main/java/com/chwl/core/bean/room/RoomMicBean.kt
Normal file
16
core/src/main/java/com/chwl/core/bean/room/RoomMicBean.kt
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.chwl.core.bean.room
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import java.io.Serializable
|
||||
|
||||
@Keep
|
||||
class RoomMicBean : Serializable {
|
||||
val position: Int? = null
|
||||
val micUser: RoomMicUserInfo? = null
|
||||
|
||||
// 是否被锁
|
||||
val micState: Int? = null
|
||||
|
||||
// 是否被禁
|
||||
val posState: Int? = null
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.chwl.core.bean.room
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import java.io.Serializable
|
||||
|
||||
@Keep
|
||||
class RoomMicUserInfo : Serializable {
|
||||
val avatar: String? = null
|
||||
val erbanNo: Long? = null
|
||||
val nick: String? = null
|
||||
val uid: String? = null
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.chwl.core.support.room
|
||||
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.chwl.core.room.core.RoomDataService
|
||||
@@ -12,7 +13,7 @@ import com.chwl.core.support.room.lifecycle.RoomLifecycleRegistry
|
||||
* Desc:一个房间
|
||||
* @param roomId roomUid
|
||||
**/
|
||||
abstract class RoomContext(val roomId: Long) : ILog {
|
||||
abstract class RoomContext(var roomId: Long) : ILog {
|
||||
|
||||
/**
|
||||
* 生命周期处理
|
||||
@@ -31,7 +32,8 @@ abstract class RoomContext(val roomId: Long) : ILog {
|
||||
/**
|
||||
* 启动(进入房间)
|
||||
*/
|
||||
fun performStart() {
|
||||
@CallSuper
|
||||
open fun performStart() {
|
||||
logI("performStart()", filePrinter = true)
|
||||
roomLifecycle.handleLifecycleEvent(this, RoomLifecycle.Event.START)
|
||||
}
|
||||
@@ -39,7 +41,8 @@ abstract class RoomContext(val roomId: Long) : ILog {
|
||||
/**
|
||||
* 停止(退出房间)
|
||||
*/
|
||||
fun performStop() {
|
||||
@CallSuper
|
||||
open fun performStop() {
|
||||
logI("performStop()", filePrinter = true)
|
||||
roomLifecycle.handleLifecycleEvent(this, RoomLifecycle.Event.STOP)
|
||||
onCleared()
|
||||
|
Reference in New Issue
Block a user