示例#1
0
        public Engine Launch(string[] args, HostType hostType)
        {
            //This two stage setup is required to ensure that a logger always exists

            var commandLine = new CommandLine(args, CommandLineKeyPrefixes);

            var gameDirectory = commandLine.GetValue("-game");

            //This can't actually happen since SharpLife loads from its own directory, so unless somebody placed the installation in the default game directory this isn't an issue
            //It's an easy way to verify that nothing went wrong during user setup though
            if (gameDirectory == null)
            {
                FatalError("No game directory specified, cannot continue");
            }

            var engineConfiguration = LoadEngineConfiguration(gameDirectory);

            var logTextWriter = new ForwardingTextWriter();

            Logger = CreateLogger(gameDirectory, engineConfiguration.LoggingConfiguration, logTextWriter);

            //Now that the logger has been set up the engine can take care of the rest
            return(new Engine(hostType, commandLine, gameDirectory, engineConfiguration, Logger, logTextWriter));
        }
示例#2
0
        private ILogger CreateLogger(string gameDirectory, LoggingConfiguration loggingConfiguration, ForwardingTextWriter logTextWriter)
        {
            var config = new LoggerConfiguration();

            config.MinimumLevel.Verbose();

            ITextFormatter fileFormatter = null;

            switch (loggingConfiguration.LogFormat)
            {
            case LoggingConfiguration.Format.Text:
            {
                fileFormatter = new MessageTemplateTextFormatter("{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}", null);
                break;
            }

            case LoggingConfiguration.Format.CompactJSON:
            {
                fileFormatter = new CompactJsonFormatter();
                break;
            }
            }

            //Invalid config setting for RetainedFileCountLimit will throw
            config
            .WriteTo.File(fileFormatter, $"{gameDirectory}/logs/engine.log",
                          rollingInterval: RollingInterval.Day,
                          retainedFileCountLimit: loggingConfiguration.RetainedFileCountLimit);

            //Use basic formatting for console output
            var logFormatter = new MessageTemplateTextFormatter("{Message:lj}{NewLine}{Exception}", null);

            if (logTextWriter != null)
            {
                config.WriteTo.TextWriter(logFormatter, logTextWriter);
            }

            return(config.CreateLogger());
        }
示例#3
0
        public Engine(HostType hostType, ICommandLine commandLine, string gameDirectory, EngineConfiguration engineConfiguration, ILogger logger, ForwardingTextWriter forwardingTextWriter)
        {
            _hostType = hostType;

            CommandLine         = commandLine ?? throw new ArgumentNullException(nameof(commandLine));
            GameDirectory       = gameDirectory ?? throw new ArgumentNullException(nameof(gameDirectory));
            EngineConfiguration = engineConfiguration ?? throw new ArgumentNullException(nameof(engineConfiguration));
            Log.Logger          = Logger = logger ?? throw new ArgumentNullException(nameof(logger));
            LogTextWriter       = forwardingTextWriter ?? throw new ArgumentNullException(nameof(forwardingTextWriter));

            FileSystem = new DiskFileSystem();

            SetupFileSystem(GameDirectory);

            CommandSystem = new SharpLife.CommandSystem.CommandSystem(Logger, CultureInfo.InvariantCulture);

            EngineContext = CommandSystem.CreateContext("EngineContext");

            var startupState = new EngineStartupState(Logger, GameDirectory,
                                                      new IModelFormatProvider[]
            {
                new SpriteModelFormatProvider(),
                new StudioModelFormatProvider(),
                //BSP loader comes last due to not having a way to positively recognize the format
                new BSPModelFormatProvider(Framework.BSPModelNamePrefix)
            });

            //Add the engine assembly so builtin data gets added
            startupState.EntitySystemMetaData.AddAssembly(typeof(Engine).Assembly);

            //create the game window if this is a client
            if (_hostType == HostType.Client)
            {
                Client = new EngineClient(this, startupState);
            }

            Server = new EngineServer(this, Logger, startupState);

            PluginManager = startupState.PluginManager.Build();

            //Automatically add in all plugin assemblies to the entity system
            foreach (var pluginAssembly in PluginManager.Assemblies)
            {
                startupState.EntitySystemMetaData.AddAssembly(pluginAssembly);
            }

            var renderer = (IRenderer)Client?.UserInterface.Renderer ?? new ServerRenderer();

            World = new WorldState(
                Logger,
                EventSystem,
                FileSystem,
                startupState.EntitySystemMetaData.Build(),
                renderer,
                startupState.ModelFormats);

            _engineTimeStopwatch.Start();

            EngineContext.AddStuffCmds(Logger, CommandLine);
            EngineContext.AddExec(Logger, FileSystem, ExecPathIDs);
            EngineContext.AddEcho(Logger);
            EngineContext.AddAlias(Logger);
            EngineContext.AddFind(Logger);
            EngineContext.AddHelp(Logger);

            _fpsMax = EngineContext.RegisterVariable(
                new VirtualVariableInfo <uint>("fps_max", DefaultFPS)
                .WithHelpInfo("Sets the maximum frames per second")
                .WithChangeHandler((ref VariableChangeEvent <uint> @event) =>
            {
                @event.Value = Math.Min(@event.Value, MaximumFPS);

                var desiredFPS = @event.Value;

                if (desiredFPS == 0)
                {
                    desiredFPS = MaximumFPS;
                }

                _desiredFrameLengthSeconds = 1.0 / desiredFPS;
            }));

            EngineContext.RegisterVariable("engine_builddate", () => BuildDate, "The engine's build date");

            EngineContext.RegisterCommand(new CommandInfo("map", StartNewMap).WithHelpInfo("Loads the specified map"));

            //Get the build date from the generated resource file
            var assembly = typeof(Engine).Assembly;

            using (var reader = new StreamReader(assembly.GetManifestResourceStream($"{assembly.GetName().Name}.Resources.BuildDate.txt")))
            {
                string buildTimestamp = reader.ReadToEnd();

                BuildDate = DateTimeOffset.Parse(buildTimestamp);

                Logger.Information($"Exe: {BuildDate.ToString("HH:mm:ss MMM dd yyyy")}");
            }

            //TODO: initialize subsystems
        }