diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index dff248e944..fe75a8fa0c 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -77,8 +77,11 @@ namespace OpenRA.Graphics bounds.TopLeftAsCPos(), bounds.BottomRightAsCPos()); - var worldRenderables = actors.SelectMany(a => a.Render(this)) - .OrderBy(r => r, comparer); + var worldRenderables = actors.SelectMany(a => a.Render(this)); + if (world.OrderGenerator != null) + worldRenderables = worldRenderables.Concat(world.OrderGenerator.Render(this, world)); + + worldRenderables = worldRenderables.OrderBy(r => r, comparer); // Effects are drawn on top of all actors // TODO: Allow effects to be interleaved with actors @@ -112,16 +115,8 @@ namespace OpenRA.Graphics foreach (var r in a.Trait.RenderAsTerrain(this, a.Actor)) r.Render(this); - foreach (var a in world.Selection.Actors) - if (!a.Destroyed) - foreach (var t in a.TraitsImplementing()) - t.RenderBeforeWorld(this, a); - Game.Renderer.Flush(); - if (world.OrderGenerator != null) - world.OrderGenerator.RenderBeforeWorld(this, world); - for (var i = 0; i < renderables.Count; i++) renderables[i].Render(this); diff --git a/OpenRA.Game/Orders/GenericSelectTarget.cs b/OpenRA.Game/Orders/GenericSelectTarget.cs index 481f19e925..250eaaa9fd 100644 --- a/OpenRA.Game/Orders/GenericSelectTarget.cs +++ b/OpenRA.Game/Orders/GenericSelectTarget.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -66,7 +66,7 @@ namespace OpenRA.Orders } public virtual void Tick(World world) { } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { } public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; } } diff --git a/OpenRA.Game/Orders/IOrderGenerator.cs b/OpenRA.Game/Orders/IOrderGenerator.cs index 7de5a38ee6..db0c3c768a 100644 --- a/OpenRA.Game/Orders/IOrderGenerator.cs +++ b/OpenRA.Game/Orders/IOrderGenerator.cs @@ -17,7 +17,7 @@ namespace OpenRA { IEnumerable Order(World world, CPos xy, MouseInput mi); void Tick(World world); - void RenderBeforeWorld(WorldRenderer wr, World world); + IEnumerable Render(WorldRenderer wr, World world); void RenderAfterWorld(WorldRenderer wr, World world); string GetCursor(World world, CPos xy, MouseInput mi); } diff --git a/OpenRA.Game/Orders/UnitOrderGenerator.cs b/OpenRA.Game/Orders/UnitOrderGenerator.cs index d3344ce9af..2c2a75950d 100644 --- a/OpenRA.Game/Orders/UnitOrderGenerator.cs +++ b/OpenRA.Game/Orders/UnitOrderGenerator.cs @@ -42,7 +42,7 @@ namespace OpenRA.Orders } public void Tick(World world) { } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { } public string GetCursor(World world, CPos xy, MouseInput mi) diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 8bbc5db90d..6098f2d3a3 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -187,7 +187,6 @@ namespace OpenRA.Traits public interface IPostRender { void RenderAfterWorld(WorldRenderer wr, Actor self); } public interface IPostRenderSelection { void RenderAfterWorld(WorldRenderer wr); } - public interface IPreRenderSelection { void RenderBeforeWorld(WorldRenderer wr, Actor self); } public interface IRenderAsTerrain { IEnumerable RenderAsTerrain(WorldRenderer wr, Actor self); } public interface IBodyOrientation { diff --git a/OpenRA.Mods.RA/Buildings/BaseProvider.cs b/OpenRA.Mods.RA/Buildings/BaseProvider.cs index d5c0f33254..880a3b0089 100755 --- a/OpenRA.Mods.RA/Buildings/BaseProvider.cs +++ b/OpenRA.Mods.RA/Buildings/BaseProvider.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA.Buildings public object Create(ActorInitializer init) { return new BaseProvider(init.self, this); } } - public class BaseProvider : ITick, IPreRenderSelection, ISelectionBar + public class BaseProvider : ITick, IPostRenderSelection, ISelectionBar { public readonly BaseProviderInfo Info; DeveloperMode devMode; @@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA.Buildings } // Range circle - public void RenderBeforeWorld(WorldRenderer wr, Actor self) + public void RenderAfterWorld(WorldRenderer wr) { // Visible to player and allies if (!self.Owner.IsAlliedWith(self.World.RenderPlayer)) diff --git a/OpenRA.Mods.RA/ChronoshiftDeploy.cs b/OpenRA.Mods.RA/ChronoshiftDeploy.cs index 0a6c5bb7a6..8f9b768e39 100644 --- a/OpenRA.Mods.RA/ChronoshiftDeploy.cs +++ b/OpenRA.Mods.RA/ChronoshiftDeploy.cs @@ -143,8 +143,9 @@ namespace OpenRA.Mods.RA if (!self.IsInWorld || self.IsDead()) world.CancelInputMode(); } - public void RenderAfterWorld(WorldRenderer wr, World world) { } - public void RenderBeforeWorld(WorldRenderer wr, World world) + + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } + public void RenderAfterWorld(WorldRenderer wr, World world) { if (!self.IsInWorld) return; diff --git a/OpenRA.Mods.RA/Guard.cs b/OpenRA.Mods.RA/Guard.cs index 355976d44b..8550b0017c 100644 --- a/OpenRA.Mods.RA/Guard.cs +++ b/OpenRA.Mods.RA/Guard.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -74,7 +74,7 @@ namespace OpenRA.Mods.RA world.CancelInputMode(); } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { } public string GetCursor(World world, CPos xy, MouseInput mi) diff --git a/OpenRA.Mods.RA/Minelayer.cs b/OpenRA.Mods.RA/Minelayer.cs index f6d25c367f..2030368a42 100644 --- a/OpenRA.Mods.RA/Minelayer.cs +++ b/OpenRA.Mods.RA/Minelayer.cs @@ -125,6 +125,7 @@ namespace OpenRA.Mods.RA } CPos lastMousePos; + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { if (!minelayer.IsInWorld) @@ -138,8 +139,6 @@ namespace OpenRA.Mods.RA wr.DrawLocus(Color.Cyan, minefield); } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } - public string GetCursor(World world, CPos xy, MouseInput mi) { lastMousePos = xy; return "ability"; } /* TODO */ } diff --git a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs index 2954df5ce7..2677892789 100755 --- a/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PlaceBuildingOrderGenerator.cs @@ -68,8 +68,8 @@ namespace OpenRA.Mods.RA.Orders } public void Tick(World world) {} - public void RenderAfterWorld(WorldRenderer wr, World world) {} - public void RenderBeforeWorld(WorldRenderer wr, World world) + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } + public void RenderAfterWorld(WorldRenderer wr, World world) { var position = Game.viewport.ViewToWorld(Viewport.LastMousePos); var topLeft = position - FootprintUtils.AdjustForBuildingSize(BuildingInfo); @@ -110,7 +110,10 @@ namespace OpenRA.Mods.RA.Orders var pal = wr.Palette("terrain"); foreach (var c in cells) - (c.Value ? buildOk : buildBlocked).DrawAt(c.Key.ToPPos().ToFloat2(), pal); + { + var tile = c.Value ? buildOk : buildBlocked; + tile.DrawAt(wr.ScreenPxPosition(c.Key.CenterPosition) - 0.5f * tile.size, pal); + } } public string GetCursor(World world, CPos xy, MouseInput mi) { return "default"; } diff --git a/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs b/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs index a56769227c..2a0eecc226 100755 --- a/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/PowerDownOrderGenerator.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -55,8 +55,8 @@ namespace OpenRA.Mods.RA.Orders world.CancelInputMode(); } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } public string GetCursor(World world, CPos xy, MouseInput mi) { diff --git a/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs b/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs index 1b6745752b..d57d624c36 100644 --- a/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs +++ b/OpenRA.Mods.RA/Orders/RepairOrderGenerator.cs @@ -1,4 +1,4 @@ -#region Copyright & License Information +#region Copyright & License Information /* * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made @@ -49,8 +49,8 @@ namespace OpenRA.Mods.RA.Orders world.CancelInputMode(); } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } public string GetCursor(World world, CPos xy, MouseInput mi) { diff --git a/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs b/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs index 3b4d2f3ab5..16315395f0 100644 --- a/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs +++ b/OpenRA.Mods.RA/Orders/SetChronoTankDestination.cs @@ -38,13 +38,12 @@ namespace OpenRA.Mods.RA.Orders } public void Tick( World world ) { } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld( WorldRenderer wr, World world ) { wr.DrawSelectionBox(self, Color.White); } - public void RenderBeforeWorld( WorldRenderer wr, World world ) { } - public string GetCursor(World world, CPos xy, MouseInput mi) { if (!world.LocalPlayer.Shroud.IsExplored(xy)) diff --git a/OpenRA.Mods.RA/Render/RenderBuilding.cs b/OpenRA.Mods.RA/Render/RenderBuilding.cs index abf92e71a1..46e98d5a65 100755 --- a/OpenRA.Mods.RA/Render/RenderBuilding.cs +++ b/OpenRA.Mods.RA/Render/RenderBuilding.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.RA.Render return; foreach (var a in w.ActorsWithTrait()) - a.Trait.RenderBeforeWorld(wr, a.Actor); + a.Trait.RenderAfterWorld(wr); } } diff --git a/OpenRA.Mods.RA/RenderDetectionCircle.cs b/OpenRA.Mods.RA/RenderDetectionCircle.cs index 8e8d0b90b1..9dcc897164 100644 --- a/OpenRA.Mods.RA/RenderDetectionCircle.cs +++ b/OpenRA.Mods.RA/RenderDetectionCircle.cs @@ -14,10 +14,18 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - class RenderDetectionCircleInfo : TraitInfo { } - class RenderDetectionCircle : IPreRenderSelection + class RenderDetectionCircleInfo : ITraitInfo { - public void RenderBeforeWorld(WorldRenderer wr, Actor self) + public object Create(ActorInitializer init) { return new RenderDetectionCircle(init.self); } + } + + class RenderDetectionCircle : IPostRenderSelection + { + Actor self; + + public RenderDetectionCircle(Actor self) { this.self = self; } + + public void RenderAfterWorld(WorldRenderer wr) { if (self.Owner != self.World.LocalPlayer) return; diff --git a/OpenRA.Mods.RA/RenderJammerCircle.cs b/OpenRA.Mods.RA/RenderJammerCircle.cs index 7d156b18ac..18522955d2 100644 --- a/OpenRA.Mods.RA/RenderJammerCircle.cs +++ b/OpenRA.Mods.RA/RenderJammerCircle.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { //todo: remove all the Render*Circle duplication - class RenderJammerCircleInfo : TraitInfo, IPlaceBuildingDecoration + class RenderJammerCircleInfo : ITraitInfo, IPlaceBuildingDecoration { public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { @@ -29,13 +29,19 @@ namespace OpenRA.Mods.RA foreach (var a in w.ActorsWithTrait()) if (a.Actor.Owner == a.Actor.World.LocalPlayer) - a.Trait.RenderBeforeWorld(wr, a.Actor); + a.Trait.RenderAfterWorld(wr); } + + public object Create(ActorInitializer init) { return new RenderJammerCircle(init.self); } } - public class RenderJammerCircle : IPreRenderSelection + class RenderJammerCircle : IPostRenderSelection { - public void RenderBeforeWorld(WorldRenderer wr, Actor self) + Actor self; + + public RenderJammerCircle(Actor self) { this.self = self; } + + public void RenderAfterWorld(WorldRenderer wr) { if (self.Owner != self.World.LocalPlayer) return; diff --git a/OpenRA.Mods.RA/RenderRangeCircle.cs b/OpenRA.Mods.RA/RenderRangeCircle.cs index 480b177ac2..6238ac68a2 100644 --- a/OpenRA.Mods.RA/RenderRangeCircle.cs +++ b/OpenRA.Mods.RA/RenderRangeCircle.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition); } - class RenderRangeCircleInfo : TraitInfo, IPlaceBuildingDecoration + class RenderRangeCircleInfo : ITraitInfo, IPlaceBuildingDecoration { public readonly string RangeCircleType = null; @@ -36,13 +36,19 @@ namespace OpenRA.Mods.RA foreach (var a in w.ActorsWithTrait()) if (a.Actor.Owner == a.Actor.World.LocalPlayer) if (a.Actor.Info.Traits.Get().RangeCircleType == RangeCircleType) - a.Trait.RenderBeforeWorld(wr, a.Actor); + a.Trait.RenderAfterWorld(wr); } + + public object Create(ActorInitializer init) { return new RenderRangeCircle(init.self); } } - class RenderRangeCircle : IPreRenderSelection + class RenderRangeCircle : IPostRenderSelection { - public void RenderBeforeWorld(WorldRenderer wr, Actor self) + Actor self; + + public RenderRangeCircle(Actor self) { this.self = self; } + + public void RenderAfterWorld(WorldRenderer wr) { if (self.Owner != self.World.LocalPlayer) return; diff --git a/OpenRA.Mods.RA/RenderShroudCircle.cs b/OpenRA.Mods.RA/RenderShroudCircle.cs index 27b0db8552..25aa7678a4 100644 --- a/OpenRA.Mods.RA/RenderShroudCircle.cs +++ b/OpenRA.Mods.RA/RenderShroudCircle.cs @@ -14,7 +14,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - class RenderShroudCircleInfo : TraitInfo, IPlaceBuildingDecoration + class RenderShroudCircleInfo : ITraitInfo, IPlaceBuildingDecoration { public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) { @@ -27,13 +27,19 @@ namespace OpenRA.Mods.RA foreach (var a in w.ActorsWithTrait()) if (a.Actor.Owner == a.Actor.World.LocalPlayer) - a.Trait.RenderBeforeWorld(wr, a.Actor); + a.Trait.RenderAfterWorld(wr); } + + public object Create(ActorInitializer init) { return new RenderShroudCircle(init.self); } } - class RenderShroudCircle : IPreRenderSelection + class RenderShroudCircle : IPostRenderSelection { - public void RenderBeforeWorld(WorldRenderer wr, Actor self) + Actor self; + + public RenderShroudCircle(Actor self) { this.self = self; } + + public void RenderAfterWorld(WorldRenderer wr) { if (self.Owner != self.World.LocalPlayer) return; diff --git a/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs index 22e74e5be5..284765b004 100755 --- a/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/ChronoshiftPower.cs @@ -140,20 +140,18 @@ namespace OpenRA.Mods.RA { var xy = Game.viewport.ViewToWorld(Viewport.LastMousePos); var targetUnits = power.UnitsInRange(xy); - foreach (var unit in targetUnits) { - if (manager.self.Owner.Shroud.IsTargetable(unit) || manager.self.Owner.HasFogVisibility()) { + foreach (var unit in targetUnits) + if (manager.self.Owner.Shroud.IsTargetable(unit) || manager.self.Owner.HasFogVisibility()) wr.DrawSelectionBox(unit, Color.Red); - } - } } - public void RenderBeforeWorld(WorldRenderer wr, World world) + public IEnumerable Render(WorldRenderer wr, World world) { var xy = Game.viewport.ViewToWorld(Viewport.LastMousePos); var tiles = world.FindTilesInCircle(xy, range); var pal = wr.Palette("terrain"); foreach (var t in tiles) - tile.DrawAt(t.ToPPos().ToFloat2(), pal); + yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true); } public string GetCursor(World world, CPos xy, MouseInput mi) @@ -221,25 +219,23 @@ namespace OpenRA.Mods.RA public void RenderAfterWorld(WorldRenderer wr, World world) { - foreach (var unit in power.UnitsInRange(sourceLocation)) { - if (manager.self.Owner.Shroud.IsTargetable(unit) || manager.self.Owner.HasFogVisibility()) { + foreach (var unit in power.UnitsInRange(sourceLocation)) + if (manager.self.Owner.Shroud.IsTargetable(unit) || manager.self.Owner.HasFogVisibility()) wr.DrawSelectionBox(unit, Color.Red); - } - } } - public void RenderBeforeWorld(WorldRenderer wr, World world) + public IEnumerable Render(WorldRenderer wr, World world) { var xy = Game.viewport.ViewToWorld(Viewport.LastMousePos); var pal = wr.Palette("terrain"); // Source tiles foreach (var t in world.FindTilesInCircle(sourceLocation, range)) - sourceTile.DrawAt(t.ToPPos().ToFloat2(), pal); + yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true); // Destination tiles foreach (var t in world.FindTilesInCircle(xy, range)) - sourceTile.DrawAt(t.ToPPos().ToFloat2(), pal); + yield return new SpriteRenderable(sourceTile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true); // Unit previews foreach (var unit in power.UnitsInRange(sourceLocation)) @@ -247,7 +243,7 @@ namespace OpenRA.Mods.RA var offset = (xy - sourceLocation).ToWVec(); if (manager.self.Owner.Shroud.IsTargetable(unit)) foreach (var r in unit.Render(wr)) - r.OffsetBy(offset).Render(wr); + yield return r.OffsetBy(offset); } // Unit tiles @@ -259,7 +255,7 @@ namespace OpenRA.Mods.RA var canEnter = ((manager.self.Owner.Shroud.IsExplored(targetCell) || manager.self.Owner.HasFogVisibility()) && unit.Trait().CanChronoshiftTo(unit,targetCell)); var tile = canEnter ? validTile : invalidTile; - tile.DrawAt(targetCell.ToPPos().ToFloat2(), pal); + yield return new SpriteRenderable(tile, targetCell.CenterPosition, WVec.Zero, -511, pal, 1f, true); } } } @@ -276,7 +272,8 @@ namespace OpenRA.Mods.RA break; } } - if (!canTeleport) { + if (!canTeleport) + { // Check the terrain types. This will allow chronoshifts to occur on empty terrain to terrain of // a similar type. This also keeps the cursor from changing in non-visible property, alerting the // chronoshifter of enemy unit presence diff --git a/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs b/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs index 50e5a47d17..ffa0d71892 100755 --- a/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/IronCurtainPower.cs @@ -95,12 +95,12 @@ namespace OpenRA.Mods.RA wr.DrawSelectionBox(unit, Color.Red); } - public void RenderBeforeWorld(WorldRenderer wr, World world) + public IEnumerable Render(WorldRenderer wr, World world) { var xy = Game.viewport.ViewToWorld(Viewport.LastMousePos); var pal = wr.Palette("terrain"); foreach (var t in world.FindTilesInCircle(xy, range)) - tile.DrawAt(t.ToPPos().ToFloat2(), pal); + yield return new SpriteRenderable(tile, t.CenterPosition, WVec.Zero, -511, pal, 1f, true); } public string GetCursor(World world, CPos xy, MouseInput mi) diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs index bb9ba10718..2e3437e499 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs @@ -221,7 +221,7 @@ namespace OpenRA.Mods.RA world.CancelInputMode(); } - public void RenderBeforeWorld(WorldRenderer wr, World world) { } + public IEnumerable Render(WorldRenderer wr, World world) { yield break; } public void RenderAfterWorld(WorldRenderer wr, World world) { } public string GetCursor(World world, CPos xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; } }