diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index 7ce7d736ca..450dfaef98 100644 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -27,13 +27,6 @@ namespace OpenRA.Network internal static void ProcessOrder(OrderManager orderManager, World world, int clientId, Order order) { - if (world != null) - { - if (!world.WorldActor.TraitsImplementing().All(vo => - vo.OrderValidation(orderManager, world, clientId, order))) - return; - } - switch (order.OrderString) { // Server message @@ -336,20 +329,30 @@ namespace OpenRA.Network default: { + if (world == null) + break; + if (order.GroupedActors == null) - ResolveOrder(order); + ResolveOrder(order, world.WorldActor.TraitsImplementing(), orderManager, clientId); else + { + // PERF: Cache the result of TraitsImplementing as we are likely to use it for several order subjects + var validateOrders = world.WorldActor.TraitsImplementing().ToArray(); foreach (var subject in order.GroupedActors) - ResolveOrder(Order.FromGroupedOrder(order, subject)); + ResolveOrder(Order.FromGroupedOrder(order, subject), validateOrders, orderManager, clientId); + } break; } } } - static void ResolveOrder(Order order) + static void ResolveOrder(Order order, IEnumerable validateOrders, OrderManager orderManager, int clientId) { - if (order.Subject != null && !order.Subject.IsDead) + if (order.Subject == null || order.Subject.IsDead) + return; + + if (validateOrders.All(vo => vo.OrderValidation(orderManager, order.Subject.World, clientId, order))) foreach (var t in order.Subject.TraitsImplementing()) t.ResolveOrder(order.Subject, order); }