Beispiel #1
0
        internal override void Receive()
        {
            lock (TcpClient)
            {
                base.Receive();
                var bytes = ReadStream(DataLength);
                PlayerId = BitConverter.ToInt32(bytes, 0);
                UserName = Encoding.ASCII.GetString(bytes, sizeof(int), 16).TrimEnd();
                Version = Encoding.ASCII.GetString(bytes, sizeof(int) + 16, 20).TrimEnd();
                Coords = new Coords(bytes, sizeof(int) + 16 + 20);
            }

            if (Config.IsServer)
            {
                if (Server.Controller.HasServerConsole) System.Media.SystemSounds.Exclamation.Play();
            }
            else
            {
                //todo: include position in this packet?
                NetworkClient.Players.TryAdd(PlayerId, new Player(PlayerId, UserName, Coords)); //note: it is not possible for the add to fail on ConcurrentDictionary, see: http://www.albahari.com/threading/part5.aspx#_Concurrent_Collections
                if (Game.UiHost != null) //ui host will be null for a client that is launching the game
                {
                    Game.UiHost.AddChatMessage(new ChatMessage(ChatMessageType.Server, string.Format("{0} has connected.", UserName)));
                    Sounds.Audio.PlaySound(Sounds.SoundType.PlayerConnect);
                }
            }
        }
Beispiel #2
0
 internal Mob(Coords coords, MobType type)
     : base(ref coords)
 {
     Type = type;
     WorldData.Mobs.TryAdd(Id, this);
     WorldData.Chunks[coords].Mobs.Add(this);
 }
Beispiel #3
0
        internal override void Receive()
        {
            if (!Config.IsSinglePlayer)
            {
                lock (TcpClient)
                {
                    base.Receive();
                    var bytes = ReadStream(DataLength);
                    Coords = new Coords(bytes, 0);
                    Velocity = new Vector3(BitConverter.ToSingle(bytes, sizeof(float) * 5),
                                           BitConverter.ToSingle(bytes, sizeof(float) * 6),
                                           BitConverter.ToSingle(bytes, sizeof(float) * 7));
                    BlockType = (Block.BlockType)BitConverter.ToUInt16(bytes, Coords.SIZE + Vector3.SizeInBytes);
                    GameObjectId = BitConverter.ToInt32(bytes, Coords.SIZE + Vector3.SizeInBytes + sizeof(ushort));
                }
            }

            //add the new block item to the chunk game items (note: constructor adds the item to the collection)
            var newBlockItem = new BlockItem(ref Coords, BlockType, Velocity, GameObjectId);

            if (Config.IsServer)
            {
                foreach (var player in Server.Controller.Players.Values)
                {
                    new AddBlockItem(ref newBlockItem.Coords, ref newBlockItem.Velocity, newBlockItem.BlockType, newBlockItem.Id) { ConnectedPlayer = player }.Send();
                }
            }
        }
Beispiel #4
0
        internal override void Receive()
        {
            if (!Config.IsSinglePlayer)
            {
                lock (TcpClient)
                {
                    base.Receive();
                    var bytes = ReadStream(DataLength);
                    Coords = new Coords(bytes, 0);
                    PlayerId = BitConverter.ToInt32(bytes, Coords.SIZE);
                }
            }

            if (Config.IsServer)
            {
                Server.Controller.Players[PlayerId].Coords = Coords;
                foreach (var player in Server.Controller.Players.Values)
                {
                    if (player.Id == PlayerId) continue; //no need to send move back to the player thats moving
                    //future enhancement could be to check if the other players are within renderable distance and skip sending the move packet to them
                    //-an issue will be that other players still need to somewhat know where each other are
                    //-could possibly be solved by sending no more than one move packet per second or something for players that are out of range
                    //	-this is enough to know where they are, prevent them from looking stuck when going out of range, etc.
                    //	-would cut down a lot of packets on servers with many players and large world, although this isnt really a big issue yet
                    new PlayerMove(Coords, PlayerId) { ConnectedPlayer = player }.Send();
                }
            }
            else if (!Config.IsSinglePlayer) //this is a network client
            {
                //gm: this assignment will be roughly 3x slower for ConcurrentDictionary, however is worth it for simpler code, less bugs and some performance gains for not having to lock while iterating
                //see: http://www.albahari.com/threading/part5.aspx#_Concurrent_Collections
                NetworkClient.Players[PlayerId].Coords = Coords;
            }
        }
Beispiel #5
0
 protected GameObject(XmlNode xmlNode)
 {
     if (xmlNode.Attributes == null) throw new Exception("Node attributes is null.");
     Id = int.Parse(xmlNode.Attributes["ID"].Value);
     if (Id >= WorldData.GameObjectIdSeq) System.Threading.Interlocked.Add(ref WorldData.GameObjectIdSeq, Id + 1); //ensure this loaded objects id will not conflict with the sequence
     Coords = new Coords(float.Parse(xmlNode.Attributes["X"].Value), float.Parse(xmlNode.Attributes["Y"].Value), float.Parse(xmlNode.Attributes["Z"].Value));
 }
