diff --git a/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs b/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs index a41361579..8a5851baf 100644 --- a/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs +++ b/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs @@ -2144,7 +2144,8 @@ private void RegisterRequestHandlers() RegisterRequestHandler(Commands.ZoneSetBaseDetails); RegisterRequestHandler(Commands.ZoneSelfDestruct); RegisterRequestHandler(Commands.ZoneSOS); - + RegisterRequestHandler(Commands.ZoneCopyGroundType); //OPP + RegisterRequestHandler(Commands.ZoneGetZoneObjectDebugInfo); RegisterRequestHandler(Commands.ZoneDrawBlockingByEid); diff --git a/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj b/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj index 53efee0bb..a0a729793 100644 --- a/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj +++ b/src/Perpetuum.RequestHandlers/Perpetuum.RequestHandlers.csproj @@ -494,6 +494,7 @@ + diff --git a/src/Perpetuum.RequestHandlers/Zone/ZoneClearLayer.cs b/src/Perpetuum.RequestHandlers/Zone/ZoneClearLayer.cs index 175a3e7bf..f45477f9f 100644 --- a/src/Perpetuum.RequestHandlers/Zone/ZoneClearLayer.cs +++ b/src/Perpetuum.RequestHandlers/Zone/ZoneClearLayer.cs @@ -23,6 +23,16 @@ public void HandleRequest(IZoneRequest request) request.Zone.Terrain.Plants.UpdateAll((x, y, pi) => { pi.Clear(); + + // Update blocking footprint of plants for this tile + request.Zone.Terrain.Blocks.UpdateValue(x, y, bi => + { + // only reset the height if there is a plant here. + // otherwise we reset blocking heights for decor, etc! + bi.Height = bi.Plant ? 0 : bi.Height; + bi.Plant = false; + return bi; + }); return pi; }); break; diff --git a/src/Perpetuum.RequestHandlers/ZoneCopyGroundType.cs b/src/Perpetuum.RequestHandlers/ZoneCopyGroundType.cs new file mode 100644 index 000000000..ba7972f2c --- /dev/null +++ b/src/Perpetuum.RequestHandlers/ZoneCopyGroundType.cs @@ -0,0 +1,43 @@ +using Perpetuum.Host.Requests; +using Perpetuum.Zones; +using System.Threading.Tasks; + +namespace Perpetuum.RequestHandlers +{ + public class ZoneCopyGroundType : IRequestHandler + { + private readonly IZoneManager _zoneManager; + + public ZoneCopyGroundType(IZoneManager zoneManager) + { + _zoneManager = zoneManager; + } + + public void HandleRequest(IRequest request) + { + var sourceZoneId = request.Data.GetOrDefault(k.source); + var targetZoneId = request.Data.GetOrDefault(k.target); + var targetZone = _zoneManager.GetZone(targetZoneId); + var sourceZone = _zoneManager.GetZone(sourceZoneId); + targetZone.IsLayerEditLocked.ThrowIfTrue(ErrorCodes.TileTerraformProtected); + targetZoneId.ThrowIfEqual(sourceZoneId, ErrorCodes.WTFErrorMedicalAttentionSuggested); + targetZone.Size.ThrowIfNotEqual(sourceZone.Size, ErrorCodes.WTFErrorMedicalAttentionSuggested); + + var area = Area.FromRectangle(0, 0, sourceZone.Size.Width, sourceZone.Size.Height); + var altBuffer = new ushort[area.Ground]; + var workAreas = area.Slice(32); + Parallel.ForEach(workAreas, (workArea) => + { + var target = targetZone.Terrain.Plants.GetArea(workArea); + var source = sourceZone.Terrain.Plants.GetArea(workArea); + for (int i=0; i< target.Length; i++) + { + target[i].SetGroundType(source[i].groundType); + } + targetZone.Terrain.Plants.SetArea(workArea, target); + }); + + Message.Builder.FromRequest(request).WithOk().Send(); + } + } +} \ No newline at end of file diff --git a/src/Perpetuum/Commands.cs b/src/Perpetuum/Commands.cs index 997979ebe..c2cdf63c0 100644 --- a/src/Perpetuum/Commands.cs +++ b/src/Perpetuum/Commands.cs @@ -1308,6 +1308,17 @@ public static Command GetCommandByText(string commandText) } }; + public static readonly Command ZoneCopyGroundType = new Command + { + Text = "zoneCopyGroundType", + AccessLevel = AccessLevel.admin, + Arguments = + { + new Argument(k.source), + new Argument(k.target) + } + }; + public static readonly Command ZoneFillGroundTypeRandom = new Command { Text = "zoneFillGroundTypeRandom", diff --git a/src/Perpetuum/Services/Channels/ChatCommands/AdminCommandHandlers.cs b/src/Perpetuum/Services/Channels/ChatCommands/AdminCommandHandlers.cs index a3fb062d7..26b527188 100644 --- a/src/Perpetuum/Services/Channels/ChatCommands/AdminCommandHandlers.cs +++ b/src/Perpetuum/Services/Channels/ChatCommands/AdminCommandHandlers.cs @@ -701,15 +701,25 @@ public static void ZoneCreateIsland(AdminCommandData data) if (!IsDevModeEnabled(data)) return; - bool err = false; - err = !int.TryParse(data.Command.Args[0], out int lvl); + int zoneId = data.Sender.ZoneId ?? -1; + int lvl; + try + { + lvl = int.Parse(data.Command.Args[0]); + if (data.Command.Args.Length > 1) + zoneId = int.Parse(data.Command.Args[1]); + } + catch (Exception ex) + { + if (ex is FormatException || ex is ArgumentNullException) + throw PerpetuumException.Create(ErrorCodes.RequiredArgumentIsNotSpecified); + throw; + } + CheckZoneId(data, zoneId); - Dictionary dictionary = new Dictionary() - { - { k.low, lvl } - }; + var dictionary = new Dictionary() { { k.low, lvl } }; - string cmd = string.Format("zoneCreateIsland:zone_{0}:{1}", data.Sender.ZoneId, GenxyConverter.Serialize(dictionary)); + string cmd = string.Format("zoneCreateIsland:zone_{0}:{1}", zoneId, GenxyConverter.Serialize(dictionary)); SendMessageToAll(data, $"zoneCreateIsland accepted: {dictionary.ToDebugString()} \r\nplease wait... "); HandleLocalRequest(data, cmd); SendMessageToAll(data, $"Complete!"); @@ -932,13 +942,28 @@ public static void ZoneClearLayer(AdminCommandData data) if (!IsDevModeEnabled(data)) return; - Dictionary dictionary = new Dictionary() - { - { "layerName", data.Command.Args[0] } - }; + string layerName; + int zoneId = data.Sender.ZoneId ?? -1; + try + { + layerName = data.Command.Args[0]; + if (data.Command.Args.Length > 1) + zoneId = int.Parse(data.Command.Args[1]); + } + catch (Exception ex) + { + SendMessageToAll(data, "Bad args"); + if (ex is ArgumentNullException) + throw PerpetuumException.Create(ErrorCodes.RequiredArgumentIsNotSpecified); + throw; + } - string cmd = string.Format("{0}:zone_{1}:{2}", Commands.ZoneClearLayer.Text, data.Sender.ZoneId, GenxyConverter.Serialize(dictionary)); + CheckZoneId(data, zoneId); + + var dictionary = new Dictionary() { { k.layerName, layerName } }; + var cmd = string.Format("{0}:zone_{1}:{2}", Commands.ZoneClearLayer.Text, zoneId, GenxyConverter.Serialize(dictionary)); HandleLocalRequest(data, cmd); + SendMessageToAll(data, $"{Commands.ZoneClearLayer.Text} executed on {zoneId} for layer: {layerName}"); } [ChatCommand("ZoneSetPlantSpeed")] public static void ZoneSetPlantSpeed(AdminCommandData data) @@ -1247,6 +1272,40 @@ public static void ZoneClearGroundType(AdminCommandData data) HandleLocalRequest(data, cmd); SendMessageToAll(data, $"Command completed"); } + [ChatCommand("ZoneCopyGroundType")] + public static void ZoneCopyGroundType(AdminCommandData data) + { + if (!IsDevModeEnabled(data)) + return; + + CheckRequiredArgLength(data, 2); + int sourceZone; + int targetZone; + try + { + sourceZone = int.Parse(data.Command.Args[0]); + targetZone = int.Parse(data.Command.Args[1]); + } + catch (Exception ex) + { + SendMessageToAll(data, "Bad args"); + if (ex is ArgumentNullException) + throw PerpetuumException.Create(ErrorCodes.RequiredArgumentIsNotSpecified); + throw; + } + if (sourceZone == targetZone) + { + SendMessageToAll(data, "copy to/from cannot be the same zone id"); + return; + } + CheckZoneId(data, sourceZone); + CheckZoneId(data, targetZone); + var dictionary = new Dictionary() { { k.source, sourceZone }, { k.target, targetZone } }; + var cmd = string.Format("{0}:relay:{1}", Commands.ZoneCopyGroundType.Text, GenxyConverter.Serialize(dictionary)); + SendMessageToAll(data, $"Sending: {cmd}"); + HandleLocalRequest(data, cmd); + SendMessageToAll(data, $"Command completed"); + } [ChatCommand("ZoneRandomFillGroundType")] public static void ZoneRandomFillGroundType(AdminCommandData data) { @@ -1298,7 +1357,7 @@ public static void ZoneUpdateSlope(AdminCommandData data) try { - if(data.Command.Args.Length > 0) + if (data.Command.Args.Length > 0) zoneId = int.Parse(data.Command.Args[0]); } catch (Exception ex)