Skip to content

Commit

Permalink
Select & show preferred skill level when making a game (#598)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrantBartlett authored Jan 3, 2025
1 parent f47d5cb commit ff5f14c
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 14 deletions.
2 changes: 2 additions & 0 deletions ClientCore/ClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ private List<TranslationGameFile> ParseTranslationGameFiles()

public string AllowedCustomGameModes => clientDefinitionsIni.GetStringValue(SETTINGS, "AllowedCustomGameModes", "Standard,Custom Map");

public string SkillLevelOptions => clientDefinitionsIni.GetStringValue(SETTINGS, "SkillLevelOptions", "Any,Beginner,Intermediate,Pro");

public string GetGameExecutableName()
{
string[] exeNames = clientDefinitionsIni.GetStringValue(SETTINGS, "GameExecutableNames", "Game.exe").Split(',');
Expand Down
2 changes: 1 addition & 1 deletion ClientCore/ProgramConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static class ProgramConstants

public const string QRES_EXECUTABLE = "qres.dat";

public const string CNCNET_PROTOCOL_REVISION = "R11";
public const string CNCNET_PROTOCOL_REVISION = "R12";
public const string LAN_PROTOCOL_REVISION = "RL7";
public const int LAN_PORT = 1234;
public const int LAN_INGAME_PORT = 1234;
Expand Down
10 changes: 7 additions & 3 deletions DXMainClient/DXGUI/Multiplayer/CnCNet/CnCNetLobby.cs
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ private void _JoinGame(HostedCnCNetGame hg, string password)
}
else
{
gameLobby.SetUp(gameChannel, false, hg.MaxPlayers, hg.TunnelServer, hg.HostName, hg.Passworded);
gameLobby.SetUp(gameChannel, false, hg.MaxPlayers, hg.TunnelServer, hg.HostName, hg.Passworded, hg.SkillLevel);
gameChannel.UserAdded += GameChannel_UserAdded;
gameChannel.InvalidPasswordEntered += GameChannel_InvalidPasswordEntered_NewGame;
gameChannel.InviteOnlyErrorOnJoin += GameChannel_InviteOnlyErrorOnJoin;
Expand Down Expand Up @@ -1049,7 +1049,7 @@ private void Gcw_GameCreated(object sender, GameCreationEventArgs e)

Channel gameChannel = connectionManager.CreateChannel(e.GameRoomName, channelName, false, true, password);
connectionManager.AddChannel(gameChannel);
gameLobby.SetUp(gameChannel, true, e.MaxPlayers, e.Tunnel, ProgramConstants.PLAYERNAME, isCustomPassword);
gameLobby.SetUp(gameChannel, true, e.MaxPlayers, e.Tunnel, ProgramConstants.PLAYERNAME, isCustomPassword, e.GameDifficulty);
gameChannel.UserAdded += GameChannel_UserAdded;
//gameChannel.MessageAdded += GameChannel_MessageAdded;
connectionManager.SendCustomMessage(new QueuedMessage("JOIN " + channelName + " " + password,
Expand Down Expand Up @@ -1496,7 +1496,7 @@ private void GameBroadcastChannel_CTCPReceived(object sender, ChannelCTCPEventAr
string msg = e.Message.Substring(5); // Cut out GAME part
string[] splitMessage = msg.Split(new char[] { ';' });

if (splitMessage.Length != 11)
if (splitMessage.Length != 12)
{
Logger.Log("Ignoring CTCP game message because of an invalid amount of parameters.");
return;
Expand Down Expand Up @@ -1526,6 +1526,9 @@ private void GameBroadcastChannel_CTCPReceived(object sender, ChannelCTCPEventAr
int tunnelPort = int.Parse(tunnelAddressAndPort[1]);

string loadedGameId = splitMessage[10];
int gameDifficulty = int.Parse(splitMessage[11]);

Logger.Log("GameDifficulty ** Received game difficulty in ctcp: " + gameDifficulty);

CnCNetGame cncnetGame = gameCollection.GameList.Find(g => g.GameBroadcastChannel == channel.ChannelName);

Expand All @@ -1548,6 +1551,7 @@ private void GameBroadcastChannel_CTCPReceived(object sender, ChannelCTCPEventAr
game.Locked = locked || (game.IsLoadedGame && !game.Players.Contains(ProgramConstants.PLAYERNAME));
game.Incompatible = cncnetGame == localGame && game.GameVersion != ProgramConstants.GAME_VERSION;
game.TunnelServer = tunnel;
game.SkillLevel = gameDifficulty;

if (isClosed)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ namespace DTAClient.DXGUI.Multiplayer.CnCNet
class GameCreationEventArgs : EventArgs
{
public GameCreationEventArgs(string roomName, int maxPlayers,
string password, CnCNetTunnel tunnel)
string password, CnCNetTunnel tunnel, int gameDifficulty)
{
GameRoomName = roomName;
MaxPlayers = maxPlayers;
Password = password;
Tunnel = tunnel;
GameDifficulty = gameDifficulty;
}

public string GameRoomName { get; private set; }
public int MaxPlayers { get; private set; }
public string Password { get; private set; }
public CnCNetTunnel Tunnel { get; private set; }
public int GameDifficulty { get; private set; }
}
}
41 changes: 36 additions & 5 deletions DXMainClient/DXGUI/Multiplayer/CnCNet/GameCreationWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ public GameCreationWindow(WindowManager windowManager, TunnelHandler tunnelHandl

private XNATextBox tbGameName;
private XNAClientDropDown ddMaxPlayers;
private XNAClientDropDown ddSkillLevel;
private XNATextBox tbPassword;

private XNALabel lblRoomName;
private XNALabel lblMaxPlayers;
private XNALabel lblSkillLevel;
private XNALabel lblPassword;

private XNALabel lblTunnelServer;
Expand All @@ -44,11 +46,15 @@ public GameCreationWindow(WindowManager windowManager, TunnelHandler tunnelHandl

private TunnelHandler tunnelHandler;

private string[] SkillLevelOptions;

public override void Initialize()
{
lbTunnelList = new TunnelListBox(WindowManager, tunnelHandler);
lbTunnelList.Name = nameof(lbTunnelList);

SkillLevelOptions = ClientConfiguration.Instance.SkillLevelOptions.Split(',');

Name = "GameCreationWindow";
Width = lbTunnelList.Width + UIDesignConstants.EMPTY_SPACE_SIDES * 2 +
UIDesignConstants.CONTROL_HORIZONTAL_MARGIN * 2;
Expand Down Expand Up @@ -82,10 +88,31 @@ public override void Initialize()
UIDesignConstants.CONTROL_HORIZONTAL_MARGIN, ddMaxPlayers.Y + 1, 0, 0);
lblMaxPlayers.Text = "Maximum number of players:".L10N("Client:Main:GameMaxPlayerCount");

// Skill Level selector
ddSkillLevel = new XNAClientDropDown(WindowManager);
ddSkillLevel.Name = nameof(ddSkillLevel);
ddSkillLevel.ClientRectangle = new Rectangle(tbGameName.X, ddMaxPlayers.Bottom + 20,
tbGameName.Width, 21);

for (int i = 0; i < SkillLevelOptions.Length; i++)
{
string skillLevel = SkillLevelOptions[i];
string localizedSkillLevel = skillLevel.L10N($"INI:ClientDefinitions:SkillLevel:{i}");
ddSkillLevel.AddItem(localizedSkillLevel);
}

ddSkillLevel.SelectedIndex = 0;

lblSkillLevel = new XNALabel(WindowManager);
lblSkillLevel.Name = nameof(lblSkillLevel);
lblSkillLevel.ClientRectangle = new Rectangle(UIDesignConstants.EMPTY_SPACE_SIDES +
UIDesignConstants.CONTROL_HORIZONTAL_MARGIN, ddSkillLevel.Y + 1, 0, 0);
lblSkillLevel.Text = "Select preferred skill level of players:".L10N("Client:Main:SelectSkillLevel");

tbPassword = new XNATextBox(WindowManager);
tbPassword.Name = nameof(tbPassword);
tbPassword.MaximumTextLength = 20;
tbPassword.ClientRectangle = new Rectangle(tbGameName.X, ddMaxPlayers.Bottom + 20,
tbPassword.ClientRectangle = new Rectangle(tbGameName.X, ddSkillLevel.Bottom + 20,
tbGameName.Width, 21);

lblPassword = new XNALabel(WindowManager);
Expand Down Expand Up @@ -142,6 +169,8 @@ public override void Initialize()
AddChild(lblRoomName);
AddChild(ddMaxPlayers);
AddChild(lblMaxPlayers);
AddChild(ddSkillLevel);
AddChild(lblSkillLevel);
AddChild(tbPassword);
AddChild(lblPassword);
AddChild(btnDisplayAdvancedOptions);
Expand Down Expand Up @@ -203,7 +232,7 @@ private void BtnLoadMPGame_LeftClick(object sender, EventArgs e)

GameCreationEventArgs ea = new GameCreationEventArgs(gameName,
spawnSGIni.GetIntValue("Settings", "PlayerCount", 2), password,
tunnelHandler.Tunnels[lbTunnelList.SelectedIndex]);
tunnelHandler.Tunnels[lbTunnelList.SelectedIndex], ddSkillLevel.SelectedIndex);

LoadedGameCreated?.Invoke(this, ea);
}
Expand All @@ -229,9 +258,11 @@ private void BtnCreateGame_LeftClick(object sender, EventArgs e)
return;
}

GameCreated?.Invoke(this, new GameCreationEventArgs(gameName,
int.Parse(ddMaxPlayers.SelectedItem.Text), tbPassword.Text,
tunnelHandler.Tunnels[lbTunnelList.SelectedIndex]));
GameCreated?.Invoke(this,
new GameCreationEventArgs(gameName,int.Parse(ddMaxPlayers.SelectedItem.Text),
tbPassword.Text,tunnelHandler.Tunnels[lbTunnelList.SelectedIndex],
ddSkillLevel.SelectedIndex)
);
}

private void BtnDisplayAdvancedOptions_LeftClick(object sender, EventArgs e)
Expand Down
20 changes: 17 additions & 3 deletions DXMainClient/DXGUI/Multiplayer/GameInformationPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Xna.Framework;
using DTAClient.Domain.Multiplayer;
using ClientCore.Extensions;
using ClientCore;

namespace DTAClient.DXGUI.Multiplayer
{
Expand All @@ -29,8 +30,11 @@ public GameInformationPanel(WindowManager windowManager, MapLoader mapLoader)
private XNALabel lblHost;
private XNALabel lblPing;
private XNALabel lblPlayers;
private XNALabel lblSkillLevel;
private XNALabel[] lblPlayerNames;

private string[] SkillLevelOptions;

public override void Initialize()
{
ClientRectangle = new Rectangle(0, 0, 235, 264);
Expand All @@ -56,8 +60,11 @@ public override void Initialize()
lblPing = new XNALabel(WindowManager);
lblPing.ClientRectangle = new Rectangle(6, 126, 0, 0);

lblSkillLevel = new XNALabel(WindowManager);
lblSkillLevel.ClientRectangle = new Rectangle(6, 150, 0, 0);

lblPlayers = new XNALabel(WindowManager);
lblPlayers.ClientRectangle = new Rectangle(6, 150, 0, 0);
lblPlayers.ClientRectangle = new Rectangle(6, 178, 0, 0);

lblPlayerNames = new XNALabel[MAX_PLAYERS];
for (int i = 0; i < lblPlayerNames.Length / 2; i++)
Expand All @@ -84,22 +91,25 @@ public override void Initialize()
AddChild(lblPing);
AddChild(lblPlayers);
AddChild(lblGameInformation);
AddChild(lblSkillLevel);

lblGameInformation.CenterOnParent();
lblGameInformation.ClientRectangle = new Rectangle(lblGameInformation.X, 6,
lblGameInformation.Width, lblGameInformation.Height);

SkillLevelOptions = ClientConfiguration.Instance.SkillLevelOptions.Split(',');

base.Initialize();
}

public void SetInfo(GenericHostedGame game)
{
// we don't have the ID of a map here
string translatedMapName = string.IsNullOrEmpty(game.Map)
string translatedMapName = string.IsNullOrEmpty(game.Map)
? "Unknown".L10N("Client:Main:Unknown") : mapLoader.TranslatedMapNames.ContainsKey(game.Map)
? mapLoader.TranslatedMapNames[game.Map] : game.Map;

string translatedGameModeName = string.IsNullOrEmpty(game.GameMode)
string translatedGameModeName = string.IsNullOrEmpty(game.GameMode)
? "Unknown".L10N("Client:Main:Unknown") : game.GameMode.L10N($"INI:GameModes:{game.GameMode}:UIName", notify: false);

lblGameMode.Text = Renderer.GetStringWithLimitedWidth("Game mode:".L10N("Client:Main:GameInfoGameMode") + " " + Renderer.GetSafeString(translatedGameModeName, lblGameMode.FontIndex),
Expand Down Expand Up @@ -132,6 +142,10 @@ public void SetInfo(GenericHostedGame game)
{
lblPlayerNames[i].Visible = false;
}

string skillLevel = SkillLevelOptions[game.SkillLevel];
string localizedSkillLevel = skillLevel.L10N($"INI:ClientDefinitions:SkillLevel:{game.SkillLevel}");
lblSkillLevel.Text = "Preferred Skill Level:".L10N("Client:Main:GameInfoSkillLevel") + " " + localizedSkillLevel;
}

public void ClearInfo()
Expand Down
32 changes: 32 additions & 0 deletions DXMainClient/DXGUI/Multiplayer/GameListBox.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

using ClientCore;
using ClientCore.Enums;
using ClientCore.Extensions;
using DTAClient.Domain.Multiplayer;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Rampastring.Tools;
using Rampastring.XNAUI;
using Rampastring.XNAUI.XNAControls;

Expand All @@ -21,6 +25,7 @@ public class GameListBox : XNAListBox
private const int ICON_MARGIN = 2;
private const int FONT_INDEX = 0;
private static string LOADED_GAME_TEXT => " (" + "Loaded Game".L10N("Client:Main:LoadedGame") + ")";
private string[] SkillLevelIcons;

public GameListBox(WindowManager windowManager, MapLoader mapLoader,
string localGameIdentifier, Predicate<GenericHostedGame> gameMatchesFilter = null)
Expand All @@ -29,8 +34,12 @@ public GameListBox(WindowManager windowManager, MapLoader mapLoader,
this.mapLoader = mapLoader;
this.localGameIdentifier = localGameIdentifier;
GameMatchesFilter = gameMatchesFilter;

SkillLevelIcons = ClientConfiguration.Instance.SkillLevelOptions.Split(',');
}

private List<Texture2D> txSkillLevelIcons = new List<Texture2D>();

private int loadedGameTextWidth;

public List<GenericHostedGame> HostedGames = new();
Expand Down Expand Up @@ -185,6 +194,18 @@ public override void Initialize()
ClientConfiguration.Instance.HoverOnGameColor);

loadedGameTextWidth = (int)Renderer.GetTextDimensions(LOADED_GAME_TEXT, FontIndex).X;

InitSkillLevelIcons();
}

private void InitSkillLevelIcons()
{
for (int i = 0; i < SkillLevelIcons.Length; i++)
{
Texture2D gd = AssetLoader.LoadTexture($"skillLevel{i}.png");
if (gd != null)
txSkillLevelIcons.Add(gd);
}
}

private bool IsValidGameIndex(int index)
Expand Down Expand Up @@ -332,6 +353,17 @@ public override void Draw(GameTime gameTime)
height, txPasswordedGame.Width, txPasswordedGame.Height),
Color.White);
}
else
{
Texture2D txSkillLevelIcon = txSkillLevelIcons[hostedGame.SkillLevel];
if (txSkillLevelIcon != null && hostedGame.SkillLevel != 0)
{
DrawTexture(txSkillLevelIcon,
new Rectangle(Width - txSkillLevelIcon.Width - TextBorderDistance - (scrollBarDrawn ? ScrollBar.Width : 0),
height, txSkillLevelIcon.Width, txSkillLevelIcon.Height),
Color.White);
}
}

var text = lbItem.Text;
if (hostedGame.IsLoadedGame)
Expand Down
8 changes: 7 additions & 1 deletion DXMainClient/DXGUI/Multiplayer/GameLobby/CnCNetGameLobby.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ PrivateMessagingWindow pmWindow

private bool closed = false;

private int gameDifficulty = 0;

private bool isCustomPassword = false;

private string gameFilesHash;
Expand Down Expand Up @@ -215,7 +217,8 @@ private void MultiplayerName_RightClick(object sender, MultiplayerNameRightClick
private void GameBroadcastTimer_TimeElapsed(object sender, EventArgs e) => BroadcastGame();

public void SetUp(Channel channel, bool isHost, int playerLimit,
CnCNetTunnel tunnel, string hostName, bool isCustomPassword)
CnCNetTunnel tunnel, string hostName, bool isCustomPassword,
int gameDifficulty)
{
this.channel = channel;
channel.MessageAdded += Channel_MessageAdded;
Expand All @@ -230,6 +233,7 @@ public void SetUp(Channel channel, bool isHost, int playerLimit,
this.hostName = hostName;
this.playerLimit = playerLimit;
this.isCustomPassword = isCustomPassword;
this.gameDifficulty = gameDifficulty;

if (isHost)
{
Expand Down Expand Up @@ -1929,6 +1933,8 @@ private void BroadcastGame()
sb.Append(tunnelHandler.CurrentTunnel.Address + ":" + tunnelHandler.CurrentTunnel.Port);
sb.Append(";");
sb.Append(0); // LoadedGameId
sb.Append(";");
sb.Append(gameDifficulty); // SkillLevel

broadcastChannel.SendCTCPMessage(sb.ToString(), QueuedMessageType.SYSTEM_MESSAGE, 20);
}
Expand Down
2 changes: 2 additions & 0 deletions DXMainClient/Domain/Multiplayer/GenericHostedGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public abstract class GenericHostedGame: IEquatable<GenericHostedGame>

public DateTime LastRefreshTime { get; set; }

public int SkillLevel { get; set; }

public virtual bool Equals(GenericHostedGame other)
=> string.Equals(RoomName, other?.RoomName, StringComparison.InvariantCultureIgnoreCase);
}
Expand Down
Binary file added DXMainClient/Resources/DTA/skillLevel1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added DXMainClient/Resources/DTA/skillLevel2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added DXMainClient/Resources/DTA/skillLevel3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ff5f14c

Please sign in to comment.