Beispiel #6
0
        internal override void Receive()
        {
            if (!Config.IsSinglePlayer)
            {
                lock (TcpClient)
                {
                    base.Receive();
                    var bytes = ReadStream(DataLength);
                    Coords = new Coords(bytes, 0);
                    Velocity = new Vector3(BitConverter.ToSingle(bytes, Coords.SIZE),
                                           BitConverter.ToSingle(bytes, Coords.SIZE + sizeof(float)),
                                           BitConverter.ToSingle(bytes, Coords.SIZE + sizeof(float) * 2));
                    BlockType = (Block.BlockType)BitConverter.ToUInt16(bytes, Coords.SIZE + Vector3.SizeInBytes);
                    AllowBounce = BitConverter.ToBoolean(bytes, Coords.SIZE + Vector3.SizeInBytes + sizeof(ushort));
                    GameObjectId = BitConverter.ToInt32(bytes, Coords.SIZE + Vector3.SizeInBytes + sizeof(ushort) + sizeof(bool));
                }
            }

            var newProjectile = new Projectile(ref Coords, BlockType, AllowBounce, Velocity, GameObjectId);

            if (Config.IsServer)
            {
                foreach (var player in Server.Controller.Players.Values)
                {
                    new AddProjectile(ref newProjectile.Coords, ref newProjectile.Velocity, newProjectile.BlockType, newProjectile.AllowBounce, newProjectile.Id) { ConnectedPlayer = player }.Send();
                }
            }
        }
Beispiel #7
0
        //gm: from the OpenTK source code (Graphics\GraphicsMode.cs), here is GraphicsMode.Default, it does seem to select sensible choices -> default display bpp, 16 bit depth buffer, 0 bit stencil buffer, 2 buffers
        public Game()
            : base(Constants.DEFAULT_GAME_WIDTH, Constants.DEFAULT_GAME_HEIGHT, GraphicsMode.Default, string.Format("Voxel Game {0}: {1}", Settings.VersionDisplay, Config.UserName))
        {
            //note: cant easily thread these loading tasks because they all need to run on the thread that creates the GL context
            Settings.Game = this;
            Diagnostics.LoadDiagnosticProperties();

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            Sounds.Audio.LoadSounds(); //ensure sounds are loaded before they are needed
            Debug.WriteLine("Sounds load time: {0}ms", stopwatch.ElapsedMilliseconds);
            stopwatch.Restart();
            Textures.TextureLoader.Load(); //ensure textures are loaded before they are needed
            Debug.WriteLine("Textures load time: {0}ms", stopwatch.ElapsedMilliseconds);
            stopwatch.Restart();
            DisplayList.LoadDisplayLists(); //ensure display lists are loaded before they are needed
            Debug.WriteLine("Display Lists load time: {0}ms", stopwatch.ElapsedMilliseconds);

            VSync = Config.VSync ? VSyncMode.On : VSyncMode.Off;

            if (Config.IsSinglePlayer)
            {
                var playerCoords = new Coords(WorldData.SizeInBlocksX / 2f, 0, WorldData.SizeInBlocksZ / 2f); //start player in center of world
                playerCoords.Yf = WorldData.Chunks[playerCoords].HeightMap[playerCoords.Xblock % Chunk.CHUNK_SIZE, playerCoords.Zblock % Chunk.CHUNK_SIZE] + 1; //start player on block above the surface
                Player = new Player(0, Config.UserName, playerCoords);
                NetworkClient.Players.TryAdd(Player.Id, Player); //note: it is not possible for the add to fail on ConcurrentDictionary, see: http://www.albahari.com/threading/part5.aspx#_Concurrent_Collections
            }
        }
Beispiel #8
0
        internal Projectile(ref Coords coords, Block.BlockType blockType, bool allowBounce, Vector3? velocity = null, int id = -1)
            : base(ref coords, GameItemType.Projectile, allowBounce, velocity, id)
        {
            BlockType = blockType;

            //Stop += OnItemStop;
            Decay += OnItemDecay;
        }
Beispiel #9
0
 public AddBlockItem(ref Coords coords, ref Vector3 velocity, Block.BlockType blockType, int gameObjectId = -1)
     : this()
 {
     Coords = coords;
     Velocity = velocity;
     BlockType = blockType;
     GameObjectId = gameObjectId;
 }
Beispiel #10
0
 public AddProjectile(ref Coords coords, ref Vector3 velocity, Block.BlockType blockType, bool allowBounce, int gameObjectId = -1)
     : this()
 {
     Coords = coords;
     Velocity = velocity;
     BlockType = blockType;
     AllowBounce = allowBounce;
     GameObjectId = gameObjectId;
 }
