Got more things functional

This commit is contained in:
zontreck 2024-05-23 22:18:59 -07:00
parent a1141cd2b8
commit fc0c1c7e7a
23 changed files with 1080 additions and 876 deletions

View file

@ -0,0 +1,18 @@
import 'package:libac_flutter/utils/TimeUtils.dart';
import 'package:servermanager/statemachine.dart';
class SessionData {
static bool shutdownPending = false;
/// This flag will track the number of seconds until restart
///
/// This is initialized initially based on the AutomaticRestart timer if enabled.
///
/// This may be updated to one to two minutes by a Mod Update, or Wrapper update
static Time timer = Time(hours: 0, minutes: 0, seconds: 0);
static Time operating_time = Time(hours: 0, minutes: 0, seconds: 0);
static String shutdownMessage = "";
static WarnIntervals CURRENT_INTERVAL = WarnIntervals.NONE;
}

View file

@ -1,32 +1,28 @@
import 'package:libac_flutter/nbt/NbtUtils.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/nbt/impl/IntTag.dart';
import 'package:libac_flutter/utils/TimeUtils.dart';
class AutomaticRestartInfo {
final int hours;
final int minutes;
final int seconds;
Time time = Time(hours: 0, minutes: 0, seconds: 0);
final bool enabled;
const AutomaticRestartInfo(
{this.hours = 0,
this.minutes = 0,
this.seconds = 0,
this.enabled = false});
AutomaticRestartInfo({required this.time, this.enabled = false});
static AutomaticRestartInfo deserialize(CompoundTag tag) {
return AutomaticRestartInfo(
hours: tag.get(TAG_HOURS)?.asInt() ?? 12,
minutes: tag.get(TAG_MINUTES)?.asInt() ?? 0,
seconds: tag.get(TAG_SECONDS)?.asInt() ?? 0,
time: Time(
hours: tag.get(TAG_HOURS)?.asInt() ?? 12,
minutes: tag.get(TAG_MINUTES)?.asInt() ?? 0,
seconds: tag.get(TAG_SECONDS)?.asInt() ?? 0),
enabled: NbtUtils.readBoolean(tag, TAG_ENABLED));
}
CompoundTag serialize() {
CompoundTag tag = CompoundTag();
tag.put(TAG_HOURS, IntTag.valueOf(hours));
tag.put(TAG_MINUTES, IntTag.valueOf(minutes));
tag.put(TAG_SECONDS, IntTag.valueOf(seconds));
tag.put(TAG_HOURS, IntTag.valueOf(time.hours));
tag.put(TAG_MINUTES, IntTag.valueOf(time.minutes));
tag.put(TAG_SECONDS, IntTag.valueOf(time.seconds));
NbtUtils.writeBoolean(tag, TAG_ENABLED, enabled);
return tag;

View file

@ -1,25 +1,19 @@
import 'package:libac_flutter/nbt/NbtUtils.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/nbt/impl/StringTag.dart';
class Credentials {
String username;
String password;
String secret;
bool has_2fa = false;
Credentials(
{required this.username,
required this.password,
required this.secret,
required this.has_2fa});
Credentials({
required this.username,
required this.password,
});
CompoundTag save() {
CompoundTag tag = CompoundTag();
tag.put(TAG_USERNAME, StringTag.valueOf(username));
tag.put(TAG_PASSWORD, StringTag.valueOf(password));
tag.put(TAG_SECRET, StringTag.valueOf(secret));
NbtUtils.writeBoolean(tag, TAG_2FA, has_2fa);
return tag;
}
@ -27,14 +21,10 @@ class Credentials {
static Credentials deserialize(CompoundTag tag) {
return Credentials(
username: tag.get(TAG_USERNAME)?.asString() ?? "",
password: tag.get(TAG_PASSWORD)?.asString() ?? "",
secret: tag.get(TAG_SECRET)?.asString() ?? "",
has_2fa: NbtUtils.readBoolean(tag, TAG_2FA));
password: tag.get(TAG_PASSWORD)?.asString() ?? "");
}
static const TAG_NAME = "credentials";
static const TAG_USERNAME = "username";
static const TAG_PASSWORD = "password";
static const TAG_SECRET = "secret";
static const TAG_2FA = "2fa";
}

View file

@ -1,4 +1,6 @@
import 'package:libac_flutter/utils/uuid/NbtUUID.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/nbt/impl/IntTag.dart';
import 'package:libac_flutter/nbt/impl/StringTag.dart';
import 'package:libac_flutter/utils/uuid/UUID.dart';
class Mod {
@ -8,10 +10,10 @@ class Mod {
String mod_hash = "";
bool newMod = false;
NbtUUID _id = NbtUUID.ZERO;
UUID _id = UUID.ZERO;
String mod_instance_id() {
if (_id.toString() == NbtUUID.ZERO) {
_id = NbtUUID.fromUUID(UUID.generate(4));
if (_id.toString() == UUID.ZERO.toString()) {
_id = UUID.generate(4);
}
return _id.toString();
@ -23,4 +25,24 @@ class Mod {
this.newMod = false,
this.mod_pak = "Not Initialized",
this.mod_hash = ""});
CompoundTag serialize() {
CompoundTag tag = CompoundTag();
tag.put("name", StringTag.valueOf(mod_name));
tag.put("id", IntTag.valueOf(mod_id));
tag.put("pak", StringTag.valueOf(mod_pak));
tag.put("hash", StringTag.valueOf(mod_hash));
return tag;
}
static Mod deserialize(CompoundTag tag) {
CompoundTag ct = tag as CompoundTag;
return Mod(
mod_name: ct.get("name")!.asString(),
mod_id: ct.get("id")!.asInt(),
mod_pak: ct.get("pak")!.asString(),
mod_hash: ct.get("hash")!.asString());
}
}

View file

@ -5,14 +5,19 @@ import 'package:dio/dio.dart';
import 'package:libac_flutter/nbt/NbtIo.dart';
import 'package:libac_flutter/nbt/NbtUtils.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/nbt/impl/StringTag.dart';
import 'package:libac_flutter/packets/packets.dart';
import 'package:libac_flutter/utils/IOTools.dart';
import 'package:libac_flutter/utils/uuid/NbtUUID.dart';
import 'package:libac_flutter/utils/uuid/UUID.dart';
import 'package:rcon/rcon.dart';
import 'package:servermanager/statemachine.dart';
import 'package:servermanager/structs/credentials.dart';
import 'package:servermanager/structs/mod.dart';
import 'package:servermanager/structs/settingsEntry.dart';
import '../proton.dart';
class Settings {
final String windows =
"https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip";
@ -28,13 +33,15 @@ class Settings {
Settings._();
static final Settings Instance = Settings._();
bool server = true;
String steamcmd_path = "";
String game_path = "";
String proton_path = "";
String base_path = "";
bool FTS = true;
Credentials serverLoginCreds = Credentials(
username: "admin", password: "changeMe123", secret: "", has_2fa: false);
Credentials serverLoginCreds =
Credentials(username: "admin", password: "changeMe123");
UUID remoteLoginToken = UUID.ZERO;
PacketClient? client;
@ -45,9 +52,50 @@ class Settings {
return Instance;
}
CompoundTag serialize() {
CompoundTag tag = CompoundTag();
tag.put("steamcmd", StringTag.valueOf(steamcmd_path));
tag.put("game", StringTag.valueOf(game_path));
tag.put("proton", StringTag.valueOf(proton_path));
tag.put("base", StringTag.valueOf(base_path));
NbtUtils.writeBoolean(tag, "fts", FTS);
tag.put("server_creds", serverLoginCreds.save());
NbtUtils.writeUUID(tag, "token", NbtUUID.fromUUID(remoteLoginToken));
if (inst != null) tag.put("main", inst!.serialize());
return tag;
}
void deserialize(CompoundTag tag) {
// Verify Remote Login Token
UUID ID = NbtUtils.readUUID(tag, "token").toUUID();
if (ID.toString() != remoteLoginToken.toString()) {
// Invalid session
print(
"Invalid login session detected, or two admins are connected at once");
}
steamcmd_path = tag.get("steamcmd")!.asString();
game_path = tag.get("game")!.asString();
proton_path = tag.get("proton")!.asString();
base_path = tag.get("proton")!.asString();
FTS = NbtUtils.readBoolean(tag, "fts"); // First Time Setup.
// FTS should be disabled by the client when sending it back to the server in a C2SApplySettingsPacket
serverLoginCreds =
Credentials.deserialize(tag.get("server_creds")!.asCompoundTag());
if (tag.containsKey("main")) {
inst = SettingsEntry.deserialize(tag.get("main")!.asCompoundTag());
}
}
SettingsEntry? inst;
Future<void> Read() async {
if (!server) return;
try {
var tag = await NbtIo.read("settings.dat");
@ -58,19 +106,23 @@ class Settings {
} catch (E) {
print("No existing settings file found, initializing default settings");
inst = SettingsEntry();
inst!.steam_creds =
Credentials(username: "", password: "", secret: "", has_2fa: false);
inst!.steam_creds = Credentials(
username: "",
password: "",
);
serverLoginCreds = Credentials(
username: "admin",
password: "changeMe123",
secret: "",
has_2fa: false);
username: "admin",
password: "changeMe123",
);
FTS = true;
}
}
void Write() {
if (!server) {
return; // safeguard against writing to a settings file on the client
}
if (inst == null) return;
CompoundTag tag = CompoundTag();
tag.put("entry", inst!.serialize());
@ -110,10 +162,6 @@ class Settings {
return steamcmd_path;
}
String getSteamCmd2FA() {
return "$steamcmd_path${Platform.pathSeparator}steamcmd-2fa${Platform.isWindows ? ".exe" : ""}";
}
String getModPath() {
return PathHelper(pth: base_path).resolve("mods").build();
}
@ -180,8 +228,9 @@ class Settings {
if (await dir.exists()) {
return;
} else
} else {
await dir.create(recursive: true);
}
}
File getModListFile() {
@ -204,7 +253,7 @@ class Settings {
.resolve("content")
.resolve("440900")
.resolve("${mod.mod_id}")
.resolve("${mod.mod_pak}")
.resolve(mod.mod_pak)
.build();
if (Platform.isWindows) {
paths.add(pth);
@ -220,6 +269,18 @@ class Settings {
flush: true, mode: FileMode.writeOnly);
}
Future<void> initializeProtonPrefix() async {
runProton("echo", ["hello"]);
}
Future<String> sendRconCommand(String command) async {
Client cli =
await Client.create("127.0.0.1", inst!.serverSettings.RconPort);
Message msg = Message.create(cli, PacketType.command, command);
return cli.send(msg).payload;
}
Future<void> initializeProton() async {
Dio dio = Dio();
print("Downloading proton...");
@ -257,7 +318,7 @@ class Settings {
if (Platform.isWindows) {
// Download zip file
final path = "${steamcmd_path}${Platform.pathSeparator}windows.zip";
final path = "$steamcmd_path${Platform.pathSeparator}windows.zip";
final reply = await dio.download(windows, path);
final bytes = File(path).readAsBytesSync();
@ -283,7 +344,7 @@ class Settings {
print("Completed.");
} else {
// Download tgz file
final path = "${steamcmd_path}${Platform.pathSeparator}linux.tgz";
final path = "$steamcmd_path${Platform.pathSeparator}linux.tgz";
final reply = await dio.download(linux, path);
final bytes = File(path).readAsBytesSync();

View file

@ -1,6 +1,8 @@
import 'package:libac_flutter/nbt/NbtUtils.dart';
import 'package:libac_flutter/nbt/Tag.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/nbt/impl/StringTag.dart';
import 'package:libac_flutter/nbt/impl/ListTag.dart';
import 'package:libac_flutter/utils/TimeUtils.dart';
import 'package:servermanager/structs/autorestarts.dart';
import 'package:servermanager/structs/credentials.dart';
import 'package:servermanager/structs/mod.dart';
@ -9,29 +11,37 @@ import 'package:servermanager/structs/serversettings.dart';
class SettingsEntry {
List<Mod> mods = [];
Credentials? steam_creds;
AutomaticRestartInfo timer = AutomaticRestartInfo();
bool pterodactylMode = true; // Default is to be compatible
AutomaticRestartInfo timer =
AutomaticRestartInfo(time: Time(hours: 0, minutes: 0, seconds: 0));
ServerSettings serverSettings = ServerSettings(
RconPassword: "Password01234",
RconPort: 7779,
GamePort: 7780,
QueryPort: 7782);
bool downloadMods = true;
String conanExilesLibraryPath = "";
static SettingsEntry deserialize(CompoundTag tag) {
SettingsEntry st = SettingsEntry();
if (tag.containsKey(Credentials.TAG_NAME))
if (tag.containsKey(Credentials.TAG_NAME)) {
st.steam_creds =
Credentials.deserialize(tag.get(Credentials.TAG_NAME) as CompoundTag);
}
st.timer = AutomaticRestartInfo.deserialize(
tag.get(AutomaticRestartInfo.TAG_NAME) as CompoundTag);
st.serverSettings = ServerSettings.deserialize(
tag.get(ServerSettings.TAG_NAME) as CompoundTag);
st.downloadMods = NbtUtils.readBoolean(tag, "download");
st.conanExilesLibraryPath = tag.get("libpath")?.asString() ?? "";
if (tag.containsKey("pterodactyl")) {
st.pterodactylMode = NbtUtils.readBoolean(tag, "pterodactyl");
}
st.mods.clear();
ListTag lMods = tag.get("mods") as ListTag;
for (Tag tag in lMods.value) {
CompoundTag cTag = tag.asCompoundTag();
st.mods.add(Mod.deserialize(cTag));
}
return st;
}
@ -41,9 +51,13 @@ class SettingsEntry {
if (steam_creds != null) tag.put(Credentials.TAG_NAME, steam_creds!.save());
tag.put(AutomaticRestartInfo.TAG_NAME, timer.serialize());
tag.put(ServerSettings.TAG_NAME, serverSettings.serialize());
NbtUtils.writeBoolean(tag, "download", downloadMods);
NbtUtils.writeBoolean(tag, "pterodactyl", pterodactylMode);
tag.put("libpath", StringTag.valueOf(conanExilesLibraryPath));
ListTag lMods = ListTag();
for (Mod mod in mods) {
lMods.add(mod.serialize());
}
tag.put("mods", lMods);
return tag;
}