Пример #1
0
        public static bool GetIds(World world, BCMCmdArea command, out EntityPlayer entity)
        {
            entity = null;
            int?entityId = null;

            if (command.Opts.ContainsKey("id"))
            {
                if (!PlayerStore.GetId(command.Opts["id"], out command.SteamId, "CON"))
                {
                    return(false);
                }

                entityId = ConsoleHelper.ParseParamSteamIdOnline(command.SteamId)?.entityId;
            }

            if (command.SteamId == null)
            {
                entityId        = BCCommandAbstract.SenderInfo.RemoteClientInfo?.entityId;
                command.SteamId = BCCommandAbstract.SenderInfo.RemoteClientInfo?.playerId;
            }

            if (entityId != null)
            {
                entity = world.Players.dict[(int)entityId];
            }

            return(entity != null || BCCommandAbstract.Params.Count >= 3);
        }
Пример #2
0
        public static void DoProcess(World world, BCMCmdArea command, BCCommandAbstract cmdRef)
        {
            if (command.Opts.ContainsKey("forcesync"))
            {
                BCCommandAbstract.SendOutput("Processing Command synchronously...");
                ProcessCommand(world, command, cmdRef);

                return;
            }

            if (BCCommandAbstract.SenderInfo.NetworkConnection != null && !(BCCommandAbstract.SenderInfo.NetworkConnection is TelnetConnection))
            {
                BCCommandAbstract.SendOutput("Processing Async Command... Sending output to log");
            }
            else
            {
                BCCommandAbstract.SendOutput("Processing Async Command...");
            }

            BCTask.AddTask(
                command.CmdType,
                ThreadManager.AddSingleTask(
                    info => ProcessCommand(world, command, cmdRef),
                    null,
                    (info, e) => BCTask.DelTask(command.CmdType, info.GetHashCode()))
                .GetHashCode(),
                command);
        }
Пример #3
0
        //todo: load chunk observers async version

        protected override void Process()
        {
            if (!BCUtils.CheckWorld(out var world))
            {
                return;
            }

            var command = new BCMCmdArea(Params, Options, "Export");

            if (!BCUtils.ProcessParams(command, 14))
            {
                SendOutput(GetHelp());

                return;
            }

            if (!BCUtils.GetIds(world, command, out var entity))
            {
                SendOutput("Command requires a position when not run by a player.");

                return;
            }

            if (!command.HasChunkPos && !command.HasPos && !BCUtils.GetEntPos(command, entity))
            {
                SendOutput("Unable to get position.");

                return;
            }

            BCUtils.DoProcess(world, command, this);
        }
Пример #4
0
        public static bool GetPosSizeXyz(BCMCmdArea command)
        {
            if (!int.TryParse(command.Pars[1], out var x) || !int.TryParse(command.Pars[2], out var y) || !int.TryParse(command.Pars[3], out var z))
            {
                BCCommandAbstract.SendOutput("Unable to parse x,y,z into ints");

                return(false);
            }

            if (!int.TryParse(command.Pars[4], out var x2) || !int.TryParse(command.Pars[5], out var y2) || !int.TryParse(command.Pars[6], out var z2))
            {
                BCCommandAbstract.SendOutput("Unable to parse x2,y2,z2 into ints");

                return(false);
            }

            command.Position = new BCMVector3(Math.Min(x, x2), Math.Min(y, y2), Math.Min(z, z2));
            command.HasPos   = true;

            command.Size    = new BCMVector3(Math.Abs(x - x2) + 1, Math.Abs(y - y2) + 1, Math.Abs(z - z2) + 1);
            command.HasSize = true;

            command.ChunkBounds = new BCMVector4(
                World.toChunkXZ(Math.Min(x, x2)),
                World.toChunkXZ(Math.Min(z, z2)),
                World.toChunkXZ(Math.Max(x, x2)),
                World.toChunkXZ(Math.Max(z, z2))
                );
            command.HasChunkPos = true;

            return(true);
        }
Пример #5
0
        private static void ExportPrefab(BCMCmdArea command, World world)
        {
            var prefab = new Prefab();

            if (command.Position == null)
            {
                command.Position = new BCMVector3(command.ChunkBounds.x * 16, 0, command.ChunkBounds.y * 16);
                command.Size     = new BCMVector3((command.ChunkBounds.z - command.ChunkBounds.x) * 16 + 15, 255, (command.ChunkBounds.w - command.ChunkBounds.y) * 16 + 15);
            }
            prefab.CopyFromWorld(world, command.Position.ToV3Int(), command.Position.ToV3Int() + command.Size.ToV3Int());

            prefab.filename       = command.Pars[0];
            prefab.bCopyAirBlocks = true;
            prefab.addAllChildBlocks();

            //todo: process meta, lock doors etc?
            //todo: parse additional config from options

            var dir = "Data/Prefabs";

            if (Options.ContainsKey("backup"))
            {
                dir = "Data/Prefabs/Backup";
            }
            SendOutput(prefab.Save(dir, prefab.filename)
        ? $"Prefab {prefab.filename} exported @ {command.Position}, size={command.Size}"
        : $"Error: Prefab {prefab.filename} failed to save.");
        }
