Skip to content

Commit

Permalink
Replaced observers abstract methods with interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
MajeurAndroid committed Jul 7, 2020
1 parent 510921a commit 05bbad5
Show file tree
Hide file tree
Showing 9 changed files with 677 additions and 601 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.util.Base64
import com.majeur.psclient.service.observer.BattleMessageObserver
import com.majeur.psclient.service.observer.ChatRoomMessageObserver
import com.majeur.psclient.service.observer.GlobalMessageObserver
import com.majeur.psclient.util.S
import okhttp3.*
import org.json.JSONException
Expand All @@ -17,10 +20,10 @@ import java.util.concurrent.atomic.AtomicBoolean
class ShowdownService : Service() {

companion object {
private const val WS_CLOSE_NORMAL: Int = 1000
private const val WS_CLOSE_GOING_AWAY: Int = 1001
private const val WS_CLOSE_NETWORK_ERROR: Int = 4001
private const val SHOWDOWN_SOCKET_URL: String = "wss://sim3.psim.us/showdown/websocket"
private const val WS_CLOSE_NORMAL = 1000
private const val WS_CLOSE_GOING_AWAY = 1001
private const val WS_CLOSE_NETWORK_ERROR = 4001
private const val SHOWDOWN_SOCKET_URL = "wss://sim3.psim.us/showdown/websocket"
}

lateinit var okHttpClient: OkHttpClient
Expand All @@ -29,10 +32,13 @@ class ShowdownService : Service() {
private lateinit var binder: Binder
private lateinit var uiHandler: Handler

private val messageObservers = mutableListOf<AbsMessageObserver>()
val globalMessageObserver by lazy { GlobalMessageObserver(this) }
val chatMessageObserver by lazy { ChatRoomMessageObserver(this) }
val battleMessageObserver by lazy { BattleMessageObserver(this) }
private val messageObservers get() = listOf(globalMessageObserver, chatMessageObserver, battleMessageObserver)

private val sharedData = mutableMapOf<String, Any>()
private var webSocket: WebSocket? = null
private var messageCache = mutableListOf<String>()
private var _connected = AtomicBoolean(false)

var isConnected: Boolean
Expand Down Expand Up @@ -100,16 +106,6 @@ class ShowdownService : Service() {
}
}

fun registerMessageObserver(observer: AbsMessageObserver) {
messageObservers.add(observer)
observer.service = this
}

fun unregisterMessageObserver(observer: AbsMessageObserver) {
messageObservers.remove(observer)
observer.service = null
}

private fun processServerData(data: String) {
if (data[0] == '>') dispatchServerData(data.removePrefix(">").substringBefore("\n"),
data.substringAfter("\n"))
Expand All @@ -123,13 +119,19 @@ class ShowdownService : Service() {
}

private fun dispatchMessage(msg: ServerMessage) {
messageObservers
val observers = messageObservers
val observersInterceptingBefore = observers
.filter { it.interceptCommandBefore.contains(msg.command) }
val observersInterceptingAfter = observers
.filter { it.interceptCommandAfter.contains(msg.command) }

observersInterceptingBefore
.forEach { it.postMessage(msg, forcePost = true) }
messageObservers
observers
.minus(observersInterceptingBefore)
.forEach { it.postMessage(msg) }
messageObservers
.filter { it.interceptCommandAfter.contains(msg.command) }
observersInterceptingAfter
.minus(observersInterceptingBefore)
.forEach { it.postMessage(msg, forcePost = true) }
}

Expand All @@ -140,7 +142,7 @@ class ShowdownService : Service() {

private val webSocketListener = object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
Timber.tag("WebSocket[OPEN]").i("Host: " + response.request().url().host())
Timber.tag("WebSocket[OPEN]").i("Host: ${response.request().url().host()}")
isConnected = true
uiHandler.post {
dispatchMessage(ServerMessage("lobby", "|connected|"))
Expand All @@ -150,12 +152,7 @@ class ShowdownService : Service() {
override fun onMessage(webSocket: WebSocket, data: String) {
Timber.tag("WebSocket[RECEIVE]").i(data)
uiHandler.post {
if (messageObservers.isEmpty()) {
messageCache.add(data)
} else {
while (messageCache.isNotEmpty()) processServerData(messageCache.removeAt(0))
processServerData(data)
}
processServerData(data)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
package com.majeur.psclient.service
package com.majeur.psclient.service.observer

abstract class AbsMessageObserver {
import com.majeur.psclient.service.ServerMessage
import com.majeur.psclient.service.ShowdownService

abstract class AbsMessageObserver<C : AbsMessageObserver.UiCallbacks>(
val service: ShowdownService
) {

open var uiCallbacks: C? = null

open var observedRoomId: String? = null

Expand All @@ -10,11 +17,13 @@ abstract class AbsMessageObserver {
var interceptCommandAfter = setOf<String>()
protected set

var service: ShowdownService? = null

fun postMessage(message: ServerMessage, forcePost: Boolean = false) {
if (forcePost || observedRoomId == message.roomId) onMessage(message)
}

protected abstract fun onMessage(message: ServerMessage)

interface UiCallbacks {

}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.majeur.psclient.service
package com.majeur.psclient.service.observer

import android.content.Context
import android.os.Looper
import com.majeur.psclient.io.BattleTextBuilder
import com.majeur.psclient.model.battle.*
import com.majeur.psclient.model.common.Colors
import com.majeur.psclient.model.pokemon.BasePokemon
import com.majeur.psclient.model.pokemon.BattlingPokemon
import com.majeur.psclient.service.ActionQueue
import com.majeur.psclient.service.ServerMessage
import com.majeur.psclient.service.ShowdownService
import com.majeur.psclient.util.*
import org.json.JSONException
import org.json.JSONObject
Expand All @@ -15,7 +17,10 @@ import java.util.*
import kotlin.math.abs
import kotlin.math.roundToInt

abstract class BattleMessageObserver : RoomMessageObserver() {
class BattleMessageObserver(service: ShowdownService)
: RoomMessageObserver<BattleMessageObserver.UiCallbacks>(service) {

override var uiCallbacks: UiCallbacks? = null

var gameType: GameType? = null
private set
Expand All @@ -25,12 +30,11 @@ abstract class BattleMessageObserver : RoomMessageObserver() {

var gen: Int = 0

private lateinit var battleTextBuilder: BattleTextBuilder
private val battleTextBuilder: BattleTextBuilder
private val actionQueue = ActionQueue(Looper.getMainLooper())
private var p1Username: String? = null
private var p2Username: String? = null


private var previewPokemonIndexes = IntArray(2)
private var lastActionRequest: BattleActionRequest? = null
private var trainerPokemons: Array<BattlingPokemon?> = emptyArray()
Expand All @@ -39,8 +43,8 @@ abstract class BattleMessageObserver : RoomMessageObserver() {
private val activeFieldEffects = LinkedList<String>() // We use LinkedList specific methods.
private var lastMove: String? = null

fun gotContext(context: Context?) {
battleTextBuilder = BattleTextBuilder(context)
init {
battleTextBuilder = BattleTextBuilder(service)
battleTextBuilder.setPokemonIdFactory { rawString: String ->
try {
return@setPokemonIdFactory PokemonId(getPlayer(rawString), rawString)
Expand All @@ -53,6 +57,7 @@ abstract class BattleMessageObserver : RoomMessageObserver() {
}

public override fun onRoomInit() {
super.onRoomInit()
p1Username = null
p2Username = null
gameType = null
Expand All @@ -66,6 +71,7 @@ abstract class BattleMessageObserver : RoomMessageObserver() {
}

public override fun onRoomDeInit() {
super.onRoomDeInit()
p1Username = null
p2Username = null
gameType = null
Expand Down Expand Up @@ -105,7 +111,7 @@ abstract class BattleMessageObserver : RoomMessageObserver() {

private fun handleRegularCommand(message: ServerMessage) = when (message.command) {
"gen" -> gen = message.nextArg.toInt()
"break" -> onMarkBreak()
"break" -> handleBreak()
"move" -> handleMove(message)
"switch" -> handleSwitch(message)
"drag" -> handleDrag(message)
Expand Down Expand Up @@ -141,6 +147,9 @@ abstract class BattleMessageObserver : RoomMessageObserver() {
else -> Unit
}

private fun handleBreak() {
actionQueue.enqueueMinorAction { onMarkBreak() }
}

// |move|p2a: Pinsir|Close Combat|p1a: Latias|[miss]
// |move|p2a: Dialga|Flash Cannon|p1: Shiftry|[notarget]
Expand Down Expand Up @@ -801,33 +810,51 @@ abstract class BattleMessageObserver : RoomMessageObserver() {
actionQueue.enqueueAction { super@BattleMessageObserver.printHtml(html) }
}

protected abstract fun onPlayerInit(playerUsername: String, foeUsername: String)
protected abstract fun onFaint(id: PokemonId)
protected abstract fun onTeamSize(player: Player, size: Int)
protected abstract fun onBattleStarted()
protected abstract fun onBattleEnded(winner: String)
protected abstract fun onTimerEnabled(enabled: Boolean)
protected abstract fun onPreviewStarted()
protected abstract fun onAddPreviewPokemon(id: PokemonId, pokemon: BasePokemon, hasItem: Boolean)
protected abstract fun onSwitch(newPokemon: BattlingPokemon)
protected abstract fun onDetailsChanged(newPokemon: BattlingPokemon)
protected abstract fun onMove(sourceId: PokemonId, targetId: PokemonId?, moveName: String, shouldAnim: Boolean)
protected abstract fun onSwap(id: PokemonId, targetIndex: Int)
protected abstract fun onRequestAsked(request: BattleActionRequest)
protected abstract fun onHealthChanged(id: PokemonId, condition: Condition)
protected abstract fun onStatusChanged(id: PokemonId, status: String?)
protected abstract fun onStatChanged(id: PokemonId)
protected abstract fun onDisplayBattleToast(id: PokemonId, text: String, color: Int)
protected abstract fun onFieldEffectChanged(weather: String?)
protected abstract fun onSideChanged(player: Player, side: String, start: Boolean)
protected abstract fun onVolatileStatusChanged(id: PokemonId, vStatus: String, start: Boolean)
protected abstract fun onPrintBattleMessage(message: CharSequence)
protected open fun onMarkBreak() {
// mActionQueue.enqueueMinorAction(new Runnable() {
// @Override
// public void run() {
// printMessage("");
// }
// });
private fun onMarkBreak() = uiCallbacks?.onMarkBreak()
private fun onPlayerInit(playerUsername: String, foeUsername: String) = uiCallbacks?.onPlayerInit(playerUsername, foeUsername)
private fun onFaint(id: PokemonId) = uiCallbacks?.onFaint(id)
private fun onTeamSize(player: Player, size: Int) = uiCallbacks?.onTeamSize(player, size)
private fun onBattleStarted() = uiCallbacks?.onBattleStarted()
private fun onBattleEnded(winner: String) = uiCallbacks?.onBattleEnded(winner)
private fun onTimerEnabled(enabled: Boolean) = uiCallbacks?.onTimerEnabled(enabled)
private fun onPreviewStarted() = uiCallbacks?.onPreviewStarted()
private fun onAddPreviewPokemon(id: PokemonId, pokemon: BasePokemon, hasItem: Boolean) = uiCallbacks?.onAddPreviewPokemon(id, pokemon, hasItem)
private fun onSwitch(newPokemon: BattlingPokemon) = uiCallbacks?.onSwitch(newPokemon)
private fun onDetailsChanged(newPokemon: BattlingPokemon) = uiCallbacks?.onDetailsChanged(newPokemon)
private fun onMove(sourceId: PokemonId, targetId: PokemonId?, moveName: String, shouldAnim: Boolean) = uiCallbacks?.onMove(sourceId, targetId, moveName, shouldAnim)
private fun onSwap(id: PokemonId, targetIndex: Int) = uiCallbacks?.onSwap(id, targetIndex)
private fun onRequestAsked(request: BattleActionRequest) = uiCallbacks?.onRequestAsked(request)
private fun onHealthChanged(id: PokemonId, condition: Condition) = uiCallbacks?.onHealthChanged(id, condition)
private fun onStatusChanged(id: PokemonId, status: String?) = uiCallbacks?.onStatusChanged(id, status)
private fun onStatChanged(id: PokemonId) = uiCallbacks?.onStatChanged(id)
private fun onDisplayBattleToast(id: PokemonId, text: String, color: Int) = uiCallbacks?.onDisplayBattleToast(id, text, color)
private fun onFieldEffectChanged(weather: String?) = uiCallbacks?.onFieldEffectChanged(weather)
private fun onSideChanged(player: Player, side: String, start: Boolean) = uiCallbacks?.onSideChanged(player, side, start)
private fun onVolatileStatusChanged(id: PokemonId, vStatus: String, start: Boolean) = uiCallbacks?.onVolatileStatusChanged(id, vStatus, start)
private fun onPrintBattleMessage(message: CharSequence) = uiCallbacks?.onPrintBattleMessage(message)

interface UiCallbacks : RoomMessageObserver.UiCallbacks {
fun onMarkBreak()
fun onPlayerInit(playerUsername: String, foeUsername: String)
fun onFaint(id: PokemonId)
fun onTeamSize(player: Player, size: Int)
fun onBattleStarted()
fun onBattleEnded(winner: String)
fun onTimerEnabled(enabled: Boolean)
fun onPreviewStarted()
fun onAddPreviewPokemon(id: PokemonId, pokemon: BasePokemon, hasItem: Boolean)
fun onSwitch(newPokemon: BattlingPokemon)
fun onDetailsChanged(newPokemon: BattlingPokemon)
fun onMove(sourceId: PokemonId, targetId: PokemonId?, moveName: String, shouldAnim: Boolean)
fun onSwap(id: PokemonId, targetIndex: Int)
fun onRequestAsked(request: BattleActionRequest)
fun onHealthChanged(id: PokemonId, condition: Condition)
fun onStatusChanged(id: PokemonId, status: String?)
fun onStatChanged(id: PokemonId)
fun onDisplayBattleToast(id: PokemonId, text: String, color: Int)
fun onFieldEffectChanged(weather: String?)
fun onSideChanged(player: Player, side: String, start: Boolean)
fun onVolatileStatusChanged(id: PokemonId, vStatus: String, start: Boolean)
fun onPrintBattleMessage(message: CharSequence)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.majeur.psclient.service.observer

import com.majeur.psclient.service.ShowdownService

class ChatRoomMessageObserver(service: ShowdownService)
: RoomMessageObserver<ChatRoomMessageObserver.UiCallbacks>(service) {

override var uiCallbacks: UiCallbacks? = null

interface UiCallbacks : RoomMessageObserver.UiCallbacks {
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package com.majeur.psclient.service
package com.majeur.psclient.service.observer

import com.majeur.psclient.model.AvailableBattleRoomsInfo
import com.majeur.psclient.model.ChatRoomInfo
import com.majeur.psclient.model.common.BattleFormat
import com.majeur.psclient.service.ServerMessage
import com.majeur.psclient.service.ShowdownService
import com.majeur.psclient.util.Utils
import org.json.JSONException
import org.json.JSONObject
import timber.log.Timber
import java.util.*

abstract class GlobalMessageObserver : AbsMessageObserver() {
class GlobalMessageObserver(service: ShowdownService)
: AbsMessageObserver<GlobalMessageObserver.UiCallbacks>(service) {

override var uiCallbacks: UiCallbacks? = null

override var observedRoomId: String? = "lobby"

Expand Down Expand Up @@ -239,19 +244,36 @@ abstract class GlobalMessageObserver : AbsMessageObserver() {
return privateMessages[with]
}

protected abstract fun onConnectedToServer()
protected abstract fun onUserChanged(userName: String, isGuest: Boolean, avatarId: String)
protected abstract fun onUpdateCounts(userCount: Int, battleCount: Int)
protected abstract fun onBattleFormatsChanged(battleFormats: List<@JvmSuppressWildcards BattleFormat.Category>)
protected abstract fun onSearchBattlesChanged(searching: List<String>, games: Map<String, String>)
protected abstract fun onUserDetails(id: String, name: String, online: Boolean, group: String, rooms: List<String>, battles: List<String>)
protected abstract fun onShowPopup(message: String)
protected abstract fun onAvailableRoomsChanged(officialRooms: List<ChatRoomInfo>, chatRooms: List<ChatRoomInfo>)
protected abstract fun onAvailableBattleRoomsChanged(availableRoomsInfo: AvailableBattleRoomsInfo)
protected abstract fun onNewPrivateMessage(with: String, message: String)
protected abstract fun onChallengesChange(to: String?, format: String?, from: Map<String, String>)
protected abstract fun onRoomInit(roomId: String, type: String)
protected abstract fun onRoomDeinit(roomId: String)
protected abstract fun onNetworkError()
protected fun onConnectedToServer() = uiCallbacks?.onConnectedToServer()
protected fun onUserChanged(userName: String, isGuest: Boolean, avatarId: String) = uiCallbacks?.onUserChanged(userName, isGuest, avatarId)
protected fun onUpdateCounts(userCount: Int, battleCount: Int) = uiCallbacks?.onUpdateCounts(userCount, battleCount)
protected fun onBattleFormatsChanged(battleFormats: List<BattleFormat.Category>) = uiCallbacks?.onBattleFormatsChanged(battleFormats)
protected fun onSearchBattlesChanged(searching: List<String>, games: Map<String, String>) = uiCallbacks?.onSearchBattlesChanged(searching, games)
protected fun onUserDetails(id: String, name: String, online: Boolean, group: String, rooms: List<String>, battles: List<String>) = uiCallbacks?.onUserDetails(id, name, online, group, rooms, battles)
protected fun onShowPopup(message: String) = uiCallbacks?.onShowPopup(message)
protected fun onAvailableRoomsChanged(officialRooms: List<ChatRoomInfo>, chatRooms: List<ChatRoomInfo>) = uiCallbacks?.onAvailableRoomsChanged(officialRooms, chatRooms)
protected fun onAvailableBattleRoomsChanged(availableRoomsInfo: AvailableBattleRoomsInfo) = uiCallbacks?.onAvailableBattleRoomsChanged(availableRoomsInfo)
protected fun onNewPrivateMessage(with: String, message: String) = uiCallbacks?.onNewPrivateMessage(with, message)
protected fun onChallengesChange(to: String?, format: String?, from: Map<String, String>) = uiCallbacks?.onChallengesChange(to, format, from)
protected fun onRoomInit(roomId: String, type: String) = uiCallbacks?.onRoomInit(roomId, type)
protected fun onRoomDeinit(roomId: String) = uiCallbacks?.onRoomDeinit(roomId)
protected fun onNetworkError() = uiCallbacks?.onNetworkError()

interface UiCallbacks : AbsMessageObserver.UiCallbacks {
fun onConnectedToServer()
fun onUserChanged(userName: String, isGuest: Boolean, avatarId: String)
fun onUpdateCounts(userCount: Int, battleCount: Int)
fun onBattleFormatsChanged(battleFormats: List<@JvmSuppressWildcards BattleFormat.Category>)
fun onSearchBattlesChanged(searching: List<String>, games: Map<String, String>)
fun onUserDetails(id: String, name: String, online: Boolean, group: String, rooms: List<String>, battles: List<String>)
fun onShowPopup(message: String)
fun onAvailableRoomsChanged(officialRooms: List<ChatRoomInfo>, chatRooms: List<ChatRoomInfo>)
fun onAvailableBattleRoomsChanged(availableRoomsInfo: AvailableBattleRoomsInfo)
fun onNewPrivateMessage(with: String, message: String)
fun onChallengesChange(to: String?, format: String?, from: Map<String, String>)
fun onRoomInit(roomId: String, type: String)
fun onRoomDeinit(roomId: String)
fun onNetworkError()
}
}

Loading

0 comments on commit 05bbad5

Please sign in to comment.