Refactored

This commit is contained in:
Sewmina 2024-10-28 17:34:48 +05:30
parent fc1f6189e6
commit 2714797fcc
220 changed files with 1996 additions and 776 deletions

BIN
images/token.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
images/vault.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:http/http.dart' as http;
import 'package:mhunt_launcher/Backend/Structures.dart';
@ -7,63 +8,68 @@ import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'DebugHelper.dart';
class Backend{
class Backend {
static const String API_ENDPOINT = "https://vps.playpoolstudios.com/metahunt/api/launcher/";
static const String SOLOGIN_ENDPOINT = "http://vps.playpoolstudios.com:20017/";
static List<GameData> Games = [
GameData(0,"mhunt","Metahunt", "High-Stake Battle Royale game with Play to earn abilities", "images/mhunt_thumbnail.png", true,"METAHUNT.exe"),
GameData(1,"pop3d","Pop3D", "a game I dont know much about xD", "images/pop3d_thumbnail.png", false, "pop3d.exe"),
GameData(0, "mhunt", "Metahunt", "High-Stake Battle Royale game with Play to earn abilities", "images/mhunt_thumbnail.png", true, "METAHUNT.exe"),
GameData(1, "pop3d", "Pop3D", "a game I dont know much about xD", "images/pop3d_thumbnail.png", false, "pop3d.exe"),
];
static SharedPreferences? prefs;
static Directory? docPath;
static String Username="";
static String Username = "";
static String displayName = "";
static String walletAddress = "";
static String pubKey = "";
static Map<String,dynamic> UserJson = {'username':'test', 'passwd':'test123'};
static Map<String, dynamic> UserJson = {'username': 'test', 'passwd': 'test123'};
static Future<bool> Login(String username, String password) async{
static Future<bool> Login(String username, String password) async {
var loginResponse = null;
init();
try {
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}login.php'),
body: <String, String>{"username": username, "password": password}));
Debug.LogResponse(loginResponse.body.toString(),src: '${API_ENDPOINT}login.php');
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}login.php'), body: <String, String>{"username": username, "password": password}));
Debug.LogResponse(loginResponse.body.toString(), src: '${API_ENDPOINT}login.php');
if(loginResponse.body.toString().contains("no user")){
return false;
}
try {
Username=username;
Username = username;
SetUsernamePassword(username, password);
return true;
} catch (e) {
}
} catch (e) {}
} catch (e) {
Debug.LogError("Error while login $e");
return false;
}
return false;
}
static void init()async{
static void init() async {
prefs = await SharedPreferences.getInstance();
docPath = await getDownloadsDirectory();
}
static Future<bool> Register(String username, String password, String displayname) async{
static Future<bool> Register(String username, String password, String displayname) async {
var loginResponse = null;
init();
try {
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}register.php'),
body: <String, String>{"username": username, "password": password, "display_name": displayname}));
Debug.LogResponse(loginResponse.body.toString(),src: '${API_ENDPOINT}register.php');
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}register.php'), body: <String, String>{"username": username, "password": password, "display_name": displayname}));
Debug.LogResponse(loginResponse.body.toString(), src: '${API_ENDPOINT}register.php');
try {
SetUsernamePassword(username, password);
Username = username;
displayName=displayname;
Debug.Log("User is " + username);
displayName = displayname;
return true;
} catch (e) {
}
} catch (e) {}
} catch (e) {
Debug.LogError("Error while login $e");
}
@ -71,44 +77,49 @@ class Backend{
return false;
}
static void SetUsernamePassword(String username, String passwd){
UserJson = {'username':username, 'passwd':passwd};
static Future<String> GetPubkey() async{
var response = await http.get(Uri.parse('${SOLOGIN_ENDPOINT}getPubkey?email=${Username}'));
pubKey = jsonDecode(response.body.toString())["pub_key"];
return pubKey;
}
static Future<List<LeaderboardEntry>> GetLeaderboard(String gameCode) async{
static void SetUsernamePassword(String username, String passwd) {
UserJson = {'username': username, 'passwd': passwd};
}
static Future<List<LeaderboardEntry>> GetLeaderboard(String gameCode) async {
String url = '${API_ENDPOINT}/${gameCode}/get_leaderboard.php';
var leaderboardResponse = await http.get(Uri.parse(url));
return LeaderboardEntry.listFromJson(leaderboardResponse.body);
}
static Future<List<Map<String,dynamic>>> GetNewsForGame(int gameId)async{
static Future<List<Map<String, dynamic>>> GetNewsForGame(int gameId) async {
String url = '${API_ENDPOINT}${Games[gameId].code}/get_news.php';
try{
try {
var res = await http.get(Uri.parse(url));
List<dynamic> jsonList = jsonDecode(res.body);
List<Map<String,dynamic>> output = [];
List<Map<String, dynamic>> output = [];
jsonList.forEach((element) {
output.add(element as Map<String,dynamic>);
output.add(element as Map<String, dynamic>);
});
return output;
}catch(e){
} catch (e) {
Debug.LogError(e);
}
return [{}];
}
static Future<Map<String,dynamic>> GetUserStatsForGame(int gameId) async{
static Future<Map<String, dynamic>> GetUserStatsForGame(int gameId) async {
var loginResponse = null;
init();
try {
String url = '${API_ENDPOINT}${Games[gameId].code}/get_user_stats.php';
loginResponse = (await http.post(Uri.parse(url),
body: <String, String>{"username": prefs!.getString("username") ?? "test"}));
Debug.LogResponse(loginResponse.body.toString(),src: url);
loginResponse = (await http.post(Uri.parse(url), body: <String, String>{"username": Username ?? "test"}));
Debug.LogResponse(loginResponse.body.toString(), src: url);
return jsonDecode(loginResponse.body);
} catch (e) {
@ -118,13 +129,13 @@ class Backend{
return {};
}
static Future<String> CreateRequest() async{
static Future<String> CreateRequest() async {
var loginResponse = null;
try {
String url = '${API_ENDPOINT}create_request.php';
loginResponse = await http.get(Uri.parse(url));
Debug.LogResponse(loginResponse.body.toString(),src: url);
Debug.LogResponse(loginResponse.body.toString(), src: url);
return loginResponse.body.toString();
} catch (e) {
@ -134,14 +145,13 @@ class Backend{
return "-1";
}
static Future<String> GetRequestResponse(String id) async{
static Future<String> GetRequestResponse(String id) async {
var loginResponse = null;
try {
String url = '${API_ENDPOINT}get_request_response.php';
loginResponse = (await http.post(Uri.parse(url),
body: <String, String>{"id":id.toString()}));
Debug.LogResponse(loginResponse.body.toString(),src: url);
loginResponse = (await http.post(Uri.parse(url), body: <String, String>{"id": id.toString()}));
Debug.LogResponse(loginResponse.body.toString(), src: url);
return loginResponse.body;
} catch (e) {
@ -151,14 +161,13 @@ class Backend{
return "-1";
}
static Future<String> GetDisplayName(String id) async{
static Future<String> GetDisplayName(String id) async {
var response = null;
try {
String url = '${API_ENDPOINT}get_display_name.php';
response = (await http.post(Uri.parse(url),
body: <String, String>{"id":id.toString()}));
Debug.LogResponse(response.body.toString(),src: url);
response = (await http.post(Uri.parse(url), body: <String, String>{"id": id.toString()}));
Debug.LogResponse(response.body.toString(), src: url);
return response.body;
} catch (e) {
@ -168,18 +177,17 @@ class Backend{
return "-1";
}
static Future<bool> GetUsernameValidation(String username) async{
static Future<bool> GetUsernameValidation(String username) async {
var loginResponse = null;
try {
String url = '${API_ENDPOINT}validate_username.php';
loginResponse = (await http.post(Uri.parse(url),
body: <String, String>{"username":username}));
Debug.LogResponse(loginResponse.body.toString(),src: url);
loginResponse = (await http.post(Uri.parse(url), body: <String, String>{"username": username}));
Debug.LogResponse(loginResponse.body.toString(), src: url);
if(loginResponse.body == "0"){
if (loginResponse.body == "0") {
return true;
}else{
} else {
return false;
}
} catch (e) {
@ -188,10 +196,39 @@ class Backend{
return false;
}
static Future<String> GetNextGuestUsername() async{
try{
String url = '${API_ENDPOINT}get_next_guest_username.php';
var response = await http.get(Uri.parse(url));
return response.body.toString();
}catch(e){
}
Random random = new Random();
return 'guest ${random.nextInt(10000000)}';
}
static VaultData vault = VaultData('0x0', 0, 0);
static Future<VaultData> RefreshVaultData() async{
var response = null;
try{
String url = '${API_ENDPOINT}get_vault_data.php';
response = (await http.post(Uri.parse(url), body: <String,String>{"id": Username}));
Debug.LogResponse(response.body.toString(), src:url);
vault = jsonDecode(response.body.toString());
}catch(e){
}
return vault;
}
}
class GameData{
class GameData {
int id;
String code;
String name;
@ -200,5 +237,13 @@ class GameData{
bool isAvailable;
String exeName;
GameData(this.id,this.code,this.name,this.description,this.imagePath,this.isAvailable,this.exeName);
}
GameData(this.id, this.code, this.name, this.description, this.imagePath, this.isAvailable, this.exeName);
}
class VaultData{
String address;
int vc;
int php;
VaultData(this.address, this.vc, this.php);
}

View File

@ -35,14 +35,16 @@ class InstallHelper{
localFiles = await getHashtable(pathDir);
}
//Get local hashtable
// Debug.Log(localFilesJson);
Debug.LogResponse(jsonEncode(localFiles), src:"local files");
//Write to file
if(!usedLocalSave){
String localFilesJson = FileHashEntry.listToJson(localFiles);
Backend.prefs!.setString(GetValidationSaveKey(gameId),localFilesJson);
if(kDebugMode) {
File writeJsonFile = File(Path.join(pathDir.parent.path, "hashes.txt"));
String hashFilePath = Path.join(pathDir.parent.path, "hashes.txt");
File writeJsonFile = File(hashFilePath);
writeJsonFile.writeAsString(localFilesJson);
Debug.Log("Wrote hash into ${hashFilePath}");
}
}

39
lib/Shared/Dialogs.dart Normal file
View File

@ -0,0 +1,39 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../main.dart';
class Dialogs{
static showAlertDialog(BuildContext context, String title, String message) {
// set up the button
Widget okButton = TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
backgroundColor: Color(0xFF1F1F1F),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: Text(title),
content: Text(message),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}

View File

@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher_string.dart';
import '../../Backend/Backend.dart';
import '../CustomWidgets.dart';
Widget AccountPage(){
return Padding(
padding: const EdgeInsets.all(25.0),
child: Column(
children: [
Row(
children: [
Text("Hello, ${Backend.displayName}", style: TextStyle(fontSize: 30)),
],
),
SizedBox(height: 100,),
Text(Backend.pubKey),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Text("Vault Credits",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 15),),
Row(
children: [
Image.asset('images/vault.png',width: 40,height: 40,),
Text(Backend.vault.php.toString(),style: TextStyle(fontSize: 50),),
],
)
],
),
SizedBox(width: 60,),
Column(
children: [
Text("Pre-hunt Points",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 15),),
Row(
children: [
Image.asset('images/token.png',width: 40,height: 40,),
Text(Backend.vault.vc.toString(),style: TextStyle(fontSize: 50),),
],
)
],
),
],
),
// Text("Your wallet address is "),
// Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(Backend.walletAddress, style: TextStyle(fontSize: 25),),
// InkWell(child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: Icon(Icons.copy),
// ), onTap: (){
// //Copy wallet
// },)
// ],
// ),
SizedBox(height: 50,),
GlassButton(onTap: (){
launchUrlString('https://auth.playpoolstudios.com');
}, child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Open Dashboard"),
SizedBox(width: 10,),
Icon(Icons.open_in_new, color: Colors.grey)
],
), width: 250, height: 50)
],
),
);
}

View File

@ -0,0 +1,342 @@
import 'dart:io';
import 'package:filepicker_windows/filepicker_windows.dart';
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../../Backend/FileHashEntry.dart';
import '../../Backend/InstallHelper.dart';
import '../../Backend/Structures.dart';
import '../CustomWidgets.dart';
Widget Dashboard({
required BuildContext context,
required Map<int, List<FileHashEntry>> downloadQueue,
required int dashboardSelectedGameIndex,
required List<FileHashEntry> missingFilesForSelectedGame,
required bool calculatingFiles,
required bool isUninstalling,
required bool isRunning,
required Map<String, dynamic> myStatsForSelectedGame,
required List<LeaderboardEntry> leaderboardForSelectedGame,
required List<Map<String, dynamic>> newsForSelectedGame,
required Function(int) onSelectedGameChanged,
required Function onUpdate,
required Function(int) onUninstallClicked,
required dynamic OnGameActionButtonClicked,
}) {
GameData selectedGameData = Backend.Games[dashboardSelectedGameIndex];
String filePath = InstallHelper.GetFilePath(dashboardSelectedGameIndex);
bool folderExists = Directory(filePath).existsSync();
String ActionBtnTxt = "Install";
if (missingFilesForSelectedGame.length <= 0) {
ActionBtnTxt = "Play";
} else {
ActionBtnTxt =
("Download ${FileHashEntry.getTotalSizeInMbytes(missingFilesForSelectedGame).toStringAsFixed(0)} MB");
}
if (calculatingFiles) {
ActionBtnTxt = "Validating";
}
if (downloadQueue.containsKey(dashboardSelectedGameIndex)) {
ActionBtnTxt = "Downloading";
}
if (isUninstalling) {
ActionBtnTxt = "Uninstalling";
}
if(isRunning){
ActionBtnTxt = "Running";
}
Widget ActionButton = GlassButton(
onTap: OnGameActionButtonClicked,
child: Text(ActionBtnTxt),
width: 200,
color: Colors.blue,
opacity: 0.5,
height: 50);
final screenHeight = MediaQuery.of(context).size.height;
List<DataRow> leaderboardList = [];
// leaderboardList.add(TableRow(children: [Text("username"),Text("kills"), Text("deaths")]));
// leaderboardList.add(TableRow());
leaderboardList
.addAll(List.generate(leaderboardForSelectedGame.length, (i) {
return DataRow(cells: <DataCell>[
DataCell(Text(leaderboardForSelectedGame[i].place.toString())),
DataCell(Text(leaderboardForSelectedGame[i].username)),
DataCell(Text(leaderboardForSelectedGame[i].kills.toString())),
DataCell(Text(leaderboardForSelectedGame[i].deaths.toString())),
DataCell(Text(leaderboardForSelectedGame[i].xp.toString())),
]);
}));
return Theme(
data: ThemeData(splashColor: Colors.transparent),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: screenHeight * 0.18,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
selectedGameData.name,
style: TextStyle(fontSize: 25),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(Backend.Games.length, (index) {
bool isSelected = index == dashboardSelectedGameIndex;
return InkWell(
onTap: (){
onSelectedGameChanged(index);
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 100),
margin: EdgeInsets.all(9),
height: 80 * (isSelected ? 1.5 : 1),
width: 130 * (isSelected ? 1.5 : 1),
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[index].imagePath),
fit: BoxFit.fill),
borderRadius: BorderRadius.circular(20)),
),
);
}),
),
],
),
),
!Backend.Games[dashboardSelectedGameIndex].isAvailable
? Center(
child: Text("Coming Soon", style: TextStyle(fontSize: 40)))
: Container(
height: screenHeight * 0.72,
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
ActionButton,
PopupMenuButton<String>(
iconColor: Colors.blueGrey,
onSelected: (val) {
if (val.toLowerCase().contains("uninstall")) {
onUninstallClicked(dashboardSelectedGameIndex);
}
},
itemBuilder: (BuildContext context) {
return {'Uninstall'}.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
},
),
],
),
GlassCard(
color: Colors.green,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text("My Stats",
style:
TextStyle(color: Colors.blueGrey)),
SizedBox(
width: 50,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Kills : ${(myStatsForSelectedGame['kills'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Deaths : ${(myStatsForSelectedGame['deaths'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Assist : ${(myStatsForSelectedGame['assists'] ?? "0")}"),
),
],
),
),
),
Container()
],
),
),
Container(
height: screenHeight * 0.6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: GlassCard(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
width: 350,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 12.0, horizontal: 20),
child: Text(
"News",
style: TextStyle(fontSize: 20),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: List.generate(
newsForSelectedGame.length,
(index) {
return NewsCard(
newsForSelectedGame[index]
['title'],
newsForSelectedGame[index]
['message']);
}),
),
),
)
],
),
)),
),
SizedBox(
width: 50,
),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
0, 20, 0, 0),
child: Text(
"Leaderboard",
style: TextStyle(fontSize: 20),
),
),
DataTable(
dataTextStyle:
TextStyle(color: Colors.white),
headingTextStyle:
TextStyle(color: Colors.white),
dividerThickness: 0,
columns: [
DataColumn(
label:
Expanded(child: Text("Place"))),
DataColumn(
label: Expanded(
child: Text("Username"))),
DataColumn(
label:
Expanded(child: Text("Kills"))),
DataColumn(
label: Expanded(
child: Text("Deaths"))),
DataColumn(
label: Expanded(child: Text("XP"))),
],
rows: leaderboardList,
),
],
),
),
],
))
],
),
),
Container(
//Install path footer
padding: EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.bottomCenter,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [Text("Install path "), Text(filePath)]),
GlassButton(
onTap: () {
DirectoryPicker file = DirectoryPicker();
final dir = file.getDirectory();
Backend.prefs!.setString(
'${selectedGameData.name}_path', dir!.path);
onUpdate();
},
child: Text("Change Install Location"),
width: 250)
],
),
SizedBox(
height: 10,
)
],
),
)
],
),
);
}
Widget NewsCard(String title, String message) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: GlassCard(
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Icon(
Icons.newspaper,
color: Colors.blueGrey,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontSize: 18),
textAlign: TextAlign.left,
),
Text(
message,
overflow: TextOverflow.clip,
)
],
)
],
)),
);
}

