Esempio n. 1
0
    private void NetChunkLoadedForClient(object[] args)
    {
        // Called on server when finished loading a chunk from file, to send to a player.
        string     data   = (string)args[0];
        int        chunkX = (int)args[1];
        int        chunkY = (int)args[2];
        GameObject player = (GameObject)args[3];

        int index = GetChunkIndex(chunkX, chunkY);

        if (AnyPendingOperationsFor(index))
        {
            // Merge the loaded data with any pending operations.
            string merged = ChunkIO.Merge(data, PendingOperations[index], ChunkSize, true);

            // Compress again using RLE.
            float  eff;
            string compressed = ChunkIO.RLE(merged, out eff);

            // Apply back to the data.
            data = compressed;
        }

        // Send to client.
        Msg_SendChunk msg = new Msg_SendChunk()
        {
            Data = data, ChunkX = chunkX, ChunkY = chunkY, Layer = Name
        };

        // Send the data to the client using the server.
        NetworkServer.SendToClientOfPlayer(player, (short)MessageTypes.SEND_CHUNK_DATA, msg);
    }
Esempio n. 2
0
    public void RecievedNetChunk(string data, int chunkX, int chunkY)
    {
        // Called on only clients, when the network message for an incomming chunk has been recieved.

        // Make sure that the chunk is created first!
        int index = GetChunkIndex(chunkX, chunkY);

        if (!IsChunkLoading(index))
        {
            return;
        }

        // First get a list of tiles, based on the data.
        BaseTile[][] tiles = ChunkIO.MakeChunk(data, ChunkSize, null, Use_RLE_In_Net);

        SetChunkTiles(tiles, chunkX * ChunkSize, chunkY * ChunkSize);


        // Mark as done loading.
        Chunk c = Chunks[index];

        c.DoneLoading();

        loading.Remove(index);
    }
Esempio n. 3
0
    public void ResolveAllPendingOperations()
    {
        // Saves all pending operations to file and clears the pending array.
        ChunkIO.MergeAllToFile(this.Map.World.RealityName, Name, ChunkSize, WidthInChunks, PendingOperations, OperationsResolved);

        // The operations will be cleared once they have been saved.
    }
Esempio n. 4
0
    [Server] // Intentional, called from Player.NetUtils.
    public void CmdRequestChunk(int x, int y, GameObject player)
    {
        // Called when a player requests a chunk from this server.
        // We need to make a compressed representation of the tiles and send it.

        // First, validation.
        if (player == null)
        {
            return;
        }

        if (!IsChunkInBounds(x, y))
        {
            return;
        }

        // FOR NOW:

        // 1. See if chunk is loaded.
        if (IsChunkLoaded(x, y))
        {
            // Great, send a copy of this.
            ChunkIO.GetChunkForNet_Loaded(player, Tiles, x, y, ChunkSize, NetChunkMade, Use_RLE_In_Net);
        }
        else
        {
            // Chunk is not loaded, what do I do?
            // Load a copy and send it?
            // But then how does the client make persistent changes to it?
            // Load it permamently in the server while the client is in it?
            // Allow the client to send a copy back once it is unloaded?
            // ---> Allow the client to make changes, record them on the server, and once the chunk is loaded, apply those changes. Also save those changes when X?

            // Decided solution:
            // Load from file.
            // Apply any 'changes' (explained later).
            // Send to client.
            // Client can then make any changes to that chunk, which are sent to the server, and stored as 'changes'.
            // Once the server really loads the chunk, the 'changes' are applied for real.
            // When a chunk is saved to file, all pending changes to that chunk are removed.

            // 1. Ensure it is saved to file...
            if (ChunkIO.IsChunkSaved(this.Map.World.RealityName, Name, x, y))
            {
                // 2. Load from file.
                ChunkIO.GetChunkForNet_Unloaded(player, this.Map.World.RealityName, Name, x, y, ChunkSize, NetChunkLoadedForClient, NetChunkLoadError);
            }
            else
            {
                // 3. 'Generate' and save to file, then send normally.
                string contents = (16 * 16) + "|?";
                string path     = ChunkIO.GetPathForChunk(this.Map.World.RealityName, Name, x, y);
                File.WriteAllText(path, contents);

                // 4. Send it.
                ChunkIO.GetChunkForNet_Unloaded(player, this.Map.World.RealityName, Name, x, y, ChunkSize, NetChunkLoadedForClient, NetChunkLoadError);
            }
        }
    }
