添加了市场和私信功能

This commit is contained in:
milimoe 2025-07-28 20:02:44 +08:00
parent 4b0c7bb942
commit e743997f65
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
15 changed files with 953 additions and 98 deletions

View File

@ -33,9 +33,9 @@ namespace Oshima.FunGame.OshimaModules.Models
public static List<Item> AllItems { get; } = [];
public static List<Skill> AllSkills { get; } = [];
public static Dictionary<long, User> UserIdAndUsername { get; } = [];
public static Dictionary<long, Item> MarketItemIdAndItem { get; } = [];
public static Dictionary<long, LastStoreModel> UserLastVisitStore { get; } = [];
public static ConcurrentDictionary<string, SemaphoreSlim> UserSemaphoreSlims { get; } = [];
public static SemaphoreSlim MarketSemaphoreSlim { get; } = new(1, 1);
public static ItemType[] ItemCanUsed => [ItemType.Consumable, ItemType.MagicCard, ItemType.SpecialItem, ItemType.GiftBox, ItemType.Others];
public static ItemType[] ItemCanNotDrawCard => [ItemType.Collectible, ItemType.QuestItem, ItemType.GiftBox, ItemType.Others];

View File

@ -10,7 +10,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override string Description => Effects.Count > 0 ? Effects.First().Description : "";
public override string DispelDescription => Effects.Count > 0 ? Effects.First().DispelDescription : "";
public override double EPCost => 100;
public override double CD => 40 - 1 * (Level - 1);
public override double CD => 60 - 1.5 * (Level - 1);
public override double HardnessTime { get; set; } = 8;
public override bool CanSelectSelf => true;
public override bool CanSelectEnemy => false;

View File

@ -10,7 +10,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override string Description => Effects.Count > 0 ? Effects.First().Description : "";
public override string DispelDescription => Effects.Count > 0 ? Effects.First().DispelDescription : "";
public override double EPCost => 100;
public override double CD => 35 - 2 * (Level - 1);
public override double CD => 80 - 4 * (Level - 1);
public override double HardnessTime { get; set; } = 0;
public override bool CanSelectSelf => true;
public override bool CanSelectEnemy => false;
@ -25,13 +25,26 @@ namespace Oshima.FunGame.OshimaModules.Skills
{
public override long Id => Skill.Id;
public override string Name => "三重叠加";
public override string Description => $"使 [ 灵能反射 ] 支持普通攻击,且当前释放魔法次数归零,最大硬直消除次数提高到 {灵能反射次数} 次;在魔法命中和普通攻击命中时能够回复所回复能量值的 3 倍魔法值,持续 {技能持续次数} 次(灵能反射每消除次数达到最大时算一次)。" +
public override string Description => $"使 [ 灵能反射 ] 支持普通攻击,且当前释放魔法次数归零,最大硬直消除次数提高到 {灵能反射次数} 次;在魔法命中和普通攻击命中时能够回复所回复能量值的 {魔法值倍数:0.#} 倍魔法值,持续 {技能持续次数} 次(灵能反射每消除次数达到最大时算一次)。" +
$"(剩余:{剩余持续次数} 次)";
public override DispelledType DispelledType => DispelledType.CannotBeDispelled;
public int { get; set; } = 0;
private readonly int = 3;
private readonly int = 2;
private double
{
get
{
return Skill.Level * 0.5;
}
}
private int
{
get
{
return Skill.Level > 3 ? 2 : 1;
}
}
public override void OnEffectGained(Character character)
{

View File

@ -59,13 +59,13 @@ namespace Oshima.FunGame.OshimaModules.Skills
{
return Level switch
{
1 => 3,
2 => 3,
3 => 4,
4 => 4,
5 => 5,
6 => 5,
_ => 3
1 => 2,
2 => 2,
3 => 3,
4 => 3,
5 => 4,
6 => 3,
_ => 2
};
}
}
@ -76,11 +76,11 @@ namespace Oshima.FunGame.OshimaModules.Skills
return Level switch
{
1 => 1,
2 => 2,
2 => 1,
3 => 2,
4 => 3,
4 => 2,
5 => 3,
6 => 4,
6 => 3,
_ => 1
};
}

View File

@ -10,7 +10,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override string Description => Effects.Count > 0 ? Effects.First().Description : "";
public override string DispelDescription => Effects.Count > 0 ? Effects.First().DispelDescription : "";
public override double EPCost => 100;
public override double CD => 60 - 2 * (Level - 1);
public override double CD => 80 - 4 * (Level - 1);
public override double HardnessTime { get; set; } = 15;
public override bool CanSelectSelf => true;
public override bool CanSelectEnemy => false;

View File