View File

@ -0,0 +1,129 @@
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../../Backend/FileHashEntry.dart';
import '../CustomWidgets.dart';
Widget DownloadCard({
required int gameId,
required Map<int, Map<FileHashEntry, num>> downloadProgress,
required Map<int, double> totalDownloadSize,
required Map<int, List<FileHashEntry>> downloadQueue,
required bool downloadRunning,
required Function(int) onChanged
}) {
int doneSize = 0;
if (downloadProgress.containsKey(gameId)) {
Map<FileHashEntry, num> _progress = downloadProgress[gameId]!;
_progress.forEach((key, value) {
doneSize += value.toInt();
});
}
double totalSize = totalDownloadSize[gameId]! / 1024 / 1024;
double doneSizeMb = doneSize / 1024 / 1024;
double progress = doneSizeMb / totalSize;
return Padding(
padding: const EdgeInsets.all(8.0),
child: GlassCard(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[gameId].imagePath)),
borderRadius: BorderRadius.circular(50)),
width: 160,
height: 80,
),
Column(
children: [
Text(
Backend.Games[gameId].name,
style: TextStyle(fontSize: 20),
),
Text((doneSizeMb).toStringAsFixed(2) +
" MB" +
" / " +
totalSize.toStringAsFixed(2) +
" MB")
],
)
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black.withOpacity(0.2),
color: Colors.blue,
),
),
),
InkWell(
child: Icon(Icons.cancel,
size: 40, color: Colors.red.withOpacity(0.6)),
onTap: () {
downloadQueue.remove(gameId);
downloadProgress.remove(gameId);
downloadRunning = false;
onChanged(gameId);
},
)
// Icon(Icons.download,size: 40,color: Colors.green.withOpacity(0.4),)
],
)
],
),
)),
);
}
Widget Downloads({
required Map<int, List<FileHashEntry>> downloadQueue,
required Map<int, Map<FileHashEntry, num>> downloadProgress,
required Map<int, double> totalDownloadSize,
required bool downloadRunning,
required Function(int) onChanged
}) {
if (downloadQueue.length <= 0) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.download_done_sharp,
size: 100,
color: Colors.white.withOpacity(0.5),
),
Text(
"No ongoing Downloads",
style:
TextStyle(fontSize: 40, color: Colors.white.withOpacity(0.4)),
),
],
),
);
}
return Container(
child: Container(
padding: EdgeInsets.all(100),
child: GlassCard(
child: Column(
children: List.generate(downloadQueue.keys.length, (index) {
int gameId = downloadQueue.keys.toList()[index];
return DownloadCard(gameId: gameId, downloadQueue:downloadQueue, downloadProgress: downloadProgress, downloadRunning: downloadRunning, totalDownloadSize: totalDownloadSize, onChanged: onChanged );
}),
))));
}