Beispiel #11
0
 internal AddStaticItem(LightSource lightSource)
     : this()
 {
     Coords = lightSource.Coords;
     StaticItemType = StaticItemType.LightSource;
     SubType = (ushort)lightSource.Type;
     AttachedToFace = lightSource.AttachedToFace;
     GameObjectId = lightSource.Id;
 }
Beispiel #12
0
 public Connect(int playerId, string userName, Coords coords)
     : this()
 {
     PlayerId = playerId;
     UserName = userName.Length > 16 ? userName.Substring(0, 16) : userName;
     if (Settings.VersionDisplay.Length > 20) throw new Exception("Version string cannot be more than 20 characters.");
     Version = Settings.VersionDisplay;
     Coords = coords;
 }
Beispiel #13
0
 internal AddStaticItem(ref Coords coords, StaticItemType staticItemType, ushort subType, Face attachedToFace, int gameObjectId = -1)
     : this()
 {
     Coords = coords;
     StaticItemType = staticItemType;
     SubType = subType;
     AttachedToFace = attachedToFace;
     GameObjectId = gameObjectId;
 }
 internal GameItemDynamic(ref Coords coords, GameItemType type, bool allowBounce, Vector3? velocity = null, int id = -1)
     : base(ref coords, id)
 {
     Type = type;
     AllowBounce = allowBounce;
     if (velocity.HasValue) Velocity = velocity.Value;
     IsMoving = true;
     if (!WorldData.GameItems.ContainsKey(Id)) WorldData.GameItems.TryAdd(Id, this);
     var chunk = WorldData.Chunks[coords];
     if (!chunk.GameItems.ContainsKey(Id)) chunk.GameItems.TryAdd(Id, this);
 }
Beispiel #15
0
        internal BlockItem(ref Coords coords, Block.BlockType blockType, Vector3? velocity = null, int id = -1)
            : base(ref coords, GameItemType.BlockItem, true, velocity, id)
        {
            Coords.Xf = (float)Math.Floor(Coords.Xf) + Constants.HALF_BLOCK_SIZE; //spawn in the middle of the block
            Coords.Yf += Constants.HALF_BLOCK_SIZE;
            Coords.Zf = (float)Math.Floor(Coords.Zf) + Constants.HALF_BLOCK_SIZE;
            if (!Coords.IsValidItemLocation) throw new Exception(string.Format("Invalid BlockItem location: {0}", Coords));

            switch (blockType)
            {
                case Block.BlockType.Grass:
                case Block.BlockType.Snow:
                    BlockType = Block.BlockType.Dirt;
                    break;
                default:
                    BlockType = blockType;
                    break;
            }
        }
Beispiel #16
0
        internal override void Receive()
        {
            if (!Config.IsSinglePlayer)
            {
                lock (TcpClient)
                {
                    base.Receive();
                    var bytes = ReadStream(DataLength);
                    Coords = new Coords(bytes, 0);
                    StaticItemType = (StaticItemType)BitConverter.ToUInt16(bytes, Coords.SIZE);
                    SubType = BitConverter.ToUInt16(bytes, Coords.SIZE + sizeof(ushort));
                    AttachedToFace = (Face)BitConverter.ToUInt16(bytes, Coords.SIZE + sizeof(ushort) * 2);
                    GameObjectId = BitConverter.ToInt32(bytes, Coords.SIZE + sizeof(ushort) * 3);
                }
            }

            switch (StaticItemType)
            {
                case StaticItemType.Clutter:
                    throw new NotSupportedException("Clutter cannot be placed yet.");
                case StaticItemType.LightSource:
                    new LightSource(ref Coords, (LightSourceType)SubType, AttachedToFace, GameObjectId);
                    if (!Config.IsServer) //lighting needs to be updated and affected chunks queued for non servers when adding a light source
                    {
                        var position = Coords.ToPosition();
                        Task<Queue<Chunk>>.Factory.StartNew(() => Lighting.UpdateLightBox(ref position, null, false, false)).ContinueWith(task => WorldData.QueueAffectedChunks(task.Result));
                    }
                    break;
                default:
                    throw new Exception(string.Format("Unknown static item type: {0}", StaticItemType));
            }

            if (Config.IsServer)
            {
                foreach (var player in Server.Controller.Players.Values)
                {
                    new AddStaticItem(ref Coords, StaticItemType, SubType, AttachedToFace, GameObjectId) {ConnectedPlayer = player}.Send();
                }
            }
        }
Beispiel #17
0
 public static void RenderDisplayList(int displayListId, ref Coords coords, BlockTextureType texture)
 {
     GL.BindTexture(TextureTarget.Texture2D, TextureLoader.GetBlockTexture(texture));
     GL.PushMatrix();
     GL.Translate(coords.Xf, coords.Yf, coords.Zf);
     GL.CallList(displayListId);
     GL.PopMatrix();
 }