Пример #6
0
        public static bool GetChunkPosXz(BCMCmdArea command)
        {
            if (!int.TryParse(command.Pars[1], out var x) || !int.TryParse(command.Pars[2], out var z))
            {
                BCCommandAbstract.SendOutput("Unable to parse x,z into ints");

                return(false);
            }

            command.ChunkBounds = new BCMVector4(x - command.Radius, z - command.Radius, x + command.Radius, z + command.Radius);
            command.HasChunkPos = true;

            return(true);
        }
Пример #7
0
        public static bool GetChunkSizeXyzw(BCMCmdArea command)
        {
            if (!int.TryParse(command.Pars[1], out var x) || !int.TryParse(command.Pars[2], out var y) || !int.TryParse(command.Pars[3], out var z) || !int.TryParse(command.Pars[4], out var w))
            {
                BCCommandAbstract.SendOutput("Unable to parse x,z x2,z2 into ints");

                return(false);
            }

            command.ChunkBounds = new BCMVector4(Math.Min(x, z), Math.Min(y, w), Math.Max(x, z), Math.Max(y, w));
            command.HasChunkPos = true;

            return(true);
        }
Пример #8
0
        public static bool GetEntPos(BCMCmdArea command, EntityPlayer entity)
        {
            //todo: if /h=#,# then set y to pos + [0], y2 to pos + [1], if only 1 number then y=pos y2=pos+#
            if (entity != null)
            {
                var loc    = new Vector3i(int.MinValue, 0, int.MinValue);
                var hasLoc = false;
                if (command.Opts.ContainsKey("loc"))
                {
                    loc = BCLocation.GetPos(BCCommandAbstract.SenderInfo.RemoteClientInfo?.playerId);
                    if (loc.x == int.MinValue)
                    {
                        BCCommandAbstract.SendOutput("No location stored or player not found. Use bc-loc to store a location.");

                        return(false);
                    }
                    hasLoc = true;

                    command.Position = new BCMVector3((int)entity.position.x, (int)entity.position.y, (int)entity.position.z);
                    command.HasPos   = true;
                    command.Position = new BCMVector3(Math.Min(loc.x, (int)entity.position.x), Math.Min(loc.y, (int)entity.position.y), Math.Min(loc.z, (int)entity.position.z));
                    command.HasPos   = true;

                    command.Size = new BCMVector3(
                        Math.Min(Math.Abs(loc.x - (int)entity.position.x), 1),
                        Math.Min(Math.Abs(loc.y - (int)entity.position.y), 1),
                        Math.Min(Math.Abs(loc.z - (int)entity.position.z), 1)
                        );
                    command.HasSize = true;
                }

                command.ChunkBounds = new BCMVector4
                {
                    x = World.toChunkXZ(hasLoc ? Math.Min(loc.x, (int)entity.position.x) : (int)entity.position.x - command.Radius),
                    y = World.toChunkXZ(hasLoc ? Math.Min(loc.z, (int)entity.position.z) : (int)entity.position.z - command.Radius),
                    z = World.toChunkXZ(hasLoc ? Math.Max(loc.x, (int)entity.position.x) : (int)entity.position.x + command.Radius),
                    w = World.toChunkXZ(hasLoc ? Math.Max(loc.z, (int)entity.position.z) : (int)entity.position.z + command.Radius)
                };
                command.HasChunkPos = true;
            }
            else
            {
                BCCommandAbstract.SendOutput("Unable to get a position");

                return(false);
            }

            return(true);
        }
Пример #9
0
 public static void GetRadius(BCMCmdArea command, ushort max)
 {
     if (command.Opts.ContainsKey("r"))
     {
         ushort.TryParse(command.Opts["r"], out command.Radius);
         if (command.Radius > max)
         {
             command.Radius = max;
         }
         BCCommandAbstract.SendOutput($"Setting radius to +{command.Radius}");
     }
     else
     {
         BCCommandAbstract.SendOutput("Setting radius to default of +0");
     }
 }