View File

@ -0,0 +1,98 @@
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../CustomWidgets.dart';
String hoveringGameCard = "";
Widget Library({
required int selectedSidebarIndex,
required Function(int) onGameChanged,
required Function onUpdate,
}) {
return Center(
child: Wrap(
spacing: 20,
children: List.generate(Backend.Games.length, (index) {
GameData gameData = Backend.Games[index];
return LibGameCard(
gameData: gameData,
selectedSidebarIndex: selectedSidebarIndex,
onUpdate: onUpdate,
onGameChanged: onGameChanged
);
}),
),
);
}
Widget LibGameCard({
required GameData gameData,
required int selectedSidebarIndex,
required Function(int) onGameChanged,
required Function onUpdate,
}) {
return InkWell(
onTap: () {
selectedSidebarIndex = 1;
onGameChanged(gameData.id);
},
onHover: (val) {
if (val) {
hoveringGameCard = gameData.name;
} else if (hoveringGameCard == gameData.name) {
hoveringGameCard = "";
}
onUpdate();
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.black,
image: DecorationImage(
image: AssetImage(gameData.imagePath), fit: BoxFit.fill)),
height: 200,
width: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
hoveringGameCard != gameData.name
? Container()
: Expanded(
child: GlassContainer(
child: Center(
child: Text(
gameData.description,
textAlign: TextAlign.center,
),
),
opacity: 0.5,
color: Colors.black)),
GlassContainer(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: true? Container():Row(
children: [
Text(gameData.name),
gameData.isAvailable
? GlassButton(
onTap: () {},
child: Text("Install"),
width: 100,
color: Colors.blue,
opacity: 0.8)
: Text("Coming soon")
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
),
opacity: 0.9,
color: Colors.black),
],
),
),
);
}

