Ejemplo n.º 1
0
        private BinaryTagNodeMultiple GetCompressedBinaryTagBlock(uint blockID, int len)
        {
            var currentNode = new BinaryTagNodeMultiple("_");

            var blockNode  = new BinaryTagNodeUShort("block");
            var lengthNode = new BinaryTagNodeUShort("length");             //Biggest possible value is 4096 so ushort

            lengthNode.Value = (ushort)Math.Max(0, len);
            blockNode.Value  = (ushort)blockID;

            currentNode.Add(lengthNode);
            currentNode.Add(blockNode);

            return(currentNode);
        }
Ejemplo n.º 2
0
        public void PopulateFromBinaryTag(BinaryTagNodeMultiple tag)
        {
            #region Block Loading
            var blocksNode           = (BinaryTagNodeList)tag.Get("blocks");
            var blockCompressionType = (BinaryTagNodeByte)tag.Get("blockCompression");

            if (blocksNode != null && blockCompressionType != null)
            {
                //No compression
                if (blockCompressionType.Value == 0)
                {
                    for (int i = 0; i < blocksNode.Count; i++)
                    {
                        var node = (BinaryTagNodeUShort)blocksNode[i];

                        if (node != null)
                        {
                            var nodeName = node.Name;
                            int pos      = int.Parse(nodeName);

                            int x, y, z;
                            z    = pos / (CHUNK_SIZE * CHUNK_SIZE);
                            pos -= (z * CHUNK_SIZE * CHUNK_SIZE);
                            y    = pos / CHUNK_SIZE;
                            x    = pos % CHUNK_SIZE;

                            chunk_blockdata[x, y, z] = node.Value;
                        }
                    }
                }
                //Compression Section
                else if (blockCompressionType.Value == 1)
                {
                    //used for traversing the linear array
                    int linearPosition = -1;

                    for (int i = 0; i < blocksNode.Count; i++)
                    {
                        var nodeRoot = (BinaryTagNodeMultiple)blocksNode[i];

                        if (nodeRoot != null)
                        {
                            var blockID = (BinaryTagNodeUShort)nodeRoot.Get("block");
                            var length  = (BinaryTagNodeUShort)nodeRoot.Get("length");

                            //null check
                            if (blockID != null && length != null)
                            {
                                for (int j = 0; j < length.Value; j++)
                                {
                                    linearPosition++;

                                    //Convert from linear to 3d
                                    var posTmp = linearPosition;

                                    int x, y, z;
                                    z       = posTmp / (CHUNK_SIZE * CHUNK_SIZE);
                                    posTmp -= (z * CHUNK_SIZE * CHUNK_SIZE);
                                    y       = posTmp / CHUNK_SIZE;
                                    x       = posTmp % CHUNK_SIZE;

                                    chunk_blockdata[x, y, z] = blockID.Value;
                                }
                            }
                        }
                    }
                }
            }
            #endregion

            #region Block State Loading

            #endregion

            #region Lighting Loading

            #endregion

            #region Metadata Loading

            #endregion

            #region Block Updates
            var blockUpdatesNodes = (BinaryTagNodeList)tag.Get("updates");

            if (blockUpdatesNodes != null)
            {
                for (int i = 0; i < blockUpdatesNodes.Count; i++)
                {
                    var theThing = (BinaryTagNodeInt)blockUpdatesNodes[i];
                    if (theThing != null && theThing.Name == "block_update")
                    {
                        //Extract the X, Y, Z values from the int
                        int x, y, z;
                        z = theThing.Value / (CHUNK_SIZE * CHUNK_SIZE);
                        theThing.Value -= (z * CHUNK_SIZE * CHUNK_SIZE);
                        y = theThing.Value / CHUNK_SIZE;
                        x = theThing.Value % CHUNK_SIZE;

                        //Add the block update
                        Vector3Int theVector = new Vector3Int(x, y, z);
                        chunk_updates.Add(GetHash(x, y, z), theVector);
                    }
                }
            }

            #endregion
        }
