diff --git a/OCGCore/ygopro-core b/OCGCore/ygopro-core index 61c73d6..4af3696 160000 --- a/OCGCore/ygopro-core +++ b/OCGCore/ygopro-core @@ -1 +1 @@ -Subproject commit 61c73d663c841486479d4ad31b81a98aaf1bfe41 +Subproject commit 4af3696866591bb06e335f9feee1913b065bf9a7 diff --git a/README.md b/README.md index 7d36fe7..7057e21 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ A C# implementation of an ygopro duel server, using the ocgcore library. * Put _cards.cdb_, _lflist.conf_, _ocgcore.dll_ and the _script_ directory next to the compiled YGOSharp.exe. -* Run the executable with or without parameters. The default configuration will host a single duel on the port 7911. +* Run the executable with or without parameters. The default configuration will host an unranked single duel on the port 7911. * Enjoy. @@ -20,7 +20,7 @@ A C# implementation of an ygopro duel server, using the ocgcore library. * `ConfigFile` (default: none) -* `ClientVersion` (default: `0x1339`) +* `ClientVersion` (default: `0x1337`) * `Port` (default: `7911`) @@ -30,8 +30,10 @@ A C# implementation of an ygopro duel server, using the ocgcore library. * `RootPath` (default: `.`) + * `ScriptDirectory` (default: `script`) + * `DatabaseFile` (default: `cards.cdb`) ### Game diff --git a/YGOSharp.OCGWrapper/Api.cs b/YGOSharp.OCGWrapper/Api.cs index 16c7ec5..7061aac 100644 --- a/YGOSharp.OCGWrapper/Api.cs +++ b/YGOSharp.OCGWrapper/Api.cs @@ -67,7 +67,8 @@ public static unsafe class Api #region Private Variables private static string _rootPath; - private static string _scriptDirectory; + private static string _primaryScriptDirectory; + private static string _alternativeScriptDirectory; private static IntPtr _buffer; private static ScriptReader _scriptCallback; @@ -78,10 +79,11 @@ public static unsafe class Api #region Public Functions - public static void Init(string rootPath = ".", string scriptDirectory = "script", string databaseFile = "cards.cdb") + public static void Init(string rootPath = ".", string primaryScriptDirectory = "script", string alternativeScriptDirectory = null, string databaseFile = "cards.cdb") { _rootPath = rootPath; - _scriptDirectory = scriptDirectory; + _primaryScriptDirectory = primaryScriptDirectory; + _alternativeScriptDirectory = alternativeScriptDirectory; CardsManager.Init(Path.Combine(Path.GetFullPath(rootPath), databaseFile)); @@ -98,6 +100,11 @@ public static void Init(string rootPath = ".", string scriptDirectory = "script" set_message_handler(_messageCallback); } + public static Card[] GetCardList() + { + return CardsManager.GetCardList(); + } + public static void Dispose() { foreach (Duel duel in Duel.Duels.Values) @@ -126,7 +133,11 @@ private static IntPtr OnScriptReader(String scriptName, Int32* len) string filename = GetScriptFilename(scriptName); if (!File.Exists(filename)) { - return IntPtr.Zero; + filename = GetAlternativeScriptFilename(scriptName); + if (!File.Exists(filename)) + { + return IntPtr.Zero; + } } byte[] content = File.ReadAllBytes(filename); *len = content.Length; @@ -150,7 +161,12 @@ private static UInt32 OnMessageHandler(IntPtr pDuel, UInt32 messageType) private static string GetScriptFilename(string scriptName) { - return Path.Combine(_rootPath, scriptName.Replace("./script", _scriptDirectory)); + return Path.Combine(_rootPath, scriptName.Replace("./script", _primaryScriptDirectory)); + } + + private static string GetAlternativeScriptFilename(string scriptName) + { + return Path.Combine(_rootPath, scriptName.Replace("./script", _alternativeScriptDirectory)); } #endregion diff --git a/YGOSharp.OCGWrapper/CardsManager.cs b/YGOSharp.OCGWrapper/CardsManager.cs index d78e1bc..e8a5193 100644 --- a/YGOSharp.OCGWrapper/CardsManager.cs +++ b/YGOSharp.OCGWrapper/CardsManager.cs @@ -36,6 +36,14 @@ internal static Card GetCard(int id) return null; } + internal static Card[] GetCardList() + { + List list = new List(); + foreach (int card in _cards.Keys) + list.Add(_cards[card]); + return list.ToArray(); + } + private static void LoadCard(IDataRecord reader) { Card card = new Card(reader); diff --git a/YGOSharp.OCGWrapper/Duel.cs b/YGOSharp.OCGWrapper/Duel.cs index 9946aa9..7c814c2 100644 --- a/YGOSharp.OCGWrapper/Duel.cs +++ b/YGOSharp.OCGWrapper/Duel.cs @@ -13,14 +13,14 @@ public class Duel private readonly IntPtr _duelPtr; private readonly IntPtr _buffer; - private Func _analyzer; + private Func _analyzer; private Action _errorHandler; #endregion #region Public Methods - public void SetAnalyzer(Func analyzer) + public void SetAnalyzer(Func analyzer) { _analyzer = analyzer; } @@ -168,7 +168,7 @@ private int HandleMessage(BinaryReader reader, byte[] raw, int len) GameMessage msg = (GameMessage)reader.ReadByte(); int result = -1; if (_analyzer != null) - result = _analyzer.Invoke(msg, reader, raw); + result = _analyzer.Invoke(msg, reader, raw, len); if (result != 0) return result; } diff --git a/YGOSharp.OCGWrapper/Enums/CardType.cs b/YGOSharp.OCGWrapper/Enums/CardType.cs index bfb527b..becf17b 100644 --- a/YGOSharp.OCGWrapper/Enums/CardType.cs +++ b/YGOSharp.OCGWrapper/Enums/CardType.cs @@ -23,6 +23,7 @@ public enum CardType Counter = 0x100000, Flip = 0x200000, Toon = 0x400000, - Xyz = 0x800000 + Xyz = 0x800000, + Pendulum = 0x1000000 } } \ No newline at end of file diff --git a/YGOSharp.OCGWrapper/Enums/GameMessage.cs b/YGOSharp.OCGWrapper/Enums/GameMessage.cs index 08b1bf9..34c37f7 100644 --- a/YGOSharp.OCGWrapper/Enums/GameMessage.cs +++ b/YGOSharp.OCGWrapper/Enums/GameMessage.cs @@ -88,6 +88,7 @@ public enum GameMessage ReloadField = 162, AiName = 163, ShowHint = 164, + PlayerHint = 165, MatchKill = 170, CustomMsg = 180, DuelWinner = 200 diff --git a/YGOSharp.VC.db b/YGOSharp.VC.db new file mode 100644 index 0000000..0d0e391 Binary files /dev/null and b/YGOSharp.VC.db differ diff --git a/YGOSharp/BanlistManager.cs b/YGOSharp/BanlistManager.cs index d34c318..fac0b22 100644 --- a/YGOSharp/BanlistManager.cs +++ b/YGOSharp/BanlistManager.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; using System.IO; +using YGOSharp.OCGWrapper; +using YGOSharp.OCGWrapper.Enums; namespace YGOSharp { @@ -30,9 +32,42 @@ public static void Init(string fileName) if (current == null) continue; string[] data = line.Split(' '); - int id = int.Parse(data[0]); + int id = 0; + int.TryParse(data[0], out id); int count = int.Parse(data[1]); - current.Add(id, count); + if (id == 0) + { + if (data[0] == "TYPE_NORMAL") + BanType(current, CardType.Normal, count); + if (data[0] == "TYPE_XYZ") + BanType(current,CardType.Xyz, count); + if (data[0] == "TYPE_SYNCHRO") + BanType(current, CardType.Synchro, count); + if (data[0] == "TYPE_FUSION") + BanType(current, CardType.Fusion, count); + if (data[0] == "TYPE_PENDULUM") + BanType(current, CardType.Pendulum, count); + if (data[0] == "TYPE_SPELL") + BanType(current, CardType.Spell, count); + if (data[0] == "TYPE_TRAP") + BanType(current, CardType.Trap, count); + if (data[0] == "TYPE_RITUAL") + BanType(current, CardType.Ritual, count); + if (data[0] == "TYPE_EFFECT") + BanType(current, CardType.Effect, count); + } + else + current.Add(id, count); + } + } + + static void BanType(Banlist current,CardType type, int count) + { + Card[] cards = Api.GetCardList(); + foreach (Card card in cards) + { + if (card.HasType(type)) + current.Add(card.Id, count); } } @@ -41,6 +76,9 @@ public static int GetIndex(uint hash) for (int i = 0; i < Banlists.Count; i++) if (Banlists[i].Hash == hash) return i; + + if (hash < Banlists.Count) + return (int)hash; return 0; } } diff --git a/YGOSharp/Game.cs b/YGOSharp/Game.cs index b813f7b..093f001 100644 --- a/YGOSharp/Game.cs +++ b/YGOSharp/Game.cs @@ -620,17 +620,17 @@ public void TpResult(Player player, bool result) opt += 0x20; Replay = new Replay((uint)seed, IsTag); - Replay.Writer.WriteUnicode(Players[0].Name, 20); - Replay.Writer.WriteUnicode(Players[1].Name, 20); + Replay.WriteUnicode(Players[0].Name, 20); + Replay.WriteUnicode(Players[1].Name, 20); if (IsTag) { - Replay.Writer.WriteUnicode(Players[2].Name, 20); - Replay.Writer.WriteUnicode(Players[3].Name, 20); + Replay.WriteUnicode(Players[2].Name, 20); + Replay.WriteUnicode(Players[3].Name, 20); } - Replay.Writer.Write(StartLp); - Replay.Writer.Write(StartHand); - Replay.Writer.Write(DrawCount); - Replay.Writer.Write(opt); + Replay.Write(StartLp); + Replay.Write(StartHand); + Replay.Write(DrawCount); + Replay.Write(opt); for (int i = 0; i < Players.Length; i++) { @@ -638,22 +638,30 @@ public void TpResult(Player player, bool result) int pid = i; if (IsTag) pid = i >= 2 ? 1 : 0; + bool HideDeckInfo = Config.GetBool("HideDeckInfo", false); if (!NoShuffleDeck) { List cards = ShuffleCards(rand, dplayer.Deck.Main); - Replay.Writer.Write(cards.Count); + if (!HideDeckInfo) + Replay.Write(cards.Count); + else + Replay.Write(0); foreach (int id in cards) { if (IsTag && (i == 1 || i == 3)) _duel.AddTagCard(id, pid, CardLocation.Deck); else _duel.AddCard(id, pid, CardLocation.Deck); - Replay.Writer.Write(id); + if(!HideDeckInfo) + Replay.Write(id); } } else { - Replay.Writer.Write(dplayer.Deck.Main.Count); + if (!HideDeckInfo) + Replay.Write(dplayer.Deck.Main.Count); + else + Replay.Write(0); for (int j = dplayer.Deck.Main.Count - 1; j >= 0; j--) { int id = dplayer.Deck.Main[j]; @@ -661,18 +669,23 @@ public void TpResult(Player player, bool result) _duel.AddTagCard(id, pid, CardLocation.Deck); else _duel.AddCard(id, pid, CardLocation.Deck); - Replay.Writer.Write(id); + if (!HideDeckInfo) + Replay.Write(id); } } - Replay.Writer.Write(dplayer.Deck.Extra.Count); + if (!HideDeckInfo) + Replay.Write(dplayer.Deck.Extra.Count); + else + Replay.Write(0); foreach (int id in dplayer.Deck.Extra) { if (IsTag && (i == 1 || i == 3)) _duel.AddTagCard(id, pid, CardLocation.Extra); else _duel.AddCard(id, pid, CardLocation.Extra); - Replay.Writer.Write(id); - } + if(!HideDeckInfo) + Replay.Write(id); + } } BinaryWriter packet = GamePacketFactory.Create(GameMessage.Start); @@ -685,6 +698,9 @@ public void TpResult(Player player, bool result) packet.Write((short)_duel.QueryFieldCount(1, CardLocation.Extra)); SendToTeam(packet, 0); + if (Config.GetBool("YRP2", false)) + Replay.Write(packet); + packet.BaseStream.Position = 2; packet.Write((byte)1); SendToTeam(packet, 1); @@ -759,6 +775,10 @@ public void RefreshMonsters(int player, int flag = 0x81fff, Player observer = nu update.Write((byte)player); update.Write((byte)CardLocation.MonsterZone); update.Write(result); + + if (Config.GetBool("YRP2", false)) + Replay.Write(update); + if (observer == null) SendToTeam(update, player); @@ -808,6 +828,10 @@ public void RefreshSpells(int player, int flag = 0x681fff, Player observer = nul update.Write((byte)player); update.Write((byte)CardLocation.SpellZone); update.Write(result); + + if (Config.GetBool("YRP2", false)) + Replay.Write(update); + if (observer == null) SendToTeam(update, player); @@ -857,6 +881,10 @@ public void RefreshHand(int player, int flag = 0x181fff, Player observer = null) update.Write((byte)player); update.Write((byte)CardLocation.Hand); update.Write(result); + + if (Config.GetBool("YRP2", false)) + Replay.Write(update); + if (observer == null) CurPlayers[player].Send(update); @@ -901,6 +929,10 @@ public void RefreshGrave(int player, int flag = 0x81fff, Player observer = null) update.Write((byte)player); update.Write((byte)CardLocation.Grave); update.Write(result); + + if (Config.GetBool("YRP2", false)) + Replay.Write(update); + if (observer == null) SendToAll(update); else @@ -914,6 +946,10 @@ public void RefreshExtra(int player, int flag = 0x81fff) update.Write((byte)player); update.Write((byte)CardLocation.Extra); update.Write(result); + + if (Config.GetBool("YRP2", false) && !Config.GetBool("HideDeckInfo", false)) + Replay.Write(update); + CurPlayers[player].Send(update); } @@ -929,6 +965,9 @@ public void RefreshSingle(int player, int location, int sequence, int flag = 0x7 update.Write((byte)location); update.Write((byte)sequence); update.Write(result); + if (Config.GetBool("YRP2", false)) + Replay.Write(update); + CurPlayers[player].Send(update); if (IsTag) @@ -976,8 +1015,11 @@ public void SetResponse(int resp) { if (!Replay.Disabled) { - Replay.Writer.Write((byte)4); - Replay.Writer.Write(BitConverter.GetBytes(resp)); + if (!Config.GetBool("YRP2", false)) + { + Replay.Write((byte)4); + Replay.Write(BitConverter.GetBytes(resp)); + } Replay.Check(); } @@ -989,8 +1031,12 @@ public void SetResponse(byte[] resp) { if (!Replay.Disabled) { - Replay.Writer.Write((byte)resp.Length); - Replay.Writer.Write(resp); + if (!Config.GetBool("YRP2", false)) + { + Replay.Write((byte)resp.Length); + Replay.Write(resp); + + } Replay.Check(); } diff --git a/YGOSharp/GameAnalyser.cs b/YGOSharp/GameAnalyser.cs index 306bbaa..1f75a19 100644 --- a/YGOSharp/GameAnalyser.cs +++ b/YGOSharp/GameAnalyser.cs @@ -14,9 +14,16 @@ public GameAnalyser(Game game) Game = game; } - public int Analyse(GameMessage msg, BinaryReader reader, byte[] raw) + public int Analyse(GameMessage msg, BinaryReader reader, byte[] raw, int len) { LastMessage = msg; + + if (Config.GetBool("YRP2", false) && msg != GameMessage.Move) + { + Game.Replay.Write((short)len); + Game.Replay.Write(raw, 0, len); + } + CoreMessage cmsg = new CoreMessage(msg, reader, raw); switch (msg) { @@ -218,6 +225,9 @@ public int Analyse(GameMessage msg, BinaryReader reader, byte[] raw) case GameMessage.CardHint: SendToAll(cmsg, 9); break; + case GameMessage.PlayerHint: + SendToAll(cmsg, len); + break; case GameMessage.MatchKill: OnMatchKill(cmsg); break; @@ -227,6 +237,7 @@ public int Analyse(GameMessage msg, BinaryReader reader, byte[] raw) default: throw new Exception("[GameAnalyser] Unhandled packet id: " + msg); } + return 0; } @@ -535,10 +546,12 @@ private void OnMove(CoreMessage msg) packet.BaseStream.Position = 2; packet.Write(0); } + if (Config.GetBool("YRP2", false)) + Game.Replay.Write(packet); Game.SendToAllBut(packet, cc); if (cl != 0 && (cl & 0x80) == 0 && (cl != pl || pc != cc)) - Game.RefreshSingle(cc, cl, cs); + Game.RefreshSingle(cc, cl, cs); } private void OnPosChange(CoreMessage msg) diff --git a/YGOSharp/GamePacketFactory.cs b/YGOSharp/GamePacketFactory.cs index 3e14a56..6da6a9d 100644 --- a/YGOSharp/GamePacketFactory.cs +++ b/YGOSharp/GamePacketFactory.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using YGOSharp.Network.Enums; using YGOSharp.OCGWrapper.Enums; diff --git a/YGOSharp/Program.cs b/YGOSharp/Program.cs index 39f24ca..703aa62 100644 --- a/YGOSharp/Program.cs +++ b/YGOSharp/Program.cs @@ -19,8 +19,10 @@ public static void Main(string[] args) #endif Config.Load(args); + + BanlistManager.Init(Config.GetString("BanlistFile", "lflist.conf")); + Api.Init(Config.GetString("RootPath", "."), Config.GetString("ScriptDirectory", "script"), Config.GetString("AlternativeScriptDirectory", "script"), Config.GetString("DatabaseFile", "cards.cdb")); BanlistManager.Init(Config.GetString("BanlistFile", "lflist.conf")); - Api.Init(Config.GetString("RootPath", "."), Config.GetString("ScriptDirectory", "script"), Config.GetString("DatabaseFile", "cards.cdb")); ClientVersion = Config.GetUInt("ClientVersion", ClientVersion); diff --git a/YGOSharp/Replay.cs b/YGOSharp/Replay.cs index bb6a070..f562bbe 100644 --- a/YGOSharp/Replay.cs +++ b/YGOSharp/Replay.cs @@ -1,4 +1,7 @@ -using System.IO; +using System; +using System.IO; +using YGOSharp.Network.Utils; +using YGOSharp.OCGWrapper.Enums; using YGOSharp.SevenZip.Compress.LZMA; namespace YGOSharp @@ -19,17 +22,19 @@ public struct ReplayHeader public const uint FlagCompressed = 0x1; public const uint FlagTag = 0x2; - public const int MaxReplaySize = 0x20000; + private int MaxReplaySize = 0x20000; public bool Disabled { get; private set; } public ReplayHeader Header; - public BinaryWriter Writer { get; private set; } + private BinaryWriter Writer; private MemoryStream _stream; private byte[] _data; public Replay(uint seed, bool tag) { + if (Config.GetBool("YRP2", false)) + MaxReplaySize = 0x7FFF; Header.Id = 0x31707279; Header.Version = Program.ClientVersion; Header.Flag = tag ? FlagTag : 0; @@ -39,6 +44,60 @@ public Replay(uint seed, bool tag) Writer = new BinaryWriter(_stream); } + public void Write(BinaryWriter packet) + { + if (Disabled) + return; + byte[] data = ((MemoryStream)packet.BaseStream).ToArray(); + byte[] replayData = new byte[data.Length - 1]; + Array.Copy(data, 1, replayData, 0, replayData.Length); + + Write((short)replayData.Length); + Write(replayData); + } + + public void Write(int packet) + { + if (Disabled) + return; + Writer.Write(packet); + } + + public void Write(short packet) + { + if (Disabled) + return; + Writer.Write(packet); + } + + public void Write(byte packet) + { + if (Disabled) + return; + Writer.Write(packet); + } + + public void Write(byte[] packet) + { + if (Disabled) + return; + Writer.Write(packet); + } + + public void WriteUnicode(string packet, int len) + { + if (Disabled) + return; + Writer.WriteUnicode(packet, len); + } + + public void Write(byte[] packet, int index, int len) + { + if (Disabled) + return; + Writer.Write(packet, index, len); + } + public void Check() { if (_stream.Position >= MaxReplaySize) @@ -53,6 +112,11 @@ public void End() { if (Disabled) return; + if (Config.GetBool("YRP2", false)) + { + Write((short)1); + Write((byte)GameMessage.Win); + } byte[] raw = _stream.ToArray(); @@ -83,6 +147,7 @@ public void End() writer.Write(raw); _data = ms.ToArray(); + } public byte[] GetContent()