First push on branch.

This commit is contained in:
lightheel 2025-08-01 15:42:37 -04:00
parent 0b1eed7da9
commit a011ae39a4
9 changed files with 654 additions and 1 deletions

View File

@ -91,4 +91,11 @@ dependencies {
implementation("com.google.android.material:material:1.2.0") implementation("com.google.android.material:material:1.2.0")
implementation(libs.protobuf.javalite) implementation(libs.protobuf.javalite)
implementation("androidx.compose.material:material") implementation("androidx.compose.material:material")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.google.code.gson:gson:2.10.1")
// HTTP request logging
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
} }

View File

@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" /> <uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:name=".di.VBHelper" android:name=".di.VBHelper"
@ -15,6 +16,7 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.VBHelper" android:theme="@style/Theme.VBHelper"
android:usesCleartextTraffic="true"
tools:targetApi="31"> tools:targetApi="31">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@ -0,0 +1,13 @@
package com.github.nacabaro.vbhelper.battle
data class APIBattleCharacter(
val name: String,
val namekey: String,
val charaId: String,
val stage: Int,
val attribute: Int,
val baseHp: Int,
val currentHp: Int,
val baseBp: Float,
val baseAp: Float
)

View File

@ -0,0 +1,13 @@
package com.github.nacabaro.vbhelper.battle
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface OpponentService {
@GET("api/opponents")
// This method returns a Call object with a generic
// type of DataModel, which represents
// the data model for the response.
fun getopponents(@Query("stage") stage: String): Call<OpponentsDataModel>
}

View File

@ -0,0 +1,5 @@
package com.github.nacabaro.vbhelper.battle
data class OpponentsDataModel (
val opponentsList: ArrayList<APIBattleCharacter>
):java.io.Serializable

View File

@ -0,0 +1,13 @@
package com.github.nacabaro.vbhelper.battle
data class PVPDataModel (
val status: String,
val state: Int,
val currentRound: Int,
val playerHP: Int,
val opponentHP: Int,
val playerAttackHit: Boolean,
val playerAttackDamage: Int,
val opponentAttackDamage: Int,
val winner: String
):java.io.Serializable

View File

@ -0,0 +1,13 @@
package com.github.nacabaro.vbhelper.battle
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface PVPService {
@GET("api/pvp")
// This method returns a Call object with a generic
// type of DataModel, which represents
// the data model for the response.
fun getwinner(@Query("apiStage") apiStage: Int, @Query("playerID") playerID: Int, @Query("playerDigi") playerDigi: String, @Query("playerStage") playerStage: Int, @Query("critBar") critBar: Int, @Query("opponentDigi") opponentDigi: String, @Query("opponentStage") opponentStage: Int): Call<PVPDataModel>
}

View File

