mirror of
https://github.com/oshima-studios/OshimaGameModule.git
synced 2026-01-21 23:18:26 +00:00
添加了市场和私信功能
This commit is contained in:
parent
4b0c7bb942
commit
e743997f65
@ -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];
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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, 实际吸血);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -155,6 +155,11 @@ namespace Oshima.FunGame.OshimaServers
|
||||
FunGameService.RefreshStoreData();
|
||||
Controller.WriteLine("刷新商店");
|
||||
});
|
||||
Task.Run(() =>
|
||||
{
|
||||
FunGameService.RefreshMarketData();
|
||||
Controller.WriteLine("刷新市场");
|
||||
});
|
||||
// 刷新活动缓存
|
||||
FunGameService.GetEventCenter();
|
||||
FunGameService.RefreshNotice();
|
||||
|
||||
@ -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%作为社团基金"},
|
||||
{"社团市场下架 <市场物品序号>", "下架指定物品"},
|
||||
{"社团市场查看 <市场物品序号>", "查看指定物品"},
|
||||
{"社团市场购买 <市场物品序号>", "购买指定物品"},
|
||||
{"社团市场清空", "管理员可下架所有物品"},
|
||||
};
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user