Beispiel #18
0
        /// <summary>Render all transparent faces in the chunk by looping through each texture vbo in the chunk, binding that texture and then rendering all of the applicable faces.</summary>
        /// <remarks>The vbo will be null if this chunk does not contain any faces with the corresponding texture.</remarks>
        public void RenderTransparentFaces()
        {
            if (ChunkBufferState == BufferState.VboNotBuffered || !IsInFrustum) return;

            bool isUnderWater = Game.Player.EyesUnderWater;
            var waterChunkVbo = _chunkVbos[(int)BlockTextureType.Water];
            if (waterChunkVbo != null && !isUnderWater) waterChunkVbo.Render(); //if this chunk contains water and the player is not under water then draw the water before anything else

            //render clutter / light sources
            //we already know this chunk is in the frustum if we make it here, now check its within a certain distance
            //also we know clutter / light source are likely to be on the surface, so render before other transparent faces such as leaves (not including water)
            if (DistanceFromPlayer() < CLUTTER_RENDER_DISTANCE)
            {
                GL.PushMatrix();
                var previousCoords = new Coords(0, 0, 0);
                foreach (var clutter in Clutters)
                {
                    //translate to each piece of clutter relative to the last so we only need to push the matrix stack once
                    GL.Translate(clutter.Coords.Xf - previousCoords.Xf, clutter.Coords.Yf - previousCoords.Yf, clutter.Coords.Zf - previousCoords.Zf);
                    clutter.Render(null);
                    previousCoords = clutter.Coords;
                }

                foreach (var lightSource in LightSources)
                {
                    //translate to each light source relative to the last so we only need to push the matrix stack once
                    GL.Translate(lightSource.Value.Coords.Xf - previousCoords.Xf, lightSource.Value.Coords.Yf - previousCoords.Yf, lightSource.Value.Coords.Zf - previousCoords.Zf);
                    lightSource.Value.Render(null);
                    previousCoords = lightSource.Value.Coords;
                }

                GL.PopMatrix();
                GameObject.ResetColor();
            }

            foreach (var chunkVbo in _chunkVbos)
            {
                if (chunkVbo == null) continue;
                if (!chunkVbo.IsTransparent || chunkVbo.BlockType == Block.BlockType.Water) continue;
                chunkVbo.Render();
            }

            if (waterChunkVbo != null && isUnderWater) waterChunkVbo.Render(); //if this chunk contains water and the player is under water then draw the water last
        }
Beispiel #19
0
 protected GameObject(ref Coords coords, int id = -1)
 {
     if (!(this is Player) && !coords.IsValidItemLocation) throw new Exception(string.Format("Invalid item location: {0}", coords));
     Id = id > -1 && !Config.IsServer ? id : WorldData.NextGameObjectId; //if this is a server we need to select our own IDs, ignore what the client said
     Coords = coords;
 }
Beispiel #20
0
 internal Block this[Coords coords]
 {
     get { return(new Block(Array[coords.Yblock, coords.Xblock % Chunk.CHUNK_SIZE, coords.Zblock % Chunk.CHUNK_SIZE])); }
     set { Array[coords.Yblock, coords.Xblock % Chunk.CHUNK_SIZE, coords.Zblock % Chunk.CHUNK_SIZE] = value.BlockData; }
 }
Beispiel #21
0
 /// <summary>Is this position and the compare coords the same block. Fast check as no math is required.</summary>
 /// <remarks>Use this to prevent building on blocks a player is standing on, etc.</remarks>
 internal bool IsOnBlock(ref Coords coords)
 {
     return(X == coords.Xblock && Y == coords.Yblock && Z == coords.Zblock);
 }
Beispiel #22
0
 public bool IsOnBlock(ref Coords compare)
 {
     return Xblock == compare.Xblock && Yblock == compare.Yblock && Zblock == compare.Zblock;
 }
Beispiel #23
0
 /// <summary>Get a block using world coords.</summary>
 internal static Block GetBlock(ref Coords coords)
 {
     return Chunks[coords].Blocks[coords];
 }
Beispiel #24
0
 /// <summary>Get a block using world coords.</summary>
 internal static Block GetBlock(ref Coords coords)
 {
     return(Chunks[coords].Blocks[coords]);
 }
Beispiel #25
0
 public PlayerMove(Coords coords, int playerId)
     : this()
 {
     Coords = coords;
     PlayerId = playerId;
 }
Beispiel #26
0
 internal Clutter(Coords coords, ClutterType type)
     : base(ref coords, Face.Bottom)
 {
     Type = type;
     WorldData.Chunks[coords].Clutters.Add(this);
 }
Beispiel #27
0
 /// <summary>Get a chunk from the array. Based on world coords.</summary>
 public Chunk this[Coords coords]
 {
     get { return(_chunks[coords.Xblock / Chunk.CHUNK_SIZE, coords.Zblock / Chunk.CHUNK_SIZE]); }
 }
Beispiel #28
0
 protected void Write(ref Coords coords)
 {
     Write(coords.ToByteArray(), Coords.SIZE);
 }
