add a simple in-game IRC client

This commit is contained in:
Matthias Mailänder
2015-07-06 14:53:54 +02:00
parent 2df76ad962
commit dae3b62d2a
19 changed files with 660 additions and 66 deletions

View File

@@ -151,6 +151,9 @@ Motmans and distributed under the MIT license.
Using ICSharpCode.SharpZipLib initially by Mike Using ICSharpCode.SharpZipLib initially by Mike
Krueger and distributed under the GNU GPL terms. Krueger and distributed under the GNU GPL terms.
Using SmartIrc4Net developed by Mirco Bauer
distributed under the LGPL version 2.1 or later.
Finally, special thanks goes to the original teams Finally, special thanks goes to the original teams
at Westwood Studios and EA for creating the classic at Westwood Studios and EA for creating the classic

View File

@@ -40,7 +40,7 @@
CSC = dmcs CSC = dmcs
CSFLAGS = -nologo -warn:4 -codepage:utf8 -unsafe -warnaserror CSFLAGS = -nologo -warn:4 -codepage:utf8 -unsafe -warnaserror
DEFINE = TRACE DEFINE = TRACE
COMMON_LIBS = System.dll System.Core.dll System.Data.dll System.Data.DataSetExtensions.dll System.Drawing.dll System.Xml.dll thirdparty/download/ICSharpCode.SharpZipLib.dll thirdparty/download/FuzzyLogicLibrary.dll thirdparty/download/Mono.Nat.dll thirdparty/download/MaxMind.Db.dll thirdparty/download/MaxMind.GeoIP2.dll thirdparty/download/Eluant.dll COMMON_LIBS = System.dll System.Core.dll System.Data.dll System.Data.DataSetExtensions.dll System.Drawing.dll System.Xml.dll thirdparty/download/ICSharpCode.SharpZipLib.dll thirdparty/download/FuzzyLogicLibrary.dll thirdparty/download/Mono.Nat.dll thirdparty/download/MaxMind.Db.dll thirdparty/download/MaxMind.GeoIP2.dll thirdparty/download/Eluant.dll thirdparty/download/SmarIrc4net.dll
DEBUG = true DEBUG = true
ifeq ($(DEBUG), $(filter $(DEBUG),false no n off 0)) ifeq ($(DEBUG), $(filter $(DEBUG),false no n off 0))

View File

@@ -288,6 +288,17 @@ namespace OpenRA
} }
} }
public class IrcSettings
{
public string[] Hostname = { "irc.openra.net" };
public int Port = 6667;
public string Channel = "lobby";
public string Nickname = "Newbie";
public string QuitMessage = "Battle control terminated!";
public string TimestampFormat = "HH:mm";
public bool ConnectAutomatically = false;
}
public class Settings public class Settings
{ {
string settingsFile; string settingsFile;
@@ -299,6 +310,7 @@ namespace OpenRA
public ServerSettings Server = new ServerSettings(); public ServerSettings Server = new ServerSettings();
public DebugSettings Debug = new DebugSettings(); public DebugSettings Debug = new DebugSettings();
public KeySettings Keys = new KeySettings(); public KeySettings Keys = new KeySettings();
public IrcSettings Irc = new IrcSettings();
public Dictionary<string, object> Sections; public Dictionary<string, object> Sections;
@@ -314,6 +326,7 @@ namespace OpenRA
{ "Server", Server }, { "Server", Server },
{ "Debug", Debug }, { "Debug", Debug },
{ "Keys", Keys }, { "Keys", Keys },
{ "Irc", Irc }
}; };
// Override fieldloader to ignore invalid entries // Override fieldloader to ignore invalid entries

19
OpenRA.Mods.Common/Irc.cs Normal file
View File

@@ -0,0 +1,19 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using Meebey.SmartIrc4net;
namespace OpenRA.Mods.Common
{
public static class Irc
{
public static volatile IrcClient Client;
}
}

View File

