diff --git a/README.md b/README.md index 2a9edbb..948bc38 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ Luban适合有以下需求的开发者: - unity + c# - unity + tolua,xlua - unity + ILRuntime + - unity + puerts - unreal + c++ - unreal + unlua - unreal + sluaunreal diff --git a/src/Luban.Client/Properties/launchSettings.json b/src/Luban.Client/Properties/launchSettings.json index 4d18b70..e0aca35 100644 --- a/src/Luban.Client/Properties/launchSettings.json +++ b/src/Luban.Client/Properties/launchSettings.json @@ -2,8 +2,8 @@ "profiles": { "Luban.Client": { "commandName": "Project", - "commandLineArgs": "-h 127.0.0.1 -p 8899 -j cfg -a \"{ 'define_file':'../../CfgDefines/root.xml', 'input_data_dir':'../../CfgDatas', 'validate_root_dir':'E:/NikkiP4_D/X6Game/Content', 'output_data_dir':'output_data', 'service':'server', 'export_test_data':true,'gen_types':'code_cs_bin,data_bin', 'output_code_dir' : 'Gen' }\"", - "workingDirectory": "E:\\workspace\\bright_gen\\DemoProjects\\Csharp_Server_DotNetCore" + "commandLineArgs": "-h %LUBAN_SERVER_IP% -j cfg -w ..\\DesignerConfigs\\Datas -- -d ..\\DesignerConfigs\\Defines\\__root__.xml --input_data_dir ..\\DesignerConfigs\\Datas --output_code_dir TsScripts/src/Gen/Cfg --output_data_dir ConfigData --gen_types code_typescript_bin,data_bin -s client --export_test_data --validate_root_dir Assets ", + "workingDirectory": "C:\\workspace\\unity-world\\Client" }, "Luban.Client-db": { "commandName": "Project", diff --git a/src/Luban.Client/Source/Net/GenClient.cs b/src/Luban.Client/Source/Net/GenClient.cs index 80fa487..61f73e7 100644 --- a/src/Luban.Client/Source/Net/GenClient.cs +++ b/src/Luban.Client/Source/Net/GenClient.cs @@ -32,10 +32,11 @@ namespace Luban.Client.Common.Net private static readonly NLog.Logger s_logger = NLog.LogManager.GetCurrentClassLogger(); - public static GenClient Ins { get; } = new GenClient(); + public static GenClient Ins { get; private set; } - public async Task Start(string host, int port, Dictionary factories) + public static async Task Start(string host, int port, Dictionary factories) { + Ins = new GenClient(); var c = new TcpClientBootstrap { RemoteAddress = new IPEndPoint(IPAddress.Parse(host), port), @@ -44,13 +45,19 @@ namespace Luban.Client.Common.Net InitHandler = ch => { ch.Pipeline.AddLast(new ProtocolFrameCodec(20_000_000, new RecycleByteBufPool(100, 10), new DefaultProtocolAllocator(factories))); - ch.Pipeline.AddLast(this); + ch.Pipeline.AddLast(Ins); } }; var ch = await c.ConnectAsync().ConfigureAwait(false); } + public static void Stop() + { + _ = Ins.Session.CloseAsync(); + Ins = null; + } + public override void HandleProtocol(Protocol proto) { diff --git a/src/Luban.Client/Source/Program.cs b/src/Luban.Client/Source/Program.cs index 25b6b92..f6c5f99 100644 --- a/src/Luban.Client/Source/Program.cs +++ b/src/Luban.Client/Source/Program.cs @@ -4,6 +4,7 @@ using Luban.Common.Protos; using Luban.Common.Utils; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -25,10 +26,14 @@ namespace Luban.Client public bool Verbose { get; set; } public string CacheMetaInfoFile { get; set; } = ".cache.meta"; + + public string WatchDir { get; set; } } private static NLog.Logger s_logger; + private static FileSystemWatcher s_watcher; + private static void PrintUsage(string err) { Console.WriteLine("ERRORS:"); @@ -39,11 +44,12 @@ e.g. Luban.Client -h 127.0.0.1 -p 2234 -j cfg -- --name abc Options: - -h, --host Required. host ip - -p --port port. default 8899 - -j --job Required. job type. avaliable value: cfg - -v --verbose verbose print - -c --cachemetafile cache meta file name + -h, --host Required. host ip + -p --port port. default 8899 + -j --job Required. job type. avaliable value: cfg + -v --verbose verbose print + -c --cachemetafile cache meta file name. default is '.cache.meta' + -w --watch watch data change and regenerate. -h --help show usage "); } @@ -90,6 +96,12 @@ Options: ops.CacheMetaInfoFile = args[++i]; break; } + case "-w": + case "--watch": + { + ops.WatchDir = args[++i]; + break; + } case "--": { ++i; @@ -135,7 +147,6 @@ Options: CommandLineOptions options = parseResult.Item2; profile.StartPhase("init logger"); - LogUtil.InitSimpleNLogConfigure(NLog.LogLevel.Info); s_logger = NLog.LogManager.GetCurrentClassLogger(); profile.EndPhaseAndLog(); @@ -143,14 +154,82 @@ Options: ThreadPool.SetMinThreads(4, 5); ThreadPool.SetMaxThreads(64, 10); + + if (string.IsNullOrWhiteSpace(options.WatchDir)) + { + Environment.Exit(GenOnce(options, profile)); + profile.EndPhaseAndLog(); + } + else + { + GenOnce(options, profile); + var watcher = new FileSystemWatcher(options.WatchDir); + + watcher.NotifyFilter = NotifyFilters.Attributes + | NotifyFilters.CreationTime + | NotifyFilters.DirectoryName + | NotifyFilters.FileName + | NotifyFilters.LastAccess + | NotifyFilters.LastWrite + | NotifyFilters.Security + | NotifyFilters.Size; + + watcher.Changed += (o, p) => OnWatchChange(options, profile); + watcher.Created += (o, p) => OnWatchChange(options, profile); + watcher.Deleted += (o, p) => OnWatchChange(options, profile); + watcher.Renamed += (o, p) => OnWatchChange(options, profile); + + //watcher.Filter = "*.txt"; + watcher.IncludeSubdirectories = true; + watcher.EnableRaisingEvents = true; + + s_logger.Info("=== start watch. dir:{} ==", options.WatchDir); + s_watcher = watcher; + } + } + + private static readonly object s_watchLocker = new object(); + private static bool s_watchDirChange = false; + + private static void OnWatchChange(CommandLineOptions options, ProfileTimer profile) + { + lock (s_watchLocker) + { + if (s_watchDirChange) + { + return; + } + s_watchDirChange = true; + + Task.Run(async () => + { + s_logger.Info("=== start new generation =="); + await Task.Delay(200); + + lock (s_watchLocker) + { + s_watchDirChange = false; + GenOnce(options, profile); + } + s_logger.Info("=== watch changes =="); + }); + } + + } + + private static int GenOnce(CommandLineOptions options, ProfileTimer profile) + { int exitCode; try { + + profile.StartPhase("connect server"); + var conn = GenClient.Start(options.Host, options.Port, ProtocolStub.Factories); + profile.StartPhase("load cache meta file"); CacheMetaManager.Ins.Load(options.CacheMetaInfoFile); profile.EndPhaseAndLog(); - profile.StartPhase("connect server"); - var conn = GenClient.Ins.Start(options.Host, options.Port, ProtocolStub.Factories); + conn.Wait(); profile.EndPhaseAndLog(); @@ -163,9 +242,13 @@ Options: exitCode = 1; s_logger.Error(e); } + finally + { + GenClient.Stop(); + } CacheMetaManager.Ins.Save(); - profile.EndPhaseAndLog(); + CacheMetaManager.Ins.Reset(); if (exitCode == 0) { s_logger.Info("== succ =="); @@ -174,7 +257,7 @@ Options: { s_logger.Error("== fail =="); } - Environment.Exit(exitCode); + return exitCode; } const int GEN_JOB_TIMEOUT = 120; diff --git a/src/Luban.Client/Source/Utils/CacheMetaManager.cs b/src/Luban.Client/Source/Utils/CacheMetaManager.cs index 6a51404..88734b8 100644 --- a/src/Luban.Client/Source/Utils/CacheMetaManager.cs +++ b/src/Luban.Client/Source/Utils/CacheMetaManager.cs @@ -121,6 +121,15 @@ namespace Luban.Client.Common.Utils s_logger.Info("[Save] meta file:{metaFile} updated!", _metaFile); } + public void Reset() + { + lock (_lock) + { + _dirty = false; + _cacheFileMetas.Clear(); + } + } + private MetaInfo GetMetaInfo(string file) { lock (_lock)