添加公告系统

This commit is contained in:
milimoe 2025-07-24 01:27:35 +08:00
parent 596611edd8
commit aa3b923a6f
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
6 changed files with 521 additions and 337 deletions

View File

@ -1,13 +1,9 @@
using System.Data; using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Base; using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Oshima.Core.Configs; using Oshima.Core.Configs;
using Oshima.Core.Constant; using Oshima.Core.Constant;
using Oshima.FunGame.OshimaServers.Model;
using Oshima.FunGame.OshimaServers.Service; using Oshima.FunGame.OshimaServers.Service;
using TaskScheduler = Milimoe.FunGame.Core.Api.Utility.TaskScheduler; using TaskScheduler = Milimoe.FunGame.Core.Api.Utility.TaskScheduler;
@ -31,6 +27,13 @@ namespace Oshima.FunGame.OshimaServers
public static HashSet<AnonymousServer> Instances { get; } = []; public static HashSet<AnonymousServer> Instances { get; } = [];
public WebSocketService Service { get; }
public AnonymousServer()
{
Service = new(this);
}
/// <summary> /// <summary>
/// 向客户端推送事件 /// 向客户端推送事件
/// </summary> /// </summary>
@ -107,12 +110,14 @@ namespace Oshima.FunGame.OshimaServers
Controller.NewMailSender(); Controller.NewMailSender();
FunGameService.InitFunGame(); FunGameService.InitFunGame();
FunGameSimulation.InitFunGameSimulation(); FunGameSimulation.InitFunGameSimulation();
FunGameService.RefreshNotice();
TaskScheduler.Shared.AddTask("重置每日运势", new TimeSpan(0, 0, 0), () => TaskScheduler.Shared.AddTask("重置每日运势", new TimeSpan(0, 0, 0), () =>
{ {
Controller.WriteLine("已重置所有人的今日运势"); Controller.WriteLine("已重置所有人的今日运势");
Daily.ClearDaily(); Daily.ClearDaily();
// 刷新活动缓存 // 刷新活动缓存
FunGameService.GetEventCenter(); FunGameService.GetEventCenter();
FunGameService.RefreshNotice();
}); });
TaskScheduler.Shared.AddTask("上九", new TimeSpan(9, 0, 0), () => TaskScheduler.Shared.AddTask("上九", new TimeSpan(9, 0, 0), () =>
{ {
@ -128,153 +133,30 @@ namespace Oshima.FunGame.OshimaServers
}); });
TaskScheduler.Shared.AddRecurringTask("刷新存档缓存", TimeSpan.FromMinutes(1), () => TaskScheduler.Shared.AddRecurringTask("刷新存档缓存", TimeSpan.FromMinutes(1), () =>
{ {
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved"; FunGameService.RefreshSavedCache();
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
PluginConfig pc = FunGameService.GetUserConfig(fileName, out _);
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
// 将用户存入缓存
FunGameConstant.UserIdAndUsername[user.Id] = user;
bool updateQuest = false;
bool updateExplore = false;
// 任务结算
EntityModuleConfig<Quest> quests = new("quests", user.Id.ToString());
quests.LoadConfig();
if (quests.Count > 0 && FunGameService.SettleQuest(user, quests))
{
quests.SaveConfig();
updateQuest = true;
}
// 探索结算
PluginConfig pc2 = new("exploring", user.Id.ToString());
pc2.LoadConfig();
if (pc2.Count > 0 && FunGameService.SettleExploreAll(pc2, user))
{
pc2.SaveConfig();
updateExplore = true;
}
if (updateQuest || updateExplore)
{
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(user.Id, pc, user);
}
if (FunGameConstant.UserLastVisitStore.TryGetValue(user.Id, out LastStoreModel? value) && value != null && (DateTime.Now - value.LastTime).TotalMinutes > 2)
{
FunGameConstant.UserLastVisitStore.Remove(user.Id);
}
}
FunGameService.ReleaseUserSemaphoreSlim(fileName);
}
Controller.WriteLine("读取 FunGame 存档缓存", LogLevel.Debug); Controller.WriteLine("读取 FunGame 存档缓存", LogLevel.Debug);
}
}, true); }, true);
TaskScheduler.Shared.AddTask("刷新每日任务", new TimeSpan(4, 0, 0), () => TaskScheduler.Shared.AddTask("刷新每日任务", new TimeSpan(4, 0, 0), () =>
{ {
// 刷新每日任务 // 刷新每日任务
Task.Run(() => Task.Run(() =>
{ {
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/quests"; FunGameService.RefreshDailyQuest();
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
EntityModuleConfig<Quest> quests = new("quests", fileName);
quests.Clear();
FunGameService.CheckQuestList(quests);
quests.SaveConfig();
}
Controller.WriteLine("刷新每日任务"); Controller.WriteLine("刷新每日任务");
}
}); });
Task.Run(() => Task.Run(() =>
{ {
// 刷新每天登录 FunGameService.RefreshDailySignIn();
FunGameService.UserNotice.Clear();
// 刷新签到
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
PluginConfig pc = FunGameService.GetUserConfig(fileName, out _);
pc.Add("signed", false);
pc.Add("logon", false);
pc.Add("exploreTimes", FunGameConstant.MaxExploreTimes);
pc.SaveConfig();
FunGameService.ReleaseUserSemaphoreSlim(fileName);
}
Controller.WriteLine("刷新签到"); Controller.WriteLine("刷新签到");
}
}); });
Task.Run(() => Task.Run(() =>
{ {
// 刷新商店 FunGameService.RefreshStoreData();
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/storeNames";
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
EntityModuleConfig<Store> stores = new("storeNames", fileName);
stores.LoadConfig();
string[] storeNames = [.. stores.Keys];
if (long.TryParse(fileName, out long userId) && FunGameConstant.UserIdAndUsername.TryGetValue(userId, out User? user) && user != null)
{
// 更新玩家商店数据,移除所有当天刷新的商店
FunGameConstant.UserLastVisitStore.Remove(userId);
stores.Remove("daily");
foreach (string key in storeNames)
{
Store? store = stores.Get(key);
if (store != null && (store.GlobalStock || (store.AutoRefresh && store.NextRefreshDate.Date <= DateTime.Today)))
{
stores.Remove(key);
}
}
FunGameService.CheckDailyStore(stores, user);
}
else
{
// 非玩家商店数据,需要更新模板的商品
foreach (string key in storeNames)
{
Store? store = stores.Get(key);
if (store != null)
{
if (store.ExpireTime != null && store.ExpireTime.Value.Date <= DateTime.Today)
{
stores.Remove(key);
continue;
}
if (store.AutoRefresh && store.NextRefreshDate.Date <= DateTime.Today)
{
store.Goods.Clear();
foreach (long goodsId in store.NextRefreshGoods.Keys)
{
store.Goods[goodsId] = store.NextRefreshGoods[goodsId];
}
store.NextRefreshDate = DateTime.Today.AddHours(4).AddDays(store.RefreshInterval);
}
}
}
}
stores.SaveConfig();
}
Controller.WriteLine("刷新商店"); Controller.WriteLine("刷新商店");
}
}); });
// 刷新活动缓存 // 刷新活动缓存
FunGameService.GetEventCenter(); FunGameService.GetEventCenter();
FunGameService.RefreshNotice();
}); });
TaskScheduler.Shared.AddRecurringTask("刷新boss", TimeSpan.FromHours(1), () => TaskScheduler.Shared.AddRecurringTask("刷新boss", TimeSpan.FromHours(1), () =>
{ {
@ -326,13 +208,13 @@ namespace Oshima.FunGame.OshimaServers
switch (command.Trim().ToLower()) switch (command.Trim().ToLower())
{ {
case "scadd": case "scadd":
msg = SCAdd(data); msg = Service.SCAdd(data);
break; break;
case "sclist": case "sclist":
msg = SCList(data); msg = Service.SCList(data);
break; break;
case "screcord": case "screcord":
msg = SCRecord(data); msg = Service.SCRecord(data);
break; break;
case "att": case "att":
break; break;
@ -350,188 +232,6 @@ namespace Oshima.FunGame.OshimaServers
return result; return result;
} }
public string SCAdd(Dictionary<string, object> data)
{
string result = "";
using SQLHelper? sql = Controller.GetSQLHelper();
if (sql != null)
{
try
{
long qq = Controller.JSON.GetObject<long>(data, "qq");
long groupid = Controller.JSON.GetObject<long>(data, "groupid");
double sc = Controller.JSON.GetObject<double>(data, "sc");
sql.NewTransaction();
sql.Script = "select * from saints where qq = @qq and `group` = @group";
sql.Parameters.Add("qq", qq);
sql.Parameters.Add("group", groupid);
sql.ExecuteDataSet();
string content = Controller.JSON.GetObject<string>(data, "content") ?? "";
string record = "";
if (sql.Success)
{
record = Convert.ToString(sql.DataSet.Tables[0].Rows[0]["record"]) ?? "";
}
record = $"{DateTime.Now:MM/dd HH:mm}{content}{(sc < 0 ? "-" : "+") + Math.Abs(sc)}\r\n{record}";
record = string.Join("\r\n", record.Split("\r\n", StringSplitOptions.RemoveEmptyEntries).Take(10));
if (sql.Success)
{
sql.Script = "update saints set sc = sc + @sc, record = @record where qq = @qq and `group` = @group";
}
else
{
sql.Script = "insert into saints(qq, sc, `group`, record) values(@qq, @sc, @group, @record)";
}
sql.Parameters.Add("sc", sc);
sql.Parameters.Add("qq", qq);
sql.Parameters.Add("group", groupid);
sql.Parameters.Add("record", record);
sql.Execute();
if (sql.Success)
{
Controller.WriteLine($"用户 {qq} 的圣人点数增加了 {sc}", LogLevel.Debug);
sql.Commit();
}
else
{
sql.Rollback();
}
}
catch (Exception e)
{
result = e.ToString();
sql.Rollback();
}
}
else result = "无法调用此接口SQL 服务不可用。";
return result;
}
public string SCList(Dictionary<string, object> data)
{
string result;
SQLHelper? sql = Controller.SQLHelper;
if (sql != null)
{
long userQQ = Controller.JSON.GetObject<long>(data, "qq");
(bool userHas, double userSC, int userTop, string userRemark) = (false, 0, 0, "");
long groupid = Controller.JSON.GetObject<long>(data, "groupid");
bool reverse = Controller.JSON.GetObject<bool>(data, "reverse");
if (!reverse)
{
result = $"☆--- OSMTV 圣人排行榜 TOP10 ---☆\r\n统计时间{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)}\r\n";
}
else
{
result = $"☆--- OSMTV 出生排行榜 TOP10 ---☆\r\n统计时间{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)}\r\n";
}
sql.Script = "select * from saints where `group` = @group order by sc" + (!reverse ? " desc" : "");
sql.Parameters.Add("group", groupid);
sql.ExecuteDataSet();
if (sql.Success && sql.DataSet.Tables.Count > 0)
{
int count = 0;
foreach (DataRow dr in sql.DataSet.Tables[0].Rows)
{
count++;
long qq = Convert.ToInt64(dr["qq"]);
double sc = Convert.ToDouble(dr["sc"]);
string remark = Convert.ToString(dr["remark"]) ?? "";
if (reverse)
{
sc = -sc;
remark = remark.Replace("+", "-");
}
if (qq == userQQ)
{
userHas = true;
userSC = sc;
userTop = count;
userRemark = remark;
}
if (count > 10) continue;
if (!reverse)
{
result += $"{count}. 用户:{qq},圣人点数:{sc} 分{(remark.Trim() != "" ? $" ({remark})" : "")}\r\n";
}
else
{
result += $"{count}. 用户:{qq},出生点数:{sc} 分{(remark.Trim() != "" ? $" ({remark})" : "")}\r\n";
}
}
if (!reverse && userHas)
{
result += $"你的圣人点数为:{userSC} 分{(userRemark.Trim() != "" ? $"{userRemark}" : "")},排在第 {userTop} / {sql.DataSet.Tables[0].Rows.Count} 名。\r\n" +
$"本排行榜仅供娱乐,不代表任何官方立场或真实情况。";
}
if (reverse && userHas)
{
result += $"你的出生点数为:{userSC} 分{(userRemark.Trim() != "" ? $"{userRemark}" : "")},排在出生榜第 {userTop} / {sql.DataSet.Tables[0].Rows.Count} 名。\r\n" +
$"本排行榜仅供娱乐,不代表任何官方立场或真实情况。";
}
}
else
{
if (reverse)
{
result = "出生榜目前没有任何数据。";
}
else
{
result = "圣人榜目前没有任何数据。";
}
}
}
else result = "无法调用此接口SQL 服务不可用。";
return result.Trim();
}
public string SCRecord(Dictionary<string, object> data)
{
string result = "";
SQLHelper? sql = Controller.SQLHelper;
if (sql != null)
{
long userQQ = Controller.JSON.GetObject<long>(data, "qq");
long groupid = Controller.JSON.GetObject<long>(data, "groupid");
result = $"☆--- 圣人点数信息 ---☆\r\n统计时间{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)}\r\n";
sql.Script = "select * from saints where `group` = @group order by sc desc";
sql.Parameters.Add("group", groupid);
sql.Parameters.Add("qq", userQQ);
sql.ExecuteDataSet();
if (sql.Success && sql.DataSet.Tables.Count > 0)
{
Dictionary<int, DataRow> dict = sql.DataSet.Tables[0].AsEnumerable().Select((r, i) => new { Index = i + 1, Row = r }).ToDictionary(c => c.Index, c => c.Row);
int index = dict.Where(kv => Convert.ToInt64(kv.Value["qq"]) == userQQ).Select(r => r.Key).FirstOrDefault();
if (index != 0 && dict.TryGetValue(index, out DataRow? dr) && dr != null)
{
long qq = Convert.ToInt64(dr["qq"]);
double sc = Convert.ToDouble(dr["sc"]);
string remark = Convert.ToString(dr["remark"]) ?? "";
string record = Convert.ToString(dr["record"]) ?? "";
result += $"用户:{qq},圣人点数:{sc} 分{(remark.Trim() != "" ? $" ({remark})" : "")},排在圣人榜第 {index} / {sql.DataSet.Tables[0].Rows.Count} 名。\r\n" +
$"{(record != "" ? "\r\n" + record + "\r\n" : "")}本系统仅供娱乐,不代表任何官方立场或真实情况。";
}
else
{
result = "你在这个群没有任何历史记录。";
}
}
else
{
result = "你在这个群没有任何历史记录。";
}
}
else result = "无法调用此接口SQL 服务不可用。";
return result.Trim();
}
public override Task<Dictionary<string, object>> GamingMessageHandler(IServerModel model, GamingType type, Dictionary<string, object> data) public override Task<Dictionary<string, object>> GamingMessageHandler(IServerModel model, GamingType type, Dictionary<string, object> data)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -0,0 +1,22 @@
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Constant;
namespace Oshima.FunGame.OshimaServers.Model
{
public class NoticeModel : BaseEntity
{
public string Title { get; set; } = "";
public string Content { get; set; } = "";
public string Author { get; set; } = "";
public DateTime StartTime { get; set; } = DateTime.MinValue;
public DateTime EndTime { get; set; } = DateTime.MaxValue;
public override string ToString()
{
return $"系统公告【{Title}】{Author} 发布于 {StartTime.ToString(General.GeneralDateTimeFormatChinese)}\r\n{Content}";
}
public override bool Equals(IBaseEntity? other) => other is NoticeModel && other.GetIdName() == GetIdName();
}
}

View File

@ -29,6 +29,7 @@ namespace Oshima.FunGame.OshimaServers.Service
public static Dictionary<int, Character> Bosses { get; } = []; public static Dictionary<int, Character> Bosses { get; } = [];
public static ServerPluginLoader? ServerPluginLoader { get; set; } = null; public static ServerPluginLoader? ServerPluginLoader { get; set; } = null;
public static WebAPIPluginLoader? WebAPIPluginLoader { get; set; } = null; public static WebAPIPluginLoader? WebAPIPluginLoader { get; set; } = null;
public static EntityModuleConfig<NoticeModel> Notices { get; } = new("notices", "notice");
public static void InitFunGame() public static void InitFunGame()
{ {
@ -619,13 +620,6 @@ namespace Oshima.FunGame.OshimaServers.Service
} }
} }
if (!pc.TryGetValue("logon", out object? value) || (value is bool logon && !logon))
{
pc.Add("logon", true);
AddNotice(user.Id, "欢迎回到筽祀牻大陆!请发送【帮助】获取更多玩法指令哦~");
AddNotice(user.Id, GetEvents());
}
return user; return user;
} }
@ -2073,12 +2067,12 @@ namespace Oshima.FunGame.OshimaServers.Service
} }
stores.Add("daily", daily); stores.Add("daily", daily);
SetLastStore(user, true, "", ""); SetLastStore(user, true, "", "");
return daily.ToString(); return daily.ToString(user);
} }
else else
{ {
SetLastStore(user, true, "", ""); SetLastStore(user, true, "", "");
return daily.ToString(); return daily.ToString(user);
} }
} }
@ -3989,7 +3983,7 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
Store? store = value.VisitStore(stores, user, storeName); Store? store = value.VisitStore(stores, user, storeName);
exist = store != null; exist = store != null;
msg = store?.ToString() ?? ""; msg = store?.ToString(user) ?? "";
} }
if (!exist) if (!exist)
@ -4004,6 +3998,203 @@ namespace Oshima.FunGame.OshimaServers.Service
return msg; return msg;
} }
public static void RefreshNotice()
{
Notices.LoadConfig();
}
public static void RefreshSavedCache()
{
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
PluginConfig pc = GetUserConfig(fileName, out _);
if (pc.Count > 0)
{
User user = GetUser(pc);
// 将用户存入缓存
FunGameConstant.UserIdAndUsername[user.Id] = user;
bool updateQuest = false;
bool updateExplore = false;
// 任务结算
EntityModuleConfig<Quest> quests = new("quests", user.Id.ToString());
quests.LoadConfig();
if (quests.Count > 0 && SettleQuest(user, quests))
{
quests.SaveConfig();
updateQuest = true;
}
// 探索结算
PluginConfig pc2 = new("exploring", user.Id.ToString());
pc2.LoadConfig();
if (pc2.Count > 0 && SettleExploreAll(pc2, user))
{
pc2.SaveConfig();
updateExplore = true;
}
if (updateQuest || updateExplore)
{
SetUserConfigButNotRelease(user.Id, pc, user);
}
if (FunGameConstant.UserLastVisitStore.TryGetValue(user.Id, out LastStoreModel? value) && value != null && (DateTime.Now - value.LastTime).TotalMinutes > 2)
{
FunGameConstant.UserLastVisitStore.Remove(user.Id);
}
}
ReleaseUserSemaphoreSlim(fileName);
}
}
}
public static void RefreshDailyQuest()
{
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/quests";
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
EntityModuleConfig<Quest> quests = new("quests", fileName);
quests.Clear();
CheckQuestList(quests);
quests.SaveConfig();
}
}
}
public static void RefreshDailySignIn()
{
// 刷新每天登录
UserNotice.Clear();
// 刷新签到
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
PluginConfig pc = GetUserConfig(fileName, out _);
pc.Add("signed", false);
pc.Add("logon", false);
pc.Add("lunch", false);
pc.Add("dinner", false);
pc.Add("exploreTimes", FunGameConstant.MaxExploreTimes);
pc.SaveConfig();
ReleaseUserSemaphoreSlim(fileName);
}
}
}
public static void RefreshStoreData()
{
// 刷新商店
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/stores";
if (Directory.Exists(directoryPath))
{
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
EntityModuleConfig<Store> stores = new("stores", fileName);
stores.LoadConfig();
string[] storeNames = [.. stores.Keys];
if (long.TryParse(fileName, out long userId) && FunGameConstant.UserIdAndUsername.TryGetValue(userId, out User? user) && user != null)
{
// 更新玩家商店数据,移除所有当天刷新的商店
FunGameConstant.UserLastVisitStore.Remove(userId);
stores.Remove("daily");
foreach (string key in storeNames)
{
Store? store = stores.Get(key);
if (store != null && (store.GlobalStock || (store.AutoRefresh && store.NextRefreshDate.Date <= DateTime.Today)))
{
stores.Remove(key);
}
}
CheckDailyStore(stores, user);
}
else
{
// 非玩家商店数据,需要更新模板的商品
foreach (string key in storeNames)
{
Store? store = stores.Get(key);
if (store != null)
{
if (store.ExpireTime != null && store.ExpireTime.Value.Date <= DateTime.Today)
{
stores.Remove(key);
continue;
}
if (store.AutoRefresh && store.NextRefreshDate.Date <= DateTime.Today)
{
store.Goods.Clear();
foreach (long goodsId in store.NextRefreshGoods.Keys)
{
store.Goods[goodsId] = store.NextRefreshGoods[goodsId];
}
store.NextRefreshDate = DateTime.Today.AddHours(4).AddDays(store.RefreshInterval);
}
}
}
}
stores.SaveConfig();
}
}
}
public static void OnUserConfigSaving(PluginConfig pc, User user)
{
DateTime now = DateTime.Now;
if (!pc.TryGetValue("logon", out object? value) || (value is bool logon && !logon))
{
pc.Add("logon", true);
AddNotice(user.Id, "欢迎回到筽祀牻大陆!请发送【帮助】获取更多玩法指令哦~");
AddNotice(user.Id, GetEvents());
foreach (NoticeModel notice in Notices.Values)
{
if (now >= notice.StartTime && now <= notice.EndTime)
{
AddNotice(user.Id, notice.ToString());
}
}
}
int count1 = 30;
int count2 = 30;
DateTime d1 = DateTime.Today.AddHours(11);
DateTime d2 = DateTime.Today.AddHours(13);
DateTime d3 = DateTime.Today.AddHours(17);
DateTime d4 = DateTime.Today.AddHours(19);
if (now >= d1 && now <= d2 && (!pc.TryGetValue("lunch", out value) || (value is bool lunch && !lunch)))
{
int exploreTimes = FunGameConstant.MaxExploreTimes + count1;
if (pc.TryGetValue("exploreTimes", out object? value2) && int.TryParse(value2.ToString(), out exploreTimes))
{
exploreTimes += count1;
}
pc.Add("exploreTimes", exploreTimes);
pc.Add("lunch", true);
AddNotice(user.Id, $"在 11-13 点期间登录游戏获得了午餐!(探索许可+{count1}");
}
if (now >= d3 && now <= d4 && (!pc.TryGetValue("dinner", out value) || (value is bool dinner && !dinner)))
{
int exploreTimes = FunGameConstant.MaxExploreTimes + count2;
if (pc.TryGetValue("exploreTimes", out object? value2) && int.TryParse(value2.ToString(), out exploreTimes))
{
exploreTimes += count2;
}
pc.Add("exploreTimes", exploreTimes);
pc.Add("dinner", true);
AddNotice(user.Id, $"在 17-19 点期间登录游戏获得了晚餐!(探索许可+{count2}");
}
}
public static void ReleaseUserSemaphoreSlim(string key) public static void ReleaseUserSemaphoreSlim(string key)
{ {
if (FunGameConstant.UserSemaphoreSlims.TryGetValue(key, out SemaphoreSlim? obj) && obj != null && obj.CurrentCount == 0) if (FunGameConstant.UserSemaphoreSlims.TryGetValue(key, out SemaphoreSlim? obj) && obj != null && obj.CurrentCount == 0)
@ -4016,6 +4207,7 @@ namespace Oshima.FunGame.OshimaServers.Service
public static void SetUserConfig(string key, PluginConfig pc, User user, bool updateLastTime = true, bool release = true) public static void SetUserConfig(string key, PluginConfig pc, User user, bool updateLastTime = true, bool release = true)
{ {
OnUserConfigSaving(pc, user);
if (updateLastTime) user.LastTime = DateTime.Now; if (updateLastTime) user.LastTime = DateTime.Now;
pc.Add("user", user); pc.Add("user", user);
pc.SaveConfig(); pc.SaveConfig();

View File

@ -0,0 +1,196 @@
using System.Data;
using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Controller;
using Milimoe.FunGame.Core.Interface.Addons;
using Milimoe.FunGame.Core.Library.Constant;
namespace Oshima.FunGame.OshimaServers.Service
{
public class WebSocketService(AnonymousServer server)
{
public AnonymousServer ServerInstance { get; set; } = server;
public ServerAddonController<IGameModuleServer> Controller => ServerInstance.Controller;
public string SCAdd(Dictionary<string, object> data)
{
string result = "";
using SQLHelper? sql = Controller.GetSQLHelper();
if (sql != null)
{
try
{
long qq = Controller.JSON.GetObject<long>(data, "qq");
long groupid = Controller.JSON.GetObject<long>(data, "groupid");
double sc = Controller.JSON.GetObject<double>(data, "sc");
sql.NewTransaction();
sql.Script = "select * from saints where qq = @qq and `group` = @group";
sql.Parameters.Add("qq", qq);
sql.Parameters.Add("group", groupid);
sql.ExecuteDataSet();
string content = Controller.JSON.GetObject<string>(data, "content") ?? "";
string record = "";
if (sql.Success)
{
record = Convert.ToString(sql.DataSet.Tables[0].Rows[0]["record"]) ?? "";
}
record = $"{DateTime.Now:MM/dd HH:mm}{content}{(sc < 0 ? "-" : "+") + Math.Abs(sc)}\r\n{record}";
record = string.Join("\r\n", record.Split("\r\n", StringSplitOptions.RemoveEmptyEntries).Take(10));
if (sql.Success)
{
sql.Script = "update saints set sc = sc + @sc, record = @record where qq = @qq and `group` = @group";
}
else
{
sql.Script = "insert into saints(qq, sc, `group`, record) values(@qq, @sc, @group, @record)";
}
sql.Parameters.Add("sc", sc);
sql.Parameters.Add("qq", qq);
sql.Parameters.Add("group", groupid);
sql.Parameters.Add("record", record);
sql.Execute();
if (sql.Success)
{
Controller.WriteLine($"用户 {qq} 的圣人点数增加了 {sc}", LogLevel.Debug);
sql.Commit();
}
else
{
sql.Rollback();
}
}
catch (Exception e)
{
result = e.ToString();
sql.Rollback();
}
}
else result = "无法调用此接口SQL 服务不可用。";
return result;
}
public string SCList(Dictionary<string, object> data)
{
string result;
SQLHelper? sql = Controller.SQLHelper;
if (sql != null)
{
long userQQ = Controller.JSON.GetObject<long>(data, "qq");
(bool userHas, double userSC, int userTop, string userRemark) = (false, 0, 0, "");
long groupid = Controller.JSON.GetObject<long>(data, "groupid");
bool reverse = Controller.JSON.GetObject<bool>(data, "reverse");
if (!reverse)
{
result = $"☆--- OSMTV 圣人排行榜 TOP10 ---☆\r\n统计时间{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)}\r\n";
}
else
{
result = $"☆--- OSMTV 出生排行榜 TOP10 ---☆\r\n统计时间{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)}\r\n";
}
sql.Script = "select * from saints where `group` = @group order by sc" + (!reverse ? " desc" : "");
sql.Parameters.Add("group", groupid);
sql.ExecuteDataSet();
if (sql.Success && sql.DataSet.Tables.Count > 0)
{
int count = 0;
foreach (DataRow dr in sql.DataSet.Tables[0].Rows)
{
count++;
long qq = Convert.ToInt64(dr["qq"]);
double sc = Convert.ToDouble(dr["sc"]);
string remark = Convert.ToString(dr["remark"]) ?? "";
if (reverse)
{
sc = -sc;
remark = remark.Replace("+", "-");
}
if (qq == userQQ)
{
userHas = true;
userSC = sc;
userTop = count;
userRemark = remark;
}
if (count > 10) continue;
if (!reverse)
{
result += $"{count}. 用户:{qq},圣人点数:{sc} 分{(remark.Trim() != "" ? $" ({remark})" : "")}\r\n";
}
else
{
result += $"{count}. 用户:{qq},出生点数:{sc} 分{(remark.Trim() != "" ? $" ({remark})" : "")}\r\n";
}
}
if (!reverse && userHas)
{
result += $"你的圣人点数为:{userSC} 分{(userRemark.Trim() != "" ? $"{userRemark}" : "")},排在第 {userTop} / {sql.DataSet.Tables[0].Rows.Count} 名。\r\n" +
$"本排行榜仅供娱乐,不代表任何官方立场或真实情况。";
}
if (reverse && userHas)
{
result += $"你的出生点数为:{userSC} 分{(userRemark.Trim() != "" ? $"{userRemark}" : "")},排在出生榜第 {userTop} / {sql.DataSet.Tables[0].Rows.Count} 名。\r\n" +
$"本排行榜仅供娱乐,不代表任何官方立场或真实情况。";
}
}
else
{
if (reverse)
{
result = "出生榜目前没有任何数据。";
}
else
{
result = "圣人榜目前没有任何数据。";
}
}
}
else result = "无法调用此接口SQL 服务不可用。";
return result.Trim();
}
public string SCRecord(Dictionary<string, object> data)
{
string result = "";
SQLHelper? sql = Controller.SQLHelper;
if (sql != null)
{
long userQQ = Controller.JSON.GetObject<long>(data, "qq");
long groupid = Controller.JSON.GetObject<long>(data, "groupid");
result = $"☆--- 圣人点数信息 ---☆\r\n统计时间{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)}\r\n";
sql.Script = "select * from saints where `group` = @group order by sc desc";
sql.Parameters.Add("group", groupid);
sql.Parameters.Add("qq", userQQ);
sql.ExecuteDataSet();
if (sql.Success && sql.DataSet.Tables.Count > 0)
{
Dictionary<int, DataRow> dict = sql.DataSet.Tables[0].AsEnumerable().Select((r, i) => new { Index = i + 1, Row = r }).ToDictionary(c => c.Index, c => c.Row);
int index = dict.Where(kv => Convert.ToInt64(kv.Value["qq"]) == userQQ).Select(r => r.Key).FirstOrDefault();
if (index != 0 && dict.TryGetValue(index, out DataRow? dr) && dr != null)
{
long qq = Convert.ToInt64(dr["qq"]);
double sc = Convert.ToDouble(dr["sc"]);
string remark = Convert.ToString(dr["remark"]) ?? "";
string record = Convert.ToString(dr["record"]) ?? "";
result += $"用户:{qq},圣人点数:{sc} 分{(remark.Trim() != "" ? $" ({remark})" : "")},排在圣人榜第 {index} / {sql.DataSet.Tables[0].Rows.Count} 名。\r\n" +
$"{(record != "" ? "\r\n" + record + "\r\n" : "")}本系统仅供娱乐,不代表任何官方立场或真实情况。";
}
else
{
result = "你在这个群没有任何历史记录。";
}
}
else
{
result = "你在这个群没有任何历史记录。";
}
}
else result = "无法调用此接口SQL 服务不可用。";
return result.Trim();
}
}
}

View File

@ -5411,7 +5411,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
if (newItem.ItemType != ItemType.MagicCard) newItem.SetLevel(1); if (newItem.ItemType != ItemType.MagicCard) newItem.SetLevel(1);
itemMsg += $"[ {count} ] {newItem.ToString(false, true)}".Trim(); itemMsg += $"[ {count} ] {newItem.ToString(false, true)}".Trim();
} }
msg = good.ToString().Split("包含物品:")[0].Trim(); msg = good.ToString(user).Split("包含物品:")[0].Trim();
msg += $"\r\n包含物品\r\n" + itemMsg + msg += $"\r\n包含物品\r\n" + itemMsg +
$"\r\n剩余库存{(good.Stock == -1 ? "" : good.Stock)}"; $"\r\n剩余库存{(good.Stock == -1 ? "" : good.Stock)}";
} }
@ -7156,7 +7156,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
if (newItem.ItemType != ItemType.MagicCard) newItem.SetLevel(1); if (newItem.ItemType != ItemType.MagicCard) newItem.SetLevel(1);
itemMsg += $"[ {count} ] {newItem.ToString(false, true)}".Trim(); itemMsg += $"[ {count} ] {newItem.ToString(false, true)}".Trim();
} }
msg = good.ToString().Split("包含物品:")[0].Trim(); msg = good.ToString(user).Split("包含物品:")[0].Trim();
msg += $"\r\n包含物品\r\n" + itemMsg + msg += $"\r\n包含物品\r\n" + itemMsg +
$"\r\n剩余库存{(good.Stock == -1 ? "" : good.Stock)}"; $"\r\n剩余库存{(good.Stock == -1 ? "" : good.Stock)}";
} }

