Commit 568f79c7 authored by SherryChaos's avatar SherryChaos

copy and share deck function

parent 344bae0e
using MDPro3.YGOSharp;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
namespace MDPro3
{
public class DeckShareURL
{
static string URL_SCHEME_HTTP = "http";
static string URL_HOST_DECK = "deck.ourygo.top";
static string ARG_DECK = "deck";
static string QUERY_VERSION = "v";
static string QUERY_YGO_TYPE = "ygotype";
static string QUERY_DECK = "d";
public static Uri DeckToUri(List<int>main, List<int>extra, List<int>side, Dictionary<string, string> parameters = null)
{
var builder = new UriBuilder(URL_SCHEME_HTTP, URL_HOST_DECK);
if (parameters != null)
foreach (var entry in parameters)
builder.Query = builder.Query.Length > 1 ? builder.Query.Substring(1) + $"&{entry.Key}={Uri.EscapeDataString(entry.Value)}" : $"{entry.Key}={entry.Value}";
builder.Query += $"{QUERY_YGO_TYPE}={ARG_DECK}";
builder.Query += $"&{QUERY_VERSION}=1";
int mNum = GetTypeNum(main);
int eNum = GetTypeNum(extra);
int sNum = GetTypeNum(side);
string deck = ToBit(main, extra, side, mNum, eNum, sNum);
string m = Convert.ToString(mNum, 2);
string e = Convert.ToString(eNum, 2);
string s = Convert.ToString(sNum, 2);
m = ToNumLength(m, 8);
e = ToNumLength(e, 4);
s = ToNumLength(s, 4);
deck = m + e + s + deck;
var bytes = ToBytes(deck);
string message = Convert.ToBase64String(bytes).Replace('+', '-').Replace('/', '_').TrimEnd('=');
builder.Query += $"&{QUERY_DECK}={Uri.EscapeDataString(message)}";
return builder.Uri;
}
static string ToBit(List<int> main, List<int> extra, List<int> side, int mNum, int eNum, int sNum)
{
var mains = ToByte(main, mNum);
var extras = ToByte(extra, eNum);
var sides = ToByte(side, sNum);
return mains + extras + sides;
}
static string ToByte(List<int> ids, int typeNum)
{
var bytes = string.Empty;
if(ids == null)
return bytes;
for(int i = 0; i < ids.Count; i++)
{
int id = ids[i];
if(id > 0)
{
string idB = ToB(id);
if (i != ids.Count - 1)
{
int id1 = ids[i + 1];
int tNum = 1;
if (id1 == id)
{
tNum++;
if (i != ids.Count - 2)
{
id1 = ids[i + 2];
if (id1 == id)
{
tNum++;
i++;
}
}
i++;
}
tNum = Math.Min(3, tNum);
switch (tNum)
{
case 1:
idB = "01" + idB;
break;
case 2:
idB = "10" + idB;
break;
case 3:
idB = "11" + idB;
break;
}
}
else
idB = "01" + idB;
bytes += idB;
}
}
return bytes;
}
static string ToB(int id)
{
return ToNumLength(Convert.ToString(id, 2), 27);
}
static string ToNumLength(string message, int num)
{
while (message.Length < num)
message = "0" + message;
return message;
}
static byte[] ToBytes(string bits)
{
int y = bits.Length % 8;
if(y != 0)
bits = ToNumLengthLast(bits, bits.Length + 8 - y);
var bytes = new byte[bits.Length / 8];
for(int i = 0; i < bits.Length / 8; i++)
bytes[i] = (byte)(Convert.ToInt32(bits.Substring(i * 8, 8), 2));
return bytes;
}
static string ToNumLengthLast(string message, int num)
{
while (message.Length < num)
message += "0";
return message;
}
static int GetTypeNum(List<int> ids)
{
int num = 0;
for(int i = 0;i < ids.Count;i++)
{
int id = ids[i];
if(id > 0)
{
num++;
if(i != ids.Count - 1)
{
int id1 = ids[i + 1];
if(id1 == id)
{
if(i != ids.Count - 2)
{
id1 = ids[i + 2];
if (id1 == id)
i++;
}
i++;
}
}
}
}
return num;
}
public static Deck UriToDeck(Uri uri)
{
if (!uri.Host.Equals(URL_HOST_DECK) || !uri.Query.Contains($"{QUERY_DECK}="))
{
throw new ArgumentException("Invalid URI format or host");
}
var queryParameters = ParseQueryParameters(uri.Query);
string encodedDeck = GetValueFromQuery(queryParameters, QUERY_DECK, string.Empty);
encodedDeck = encodedDeck.Replace('-', '+').Replace('_', '/');
byte[] deckBytes = Convert.FromBase64String(encodedDeck.PadRight(encodedDeck.Length + (4 - encodedDeck.Length % 4) % 4, '='));
string deckBits = "";
for (int i = 0; i < deckBytes.Length; i++)
{
deckBits += Convert.ToString(deckBytes[i], 2).PadLeft(8, '0');
}
int totalMainLength = 29 * GetBinaryIntValue(deckBits.Substring(0, 8));
int totalExtraLength = 29 * GetBinaryIntValue(deckBits.Substring(8, 4));
int totalSideLength = 29 * GetBinaryIntValue(deckBits.Substring(12, 4));
int startIndex = 16;
var main = DecodeCardList(deckBits.Substring(startIndex, totalMainLength));
startIndex += totalMainLength;
var extra = DecodeCardList(deckBits.Substring(startIndex, totalExtraLength));
startIndex += totalExtraLength;
var side = DecodeCardList(deckBits.Substring(startIndex, totalSideLength));
return new Deck(main, extra, side);
}
private static Dictionary<string, string> ParseQueryParameters(string query)
{
var result = new Dictionary<string, string>();
var parts = query.Split('&');
foreach (var part in parts)
{
var keyValue = part.Split('=');
if (keyValue.Length == 2)
{
result[keyValue[0]] = Uri.UnescapeDataString(keyValue[1]);
}
}
return result;
}
private static int GetBinaryIntValue(string binaryString)
{
return Convert.ToInt32(binaryString, 2);
}
private static List<int> DecodeCardList(string bitString)
{
List<int> cardIds = new List<int>();
int currentIndex = 0;
while (currentIndex < bitString.Length)
{
int count;
int currentId = GetCardId(bitString, ref currentIndex, out count);
for (int i = 0; i < count; i++)
{
cardIds.Add(currentId);
}
}
return cardIds;
}
private static int GetCardId(string bitString, ref int currentIndex, out int count)
{
count = 1;
if (bitString.Length - currentIndex >= 2)
{
switch (bitString.Substring(currentIndex, 2))
{
case "01":
count = 1;
break;
case "10":
count = 2;
break;
case "11":
count = 3;
break;
}
currentIndex += 2;
}
int id = Convert.ToInt32(bitString.Substring(currentIndex, 27), 2);
currentIndex += 27;
return id;
}
private static string GetValueFromQuery(Dictionary<string, string> queryParameters, string key, string defaultValue = "")
{
string value;
if (queryParameters.TryGetValue(key, out value))
{
return value;
}
return defaultValue;
}
}
}
fileFormatVersion: 2 fileFormatVersion: 2
guid: df4cc14ead2a8bb4c8a2d593d8de19e8 guid: fce526caba5d4154d8c3a55c80e3731e
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
......
...@@ -142,6 +142,26 @@ namespace MDPro3.YGOSharp ...@@ -142,6 +142,26 @@ namespace MDPro3.YGOSharp
Mate.Add(1000001); Mate.Add(1000001);
} }
public Deck(List<int> main, List<int> extra, List<int> side)
{
Main = main;
Extra = extra;
Side = side;
Pickup = new List<int>();
Protector = new List<int>();
Case = new List<int>();
Field = new List<int>();
Grave = new List<int>();
Stand = new List<int>();
Mate = new List<int>();
Protector.Add(1070001);
Case.Add(1080001);
Field.Add(1090001);
Grave.Add(1100001);
Stand.Add(1110001);
Mate.Add(1000001);
}
public int Check(Banlist ban, bool ocg, bool tcg) public int Check(Banlist ban, bool ocg, bool tcg)
{ {
if (Main.Count < 40 || if (Main.Count < 40 ||
......
...@@ -15,6 +15,7 @@ using MDPro3.YGOSharp.OCGWrapper.Enums; ...@@ -15,6 +15,7 @@ using MDPro3.YGOSharp.OCGWrapper.Enums;
using MDPro3.UI; using MDPro3.UI;
using Toggle = MDPro3.UI.Toggle; using Toggle = MDPro3.UI.Toggle;
using UnityEngine.Android; using UnityEngine.Android;
using static YgomSystem.Utility.AssetLinker;
namespace MDPro3 namespace MDPro3
{ {
...@@ -1025,11 +1026,14 @@ namespace MDPro3 ...@@ -1025,11 +1026,14 @@ namespace MDPro3
return; return;
} }
#if UNITY_ANDROID && !UNITY_EDITOR //#if UNITY_ANDROID && !UNITY_EDITOR
new NativeShare().SetText(File.ReadAllText("Deck/" + deckName + ".ydk")).Share(); // new NativeShare().SetText(File.ReadAllText("Deck/" + deckName + ".ydk")).Share();
#else //#else
Tools.TryOpenInFileExplorer(Path.GetFullPath("Deck/" + deckName + ".ydk")); // Tools.TryOpenInFileExplorer(Path.GetFullPath("Deck/" + deckName + ".ydk"));
#endif //#endif
var url = DeckShareURL.DeckToUri(deck.Main, deck.Extra, deck.Side).ToString();
GUIUtility.systemCopyBuffer = url;
Application.OpenURL(url);
} }
public void OnSave() public void OnSave()
{ {
...@@ -1085,6 +1089,24 @@ namespace MDPro3 ...@@ -1085,6 +1089,24 @@ namespace MDPro3
} }
void FileSave() void FileSave()
{
try
{
SaveDeckFile(deck, input.text);
if (input.text != deckName)
File.Delete("Deck/" + deckName + ".ydk");
Config.Set("DeckInUse", input.text);
deckName = input.text;
MessageManager.Cast(InterString.Get("卡组「[?]」已保存。", input.text));
dirty = false;
}
catch
{
MessageManager.Cast(InterString.Get("保存失败!"));
}
}
public void SaveDeckFile(Deck deck, string deckName)
{ {
var value = "#created by mdpro3\r\n#main\r\n"; var value = "#created by mdpro3\r\n#main\r\n";
for (var i = 0; i < deck.Main.Count; i++) value += deck.Main[i] + "\r\n"; for (var i = 0; i < deck.Main.Count; i++) value += deck.Main[i] + "\r\n";
...@@ -1107,16 +1129,11 @@ namespace MDPro3 ...@@ -1107,16 +1129,11 @@ namespace MDPro3
value += "#mate\r\n"; value += "#mate\r\n";
for (var i = 0; i < deck.Mate.Count; i++) value += deck.Mate[i] + "#\r\n"; for (var i = 0; i < deck.Mate.Count; i++) value += deck.Mate[i] + "#\r\n";
var outName = input.text;
try try
{ {
File.WriteAllText("Deck/" + outName + ".ydk", value, Encoding.UTF8); File.WriteAllText("Deck/" + deckName + ".ydk", value, Encoding.UTF8);
if (outName != deckName) Config.Set("DeckInUse", deckName);
File.Delete("Deck/" + deckName + ".ydk"); MessageManager.Cast(InterString.Get("卡组「[?]」已保存。", deckName));
Config.Set("DeckInUse", outName);
deckName = outName;
MessageManager.Cast(InterString.Get("卡组「[?]」已保存。", outName));
dirty = false;
} }
catch catch
{ {
......
...@@ -229,11 +229,18 @@ namespace MDPro3 ...@@ -229,11 +229,18 @@ namespace MDPro3
string clipBoard = GUIUtility.systemCopyBuffer; string clipBoard = GUIUtility.systemCopyBuffer;
if (clipBoard.Contains("#main")) if (clipBoard.Contains("#main"))
File.WriteAllText(path!, clipBoard, Encoding.UTF8); File.WriteAllText(path!, clipBoard, Encoding.UTF8);
else if (clipBoard.Contains("ygotype=deck&v=1&d="))
{
var uri = new Uri(clipBoard);
var deck = DeckShareURL.UriToDeck(uri);
Program.I().editDeck.SaveDeckFile(deck, deckName);
}
Config.Set("DeckInUse", deckName); Config.Set("DeckInUse", deckName);
Program.I().selectDeck.RefreshList(); Program.I().selectDeck.RefreshList();
} }
catch catch(Exception e)
{ {
Debug.LogException(e);
MessageManager.Cast(InterString.Get("创建卡组失败!请检查文件夹权限。")); MessageManager.Cast(InterString.Get("创建卡组失败!请检查文件夹权限。"));
} }
} }
......
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine;
namespace MDPro3.Net
{
public class Server
{
public static void Main()
{
var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ip = IPAddress.Parse("192.168.3.2");
int port = 7911;
serverSocket.Bind(new IPEndPoint(ip, port));
serverSocket.Listen(100);
Debug.Log("服务器启动了");
var clientSocket = serverSocket.Accept();
Debug.Log("服务器接受了一个客户端的连接,客户端的详细数据为:" + clientSocket.RemoteEndPoint.ToString());
byte[] msgArr = new byte[1024];
clientSocket.Receive(msgArr);
string msg = Encoding.UTF8.GetString(msgArr);
Debug.Log("从客户端接收到的数据为:" + msg);
}
public static string GetLocalIPv4Address()
{
var addresses = Dns.GetHostAddresses(Dns.GetHostName());
foreach (var address in addresses)
if (address.AddressFamily == AddressFamily.InterNetwork)
return address.ToString();
throw new Exception("No valid IPv4 address was found.");
}
}
public class Client
{
public static void Main()
{
var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var ip = IPAddress.Parse("192.168.3.2");
int port = 7911;
clientSocket.Connect(new IPEndPoint(ip, port));
Debug.Log("连接到了服务器");
var connect = "666666";
byte[] msg = Encoding.UTF8.GetBytes(connect);
clientSocket.Send(msg);
}
}
}
\ No newline at end of file
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