@@ -78,6 +78,9 @@
<HintPath>..\thirdparty\download\ICSharpCode.SharpZipLib.dll</HintPath> <HintPath>..\thirdparty\download\ICSharpCode.SharpZipLib.dll</HintPath>
<Private>False</Private> <Private>False</Private>
</Reference> </Reference>
<Reference Include="SmarIrc4net">
<HintPath>..\thirdparty\download\SmarIrc4net.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj"> <ProjectReference Include="..\OpenRA.Game\OpenRA.Game.csproj">
@@ -604,6 +607,8 @@
<Compile Include="Widgets\Logic\Installation\DownloadPackagesLogic.cs" /> <Compile Include="Widgets\Logic\Installation\DownloadPackagesLogic.cs" />
<Compile Include="Widgets\Logic\Installation\InstallLogic.cs" /> <Compile Include="Widgets\Logic\Installation\InstallLogic.cs" />
<Compile Include="Widgets\Logic\Installation\InstallMusicLogic.cs" /> <Compile Include="Widgets\Logic\Installation\InstallMusicLogic.cs" />
<Compile Include="Widgets\Logic\IrcLogic.cs" />
<Compile Include="Irc.cs" />
<Compile Include="Widgets\Logic\Lobby\ClientTooltipLogic.cs" /> <Compile Include="Widgets\Logic\Lobby\ClientTooltipLogic.cs" />
<Compile Include="Widgets\Logic\Lobby\KickClientLogic.cs" /> <Compile Include="Widgets\Logic\Lobby\KickClientLogic.cs" />
<Compile Include="Widgets\Logic\Lobby\KickSpectatorsLogic.cs" /> <Compile Include="Widgets\Logic\Lobby\KickSpectatorsLogic.cs" />

View File