@ -0,0 +1,179 @@
package com.github.nacabaro.vbhelper.battle
import android.content.Context
import retrofit2.Retrofit
import android.widget.Toast
import retrofit2.*
import retrofit2.converter.gson.GsonConverterFactory
class RetrofitHelper {
fun getOpponents(context: Context, stage: String, callback: (OpponentsDataModel) -> Unit) {
println("RetrofitHelper: Starting API call for stage: $stage")
try {
// Create a Retrofit instance with the base URL and
// a GsonConverterFactory for parsing the response.
val retrofit: Retrofit = Retrofit.Builder().baseUrl("http://192.168.0.230:8080/").addConverterFactory(
GsonConverterFactory.create()).build()
println("RetrofitHelper: Retrofit instance created")
// Create an ApiService instance from the Retrofit instance.
val service: OpponentService = retrofit.create<OpponentService>(OpponentService::class.java)
println("RetrofitHelper: Service created")
// Call the getopponents() method of the ApiService
// to make an API request.
val call: Call<OpponentsDataModel> = service.getopponents(stage)
println("RetrofitHelper: API call created, enqueueing...")
// Use the enqueue() method of the Call object to
// make an asynchronous API request.
call.enqueue(object : Callback<OpponentsDataModel> {
override fun onFailure(call: Call<OpponentsDataModel>, t: Throwable) {
println("RetrofitHelper: API call failed: ${t.message}")
t.printStackTrace()
Toast.makeText(context, "Request Fail", Toast.LENGTH_SHORT).show()
}
override fun onResponse(call: Call<OpponentsDataModel>, response: Response<OpponentsDataModel>) {
println("RetrofitHelper: API response received - Code: ${response.code()}")
println("RetrofitHelper: Response body: ${response.body()}")
if(response.isSuccessful){
println("RetrofitHelper: Response successful, calling callback")
val opponentsList: OpponentsDataModel = response.body() as OpponentsDataModel
callback(opponentsList)
} else {
println("RetrofitHelper: Response not successful - Error: ${response.errorBody()?.string()}")
}
}
})
} catch (e: Exception) {
println("RetrofitHelper: Exception in getOpponents: ${e.message}")
e.printStackTrace()
}
}
/*
fun getCombatWinner(context: Context, stage: String, callback: (CombatDataModel) -> Unit) {
// Create a Retrofit instance with the base URL and
// a GsonConverterFactory for parsing the response.
val retrofit: Retrofit = Retrofit.Builder().baseUrl("http://192.168.0.230:8080/").addConverterFactory(
GsonConverterFactory.create()).build()
// Create an ApiService instance from the Retrofit instance.
val service: CombatService = retrofit.create<CombatService>(CombatService::class.java)
// Call the getwinner() method of the ApiService
// to make an API request.
val call: Call<CombatDataModel> = service.getwinner(stage)
// Use the enqueue() method of the Call object to
// make an asynchronous API request.
call.enqueue(object : Callback<CombatDataModel> {
// This is an anonymous inner class that implements the Callback interface.
override fun onFailure(call: Call<CombatDataModel>, t: Throwable) {
// This method is called when the API request fails.
Toast.makeText(context, "Request Fail", Toast.LENGTH_SHORT).show()
}
override fun onResponse(call: Call<CombatDataModel>, response: Response<CombatDataModel>) {
// This method is called when the API response is received successfully.
if(response.isSuccessful){
// If the response is successful, parse the
// response body to a DataModel object.
val winner: CombatDataModel = response.body() as CombatDataModel
// Call the callback function with the DataModel
// object as a parameter.
callback(winner)
}
}
})
}
fun getBattleWinner(context: Context, playerDigi: String, playerStage: Int, opponentDigi: String, opponentStage: Int, callback: (BattleDataModel) -> Unit) {
// Create a Retrofit instance with the base URL and
// a GsonConverterFactory for parsing the response.
val retrofit: Retrofit = Retrofit.Builder().baseUrl("http://192.168.0.230:8080/").addConverterFactory(
GsonConverterFactory.create()).build()
// Create an ApiService instance from the Retrofit instance.
val service: BattleService = retrofit.create<BattleService>(BattleService::class.java)
// Call the getwinner() method of the ApiService
// to make an API request.
val call: Call<BattleDataModel> = service.getwinner(playerDigi, playerStage, opponentDigi, opponentStage)
// Use the enqueue() method of the Call object to
// make an asynchronous API request.
call.enqueue(object : Callback<BattleDataModel> {
// This is an anonymous inner class that implements the Callback interface.
override fun onFailure(call: Call<BattleDataModel>, t: Throwable) {
// This method is called when the API request fails.
Toast.makeText(context, "Request Fail", Toast.LENGTH_SHORT).show()
}
override fun onResponse(call: Call<BattleDataModel>, response: Response<BattleDataModel>) {
// This method is called when the API response is received successfully.
if(response.isSuccessful){
// If the response is successful, parse the
// response body to a DataModel object.
val winner: BattleDataModel = response.body() as BattleDataModel
// Call the callback function with the DataModel
// object as a parameter.
callback(winner)
}
}
})
}
*/
fun getPVPWinner(context: Context, apiStage: Int, playerID: Int, playerDigi: String, playerStage: Int, critBar: Int, opponentDigi: String, opponentStage: Int, callback: (PVPDataModel) -> Unit) {
// Create a Retrofit instance with the base URL and
// a GsonConverterFactory for parsing the response.
val retrofit: Retrofit = Retrofit.Builder().baseUrl("http://192.168.0.230:8080/").addConverterFactory(
GsonConverterFactory.create()).build()
// Create an ApiService instance from the Retrofit instance.
val service: PVPService = retrofit.create<PVPService>(PVPService::class.java)
// Call the getwinner() method of the ApiService
// to make an API request.
val call: Call<PVPDataModel> = service.getwinner(apiStage, playerID, playerDigi, playerStage, critBar, opponentDigi, opponentStage)
// Use the enqueue() method of the Call object to
// make an asynchronous API request.
call.enqueue(object : Callback<PVPDataModel> {
// This is an anonymous inner class that implements the Callback interface.
override fun onFailure(call: Call<PVPDataModel>, t: Throwable) {
// This method is called when the API request fails.
Toast.makeText(context, "Request Fail", Toast.LENGTH_SHORT).show()
}
override fun onResponse(call: Call<PVPDataModel>, response: Response<PVPDataModel>) {
// This method is called when the API response is received successfully.
if(response.isSuccessful){
// If the response is successful, parse the
// response body to a DataModel object.
val apiResults: PVPDataModel = response.body() as PVPDataModel
// Call the callback function with the DataModel
// object as a parameter.
callback(apiResults)
}
}
})
}
}