@ -9,8 +9,8 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override string Name => "能量毁灭";
public override string Description => Effects.Count > 0 ? Effects.First().Description : "";
public override double EPCost => 100;
public override double CD => 60 - 1 * (Level - 1);
public override double HardnessTime { get; set; } = 25;
public override double CD => 100 - 4 * (Level - 1);
public override double HardnessTime { get; set; } = 18;
public override string Slogan => "从深渊引爆力量,世界将为之颤抖!!!!";
public override bool CanSelectSelf => false;
public override bool CanSelectEnemy => true;
@ -39,7 +39,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
private double => 0.2 * Level;
private double => * Skill.Character?.INT ?? 0;
private double => 1.05 * Level;
private double => 1 * Level;
public override void OnSkillCasted(Character caster, List<Character> targets, Dictionary<string, object> others)
{

View File

@ -10,7 +10,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override string Description => Effects.Count > 0 ? Effects.First().Description : "";
public override string DispelDescription => Effects.Count > 0 ? Effects.First().DispelDescription : "";
public override double EPCost => 100;
public override double CD => 45;
public override double CD => 45 + 1 * (Level - 1);
public override double HardnessTime { get; set; } = 7;
public override bool CanSelectSelf => true;
public override bool CanSelectEnemy => false;
@ -25,16 +25,18 @@ namespace Oshima.FunGame.OshimaModules.Skills
{
public override long Id => Skill.Id;
public override string Name => Skill.Name;
public override string Description => $"获得 40% 吸血,持续 {Duration:0.##} {GameplayEquilibriumConstant.InGameTime}。";
public override string Description => $"获得 {吸血系数 * 100:0.##}% 吸血,持续 {Duration:0.##} {GameplayEquilibriumConstant.InGameTime}。";
public override bool Durative => true;
public override double Duration => 30;
public override DispelledType DispelledType => DispelledType.CannotBeDispelled;
private double => 0.2 + 0.05 * (Level - 1);
public override void AfterDamageCalculation(Character character, Character enemy, double damage, double actualDamage, bool isNormalAttack, DamageType damageType, MagicType magicType, DamageResult damageResult)
{
if (character == Skill.Character && (damageResult == DamageResult.Normal || damageResult == DamageResult.Critical) && character.HP < character.MaxHP)
{
double = 0.4 * damage;
double = * damage;
HealToTarget(character, character, );
}
}

View File

@ -25,22 +25,25 @@ namespace Oshima.FunGame.OshimaModules.Skills
{
public override long Id => Skill.Id;
public override string Name => Skill.Name;
public override string Description => $"{Duration:0.##} {GameplayEquilibriumConstant.InGameTime}内,增加 40% 攻击力 [ {攻击力提升:0.##} ]、30% 物理穿透和 25% 闪避率(不可叠加),普通攻击硬直时间额外减少 20%,基于 {系数 * 100:0.##}% 敏捷 [ {伤害加成:0.##} ] 强化普通攻击的伤害。在持续时间内,[ 心灵之火 ] 的冷却时间降低至 3 {GameplayEquilibriumConstant.InGameTime}。";
public override string Description => $"{Duration:0.##} {GameplayEquilibriumConstant.InGameTime}内,增加 {攻击力提升系数 * 100:0.##}% 攻击力 [ {攻击力提升:0.##} ]、{物理穿透提升 * 100:0.##}% 物理穿透和 {闪避率提升 * 100:0.##}% 闪避率(不可叠加),普通攻击硬直时间额外减少 20%,基于 {系数 * 100:0.##}% 敏捷 [ {伤害加成:0.##} ] 强化普通攻击的伤害。在持续时间内,[ 心灵之火 ] 的冷却时间降低至 3 {GameplayEquilibriumConstant.InGameTime}。";
public override bool Durative => true;
public override double Duration => 40;
public override double Duration => 30;
public override DispelledType DispelledType => DispelledType.CannotBeDispelled;
private double => 1.2 * (1 + 0.6 * (Skill.Level - 1));
private double => 1.2 * (1 + 0.5 * (Skill.Level - 1));
private double => * Skill.Character?.AGI ?? 0;
private double => 0.4 * Skill.Character?.BaseATK ?? 0;
private double => Skill.Level > 0 ? 0.15 + 0.03 * (Skill.Level - 1) : 0.15;
private double => * Skill.Character?.BaseATK ?? 0;
private double 穿 => Skill.Level > 0 ? 0.1 + 0.03 * (Skill.Level - 1) : 0.1;
private double => Skill.Level > 0 ? 0.1 + 0.02 * (Skill.Level - 1) : 0.1;
private double = 0;
public override void OnEffectGained(Character character)
{
= ;
character.ExATK2 += ;
character.PhysicalPenetration += 0.3;
character.ExEvadeRate += 0.25;
character.PhysicalPenetration += 穿;
character.ExEvadeRate += ;
if (character.Effects.Where(e => e is ).FirstOrDefault() is e)
{
e. = 3;
@ -51,11 +54,11 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override void OnEffectLost(Character character)
{
character.ExATK2 -= ;
character.PhysicalPenetration -= 0.3;
character.ExEvadeRate -= 0.25;
character.PhysicalPenetration -= 穿;
character.ExEvadeRate -= ;
if (character.Effects.Where(e => e is ).FirstOrDefault() is e)
{
e. = 8;
e. = 10;
}
}

View File

@ -28,7 +28,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
( > 0 ? $"(正在冷却:剩余 {冷却时间:0.##} {GameplayEquilibriumConstant.InGameTime}" : "");
public double { get; set; } = 0;
public double { get; set; } = 12;
public double { get; set; } = 10;
private bool = false;
public override double AlterActualDamageAfterCalculation(Character character, Character enemy, double damage, bool isNormalAttack, DamageType damageType, MagicType magicType, DamageResult damageResult, ref bool isEvaded, Dictionary<Effect, double> totalDamageBonus)

View File

@ -10,7 +10,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override string Description => Effects.Count > 0 ? Effects.First().Description : "";
public override string DispelDescription => Effects.Count > 0 ? Effects.First().DispelDescription : "";
public override double EPCost => 100;
public override double CD => 35;
public override double CD => 50;
public override double HardnessTime { get; set; } = 3;
public override bool CanSelectSelf => true;
public override bool CanSelectEnemy => false;

View File

@ -155,6 +155,11 @@ namespace Oshima.FunGame.OshimaServers
FunGameService.RefreshStoreData();
Controller.WriteLine("刷新商店");
});
Task.Run(() =>
{
FunGameService.RefreshMarketData();
Controller.WriteLine("刷新市场");
});
// 刷新活动缓存
FunGameService.GetEventCenter();
FunGameService.RefreshNotice();

View File

@ -102,6 +102,7 @@
public static Dictionary<string, string> ClubHelp { get; } = new() {
{"我的社团", "查看社团信息"},
{"私信 <对方UID/昵称> <内容>", "发送私信给对方"},
{"加入社团 <社团序号>", "申请加入社团"},
{"退出社团", "退出当前社团"},
{"创建社团 <前缀>", "创建一个公开社团,若指令中包含私密一词,将创建私密社团\r\n社团前缀3-4个字符允许英文字母和数字、部分特殊字符"},
@ -122,14 +123,17 @@
{"社团商店查看 <商品序号>", "查看指定商品详情"},
{"社团商店购买 <商品序号>", "购买指定商品"},
{"社团商店出售 <物品序号>", "向商店出售具有回收价的指定物品"},
{"社团市场上架 <物品序号> <定价>", "将物品寄售到社团市场上手续费10%并且8%进入社团基金"},
{"社团市场 [页码]", "查看社团市场商品"},
{"社团市场出售 <物品序号> <定价>", "将物品寄售到社团市场上系统手续费4%社团收取8%作为社团基金"},
{"社团市场下架 <市场物品序号>", "下架指定物品"},
{"社团市场查看 <市场物品序号>", "查看指定物品"},
{"社团市场购买 <市场物品序号>", "购买指定物品"},
{"社团市场清空", "管理员可下架所有物品"},
};
public static Dictionary<string, string> ActivityHelp { get; } = new() {
{"签到", "每日签到奖励"},
{"公告", "查看系统公告"},
{"活动", "查看活动中心"},
{"查活动 <活动序号>", "查看指定活动详情"},
{"做活动任务 <活动序号> <任务序号>", "开始指定活动任务"},
@ -156,11 +160,15 @@
{"报价添加对方物品 <报价序号> <{物品序号}...>", "仅发起方可操作"},
{"报价移除物品 <报价序号> <{报价物品序号}...>", "仅发起方可操作"},
{"报价移除对方物品 <报价序号> <{报价物品序号}...>", "仅发起方可操作"},
{"市场上架 <物品序号> <定价>", "将物品寄售到市场上手续费15%"},
{"市场 [页码]", "查看市场商品"},
{"市场出售 <物品序号> <定价>", "将物品寄售到市场上手续费15%"},
{"市场下架 <市场物品序号>", "下架指定物品"},
{"市场查看 <市场物品序号>", "查看指定物品"},
{"市场购买 <市场物品序号>", "购买指定物品"},
{"社团市场上架 <物品序号> <定价>", "将物品寄售到社团市场上手续费10%并且8%进入社团基金"},
{"社团市场 [页码]", "查看社团市场商品"},
{"社团市场出售 <物品序号> <定价>", "将物品寄售到社团市场上系统手续费4%社团收取8%作为社团基金"},
{"社团市场下架 <市场物品序号>", "下架指定物品"},
{"社团市场查看 <市场物品序号>", "查看指定物品"},
{"社团市场购买 <市场物品序号>", "购买指定物品"},
{"社团市场清空", "管理员可下架所有物品"},
};

View File

@ -2113,13 +2113,13 @@ namespace Oshima.FunGame.OshimaServers.Service
if (goods.Stock != -1 && goods.Stock - count < 0)
{
return msg = $"此商品【{goods.Name}】库存不足,无法购买!\r\n你想要购买 {count} 件,但库存只有 {goods.Stock} 件。";
return $"此商品【{goods.Name}】库存不足,无法购买!\r\n你想要购买 {count} 件,但库存只有 {goods.Stock} 件。";
}
goods.UsersBuyCount.TryGetValue(user.Id, out int buyCount);
if (goods.Quota > 0 && (buyCount + count > goods.Quota))
{
return msg = $"此商品【{goods.Name}】限量购买 {goods.Quota} 件!\r\n你已经购买了 {buyCount} 件,想要购买 {count} 件,超过了购买限制。";
return $"此商品【{goods.Name}】限量购买 {goods.Quota} 件!\r\n你已经购买了 {buyCount} 件,想要购买 {count} 件,超过了购买限制。";
}
foreach (string needy in goods.Prices.Keys)
@ -2169,7 +2169,7 @@ namespace Oshima.FunGame.OshimaServers.Service
foreach (Item item in goods.Items)
{
if (item.Name == nameof())
if (item.Id == (long)SpecialItemID.)
{
int exploreTimes = FunGameConstant.MaxExploreTimes + count;
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out exploreTimes))
@ -2210,6 +2210,80 @@ namespace Oshima.FunGame.OshimaServers.Service
return msg;
}
public static string MarketBuyItem(Market market, MarketItem item, PluginConfig pc, User user, int count, out bool result)
{
result = false;
string msg = "";
DateTime now = DateTime.Now;
if (market.StartTime > now || market.EndTime < now)
{
return "铎京集市未处于营业时间内。";
}
if (item.Status != MarketItemState.Listed)
{
return $"无法购买此商品,原因:该商品的状态是:{CommonSet.GetMarketItemStatus(item.Status)}。";
}
if (item.User == user.Id)
{
return $"不能购买自己上架的商品!如需下架,请使用【市场下架+序号】指令。";
}
if (item.Stock != -1 && item.Stock - count < 0)
{
return $"此商品【{item.Name}】库存不足,无法购买!\r\n你想要购买 {count} 件,但库存只有 {item.Stock} 件。";
}
double reduce = Calculation.Round2Digits(item.Price * count);
if (user.Inventory.Credits >= reduce)
{
user.Inventory.Credits -= reduce;
}
else
{
return $"你的{General.GameplayEquilibriumConstant.InGameCurrency}不足 {reduce} 呢,无法购买【{item.Name}】!";
}
if (item.Item.Id == (long)SpecialItemID.)
{
int exploreTimes = FunGameConstant.MaxExploreTimes + count;
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out exploreTimes))
{
exploreTimes += count;
}
pc.Add("exploreTimes", exploreTimes);
}
else
{
for (int i = 0; i < count; i++)
{
AddItemToUserInventory(user, item.Item, copyLevel: true, useOriginalPrice: true, toExploreCache: false, toActivitiesCache: false);
}
}
if (item.Stock != -1)
{
item.Stock -= count;
if (item.Stock < 0) item.Stock = 0;
if (item.Stock == 0)
{
item.Status = MarketItemState.Purchased;
item.FinishTime = DateTime.Now;
}
}
item.Buyers.Add(user.Id);
result = true;
msg += $"恭喜你成功购买 {count} 件【{item.Name}】!\r\n" +
$"总计消费:{(item.Price > 0 ? item.Price : "")}\r\n" +
$"包含物品:[{ItemSet.GetQualityTypeName(item.Item.QualityType)}|{ItemSet.GetItemTypeName(item.Item.ItemType)}] {item.Item.Name} * {count}\r\n" +
$"铎京集市期待你的下次光临。";
return msg;
}
public static string Select_CheckAutoKey(SQLHelper SQLHelper, string AutoKey)
{
SQLHelper.Parameters["@AutoKey"] = AutoKey;
@ -3289,7 +3363,7 @@ namespace Oshima.FunGame.OshimaServers.Service
{
user.Inventory.Items.Remove(item);
Item newItem = item.Copy(copyGuid: true);
Item newItem = item.Copy(true, true);
newItem.User = user2;
newItem.IsSellable = false;
newItem.IsTradable = false;
@ -3306,7 +3380,7 @@ namespace Oshima.FunGame.OshimaServers.Service
{
user2.Inventory.Items.Remove(item);
Item newItem = item.Copy(copyGuid: true);
Item newItem = item.Copy(true, true);
newItem.User = user;
newItem.IsSellable = false;
newItem.IsTradable = false;
@ -4204,6 +4278,156 @@ namespace Oshima.FunGame.OshimaServers.Service
}
}
public static string GetMarketInfo(Market market, User? user = null, int page = 1, bool simply = false, bool showListed = true)
{
if (page <= 0) page = 1;
int maxPage = market.MarketItems.Values.MaxPage(10);
if (page > maxPage) page = maxPage;
IEnumerable<MarketItem> marketItems = market.MarketItems.Values.GetPage(page, 10);
StringBuilder builder = new();
builder.AppendLine($"☆★☆ {market.Name} ☆★☆");
if (market.Description != "") builder.AppendLine($"{market.Description}");
if (market.StartTime.HasValue && market.EndTime.HasValue)
{
builder.AppendLine($"开放时间:{market.StartTime.Value.ToString(General.GeneralDateTimeFormatChinese)} 至 {market.EndTime.Value.ToString(General.GeneralDateTimeFormatChinese)}");
}
else if (market.StartTime.HasValue && !market.EndTime.HasValue)
{
builder.AppendLine($"开始开放时间:{market.StartTime.Value.ToString(General.GeneralDateTimeFormatChinese)}");
}
else if (!market.StartTime.HasValue && market.EndTime.HasValue)
{
builder.AppendLine($"停止开放时间:{market.EndTime.Value.ToString(General.GeneralDateTimeFormatChinese)}");
}
else
{
builder.AppendLine($"开放时间:全年无休,永久开放");
}
if (market.StartTimeOfDay.HasValue && market.EndTimeOfDay.HasValue)
{
builder.AppendLine($"每日交易时间:{market.StartTimeOfDay.Value.ToString(General.GeneralDateTimeFormatTimeOnly)} 至 {market.EndTimeOfDay.Value.ToString(General.GeneralDateTimeFormatTimeOnly)}");
}
else
{
builder.AppendLine($"[ 24H ] 全天开放交易");
}
DateTime now = DateTime.Now;
TimeSpan nowTimeOfDay = now.TimeOfDay;
bool isStoreOpen = true;
if (market.StartTime.HasValue && market.StartTime.Value > now || market.EndTime.HasValue && market.EndTime.Value < now)
{
isStoreOpen = false;
}
if (isStoreOpen && market.StartTimeOfDay.HasValue && market.EndTimeOfDay.HasValue)
{
TimeSpan startTimeSpan = market.StartTimeOfDay.Value.TimeOfDay;
TimeSpan endTimeSpan = market.EndTimeOfDay.Value.TimeOfDay;
if (startTimeSpan <= endTimeSpan)
{
isStoreOpen = nowTimeOfDay >= startTimeSpan && nowTimeOfDay <= endTimeSpan;
}
else
{
isStoreOpen = nowTimeOfDay >= startTimeSpan || nowTimeOfDay <= endTimeSpan;
}
}
if (!isStoreOpen)
{
builder.AppendLine($"市场现在不在交易时间内。");
}
builder.AppendLine($"☆--- 市场商品列表 ---☆");
MarketItem[] MarketItemsValid = [.. market.MarketItems.Values];
if (showListed) MarketItemsValid = [.. MarketItemsValid.Where(g => g.Status == MarketItemState.Listed)];
if (MarketItemsValid.Length == 0)
{
builder.AppendLine("当前没有商品可供购买,过一段时间再来吧。");
}
else
{
foreach (MarketItem marketItem in MarketItemsValid)
{
builder.AppendLine(FunGameService.GetMarketItemInfo(marketItem, true, user?.Id ?? 0));
}
builder.AppendLine("提示:使用【市场查看+序号】查看商品详细信息,使用【市场购买+序号】购买商品。");
}
if (user != null)
{
builder.AppendLine($"你的现有{General.GameplayEquilibriumConstant.InGameCurrency}{user.Inventory.Credits:0.##}");
}
builder.AppendLine($"页数:{page} / {maxPage},使用【市场+页码】快速跳转指定页面。");
return builder.ToString().Trim();
}
public static string GetMarketItemInfo(MarketItem item, bool simply, long visitUser)
{
StringBuilder builder = new();
if (simply)
{
builder.AppendLine($"{item.Id}. {item.Name}");
builder.AppendLine($"{ItemSet.GetQualityTypeName(item.Item.QualityType)} {ItemSet.GetItemTypeName(item.Item.ItemType)}");
string username = item.Username;
if (FunGameConstant.UserIdAndUsername.TryGetValue(item.User, out User? user) && user != null)
{
username = user.Username;
}
builder.AppendLine($"卖家:{username}");
builder.AppendLine($"商品描述:{item.Item.Description}");
builder.AppendLine($"商品售价:{(item.Price > 0 ? item.Price : "")} {General.GameplayEquilibriumConstant.InGameCurrency}");
if (item.Status == MarketItemState.Purchased)
{
builder.AppendLine($"商品已售罄");
}
else if (item.Status == MarketItemState.Delisted)
{
builder.AppendLine($"商品已下架");
}
else builder.AppendLine($"剩余库存:{(item.Stock == -1 ? "" : item.Stock)}");
}
else
{
builder.AppendLine($"{item.Id}. {item.Name}");
string username = item.Username;
if (FunGameConstant.UserIdAndUsername.TryGetValue(item.User, out User? user) && user != null)
{
username = user.Username;
}
builder.AppendLine($"卖家:{username}");
builder.AppendLine($"上架时间:{item.CreateTime.ToString(General.GeneralDateTimeFormatChinese)}");
builder.AppendLine($"商品售价:{(item.Price > 0 ? item.Price : "")} {General.GameplayEquilibriumConstant.InGameCurrency}");
if (item.Status == MarketItemState.Purchased)
{
builder.AppendLine($"商品已售罄");
if (item.FinishTime.HasValue) builder.AppendLine($"售罄时间:{item.FinishTime.Value.ToString(General.GeneralDateTimeFormatChinese)}");
if (visitUser == item.User && item.Buyers.Count > 0)
{
HashSet<string> buyers = [];
foreach (long buyerid in item.Buyers)
{
username = "Unknown";
if (FunGameConstant.UserIdAndUsername.TryGetValue(buyerid, out User? buyer) && buyer != null)
{
username = buyer.Username;
}
buyers.Add(username);
}
builder.AppendLine($"买家:{string.Join("", buyers)}");
}
}
else if (item.Status == MarketItemState.Delisted)
{
builder.AppendLine($"商品已下架");
if (item.FinishTime.HasValue) builder.AppendLine($"下架时间:{item.FinishTime.Value.ToString(General.GeneralDateTimeFormatChinese)}");
}
else builder.AppendLine($"剩余库存:{(item.Stock == -1 ? "" : item.Stock)}");
builder.AppendLine($"☆--- 物品信息 ---☆\r\n{item.Item}");
}
return builder.ToString().Trim();
}
public static void RefreshNotice()
{
Notices.LoadConfig();
@ -4335,7 +4559,6 @@ namespace Oshima.FunGame.OshimaServers.Service
{
if (store.ExpireTime != null && store.ExpireTime.Value.Date <= DateTime.Today)
{
stores.Remove(key);
continue;
}
if (store.AutoRefresh && store.NextRefreshDate.Date <= DateTime.Today)
@ -4347,6 +4570,7 @@ namespace Oshima.FunGame.OshimaServers.Service
}
store.NextRefreshDate = DateTime.Today.AddHours(4).AddDays(store.RefreshInterval);
}
stores.Add(key, store);
}
}
}
@ -4355,6 +4579,44 @@ namespace Oshima.FunGame.OshimaServers.Service
}
}
public static void RefreshMarketData()
{
// 刷新市场
GetMarketSemaphoreSlim();
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/markets";
if (Directory.Exists(directoryPath))
{
DateTime now = DateTime.Now;
string[] filePaths = Directory.GetFiles(directoryPath);
foreach (string filePath in filePaths)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
EntityModuleConfig<Market> markets = new("markets", fileName);
markets.LoadConfig();
string[] marketNames = [.. markets.Keys];
foreach (string key in marketNames)
{
Market? market = markets.Get(key);
if (market != null)
{
long[] items = [.. market.MarketItems.Keys];
foreach (long id in items)
{
MarketItem item = market.MarketItems[id];
if ((item.Status == MarketItemState.Delisted || item.Status == MarketItemState.Purchased) && item.FinishTime.HasValue && (now - item.FinishTime.Value).TotalDays >= 3)
{
market.MarketItems.Remove(id);
}
}
markets.Add(key, market);
}
}
markets.SaveConfig();
}
}
ReleaseMarketSemaphoreSlim();
}
public static void PreRefreshStore()
{
foreach (OshimaRegion region in FunGameConstant.PlayerRegions)
@ -4465,5 +4727,18 @@ namespace Oshima.FunGame.OshimaServers.Service
}
public static bool CheckSemaphoreSlim(long uid) => CheckSemaphoreSlim(uid.ToString());
public static void GetMarketSemaphoreSlim()
{
FunGameConstant.MarketSemaphoreSlim.Wait(FunGameConstant.SemaphoreSlimTimeout);
}
public static void ReleaseMarketSemaphoreSlim()
{
if (FunGameConstant.MarketSemaphoreSlim.CurrentCount == 0)
{
FunGameConstant.MarketSemaphoreSlim.Release();
}
}
}
}