Beispiel #29
0
 /// <summary>Plays a sound with a volume relative to how far from the listener it is.</summary>
 /// <param name="sound">sound type to play</param>
 /// <param name="sourceCoords">source coords of the sound</param>
 /// <param name="maxDistance">max distance the sound can be heard</param>
 internal static void PlaySound(SoundType sound, ref Coords sourceCoords, byte maxDistance = 25)
 {
     if (!Config.SoundEnabled) return;
     float gain = (maxDistance - Game.Player.Coords.GetDistanceExact(ref sourceCoords)) / maxDistance;
     Play(sound, gain);
 }
Beispiel #30
0
        public static void SendPlayerLocation(Coords newCoords, bool forceSend = false)
        {
            var minDeltaToBeDiff = (Players.Count >= 5 ? Constants.BLOCK_SIZE / 4 : Constants.BLOCK_SIZE / 8);
            var minAngleToBeDiff = (Players.Count >= 5 ? Constants.PI_OVER_6 : Constants.PI_OVER_12);
            if (forceSend || Math.Abs(_prevCoords.Xf - newCoords.Xf) > minDeltaToBeDiff || Math.Abs(_prevCoords.Yf - newCoords.Yf) > minDeltaToBeDiff || Math.Abs(_prevCoords.Zf - newCoords.Zf) > minDeltaToBeDiff || Math.Abs(_prevCoords.Direction - newCoords.Direction) > minAngleToBeDiff || Math.Abs(_prevCoords.Pitch - newCoords.Pitch) > minAngleToBeDiff)
            {
                new PlayerMove(newCoords, Game.Player.Id).Send();

                var chunk = WorldData.Chunks[newCoords];
                foreach (var gameItem in chunk.GameItems.Values)
                {
                    if (gameItem.Type == GameItemType.BlockItem && newCoords.GetDistanceExact(ref gameItem.Coords) <= 2)
                    {
                        if (!Config.CreativeMode)
                        {
                            new PickupBlockItem(Game.Player.Id, gameItem.Id).Send();
                        }
                    }
                }

                _prevCoords = newCoords;
            }
        }
Beispiel #31
0
 /// <summary>Get the exact distance from the supplied coords.</summary>
 public float GetDistanceExact(ref Coords coords)
 {
     return (float)Math.Sqrt(Math.Pow(Xf - coords.Xf, 2) + Math.Pow(Yf - coords.Yf, 2) + Math.Pow(Zf - coords.Zf, 2));
 }