@@ -0,0 +1,374 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Meebey.SmartIrc4net;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
{
class IrcLogic
{
readonly TextFieldWidget inputBox;
readonly TextFieldWidget nicknameBox;
readonly Widget connectBG;
readonly Widget ircContainer;
readonly ScrollPanelWidget historyPanel;
readonly LabelWidget historyTemplate;
readonly ScrollPanelWidget nicknamePanel;
readonly LabelWidget nicknameTemplate;
bool pingSent;
Channel channel;
[ObjectCreator.UseCtor]
public IrcLogic(Widget widget)
{
Log.AddChannel("irc", "irc.log");
historyPanel = widget.Get<ScrollPanelWidget>("HISTORY_PANEL");
historyTemplate = widget.Get<LabelWidget>("HISTORY_TEMPLATE");
nicknamePanel = widget.Get<ScrollPanelWidget>("NICKNAME_PANEL");
nicknameTemplate = widget.Get<LabelWidget>("NICKNAME_TEMPLATE");
inputBox = widget.Get<TextFieldWidget>("INPUT_BOX");
inputBox.OnEnterKey = EnterPressed;
inputBox.IsDisabled = () => Irc.Client == null;
if (Game.Settings.Irc.Nickname == new IrcSettings().Nickname)
Game.Settings.Irc.Nickname += Game.CosmeticRandom.Next(100, 999);
nicknameBox = widget.Get<TextFieldWidget>("NICKNAME_BOX");
nicknameBox.Text = SanitizedName(Game.Settings.Irc.Nickname);
nicknameBox.OnTextEdited = () =>
{
nicknameBox.Text = SanitizedName(nicknameBox.Text);
Game.Settings.Irc.Nickname = nicknameBox.Text;
Game.Settings.Save();
};
connectBG = widget.Get("IRC_CONNECT_BG");
ircContainer = widget.Get("IRC_CONTAINER");
var disconnectButton = widget.Get<ButtonWidget>("DISCONNECT_BUTTON");
disconnectButton.IsDisabled = () => Irc.Client == null;
disconnectButton.OnClick = Disconnect;
MaybeShowConnectPanel();
}
static string SanitizedName(string dirty)
{
if (string.IsNullOrEmpty(dirty))
return null;
// TODO: some special chars are allowed as well, but not at every position
var clean = new string(dirty.Where(c => char.IsLetterOrDigit(c)).ToArray());
if (string.IsNullOrEmpty(clean))
return null;
if (char.IsDigit(clean[0]))
return SanitizedName(clean.Substring(1));
// Source: https://tools.ietf.org/html/rfc2812#section-1.2.1
if (clean.Length > 9)
clean = clean.Substring(0, 9);
return clean;
}
void MaybeShowConnectPanel()
{
if (Irc.Client != null && Irc.Client.IsConnected)
{
ircContainer.Visible = true;
connectBG.Visible = false;
Initialize();
if (Irc.Client.JoinedChannels.Count > 0)
channel = Irc.Client.GetChannel(Irc.Client.JoinedChannels[0]);
SyncNicknamePanel();
return;
}
if (Game.Settings.Irc.ConnectAutomatically)
{
ircContainer.Visible = true;
connectBG.Visible = false;
Connect();
return;
}
ircContainer.Visible = false;
connectBG.Visible = true;
var connectAutomaticallyCheckBox = connectBG.Get<CheckboxWidget>("CONNECT_AUTOMATICALLY_CHECKBOX");
connectAutomaticallyCheckBox.IsChecked = () => Game.Settings.Irc.ConnectAutomatically;
connectAutomaticallyCheckBox.OnClick = () => Game.Settings.Irc.ConnectAutomatically ^= true;
var connectButton = connectBG.Get<ButtonWidget>("CONNECT_BUTTON");
connectButton.IsDisabled = () => string.IsNullOrEmpty(nicknameBox.Text);
connectButton.OnClick = () =>
{
ircContainer.Visible = true;
connectBG.Visible = false;
Game.Settings.Irc.ConnectAutomatically = connectAutomaticallyCheckBox.IsChecked();
Game.Settings.Save();
Connect();
};
}
void Initialize()
{
Irc.Client.OnConnected += OnConnected;
Irc.Client.OnError += OnError;
Irc.Client.OnRawMessage += OnRawMessage;
Irc.Client.OnJoin += OnJoin;
Irc.Client.OnChannelActiveSynced += OnChannelActiveSynced;
Irc.Client.OnNickChange += OnNickChange;
Irc.Client.OnPart += OnPart;
Irc.Client.OnQuit += OnQuit;
Irc.Client.OnChannelMessage += OnChannelMessage;
Irc.Client.OnPong += OnPong;
}
void Connect()
{
Irc.Client = new IrcClient();
Irc.Client.Encoding = System.Text.Encoding.UTF8;
Irc.Client.SendDelay = 100;
Irc.Client.ActiveChannelSyncing = true;
Initialize();
Game.OnQuit += Disconnect;
try
{
AddChatLine("Connecting to {0}...".F(Game.Settings.Irc.Hostname));
Irc.Client.Connect(Game.Settings.Irc.Hostname, Game.Settings.Irc.Port);
}
catch (Exception e)
{
AddChatLine("Connection error: {0}".F(e.Message));
Game.RunAfterTick(() =>
{
Log.Write("irc", e.ToString());
});
}
new Thread(Irc.Client.Listen) { Name = "IrcListenThread" }.Start();
}
void OnPong(object sender, PongEventArgs e)
{
if (pingSent)
{
AddChatLine("PONG recieved after {0} ms.".F(e.Lag.Milliseconds));
pingSent = false;
}
else
{
Game.RunAfterTick(() =>
{
Log.Write("irc", "PONG sent after {0} ms.".F(e.Lag.Milliseconds));
});
}
}
Widget MakeLabelWidget(LabelWidget template, string item)
{
var widget = (LabelWidget)template.Clone();
var font = Game.Renderer.Fonts[widget.Font];
item = WidgetUtils.WrapText(item, widget.Bounds.Width, font);
widget.Bounds.Height = font.Measure(item).Y;
widget.GetText = () => item;
widget.Id = item;
return widget;
}
void AddChatLine(string text)
{
Game.RunAfterTick(() =>
{
Log.Write("irc", text);
var scrolledToBottom = historyPanel.ScrolledToBottom;
var newChild = MakeLabelWidget(historyTemplate, text);
historyPanel.AddChild(newChild);
if (scrolledToBottom)
historyPanel.ScrollToBottom(smooth: true);
});
}
bool EnterPressed()
{
if (inputBox.Text.Length == 0)
return true;
var text = inputBox.Text;
inputBox.Text = "";
if (text.StartsWith("/nick "))
{
var nick = text.Replace("/nick ", string.Empty);
if (Rfc2812.IsValidNickname(nick))
Irc.Client.RfcNick(nick);
else
AddChatLine("Invalid nickname.");
}
else if (text.StartsWith("/ping "))
{
Irc.Client.RfcPing(Irc.Client.GetIrcUser(text.Replace("/ping ", string.Empty)).Host);
pingSent = true;
}
else if (text.StartsWith("/"))
AddChatLine("Unknown command.");
else
{
AddChatLine("[{0}] <{1}> {2}".F(DateTime.Now.ToString(Game.Settings.Irc.TimestampFormat), Irc.Client.Nickname, text));
Irc.Client.SendMessage(SendType.Message, "#" + Game.Settings.Irc.Channel, text);
}
return true;
}
void OnConnected(object sender, EventArgs e)
{
AddChatLine("Connected.");
if (!Rfc2812.IsValidNickname(Game.Settings.Irc.Nickname))
{
AddChatLine("Invalid nickname. Can't login.");
return;
}
Irc.Client.Login(new[] { Game.Settings.Irc.Nickname }, "in-game IRC client", 0, "OpenRA");
Irc.Client.RfcJoin("#" + Game.Settings.Irc.Channel);
}
void OnError(object sender, ErrorEventArgs e)
{
AddChatLine("Error: " + e.ErrorMessage);
Game.RunAfterTick(() =>
{
Log.Write("irc", e.ToString());
});
}
void OnRawMessage(object sender, IrcEventArgs e)
{
Game.RunAfterTick(() =>
{
Log.Write("irc", e.Data.RawMessage);
});
}
void OnChannelMessage(object sender, IrcEventArgs e)
{
AddChatLine("[{0}] <{1}> {2}".F(DateTime.Now.ToString(Game.Settings.Irc.TimestampFormat), e.Data.Nick, e.Data.Message));
}
void OnJoin(object sender, JoinEventArgs e)
{
if (e.Who == Irc.Client.Nickname)
return;
AddChatLine("{0} joined channel {1}.".F(e.Who, e.Channel));
channel = Irc.Client.GetChannel(e.Channel);
SyncNicknamePanel();
}
void OnChannelActiveSynced(object sender, IrcEventArgs e)
{
channel = Irc.Client.GetChannel(e.Data.Channel);
AddChatLine("{0} users online".F(channel.Users.Count));
if (!string.IsNullOrEmpty(channel.Topic))
AddChatLine("*** Topic: {0}".F(channel.Topic));
SyncNicknamePanel();
}
void OnNickChange(object sender, NickChangeEventArgs e)
{
AddChatLine("{0} is now known as {1}.".F(e.OldNickname, e.NewNickname));
SyncNicknamePanel();
}
void SyncNicknamePanel()
{
if (channel == null)
return;
var users = channel.Users;
Game.RunAfterTick(() =>
{
nicknamePanel.RemoveChildren();
foreach (DictionaryEntry user in users)
{
var channeluser = (ChannelUser)user.Value;
var prefix = channeluser.IsOp ? "@" : channeluser.IsVoice ? "+" : "";
var newChild = MakeLabelWidget(nicknameTemplate, prefix + channeluser.Nick);
nicknamePanel.AddChild(newChild);
}
});
}
void OnQuit(object sender, QuitEventArgs e)
{
AddChatLine("{0} quit.".F(e.Who));
}
void OnPart(object sender, PartEventArgs e)
{
AddChatLine("{0} left {1}.".F(e.Who, e.Data.Channel));
channel = Irc.Client.GetChannel(e.Data.Channel);
SyncNicknamePanel();
}
void Disconnect()
{
if (Irc.Client == null)
return;
Irc.Client.RfcQuit(Game.Settings.Irc.QuitMessage);
AddChatLine("Disconnecting from {0}...".F(Irc.Client.Address));
if (Irc.Client.IsConnected)
Irc.Client.Disconnect();
nicknamePanel.RemoveChildren();
Game.Settings.Irc.ConnectAutomatically = false;
Irc.Client = null;
MaybeShowConnectPanel();
}
}
}