Ejemplo n.º 3
0
        public void LoadChunks()
        {
            //TODO: Deserialize

            //ROADMAP:
            //
            // Get chunks folder
            // Get level data
            // Get player position
            // Apply level data
            // Get chunk at player pos
            // Read
            // Update => if(chunkManager.ChunkCount < ChunkThreshold) { return; }

            #region World Data
            BinaryTagNode levelData = FileUtil.DeseralizeFromFile(Path.Combine(WorldDirectory, "level.dat"));

            if (levelData.Type == TagType.TagEnd)
            {
                Logger.error(-1, "The file \"" + Path.Combine(WorldDirectory, "level.dat") + "\" doesn't exist, or is malformed!");
            }
            if (levelData.Type == TagType.TagMultiple)
            {
                try
                {
                    BinaryTagNodeMultiple levelRoot = (BinaryTagNodeMultiple)levelData;

                    #region Player state
                    BinaryTagNodeMultiple playerTag = (BinaryTagNodeMultiple)levelRoot.Get("player");

                    BinaryTagNodeMultiple playerPosTag = (BinaryTagNodeMultiple)playerTag.Get("position");
                    BinaryTagNodeMultiple playerRotTag = (BinaryTagNodeMultiple)playerTag.Get("rotation");

                    player.position.X = ((BinaryTagNodeFloat)playerPosTag.Get("X")).Value;
                    player.position.Y = ((BinaryTagNodeFloat)playerPosTag.Get("Y")).Value;
                    player.position.Z = ((BinaryTagNodeFloat)playerPosTag.Get("Z")).Value;

                    player.camera.Pitch = ((BinaryTagNodeFloat)playerRotTag.Get("X")).Value;
                    player.camera.Yaw   = ((BinaryTagNodeFloat)playerRotTag.Get("Y")).Value;
                    player.camera.Roll  = ((BinaryTagNodeFloat)playerRotTag.Get("Z")).Value;

                    player.HeldSlot = ((BinaryTagNodeByte)playerTag.Get("inventorySlot")).Value;

                    //TODO: Deserialize inventory
                    #endregion

                    seed = ((BinaryTagNodeLong)levelRoot.Get("seed")).Value;
                }
                catch (Exception ex)
                {
                    Logger.error(-1, "MalformedBinaryTagNodeException:\n" + ex.StackTrace);
                }
            }
            #endregion

            #region Chunks

            string chunkFolder = Path.Combine(WorldDirectory, "chunks");

            if (Directory.Exists(chunkFolder))
            {
                string[] fileEntries = Directory.GetFiles(chunkFolder, "*.cnk");

                for (int i = 0; i < fileEntries.Length; i++)
                {
                    //TODO: loop through chunks folder
                    BinaryTagNode chunkData = FileUtil.DeseralizeFromFile(fileEntries[i]);

                    if (chunkData.Type == TagType.TagEnd)
                    {
                        Logger.error(-1, "The file \"" + Path.Combine(chunkFolder, "level.dat") + "\" doesn't exist, or is malformed!");
                    }
                    if (chunkData.Type == TagType.TagMultiple)
                    {
                        try
                        {
                            var chunkRoot = (BinaryTagNodeMultiple)chunkData;

                            var chunkX = ((BinaryTagNodeInt)chunkRoot.Get("X"));
                            var chunkY = ((BinaryTagNodeInt)chunkRoot.Get("Y"));
                            var chunkZ = ((BinaryTagNodeInt)chunkRoot.Get("Z"));

                            if (chunkX != null && chunkY != null && chunkZ != null)
                            {
                                var hash = Chunk.GetHash(chunkX.Value, chunkY.Value, chunkZ.Value);

                                if (chunks.ContainsKey(hash))
                                {
                                    chunks[hash].PopulateFromBinaryTag(chunkRoot);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.error(-1, "MalformedBinaryTagNodeException:\n" + ex.StackTrace);
                        }
                    }
                }
            }
            #endregion
        }
Ejemplo n.º 4
0
        public BinaryTagNodeMultiple SerializeToBinaryTag()
        {
            BinaryTagNodeMultiple rootTag = new BinaryTagNodeMultiple("root");

            //Position. Most important parts
            rootTag.Add(new BinaryTagNodeInt("X", posX));
            rootTag.Add(new BinaryTagNodeInt("Y", posY));
            rootTag.Add(new BinaryTagNodeInt("Z", posZ));

            //Chunk versioning. Unused for now, to be used by the file upgrader API when written.
            rootTag.Add(new BinaryTagNodeUShort("version", 0));

            #region Block Compression
            byte blockCompressionID = 1;

            //TODO: Compress with all algorithms, determine smallest and write smallest to file

            #region No Compression
            //Convert the block array to a flat linear array
            var blockFlatArr = new List <BinaryTagNode>();

            for (int z = 0; z < CHUNK_SIZE; z++)
            {
                for (int y = 0; y < CHUNK_SIZE; y++)
                {
                    for (int x = 0; x < CHUNK_SIZE; x++)
                    {
                        int pos = (z * CHUNK_SIZE * CHUNK_SIZE) + (y * CHUNK_SIZE) + x;
                        blockFlatArr.Add(new BinaryTagNodeUShort(pos.ToString(), (ushort)chunk_blockdata[x, y, z]));
                    }
                }
            }
            #endregion

            #region Compression Variant 1
            var blockCompressedArr = new List <BinaryTagNode>();

            uint size           = 56;
            uint currentBlockID = 0;
            int  blockLength    = 0;

            for (int z = 0; z < CHUNK_SIZE; z++)
            {
                for (int y = 0; y < CHUNK_SIZE; y++)
                {
                    for (int x = 0; x < CHUNK_SIZE; x++)
                    {
                        //get the voxel and check if its the current block
                        if (chunk_blockdata[x, y, z] == currentBlockID)
                        {
                            blockLength++;
                        }
                        else
                        {
                            //Add data to the binarytag
                            var currentNode = GetCompressedBinaryTagBlock(currentBlockID, Math.Max(0, blockLength));
                            blockCompressedArr.Add(currentNode);

                            size += 56;                             //Assuming each part is 16 + 8 bits (BlockID) + 16 + 8 bits (Length) + 8 bits (TagMultiple)

                            //Reset
                            currentBlockID = chunk_blockdata[x, y, z];
                            blockLength    = 1;
                        }
                    }
                }
            }

            blockCompressedArr.Add(GetCompressedBinaryTagBlock(currentBlockID, Math.Max(0, blockLength)));

            #endregion

            if (size >= 98304)             //(16 + 8) bits * 4096 entries (no compression)
            {
                blockCompressionID = 0;
            }

            rootTag.Add(new BinaryTagNodeByte("blockCompression", blockCompressionID));

            if (blockCompressionID == 0)
            {
                rootTag.Add(new BinaryTagNodeList("blocks", blockFlatArr));
            }
            else if (blockCompressionID == 1)
            {
                rootTag.Add(new BinaryTagNodeList("blocks", blockCompressedArr));
            }
            #endregion

            #region Block states

            //TODO: Compress blockstates

            #endregion

            #region Lighting

            //TODO: Compress sky light

            //TODO: Compress block light

            #endregion

            #region Metadata

            //TODO: Compress blockmeta

            #endregion

            #region Tickables

            //No updates means we don't bother adding it, since its the default state
            if (chunk_updates.Count > 0)
            {
                #region No Compression
                //Convert the block array to a flat linear array
                var tickFlatArr = new List <BinaryTagNode>();

                for (int i = 0; i < chunk_updates.Count; i++)
                {
                    int pos = (chunk_updates.Values[i].Z * CHUNK_SIZE * CHUNK_SIZE) + (chunk_updates.Values[i].Y * CHUNK_SIZE) + chunk_updates.Values[i].X;
                    tickFlatArr.Add(new BinaryTagNodeInt("block_update", pos));
                }
                #endregion

                rootTag.Add(new BinaryTagNodeList("updates", tickFlatArr));
            }

            #endregion

            return(rootTag);
        }
Ejemplo n.º 5
0
        public void SaveChunks()
        {
            //TODO: Serialize

            //ROADMAP:
            //
            // Get world folder
            // Construct Level NBT Data
            // Write File to folder
            // create chunks dir if non-existent
            // for (chunk in chunks)
            // {
            //		NBT = chunk.Serialize();
            //		writeToFile(NBT);
            // }

            #region World Data
            var root = new BinaryTagNodeMultiple("root");

            //Serialize player position
            #region Player State
            var plr    = new BinaryTagNodeMultiple("player");
            var plrPos = new BinaryTagNodeMultiple("position");
            var plrRot = new BinaryTagNodeMultiple("rotation");

            plrPos.Add(new BinaryTagNodeFloat("X", player.position.X));
            plrPos.Add(new BinaryTagNodeFloat("Y", player.position.Y));
            plrPos.Add(new BinaryTagNodeFloat("Z", player.position.Z));

            plrRot.Add(new BinaryTagNodeFloat("X", player.camera.Pitch));
            plrRot.Add(new BinaryTagNodeFloat("Y", player.camera.Yaw));
            plrRot.Add(new BinaryTagNodeFloat("Z", player.camera.Roll));

            plr.Add(plrPos);
            plr.Add(plrRot);

            plr.Add(new BinaryTagNodeByte("inventorySlot", (byte)player.HeldSlot));

            //TODO: Serialize inventory

            root.Add(plr);

            #endregion

            root.Add(new BinaryTagNodeLong("seed", seed));

            root.Add(new BinaryTagNode(""));
            #endregion

            FileUtil.SerializeToFile(Path.Combine(WorldDirectory, "level.dat"), root);

            string chunkFolder = Path.Combine(WorldDirectory, "chunks");

            #region Chunks
            for (int i = 0; i < chunks.Count; i++)
            {
                var data = chunks[chunkHashes[i]].SerializeToBinaryTag();

                FileUtil.SerializeToFile(Path.Combine(chunkFolder, chunks[chunkHashes[i]].posX + "." + chunks[chunkHashes[i]].posY + "." + chunks[chunkHashes[i]].posZ + "p.cnk"), data);
            }
            #endregion
        }