View File

@ -0,0 +1,127 @@
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../CustomWidgets.dart';
int selectedSidebarIndex = 0;
Widget SideBar(
{required double width, required double height,required Function(int) onChanged, int selectedIndex = 0}) {
return GlassContainer(
child: Container(
width: width,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
SizedBox(
height: 100,
),
SidebarTitle("Library", Icons.laptop_chromebook_outlined, onChanged,
index: 0),
SidebarTitle("Dashboard", Icons.dashboard,onChanged, index: 1),
SidebarTitle("Downloads", Icons.download,onChanged, index: 2),
],
),
InkWell(
onTap:(){
selectedSidebarIndex=3;
onChanged(3);
},
child: GlassContainer(child: Padding(
padding: const EdgeInsets.fromLTRB(10,0,10,10),
child: Row(
children: [
Icon(Icons.supervised_user_circle_rounded, size: 50),
SizedBox(width: 15,),
Column(crossAxisAlignment:CrossAxisAlignment.start,children: [
Text(Backend.displayName,style: TextStyle(fontSize: 24),),
// Text("Vault credits : 50")
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 10,vertical: 2),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.black.withAlpha(100)),
child: Row(
children: [
Container(
height: 30,
width: 30,
child: Image.asset('images/vault.png'),
),
SizedBox(width: 5,),
Text(Backend.vault.vc.toString())
],
),
),
SizedBox(width: 5,),
Container(
padding: EdgeInsets.symmetric(horizontal: 10,vertical: 2),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.black.withAlpha(100)),
child: Row(
children: [
Container(
height: 30,
width: 30,
child: Image.asset('images/token.png'),
),
SizedBox(width: 5,),
Text(Backend.vault.php.toString())
],
),
),
],
)
],
),
],)
],
),
)),
)
],
),
),
opacity: 0.15,
color: Colors.blueGrey);
}
Widget SidebarTitle(String title, IconData iconData, Function(int) onChanged, {int index = 0}) {
return InkWell(
onTap: () {
selectedSidebarIndex = index;
onChanged(index);
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 0),
child: GlassContainer(
opacity: selectedSidebarIndex == index ? 0.1 : 0,
color:
selectedSidebarIndex == index ? Colors.white : Colors.transparent,
child: Container(
height: 75,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(iconData),
SizedBox(
width: 20,
),
Text(
title,
style: TextStyle(fontSize: 20),
),
],
),
),
),
),
);
}

View File

