Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Config/BotConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ namespace LVCMod
class BotConfig
{
public string Token { get; set; } = "";

public ulong MainVoiceChatId { get; set; } = 0;
public string MainVoiceChatName { get; set; } = "Talk";

public ulong VoiceChatsCategoryId { get; set; } = 0;
public string VoiceChatsCategoryName { get; set; } = "Stardew Valley LVC";

public bool DeleteVoiceChats { get; set; } = true;
}
}
4 changes: 2 additions & 2 deletions Config/HostConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace LVCMod
class HostConfig
{
public ulong DiscordGuildId { get; set; } = 0;

public Dictionary<ulong, PlayerData> SavesData { get; set; } = new();
// Per-save data (players and channels) are stored in separate files under data/{saveId}/
// This config only keeps host-specific settings such as the guild id.
}
}
15 changes: 13 additions & 2 deletions Config/JsonKeys/PlayerData.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
namespace LVCMod
using System.Collections.Generic;

namespace LVCMod
{
public class PlayerData
{
public Dictionary<long, ulong> Players { get; set; } = new();
public Dictionary<long, FarmerInfo> Players { get; set; } = new();
}

public class FarmerInfo
{
public ulong DiscordId { get; set; }
public string Team { get; set; } = "None";
// Per-player voice state persisted to players.json
public bool Muted { get; set; } = false;
public bool Deafen { get; set; } = false;
}
}
10 changes: 6 additions & 4 deletions Config/UserConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ class UserConfig
{
public ulong DiscordId { get; set; } = 0;

public bool MicrophoneActivated { get; set; } = true;
public string Team { get; set; } = "None"; // None, Blue, Red, Green, Yellow

public bool DeaferDesactivated { get; set; } = true;
// Muted and Deafen are now stored per-save in players.json

public SButton ChangeStateMicrophone { get; set; } = SButton.H;
public bool EnableVoiceHotkeys { get; set; } = true;

public SButton ChangeStateAudio { get; set; } = SButton.J;
public SButton ChangeStateMute { get; set; } = SButton.H;

public SButton ChangeStateDeaf { get; set; } = SButton.J;
}
}
17 changes: 15 additions & 2 deletions Discord API/Bot/Bot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Discord;
using Discord.Rest;
using Discord.WebSocket;
using StardewModdingAPI;
using StardewValley;

namespace LVCMod
Expand All @@ -12,7 +13,7 @@ partial class Bot
private ModEntry Mod { get; set; }

private DiscordSocketClient DiscordClient { get; set; }

private SocketGuild Guild { get; set; }

private TaskCompletionSource<bool> IsBotReady { get; set; } = new();
Expand All @@ -25,7 +26,19 @@ public Bot(ModEntry modEntry)
DiscordClient.Log += OnLog;
DiscordClient.Ready += OnReady;

_ = Start();
var startTask = Start();
startTask.ContinueWith(t =>
{
if (t.IsFaulted)
{
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.error.bot-login-failed", new { reason = t.Exception?.Flatten().Message })}", LogLevel.Error);
if (t.Exception != null)
{
foreach (var ex in t.Exception.Flatten().InnerExceptions)
Mod.Monitor.Log(ex.ToString(), LogLevel.Error);
}
}
}, TaskScheduler.Default);
}
}
}
77 changes: 67 additions & 10 deletions Discord API/Bot/Events/Starters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,30 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StardewModdingAPI;

namespace LVCMod
{
partial class Bot
{
private Task OnLog(LogMessage message)
{
LogLevel level = message.Severity switch
{
LogSeverity.Critical => LogLevel.Error,
LogSeverity.Error => LogLevel.Error,
LogSeverity.Warning => LogLevel.Warn,
LogSeverity.Info => LogLevel.Info,
LogSeverity.Verbose => LogLevel.Trace,
LogSeverity.Debug => LogLevel.Trace,
_ => LogLevel.Info
};

string text = $"[LVC-BOT] {message.Source}: {message.Message}";
if (message.Exception != null)
text += $" | Exception: {message.Exception.Message}";

Mod.Monitor.Log(text, level);
return Task.CompletedTask;
}

Expand All @@ -21,19 +38,47 @@ private Task OnLog(LogMessage message)
/// <returns>Task</returns>
private async Task OnReady()
{
Guild = DiscordClient.GetGuild(Mod.Config.Host.DiscordGuildId);
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.bot-ready")}", LogLevel.Info);

if (GetCategoryByName(Mod.Config.Bot.VoiceChatsCategoryName) is null)
await CreateVoiceChatsCategory();
Guild = DiscordClient.GetGuild(Mod.Config.Host.DiscordGuildId);
if (Guild is null)
{
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.error.guild-not-found", new { guildId = Mod.Config.Host.DiscordGuildId })}", LogLevel.Error);
}
else
{
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.guild-connected", new { guildName = Guild.Name, guildId = Guild.Id })}", LogLevel.Info);
}