View File

@@ -135,6 +135,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
showIncompatibleCheckbox.OnClick = () => { showIncompatible ^= true; RefreshServerList(); }; showIncompatibleCheckbox.OnClick = () => { showIncompatible ^= true; RefreshServerList(); };
} }
try
{
Game.LoadWidget(null, "SERVERBROWSER_IRC", panel.Get("IRC_ROOT"), new WidgetArgs());
}
catch
{
Log.Write("debug", "Failed to load server browser IRC chrome layout");
}
RefreshServerList(); RefreshServerList();
if (directConnectHost != null) if (directConnectHost != null)

70
mods/cnc/chrome/irc.yaml Normal file
View File

@@ -0,0 +1,70 @@
Container@SERVERBROWSER_IRC:
Logic: IrcLogic
Width: 700
Height: 250
Children:
Container@IRC_CONTAINER:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
ScrollPanel@HISTORY_PANEL:
Width: 565
Height: PARENT_BOTTOM - 30
ItemSpacing: 5
Label@HISTORY_TEMPLATE:
X: 5
Width: 530
Height: 25
WordWrap: True
TextField@INPUT_BOX:
Y: PARENT_BOTTOM - 25
Width: 565
Height: 25
ScrollPanel@NICKNAME_PANEL:
X: 570
Width: 130
Height: PARENT_BOTTOM - 30
Label@NICKNAME_TEMPLATE:
X: 5
Button@DISCONNECT_BUTTON:
X: 570
Y: PARENT_BOTTOM - 25
Width: 130
Height: 25
Text: Disconnect
Font: Bold
Background@IRC_CONNECT_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background: scrollpanel-bg
Children:
Label@GLOBAL_CHAT_LABEL:
Y: PARENT_BOTTOM / 4
Width: PARENT_RIGHT
Align: Center
Text: Global Chat
Font: Bold
Label@NICKNAME_LABEL:
X: 200
Y: PARENT_BOTTOM / 4 + 35
Text: Nickname:
TextField@NICKNAME_BOX:
X: 270
Y: PARENT_BOTTOM / 4 + 25
Width: 150
Height: 25
Checkbox@CONNECT_AUTOMATICALLY_CHECKBOX:
X: 270
Y: PARENT_BOTTOM / 4 + 75
Height: 20
Width: 180
Font: Regular
Text: Connect Automatically
Button@CONNECT_BUTTON:
X: 430
Y: PARENT_BOTTOM / 4 + 25
Width: 100
Height: 25
Text: Connect
Font: Bold