@ -1,10 +1,11 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:http/http.dart' as http;
import 'package:mhunt_launcher/home.dart';
import 'package:process_run/shell.dart';
import 'package:mhunt_launcher/login.dart';
class UpdateCheckScreen extends StatefulWidget {
const UpdateCheckScreen({super.key});
@ -15,8 +16,8 @@ class UpdateCheckScreen extends StatefulWidget {
class _UpdateCheckScreenState extends State<UpdateCheckScreen> {
int localVersion = 0;
String otaPath = Directory.current.path + "\\ota_wrapper_v2.exe";
int localVersion = 4;
String otaPath = Directory.current.path + "\\ota_wrapper_silent.vbs";
@override
void initState() {
@ -25,31 +26,35 @@ class _UpdateCheckScreenState extends State<UpdateCheckScreen> {
CheckForUpdates();
}
Future<List<ProcessResult>> runExecutable(String executable) async {
return await run(executable);
}
void CheckForUpdates() async{
// http.Response remoteVersionResponse = await http.get(Uri.parse("https://vps.playpoolstudios.com/metahunt/api/launcher/get_version.php"));
// int remoteVersion = int.parse(remoteVersionResponse.body);
if(!await File(otaPath).exists()){
print("otapath not existing");
setState(() {
updateStatus=2;
});
return;
}
try {
final result = await runExecutable(otaPath + " noupdate");
if (result[0].stdout.trim() == '0') {
updateStatus = 2;
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> HomePage()));
}else{
updateStatus = 1;
}
} catch (e) {
print('Error running the executable: $e');
}
http.Response remoteVersionResponse = await http.get(Uri.parse("https://vps.playpoolstudios.com/metahunt/data/bin/launcher_win/get_version_code.php"));
int remoteVersion = int.parse(remoteVersionResponse.body);
print("local version:${localVersion}, remote version:${remoteVersion}");
if(remoteVersion>localVersion){
updateStatus = 1;
}else{
updateStatus=2;
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> LoginPage()));
}
// if(!await File(otaPath).exists()){
// print("otapath not existing");
// setState(() {
// updateStatus=2;
// });
// return;
// }
// try {
//
// final result = await runExecutable(otaPath + " noupdate");
// if (result[0].stdout.trim() == '0') {
// updateStatus = 2;
// Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> LoginPage()));
// }else{
// updateStatus = 1;
// }
// } catch (e) {
// print('Error running the executable: $e');
// }
setState(() {
@ -57,10 +62,16 @@ class _UpdateCheckScreenState extends State<UpdateCheckScreen> {
});
}
void update() async{
await Process.start(otaPath,[], runInShell: true);
// await Future.delayed(const Duration(seconds: 5));
// await Process.start(otaPath,[], runInShell: true);
//
final process = await Process.start('wscript',[otaPath], runInShell: true);
updateStatus = 2;
process.stdout.transform(utf8.decoder).listen((data) {
});
process.stderr.transform(utf8.decoder).listen((data) {
print(data);
});
await Future.delayed(const Duration(seconds: 1));
exit(0);
setState(() {

View File

@ -14,11 +14,17 @@ import 'package:mhunt_launcher/sidebar.dart';
import 'package:process_run/process_run.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:path/path.dart' as Path;
import 'package:url_launcher/url_launcher_string.dart';
import 'Backend/DebugHelper.dart';
import 'package:http/http.dart' as http;
import 'Backend/FileHashEntry.dart';
import 'Backend/Structures.dart';
import 'Widgets/Home/AccountsPage.dart';
import 'Widgets/Home/Dashboard.dart';
import 'Widgets/Home/Downloads.dart';
import 'Widgets/Home/Library.dart';
import 'Widgets/Home/Sidebar.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@ -39,14 +45,38 @@ class _HomePageState extends State<HomePage> {
bool downloadRunning = false;
int unwaitingFiles = 0;
int dashboardSelectedGameIndex = 0;
String userPubKey = "loading";
@override
void initState() {
// TODO: implement initState
super.initState();
kickstartAnimations();
initData();
SetSelectedDashboardGame(0);
SetVaultUpdateLoop();
}
void SetVaultUpdateLoop() async{
while(true){
await Backend.RefreshVaultData();
setState(() {
});
await Future.delayed(const Duration(seconds: 30));
}
}
void initData()async{
userPubKey= await Backend.GetPubkey();
setState(() {
});
}
void kickstartAnimations() async {
@ -63,11 +93,50 @@ class _HomePageState extends State<HomePage> {
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
Widget content = Library();
Widget content = Library(
selectedSidebarIndex: selectedSidebarIndex,
onGameChanged: SetSelectedDashboardGame,
onUpdate: (){
setState(() {
});
}
);
if (selectedSidebarIndex == 1) {
content = Dashboard();
content = Dashboard(
context: context,
downloadQueue: downloadQueue,
dashboardSelectedGameIndex: dashboardSelectedGameIndex,
missingFilesForSelectedGame: missingFilesForSelectedGame,
calculatingFiles: calculatingFiles,
isRunning: runningProcs.containsKey(dashboardSelectedGameIndex),
isUninstalling: isUninstalling,
myStatsForSelectedGame: myStatsForSelectedGame,
leaderboardForSelectedGame: leaderboardForSelectedGame,
newsForSelectedGame: newsForSelectedGame,
onSelectedGameChanged: SetSelectedDashboardGame,
onUninstallClicked: UninstallGame,
OnGameActionButtonClicked: OnGameActionButtonClicked,
onUpdate: (){
setState(() {
});
}
);
} else if (selectedSidebarIndex == 2) {
content = Downloads();
content = Downloads(
downloadQueue: downloadQueue,
downloadRunning: downloadRunning,
downloadProgress: downloadProgress,
totalDownloadSize: totalDownloadSize,
onChanged: (val){
setState(() {
SetSelectedDashboardGame(val);
});
}
);
}else if(selectedSidebarIndex == 3){
content = AccountPage();
}
@ -83,7 +152,11 @@ class _HomePageState extends State<HomePage> {
children: [
SideBar(
width: screenWidth * 0.2,
height: screenHeight,
height: screenHeight, onChanged: (val){
setState(() {
selectedSidebarIndex = val;
});
},
),
SizedBox(
width: screenWidth * 0.8,
@ -96,301 +169,7 @@ class _HomePageState extends State<HomePage> {
);
}
Widget Library() {
return Center(
child: Wrap(
spacing: 20,
children: List.generate(Backend.Games.length, (index) {
GameData gameData = Backend.Games[index];
return LibGameCard(gameData);
}),
),
);
}
Widget AccountPage(){
return Padding(
padding: const EdgeInsets.all(25.0),
child: Column(
children: [
Row(
children: [
Text("Hello, ${Backend.displayName}", style: TextStyle(fontSize: 30)),
],
),
],
),
);
}
Widget Downloads() {
if (downloadQueue.length <= 0) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.download_done_sharp,
size: 100,
color: Colors.white.withOpacity(0.5),
),
Text(
"No ongoing Downloads",
style:
TextStyle(fontSize: 40, color: Colors.white.withOpacity(0.4)),
),
],
),
);
}
return Container(
child: Container(
padding: EdgeInsets.all(100),
child: GlassCard(
child: Column(
children: List.generate(downloadQueue.keys.length, (index) {
int gameId = downloadQueue.keys.toList()[index];
return DownloadCard(gameId, downloadQueue[gameId]!);
}),
))));
}
Widget DownloadCard(int gameId, List<FileHashEntry> files) {
int doneSize = 0;
if (downloadProgress.containsKey(gameId)) {
Map<FileHashEntry, num> _progress = downloadProgress[gameId]!;
_progress.forEach((key, value) {
doneSize += value.toInt();
});
}
double totalSize = totalDownloadSize[gameId]! / 1024 / 1024;
double doneSizeMb = doneSize / 1024 / 1024;
double progress = doneSizeMb / totalSize;
return Padding(
padding: const EdgeInsets.all(8.0),
child: GlassCard(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[gameId].imagePath)),
borderRadius: BorderRadius.circular(50)),
width: 160,
height: 80,
),
Column(
children: [
Text(
Backend.Games[gameId].name,
style: TextStyle(fontSize: 20),
),
Text((doneSizeMb).toStringAsFixed(2) +
" MB" +
" / " +
totalSize.toStringAsFixed(2) +
" MB")
],
)
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black.withOpacity(0.2),
color: Colors.blue,
),
),
),
InkWell(
child: Icon(Icons.cancel,
size: 40, color: Colors.red.withOpacity(0.6)),
onTap: () {
downloadQueue.remove(gameId);
downloadProgress.remove(gameId);
downloadRunning = false;
SetSelectedDashboardGame(gameId);
setState(() {});
},
)
// Icon(Icons.download,size: 40,color: Colors.green.withOpacity(0.4),)
],
)
],
),
)),
);
}
Widget SideBar(
{required double width, required double height, int selectedIndex = 0}) {
return GlassContainer(
child: Container(
width: width,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// SizedBox(width: 10,),
// Text("10")
// ],
// ),
// ),
SizedBox(
height: 100,
),
SidebarTitle("Library", Icons.laptop_chromebook_outlined,
index: 0),
SidebarTitle("Dashboard", Icons.dashboard, index: 1),
SidebarTitle("Downloads", Icons.download, index: 2),
],
),
InkWell(
onTap:(){
setState(() {
selectedSidebarIndex=3;
});
},
child: GlassContainer(child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
children: [
Icon(Icons.supervised_user_circle_rounded, size: 50),
SizedBox(width: 15,),
Column(crossAxisAlignment:CrossAxisAlignment.start,children: [
Text(Backend.displayName,style: TextStyle(fontSize: 24),),
// Text("Vault credits : 50")
],)
],
),
)),
)
],
),
),
opacity: 0.15,
color: Colors.blueGrey);
}
Widget SidebarTitle(String title, IconData iconData, {int index = 0}) {
return InkWell(
onTap: () {
setState(() {
selectedSidebarIndex = index;
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 0),
child: GlassContainer(
opacity: selectedSidebarIndex == index ? 0.1 : 0,
color:
selectedSidebarIndex == index ? Colors.white : Colors.transparent,
child: Container(
height: 75,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(iconData),
SizedBox(
width: 20,
),
Text(
title,
style: TextStyle(fontSize: 20),
),
],
),
),
),
),
);
}
String hoveringGameCard = "";
Widget LibGameCard(GameData gameData) {
return InkWell(
onTap: () {
selectedSidebarIndex = 1;
SetSelectedDashboardGame(gameData.id);
},
onHover: (val) {
if (val) {
hoveringGameCard = gameData.name;
} else if (hoveringGameCard == gameData.name) {
hoveringGameCard = "";
}
setState(() {});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.black,
image: DecorationImage(
image: AssetImage(gameData.imagePath), fit: BoxFit.fill)),
height: 200,
width: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
hoveringGameCard != gameData.name
? Container()
: Expanded(
child: GlassContainer(
child: Center(
child: Text(
gameData.description,
textAlign: TextAlign.center,
),
),
opacity: 0.5,
color: Colors.black)),
GlassContainer(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: true? Container():Row(
children: [
Text(gameData.name),
gameData.isAvailable
? GlassButton(
onTap: () {},
child: Text("Install"),
width: 100,
color: Colors.blue,
opacity: 0.8)
: Text("Coming soon")
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
),
opacity: 0.9,
color: Colors.black),
],
),
),
);
}
void SetSelectedDashboardGame(int i) async {
calculatingFiles = true;
@ -448,7 +227,7 @@ class _HomePageState extends State<HomePage> {
if(runningProcs.containsKey(id)){return;}
String exePath = InstallHelper.GetExeFilePath(dashboardSelectedGameIndex);
// Process proc = await run(exePath,);
runningProcs.putIfAbsent(id, ()=> run(exePath + " username ${Backend.UserJson['username']} password ${Backend.UserJson['passwd']}"));
runningProcs.putIfAbsent(id, ()=> run(exePath + " username ${Backend.Username} password ${Backend.UserJson['passwd']}"));
setState(() {
});
@ -475,11 +254,6 @@ class _HomePageState extends State<HomePage> {
bool isUninstalling = false;
void UninstallGame(int id) async {
if(runningProcs.containsKey(id)){return;}
// String exeFilePath = InstallHelper.GetExeFilePath(id);
// if(!File(exeFilePath).existsSync()){
// Debug.LogError("No game installed to uninstall");
// return;
// }
isUninstalling = true;
setState(() {});
@ -592,322 +366,4 @@ class _HomePageState extends State<HomePage> {
});
});
}
Widget Dashboard() {
GameData selectedGameData = Backend.Games[dashboardSelectedGameIndex];
String filePath = InstallHelper.GetFilePath(dashboardSelectedGameIndex);
bool folderExists = Directory(filePath).existsSync();
String ActionBtnTxt = "Install";
if (missingFilesForSelectedGame.length <= 0) {
ActionBtnTxt = "Play";
} else {
ActionBtnTxt =
("Download ${FileHashEntry.getTotalSizeInMbytes(missingFilesForSelectedGame).toStringAsFixed(0)} MB");
}
if (calculatingFiles) {
ActionBtnTxt = "Validating";
}
if (downloadQueue.containsKey(dashboardSelectedGameIndex)) {
ActionBtnTxt = "Downloading";
}
if (isUninstalling) {
ActionBtnTxt = "Uninstalling";
}
if(runningProcs.containsKey(dashboardSelectedGameIndex)){
ActionBtnTxt = "Running";
}
Widget ActionButton = GlassButton(
onTap: OnGameActionButtonClicked,
child: Text(ActionBtnTxt),
width: 200,
color: Colors.blue,
opacity: 0.5,
height: 50);
final screenHeight = MediaQuery.of(context).size.height;
List<DataRow> leaderboardList = [];
// leaderboardList.add(TableRow(children: [Text("username"),Text("kills"), Text("deaths")]));
// leaderboardList.add(TableRow());
leaderboardList
.addAll(List.generate(leaderboardForSelectedGame.length, (i) {
return DataRow(cells: <DataCell>[
DataCell(Text(leaderboardForSelectedGame[i].place.toString())),
DataCell(Text(leaderboardForSelectedGame[i].username)),
DataCell(Text(leaderboardForSelectedGame[i].kills.toString())),
DataCell(Text(leaderboardForSelectedGame[i].deaths.toString())),
DataCell(Text(leaderboardForSelectedGame[i].xp.toString())),
]);
}));
return Theme(
data: ThemeData(splashColor: Colors.transparent),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: screenHeight * 0.18,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
selectedGameData.name,
style: TextStyle(fontSize: 25),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(Backend.Games.length, (index) {
bool isSelected = index == dashboardSelectedGameIndex;
return InkWell(
onTap: () {
SetSelectedDashboardGame(index);
setState(() {});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 100),
margin: EdgeInsets.all(9),
height: 80 * (isSelected ? 1.5 : 1),
width: 130 * (isSelected ? 1.5 : 1),
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[index].imagePath),
fit: BoxFit.fill),
borderRadius: BorderRadius.circular(20)),
),
);
}),
),
],
),
),
!Backend.Games[dashboardSelectedGameIndex].isAvailable
? Center(
child: Text("Coming Soon", style: TextStyle(fontSize: 40)))
: Container(
height: screenHeight * 0.72,
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
ActionButton,
PopupMenuButton<String>(
iconColor: Colors.blueGrey,
onSelected: (val) {
if (val
.toLowerCase()
.contains("uninstall")) {
UninstallGame(dashboardSelectedGameIndex);
}
},
itemBuilder: (BuildContext context) {
return {'Uninstall'}.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
},
),
],
),
GlassCard(
color: Colors.green,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text("My Stats",
style:
TextStyle(color: Colors.blueGrey)),
SizedBox(
width: 50,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Kills : ${(myStatsForSelectedGame['kills'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Deaths : ${(myStatsForSelectedGame['deaths'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Assist : ${(myStatsForSelectedGame['assists'] ?? "0")}"),
),
],
),
),
),
],
),
),
Container(
height: screenHeight * 0.6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: GlassCard(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
width: 350,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 12.0, horizontal: 20),
child: Text(
"News",
style: TextStyle(fontSize: 20),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: List.generate(
newsForSelectedGame.length,
(index) {
return NewsCard(
newsForSelectedGame[index]
['title'],
newsForSelectedGame[index]
['message']);
}),
),
),
)
],
),
)),
),
SizedBox(
width: 50,
),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
0, 20, 0, 0),
child: Text(
"Leaderboard",
style: TextStyle(fontSize: 20),
),
),
DataTable(
dataTextStyle:
TextStyle(color: Colors.white),
headingTextStyle:
TextStyle(color: Colors.white),
dividerThickness: 0,
columns: [
DataColumn(
label:
Expanded(child: Text("Place"))),
DataColumn(
label: Expanded(
child: Text("Username"))),
DataColumn(
label:
Expanded(child: Text("Kills"))),
DataColumn(
label: Expanded(
child: Text("Deaths"))),
DataColumn(
label: Expanded(child: Text("XP"))),
],
rows: leaderboardList,
),
],
),
),
],
))
],
),
),
Container(
//Install path footer
padding: EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.bottomCenter,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [Text("Install path "), Text(filePath)]),
GlassButton(
onTap: () {
DirectoryPicker file = DirectoryPicker();
final dir = file.getDirectory();
Backend.prefs!.setString(
'${selectedGameData.name}_path', dir!.path);
setState(() {});
},
child: Text("Change Install Location"),
width: 250)
],
),
SizedBox(
height: 10,
)
],
),
)
],
),
);
}
Widget NewsCard(String title, String message) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: GlassCard(
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Icon(
Icons.newspaper,
color: Colors.blueGrey,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontSize: 18),
textAlign: TextAlign.left,
),
Text(
message,
overflow: TextOverflow.clip,
)
],
)
],
)),
);
}
}