if (GetVoiceChannelByName(Mod.Config.Bot.MainVoiceChatName) is null)
await CreateVoiceChannel(Mod.Config.Bot.MainVoiceChatName, false);
var category = GetCategoryByName(Mod.Config.Bot.VoiceChatsCategoryName);
if (category is null)
{
var newCat = await CreateVoiceChatsCategory();
Mod.Config.Bot.VoiceChatsCategoryId = newCat.Id;
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.category-created", new { categoryName = newCat.Name, categoryId = newCat.Id })}", LogLevel.Info);
}
else
{
Mod.Config.Bot.VoiceChatsCategoryId = category.Id;
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.category-found", new { categoryName = category.Name, categoryId = category.Id })}", LogLevel.Info);
}

await DiscordClient.SetCustomStatusAsync("Managing conversations");
var mainChannel = GetVoiceChannelByName(Mod.Config.Bot.MainVoiceChatName);
if (mainChannel is null)
{
var newChan = await CreateVoiceChannel(Mod.Config.Bot.MainVoiceChatName, false);
Mod.Config.Bot.MainVoiceChatId = newChan.Id;
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.main-channel-created", new { channelName = newChan.Name, channelId = newChan.Id })}", LogLevel.Info);
}
else
{
Mod.Config.Bot.MainVoiceChatId = mainChannel.Id;
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.main-channel-found", new { channelName = mainChannel.Name, channelId = mainChannel.Id })}", LogLevel.Info);
}

Mod.Helper.WriteConfig(Mod.Config);
await DiscordClient.SetCustomStatusAsync($"{Mod.Helper.Translation.Get("host.bot.activity.label")}");
IsBotReady.SetResult(true);

Debug.WriteLine($"{Mod.ModManifest.UniqueID}, {DiscordClient.ConnectionState}, {Guild.Id}, {IsBotReady}");
}

public async Task WaitForReady()
Expand All @@ -47,8 +92,20 @@ public async Task WaitForReady()
/// <returns>Task</returns>
private async Task Start()
{
await DiscordClient.LoginAsync(TokenType.Bot, Mod.Config.Bot.Token);
await DiscordClient.StartAsync();
try
{
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.bot-starting")}", LogLevel.Info);
await DiscordClient.LoginAsync(TokenType.Bot, Mod.Config.Bot.Token);
await DiscordClient.StartAsync();
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.info.bot-login-complete")}", LogLevel.Info);
}
catch (Exception ex)
{
Mod.Monitor.Log($"{Mod.Helper.Translation.Get("log.error.bot-login-failed", new { reason = ex.Message })}", LogLevel.Error);
Mod.Monitor.Log(ex.ToString(), LogLevel.Error);
IsBotReady.TrySetException(ex);
throw;
}
}
}
}
6 changes: 3 additions & 3 deletions Discord API/Bot/Methods/ForChannels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public async Task<RestCategoryChannel> CreateVoiceChatsCategory()
/// <param name="voiceChannel">Voice Channel To Delete</param>
/// <param name="beforeCondition">Condition to delete</param>
/// <returns>Task</returns>
public static async Task DeleteVoiceChannel(SocketVoiceChannel voiceChannel, Func<bool>? beforeCondition = null)
public static async Task DeleteVoiceChannel(SocketVoiceChannel voiceChannel, Func<bool> beforeCondition = null)
{
if (beforeCondition is not null)
{
Expand All @@ -82,9 +82,9 @@ public static async Task DeleteVoiceChannel(SocketVoiceChannel voiceChannel, Fun
/// <param name="voiceChannelName">Channel Name to Search</param>
/// <param name="beforeCondition">Condition</param>
/// <returns>Task</returns>
public async Task DeleteVoiceChannel(string voiceChannelName, Func<bool>? beforeCondition = null)
public async Task DeleteVoiceChannel(string voiceChannelName, Func<bool> beforeCondition = null)
{
SocketVoiceChannel? voiceChannel = GetVoiceChannelByName(voiceChannelName);
SocketVoiceChannel voiceChannel = GetVoiceChannelByName(voiceChannelName);

if (voiceChannel is null)
return;
Expand Down
Loading