View File

@ -16,7 +16,6 @@ using Oshima.FunGame.OshimaModules.Models;
using Oshima.FunGame.OshimaModules.Regions;
using Oshima.FunGame.OshimaServers.Model;
using Oshima.FunGame.OshimaServers.Service;
using ProjectRedbud.FunGame.SQLQueryExtension;
namespace Oshima.FunGame.WebAPI.Controllers
{
@ -6877,12 +6876,24 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
[HttpPost("marketsellitem")]
public string MarketSellItem([FromQuery] long? uid = null, [FromQuery] int itemIndex = -1, [FromQuery] double price = 0)
public string MarketSellItem([FromQuery] long uid = -1, [FromQuery] double price = 0, [FromBody] int[]? itemIndexs = null)
{
long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11));
long userid = uid;
itemIndexs ??= [];
if (price <= 0)
{
return "请输入一个大于 0 的售价。";
}
try
{
using SQLHelper? sql = Factory.OpenFactory.GetSQLHelper();
if (sql is null)
{
return busy;
}
PluginConfig pc = FunGameService.GetUserConfig(userid, out _);
if (pc.Count > 0)
@ -6890,73 +6901,75 @@ namespace Oshima.FunGame.WebAPI.Controllers
User user = FunGameService.GetUser(pc);
List<string> msgs = [];
using SQLHelper? sql = Factory.OpenFactory.GetSQLHelper();
List<Guid> itemTrading = [];
if (sql != null)
{
itemTrading = SQLService.GetUserItemGuids(sql, userid);
}
itemTrading = SQLService.GetUserItemGuids(sql, userid);
Dictionary<int, Item> dict = user.Inventory.Items.Select((item, index) => new { item, index }).ToDictionary(x => x.index + 1, x => x.item);
Item? item = null;
if (itemIndex > 0 && itemIndex <= user.Inventory.Items.Count)
FunGameService.GetMarketSemaphoreSlim();
List<Item> successItems = [];
foreach (int itemIndex in itemIndexs)
{
item = user.Inventory.Items.ToList()[itemIndex - 1];
if (price <= 0)
if (itemIndex > 0 && itemIndex <= user.Inventory.Items.Count)
{
msgs.Add($"请输入一个大于 0 的售价。");
Item item = user.Inventory.Items.ToList()[itemIndex - 1];
if (item.IsLock)
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品已上锁,无法出售。");
}
if (item.Character != null)
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品已被 {item.Character} 装备中,无法出售。");
}
if (itemTrading.Contains(item.Guid))
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品正在进行交易,无法出售,请检查交易报价。");
}
if (!item.IsSellable)
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品无法出售{(item.NextSellableTime != DateTime.MinValue ? $" {item.NextSellableTime.ToString(General.GeneralDateTimeFormatChinese)} " : "")}。");
}
if (msgs.Count == 0)
{
user.Inventory.Items.Remove(item);
successItems.Add(item);
msgs.Add($"物品 {itemIndex}. {item.Name}:上架市场成功!定价:{price:0.##} {General.GameplayEquilibriumConstant.InGameCurrency}。");
}
}
else
{
msgs.Add($"{itemIndex}. 没有找到与这个序号相对应的物品!");
}
}
if (successItems.Count > 0)
{
EntityModuleConfig<Market> emc = new("markets", "general");
emc.LoadConfig();
Market market = emc.Get("dokyo") ?? new("铎京集市");
foreach (Item successItem in successItems)
{
Item newItem = successItem.Copy(true);
market.AddItem(user, newItem, price, 1);
}
if (item.IsLock)
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品已上锁,无法出售。");
}
if (item.Character != null)
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品已被 {item.Character} 装备中,无法出售。");
}
if (itemTrading.Contains(item.Guid))
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品正在进行交易,无法出售,请检查交易报价。");
}
if (!item.IsSellable)
{
msgs.Add($"物品 {itemIndex}. {item.Name}:此物品无法出售{(item.NextSellableTime != DateTime.MinValue ? $" {item.NextSellableTime.ToString(General.GeneralDateTimeFormatChinese)} " : "")}。");
}
if (msgs.Count > 0) item = null;
emc.Add("dokyo", market);
emc.SaveConfig();
}
else
{
msgs.Add($"没有找到与这个序号相对应的物品!");
}
if (item != null && sql != null && user.Inventory.Items.Remove(item))
{
EntityModuleConfig<Item> emc = new("markets", user.Id.ToString());
emc.LoadConfig();
Item newItem = item.Copy(true);
emc.Add(item.Guid.ToString(), newItem);
sql.AddMarketItem(newItem.Guid, userid, price);
long marketId = sql.LastInsertId;
FunGameConstant.MarketItemIdAndItem[marketId] = newItem;
if (sql.Success)
{
emc.SaveConfig();
msgs.Add($"物品 {itemIndex}. {item.Name} 上架市场成功,售价:{price} {General.GameplayEquilibriumConstant.InGameCurrency},市场编号:{marketId}。");
}
}
if (msgs.Count == 0)
{
msgs.Add($"没有成功上架任何物品。请检查物品是否存在或是否满足上架条件。");
}
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return string.Join("\r\n", msgs);
}
else
@ -6967,6 +6980,262 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
catch (Exception e)
{
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.ReleaseUserSemaphoreSlim(userid);
Logger.LogError(e, "Error: {e}", e);
return busy;
}
}
[HttpPost("marketshowlist")]
public string MarketShowList([FromQuery] long userid = -1, [FromQuery] int page = 0)
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(userid, out _);
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
FunGameService.GetMarketSemaphoreSlim();
EntityModuleConfig<Market> emc = new("markets", "general");
emc.LoadConfig();
Market market = emc.Get("dokyo") ?? new("铎京集市");
string msg = FunGameService.GetMarketInfo(market, user, page, true);
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return msg;
}
else
{
FunGameService.ReleaseUserSemaphoreSlim(userid);
return noSaved;
}
}
catch (Exception e)
{
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.ReleaseUserSemaphoreSlim(userid);
Logger.LogError(e, "Error: {e}", e);
return busy;
}
}
[HttpPost("marketshowlistmysells")]
public string MarketShowListMySells([FromQuery] long userid = -1, [FromQuery] int page = 0)
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(userid, out _);
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
FunGameService.GetMarketSemaphoreSlim();
EntityModuleConfig<Market> emc = new("markets", "general");
emc.LoadConfig();
Market market = emc.Get("dokyo") ?? new("铎京集市");
string msg = "☆--- 我的市场商品 ---☆\r\n";
MarketItem[] marketItems = [.. market.MarketItems.Values.Where(m => m.User == userid)];
if (marketItems.Length > 0)
{
foreach (MarketItem marketItem in marketItems)
{
msg += FunGameService.GetMarketItemInfo(marketItem, true, userid) + "\r\n";
}
}
else msg += "你还没有上架过任何物品。";
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return msg.Trim();
}
else
{
FunGameService.ReleaseUserSemaphoreSlim(userid);
return noSaved;
}
}
catch (Exception e)
{
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.ReleaseUserSemaphoreSlim(userid);
Logger.LogError(e, "Error: {e}", e);
return busy;
}
}
[HttpPost("marketiteminfo")]
public string MarketItemInfo([FromQuery] long userid = -1, [FromQuery] long itemid = 0)
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(userid, out _);
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
FunGameService.GetMarketSemaphoreSlim();
EntityModuleConfig<Market> emc = new("markets", "general");
emc.LoadConfig();
Market market = emc.Get("dokyo") ?? new("铎京集市");
string msg = "";
if (market.MarketItems.TryGetValue(itemid, out MarketItem? item) && item != null)
{
msg = FunGameService.GetMarketItemInfo(item, false, userid);
}
if (msg != "")
{
msg += $"\r\n提示使用【市场查看+序号】查看商品详细信息,使用【市场购买+序号】购买商品。\r\n你的现有{General.GameplayEquilibriumConstant.InGameCurrency}{user.Inventory.Credits:0.##}";
}
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return msg;
}
else
{
FunGameService.ReleaseUserSemaphoreSlim(userid);
return noSaved;
}
}
catch (Exception e)
{
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.ReleaseUserSemaphoreSlim(userid);
Logger.LogError(e, "Error: {e}", e);
return busy;
}
}
[HttpPost("marketbuyitem")]
public string MarketBuyItem([FromQuery] long userid = -1, [FromQuery] long itemid = 0, [FromQuery] int count = 1)
{
if (count <= 0) count = 1;
try
{
PluginConfig pc = FunGameService.GetUserConfig(userid, out _);
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
FunGameService.GetMarketSemaphoreSlim();
EntityModuleConfig<Market> emc = new("markets", "general");
emc.LoadConfig();
Market market = emc.Get("dokyo") ?? new("铎京集市");
string msg = "";
if (market.MarketItems.TryGetValue(itemid, out MarketItem? item) && item != null)
{
msg = FunGameService.MarketBuyItem(market, item, pc, user, count, out bool result);
if (result)
{
long userid2 = item.User;
try
{
PluginConfig pc2 = FunGameService.GetUserConfig(userid2, out _);
if (pc2.Count > 0)
{
User user2 = FunGameService.GetUser(pc2);
double amount = item.Price * count;
double fee = amount * 0.15;
double net = amount - fee;
user2.Inventory.Credits += net;
FunGameService.AddNotice(userid2, $"【市场通知】你售出了 {count} 件{item.Name}!净收入 {net:0.##} {General.GameplayEquilibriumConstant.InGameCurrency};市场收取手续费 {fee:0.##} {General.GameplayEquilibriumConstant.InGameCurrency}。");
FunGameService.SetUserConfigButNotRelease(userid2, pc2, user2, false);
}
FunGameService.ReleaseUserSemaphoreSlim(userid2);
}
catch (Exception e)
{
FunGameService.ReleaseUserSemaphoreSlim(userid2);
Logger.LogError(e, "Error: {e}", e);
throw;
}
}
}
emc.Add("dokyo", market);
emc.SaveConfig();
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return msg;
}
else
{
FunGameService.ReleaseUserSemaphoreSlim(userid);
return noSaved;
}
}
catch (Exception e)
{
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.ReleaseUserSemaphoreSlim(userid);
Logger.LogError(e, "Error: {e}", e);
return busy;
}
}
[HttpPost("marketdelistitem")]
public string MarketDelistItem([FromQuery] long userid = -1, [FromQuery] long itemid = 0)
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(userid, out _);
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
FunGameService.GetMarketSemaphoreSlim();
EntityModuleConfig<Market> emc = new("markets", "general");
emc.LoadConfig();
Market market = emc.Get("dokyo") ?? new("铎京集市");
string msg = "";
if (market.MarketItems.TryGetValue(itemid, out MarketItem? item) && item != null && item.User == user.Id)
{
item.Status = MarketItemState.Delisted;
item.FinishTime = DateTime.Now;
for (int i = 0; i < item.Stock; i++)
{
FunGameService.AddItemToUserInventory(user, item.Item, copyLevel: true, useOriginalPrice: true, toExploreCache: false, toActivitiesCache: false);
}
msg = $"下架商品 {item.Name} 成功!{item.Stock} 个 {item.Name} 已回到你的库存。";
}
else
{
msg = $"没有找到指定的商品,或者你不是该商品的卖家,下架失败。";
}
emc.Add("dokyo", market);
emc.SaveConfig();
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return msg;
}
else
{
FunGameService.ReleaseUserSemaphoreSlim(userid);
return noSaved;
}
}
catch (Exception e)
{
FunGameService.ReleaseMarketSemaphoreSlim();
FunGameService.ReleaseUserSemaphoreSlim(userid);
Logger.LogError(e, "Error: {e}", e);
return busy;
@ -7563,6 +7832,130 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
}
[HttpPost("chat")]
public string Chat([FromQuery] long uid = -1, [FromQuery] long uid2 = -1, [FromQuery] string msgTo = "")
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(uid, out bool isTimeout);
if (isTimeout)
{
return busy;
}
if (msgTo == "")
{
return "发送了空信息。";
}
if (msgTo.Length > 30)
{
return "超过 30 字符。";
}
string msg = "";
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
if (uid == uid2)
{
msg = "不能对自己发私信。";
}
else if (FunGameConstant.UserIdAndUsername.TryGetValue(uid2, out User? user2) && user2 != null)
{
FunGameService.AddNotice(user2.Id, $"【私信】{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)} [ {user.Username} ] 说:{msgTo}");
msg = $"私信已经成功发送至 [ {user2.Username} ] 的离线信箱。";
}
else
{
msg = $"没有找到 UID 为 {uid2} 的玩家,无法发送私信。";
}
FunGameService.SetUserConfigButNotRelease(uid, pc, user);
return msg;
}
else
{
return noSaved;
}
}
catch (Exception e)
{
Logger.LogError(e, "Error: {e}", e);
return busy;
}
finally
{
FunGameService.ReleaseUserSemaphoreSlim(uid);
}
}
[HttpPost("chatname")]
public string Chat_Name([FromQuery] long uid = -1, [FromQuery] string name = "", [FromQuery] string msgTo = "")
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(uid, out bool isTimeout);
if (isTimeout)
{
return busy;
}
name = name.Trim();
if (name == "")
{
return "未输入目标玩家的昵称。";
}
if (msgTo == "")
{
return "发送了空信息。";
}
if (msgTo.Length > 30)
{
return "超过 30 字符。";
}
string msg = "";
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
if (user.Username == name)
{
msg = "不能对自己发私信。";
}
else if (FunGameConstant.UserIdAndUsername.Values.FirstOrDefault(u => u.Username == name) is User user2 && user2 != null)
{
FunGameService.AddNotice(user2.Id, $"【私信】{DateTime.Now.ToString(General.GeneralDateTimeFormatChinese)} [ {user.Username} ] 说:{msgTo}");
msg = $"私信已经成功发送至 [ {user2.Username} ] 的离线信箱。";
}
else
{
msg = $"没有找到昵称为 {name} 的玩家,无法发送私信。";
}
FunGameService.SetUserConfigButNotRelease(uid, pc, user);
return msg;
}
else
{
return noSaved;
}
}
catch (Exception e)
{
Logger.LogError(e, "Error: {e}", e);
return busy;
}
finally
{
FunGameService.ReleaseUserSemaphoreSlim(uid);
}
}
[HttpPost("template")]
public string Template([FromQuery] long uid = -1)
{

View File

@ -3064,6 +3064,162 @@ namespace Oshima.FunGame.WebAPI.Services
return result;
}
if (e.Detail.StartsWith("市场出售"))
{
string detail = e.Detail.Replace("市场出售", "").Trim();
string[] strings = detail.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
if (strings.Length < 2 || !double.TryParse(strings[^1], out double price))
{
await SendAsync(e, "市场出售", "格式不正确,请使用:市场出售 <{物品序号...}> <价格>。多个物品序号使用空格隔开。");
return result;
}
List<int> ids = [];
for (int i = 0; i < strings.Length; i++)
{
if (i != strings.Length - 1 && int.TryParse(strings[i], out int id))
{
ids.Add(id);
}
}
string msg = Controller.MarketSellItem(uid, price, [.. ids]);
if (msg != "")
{
await SendAsync(e, "市场出售", msg);
}
return result;
}
if (e.Detail.StartsWith("市场购买"))
{
string detail = e.Detail.Replace("市场购买", "").Trim();
string[] strings = detail.Split(" ", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
int id = -1;
if (strings.Length > 0 && int.TryParse(strings[0].Trim(), out id))
{
int count = 1;
if (strings.Length > 1) _ = int.TryParse(strings[1].Trim(), out count);
if (id != -1)
{
string msg = Controller.MarketBuyItem(uid, id, count);
if (msg != "")
{
await SendAsync(e, "市场购买", msg);
}
}
}
return result;
}
if (e.Detail.StartsWith("市场查看"))
{
string detail = e.Detail.Replace("市场查看", "").Trim();
string msg = "";
if (int.TryParse(detail, out int id))
{
msg = Controller.MarketItemInfo(uid, id);
if (msg.Trim() != "")
{
await SendAsync(e, "市场查看", msg);
}
}
return result;
}
if (e.Detail.StartsWith("市场下架"))
{
string detail = e.Detail.Replace("市场下架", "").Trim();
string msg = "";
if (int.TryParse(detail, out int id))
{
msg = Controller.MarketDelistItem(uid, id);
if (msg.Trim() != "")
{
await SendAsync(e, "市场下架", msg);
}
}
return result;
}
if (e.Detail.StartsWith("我的市场"))
{
string detail = e.Detail.Replace("我的市场", "").Trim();
string msg = "";
if (int.TryParse(detail, out int page))
{
msg = Controller.MarketShowListMySells(uid, page);
}
else
{
msg = Controller.MarketShowListMySells(uid, 1);
}
if (msg.Trim() != "")
{
await SendAsync(e, "我的市场", msg);
}
return result;
}
if (e.Detail.StartsWith("市场"))
{
string detail = e.Detail.Replace("市场", "").Trim();
string msg = "";
if (int.TryParse(detail, out int page))
{
msg = Controller.MarketShowList(uid, page);
}
else
{
msg = Controller.MarketShowList(uid, 1);
}
if (msg.Trim() != "")
{
await SendAsync(e, "市场", msg);
}
return result;
}
if (e.Detail.StartsWith("私信"))
{
string detail = e.Detail.Replace("私信", "").Trim();
string[] strings = detail.Split(" ", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
long id = -1;
string name = "";
bool useId = false;
if (strings.Length > 0)
{
if (long.TryParse(strings[0].Trim(), out id))
{
useId = true;
}
else
{
name = strings[0].Trim();
}
}
else
{
await SendAsync(e, "私信", "你输入的格式不正确,正确格式:私信 <对方UID/昵称> <内容>");
return result;
}
string content = "";
if (strings.Length > 1) content = string.Join(" ", strings[1..]);
string msg = "";
if (useId)
{
msg = Controller.Chat(uid, id, content);
}
else
{
msg = Controller.Chat_Name(uid, name, content);
}
if (msg != "")
{
await SendAsync(e, "私信", msg);
}
return result;
}
if (uid == GeneralSettings.Master && e.Detail.StartsWith("重载FunGame", StringComparison.CurrentCultureIgnoreCase))
{
string msg = Controller.Relaod(uid);