View File

@ -1,12 +1,17 @@
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mhunt_launcher/Backend/Backend.dart';
import 'package:mhunt_launcher/Backend/DebugHelper.dart';
import 'package:mhunt_launcher/Widgets/CustomWidgets.dart';
import 'package:mhunt_launcher/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
import 'Shared/Dialogs.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@ -32,7 +37,6 @@ class _LoginPageState extends State<LoginPage> {
if (prefs.containsKey("username") && prefs.containsKey("password")) {
usernameController.text = prefs.getString("username") ?? '';
passwordController.text = prefs.getString("password") ?? '';
LoginOrReg();
}
}
@ -48,6 +52,7 @@ class _LoginPageState extends State<LoginPage> {
}
TextEditingController usernameController = TextEditingController();
TextEditingController gamertagController = TextEditingController();
TextEditingController passwordController = TextEditingController();
@override
@ -64,7 +69,7 @@ class _LoginPageState extends State<LoginPage> {
setState(() {});
},
child: Center(
child: web3LoginCard()
child: TraditionalLoginCard()
))
);
}
@ -145,7 +150,7 @@ class _LoginPageState extends State<LoginPage> {
setState(() {
web3loginState = 1;
});
launchUrl(Uri.parse('https://auth.playpoolstudios.com/?request_id=${requestId}'));
launchUrl(Uri.parse('https://auth.playpoolstudios.com/auth/?request_id=${requestId}'));
String requestResponse = "-1";
while(requestResponse == "-1"){
await Future.delayed(const Duration(seconds: 1));
@ -190,72 +195,120 @@ class _LoginPageState extends State<LoginPage> {
}
await Backend.Register(web3id,web3id,usernameEditingController.text);
await Backend.Login(usernameEditingController.text, web3id);
await Backend.Login(web3id, web3id);
OnLoginSuccess();
}
bool isGuest = false;
Widget TraditionalLoginCard(){
return GlassCard(
child: Container(
padding: EdgeInsets.all(25),
width: 600,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Welcome to W3B Launcher",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Text("Username "),
SizedBox(
width: 300,
child: TextField(
controller: usernameController,
))
],
mainAxisAlignment: MainAxisAlignment.center,
),
Row(children: [
Text("Password "),
SizedBox(
width: 300,
child: TextField(
controller: passwordController,
))
], mainAxisAlignment: MainAxisAlignment.center),
SizedBox(
height: 30,
),
GlassButton(onTap: LoginOrReg, child: Text(isReg ? "Register" : "Login"), width: 150, height: 40),
],
),
Row(children: [
Text(isReg ? "Already have an Account? " : "Don't have an Account? "),
InkWell(
child: Text(
isReg ? "Login Here" : "Register Here",
style: TextStyle(color: Colors.blue),
),
onTap: () {
setState(() {
isReg = !isReg;
});
},
)
], mainAxisAlignment: MainAxisAlignment.center)
],
),
child: isGuest? TraditionalLoginGuest() :TraditionalLoginMain()
));
}
Widget TraditionalLoginMain(){
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Welcome to W3B Launcher",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Text("Username "),
SizedBox(
width: 300,
child: TextField(
controller: usernameController,
))
],
mainAxisAlignment: MainAxisAlignment.center,
),
Row(children: [
Text("Password "),
SizedBox(
width: 300,
child: TextField(
controller: passwordController,
))
], mainAxisAlignment: MainAxisAlignment.center),
SizedBox(
height: 30,
),
GlassButton(onTap: LoginOrReg, child: Text(isReg ? "Register" : "Login"), width: 150, height: 40),
],
),
Row(children: [
Text(isReg ? "Already have an Account? " : "Don't have an Account? "),
InkWell(
child: Text(
isReg ? "Login Here" : "Register Here",
style: TextStyle(color: Colors.blue),
),
onTap: () {
setState(() {
isReg = !isReg;
});
},
)
], mainAxisAlignment: MainAxisAlignment.center),
GlassButton(onTap: (){setState(() {
isGuest=true;
});}, child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.person),
SizedBox(width: 10,),
Text("Guest Mode"),
],
), width: 130, height: 30)
],
);
}
Widget TraditionalLoginGuest(){
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Welcome to W3B Launcher - Guest Mode",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Column(
children: [
Row(
children: [
Text("Gamer Tag "),
SizedBox(
width: 300,
child: TextField(
controller: gamertagController,
))
],
mainAxisAlignment: MainAxisAlignment.center,
),
SizedBox(height: 15,),
SizedBox(width: 250,child:usernameExists ? Text("Username is taken",style: TextStyle(color: Colors.red),) : Container()),
GlassButton(onTap:GuestModeComplete , child: Text("Complete Login"), width: 250,height: 40,color: Colors.green)
],
),
GlassButton(onTap: (){setState(() {
isGuest=false;
});}, child: Text("Back"), width: 200, color: Colors.blueGrey)
],
);
}
void LoginOrReg() async {
// if(kDebugMode){
// Navigator.of(context).push(MaterialPageRoute(builder: (context)=>HomePage()));
@ -268,8 +321,35 @@ class _LoginPageState extends State<LoginPage> {
success = await Backend.Login(usernameController.text, passwordController.text);
}
Debug.Log('${isReg ? "Register": "Login"} was ${success ? "success" : "faild"}');
if (success) {
OnLoginSuccess();
}else{
if(isReg){
Dialogs.showAlertDialog(context, 'Failed Register', "Username already exists");
}else{
Dialogs.showAlertDialog(context, 'Failed Login', "Username or Password is incorrect");
}
}
}
void GuestModeComplete()async{
bool usernameValidated = await Backend.GetUsernameValidation(gamertagController.text);
if(!usernameValidated){
setState(() {
usernameExists=true;
});
}
String username = await Backend.GetNextGuestUsername();
bool success= await Backend.Register(username, username, gamertagController.text);
if(success){
usernameController.text = username;
passwordController.text = username;
OnLoginSuccess();
}
}
@ -277,7 +357,7 @@ class _LoginPageState extends State<LoginPage> {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('username', usernameController.text);
prefs.setString('password', passwordController.text);
prefs.setString('displayname', Backend.displayName);
Navigator.of(context).push(MaterialPageRoute(builder: (context) => HomePage()));
}
}

BIN
ota/Microsoft.CSharp.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/Newtonsoft.Json.dll Normal file

Binary file not shown.

BIN
ota/System.AppContext.dll Normal file

Binary file not shown.

BIN
ota/System.Buffers.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Collections.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Console.dll Normal file

Binary file not shown.

BIN
ota/System.Core.dll Normal file

Binary file not shown.

BIN
ota/System.Data.Common.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Data.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Drawing.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Formats.Asn1.dll Normal file

Binary file not shown.

BIN
ota/System.Formats.Tar.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.IO.Pipes.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.IO.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Linq.dll Normal file

Binary file not shown.

BIN
ota/System.Memory.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.Http.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.Mail.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.Ping.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.Quic.dll Normal file

Binary file not shown.

BIN
ota/System.Net.Requests.dll Normal file

Binary file not shown.

BIN
ota/System.Net.Security.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.Sockets.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.WebProxy.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ota/System.Net.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
ota/System.Numerics.dll Normal file

Binary file not shown.

BIN
ota/System.ObjectModel.dll Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More