Files
SVSimServer/SVSim.BattleEngine/Engine/Wizard/QRCodeUtility.cs
gamer147 824309ec44 feat(battle-engine): close the AI-simulation subsystem (verbatim)
Copied the 89 uncopied AI*SimulationUtility/extension files defining the
AIVirtualCard/AIVirtualField extension methods; the compile loop then auto-closed
the revealed type deps (~3049 files total, drift-clean). 10.0k -> 62 errors.
2026-06-05 20:30:59 -04:00

312 lines
8.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Cute;
using UnityEngine;
using ZXing;
using ZXing.QrCode;
using ZXing.QrCode.Internal;
namespace Wizard;
public class QRCodeUtility
{
public struct DeckDataFromQRCode
{
public CardBasePrm.ClanType ClanId;
public CardBasePrm.ClanType SubClanId;
public int[] CardIds;
public bool IsSubClassSet;
public Format Format;
public MyRotationInfo MyRotationInfo { get; }
public DeckDataFromQRCode(Format format, CardBasePrm.ClanType clanId, CardBasePrm.ClanType subClanId, int[] cardIds, MyRotationInfo myRotationInfo)
{
ClanId = clanId;
CardIds = cardIds;
SubClanId = subClanId;
IsSubClassSet = CardBasePrm.ClanTypeIsUseable(subClanId);
Format = format;
MyRotationInfo = myRotationInfo;
}
}
public const int SIZE_SMALL = 207;
public const int SIZE_BIG = 508;
public const int BIGQRCODE_TEXTURE_WIDGIT_SIZE = 400;
private const string NORMAL_URL_TAIL = "/deck/";
private const string CROSSOVER_URL_TAIL = "/deck_co/";
private const string MY_ROTATION_URL_TAIL = "/deck_my/";
public static DeckDataFromQRCode deckDataFromQRCode;
public static Texture2D CreateQrCodeTexture(int width, int height, string content)
{
BarcodeWriter barcodeWriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
ErrorCorrection = ErrorCorrectionLevel.L,
Width = width,
Height = height
}
};
Texture2D texture2D = new Texture2D(width, height, TextureFormat.ARGB32, mipChain: false);
Color32[] pixels = barcodeWriter.Write(content);
texture2D.SetPixels32(pixels);
texture2D.Apply();
return texture2D;
}
private static string GetAppendUrlFromDeckType(IFormatBehavior formatBehavior, Format format)
{
if (formatBehavior.UseSubClass)
{
return "/deck_co/";
}
if (format == Format.MyRotation)
{
return "/deck_my/";
}
return "/deck/";
}
public static string GenerateQRCodeText(List<int> deckList, CardBasePrm.ClanType? clanType, ClassSet classSet, IFormatBehavior formatBehavior, Format format, MyRotationInfo myRotationInfo)
{
bool useSubClass = formatBehavior.UseSubClass;
StringBuilder tempStringBuilder = UIUtil.GetTempStringBuilder();
tempStringBuilder.Append("https://").Append("shadowverse-portal.com/api/v1/game_api/".Split('/')[0]);
tempStringBuilder.Append(GetAppendUrlFromDeckType(formatBehavior, format));
tempStringBuilder.Append(((int)formatBehavior.DeckCodeType).ToString()).Append(".");
string value;
if (classSet == null)
{
value = ((int)clanType.Value).ToString();
}
else
{
int mainClass = (int)classSet.MainClass;
value = mainClass.ToString();
}
tempStringBuilder.Append(value).Append(".");
if (useSubClass)
{
int mainClass = (int)classSet.SubClass;
tempStringBuilder.Append(mainClass.ToString()).Append(".");
}
if (format == Format.MyRotation)
{
tempStringBuilder.Append(myRotationInfo.Id).Append(".");
}
CardMaster instance = CardMaster.GetInstance(formatBehavior.CardMasterId);
for (int i = 0; i < deckList.Count; i++)
{
int normalCardId = instance.GetCardParameterFromId(deckList[i]).NormalCardId;
tempStringBuilder.Append(instance.GetCardParameterFromId(normalCardId).CardHashId);
if (i != deckList.Count - 1)
{
tempStringBuilder.Append(".");
}
}
tempStringBuilder.Append("?lang=").Append(GetLanguageCode());
return tempStringBuilder.ToString();
}
public static string GetLanguageCode()
{
string result = "";
switch (CustomPreference.GetTextLanguage())
{
case "Jpn":
result = "ja";
break;
case "Ger":
result = "de";
break;
case "Fre":
result = "fr";
break;
case "Ita":
result = "it";
break;
case "Cht":
result = "zh-tw";
break;
case "Kor":
result = "ko";
break;
case "Spa":
result = "es";
break;
case "Chs":
case "Eng":
result = "en";
break;
}
return result;
}
public static string DecodeContentText(WebCamTexture webCamTexture)
{
if (webCamTexture == null)
{
return string.Empty;
}
return DecodeContentText(webCamTexture.GetPixels32(), webCamTexture.width, webCamTexture.height, isFromCamera: true);
}
public static string DecodeContentText(Color32[] pixels, int width, int height, bool isFromCamera)
{
BarcodeReader barcodeReader = new BarcodeReader
{
AutoRotate = !isFromCamera
};
Result result;
try
{
result = barcodeReader.Decode(pixels, width, height);
}
catch (Exception ex)
{
LocalLog.AccumulateTraceLog("#699501 :" + ex);
result = null;
}
if (result == null)
{
return string.Empty;
}
return result.Text;
}
public static bool SetDeckFromQRCodeText(string qrCodeText, CardMaster.CardMasterId cardMasterId)
{
bool result = false;
string text = "https://" + "shadowverse-portal.com/api/v1/game_api/".Split('/')[0] + "/deck/";
string text2 = "https://" + "shadowverse-portal.com/api/v1/game_api/".Split('/')[0] + "/deck_co/";
string text3 = "https://" + "shadowverse-portal.com/api/v1/game_api/".Split('/')[0] + "/deck_my/";
bool flag = qrCodeText.StartsWith(text);
bool flag2 = qrCodeText.StartsWith(text2);
bool flag3 = qrCodeText.StartsWith(text3);
if (!flag && !flag2 && !flag3)
{
return result;
}
if (!Regex.IsMatch(qrCodeText, "\\?lang=(\\w+$|zh-tw)"))
{
return result;
}
if (flag)
{
qrCodeText = Regex.Replace(qrCodeText, text, "");
}
else if (flag2)
{
qrCodeText = Regex.Replace(qrCodeText, text2, "");
}
else if (flag3)
{
qrCodeText = Regex.Replace(qrCodeText, text3, "");
}
qrCodeText = Regex.Replace(qrCodeText, "\\?lang=(\\w+$|zh-tw)", "");
string[] array = qrCodeText.Split('.');
CardBasePrm.ClanType clanType = CardBasePrm.ClanType.NONE;
CardBasePrm.ClanType subClanId = CardBasePrm.ClanType.NONE;
MyRotationInfo myRotationInfo = null;
Format format = Format.Max;
try
{
format = GetFormatFromDeckCodeType((GenerateDeckCodeTask.SubmitDeckType)int.Parse(array[0]));
clanType = (CardBasePrm.ClanType)int.Parse(array[1]);
if (flag2)
{
subClanId = (CardBasePrm.ClanType)int.Parse(array[2]);
}
if (flag3)
{
myRotationInfo = Data.MyRotationAllInfo.Get(array[2]);
}
if (clanType < CardBasePrm.ClanType.MIN || clanType > CardBasePrm.ClanType.MAX)
{
return result;
}
}
catch (Exception ex)
{
if (array.Length >= 3)
{
Debug.LogError($"フォーマット: {array[0].ToString()}、クラス: {array[1].ToString()}、サブクラス: {array[2].ToString()}のいずれかの情報取得に失敗。{ex.ToString()}");
}
else
{
Debug.LogError($"cardHashIdListの長さが{array.Length.ToString()}です。{ex.ToString()}");
}
return result;
}
List<int> list = new List<int>();
int num = 2;
if (flag2 || flag3)
{
num = 3;
}
for (int i = num; i < array.Length; i++)
{
try
{
int cardId = CardMaster.GetInstance(cardMasterId).GetCardParamFromCardHashId(array[i]).CardId;
if (!CardMaster.GetInstance(cardMasterId).CardExists(cardId))
{
return result;
}
list.Add(cardId);
}
catch (Exception ex2)
{
Debug.LogError($"カードリストの{i.ToString()}番目要素の取得に失敗。{ex2.ToString()}");
return result;
}
}
deckDataFromQRCode = new DeckDataFromQRCode(format, clanType, subClanId, list.ToArray(), myRotationInfo);
return true;
}
public static Format GetFormatFromDeckCodeType(GenerateDeckCodeTask.SubmitDeckType type)
{
return type switch
{
GenerateDeckCodeTask.SubmitDeckType.NORMAL => Format.Unlimited,
GenerateDeckCodeTask.SubmitDeckType.Crossover => Format.Crossover,
_ => Format.Max,
};
}
public static bool IsShowQRCode(UICardList deckViewer, IFormatBehavior formatBehavior, Format format)
{
bool flag = deckViewer.getCardNum() == 40;
if (formatBehavior.UseSubClass)
{
flag &= deckViewer.CanShowQRCodeUseSubclass();
}
if (format == Format.MyRotation && !deckViewer.IsDeckNull())
{
flag &= deckViewer.IsAllCardCorrectMyRotation();
}
if (format == Format.Avatar)
{
flag = false;
}
return flag;
}
}