View File

@@ -1,74 +1,31 @@
Container@SERVERBROWSER_PANEL: Container@SERVERBROWSER_PANEL:
Logic: ServerBrowserLogic Logic: ServerBrowserLogic
X: (WINDOW_RIGHT - WIDTH)/2 X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - 500)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 730 Width: 730
Height: 535 Height: 595
Children: Children:
Label@TITLE: Label@TITLE:
Text: Multiplayer Text: Multiplayer
Width: 740 Width: 740
Y: 0-25 Y: 0-10
Font: BigBold Font: BigBold
Contrast: true Contrast: true
Align: Center Align: Center
Background@bg: Background@bg:
Width: 730 Width: 730
Height: 500 Height: PARENT_BOTTOM - 30
Background: panel-black Background: panel-black
Y: 15
Children: Children:
Label@SHOW_LABEL_TITLE: Container@IRC_ROOT:
X: 20
Y: 465
Width: 20
Height: 25
Text: Show:
Font: Bold
Checkbox@WAITING_FOR_PLAYERS:
X: 80
Y: 467
Width: 100
Height: 20
Text: Waiting
TextColor: 50,205,50
Checkbox@EMPTY:
X: 180
Y: 467
Width: 100
Height: 20
Text: Empty
Checkbox@PASSWORD_PROTECTED:
X: 270
Y: 467
Width: 100
Height: 20
Text: Protected
TextColor: 255,0,0
Checkbox@ALREADY_STARTED:
X: 385
Y: 467
Width: 100
Height: 20
Text: Started
TextColor: 255,165,0
Checkbox@INCOMPATIBLE_VERSION:
X: 480
Y: 467
Width: 100
Height: 20
Text: Incompatible
TextColor: 190,190,190
Button@REFRESH_BUTTON:
X: PARENT_RIGHT - WIDTH - 15
Y: 465
Width: 100
Height: 25
Text: Refresh
ScrollPanel@SERVER_LIST:
X: 15 X: 15
Y: 15 Y: 15
ScrollPanel@SERVER_LIST:
X: 15
Y: 280
Width: 700 Width: 700
Height: 440 Height: 240
Children: Children:
ScrollItem@HEADER_TEMPLATE: ScrollItem@HEADER_TEMPLATE:
Width: PARENT_RIGHT-27 Width: PARENT_RIGHT-27
@@ -129,35 +86,82 @@ Container@SERVERBROWSER_PANEL:
Height: 25 Height: 25
Label@PROGRESS_LABEL: Label@PROGRESS_LABEL:
X: (PARENT_RIGHT - WIDTH) / 2 X: (PARENT_RIGHT - WIDTH) / 2
Y: PARENT_BOTTOM / 2 - HEIGHT Y: PARENT_BOTTOM / 2 - HEIGHT + (280 / 2)
Width: 710 Width: 710
Height: 25 Height: 25
Font: Bold Font: Bold
Align: Center Align: Center
Visible: false Visible: false
Label@SHOW_LABEL_TITLE:
X: 20
Y: 525
Width: 20
Height: 25
Text: Show:
Font: Bold
Checkbox@WAITING_FOR_PLAYERS:
X: 80
Y: 527
Width: 100
Height: 20
Text: Waiting
TextColor: 50,205,50
Checkbox@EMPTY:
X: 180
Y: 527
Width: 100
Height: 20
Text: Empty
Checkbox@PASSWORD_PROTECTED:
X: 270
Y: 527
Width: 100
Height: 20
Text: Protected
TextColor: 255,0,0
Checkbox@ALREADY_STARTED:
X: 385
Y: 527
Width: 100
Height: 20
Text: Started
TextColor: 255,165,0
Checkbox@INCOMPATIBLE_VERSION:
X: 480
Y: 527
Width: 100
Height: 20
Text: Incompatible
TextColor: 190,190,190
Button@REFRESH_BUTTON:
X: PARENT_RIGHT - WIDTH - 15
Y: 525
Width: 100
Height: 25
Text: Refresh
Button@BACK_BUTTON: Button@BACK_BUTTON:
Key: escape Key: escape
X: 0 X: 0
Y: 499 Y: PARENT_BOTTOM - 16
Width: 140 Width: 140
Height: 35 Height: 35
Text: Back Text: Back
Button@CREATE_BUTTON: Button@CREATE_BUTTON:
X: PARENT_RIGHT - 140 - 10 - 140 - 10 - 140 X: PARENT_RIGHT - 140 - 10 - 140 - 10 - 140
Y: 499 Y: PARENT_BOTTOM - 16
Width: 140 Width: 140
Height: 35 Height: 35
Text: Create Text: Create
Button@DIRECTCONNECT_BUTTON: Button@DIRECTCONNECT_BUTTON:
X: PARENT_RIGHT - 140 - 10 - 140 X: PARENT_RIGHT - 140 - 10 - 140
Y: 499 Y: PARENT_BOTTOM - 16
Width: 140 Width: 140
Height: 35 Height: 35
Text: Direct IP Text: Direct IP
Button@JOIN_BUTTON: Button@JOIN_BUTTON:
Key: return Key: return
X: PARENT_RIGHT - 140 X: PARENT_RIGHT - 140
Y: 499 Y: PARENT_BOTTOM - 16
Width: 140 Width: 140
Height: 35 Height: 35
Text: Join Text: Join

