Support map-defined AI in the lobby.
This commit is contained in:
@@ -210,6 +210,9 @@ namespace OpenRA
|
|||||||
Status = MapStatus.Unavailable;
|
Status = MapStatus.Unavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: multiple threads may try to access the value at the same time
|
||||||
|
// We rely on the thread-safety guarantees given by Lazy<T> to prevent race conitions.
|
||||||
|
// If you're thinking about replacing this, then you must be careful to keep this safe.
|
||||||
rules = Exts.Lazy(() =>
|
rules = Exts.Lazy(() =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -249,8 +249,6 @@ namespace OpenRA.Widgets
|
|||||||
return trimmed;
|
return trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Action Once(Action a) { return () => { if (a != null) { a(); a = null; } }; }
|
|
||||||
|
|
||||||
public static string ChooseInitialMap(string initialUid)
|
public static string ChooseInitialMap(string initialUid)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(initialUid) || Game.ModData.MapCache[initialUid].Status != MapStatus.Available)
|
if (string.IsNullOrEmpty(initialUid) || Game.ModData.MapCache[initialUid].Status != MapStatus.Available)
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
readonly LabelWidget chatLabel;
|
readonly LabelWidget chatLabel;
|
||||||
bool teamChat;
|
bool teamChat;
|
||||||
|
|
||||||
|
bool addBotOnMapLoad;
|
||||||
|
|
||||||
int lobbyChatUnreadMessages;
|
int lobbyChatUnreadMessages;
|
||||||
int globalChatLastReadMessages;
|
int globalChatLastReadMessages;
|
||||||
int globalChatUnreadMessages;
|
int globalChatUnreadMessages;
|
||||||
@@ -201,9 +203,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
(orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) &&
|
(orderManager.LobbyInfo.Slots.Values.All(s => !s.AllowBots) &&
|
||||||
orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0);
|
orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) == 0);
|
||||||
|
|
||||||
var botNames = modRules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name);
|
|
||||||
slotsButton.OnMouseDown = _ =>
|
slotsButton.OnMouseDown = _ =>
|
||||||
{
|
{
|
||||||
|
var botNames = Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name);
|
||||||
var options = new Dictionary<string, IEnumerable<DropDownOption>>();
|
var options = new Dictionary<string, IEnumerable<DropDownOption>>();
|
||||||
|
|
||||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||||
@@ -711,16 +713,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
// Add a bot on the first lobbyinfo update
|
// Add a bot on the first lobbyinfo update
|
||||||
if (skirmishMode)
|
if (skirmishMode)
|
||||||
{
|
addBotOnMapLoad = true;
|
||||||
Game.LobbyInfoChanged += WidgetUtils.Once(() =>
|
|
||||||
{
|
|
||||||
var slot = orderManager.LobbyInfo.FirstEmptyBotSlot();
|
|
||||||
var bot = modRules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name).FirstOrDefault();
|
|
||||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
|
||||||
if (slot != null && bot != null)
|
|
||||||
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Tick()
|
public override void Tick()
|
||||||
@@ -796,6 +789,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var currentMap = Map;
|
var currentMap = Map;
|
||||||
new Task(() =>
|
new Task(() =>
|
||||||
{
|
{
|
||||||
|
// Force map rules to be loaded on this background thread
|
||||||
var unused = currentMap.Rules;
|
var unused = currentMap.Rules;
|
||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
@@ -806,6 +800,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
// Tell the server that we have the map
|
// Tell the server that we have the map
|
||||||
if (!currentMap.InvalidCustomRules)
|
if (!currentMap.InvalidCustomRules)
|
||||||
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
orderManager.IssueOrder(Order.Command("state {0}".F(Session.ClientState.NotReady)));
|
||||||
|
|
||||||
|
if (addBotOnMapLoad)
|
||||||
|
{
|
||||||
|
var slot = orderManager.LobbyInfo.FirstEmptyBotSlot();
|
||||||
|
var bot = currentMap.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name).FirstOrDefault();
|
||||||
|
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||||
|
if (slot != null && bot != null)
|
||||||
|
orderManager.IssueOrder(Order.Command("slot_bot {0} {1} {2}".F(slot, botController.Index, bot)));
|
||||||
|
|
||||||
|
addBotOnMapLoad = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).Start();
|
}).Start();
|
||||||
}
|
}
|
||||||
@@ -837,7 +842,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
template = emptySlotTemplate.Clone();
|
template = emptySlotTemplate.Clone();
|
||||||
|
|
||||||
if (Game.IsHost)
|
if (Game.IsHost)
|
||||||
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, modRules);
|
LobbyUtils.SetupEditableSlotWidget(this, template, slot, client, orderManager);
|
||||||
else
|
else
|
||||||
LobbyUtils.SetupSlotWidget(template, slot, client);
|
LobbyUtils.SetupSlotWidget(template, slot, client);
|
||||||
|
|
||||||
@@ -856,7 +861,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
LobbyUtils.SetupClientWidget(template, client, orderManager, client.Bot == null);
|
LobbyUtils.SetupClientWidget(template, client, orderManager, client.Bot == null);
|
||||||
|
|
||||||
if (client.Bot != null)
|
if (client.Bot != null)
|
||||||
LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, modRules);
|
LobbyUtils.SetupEditableSlotWidget(this, template, slot, client, orderManager);
|
||||||
else
|
else
|
||||||
LobbyUtils.SetupEditableNameWidget(template, slot, client, orderManager);
|
LobbyUtils.SetupEditableNameWidget(template, slot, client, orderManager);
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowSlotDropDown(Ruleset rules, DropDownButtonWidget dropdown, Session.Slot slot,
|
public static void ShowSlotDropDown(LobbyLogic logic, DropDownButtonWidget dropdown, Session.Slot slot,
|
||||||
Session.Client client, OrderManager orderManager)
|
Session.Client client, OrderManager orderManager)
|
||||||
{
|
{
|
||||||
var options = new Dictionary<string, IEnumerable<SlotDropDownOption>>() { { "Slot", new List<SlotDropDownOption>()
|
var options = new Dictionary<string, IEnumerable<SlotDropDownOption>>() { { "Slot", new List<SlotDropDownOption>()
|
||||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var bots = new List<SlotDropDownOption>();
|
var bots = new List<SlotDropDownOption>();
|
||||||
if (slot.AllowBots)
|
if (slot.AllowBots)
|
||||||
{
|
{
|
||||||
foreach (var b in rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name))
|
foreach (var b in logic.Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name))
|
||||||
{
|
{
|
||||||
var bot = b;
|
var bot = b;
|
||||||
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
var botController = orderManager.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin);
|
||||||
@@ -303,13 +303,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
name.GetText = () => label;
|
name.GetText = () => label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetupEditableSlotWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, Ruleset rules)
|
public static void SetupEditableSlotWidget(LobbyLogic logic, Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager)
|
||||||
{
|
{
|
||||||
var slot = parent.Get<DropDownButtonWidget>("SLOT_OPTIONS");
|
var slot = parent.Get<DropDownButtonWidget>("SLOT_OPTIONS");
|
||||||
slot.IsVisible = () => true;
|
slot.IsVisible = () => true;
|
||||||
slot.IsDisabled = () => orderManager.LocalClient.IsReady;
|
slot.IsDisabled = () => orderManager.LocalClient.IsReady;
|
||||||
slot.GetText = () => c != null ? c.Name : s.Closed ? "Closed" : "Open";
|
slot.GetText = () => c != null ? c.Name : s.Closed ? "Closed" : "Open";
|
||||||
slot.OnMouseDown = _ => ShowSlotDropDown(rules, slot, s, c, orderManager);
|
slot.OnMouseDown = _ => ShowSlotDropDown(logic, slot, s, c, orderManager);
|
||||||
|
|
||||||
// Ensure Name selector (if present) is hidden
|
// Ensure Name selector (if present) is hidden
|
||||||
var name = parent.GetOrNull("NAME");
|
var name = parent.GetOrNull("NAME");
|
||||||
|
|||||||
Reference in New Issue
Block a user