Beispiel #32
0
        /// <summary>Process a user entered slash command.</summary>
        /// <remarks>
        /// when a command is successful use 'return' to leave the function
        /// when a command is not succesful use 'break' for an invalid command msg to get displayed
        /// </remarks>
        public static void ProcessSlashCommand(string text)
        {
            if (text.Length <= 1) { AddSlashResult("Unknown command."); return;}
            LastSlashCommand = text;
            var args = text.TrimStart('/').ToLower().Split(' ');
            switch (args[0])
            {
                case "?":
                case "help":
                case "commands":
                    DisplayCommandHelp();
                    return;
                case "admin":
                    if (ArgCountInvalid(2, args)) return;
                    new PlayerOption(PlayerOption.OptionType.Admin, System.Text.Encoding.UTF8.GetBytes(args[1])).Send();
                    return;
                case "broadcast":
                    if (Config.IsSinglePlayer) { AddSlashResult("Only available in Multiplayer."); return; }
                    new ServerCommand(ServerCommandType.Broadcast).Send(); //this would still need a way to send the actual message
                    return;
                case "clear":
                    Game.UiHost.ClearChatMessages();
                    return;
                case "cr":
                case "creative":
                    if (args.Length == 1) { AddSlashResult(string.Format("Creative mode {0}.", Config.CreativeMode ? "On" : "Off")); return; }
                    if (ArgCountInvalid(2, args)) return;
                    switch (args[1])
                    {
                        case "on":
                            new PlayerOption(PlayerOption.OptionType.Creative, BitConverter.GetBytes(1)).Send();
                            return;
                        case "off":
                            new PlayerOption(PlayerOption.OptionType.Creative, BitConverter.GetBytes(0)).Send();
                            return;
                    }
                    break;
                case "ci":
                case "chunk":
                    var chunk = WorldData.Chunks[Game.Player.Coords];
                    AddSlashResult(string.Format("Chunk {0}: VBOs {1}; Primitives {2}; Deepest transparent level {3}; Highest non air level {4}", chunk.Coords, chunk.VboCount, chunk.PrimitiveCount, chunk.DeepestTransparentLevel, chunk.HighestNonAirLevel));
                    return;
                case "cu":
                case "chunkupdates":
                    if (ArgCountInvalid(2, args)) return;
                    switch (args[1])
                    {
                        case "on": Settings.ChunkUpdatesDisabled = false; AddSlashResult("Chunk updates enabled."); return;
                        case "off": Settings.ChunkUpdatesDisabled = true; AddSlashResult("Chunk updates disabled."); return;
                    }
                    break;
                case "heightmap":
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    AddSlashResult(string.Format("HeightMap value for {0} is {1}", BlockCursorHost.Position, WorldData.Chunks[BlockCursorHost.Position].HeightMap[BlockCursorHost.Position.X % Chunk.CHUNK_SIZE, BlockCursorHost.Position.Z % Chunk.CHUNK_SIZE]));
                    return;
                case "id":
                    AddSlashResult(string.Format("UserName: {0} (Id {1})", Game.Player.UserName, Game.Player.Id));
                    return;
                case "invhack":
                    for (int i = 0; i < Game.Player.Inventory.Length; i++) Game.Player.Inventory[i] += 200;
                    return;
                case "itemcount":
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    AddSlashResult(string.Format("World contains {0} items.", WorldData.GameItems.Count));
                    return;
                case "lantern":
                    var position = BlockCursorHost.PositionAdd;
                    if (WorldData.IsValidStaticItemPosition(position))
                    {
                        var lantern = new LightSource(ref position, LightSourceType.Lantern, BlockCursorHost.SelectedFace.ToOpposite());
                        new AddStaticItem(lantern).Send();
                    }
                    return;
                case "loc":
                case "location":
                    AddSlashResult(string.Format("{0}:", Game.Player.UserName));
                    AddSlashResult(string.Format(" Block {0}", Game.Player.Coords));
                    AddSlashResult(string.Format(" Coords (x={0}, y={1}, z={2})", Game.Player.Coords.Xf, Game.Player.Coords.Yf, Game.Player.Coords.Zf));
                    AddSlashResult(string.Format(" Dir ({0}) Pitch ({1})", MathHelper.RadiansToDegrees(Game.Player.Coords.Direction), MathHelper.RadiansToDegrees(Game.Player.Coords.Pitch)));
                    return;
                case "maxtexturesize":
                    int mts;
                    GL.GetInteger(GetPName.MaxTextureSize, out mts);
                    AddSlashResult("Max texture size: " + mts);
                    return;
                case "m":
                case "move":
                    if (ArgCountInvalid(3, args)) return;
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    short moveTo;
                    if (!short.TryParse(args[2], out moveTo)) break;
                    var newCoords = Game.Player.Coords;
                    switch (args[1])
                    {
                        case "x": newCoords.Xf = moveTo; break;
                        case "y": newCoords.Yf = moveTo; break;
                        case "z": newCoords.Zf = moveTo; break;
                    }
                    if (!newCoords.Equals(Game.Player.Coords))
                    {
                        if (newCoords.IsValidPlayerLocation) { Game.Player.Coords = newCoords; return; }
                        AddSlashResult("Invalid location.");
                        return;
                    }
                    break;
                case "movechunk":
                case "movetochunk":
                    if (ArgCountInvalid(3, args)) return;
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    byte chunkX, chunkZ;
                    if (!byte.TryParse(args[1], out chunkX) || !byte.TryParse(args[2], out chunkZ)) break;
                    var newChunkMoveCoords = new Coords(chunkX * Chunk.CHUNK_SIZE + Chunk.CHUNK_SIZE / 2, Chunk.CHUNK_HEIGHT, chunkZ * Chunk.CHUNK_SIZE + Chunk.CHUNK_SIZE / 2, Game.Player.Coords.Direction, Game.Player.Coords.Pitch);
                    if (newChunkMoveCoords.IsValidPlayerLocation) { Game.Player.Coords = newChunkMoveCoords; return; }
                    break;
                case "music":
                    if (ArgCountInvalid(2, args)) return;
                    if (!Config.SoundEnabled) { AddSlashResult("Sound is disabled."); return; }
                    switch (args[1])
                    {
                        case "on":
                            if (!Config.MusicEnabled)
                            {
                                Config.MusicEnabled = true;
                                Config.Save();
                                Sounds.Music.StartMusic();
                            }
                            AddSlashResult("Music enabled.");
                            return;
                        case "off":
                            Config.MusicEnabled = false;
                            Config.Save();
                            Sounds.Music.StopMusic();
                            AddSlashResult("Music disabled.");
                            return;
                    }
                    break;
                case "opengl":
                    AddSlashResult(Utilities.Diagnostics.OpenGlInfo());
                    return;
                case "outline":
                    Settings.OutlineChunks = !Settings.OutlineChunks;
                    WorldData.Chunks.QueueAllWithinViewDistance();
                    AddSlashResult(string.Format("Chunk outlining {0}.", Settings.OutlineChunks ? "enabled" : "disabled"));
                    return;
                case "phack":
                case "playerhack":
                    NetworkClient.Players.TryAdd(5000, new Player(5000, "Tester McGee", new Coords(Game.Player.Coords.Xf - 1, Game.Player.Coords.Yf, Game.Player.Coords.Zf, Game.Player.Coords.Direction, Game.Player.Coords.Pitch)));
                    NetworkClient.Players.TryAdd(5001, new Player(5001, "Tester McGee2", new Coords(Game.Player.Coords.Xf + 3, Game.Player.Coords.Yf, Game.Player.Coords.Zf, Game.Player.Coords.Direction + MathHelper.Pi, Game.Player.Coords.Pitch)));
                    return;
                case "raiseexception":
                    //-can be used to test the msgbox error handler in release mode
                    //-can be used to test obfuscation was done properly by looking at the stack trace displayed in release mode
                    throw new Exception("Manually created exception from slash command.");
                case "server":
                    AddSlashResult(Config.IsSinglePlayer ? "Not applicable in single player mode." : string.Format("{0}:{1}", NetworkClient.ServerIp, NetworkClient.ServerPort));
                    return;
                case "serverversion":
                    if (Config.IsSinglePlayer) { AddSlashResult("Not applicable in single player mode."); return; }
                    new ServerCommand(ServerCommandType.ServerVersion).Send();
                    return;
                case "sp":
                case "speed":
                    if (ArgCountInvalid(2, args)) return;
                    switch (args[1])
                    {
                        case "on":
                            new PlayerOption(PlayerOption.OptionType.Speed, BitConverter.GetBytes(5)).Send();
                            return;
                        case "off":
                            new PlayerOption(PlayerOption.OptionType.Speed, BitConverter.GetBytes(1)).Send();
                            return;
                        default:
                            int multiplier;
                            if (int.TryParse(args[1], out multiplier))
                            {
                                new PlayerOption(PlayerOption.OptionType.Speed, BitConverter.GetBytes(multiplier)).Send();
                                return;
                            }
                            break;
                    }
                    break;
                case "sound":
                    if (ArgCountInvalid(2, args)) return;
                    switch (args[1])
                    {
                        case "on":
                            Config.SoundEnabled = true;
                            Sounds.Audio.LoadSounds();
                            AddSlashResult("Sound enabled.");
                            return;
                        case "off":
                            Config.SoundEnabled = false;
                            Sounds.Audio.Dispose();
                            AddSlashResult("Sound disabled.");
                            return;
                    }
                    break;
                case "stuck":
                    Game.Player.Coords = new Coords(WorldData.SizeInBlocksX / 2f, Chunk.CHUNK_HEIGHT, WorldData.SizeInBlocksZ / 2f, Game.Player.Coords.Direction, Game.Player.Coords.Pitch);
                    return;
                case "sun":
                    if (ArgCountInvalid(2, 3, args)) return;
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    switch (args[1])
                    {
                        case "loc":
                        case "info":
                        case "position":
                        case "speed":
                            AddSlashResult(string.Format("Sun: Degrees {0}, Strength {1}, Speed {2}", MathHelper.RadiansToDegrees(SkyHost.SunAngleRadians), SkyHost.SunLightStrength, SkyHost.SpeedMultiplier));
                            return;
                        case "move":
                        case "degrees":
                            if (ArgCountInvalid(3, args)) return;
                            ushort sunDegrees;
                            if (ushort.TryParse(args[2], out sunDegrees) && sunDegrees <= 360)
                            {
                                new ServerCommand(ServerCommandType.MoveSun, sunDegrees).Send();
                                return;
                            }
                            AddSlashResult("Invalid degrees.");
                            return;
                    }

                    //following commands only work in single player
                    if (!Config.IsSinglePlayer) { AddSlashResult("Cannot change sun speed in Multiplayer."); return; }
                    switch (args[1])
                    {
                        case "+":
                        case "faster":
                            SkyHost.SpeedMultiplier *= 2;
                            AddSlashResult("Sun speed increased.");
                            return;
                        case "-":
                        case "slower":
                            SkyHost.SpeedMultiplier /= 2;
                            AddSlashResult("Sun speed decreased.");
                            return;
                        case "default":
                        case "start":
                            SkyHost.SpeedMultiplier = SkyHost.DEFAULT_SPEED_MULTIPLIER;
                            AddSlashResult("Sun reset to default speed.");
                            return;
                        case "stop":
                            SkyHost.SpeedMultiplier = 0;
                            AddSlashResult("Sun stopped.");
                            return;
                    }
                    break;
                case "tp":
                case "teleport":
                    if (ArgCountInvalid(2, args)) return;
                    int playerId;
                    if (!Config.CreativeMode)
                    {
                        AddSlashResult("Must be in Creative Mode.");
                    }
                    else if (!int.TryParse(args[1], out playerId) || !NetworkClient.Players.ContainsKey(playerId))
                    {
                        AddSlashResult("Invalid player id.");
                    }
                    else if(playerId == Game.Player.Id)
                    {
                        AddSlashResult("Cannot teleport to yourself.");
                    }
                    else
                    {
                        Game.Player.Coords = NetworkClient.Players[playerId].Coords;
                    }
                    return;
                case "throwexception":
                    new ThrowException().Send();
                    return;
                case "time":
                    AddSlashResult(string.Format("Time in game: {0:h:mm tt}", SkyHost.Time));
                    return;
                case "ui":
                    if (ArgCountInvalid(2, args)) return;
                    switch (args[1])
                    {
                        case "on": Settings.UiDisabled = false; AddSlashResult("UI enabled."); return;
                        case "off": Settings.UiDisabled = true; AddSlashResult("UI disabled."); return;
                    }
                    break;
                case "username":
                    AddSlashResult(Game.Player.UserName);
                    return;
                case "ver":
                case "version":
                    AddSlashResult(string.Format("Version {0}", Settings.VersionDisplay));
                    return;
                case "vd":
                case "view":
                case "viewdistance":
                    switch (args.Length)
                    {
                        case 1:
                            AddSlashResult(string.Format("{0} ({1} blocks)", Config.ViewDistance, Settings.ZFar));
                            return;
                        case 2:
                            //view distance can be changed by either entering the string view distance or the numeric enum value
                            //the check of enum length is needed because the TryParse lets numeric values through that are larger then the number of values strangely
                            ViewDistance vd;
                            if (Enum.TryParse(args[1], true, out vd) && (int)vd < Enum.GetValues(typeof(ViewDistance)).Length)
                            {
                                Utilities.Misc.ChangeViewDistance(vd);
                                AddSlashResult(string.Format("{0} ({1} blocks)", Config.ViewDistance, Settings.ZFar));
                            }
                            else
                            {
                                AddSlashResult("Unknown view distance.");
                            }
                            return;
                    }
                    break;
                case "vsync":
                    Config.VSync = !Config.VSync;
                    Settings.Game.VSync = Config.VSync ? VSyncMode.On : VSyncMode.Off;
                    AddSlashResult("VSync: " + Settings.Game.VSync);
                    return;
                case "walloftext":
                    for (int i = 0; i < 10; i++) AddSlashResult(new string('X', 80));
                    return;
                case "who":
                    switch (args.Length)
                    {
                        case 1:
                            if (NetworkClient.Players.Count > 1) AddSlashResult(string.Format("{0} players connected:", NetworkClient.Players.Count));
                            foreach (var player in NetworkClient.Players.Values) AddSlashResult(player);
                            return;
                        case 2:
                            foreach (var player in NetworkClient.Players.Values.Where(player => player.UserName.Equals(args[1], StringComparison.InvariantCultureIgnoreCase)))
                            {
                                AddSlashResult(player);
                                return;
                            }
                            AddSlashResult("Player not found.");
                            return;
                    }
                    break;
                case "wireframe":
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    int mode;
                    GL.GetInteger(GetPName.PolygonMode, out mode);
                    GL.PolygonMode(MaterialFace.FrontAndBack, mode == (int)PolygonMode.Fill ? PolygonMode.Line : PolygonMode.Fill);
                    return;
                case "worldname":
                    AddSlashResult(string.Format("World name: {0}", Settings.WorldName));
                    return;
                case "worldsave":
                    if (Config.IsSinglePlayer)
                    {
                        System.Threading.Tasks.Task.Factory.StartNew(WorldData.SaveToDisk).ContinueWith(task => AddSlashResult(string.Format("World saved: {0}", Settings.WorldFilePath)));
                    }
                    else
                    {
                        AddSlashResult("Cannot save in Multiplayer.");
                    }
                    return;
                case "worldsize":
                case "size":
                    new ServerCommand(ServerCommandType.WorldSize).Send();
                    return;
                case "worldtype":
                    AddSlashResult(string.Format("World type: {0}", WorldData.WorldType));
                    return;
                case "xmldump":
                    if (!Config.CreativeMode) { AddSlashResult("Must be in Creative Mode."); return; }
                    var xml = WorldSettings.GetXmlByteArray();
                    using (var file = new FileStream(Path.Combine(Config.SaveDirectory.FullName, Settings.WorldName) + ".xml", FileMode.Create))
                    {
                        file.Write(xml, 0, xml.Length);
                        AddSlashResult("Dumped XML to " + file.Name);
                        file.Close();
                    }
                    return;
            }
            AddSlashResult("Invalid command.");
        }
Beispiel #33
0
 internal Block this[Coords coords]
 {
     get { return new Block(Array[coords.Yblock, coords.Xblock % Chunk.CHUNK_SIZE, coords.Zblock % Chunk.CHUNK_SIZE]); }
     set { Array[coords.Yblock, coords.Xblock % Chunk.CHUNK_SIZE, coords.Zblock % Chunk.CHUNK_SIZE] = value.BlockData; }
 }
Beispiel #34
0
 /// <summary>Is this position and the compare coords the same block. Fast check as no math is required.</summary>
 /// <remarks>Use this to prevent building on blocks a player is standing on, etc.</remarks>
 internal bool IsOnBlock(ref Coords coords)
 {
     return X == coords.Xblock && Y == coords.Yblock && Z == coords.Zblock;
 }