Пример #10
0
        public static bool GetPositionXyz(BCMCmdArea command)
        {
            if (!int.TryParse(command.Pars[1], out var x) || !int.TryParse(command.Pars[2], out var y) || !int.TryParse(command.Pars[3], out var z))
            {
                BCCommandAbstract.SendOutput("Unable to parse x,y,z into ints");

                return(false);
            }

            command.Position = new BCMVector3(x, y, z);
            command.HasPos   = true;

            command.ChunkBounds = new BCMVector4(World.toChunkXZ(x), World.toChunkXZ(z), World.toChunkXZ(x), World.toChunkXZ(z));
            command.HasChunkPos = true;

            return(!command.Opts.ContainsKey("item") || command.Command != "additem" || GetItemStack(command));
        }
Пример #11
0
        public static bool GetItemStack(BCMCmdArea command)
        {
            var quality = -1;
            var count   = 1;

            if (command.Opts.ContainsKey("q"))
            {
                if (!int.TryParse(command.Opts["q"], out quality))
                {
                    BCCommandAbstract.SendOutput("Unable to parse quality, using random value");
                }
            }
            if (command.Opts.ContainsKey("c"))
            {
                if (!int.TryParse(command.Opts["c"], out count))
                {
                    BCCommandAbstract.SendOutput($"Unable to parse count, using default value of {count}");
                }
            }

            var ic = int.TryParse(command.Opts["item"], out var id) ? ItemClass.GetForId(id) : ItemData.GetForName(command.Opts["item"]);

            if (ic == null)
            {
                BCCommandAbstract.SendOutput($"Unable to get item or block from given value '{command.Opts["item"]}'");

                return(false);
            }

            command.ItemStack = new ItemStack
            {
                itemValue = new ItemValue(ic.Id, true),
                count     = count <= ic.Stacknumber.Value ? count : ic.Stacknumber.Value
            };
            if (command.ItemStack.count < count)
            {
                BCCommandAbstract.SendOutput("Using max stack size for " + ic.Name + " of " + command.ItemStack.count);
            }
            if (command.ItemStack.itemValue.HasQuality && quality > 0)
            {
                command.ItemStack.itemValue.Quality = quality;
            }

            return(true);
        }
Пример #12
0
        public static void ProcessCommand(World world, BCMCmdArea command, BCCommandAbstract cmdRef)
        {
            var affectedChunks = GetAffectedChunks(command, world);

            if (affectedChunks == null)
            {
                BCCommandAbstract.SendOutput("Aborting, unable to load all chunks in area before timeout.");
                BCCommandAbstract.SendOutput("Use /timeout=#### to override the default 2000 millisecond limit, or wait for the requested chunks to finish loading and try again.");

                return;
            }

            var location = "";

            if (command.HasPos)
            {
                location += $"Pos {command.Position.x} {command.Position.y} {command.Position.z} ";
                if (command.HasSize)
                {
                    var maxPos = command.MaxPos;
                    location += $"to {maxPos.x} {maxPos.y} {maxPos.z} ";
                }
            }
            if (command.HasChunkPos)
            {
                location += $"Chunks {command.ChunkBounds.x} {command.ChunkBounds.y} to {command.ChunkBounds.z} {command.ChunkBounds.w}";
            }
            if (!string.IsNullOrEmpty(location))
            {
                BCCommandAbstract.SendOutput(location);
            }

            cmdRef.ProcessSwitch(world, command, out var reload);

            //RELOAD CHUNKS FOR PLAYER(S) - If steamId is empty then all players in area will get reload
            if (reload != ReloadMode.None && !(command.Opts.ContainsKey("noreload") || command.Opts.ContainsKey("nr")))
            {
                BCChunks.ReloadForClients(affectedChunks, reload == ReloadMode.Target ? command.SteamId : string.Empty);
            }
        }
Пример #13
0
        public static bool ProcessParams(BCMCmdArea command, ushort maxRadius)
        {
            if (command.Opts.ContainsKey("type"))
            {
                command.Filter = command.Opts["type"];
            }
            switch (command.Pars.Count)
            {
            case 1:
                //command with no extras, blocks if /loc, chunks if /r= or nothing
                GetRadius(command, maxRadius);
                command.Command = command.Pars[0];
                return(true);

            case 3:
                //XZ single chunk with /r
                command.Command = command.Pars[0];
                GetRadius(command, maxRadius);
                return(GetChunkPosXz(command));

            case 4:
                //XYZ single block
                command.Command = command.Pars[0];
                return(GetPositionXyz(command));

            case 5:
                //XY-ZW multi chunk
                command.Command = command.Pars[0];
                return(GetChunkSizeXyzw(command));

            case 7:
                //XYZ-XYZ world pos bounds
                command.Command = command.Pars[0];
                return(GetPosSizeXyz(command));

            default:
                return(false);
            }
        }