View File

@@ -120,6 +120,7 @@ ChromeLayout:
./mods/cnc/chrome/assetbrowser.yaml ./mods/cnc/chrome/assetbrowser.yaml
./mods/cnc/chrome/missionbrowser.yaml ./mods/cnc/chrome/missionbrowser.yaml
./mods/cnc/chrome/editor.yaml ./mods/cnc/chrome/editor.yaml
./mods/cnc/chrome/irc.yaml
Voices: Voices:
./mods/cnc/audio/voices.yaml ./mods/cnc/audio/voices.yaml

View File

@@ -102,6 +102,7 @@ ChromeLayout:
./mods/d2k/chrome/missionbrowser.yaml ./mods/d2k/chrome/missionbrowser.yaml
./mods/ra/chrome/confirmation-dialogs.yaml ./mods/ra/chrome/confirmation-dialogs.yaml
./mods/ra/chrome/editor.yaml ./mods/ra/chrome/editor.yaml
./mods/ra/chrome/irc.yaml
Weapons: Weapons:
./mods/d2k/weapons.yaml ./mods/d2k/weapons.yaml

69
mods/ra/chrome/irc.yaml Normal file
View File

@@ -0,0 +1,69 @@
Container@SERVERBROWSER_IRC:
Logic: IrcLogic
Width: 700
Height: 250
Children:
Container@IRC_CONTAINER:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Children:
ScrollPanel@HISTORY_PANEL:
Width: 565
Height: PARENT_BOTTOM - 30
ItemSpacing: 5
Label@HISTORY_TEMPLATE:
X: 5
Width: 530
Height: 25
WordWrap: True
TextField@INPUT_BOX:
Y: PARENT_BOTTOM - 25
Width: 565
Height: 25
ScrollPanel@NICKNAME_PANEL:
X: 570
Width: 130
Height: PARENT_BOTTOM - 30
Label@NICKNAME_TEMPLATE:
X: 5
Button@DISCONNECT_BUTTON:
X: 570
Y: PARENT_BOTTOM - 25
Width: 130
Height: 25
Text: Disconnect
Font: Bold
Background@IRC_CONNECT_BG:
Width: PARENT_RIGHT
Height: PARENT_BOTTOM
Background: scrollpanel-bg
Children:
Label@GLOBAL_CHAT_LABEL:
Y: PARENT_BOTTOM / 4
Width: PARENT_RIGHT
Align: Center
Text: Global Chat
Font: Bold
Label@NICKNAME_LABEL:
X: 200
Y: PARENT_BOTTOM / 4 + 35
Text: Nickname:
TextField@NICKNAME_BOX:
X: 270
Y: PARENT_BOTTOM / 4 + 25
Width: 150
Height: 25
Checkbox@CONNECT_AUTOMATICALLY_CHECKBOX:
X: 270
Y: PARENT_BOTTOM / 4 + 75
Height: 20
Width: 180
Text: Connect Automatically
Button@CONNECT_BUTTON:
X: 430
Y: PARENT_BOTTOM / 4 + 25
Width: 100
Height: 25
Text: Connect
Font: Bold

