Commit 42452a4b authored by SherryChaos's avatar SherryChaos

banlist support genesys credit

parent 72a347df
using System;
using System.Collections.Generic;
using System.Linq;
namespace MDPro3.Duel.YGOSharp
{
......@@ -10,9 +11,17 @@ namespace MDPro3.Duel.YGOSharp
public IList<int> SemiLimitedIds { get; private set; }
public IList<int> UnlimitedIds { get; private set; }
public bool WhitelistOnly { get; private set; }
public uint Hash { get; private set; }
private uint _hash = 0x7dfcee6a;
public uint Hash
{
get => _hash;
private set => _hash = value;
}
public string Name = "";
public Dictionary<string, uint> CreditLimits { get; private set; }
public Dictionary<int, Dictionary<string, int>> CardCredits { get; private set; }
public Banlist()
{
BannedIds = new List<int>();
......@@ -20,7 +29,27 @@ namespace MDPro3.Duel.YGOSharp
SemiLimitedIds = new List<int>();
UnlimitedIds = new List<int>();
WhitelistOnly = false;
Hash = 0x7dfcee6a;
}
public void AddCreditLimit(string key, uint limit)
{
CreditLimits ??= new();
if (CreditLimits.ContainsKey(key)) return;
CreditLimits[key] = limit;
uint keyHash = CreditHash(key);
UpdateHash(ref _hash, keyHash, limit, 0x43524544u);
}
public void AddCardCredit(int cardId, string key, int value)
{
CardCredits ??= new();
if (!CardCredits.ContainsKey(cardId))
CardCredits[cardId] = new Dictionary<string, int>();
CardCredits[cardId][key] = value;
uint keyHash = CreditHash(key);
UpdateHash(ref _hash, (uint)cardId, keyHash, value);
}
public int GetQuantity(int cardId)
......@@ -60,6 +89,26 @@ namespace MDPro3.Duel.YGOSharp
}
public int GetCredit(int cardId)
{
if(!IsCreditBanlist())
return 0;
var first = CreditLimits.FirstOrDefault().Key;
return GetCredit(cardId, first);
}
public int GetCredit(int cardId, string creditKey)
{
if (!IsCreditBanlist())
return 0;
if (CardCredits.ContainsKey(cardId) && CardCredits[cardId].ContainsKey(creditKey))
return CardCredits[cardId][creditKey];
return 0;
}
public void EnableWhitelistMode()
{
if (WhitelistOnly)
......@@ -90,5 +139,41 @@ namespace MDPro3.Duel.YGOSharp
uint code = (uint)cardId;
Hash = Hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + quantity)) | (code >> (5 - quantity)));
}
private bool IsCreditBanlist()
{
if(CreditLimits == null || CreditLimits.Count == 0)
return false;
if(CardCredits == null || CardCredits.Count == 0)
return false;
return true;
}
private static uint CreditHash(string s)
{
uint h = 2166136261u;
foreach (char c in s)
{
byte b = (byte)c; // 假设字符串为 UTF-8 编码的字节,这里简单取低 8 位
h ^= b;
h *= 16777619u;
}
return h;
}
private static void UpdateHash(ref uint h, uint a, uint b, int c)
{
UpdateHash(ref h, a, b, unchecked((uint)c));
}
private static void UpdateHash(ref uint h, uint a, uint b, uint c)
{
h = h ^ ((a << 18) | (a >> 14)) ^
((b << 9) | (b >> 23)) ^
((c << 27) | (c >> 5));
}
}
}
......@@ -74,33 +74,82 @@ namespace MDPro3.Duel.YGOSharp
AppendLflistText(builder, line);
try
{
if (line == null)
if (string.IsNullOrWhiteSpace(line))
continue;
if (line.StartsWith("#"))
line = line.Trim(); // 去掉首尾空白
if (line[0] == '#') // 注释行
continue;
if (line.StartsWith("!"))
if (line[0] == '!') // 新列表开始
{
current = new Banlist();
current.Name = line.Substring(1, line.Length - 1);
current = new Banlist
{
Name = line[1..].Trim()
};
Banlists.Add(current);
continue;
}
if (line.StartsWith("$"))
if (current == null) // 尚未有激活的列表
continue;
if (line[0] == '$') // $ 开头的行
{
if (current != null && line.Equals("$whitelist", StringComparison.OrdinalIgnoreCase))
string rest = line[1..].Trim();
// 白名单模式指令:$whitelist
if (rest.StartsWith("whitelist", StringComparison.OrdinalIgnoreCase))
{
current.EnableWhitelistMode();
continue;
}
// 否则解析为全局信用额度:$key value
string[] parts = rest.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length >= 2)
{
string key = parts[0];
if (uint.TryParse(parts[1], out uint limit))
current.AddCreditLimit(key, limit);
}
continue;
}
if (!line.Contains(" "))
continue;
if (current == null)
// 普通行:可能是传统限制行,也可能是卡牌信用消耗行
string[] data = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (data.Length < 2)
continue;
string[] data = line.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries);
int id = int.Parse(data[0]);
int count = int.Parse(data[1]);
current.Add(id, count);
// 检查是否包含 $(信用消耗行)
bool isCreditLine = false;
int dollarIndex = -1;
for (int i = 0; i < data.Length; i++)
{
if (data[i].StartsWith("$"))
{
isCreditLine = true;
dollarIndex = i;
break;
}
}
if (isCreditLine)
{
// 格式:卡号 $信用类型 消耗值
if (dollarIndex + 1 >= data.Length)
continue;
if (int.TryParse(data[0], out int cardId) && int.TryParse(data[dollarIndex + 1], out int value))
{
string key = data[dollarIndex][1..]; // 去掉 $
current.AddCardCredit(cardId, key, value);
}
}
else
{
// 传统格式:卡号 数量
if (int.TryParse(data[0], out int id) && int.TryParse(data[1], out int count))
current.Add(id, count);
}
}
catch (System.Exception e)
catch (Exception e)
{
UnityEngine.Debug.Log(line);
UnityEngine.Debug.Log(e);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment