Пример #1
0
        public GameWorld(GameWorldConfiguration configuration,
                         FileSystemPath worldFilePath, TrippingCubesGame game)
        {
            DateTime startTime = DateTime.Now;

            Game = game;

            Entities = new ReadOnlyCollection <IEntity>(entities);

            Physics = new PhysicsSystem(IsBlockSolid, IsBlockLiquid);

            Paths = new ReadOnlyDictionary <string, PathLinear>(
                configuration.Paths ?? new Dictionary <string, PathLinear>());

            Log.Trace("Initializing world style...");
            try
            {
                Game.Resources.LoadMesh(MeshData.Skybox).Subscribe(
                    r => skyboxMesh = r);
                Game.Resources.LoadTexture(configuration.SkyboxPath,
                                           TextureFilter.Linear).Subscribe(
                    r => skyboxTexture = r);
                if (!configuration.InnerSkyboxPath.IsEmpty)
                {
                    Game.Resources.LoadTexture(configuration.InnerSkyboxPath,
                                               TextureFilter.Linear).Subscribe(
                        r => innerSkyboxTexture = r);
                }
            }
            catch (Exception exc)
            {
                Log.Warning("The skybox couldn't be loaded and will not " +
                            "be available.", exc);
            }
            try
            {
                DateTime             localStartTime       = DateTime.Now;
                BlockRegistryBuilder blockRegistryBuilder =
                    BlockRegistryBuilder.FromXml(
                        configuration.BlockRegistryPath,
                        FileSystem, false);
                Blocks = blockRegistryBuilder.GenerateRegistry(
                    FileSystem);
                Log.Trace("Block registry with " + Blocks.Count +
                          " block definitions initialized in " +
                          (DateTime.Now - localStartTime).TotalMilliseconds + "ms.");
            }
            catch (Exception exc)
            {
                throw new Exception("The block registry couldn't be " +
                                    "initialized.", exc);
            }


            Log.Trace("Initializing world chunk manager...");
            try
            {
                FileSystemPath primaryWorldBackupPath =
                    FileSystemPath.Combine(worldFilePath.GetParentDirectory(),
                                           $"{worldFilePath.GetFileName(false)}1");
                FileSystemPath secondaryWorldBackupPath =
                    FileSystemPath.Combine(worldFilePath.GetParentDirectory(),
                                           $"{worldFilePath.GetFileName(false)}2");

                if (FileSystem.IsWritable)
                {
                    try
                    {
                        if (FileSystem.ExistsFile(primaryWorldBackupPath))
                        {
                            using Stream secondaryBackupStream =
                                      FileSystem.CreateFile(secondaryWorldBackupPath,
                                                            true);
                            using Stream primaryWorldBackup =
                                      FileSystem.OpenFile(primaryWorldBackupPath,
                                                          false);

                            primaryWorldBackup.CopyTo(secondaryBackupStream);
                        }

                        if (FileSystem.ExistsFile(worldFilePath))
                        {
                            using Stream primaryWorldBackup =
                                      FileSystem.CreateFile(primaryWorldBackupPath,
                                                            true);
                            using Stream worldFile =
                                      FileSystem.OpenFile(worldFilePath, false);

                            worldFile.CopyTo(primaryWorldBackup);
                        }
                    }
                    catch (Exception exc)
                    {
                        throw new Exception("The world backups couldn't be " +
                                            "updated.", exc);
                    }
                }

                if (FileSystem.ExistsFile(worldFilePath))
                {
                    zipFileSystem = new ZipFileSystem(FileSystem.OpenFile(
                                                          worldFilePath, FileSystem.IsWritable));
                }
                else if (FileSystem.IsWritable)
                {
                    Log.Information("No world data file was found at the " +
                                    "specified path. A new world file is initialized.");
                    zipFileSystem = ZipFileSystem.Initialize(FileSystem,
                                                             worldFilePath, false);
                }
                else
                {
                    throw new Exception("The world data file doesn't exist " +
                                        $"under the path {worldFilePath} and can't be created, " +
                                        "as the file system is read-only.");
                }

                RootChunk = new Chunk <BlockVoxel>(
                    new BlockChunkManager(Blocks, Game.Resources,
                                          zipFileSystem, "/"));
            }
            catch (Exception exc)
            {
                throw new Exception("The world chunk manager couldn't be " +
                                    "initialized.", exc);
            }


            Log.Trace("Spawning entities...");
            foreach (EntityInstantiation instantiation in
                     configuration.Entities)
            {
                if (configuration.EntityConfigurations.TryGetValue(
                        instantiation.ConfigurationIdentifier,
                        out EntityConfiguration entityConfiguration))
                {
                    try
                    {
                        IEntity entity = entityConfiguration.Instantiate(this,
                                                                         instantiation.InstanceParameters);
                        entities.Add(entity);
                    }
                    catch (Exception exc)
                    {
                        Log.Warning($"Entity #{entities.Count} couldn't " +
                                    "be spawned and will be skipped.", exc);
                    }
                }
            }
            Log.Trace($"Spawned {entities.Count} entities.");

            Log.Trace("Game world initialized in " +
                      (DateTime.Now - startTime).TotalMilliseconds + "ms.");
        }