View File

@@ -3,7 +3,7 @@ Background@SERVERBROWSER_PANEL:
X: (WINDOW_RIGHT - WIDTH)/2 X: (WINDOW_RIGHT - WIDTH)/2
Y: (WINDOW_BOTTOM - HEIGHT)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2
Width: 740 Width: 740
Height: 500 Height: 645
Children: Children:
Label@MULTIPLAYER_LABEL_TITLE: Label@MULTIPLAYER_LABEL_TITLE:
X: 0 X: 0
@@ -58,7 +58,7 @@ Background@SERVERBROWSER_PANEL:
X: 20 X: 20
Y: 80 Y: 80
Width: 700 Width: 700
Height: 360 Height: 240
Children: Children:
ScrollItem@HEADER_TEMPLATE: ScrollItem@HEADER_TEMPLATE:
BaseName: scrollheader BaseName: scrollheader
@@ -118,6 +118,10 @@ Background@SERVERBROWSER_PANEL:
Y: 40 Y: 40
Align: Right Align: Right
Height: 25 Height: 25
Container@IRC_ROOT:
X: 20
Y: 370
Width: 260
Label@PROGRESS_LABEL: Label@PROGRESS_LABEL:
X: (PARENT_RIGHT - WIDTH) / 2 X: (PARENT_RIGHT - WIDTH) / 2
Y: PARENT_BOTTOM / 2 - HEIGHT Y: PARENT_BOTTOM / 2 - HEIGHT
@@ -127,28 +131,28 @@ Background@SERVERBROWSER_PANEL:
Align: Center Align: Center
Button@REFRESH_BUTTON: Button@REFRESH_BUTTON:
X: 20 X: 20
Y: PARENT_BOTTOM - 45 Y: 325
Width: 100 Width: 100
Height: 25 Height: 25
Text: Refresh Text: Refresh
Font: Bold Font: Bold
Button@CREATE_BUTTON: Button@CREATE_BUTTON:
X: PARENT_RIGHT - 120 - 120 - 120 - 120 X: PARENT_RIGHT - 120 - 120 - 120 - 120
Y: PARENT_BOTTOM - 45 Y: 325
Width: 100 Width: 100
Height: 25 Height: 25
Text: Create Text: Create
Font: Bold Font: Bold
Button@DIRECTCONNECT_BUTTON: Button@DIRECTCONNECT_BUTTON:
X: PARENT_RIGHT - 120 - 120 - 120 X: PARENT_RIGHT - 120 - 120 - 120
Y: PARENT_BOTTOM - 45 Y: 325
Width: 100 Width: 100
Height: 25 Height: 25
Text: Direct IP Text: Direct IP
Font: Bold Font: Bold
Button@JOIN_BUTTON: Button@JOIN_BUTTON:
X: PARENT_RIGHT - 120 - 120 X: PARENT_RIGHT - 120 - 120
Y: PARENT_BOTTOM - 45 Y: 325
Width: 100 Width: 100
Height: 25 Height: 25
Text: Join Text: Join
@@ -156,7 +160,7 @@ Background@SERVERBROWSER_PANEL:
Key: return Key: return
Button@BACK_BUTTON: Button@BACK_BUTTON:
X: PARENT_RIGHT - 120 X: PARENT_RIGHT - 120
Y: PARENT_BOTTOM - 45 Y: 325
Width: 100 Width: 100
Height: 25 Height: 25
Text: Cancel Text: Cancel

View File

