From c580a40c2669109a0b2b3d1966b68d75e66cfae5 Mon Sep 17 00:00:00 2001 From: Tom Quinn Date: Fri, 20 Feb 2015 04:28:18 -0500 Subject: [PATCH] First release. Configurable image directory, show IP on server launch, vobf. --- .gitignore | 16 ++------- ConnectWindow.Designer.cs | 31 ++++++++--------- ConnectWindow.cs | 3 ++ DraftClient.cs | 7 ++++ DraftPicker.cs | 5 +++ DraftServer.cs | 17 +++++++-- DraftWindow.cs | 14 ++++++-- README.md | 21 ++++++----- ServerWindow.Designer.cs | 73 ++++++++++++++++++++++++++++++++++----- ServerWindow.cs | 45 +++++++++++++++++++----- Util.cs | 1 + 11 files changed, 173 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index e08b20f..3dea4ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,2 @@ -obj/x86/Debug/DesignTimeResolveAssemblyReferences.cache -*.cache -obj/x86/Debug/IsochronDrafter.CardWindow.resources -*.resources -obj/x86/Debug/IsochronDrafter.csproj.FileListAbsolute.txt -obj/x86/Debug/IsochronDrafter.exe -obj/x86/Debug/IsochronDrafter.pdb -bin/Debug/tcpServer.pdb -bin/Debug/tcpServer.dll -bin/Debug/IsochronDrafter.vshost.exe.manifest -bin/Debug/IsochronDrafter.vshost.exe -bin/Debug/IsochronDrafter - Copy.exe -bin/Debug/IsochronDrafter.exe -bin/Debug/IsochronDrafter.pdb \ No newline at end of file +bin/* +obj/* \ No newline at end of file diff --git a/ConnectWindow.Designer.cs b/ConnectWindow.Designer.cs index f13135f..88ee022 100644 --- a/ConnectWindow.Designer.cs +++ b/ConnectWindow.Designer.cs @@ -37,13 +37,22 @@ private void InitializeComponent() button1 = new System.Windows.Forms.Button(); this.SuspendLayout(); // + // button1 + // + button1.Location = new System.Drawing.Point(55, 60); + button1.Name = "button1"; + button1.Size = new System.Drawing.Size(129, 23); + button1.TabIndex = 2; + button1.Text = "Connect"; + button1.UseVisualStyleBackColor = true; + button1.Click += new System.EventHandler(this.button1_Click); + // // textBox1 // this.textBox1.Location = new System.Drawing.Point(74, 12); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(149, 20); this.textBox1.TabIndex = 0; - this.textBox1.Text = "isochron.us.to"; // // label1 // @@ -59,7 +68,7 @@ private void InitializeComponent() this.textBox2.Location = new System.Drawing.Point(74, 34); this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(149, 20); - this.textBox2.TabIndex = 0; + this.textBox2.TabIndex = 1; // // label2 // @@ -70,23 +79,13 @@ private void InitializeComponent() this.label2.TabIndex = 1; this.label2.Text = "Alias:"; // - // button1 - // - button1.Location = new System.Drawing.Point(17, 60); - button1.Name = "button1"; - button1.Size = new System.Drawing.Size(206, 23); - button1.TabIndex = 2; - button1.Text = "Connect"; - button1.UseVisualStyleBackColor = true; - button1.Click += new System.EventHandler(this.button1_Click); - // // button2 // - this.button2.Location = new System.Drawing.Point(17, 89); + this.button2.Location = new System.Drawing.Point(55, 89); this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(206, 23); - this.button2.TabIndex = 2; - this.button2.Text = "Start Server"; + this.button2.Size = new System.Drawing.Size(129, 23); + this.button2.TabIndex = 3; + this.button2.Text = "Start Server..."; this.button2.UseVisualStyleBackColor = true; this.button2.Click += new System.EventHandler(this.button2_Click); // diff --git a/ConnectWindow.cs b/ConnectWindow.cs index e82ed60..5248763 100644 --- a/ConnectWindow.cs +++ b/ConnectWindow.cs @@ -15,6 +15,9 @@ public ConnectWindow() { InitializeComponent(); MaximizeBox = false; + #if DEBUG + textBox1.Text = "isochron.us.to"; + #endif } // Connect. diff --git a/DraftClient.cs b/DraftClient.cs index f6c9568..f6cda3a 100644 --- a/DraftClient.cs +++ b/DraftClient.cs @@ -71,6 +71,7 @@ private void HandleMessage(string msg) else if (parts[1] == "PICK") { draftWindow.ClearDraftPicker(); + draftWindow.EnableDraftPicker(); } } else if (parts[0] == "ERROR") @@ -87,6 +88,11 @@ private void HandleMessage(string msg) draftWindow.PrintLine("Unknown error from server: " + parts[1]); client.Disconnect(); } + else if (parts[0] == "IMAGE_DIR") + { + Util.imageDirectory = parts[1]; + draftWindow.PrintLine("Set image directory."); + } else if (parts[0] == "USER_CONNECTED") { if (parts[1] != alias) @@ -106,6 +112,7 @@ private void HandleMessage(string msg) else if (parts[0] == "BOOSTER") { draftWindow.PopulateDraftPicker(msg); + draftWindow.EnableDraftPicker(); } else if (parts[0] == "CARD_POOL") { diff --git a/DraftPicker.cs b/DraftPicker.cs index 66af338..1d894ad 100644 --- a/DraftPicker.cs +++ b/DraftPicker.cs @@ -31,6 +31,11 @@ public void Populate(List cardNames) DraftWindow.LoadImage(cardName); Invalidate(); } + public void Clear() + { + cardNames = new List(); + Invalidate(); + } protected override void OnPaint(PaintEventArgs e) { diff --git a/DraftServer.cs b/DraftServer.cs index 275c870..3108620 100644 --- a/DraftServer.cs +++ b/DraftServer.cs @@ -37,13 +37,25 @@ public DraftServer(ServerWindow serverWindow, string setFilename) ParseText(File.ReadAllText(setFilename)); serverWindow.PrintLine("Loaded set: " + setName + "."); + // Get public IP address of server. + string url = "http://checkip.dyndns.org"; + System.Net.WebRequest req = System.Net.WebRequest.Create(url); + System.Net.WebResponse resp = req.GetResponse(); + System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream()); + string response = sr.ReadToEnd().Trim(); + string[] a = response.Split(':'); + string a2 = a[1].Substring(1); + string[] a3 = a2.Split('<'); + string ip = a3[0]; + + server = new TcpServer(); server.Port = 10024; server.OnConnect += OnConnect; server.OnDisconnect += OnDisconnect; server.OnDataAvailable += OnDataAvailable; server.Open(); - serverWindow.PrintLine("Launched server on port " + server.Port + ". Accepting connections."); + serverWindow.PrintLine("Launched server at " + ip + " on port " + server.Port + ". Accepting connections."); } private void OnConnect(TcpServerConnection connection) @@ -135,6 +147,7 @@ private void HandleMessage(TcpServerConnection connection, string msg) serverWindow.PrintLine("<" + GetAlias(connection) + "> has new alias " + parts[1] + "."); aliases.TryAdd(connection, parts[1]); TrySendMessage(connection, "OK|ALIAS"); + TrySendMessage(connection, "IMAGE_DIR|" + Util.imageDirectory); TrySendMessage("USER_CONNECTED|" + parts[1]); if (draftStarted) { @@ -167,7 +180,7 @@ private void HandleMessage(TcpServerConnection connection, string msg) booster.RemoveAt(pickIndex); draftState.boosters.Remove(booster); TrySendMessage(connection, "OK|PICK"); - serverWindow.PrintLine("<" + draftState.alias + "> picked " + pick + "."); + serverWindow.PrintLine("<" + draftState.alias + "> made a pick."); // Pass the pack to the next player, if not empty. if (booster.Count > 0) diff --git a/DraftWindow.cs b/DraftWindow.cs index ef57e7c..fee3193 100644 --- a/DraftWindow.cs +++ b/DraftWindow.cs @@ -18,6 +18,7 @@ public partial class DraftWindow : Form private static Dictionary cardImages = new Dictionary(); public CardWindow cardWindow; public DraftClient draftClient; + public bool canPick = true; public DraftWindow() { @@ -62,7 +63,7 @@ public static void LoadImage(string cardName) { if (cardImages.ContainsKey(cardName)) return; - HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("https://dl.dropboxusercontent.com/u/1377551/IsochronDrafter/" + cardName.Replace(",", "").Replace("’", "") + ".full.jpg"); + HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(Util.imageDirectory + cardName.Replace(",", "").Replace("’", "") + ".full.jpg"); HttpWebResponse httpWebReponse = (HttpWebResponse)httpWebRequest.GetResponse(); Stream stream = httpWebReponse.GetResponseStream(); cardImages.Add(cardName, Image.FromStream(stream)); @@ -88,7 +89,11 @@ public void PopulateDraftPicker(string message) } public void ClearDraftPicker() { - draftPicker.Populate(new List()); + draftPicker.Clear(); + } + public void EnableDraftPicker() + { + canPick = true; } public void AddCardToPool(string cardName) { @@ -107,10 +112,15 @@ public void ClearCardPool() private void draftPicker1_DoubleClick(object sender, EventArgs e) { + if (!canPick) + return; MouseEventArgs me = e as MouseEventArgs; int index = draftPicker.GetIndexFromCoor(me.X, me.Y); if (index != -1) + { + canPick = false; draftClient.Pick(index, draftPicker.cardNames[index]); + } } // Menu items. diff --git a/README.md b/README.md index 6b89dd3..bb758a5 100644 --- a/README.md +++ b/README.md @@ -6,32 +6,35 @@ A hacked-together way to draft custom Magic: the Gathering sets online. ## Features * Draft custom Magic sets online with your friends! * Graphical deck builder allows you to build your deck as you draft! -* That's it. +* That's it. [Screenshot.](http://i.imgur.com/ssYb7TB.jpg) + +## Requirements +Windows and .NET 4.0, until someone wants to do a Mono port. ## What's Broken? Well, a lot of stuff. For starters: * Slow image downloading * Scrollbars sometimes flicker rapidly when they appear/disappear -* Very little error handling when parsing set files, loading images, etc. +* Little to no error handling when parsing set files, loading images, etc. -## Coming Soon -* A more configurable server +## Coming Eventually * Graphical bug fixes * More error handling -* Miscellaneous beautification +* More info about table order, who has how many packs during drafts +* Resizable windows +* Better image downloading ## How to Use -NOTE: This process will get much easier shortly. * Export your set from Magic Set Editor using the script in the scripts/ directory. +* Export card images from your set -- filename must be ".full.jpg". * Upload the card images from your set somewhere. -* Fix the base image directory in LoadImage(...) in DraftWindow.cs. Recompile. -* In Isochron Drafter, start a server and select the exported set. +* In Isochron Drafter, start a server, browse to the set file, enter the image directory. * Have everyone connect to the IP you're hosting the server on. * Start the draft on the server. * Enjoy. ## Notes * Isochron Drafter was written by Tom Quinn, and is available under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/). -* It uses Craig Baird's [C# TCP Server](http://www.codeproject.com/Articles/488668/Csharp-TCP-Server) and skatamatic's [Event-Driven TCP Client](https://www.daniweb.com/software-development/csharp/code/422291/user-friendly-asynchronous-event-driven-tcp-client). +* It uses Craig Baird's [C# TCP Server](http://www.codeproject.com/Articles/488668/Csharp-TCP-Server) and skatamatic's [Event-Driven TCP Client](https://www.daniweb.com/software-development/csharp/code/422291/user-friendly-asynchronous-event-driven-tcp-client), each with some minor changes. * It is really hacked together, and not at all representative of my overall coding style or quality. Don't judge... ;_; * Find my other stuff at my [portfolio site](http://cargocollective.com/tomquinn), and let me know what you think! diff --git a/ServerWindow.Designer.cs b/ServerWindow.Designer.cs index 7048607..279ed01 100644 --- a/ServerWindow.Designer.cs +++ b/ServerWindow.Designer.cs @@ -32,16 +32,21 @@ private void InitializeComponent() this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); this.button2 = new System.Windows.Forms.Button(); this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button3 = new System.Windows.Forms.Button(); + this.textBox3 = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // button1 // - this.button1.Anchor = System.Windows.Forms.AnchorStyles.Bottom; - this.button1.Location = new System.Drawing.Point(249, 403); + this.button1.Anchor = System.Windows.Forms.AnchorStyles.None; + this.button1.Location = new System.Drawing.Point(278, 452); this.button1.Name = "button1"; - this.button1.Size = new System.Drawing.Size(160, 23); - this.button1.TabIndex = 1; - this.button1.Text = "Browse and Launch Server"; + this.button1.Size = new System.Drawing.Size(101, 23); + this.button1.TabIndex = 3; + this.button1.Text = "Launch Server"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // @@ -52,10 +57,10 @@ private void InitializeComponent() // button2 // this.button2.Enabled = false; - this.button2.Location = new System.Drawing.Point(415, 403); + this.button2.Location = new System.Drawing.Point(385, 452); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(85, 23); - this.button2.TabIndex = 2; + this.button2.TabIndex = 4; this.button2.Text = "Start Draft"; this.button2.UseVisualStyleBackColor = true; this.button2.Click += new System.EventHandler(this.button2_Click); @@ -70,11 +75,58 @@ private void InitializeComponent() this.textBox1.Size = new System.Drawing.Size(725, 385); this.textBox1.TabIndex = 0; // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(51, 404); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(45, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Set File:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 429); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(84, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Image Directory:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(102, 401); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(554, 20); + this.textBox2.TabIndex = 0; + // + // button3 + // + this.button3.Location = new System.Drawing.Point(662, 399); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(75, 23); + this.button3.TabIndex = 1; + this.button3.Text = "Browse..."; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(102, 426); + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(554, 20); + this.textBox3.TabIndex = 2; + // // ServerWindow // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(749, 438); + this.ClientSize = new System.Drawing.Size(749, 483); + this.Controls.Add(this.button3); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Controls.Add(this.textBox1); @@ -92,5 +144,10 @@ private void InitializeComponent() private System.Windows.Forms.OpenFileDialog openFileDialog1; private System.Windows.Forms.Button button2; private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.TextBox textBox3; } } \ No newline at end of file diff --git a/ServerWindow.cs b/ServerWindow.cs index abaf85a..02952a4 100644 --- a/ServerWindow.cs +++ b/ServerWindow.cs @@ -19,17 +19,12 @@ public ServerWindow() { InitializeComponent(); MaximizeBox = false; + #if DEBUG + textBox2.Text = "C:\\Users\\Tom\\Desktop\\Kavanagh.txt"; + textBox3.Text = "https://dl.dropboxusercontent.com/u/1377551/IsochronDrafter/"; + #endif } - private void button1_Click(object sender, EventArgs e) - { - DialogResult result = openFileDialog1.ShowDialog(); - if (result == System.Windows.Forms.DialogResult.OK) - { - server = new DraftServer(this, openFileDialog1.FileName); - button1.Enabled = false; - } - } public void PrintLine(string text) { textBox1.Invoke(new MethodInvoker(delegate @@ -49,6 +44,38 @@ public void DraftButtonEnabled(bool enabled) })); } + private void button3_Click(object sender, EventArgs e) + { + DialogResult result = openFileDialog1.ShowDialog(); + if (result == System.Windows.Forms.DialogResult.OK) + { + textBox2.Text = openFileDialog1.FileName; + } + } + + private void button1_Click(object sender, EventArgs e) + { + if (textBox2.Text.Length == 0) + { + MessageBox.Show("You must choose a set file."); + return; + } + if (textBox3.Text.Length == 0) + { + MessageBox.Show("You must enter a remote image directory."); + return; + } + + Util.imageDirectory = textBox3.Text; + if (!Util.imageDirectory.EndsWith("/")) + Util.imageDirectory += "/"; + server = new DraftServer(this, textBox2.Text); + button1.Enabled = false; + button3.Enabled = false; + textBox2.Enabled = false; + textBox3.Enabled = false; + } + private void button2_Click(object sender, EventArgs e) { PrintLine("Starting draft with " + server.aliases.Count + " players."); diff --git a/Util.cs b/Util.cs index 59a722b..b418af9 100644 --- a/Util.cs +++ b/Util.cs @@ -8,6 +8,7 @@ namespace IsochronDrafter public class Util { public static readonly int version = 1; + public static string imageDirectory; public static Random random = new Random(); public static int[] PickN(int max, int count)