Files
crtr/Assets/Cryville/Crtr/Game.cs

185 lines
5.7 KiB
C#

using Cryville.Audio;
using Cryville.Audio.Source;
using Cryville.Common;
using Cryville.Common.Unity;
using Cryville.Common.Unity.Input;
using FFmpeg.AutoGen;
using Ionic.Zip;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Logger = Cryville.Common.Logger;
#if UNITY_ANDROID
using AOT;
#endif
namespace Cryville.Crtr {
public static class Game {
public static string GameDataPath {
get;
private set;
}
public readonly static string FileProtocolPrefix
#if UNITY_STANDALONE_WIN
= "file:///";
#elif UNITY_ANDROID
= "file://";
#else
#error No file protocol prefix is defined.
#endif
public static IAudioDeviceManager AudioManager;
public static AudioClient AudioClient;
public static SimpleSequencerSource AudioSequencer;
public static SimpleSequencerSession AudioSession;
public static InputManager InputManager;
public readonly static NetworkTaskWorker NetworkTaskWorker = new NetworkTaskWorker();
public readonly static JsonSerializerSettings GlobalJsonSerializerSettings
= new JsonSerializerSettings() {
DefaultValueHandling = DefaultValueHandling.Ignore,
};
public static BufferedLogger MainLogger { get; private set; }
static bool _init;
public static void Init() {
if (_init) return;
_init = true;
bool _bcflag = new Version(Settings.Default.LastRunVersion) < new Version("0.4");
if (_bcflag) Settings.Default.Reset();
Logger.SetLogPath(Settings.Default.GameDataPath + "/logs");
MainLogger = new BufferedLogger();
Application.logMessageReceivedThreaded += OnLog;
Logger.Create("main", MainLogger);
if (_bcflag) Logger.Log("main", 2, "Game", "Reset all settings");
GameDataPath = Settings.Default.GameDataPath;
Input.simulateMouseWithTouches = false;
InputManager = new InputManager();
#if UNITY_EDITOR_WIN
ffmpeg.RootPath = Application.dataPath + "/Plugins/Windows";
#elif UNITY_STANDALONE_WIN
ffmpeg.RootPath = Application.dataPath + "/Plugins/x86_64";
#elif UNITY_ANDROID
ffmpeg.RootPath = "";
#else
#error No FFmpeg search path.
#endif
#if UNITY_ANDROID
Cryville.Audio.OpenSL.OutputClient.CallbackFunction = audioCallback;
#endif
while (true) {
try {
AudioManager = EngineBuilder.Create();
if (AudioManager == null) {
Popup.Create("Cannot initialize audio engine");
Logger.Log("main", 5, "Audio", "Cannot initialize audio engine");
}
else {
Logger.Log("main", 1, "Audio", "Using audio API: {0}", AudioManager.GetType().Namespace);
AudioClient = AudioManager.GetDefaultDevice(DataFlow.Out).Connect();
AudioClient.Init(AudioClient.DefaultFormat);
AudioClient.Source = AudioSequencer = new SimpleSequencerSource();
AudioSession = AudioSequencer.NewSession();
AudioSequencer.Playing = true;
AudioClient.Start();
}
break;
}
catch (Exception ex) {
Logger.Log("main", 4, "Audio", "An error occured when initializing the audio engine: {0}", ex);
Logger.Log("main", 3, "Audio", "Trying to use fallback audio engines");
EngineBuilder.Engines.Remove(AudioManager.GetType());
}
}
ChartPlayer.motionRegistry = new Dictionary<Identifier, MotionRegistry> {
{ "pt" , new MotionRegistry(typeof(VecPt)) },
{ "dir" , new MotionRegistry(typeof(Vec3)) },
{ "normal" , new MotionRegistry(typeof(Vec3)) },
{ "sv" , new MotionRegistry(new VecPtComp(0f, 0f), new VecPtComp(0f, 1f)) },
{ "svm" , new MotionRegistry(new Vec1m(1f)) },
{ "dist" , new MotionRegistry(new VecPtComp(0f, 0f), new VecPtComp(0f, float.PositiveInfinity)) },
{ "corner" , new MotionRegistry(typeof(VecI1)) },
{ "ctrl0" , new MotionRegistry(typeof(VecCtrl)) },
{ "ctrl1" , new MotionRegistry(typeof(VecCtrl)) },
{ "track" , new MotionRegistry(typeof(Vec1)) },
};
var dir = new DirectoryInfo(Settings.Default.GameDataPath + "/charts");
if (!dir.Exists || Settings.Default.LastRunVersion != Application.version) {
Directory.CreateDirectory(dir.FullName);
var defaultData = Resources.Load<TextAsset>("default");
using (var zip = ZipFile.Read(defaultData.bytes)) {
zip.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;
zip.ExtractAll(Settings.Default.GameDataPath);
}
}
Settings.Default.LastRunVersion = Application.version;
Settings.Default.Save();
Logger.Log("main", 1, "Game", "Initialized");
}
#if UNITY_ANDROID
[MonoPInvokeCallback(typeof(OpenSL.Native.slBufferQueueCallback))]
static void audioCallback(IntPtr caller, IntPtr context) {
Cryville.Audio.OpenSL.OutputClient.Callback(caller, context);
}
#endif
static bool _shutdown;
public static void Shutdown() {
if (_shutdown) return;
_shutdown = true;
Logger.Log("main", 1, "Game", "Shutting down");
try {
AudioSequencer.Dispose();
AudioClient.Dispose();
AudioManager.Dispose();
}
catch (Exception ex) {
LogException("Game", "An error occured while shutting down", ex);
}
finally {
Logger.Close();
}
}
public static DirectoryInfo[] GetDatabaseList() {
return new DirectoryInfo(GameDataPath + "/db").GetDirectories();
}
public static void ConnectDatabase(string name) {
}
public static void DisconnectDatabase() {
}
public static void LogException(string module, string prefix, Exception ex) {
Logger.Log("main", 4, module, "{0}: {1}", prefix, ex);
}
static void OnLog(string condition, string stackTrace, LogType type) {
int l;
switch (type) {
case LogType.Log: l = 1; break;
case LogType.Assert: l = 2; break;
case LogType.Warning: l = 3; break;
case LogType.Error:
case LogType.Exception: l = 4; break;
default: l = 1; break;
}
Logger.Log("main", l, "Internal", "{0}\n{1}", condition, stackTrace);
}
}
}