Пример #14
0
        public static void ChunkObserver(BCMCmdArea command, World world, int timeoutSec)
        {
            var pos           = command.HasPos ? command.Position.ToV3() : command.ChunkBounds.ToV3();
            var viewDim       = !command.Opts.ContainsKey("r") ? command.Radius : command.ChunkBounds.GetRadius();
            var chunkObserver = world.m_ChunkManager.AddChunkObserver(pos, false, viewDim, -1);

            var timerSec = 60;

            if (command.Opts.ContainsKey("ts") && command.Opts["ts"] != null)
            {
                int.TryParse(command.Opts["ts"], out timerSec);
            }
            timerSec += timeoutSec;
            BCTask.AddTask(
                command.CmdType,
                ThreadManager.AddSingleTask(
                    info => DoCleanup(world, chunkObserver, command.CmdType, timerSec, info),
                    null,
                    (info, e) => BCTask.DelTask(command.CmdType, info.GetHashCode(), 120)
                    ).GetHashCode(),
                command);
        }
Пример #15
0
        public override void Process()
        {
            var world = GameManager.Instance.World;

            if (world == null)
            {
                SendOutput("World not initialized.");

                return;
            }

            var command = new BCMCmdArea(Params, Options, "Export");

            if (!BCUtils.ProcessParams(command, 14))
            {
                SendOutput(GetHelp());

                return;
            }

            if (!BCUtils.GetIds(world, command, out var entity))
            {
                SendOutput("Command requires a position when not run by a player.");

                return;
            }

            if (!command.HasChunkPos && !command.HasPos && !BCUtils.GetEntPos(command, entity))
            {
                SendOutput("Unable to get position.");

                return;
            }

            BCUtils.DoProcess(world, command, this);
        }
Пример #16
0
 public virtual void ProcessSwitch(World world, BCMCmdArea command, out ReloadMode reload) => reload = ReloadMode.None;
Пример #17
0
 public override void ProcessSwitch(World world, BCMCmdArea command, out ReloadMode reload)
 {
     reload = ReloadMode.None;
     ExportPrefab(command, world);
 }
Пример #18
0
        public static Dictionary <long, Chunk> GetAffectedChunks(BCMCmdArea command, World world)
        {
            var modifiedChunks = new Dictionary <long, Chunk>();

            var timeout = 2000;

            if (command.Opts.ContainsKey("timeout"))
            {
                if (command.Opts["timeout"] != null)
                {
                    int.TryParse(command.Opts["timeout"], out timeout);
                }
            }

            ChunkObserver(command, world, timeout / 2000);

            //request any unloaded chunks in area
            for (var x = command.ChunkBounds.x; x <= command.ChunkBounds.z; x++)
            {
                for (var z = command.ChunkBounds.y; z <= command.ChunkBounds.w; z++)
                {
                    var chunkKey = WorldChunkCache.MakeChunkKey(x, z);
                    modifiedChunks.Add(chunkKey, null);
                }
            }

            var chunkCount = (command.ChunkBounds.z - command.ChunkBounds.x + 1) * (command.ChunkBounds.w - command.ChunkBounds.y + 1);
            var count      = 0;
            var sw         = Stopwatch.StartNew();

            while (count < chunkCount && sw.ElapsedMilliseconds < timeout)
            {
                for (var x = command.ChunkBounds.x; x <= command.ChunkBounds.z; x++)
                {
                    for (var z = command.ChunkBounds.y; z <= command.ChunkBounds.w; z++)
                    {
                        //check if already in list
                        var chunkKey = WorldChunkCache.MakeChunkKey(x, z);
                        if (modifiedChunks.ContainsKey(chunkKey) && modifiedChunks[chunkKey] != null)
                        {
                            continue;
                        }

                        //check if chunk has loaded
                        if (!world.ChunkCache.ContainsChunkSync(chunkKey))
                        {
                            continue;
                        }

                        modifiedChunks[chunkKey] = world.GetChunkSync(chunkKey) as Chunk;
                        if (modifiedChunks[chunkKey] != null)
                        {
                            count++;
                        }
                    }
                }
            }

            sw.Stop();

            if (count < chunkCount)
            {
                BCCommandAbstract.SendOutput($"Unable to load {chunkCount - count}/{chunkCount} chunks");

                return(null);
            }

            BCCommandAbstract.SendOutput($"Loading {chunkCount} chunks took {Math.Round(sw.ElapsedMilliseconds / 1000f, 2)} seconds");

            return(modifiedChunks);
        }