View File

@ -34,9 +34,8 @@ namespace Oshima.FunGame.WebAPI.Services
{ {
third.Result += "\r\n" + content.Trim(); third.Result += "\r\n" + content.Trim();
third.IsCompleted = true; third.IsCompleted = true;
return;
} }
if (msg.IsGroup) else if (msg.IsGroup)
{ {
content = "\r\n" + content.Trim(); content = "\r\n" + content.Trim();
await Service.SendGroupMessageAsync(msg.OpenId, content, msgType, media, msg.Id, msgSeq); await Service.SendGroupMessageAsync(msg.OpenId, content, msgType, media, msg.Id, msgSeq);
@ -49,7 +48,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (msg.UseNotice && msg.FunGameUID > 0 && FunGameService.UserNotice.TryGetValue(msg.FunGameUID, out HashSet<string>? msgs) && msgs != null) if (msg.UseNotice && msg.FunGameUID > 0 && FunGameService.UserNotice.TryGetValue(msg.FunGameUID, out HashSet<string>? msgs) && msgs != null)
{ {
FunGameService.UserNotice.Remove(msg.FunGameUID); FunGameService.UserNotice.Remove(msg.FunGameUID);
await SendAsync(msg, "每日登录提醒", string.Join("\r\n", msgs), msgType, media, 5); await SendAsync(msg, "离线未读信箱", $"☆--- 离线未读信箱 ---☆\r\n{string.Join("\r\n", msgs)}", msgType, media, 5);
} }
} }
@ -154,6 +153,81 @@ namespace Oshima.FunGame.WebAPI.Services
return true; return true;
} }
if (e.Detail == "公告")
{
e.UseNotice = false;
FunGameService.RefreshNotice();
if (FunGameService.Notices.Count > 0)
{
List<string> msgs = [];
DateTime now = DateTime.Now;
foreach (NoticeModel notice in FunGameService.Notices.Values)
{
if (now >= notice.StartTime && now <= notice.EndTime)
{
msgs.Add(notice.ToString());
}
}
await SendAsync(e, "公告", string.Join("\r\n", msgs));
}
else
{
await SendAsync(e, "公告", "当前没有任何系统公告。");
}
return true;
}
if (e.Detail == "刷新公告")
{
e.UseNotice = false;
FunGameService.RefreshNotice();
return true;
}
if (e.Detail.StartsWith("添加公告"))
{
e.UseNotice = false;
string detail = e.Detail.Replace("添加公告", "").Trim();
string[] strings = detail.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
string title = $"#Unknown";
if (strings.Length > 1)
{
title = strings[0].Trim();
detail = strings[1].Trim();
}
else
{
await SendAsync(e, "添加公告", $"格式错误:添加公告 <标题>\r\n<内容> [有效期 <天数>]。");
return true;
}
strings = detail.Split("有效期");
int days = 1;
if (strings.Length > 1)
{
if (int.TryParse(strings[1].Trim(), out int d))
{
days = d;
}
detail = strings[0].Trim();
}
string author = "FunGame";
if (FunGameConstant.UserIdAndUsername.TryGetValue(uid, out User? user) && user != null)
{
author = user.Username;
}
FunGameService.Notices.Add(title, new NoticeModel()
{
Title = title,
Author = author,
Content = detail,
StartTime = DateTime.Now,
EndTime = DateTime.Today.AddHours(3).AddMinutes(59).AddSeconds(59).AddDays(days)
});
FunGameService.Notices.SaveConfig();
await SendAsync(e, "添加公告", $"添加完毕,请查看【公告】列表!");
return true;
}
if (e.Detail == "查询服务器启动时间") if (e.Detail == "查询服务器启动时间")
{ {
e.UseNotice = false; e.UseNotice = false;