@@ -114,6 +114,7 @@ ChromeLayout:
./mods/ra/chrome/missionbrowser.yaml ./mods/ra/chrome/missionbrowser.yaml
./mods/ra/chrome/confirmation-dialogs.yaml ./mods/ra/chrome/confirmation-dialogs.yaml
./mods/ra/chrome/editor.yaml ./mods/ra/chrome/editor.yaml
./mods/ra/chrome/irc.yaml
Weapons: Weapons:
./mods/ra/weapons/explosions.yaml ./mods/ra/weapons/explosions.yaml

View File

@@ -168,6 +168,7 @@ ChromeLayout:
./mods/ra/chrome/missionbrowser.yaml ./mods/ra/chrome/missionbrowser.yaml
./mods/ra/chrome/confirmation-dialogs.yaml ./mods/ra/chrome/confirmation-dialogs.yaml
./mods/ra/chrome/editor.yaml ./mods/ra/chrome/editor.yaml
./mods/ra/chrome/irc.yaml
Voices: Voices:
./mods/ts/audio/voices.yaml ./mods/ts/audio/voices.yaml

View File

@@ -67,6 +67,9 @@ cp thirdparty/download/MaxMind.GeoIP2.dll packaging/built
cp thirdparty/download/Newtonsoft.Json.dll packaging/built cp thirdparty/download/Newtonsoft.Json.dll packaging/built
cp thirdparty/download/RestSharp.dll packaging/built cp thirdparty/download/RestSharp.dll packaging/built
# global chat
cp thirdparty/download/SmarIrc4net.dll packaging/built
# Copy game icon for windows package # Copy game icon for windows package
cp OpenRA.Game/OpenRA.ico packaging/built cp OpenRA.Game/OpenRA.ico packaging/built

View File

@@ -104,6 +104,7 @@ Section "Game" GAME
File "${SRCDIR}\RestSharp.dll" File "${SRCDIR}\RestSharp.dll"
File "${SRCDIR}\GeoLite2-Country.mmdb.gz" File "${SRCDIR}\GeoLite2-Country.mmdb.gz"
File "${SRCDIR}\eluant.dll" File "${SRCDIR}\eluant.dll"
File "${SRCDIR}\SmarIrc4net.dll"
File "${DEPSDIR}\soft_oal.dll" File "${DEPSDIR}\soft_oal.dll"
File "${DEPSDIR}\SDL2.dll" File "${DEPSDIR}\SDL2.dll"
File "${DEPSDIR}\freetype6.dll" File "${DEPSDIR}\freetype6.dll"
@@ -214,6 +215,7 @@ Function ${UN}Clean
Delete $INSTDIR\eluant.dll Delete $INSTDIR\eluant.dll
Delete $INSTDIR\freetype6.dll Delete $INSTDIR\freetype6.dll
Delete $INSTDIR\SDL2-CS.dll Delete $INSTDIR\SDL2-CS.dll
Delete $INSTDIR\SmarIrc4net.dll
RMDir /r $INSTDIR\Support RMDir /r $INSTDIR\Support
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenRA" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenRA"

View File

@@ -137,4 +137,12 @@ if (!(Test-Path "GeoLite2-Country.mmdb.gz") -Or (((get-date) - (get-item "GeoLit
(New-Object System.Net.WebClient).DownloadFile("http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz", $target) (New-Object System.Net.WebClient).DownloadFile("http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz", $target)
} }
if (!(Test-Path "SmarIrc4net.dll"))
{
echo "Fetching SmartIrc4net from NuGet."
./nuget.exe install SmartIrc4net -Version 0.4.5.1 -ExcludeVersion
cp SmartIrc4net/lib/net40/SmarIrc4net.* .
rmdir SmartIrc4net -Recurse
}
cd .. cd ..

View File

@@ -101,3 +101,10 @@ if [ ! -f Eluant.dll ]; then
echo "Fetching Eluant from GitHub." echo "Fetching Eluant from GitHub."
curl -s -L -O https://github.com/OpenRA/Eluant/releases/download/20140425/Eluant.dll curl -s -L -O https://github.com/OpenRA/Eluant/releases/download/20140425/Eluant.dll
fi fi
if [ ! -f SmarIrc4net.dll ]; then
echo "Fetching SmartIrc4net from NuGet."
get SmartIrc4net 0.4.5.1
cp ./SmartIrc4net/lib/net40/SmarIrc4net* .
rm -rf SmartIrc4net
fi