Add Discord Rich Presence
This commit is contained in:
6
AUTHORS
6
AUTHORS
@@ -180,6 +180,12 @@ Krueger and distributed under the GNU GPL terms.
|
|||||||
Using rix0rrr.BeaconLib developed by Rico Huijbers
|
Using rix0rrr.BeaconLib developed by Rico Huijbers
|
||||||
distributed under MIT License.
|
distributed under MIT License.
|
||||||
|
|
||||||
|
Using DiscordRichPresence developed by Lachee
|
||||||
|
distributed under MIT License.
|
||||||
|
|
||||||
|
Using Json.NET developed by James Newton-King
|
||||||
|
distributed under MIT License.
|
||||||
|
|
||||||
This site or product includes IP2Location LITE data
|
This site or product includes IP2Location LITE data
|
||||||
available from http://www.ip2location.com.
|
available from http://www.ip2location.com.
|
||||||
|
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -39,7 +39,7 @@
|
|||||||
WHITELISTED_OPENRA_ASSEMBLIES = OpenRA.Game.exe OpenRA.Utility.exe OpenRA.Platforms.Default.dll OpenRA.Mods.Common.dll OpenRA.Mods.Cnc.dll OpenRA.Mods.D2k.dll OpenRA.Game.dll
|
WHITELISTED_OPENRA_ASSEMBLIES = OpenRA.Game.exe OpenRA.Utility.exe OpenRA.Platforms.Default.dll OpenRA.Mods.Common.dll OpenRA.Mods.Cnc.dll OpenRA.Mods.D2k.dll OpenRA.Game.dll
|
||||||
|
|
||||||
# These are explicitly shipped alongside our core files by the packaging script
|
# These are explicitly shipped alongside our core files by the packaging script
|
||||||
WHITELISTED_THIRDPARTY_ASSEMBLIES = ICSharpCode.SharpZipLib.dll FuzzyLogicLibrary.dll Eluant.dll BeaconLib.dll Open.Nat.dll SDL2-CS.dll OpenAL-CS.Core.dll
|
WHITELISTED_THIRDPARTY_ASSEMBLIES = ICSharpCode.SharpZipLib.dll FuzzyLogicLibrary.dll Eluant.dll BeaconLib.dll Open.Nat.dll SDL2-CS.dll OpenAL-CS.Core.dll DiscordRPC.dll Newtonsoft.Json.dll
|
||||||
|
|
||||||
# These are shipped in our custom minimal mono runtime and also available in the full system-installed .NET/mono stack
|
# These are shipped in our custom minimal mono runtime and also available in the full system-installed .NET/mono stack
|
||||||
# This list *must* be kept in sync with the files packaged by the AppImageSupport and OpenRALauncherOSX repositories
|
# This list *must* be kept in sync with the files packaged by the AppImageSupport and OpenRALauncherOSX repositories
|
||||||
@@ -210,6 +210,8 @@ endif
|
|||||||
@$(INSTALL_PROGRAM) FuzzyLogicLibrary.dll "$(DATA_INSTALL_DIR)"
|
@$(INSTALL_PROGRAM) FuzzyLogicLibrary.dll "$(DATA_INSTALL_DIR)"
|
||||||
@$(INSTALL_PROGRAM) Open.Nat.dll "$(DATA_INSTALL_DIR)"
|
@$(INSTALL_PROGRAM) Open.Nat.dll "$(DATA_INSTALL_DIR)"
|
||||||
@$(INSTALL_PROGRAM) BeaconLib.dll "$(DATA_INSTALL_DIR)"
|
@$(INSTALL_PROGRAM) BeaconLib.dll "$(DATA_INSTALL_DIR)"
|
||||||
|
@$(INSTALL_PROGRAM) DiscordRPC.dll "$(DATA_INSTALL_DIR)"
|
||||||
|
@$(INSTALL_PROGRAM) Newtonsoft.Json.dll "$(DATA_INSTALL_DIR)"
|
||||||
|
|
||||||
install-common-mod-files:
|
install-common-mod-files:
|
||||||
@-echo "Installing OpenRA common mod files to $(DATA_INSTALL_DIR)"
|
@-echo "Installing OpenRA common mod files to $(DATA_INSTALL_DIR)"
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Describes what is to be loaded in order to run a mod. </summary>
|
/// <summary> Describes what is to be loaded in order to run a mod. </summary>
|
||||||
public class Manifest
|
public class Manifest : IDisposable
|
||||||
{
|
{
|
||||||
public readonly string Id;
|
public readonly string Id;
|
||||||
public readonly IReadOnlyPackage Package;
|
public readonly IReadOnlyPackage Package;
|
||||||
@@ -241,5 +241,15 @@ namespace OpenRA
|
|||||||
|
|
||||||
return (T)module;
|
return (T)module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var module in modules)
|
||||||
|
{
|
||||||
|
var disposableModule = module as IDisposable;
|
||||||
|
if (disposableModule != null)
|
||||||
|
disposableModule.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ namespace OpenRA
|
|||||||
|
|
||||||
if (ObjectCreator != null)
|
if (ObjectCreator != null)
|
||||||
ObjectCreator.Dispose();
|
ObjectCreator.Dispose();
|
||||||
|
|
||||||
|
Manifest.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
201
OpenRA.Mods.Common/DiscordService.cs
Normal file
201
OpenRA.Mods.Common/DiscordService.cs
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2020 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, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using DiscordRPC;
|
||||||
|
using DiscordRPC.Message;
|
||||||
|
using OpenRA.Network;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common
|
||||||
|
{
|
||||||
|
public enum DiscordState
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
InMenu,
|
||||||
|
InMapEditor,
|
||||||
|
InSkirmishLobby,
|
||||||
|
InMultiplayerLobby,
|
||||||
|
PlayingMultiplayer,
|
||||||
|
WatchingReplay,
|
||||||
|
PlayingCampaign,
|
||||||
|
PlayingSkirmish
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DiscordService : IGlobalModData, IDisposable
|
||||||
|
{
|
||||||
|
public readonly string ApplicationId = null;
|
||||||
|
readonly DiscordRpcClient client;
|
||||||
|
DiscordState currentState;
|
||||||
|
|
||||||
|
static readonly Lazy<DiscordService> Service = Exts.Lazy(() =>
|
||||||
|
{
|
||||||
|
if (!Game.ModData.Manifest.Contains<DiscordService>())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Game.ModData.Manifest.Get<DiscordService>();
|
||||||
|
});
|
||||||
|
|
||||||
|
public DiscordService(MiniYaml yaml)
|
||||||
|
{
|
||||||
|
FieldLoader.Load(this, yaml);
|
||||||
|
|
||||||
|
// HACK: Prevent service from starting when launching the utility or server.
|
||||||
|
if (Game.Renderer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
client = new DiscordRpcClient(ApplicationId, autoEvents: true)
|
||||||
|
{
|
||||||
|
SkipIdenticalPresence = false
|
||||||
|
};
|
||||||
|
|
||||||
|
client.OnJoin += OnJoin;
|
||||||
|
client.OnJoinRequested += OnJoinRequested;
|
||||||
|
|
||||||
|
// HACK: We need to set HasRegisteredUriScheme to bypass the check that is done when calling SetPresence with a joinSecret.
|
||||||
|
// DiscordRpc lib expect us to register uri handlers with RegisterUriScheme(), we are doing it ourselves in our installers/launchers.
|
||||||
|
client.GetType().GetProperty("HasRegisteredUriScheme").SetValue(client, true);
|
||||||
|
|
||||||
|
client.SetSubscription(EventType.Join | EventType.JoinRequest);
|
||||||
|
client.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnJoinRequested(object sender, JoinRequestMessage args)
|
||||||
|
{
|
||||||
|
var client = (DiscordRpcClient)sender;
|
||||||
|
client.Respond(args, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnJoin(object sender, JoinMessage args)
|
||||||
|
{
|
||||||
|
if (currentState != DiscordState.InMenu)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var server = args.Secret.Split('|');
|
||||||
|
Game.RunAfterTick(() =>
|
||||||
|
{
|
||||||
|
Game.RemoteDirectConnect(new ConnectionTarget(server[0], int.Parse(server[1])));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStatus(DiscordState state, string details = null, string secret = null, int? players = null, int? slots = null)
|
||||||
|
{
|
||||||
|
if (currentState == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Service.Value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string stateText;
|
||||||
|
DateTime? timestamp = null;
|
||||||
|
Party party = null;
|
||||||
|
Secrets secrets = null;
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case DiscordState.InMenu:
|
||||||
|
stateText = "In menu";
|
||||||
|
break;
|
||||||
|
case DiscordState.InMapEditor:
|
||||||
|
stateText = "In Map Editor";
|
||||||
|
break;
|
||||||
|
case DiscordState.InSkirmishLobby:
|
||||||
|
stateText = "In Skirmish Lobby";
|
||||||
|
break;
|
||||||
|
case DiscordState.InMultiplayerLobby:
|
||||||
|
stateText = "In Multiplayer Lobby";
|
||||||
|
timestamp = DateTime.UtcNow;
|
||||||
|
party = new Party
|
||||||
|
{
|
||||||
|
ID = Secrets.CreateFriendlySecret(new Random()),
|
||||||
|
Size = players.Value,
|
||||||
|
Max = slots.Value
|
||||||
|
};
|
||||||
|
secrets = new Secrets
|
||||||
|
{
|
||||||
|
JoinSecret = secret
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case DiscordState.PlayingMultiplayer:
|
||||||
|
stateText = "Playing Multiplayer";
|
||||||
|
timestamp = DateTime.UtcNow;
|
||||||
|
break;
|
||||||
|
case DiscordState.PlayingCampaign:
|
||||||
|
stateText = "Playing Campaign";
|
||||||
|
timestamp = DateTime.UtcNow;
|
||||||
|
break;
|
||||||
|
case DiscordState.WatchingReplay:
|
||||||
|
stateText = "Watching Replay";
|
||||||
|
timestamp = DateTime.UtcNow;
|
||||||
|
break;
|
||||||
|
case DiscordState.PlayingSkirmish:
|
||||||
|
stateText = "Playing Skirmish";
|
||||||
|
timestamp = DateTime.UtcNow;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException("state", state, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var richPresence = new RichPresence
|
||||||
|
{
|
||||||
|
Details = details,
|
||||||
|
State = stateText,
|
||||||
|
Assets = new Assets
|
||||||
|
{
|
||||||
|
LargeImageKey = "large",
|
||||||
|
LargeImageText = Game.ModData.Manifest.Metadata.Title,
|
||||||
|
},
|
||||||
|
Timestamps = timestamp.HasValue ? new Timestamps(timestamp.Value) : null,
|
||||||
|
Party = party,
|
||||||
|
Secrets = secrets
|
||||||
|
};
|
||||||
|
|
||||||
|
client.SetPresence(richPresence);
|
||||||
|
currentState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (client != null)
|
||||||
|
client.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateStatus(DiscordState state, string details = null, string secret = null, int? players = null, int? slots = null)
|
||||||
|
{
|
||||||
|
if (Service.Value != null)
|
||||||
|
Service.Value.SetStatus(state, details, secret, players, slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetPlayers(int players, int slots)
|
||||||
|
{
|
||||||
|
if (Service.Value != null)
|
||||||
|
{
|
||||||
|
Service.Value.client.UpdateParty(new Party
|
||||||
|
{
|
||||||
|
ID = Secrets.CreateFriendlySecret(new Random()),
|
||||||
|
Size = players,
|
||||||
|
Max = slots
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdatePlayers(int players, int slots)
|
||||||
|
{
|
||||||
|
if (Service.Value != null)
|
||||||
|
Service.Value.client.UpdatePartySize(players, slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UpdateDetails(string details)
|
||||||
|
{
|
||||||
|
if (Service.Value != null)
|
||||||
|
Service.Value.client.UpdateDetails(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
<Private>False</Private>
|
<Private>False</Private>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<PackageReference Include="OpenRA-FuzzyLogicLibrary" Version="1.0.1" />
|
<PackageReference Include="OpenRA-FuzzyLogicLibrary" Version="1.0.1" />
|
||||||
|
<PackageReference Include="DiscordRichPresence" Version="1.0.150" />
|
||||||
<PackageReference Include="rix0rrr.BeaconLib" Version="1.0.2" />
|
<PackageReference Include="rix0rrr.BeaconLib" Version="1.0.2" />
|
||||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
|
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />
|
||||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
bool addBotOnMapLoad;
|
bool addBotOnMapLoad;
|
||||||
bool disableTeamChat;
|
bool disableTeamChat;
|
||||||
bool teamChat;
|
bool teamChat;
|
||||||
|
bool updateDiscordStatus = true;
|
||||||
|
|
||||||
readonly string chatLineSound = ChromeMetrics.Get<string>("ChatLineSound");
|
readonly string chatLineSound = ChromeMetrics.Get<string>("ChatLineSound");
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
orderManager.AddChatLine += AddChatLine;
|
orderManager.AddChatLine += AddChatLine;
|
||||||
Game.LobbyInfoChanged += UpdateCurrentMap;
|
Game.LobbyInfoChanged += UpdateCurrentMap;
|
||||||
Game.LobbyInfoChanged += UpdatePlayerList;
|
Game.LobbyInfoChanged += UpdatePlayerList;
|
||||||
|
Game.LobbyInfoChanged += UpdateDiscordStatus;
|
||||||
Game.BeforeGameStart += OnGameStart;
|
Game.BeforeGameStart += OnGameStart;
|
||||||
Game.ConnectionStateChanged += ConnectionStateChanged;
|
Game.ConnectionStateChanged += ConnectionStateChanged;
|
||||||
|
|
||||||
@@ -462,6 +464,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
orderManager.AddChatLine -= AddChatLine;
|
orderManager.AddChatLine -= AddChatLine;
|
||||||
Game.LobbyInfoChanged -= UpdateCurrentMap;
|
Game.LobbyInfoChanged -= UpdateCurrentMap;
|
||||||
Game.LobbyInfoChanged -= UpdatePlayerList;
|
Game.LobbyInfoChanged -= UpdatePlayerList;
|
||||||
|
Game.LobbyInfoChanged -= UpdateDiscordStatus;
|
||||||
Game.BeforeGameStart -= OnGameStart;
|
Game.BeforeGameStart -= OnGameStart;
|
||||||
Game.ConnectionStateChanged -= ConnectionStateChanged;
|
Game.ConnectionStateChanged -= ConnectionStateChanged;
|
||||||
}
|
}
|
||||||
@@ -743,9 +746,56 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
|
tabCompletion.Names = orderManager.LobbyInfo.Clients.Select(c => c.Name).Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateDiscordStatus()
|
||||||
|
{
|
||||||
|
var mapTitle = map.Title;
|
||||||
|
var numberOfPlayers = 0;
|
||||||
|
var slots = 0;
|
||||||
|
|
||||||
|
if (!skirmishMode)
|
||||||
|
{
|
||||||
|
foreach (var kv in orderManager.LobbyInfo.Slots)
|
||||||
|
{
|
||||||
|
if (kv.Value.Closed)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
slots++;
|
||||||
|
var client = orderManager.LobbyInfo.ClientInSlot(kv.Key);
|
||||||
|
|
||||||
|
if (client != null)
|
||||||
|
numberOfPlayers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateDiscordStatus)
|
||||||
|
{
|
||||||
|
string secret = null;
|
||||||
|
if (orderManager.LobbyInfo.GlobalSettings.Dedicated)
|
||||||
|
{
|
||||||
|
var endpoint = orderManager.Endpoint.GetConnectEndPoints().First();
|
||||||
|
secret = string.Concat(endpoint.Address, "|", endpoint.Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = skirmishMode ? DiscordState.InSkirmishLobby : DiscordState.InMultiplayerLobby;
|
||||||
|
DiscordService.UpdateStatus(state, mapTitle, secret, numberOfPlayers, slots);
|
||||||
|
|
||||||
|
updateDiscordStatus = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!skirmishMode)
|
||||||
|
DiscordService.UpdatePlayers(numberOfPlayers, slots);
|
||||||
|
DiscordService.UpdateDetails(mapTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OnGameStart()
|
void OnGameStart()
|
||||||
{
|
{
|
||||||
Ui.CloseWindow();
|
Ui.CloseWindow();
|
||||||
|
|
||||||
|
var state = skirmishMode ? DiscordState.PlayingSkirmish : DiscordState.PlayingMultiplayer;
|
||||||
|
DiscordService.UpdateStatus(state);
|
||||||
|
|
||||||
onStart();
|
onStart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
menuType = type;
|
menuType = type;
|
||||||
|
|
||||||
|
DiscordService.UpdateStatus(DiscordState.InMenu);
|
||||||
|
|
||||||
// Update button mouseover
|
// Update button mouseover
|
||||||
Game.RunAfterTick(Ui.ResetTooltips);
|
Game.RunAfterTick(Ui.ResetTooltips);
|
||||||
}
|
}
|
||||||
@@ -258,6 +260,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
onIntroductionComplete();
|
onIntroductionComplete();
|
||||||
|
|
||||||
Game.OnShellmapLoaded += OpenMenuBasedOnLastGame;
|
Game.OnShellmapLoaded += OpenMenuBasedOnLastGame;
|
||||||
|
|
||||||
|
DiscordService.UpdateStatus(DiscordState.InMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadAndDisplayNews(string newsURL, Widget newsBG)
|
void LoadAndDisplayNews(string newsURL, Widget newsBG)
|
||||||
@@ -317,6 +321,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
() => { Game.LoadEditor(uid); },
|
() => { Game.LoadEditor(uid); },
|
||||||
() => { Game.CloseServer(); SwitchMenu(MenuType.MapEditor); });
|
() => { Game.CloseServer(); SwitchMenu(MenuType.MapEditor); });
|
||||||
|
|
||||||
|
DiscordService.UpdateStatus(DiscordState.InMapEditor);
|
||||||
|
|
||||||
lastGameState = MenuPanel.MapEditor;
|
lastGameState = MenuPanel.MapEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,6 +164,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
void OnGameStart()
|
void OnGameStart()
|
||||||
{
|
{
|
||||||
Ui.CloseWindow();
|
Ui.CloseWindow();
|
||||||
|
|
||||||
|
DiscordService.UpdateStatus(DiscordState.PlayingCampaign);
|
||||||
|
|
||||||
onStart();
|
onStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
});
|
});
|
||||||
|
|
||||||
Game.Disconnect();
|
Game.Disconnect();
|
||||||
|
|
||||||
|
DiscordService.UpdateStatus(DiscordState.InMenu);
|
||||||
};
|
};
|
||||||
|
|
||||||
Game.OpenWindow("SERVER_LOBBY", new WidgetArgs
|
Game.OpenWindow("SERVER_LOBBY", new WidgetArgs
|
||||||
|
|||||||
@@ -688,6 +688,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
if (selectedReplay != null && ReplayUtils.PromptConfirmReplayCompatibility(selectedReplay))
|
if (selectedReplay != null && ReplayUtils.PromptConfirmReplayCompatibility(selectedReplay))
|
||||||
{
|
{
|
||||||
cancelLoadingReplays = true;
|
cancelLoadingReplays = true;
|
||||||
|
|
||||||
|
DiscordService.UpdateStatus(DiscordState.WatchingReplay);
|
||||||
|
|
||||||
Game.JoinReplay(selectedReplay.FilePath);
|
Game.JoinReplay(selectedReplay.FilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,3 +32,6 @@ SpriteFormats:
|
|||||||
SpriteSequenceFormat: DefaultSpriteSequence
|
SpriteSequenceFormat: DefaultSpriteSequence
|
||||||
|
|
||||||
ModelSequenceFormat: PlaceholderModelSequence
|
ModelSequenceFormat: PlaceholderModelSequence
|
||||||
|
|
||||||
|
DiscordService:
|
||||||
|
ApplicationId: 699222659766026240
|
||||||
|
|||||||
@@ -288,3 +288,6 @@ ModContent:
|
|||||||
cnc|installer/gdi95.yaml
|
cnc|installer/gdi95.yaml
|
||||||
cnc|installer/nod95.yaml
|
cnc|installer/nod95.yaml
|
||||||
cnc|installer/origin.yaml
|
cnc|installer/origin.yaml
|
||||||
|
|
||||||
|
DiscordService:
|
||||||
|
ApplicationId: 699223250181292033
|
||||||
|
|||||||
@@ -264,3 +264,6 @@ ModContent:
|
|||||||
d2k|installer/d2k-e.yaml
|
d2k|installer/d2k-e.yaml
|
||||||
d2k|installer/downloads.yaml
|
d2k|installer/downloads.yaml
|
||||||
d2k|installer/gruntmods.yaml
|
d2k|installer/gruntmods.yaml
|
||||||
|
|
||||||
|
DiscordService:
|
||||||
|
ApplicationId: 712711732770111550
|
||||||
|
|||||||
@@ -305,3 +305,6 @@ ModContent:
|
|||||||
ra|installer/firstdecade.yaml
|
ra|installer/firstdecade.yaml
|
||||||
ra|installer/origin.yaml
|
ra|installer/origin.yaml
|
||||||
ra|installer/soviet95.yaml
|
ra|installer/soviet95.yaml
|
||||||
|
|
||||||
|
DiscordService:
|
||||||
|
ApplicationId: 699222659766026240
|
||||||
|
|||||||
@@ -323,3 +323,6 @@ ModContent:
|
|||||||
ts|installer/firstdecade.yaml
|
ts|installer/firstdecade.yaml
|
||||||
ts|installer/origin.yaml
|
ts|installer/origin.yaml
|
||||||
ts|installer/tibsun.yaml
|
ts|installer/tibsun.yaml
|
||||||
|
|
||||||
|
DiscordService:
|
||||||
|
ApplicationId: 712713986558394399
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ rm -rf libs mono.tar.bz2
|
|||||||
build_appimage() {
|
build_appimage() {
|
||||||
MOD_ID=${1}
|
MOD_ID=${1}
|
||||||
DISPLAY_NAME=${2}
|
DISPLAY_NAME=${2}
|
||||||
|
DISCORD_ID=${3}
|
||||||
APPDIR="$(pwd)/${MOD_ID}.appdir"
|
APPDIR="$(pwd)/${MOD_ID}.appdir"
|
||||||
APPIMAGE="OpenRA-$(echo "${DISPLAY_NAME}" | sed 's/ /-/g')${SUFFIX}-x86_64.AppImage"
|
APPIMAGE="OpenRA-$(echo "${DISPLAY_NAME}" | sed 's/ /-/g')${SUFFIX}-x86_64.AppImage"
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ build_appimage() {
|
|||||||
sed "s/{MODID}/${MOD_ID}/g" AppRun.in | sed "s/{MODNAME}/${DISPLAY_NAME}/g" > AppRun.temp
|
sed "s/{MODID}/${MOD_ID}/g" AppRun.in | sed "s/{MODNAME}/${DISPLAY_NAME}/g" > AppRun.temp
|
||||||
install -m 0755 AppRun.temp "${APPDIR}/AppRun"
|
install -m 0755 AppRun.temp "${APPDIR}/AppRun"
|
||||||
|
|
||||||
sed "s/{MODID}/${MOD_ID}/g" openra.desktop.in | sed "s/{MODNAME}/${DISPLAY_NAME}/g" | sed "s/{TAG}/${TAG}/g" > temp.desktop
|
sed "s/{MODID}/${MOD_ID}/g" openra.desktop.in | sed "s/{MODNAME}/${DISPLAY_NAME}/g" | sed "s/{TAG}/${TAG}/g" | sed "s/{DISCORDAPPID}/${DISCORD_ID}/g" > temp.desktop
|
||||||
echo "StartupWMClass=openra-${MOD_ID}-${TAG}" >> temp.desktop
|
echo "StartupWMClass=openra-${MOD_ID}-${TAG}" >> temp.desktop
|
||||||
|
|
||||||
install -Dm 0755 temp.desktop "${APPDIR}/usr/share/applications/openra-${MOD_ID}.desktop"
|
install -Dm 0755 temp.desktop "${APPDIR}/usr/share/applications/openra-${MOD_ID}.desktop"
|
||||||
@@ -154,9 +155,9 @@ build_appimage() {
|
|||||||
rm -rf "${APPDIR}"
|
rm -rf "${APPDIR}"
|
||||||
}
|
}
|
||||||
|
|
||||||
build_appimage "ra" "Red Alert"
|
build_appimage "ra" "Red Alert" "699222659766026240"
|
||||||
build_appimage "cnc" "Tiberian Dawn"
|
build_appimage "cnc" "Tiberian Dawn" "699223250181292033"
|
||||||
build_appimage "d2k" "Dune 2000"
|
build_appimage "d2k" "Dune 2000" "712711732770111550"
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
rm -rf openra-mod.temp openra-mod-server.temp openra-mod-utility.temp temp.desktop temp.xml AppRun.temp appimagetool-x86_64.AppImage squashfs-root "${BUILTDIR}"
|
rm -rf openra-mod.temp openra-mod-server.temp openra-mod-utility.temp temp.desktop temp.xml AppRun.temp appimagetool-x86_64.AppImage squashfs-root "${BUILTDIR}"
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ Icon=openra-{MODID}
|
|||||||
Exec=openra-{MODID} %U
|
Exec=openra-{MODID} %U
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Categories=Game;StrategyGame;
|
Categories=Game;StrategyGame;
|
||||||
MimeType=x-scheme-handler/openra-{MODID}-{TAG};
|
MimeType=x-scheme-handler/openra-{MODID}-{TAG};x-scheme-handler/discord-{DISCORDAPPID};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
# MACOS_DEVELOPER_PASSWORD: App-specific password for the developer account
|
# MACOS_DEVELOPER_PASSWORD: App-specific password for the developer account
|
||||||
#
|
#
|
||||||
|
|
||||||
LAUNCHER_TAG="osx-launcher-20200328"
|
LAUNCHER_TAG="osx-launcher-20200525"
|
||||||
|
|
||||||
if [ $# -ne "2" ]; then
|
if [ $# -ne "2" ]; then
|
||||||
echo "Usage: $(basename "$0") tag outputdir"
|
echo "Usage: $(basename "$0") tag outputdir"
|
||||||
@@ -54,6 +54,7 @@ populate_bundle() {
|
|||||||
TEMPLATE_DIR="${BUILTDIR}/${1}"
|
TEMPLATE_DIR="${BUILTDIR}/${1}"
|
||||||
MOD_ID=${2}
|
MOD_ID=${2}
|
||||||
MOD_NAME=${3}
|
MOD_NAME=${3}
|
||||||
|
DISCORD_APPID=${4}
|
||||||
cp -r "${BUILTDIR}/OpenRA.app" "${TEMPLATE_DIR}"
|
cp -r "${BUILTDIR}/OpenRA.app" "${TEMPLATE_DIR}"
|
||||||
|
|
||||||
# Assemble multi-resolution icon
|
# Assemble multi-resolution icon
|
||||||
@@ -63,6 +64,7 @@ populate_bundle() {
|
|||||||
modify_plist "{MOD_ID}" "${MOD_ID}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
modify_plist "{MOD_ID}" "${MOD_ID}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||||
modify_plist "{MOD_NAME}" "${MOD_NAME}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
modify_plist "{MOD_NAME}" "${MOD_NAME}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||||
modify_plist "{JOIN_SERVER_URL_SCHEME}" "openra-${MOD_ID}-${TAG}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
modify_plist "{JOIN_SERVER_URL_SCHEME}" "openra-${MOD_ID}-${TAG}" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||||
|
modify_plist "{ADDITIONAL_URL_SCHEMES}" "<string>discord-${DISCORD_APPID}</string>" "${TEMPLATE_DIR}/Contents/Info.plist"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Deletes from the first argument's mod dirs all the later arguments
|
# Deletes from the first argument's mod dirs all the later arguments
|
||||||
@@ -98,15 +100,15 @@ make install-core gameinstalldir="/Contents/Resources/" DESTDIR="${BUILTDIR}/Ope
|
|||||||
make install-dependencies TARGETPLATFORM=osx-x64 gameinstalldir="/Contents/Resources/" DESTDIR="${BUILTDIR}/OpenRA.app"
|
make install-dependencies TARGETPLATFORM=osx-x64 gameinstalldir="/Contents/Resources/" DESTDIR="${BUILTDIR}/OpenRA.app"
|
||||||
popd > /dev/null || exit 1
|
popd > /dev/null || exit 1
|
||||||
|
|
||||||
populate_bundle "OpenRA - Red Alert.app" "ra" "Red Alert"
|
populate_bundle "OpenRA - Red Alert.app" "ra" "Red Alert" "699222659766026240"
|
||||||
delete_mods "OpenRA - Red Alert.app" "cnc" "d2k"
|
delete_mods "OpenRA - Red Alert.app" "cnc" "d2k"
|
||||||
sign_bundle "OpenRA - Red Alert.app"
|
sign_bundle "OpenRA - Red Alert.app"
|
||||||
|
|
||||||
populate_bundle "OpenRA - Tiberian Dawn.app" "cnc" "Tiberian Dawn"
|
populate_bundle "OpenRA - Tiberian Dawn.app" "cnc" "Tiberian Dawn" "699223250181292033"
|
||||||
delete_mods "OpenRA - Tiberian Dawn.app" "ra" "d2k"
|
delete_mods "OpenRA - Tiberian Dawn.app" "ra" "d2k"
|
||||||
sign_bundle "OpenRA - Tiberian Dawn.app"
|
sign_bundle "OpenRA - Tiberian Dawn.app"
|
||||||
|
|
||||||
populate_bundle "OpenRA - Dune 2000.app" "d2k" "Dune 2000"
|
populate_bundle "OpenRA - Dune 2000.app" "d2k" "Dune 2000" "712711732770111550"
|
||||||
delete_mods "OpenRA - Dune 2000.app" "ra" "cnc"
|
delete_mods "OpenRA - Dune 2000.app" "ra" "cnc"
|
||||||
sign_bundle "OpenRA - Dune 2000.app"
|
sign_bundle "OpenRA - Dune 2000.app"
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ Var StartMenuFolder
|
|||||||
|
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
|
|
||||||
|
!define RA_DISCORDID 699222659766026240
|
||||||
|
!define CNC_DISCORDID 699223250181292033
|
||||||
|
!define D2K_DISCORDID 712711732770111550
|
||||||
|
|
||||||
;***************************
|
;***************************
|
||||||
;Section Definitions
|
;Section Definitions
|
||||||
;***************************
|
;***************************
|
||||||
@@ -76,16 +80,31 @@ Section "-Reg" Reg
|
|||||||
WriteRegStr HKLM "Software\Classes\openra-ra-${TAG}\DefaultIcon" "" "$INSTDIR\RedAlert.ico,0"
|
WriteRegStr HKLM "Software\Classes\openra-ra-${TAG}\DefaultIcon" "" "$INSTDIR\RedAlert.ico,0"
|
||||||
WriteRegStr HKLM "Software\Classes\openra-ra-${TAG}\Shell\Open\Command" "" "$INSTDIR\RedAlert.exe Launch.URI=%1"
|
WriteRegStr HKLM "Software\Classes\openra-ra-${TAG}\Shell\Open\Command" "" "$INSTDIR\RedAlert.exe Launch.URI=%1"
|
||||||
|
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${RA_DISCORDID}" "" "URL:Run game ${RA_DISCORDID} protocol"
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${RA_DISCORDID}" "URL Protocol" ""
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${RA_DISCORDID}\DefaultIcon" "" "$INSTDIR\RedAlert.ico,0"
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${RA_DISCORDID}\Shell\Open\Command" "" "$INSTDIR\RedAlert.exe"
|
||||||
|
|
||||||
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}" "" "URL:Join OpenRA server"
|
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}" "" "URL:Join OpenRA server"
|
||||||
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}" "URL Protocol" ""
|
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}" "URL Protocol" ""
|
||||||
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}\DefaultIcon" "" "$INSTDIR\TiberianDawn.ico,0"
|
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}\DefaultIcon" "" "$INSTDIR\TiberianDawn.ico,0"
|
||||||
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}\Shell\Open\Command" "" "$INSTDIR\TiberianDawn.exe Launch.URI=%1"
|
WriteRegStr HKLM "Software\Classes\openra-cnc-${TAG}\Shell\Open\Command" "" "$INSTDIR\TiberianDawn.exe Launch.URI=%1"
|
||||||
|
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${CNC_DISCORDID}" "" "URL:Run game ${CNC_DISCORDID} protocol"
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${CNC_DISCORDID}" "URL Protocol" ""
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${CNC_DISCORDID}\DefaultIcon" "" "$INSTDIR\TiberianDawn.ico,0"
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${CNC_DISCORDID}\Shell\Open\Command" "" "$INSTDIR\TiberianDawn.exe"
|
||||||
|
|
||||||
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}" "" "URL:Join OpenRA server"
|
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}" "" "URL:Join OpenRA server"
|
||||||
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}" "URL Protocol" ""
|
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}" "URL Protocol" ""
|
||||||
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}\DefaultIcon" "" "$INSTDIR\Dune2000.ico,0"
|
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}\DefaultIcon" "" "$INSTDIR\Dune2000.ico,0"
|
||||||
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}\Shell\Open\Command" "" "$INSTDIR\Dune2000.exe Launch.URI=%1"
|
WriteRegStr HKLM "Software\Classes\openra-d2k-${TAG}\Shell\Open\Command" "" "$INSTDIR\Dune2000.exe Launch.URI=%1"
|
||||||
|
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${D2K_DISCORDID}" "" "URL:Run game ${D2K_DISCORDID} protocol"
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${D2K_DISCORDID}" "URL Protocol" ""
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${D2K_DISCORDID}\DefaultIcon" "" "$INSTDIR\Dune2000.ico,0"
|
||||||
|
WriteRegStr HKLM "Software\Classes\discord-${D2K_DISCORDID}\Shell\Open\Command" "" "$INSTDIR\Dune2000.exe"
|
||||||
|
|
||||||
; Remove obsolete file associations
|
; Remove obsolete file associations
|
||||||
DeleteRegKey HKLM "Software\Classes\.orarep"
|
DeleteRegKey HKLM "Software\Classes\.orarep"
|
||||||
DeleteRegKey HKLM "Software\Classes\OpenRA_replay"
|
DeleteRegKey HKLM "Software\Classes\OpenRA_replay"
|
||||||
@@ -135,6 +154,8 @@ Section "Game" GAME
|
|||||||
File "${SRCDIR}\eluant.dll"
|
File "${SRCDIR}\eluant.dll"
|
||||||
File "${SRCDIR}\BeaconLib.dll"
|
File "${SRCDIR}\BeaconLib.dll"
|
||||||
File "${SRCDIR}\soft_oal.dll"
|
File "${SRCDIR}\soft_oal.dll"
|
||||||
|
File "${SRCDIR}\DiscordRPC.dll"
|
||||||
|
File "${SRCDIR}\Newtonsoft.Json.dll"
|
||||||
File "${SRCDIR}\SDL2.dll"
|
File "${SRCDIR}\SDL2.dll"
|
||||||
File "${SRCDIR}\freetype6.dll"
|
File "${SRCDIR}\freetype6.dll"
|
||||||
File "${SRCDIR}\lua51.dll"
|
File "${SRCDIR}\lua51.dll"
|
||||||
@@ -254,6 +275,8 @@ Function ${UN}Clean
|
|||||||
Delete $INSTDIR\lua51.dll
|
Delete $INSTDIR\lua51.dll
|
||||||
Delete $INSTDIR\eluant.dll
|
Delete $INSTDIR\eluant.dll
|
||||||
Delete $INSTDIR\freetype6.dll
|
Delete $INSTDIR\freetype6.dll
|
||||||
|
Delete $INSTDIR\DiscordRPC.dll
|
||||||
|
Delete $INSTDIR\Newtonsoft.Json.dll
|
||||||
Delete $INSTDIR\SDL2-CS.dll
|
Delete $INSTDIR\SDL2-CS.dll
|
||||||
Delete $INSTDIR\OpenAL-CS.Core.dll
|
Delete $INSTDIR\OpenAL-CS.Core.dll
|
||||||
Delete $INSTDIR\BeaconLib.dll
|
Delete $INSTDIR\BeaconLib.dll
|
||||||
@@ -264,6 +287,10 @@ Function ${UN}Clean
|
|||||||
DeleteRegKey HKLM "Software\Classes\openra-cnc-${TAG}"
|
DeleteRegKey HKLM "Software\Classes\openra-cnc-${TAG}"
|
||||||
DeleteRegKey HKLM "Software\Classes\openra-d2k-${TAG}"
|
DeleteRegKey HKLM "Software\Classes\openra-d2k-${TAG}"
|
||||||
|
|
||||||
|
DeleteRegKey HKLM "Software\Classes\discord-${RA_DISCORDID}"
|
||||||
|
DeleteRegKey HKLM "Software\Classes\discord-${CNC_DISCORDID}"
|
||||||
|
DeleteRegKey HKLM "Software\Classes\discord-${D2K_DISCORDID}"
|
||||||
|
|
||||||
Delete $INSTDIR\uninstaller.exe
|
Delete $INSTDIR\uninstaller.exe
|
||||||
RMDir $INSTDIR
|
RMDir $INSTDIR
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user