Esempio n. 5
0
    private void LoadChunk_Server(int x, int y)
    {
        if (!IsChunkInBounds(x, y))
        {
            Debug.LogError("Chunk coordinate " + x + ", " + y + " (chunk space) is not in bounds.");
            return;
        }

        if (IsChunkLoaded(x, y))
        {
            Debug.LogError("Chunk at " + x + ", " + y + " (chunk space) is already loaded, cannot load again!");
            return;
        }

        int index = GetChunkIndex(x, y);

        if (IsChunkLoading(index))
        {
            Debug.LogError("Chunk at " + x + ", " + y + " is already loading.");
            return;
        }

        // Flag as loading...
        loading.Add(index);

        // Instantiate object, TODO pool me.
        Chunk newChunk = Instantiate(ChunkPrefab.gameObject, transform).GetComponent <Chunk>();

        // Create the chunk object.
        newChunk.Create(x, y, ChunkSize, ChunkSize, index);

        // Add to the chunks list.
        Chunks.Add(index, newChunk);

        // Check if is saved data...
        if (ChunkIO.IsChunkSaved(this.Map.World.RealityName, Name, x, y))
        {
            // Load from disk.
            ChunkIO.LoadChunk(this.Map.World.RealityName, Name, x, y, ChunkSize, ChunkLoaded, ChunkLoadError);
        }
        else
        {
            // TODO add something, like generating this chunk.
            // Just leave a blank chunk, lol.

            // Mark as loaded, after 'generation'.
            Chunks[index].DoneLoading();
            loading.Remove(index);
        }
    }
Esempio n. 6
0
    public void SaveAll()
    {
        // Saves everything about this layer to file, ready to shut down.
        // Async, for now. You could block until Saving == false to have sync behaviour.

        if (Saving)
        {
            Debug.LogError("Already saving! " + ChunksLeftToSave + " chunks to go!");
            return;
        }

        Debug.Log("Saving layer '" + Name + "'");

        Saving        = true;
        saveStartTime = Time.time;

        // Debug.
        int count = 0;

        foreach (int index in PendingOperations.Keys)
        {
            if (!AnyPendingOperationsFor(index))
            {
                continue;
            }

            count += PendingOperations[index].Count;
        }

        ChunksLeftToSave        = 0;
        OperationsPendingInSave = count;

        // First save all loaded chunks.
        foreach (int index in Chunks.Keys)
        {
            Vector2Int pos = GetChunkCoordsFromIndex(index);
            ChunksLeftToSave++;
            ChunkIO.SaveChunk(this.Map.World.RealityName, Name, Tiles, pos.x, pos.y, ChunkSize, ChunkSavedEmpty);
        }
        // Done!
    }
Esempio n. 7
0
 private void UnloadChunk_Server(int index, Chunk chunk)
 {
     unloading.Add(index);
     ChunkIO.SaveChunk(this.Map.World.RealityName, Name, Tiles, chunk.X, chunk.Y, ChunkSize, ChunkSaved);
 }
Esempio n. 8
0
        public World(String save)
        {
            provider = new WorldProvider(this);
            generator = new WorldGenerator(1337, this);
            chunkIO = new ChunkIO(this, save);
            players = new Player[]{new Player(this)};

            loadThread = new Thread(ChunkLoadLoop);
            updateThread = new Thread(ChunkUpdateLoop);

            loadThread.Start();
            updateThread.Start();
        }