View File

@ -9,10 +9,269 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.material3.Button
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.dp
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.foundation.layout.Box
import androidx.compose.ui.platform.LocalContext
import androidx.compose.material3.ExperimentalMaterial3Api
import com.github.nacabaro.vbhelper.battle.APIBattleCharacter
import com.github.nacabaro.vbhelper.components.TopBanner import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.battle.RetrofitHelper
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun BattlesScreen() { fun BattlesScreen() {
var currentView by remember { mutableStateOf("main") }
var opponentsList by remember { mutableStateOf(ArrayList<APIBattleCharacter>()) }
var activeCharacter by remember { mutableStateOf<APIBattleCharacter?>(null) }
var expanded by remember { mutableStateOf(false) }
var selectedStage by remember { mutableStateOf("") }
val context = LocalContext.current
val rookieButton = @Composable {
Button(
onClick = {
println("Rookie button clicked - starting API call")
try {
RetrofitHelper().getOpponents(context, "rookie") { opponents ->
println("API call completed successfully")
try {
println("Received opponents data: $opponents")
println("Opponents list size: ${opponents.opponentsList.size}")
// For loop to check opponents and print their names
for (opponent in opponents.opponentsList) {
println("Opponent: ${opponent.name}")
}
// Store the opponents in your ArrayList
opponentsList.clear()
opponentsList.addAll(opponents.opponentsList)
println("Updated opponentsList size: ${opponentsList.size}")
println("About to change view to rookie")
currentView = "rookie"
println("View changed to rookie")
} catch (e: Exception) {
println("Error processing opponents data: ${e.message}")
e.printStackTrace()
}
}
} catch (e: Exception) {
println("Error calling getOpponents: ${e.message}")
e.printStackTrace()
}
}
) {
Text("Rookie Battles")
}
}
val championButton = @Composable {
Button(
onClick = {
println("Champion button clicked - starting API call")
try {
RetrofitHelper().getOpponents(context, "champion") { opponents ->
println("API call completed successfully")
try {
println("Received opponents data: $opponents")
println("Opponents list size: ${opponents.opponentsList.size}")
// For loop to check opponents and print their names
for (opponent in opponents.opponentsList) {
println("Opponent: ${opponent.name}")
}
// Store the opponents in your ArrayList
opponentsList.clear()
opponentsList.addAll(opponents.opponentsList)
println("Updated opponentsList size: ${opponentsList.size}")
println("About to change view to champion")
currentView = "champion"
println("View changed to champion")
} catch (e: Exception) {
println("Error processing opponents data: ${e.message}")
e.printStackTrace()
}
}
} catch (e: Exception) {
println("Error calling getOpponents: ${e.message}")
e.printStackTrace()
}
}
) {
Text("Champion Battles")
}
}
val ultimateButton = @Composable {
Button(
onClick = {
println("Ultimate button clicked - starting API call")
try {
RetrofitHelper().getOpponents(context, "ultimate") { opponents ->
println("API call completed successfully")
try {
println("Received opponents data: $opponents")
println("Opponents list size: ${opponents.opponentsList.size}")
// For loop to check opponents and print their names
for (opponent in opponents.opponentsList) {
println("Opponent: ${opponent.name}")
}
// Store the opponents in your ArrayList
opponentsList.clear()
opponentsList.addAll(opponents.opponentsList)
println("Updated opponentsList size: ${opponentsList.size}")
println("About to change view to ultimate")
currentView = "ultimate"
println("View changed to ultimate")
} catch (e: Exception) {
println("Error processing opponents data: ${e.message}")
e.printStackTrace()
}
}
} catch (e: Exception) {
println("Error calling getOpponents: ${e.message}")
e.printStackTrace()
}
}
) {
Text("Ultimate Battles")
}
}
val megaButton = @Composable {
Button(
onClick = {
println("Mega button clicked - starting API call")
try {
RetrofitHelper().getOpponents(context, "mega") { opponents ->
println("API call completed successfully")
try {
println("Received opponents data: $opponents")
println("Opponents list size: ${opponents.opponentsList.size}")
// For loop to check opponents and print their names
for (opponent in opponents.opponentsList) {
println("Opponent: ${opponent.name}")
}
// Store the opponents in your ArrayList
opponentsList.clear()
opponentsList.addAll(opponents.opponentsList)
println("Updated opponentsList size: ${opponentsList.size}")
println("About to change view to mega")
currentView = "mega"
println("View changed to mega")
} catch (e: Exception) {
println("Error processing opponents data: ${e.message}")
e.printStackTrace()
}
}
} catch (e: Exception) {
println("Error calling getOpponents: ${e.message}")
e.printStackTrace()
}
}
) {
Text("Mega Battles")
}
}
val backButton = @Composable {
Button(
onClick = {
currentView = "main"
}
) {
Text("Back")
}
}
val characterDropdown = @Composable { currentStage: String ->
// Create hardcoded character lists for each stage
val rookieCharacters = listOf(
APIBattleCharacter("AGUMON", "degimon_name_Dim012_003", "dim012_mon03", 0, 1, 1800, 1800, 2400.0f, 700.0f),
APIBattleCharacter("PULSEMON", "degimon_name_Dim000_003", "dim000_mon03", 0, 1, 1800, 1800, 2400.0f, 700.0f),
APIBattleCharacter("DORUMON", "degimon_name_dim137_mon03", "dim137_mon03", 0, 1, 3000, 3000, 5100.0f, 1050.0f)
)
val championCharacters = listOf(
APIBattleCharacter("GREYMON","degimon_name_Dim012_004","dim012_mon04",1,1,2000, 2000, 3000.0f,900.0f),
APIBattleCharacter("TYRANNOMON","degimon_name_Dim008_006","dim008_mon06",1,3,2000, 2000, 2400.0f,600.0f),
APIBattleCharacter("DORUGAMON","degimon_name_dim137_mon05","dim137_mon05",1,3,3500, 3500, 5200.0f,1200.0f)
)
val ultimateCharacters = listOf(
APIBattleCharacter("METALGREYMON (VIRUS)","degimon_name_Dim014_005","dim014_mon05",2,2,2640, 2640, 2450.0f,800.0f),
APIBattleCharacter("MAMEMON", "degimon_name_Dim000_005", "dim000_mon05", 2, 1, 3000, 3000, 4000.0f, 1000.0f),
APIBattleCharacter("DORUGREYMON","degimon_name_dim137_mon09","dim137_mon09",2,3,5000, 5000, 6400.0f,1400.0f)
)
val megaCharacters = listOf(
APIBattleCharacter("WARGREYMON","degimon_name_Dim012_014","dim012_mon14",3,1,3080, 3080, 3825.0f,800.0f),
APIBattleCharacter("SLAYERDRAMON","degimon_name_dim129_mon15","dim129_mon15",3,1,4800, 4800, 6300.0f,1950.0f),
APIBattleCharacter("BREAKDRAMON","degimon_name_dim129_mon17","dim129_mon17",3,2,6000, 6000, 4000.0f,1980.0f)
)
// Get the appropriate character list based on current stage
val characterList = when (currentStage.lowercase()) {
"rookie" -> rookieCharacters
"champion" -> championCharacters
"ultimate" -> ultimateCharacters
"mega" -> megaCharacters
else -> rookieCharacters
}
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded }
) {
OutlinedTextField(
value = selectedStage.ifEmpty { "Select Character" },
onValueChange = {},
readOnly = true,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
modifier = Modifier.menuAnchor()
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
characterList.forEach { character ->
DropdownMenuItem(
text = { Text(character.name) },
onClick = {
selectedStage = character.name
activeCharacter = character
expanded = false
println("Selected character: ${character.name}")
}
)
}
}
}
}
Scaffold ( Scaffold (
topBar = { topBar = {
TopBanner( TopBanner(
@ -27,7 +286,156 @@ fun BattlesScreen() {
.padding(top = contentPadding.calculateTopPadding()) .padding(top = contentPadding.calculateTopPadding())
.fillMaxSize() .fillMaxSize()
) { ) {
Text("Coming soon") when (currentView) {
"main" -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
rookieButton()
championButton()
ultimateButton()
megaButton()
}
}
"rookie" -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Rookie Battle View")
// Add character selection dropdown
characterDropdown("rookie")
// Display buttons for each opponent
opponentsList.forEach { opponent ->
Button(
onClick = {
activeCharacter = opponent
println("Selected character: ${opponent.name}")
// You can add battle logic here
},
modifier = Modifier.padding(vertical = 4.dp)
) {
Text("Battle ${opponent.name}")
}
}
// Show selected character info
activeCharacter?.let { character ->
Text("Active Character: ${character.name}")
Text("HP: ${character.currentHp}/${character.baseHp}")
Text("BP: ${character.baseBp}")
Text("AP: ${character.baseAp}")
}
backButton()
}
}
"champion" -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Champion Battle View")
// Add character selection dropdown
characterDropdown("champion")
// Display buttons for each opponent
opponentsList.forEach { opponent ->
Button(
onClick = {
activeCharacter = opponent
println("Selected character: ${opponent.name}")
},
modifier = Modifier.padding(vertical = 4.dp)
) {
Text("Battle ${opponent.name}")
}
}
// Show selected character info
activeCharacter?.let { character ->
Text("Active Character: ${character.name}")
Text("HP: ${character.currentHp}/${character.baseHp}")
Text("BP: ${character.baseBp}")
Text("AP: ${character.baseAp}")
}
backButton()
}
}
"ultimate" -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Ultimate Battle View")
// Add character selection dropdown
characterDropdown("ultimate")
// Display buttons for each opponent
opponentsList.forEach { opponent ->
Button(
onClick = {
activeCharacter = opponent
println("Selected character: ${opponent.name}")
},
modifier = Modifier.padding(vertical = 4.dp)
) {
Text("Battle ${opponent.name}")
}
}
// Show selected character info
activeCharacter?.let { character ->
Text("Active Character: ${character.name}")
Text("HP: ${character.currentHp}/${character.baseHp}")
Text("BP: ${character.baseBp}")
Text("AP: ${character.baseAp}")
}
backButton()
}
}
"mega" -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Mega Battle View")
// Add character selection dropdown
characterDropdown("mega")
// Display buttons for each opponent
opponentsList.forEach { opponent ->
Button(
onClick = {
activeCharacter = opponent
println("Selected character: ${opponent.name}")
},
modifier = Modifier.padding(vertical = 4.dp)
) {
Text("Battle ${opponent.name}")
}
}
// Show selected character info
activeCharacter?.let { character ->
Text("Active Character: ${character.name}")
Text("HP: ${character.currentHp}/${character.baseHp}")
Text("BP: ${character.baseBp}")
Text("AP: ${character.baseAp}")
}
backButton()
}
}
}
} }
} }
} }