import 'package:flutter/material.dart'; import 'package:libac_dart/packets/packets.dart'; import 'package:servermanager/packets/ClientPackets.dart'; import 'package:servermanager/pages/ACL.dart'; import 'package:servermanager/pages/Constants.dart'; import 'package:servermanager/pages/DiscordConfigPage.dart'; import 'package:servermanager/pages/GameServerPage.dart'; import 'package:servermanager/pages/ModManager.dart'; import 'package:servermanager/pages/autorestart.dart'; import 'package:servermanager/pages/home.dart'; import 'package:servermanager/pages/snapshots.dart'; import 'package:servermanager/structs/settings.dart'; import 'pages/ServerSettings.dart'; Future main() async { runApp(MyApp()); } class MyApp extends StatelessWidget { MyApp({super.key}); Settings appSettings = Settings(); @override Widget build(BuildContext context) { return MaterialApp( title: 'Server Manager', theme: ThemeData.dark(useMaterial3: true), routes: { "/": (context) => ServerPage(), "/home": (context) => HomePage(settings: appSettings), "/acl": (context) => AccessControlListPage(), "/acl/edit": (context) => ACLEdit(), "/server": (context) => GameServerPage(settings: appSettings), "/server/autorestart": (context) => AutoRestartPage(), "/server/ports": (context) => ServerSettingsPage(), "/server/mods": (context) => ModManager(settings: appSettings), "/server/mods/edit": (context) => ModPage(), "/server/discord": (context) => DiscordConfigPage(), "/server/snapshots": (context) => SnapshotsPage(), "/server/snapshots/restore": (context) => SnapshotListPage() }); } } class ServerPage extends StatelessWidget { TextEditingController serverIP = TextEditingController(); TextEditingController username = TextEditingController(); TextEditingController password = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Conan Exiles Server Manager - Login"), backgroundColor: Constants.TITLEBAR_COLOR, ), floatingActionButton: ElevatedButton( onPressed: () async { // Send login packet to server Settings settings = Settings(); settings.client = PacketClient(); int port = 25306; String ip = serverIP.text; List ipParts = ip.split(':'); if (ipParts.length == 2) { ip = ipParts[0]; port = int.parse(ipParts[1]); } print("Attempting to connect to FQDN/IP : $ip on port $port"); await settings.client!.startConnect(ip, port); C2SLoginPacket login = C2SLoginPacket(); login.username = username.text; login.password = password.text; S2CResponse response = await settings.client!.send(login, true); S2CLoginReply loginResponse = S2CLoginReply(); loginResponse.decodeTag(response.contents); loginResponse.handleClientPacket(); if (loginResponse.valid) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text("Login Success - Downloading remote Settings"))); int retryCount = 0; while (true) { try { if (retryCount > 0) ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( "> Retrying to download settings in 10 seconds (Attempt $retryCount"))); await Future.delayed(Duration(seconds: 10)); S2CResponse settingsData = await settings.client! .send(C2SRequestSettingsPacket(), true); C2SRequestSettingsPacket settingsBack = C2SRequestSettingsPacket(); settingsBack.decodeTag(settingsData.contents); settingsBack.handleClientPacket(); break; } catch (E) { retryCount++; } } Navigator.pushNamed(context, "/home"); } else { print("Login not valid"); } }, child: Text("Login"), ), body: SingleChildScrollView( child: Column( children: [ ListTile( title: Text("Server IP/FQDN"), subtitle: TextField( controller: serverIP, decoration: InputDecoration(hintText: "ex. 192.168.1.100"), ), ), ListTile( title: Text("Username"), subtitle: TextField( controller: username, decoration: InputDecoration(hintText: "the_user"), ), ), ListTile( title: Text("Password"), subtitle: TextField( controller: password, decoration: InputDecoration(hintText: "pass"), obscureText: true, ), ) ], ), )); } }