forked from sin365/AxibugEmuOnline
Merge branch 'master' of http://git.axibug.com/sin365/AxibugEmuOnline
This commit is contained in:
commit
ccc638defb
@ -5,8 +5,6 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
|
||||
[CreateAssetMenu(fileName = "CrossMapCfg", menuName = "Tools/AxiPrefabCachec", order = 0)]
|
||||
public class AxiPrefabCache : ScriptableObject
|
||||
{
|
||||
public List<AxiPrefabCache_Com2GUID> caches = new List<AxiPrefabCache_Com2GUID>();
|
||||
|
@ -47,6 +47,8 @@ namespace AxibugEmuOnline.Client.ClientCore
|
||||
#endif
|
||||
public static void Init( bool isTest = false, string testSrvIP = "")
|
||||
{
|
||||
log = new LogManager(OnLogOut);
|
||||
|
||||
//其他平台必要的初始化
|
||||
if (UnityEngine.Application.platform == RuntimePlatform.PSP2)
|
||||
{
|
||||
@ -54,9 +56,6 @@ namespace AxibugEmuOnline.Client.ClientCore
|
||||
}
|
||||
|
||||
settings = new AppSettings();
|
||||
|
||||
log = new LogManager();
|
||||
LogManager.OnLog += OnNoSugarNetLog;
|
||||
network = new NetworkHelper();
|
||||
login = new AppLogin();
|
||||
chat = new AppChat();
|
||||
@ -187,20 +186,20 @@ namespace AxibugEmuOnline.Client.ClientCore
|
||||
{
|
||||
App.log.Info("停止");
|
||||
}
|
||||
static void OnNoSugarNetLog(int LogLevel, string msg)
|
||||
static void OnLogOut(int LogLevel, string msg)
|
||||
{
|
||||
E_LogType logType = (E_LogType)LogLevel;
|
||||
switch (logType)
|
||||
{
|
||||
case E_LogType.Debug:
|
||||
case E_LogType.Info:
|
||||
Debug.Log("[AxiEmu]:" + msg);
|
||||
Debug.Log("[AxiNet]:" + msg);
|
||||
break;
|
||||
case E_LogType.Warning:
|
||||
Debug.LogWarning("[AxiEmu]:" + msg);
|
||||
Debug.LogWarning("[AxiNet]:" + msg);
|
||||
break;
|
||||
case E_LogType.Error:
|
||||
Debug.LogError("[AxiEmu]:" + msg);
|
||||
Debug.LogError("[AxiNet]:" + msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,12 @@ using System.Threading;
|
||||
|
||||
public static class PSVThread
|
||||
{
|
||||
|
||||
#if UNITY_PSP2
|
||||
static AutoResetEvent autoEvent = new AutoResetEvent(false);
|
||||
static Queue<Action> qActs = new Queue<Action>();
|
||||
static Queue<Action> qWork = new Queue<Action>();
|
||||
#endif
|
||||
|
||||
public static void DoTask(Action act)
|
||||
{
|
||||
@ -85,7 +88,7 @@ public static class AxiHttp
|
||||
public static long index = 0;
|
||||
static int singlePkgMaxRead = 1024;
|
||||
|
||||
public class WaitAxiRequest : UnityEngine.CustomYieldInstruction
|
||||
public class WaitAxiRequest : UnityEngine.CustomYieldInstruction
|
||||
{
|
||||
public AxiRespInfo mReqAsync;
|
||||
public WaitAxiRequest(AxiRespInfo reqAsync)
|
||||
|
@ -0,0 +1,404 @@
|
||||
using AxibugEmuOnline.Client.ClientCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace AxibugEmuOnline.Client.Common
|
||||
{
|
||||
public static class ObjectPoolAuto
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static T Acquire<T>()
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Acquire();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或者创建一个新的
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(T)"/> 需要回收参见这个</remarks>
|
||||
public static void Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> item = ObjectPool<T>.Acquire();
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Release(item);
|
||||
|
||||
/// <summary>
|
||||
/// 回收对象
|
||||
/// </summary>
|
||||
public static void Release<T>(ref T item) where T : class, new()
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
ObjectPool<T>.Release(item);
|
||||
item = null;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
public const string
|
||||
NotClearError = " They must be cleared before being released to the pool and not modified after that.";
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建List
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(List{T})"/> 回收参见此方法</remarks>
|
||||
public static List<T> AcquireList<T>()
|
||||
{
|
||||
var list = ObjectPool<List<T>>.Acquire();
|
||||
App.log.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收List
|
||||
/// </summary>
|
||||
public static void Release<T>(List<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
ObjectPool<List<T>>.Release(list);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建Queue
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release{T}(Queue{T})"/> 回收参见此方法</remarks>
|
||||
public static Queue<T> AcquireQueue<T>()
|
||||
{
|
||||
var queue = ObjectPool<Queue<T>>.Acquire();
|
||||
App.log.Assert(queue.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return queue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收Queue
|
||||
/// </summary>
|
||||
public static void Release<T>(Queue<T> list)
|
||||
{
|
||||
list.Clear();
|
||||
ObjectPool<Queue<T>>.Release(list);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取或创建HashSet
|
||||
/// </summary>
|
||||
public static HashSet<T> AcquireSet<T>()
|
||||
{
|
||||
var set = ObjectPool<HashSet<T>>.Acquire();
|
||||
App.log.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放HashSet
|
||||
/// </summary>
|
||||
public static void Release<T>(HashSet<T> set)
|
||||
{
|
||||
set.Clear();
|
||||
ObjectPool<HashSet<T>>.Release(set);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个字符串StringBuilder
|
||||
/// </summary>
|
||||
/// <remarks>Remember to <see cref="Release(StringBuilder)"/>回收参见这个</remarks>
|
||||
public static StringBuilder AcquireStringBuilder()
|
||||
{
|
||||
var builder = ObjectPool<StringBuilder>.Acquire();
|
||||
App.log.Assert(builder.Length == 0, $"A pooled {nameof(StringBuilder)} is not empty." + NotClearError);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static void Release(StringBuilder builder)
|
||||
{
|
||||
builder.Length = 0;
|
||||
ObjectPool<StringBuilder>.Release(builder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回收 StringBuilder
|
||||
/// </summary>
|
||||
public static string ReleaseToString(this StringBuilder builder)
|
||||
{
|
||||
var result = builder.ToString();
|
||||
Release(builder);
|
||||
return result;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static class Cache<T>
|
||||
{
|
||||
public static readonly Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>
|
||||
Results = new Dictionary<MethodInfo, KeyValuePair<Func<T>, T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此方法主要用于频繁绘制缓存,比如说GUI绘制
|
||||
/// </summary>
|
||||
public static T GetCachedResult<T>(Func<T> function)
|
||||
{
|
||||
var method = function.Method;
|
||||
if (!Cache<T>.Results.TryGetValue(method, out var result))
|
||||
{
|
||||
|
||||
result = new KeyValuePair<Func<T>, T>(function, function());
|
||||
Cache<T>.Results.Add(method, result);
|
||||
}
|
||||
else if (result.Key != function)
|
||||
{
|
||||
App.log.Warning(
|
||||
$"{nameof(GetCachedResult)}<{typeof(T).Name}>" +
|
||||
$" was previously called on {method.Name} with a different target." +
|
||||
" This likely means that a new delegate is being passed into every call" +
|
||||
" so it can't actually return the same cached object.");
|
||||
}
|
||||
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
public static class Disposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable Acquire<T>(out T item)
|
||||
where T : class, new()
|
||||
=> ObjectPool<T>.Disposable.Acquire(out item);
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="List{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireList<T>(out List<T> list)
|
||||
{
|
||||
var disposable = ObjectPool<List<T>>.Disposable.Acquire(out list, onRelease: (l) => l.Clear());
|
||||
App.log.Assert(list.Count == 0, "A pooled list is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Disposable.Acquire"/> to get a spare <see cref="HashSet{T}"/> if
|
||||
/// </summary>
|
||||
public static IDisposable AcquireSet<T>(out HashSet<T> set)
|
||||
{
|
||||
var disposable = ObjectPool<HashSet<T>>.Disposable.Acquire(out set, onRelease: (s) => s.Clear());
|
||||
App.log.Assert(set.Count == 0, "A pooled set is not empty." + NotClearError);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
|
||||
public static class ObjectPool<T> where T : class, new()
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<T>
|
||||
Items = new List<T>();
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The number of spare items currently in the pool.</summary>
|
||||
public static int Count
|
||||
{
|
||||
get => Items.Count;
|
||||
set
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count < value)
|
||||
{
|
||||
if (Items.Capacity < value)
|
||||
Items.Capacity = NextPowerOfTwo(value);
|
||||
|
||||
do
|
||||
{
|
||||
Items.Add(new T());
|
||||
count++;
|
||||
}
|
||||
while (count < value);
|
||||
|
||||
}
|
||||
else if (count > value)
|
||||
{
|
||||
Items.RemoveRange(value, count - value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int NextPowerOfTwo(int value)
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw new ArgumentException("Value must be greater than zero.");
|
||||
}
|
||||
|
||||
int powerOfTwo = 1;
|
||||
while (powerOfTwo < value)
|
||||
{
|
||||
powerOfTwo <<= 1; // equivalent to multiplying by 2
|
||||
}
|
||||
|
||||
return powerOfTwo;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="Count"/> is less than the specified value, this method increases it to that value by
|
||||
/// creating new objects.
|
||||
/// </summary>
|
||||
public static void SetMinCount(int count)
|
||||
{
|
||||
if (Count < count)
|
||||
Count = count;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>The <see cref="List{T}.Capacity"/> of the internal list of spare items.</summary>
|
||||
public static int Capacity
|
||||
{
|
||||
get => Items.Capacity;
|
||||
set
|
||||
{
|
||||
if (Items.Count > value)
|
||||
Items.RemoveRange(value, Items.Count - value);
|
||||
Items.Capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a spare item if there are any, or creates a new one.</summary>
|
||||
/// <remarks>Remember to <see cref="Release(T)"/> it when you are done.</remarks>
|
||||
public static T Acquire()
|
||||
{
|
||||
var count = Items.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
else
|
||||
{
|
||||
count--;
|
||||
var item = Items[count];
|
||||
Items.RemoveAt(count);
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Adds the `item` to the list of spares so it can be reused.</summary>
|
||||
public static void Release(T item)
|
||||
{
|
||||
Items.Add(item);
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>Returns a description of the state of this pool.</summary>
|
||||
public static string GetDetails()
|
||||
{
|
||||
return
|
||||
$"{typeof(T).Name}" +
|
||||
$" ({nameof(Count)} = {Items.Count}" +
|
||||
$", {nameof(Capacity)} = {Items.Capacity}" +
|
||||
")";
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="IDisposable"/> system to allow pooled objects to be acquired and released within <c>using</c>
|
||||
/// statements instead of needing to manually release everything.
|
||||
/// </summary>
|
||||
public sealed class Disposable : IDisposable
|
||||
{
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private static readonly List<Disposable> LazyStack = new List<Disposable>();
|
||||
|
||||
private static int _ActiveDisposables;
|
||||
|
||||
private T _Item;
|
||||
private Action<T> _OnRelease;
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
private Disposable() { }
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ObjectPool{T}.Acquire"/> to set the `item` and returns an <see cref="IDisposable"/>
|
||||
/// that will call <see cref="Release(T)"/> on the `item` when disposed.
|
||||
/// </summary>
|
||||
public static IDisposable Acquire(out T item, Action<T> onRelease = null)
|
||||
{
|
||||
Disposable disposable;
|
||||
|
||||
if (LazyStack.Count <= _ActiveDisposables)
|
||||
{
|
||||
LazyStack.Add(disposable = new Disposable());
|
||||
}
|
||||
else
|
||||
{
|
||||
disposable = LazyStack[_ActiveDisposables];
|
||||
}
|
||||
|
||||
_ActiveDisposables++;
|
||||
|
||||
disposable._Item = item = ObjectPool<T>.Acquire();
|
||||
disposable._OnRelease = onRelease;
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_OnRelease?.Invoke(_Item);
|
||||
Release(_Item);
|
||||
_ActiveDisposables--;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca23a07857cb5674d9e563ca515e70d0
|
@ -19,16 +19,22 @@ namespace AxibugEmuOnline.Client
|
||||
#if UNITY_EDITOR
|
||||
public bool bTest = false;
|
||||
public string mTestSrvIP = "192.168.0.47";
|
||||
public bool bEditorUUID = false;
|
||||
#endif
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
App.Init(bTest, mTestSrvIP);
|
||||
dev_UUID = SystemInfo.deviceUniqueIdentifier;
|
||||
if (bEditorUUID)
|
||||
{
|
||||
dev_UUID += "_Editor";
|
||||
}
|
||||
#else
|
||||
App.Init(this);
|
||||
#endif
|
||||
dev_UUID = SystemInfo.deviceUniqueIdentifier;
|
||||
#endif
|
||||
|
||||
m_refs = Instantiate(IMPORTENT, transform).GetComponent<GlobalRef>();
|
||||
}
|
||||
|
@ -2,6 +2,11 @@
|
||||
{
|
||||
public class LogManager
|
||||
{
|
||||
public LogManager(OnLogHandler logOut)
|
||||
{
|
||||
OnLog += logOut;
|
||||
}
|
||||
|
||||
public enum E_LogType : byte
|
||||
{
|
||||
Info = 0,
|
||||
@ -18,7 +23,7 @@
|
||||
/// <summary>
|
||||
/// 内部输出
|
||||
/// </summary>
|
||||
public static event OnLogHandler OnLog;
|
||||
static event OnLogHandler OnLog;
|
||||
|
||||
public void Info(string str)
|
||||
{
|
||||
@ -40,6 +45,14 @@
|
||||
Log(E_LogType.Error, str);
|
||||
}
|
||||
|
||||
public void Assert(bool conditional, string message)
|
||||
{
|
||||
if (!conditional)
|
||||
{
|
||||
Debug(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(E_LogType logtype, string str)
|
||||
{
|
||||
OnLog?.Invoke((int)logtype, str);
|
||||
|
@ -707,13 +707,13 @@ namespace AxibugEmuOnline.Server
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<uint, uint> GetSlotDataByUID(long uid)
|
||||
public bool GetSlotDataByUID(long uid, out Dictionary<uint, uint> slotIdx2JoyIdx)
|
||||
{
|
||||
Dictionary<uint, uint> slotIdx2JoyIdx = new Dictionary<uint, uint>();
|
||||
slotIdx2JoyIdx = new Dictionary<uint, uint>();
|
||||
var dataarr = PlayerSlot.Where(w => w.UID == uid).ToArray();
|
||||
foreach (var slot in dataarr)
|
||||
slotIdx2JoyIdx[slot.SlotIdx] = slot.LocalJoyIdx;
|
||||
return slotIdx2JoyIdx;
|
||||
return slotIdx2JoyIdx.Count > 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// 按照SlotIdx设置Input
|
||||
@ -738,7 +738,7 @@ namespace AxibugEmuOnline.Server
|
||||
var dataarr = PlayerSlot.Where(w => w.UID == uid).ToArray();
|
||||
foreach (var slot in dataarr)
|
||||
{
|
||||
dataarr[slot.SlotIdx].Init(slot.SlotIdx);
|
||||
slot.Init(slot.SlotIdx);
|
||||
ClearInputDataBySlotIdx(slot.SlotIdx);
|
||||
}
|
||||
}
|
||||
@ -832,7 +832,7 @@ namespace AxibugEmuOnline.Server
|
||||
|
||||
public void SetPlayerSlotData(ClientInfo _c, ref readonly Dictionary<uint, uint> newSlotIdx2JoyIdx)
|
||||
{
|
||||
Dictionary<uint, uint> oldSlotIdx2JoyIdx = GetSlotDataByUID(_c.UID);
|
||||
GetSlotDataByUID(_c.UID, out Dictionary<uint, uint> oldSlotIdx2JoyIdx);
|
||||
HashSet<uint> diffSlotIdxs = ObjectPoolAuto.AcquireSet<uint>();// new HashSet<uint>();
|
||||
foreach (var old in oldSlotIdx2JoyIdx)
|
||||
{
|
||||
@ -1132,6 +1132,32 @@ namespace AxibugEmuOnline.Server
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//房主离线,自动选择延迟最低另一名玩家做房主
|
||||
if (!GetSlotDataByUID(this.HostUID, out Dictionary<uint, uint> slotIdx2JoyIdx))
|
||||
{
|
||||
List<ClientInfo> userlist = ObjectPoolAuto.AcquireList<ClientInfo>();
|
||||
GetAllPlayerClientList(ref userlist);
|
||||
if (userlist.Count > 0)
|
||||
{
|
||||
ClientInfo? client = userlist.OrderBy(w => w.AveNetDelay).FirstOrDefault();
|
||||
this.HostUID = client.UID;
|
||||
AppSrv.g_Log.DebugCmd($"更换房主为{this.HostUID}");
|
||||
bChanged = true;
|
||||
}
|
||||
ObjectPoolAuto.Release(userlist);
|
||||
}
|
||||
|
||||
if (this.GameState > RoomGameState.OnlyHost && newPlayerCount == 1)
|
||||
{
|
||||
this.GameState = RoomGameState.OnlyHost;
|
||||
AppSrv.g_Log.DebugCmd("回到OnlyHost状态");
|
||||
bChanged = true;
|
||||
}
|
||||
|
||||
|
||||
return bChanged;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<History>True|2024-12-11T02:52:05.7940446Z||;True|2024-12-04T22:26:53.2238425+08:00||;True|2024-12-04T22:26:10.9572308+08:00||;True|2024-12-04T21:24:20.1913809+08:00||;True|2024-12-04T21:24:02.9590471+08:00||;True|2024-12-04T01:43:54.7646411+08:00||;True|2024-12-04T01:22:11.8117030+08:00||;True|2024-12-04T01:20:06.5770785+08:00||;True|2024-12-04T01:16:31.6391421+08:00||;True|2024-12-04T01:12:43.4697251+08:00||;True|2024-12-04T01:07:04.8333668+08:00||;True|2024-12-04T00:59:23.6611648+08:00||;True|2024-12-04T00:27:05.0229247+08:00||;True|2024-12-03T23:50:48.5712706+08:00||;True|2024-12-03T23:47:47.1095592+08:00||;True|2024-12-03T20:24:57.4098592+08:00||;True|2024-12-03T20:16:36.9886489+08:00||;True|2024-12-03T20:15:52.5482738+08:00||;True|2024-12-02T20:10:07.8192795+08:00||;True|2024-11-28T19:58:55.3995125+08:00||;True|2024-09-14T16:39:29.4677979+08:00||;True|2024-09-14T16:38:22.2398996+08:00||;True|2024-09-13T13:39:28.9591993+08:00||;True|2024-09-12T17:48:43.1521740+08:00||;True|2024-09-12T17:43:57.0504432+08:00||;True|2024-09-12T17:19:48.6392091+08:00||;True|2024-09-12T13:38:45.0141937+08:00||;False|2024-09-12T13:37:57.6131232+08:00||;True|2024-06-28T16:25:59.3159172+08:00||;True|2024-06-28T15:30:49.8257235+08:00||;</History>
|
||||
<History>True|2025-01-02T07:36:28.7979053Z||;True|2025-01-02T15:31:33.8583976+08:00||;True|2024-12-11T10:52:05.7940446+08:00||;True|2024-12-04T22:26:53.2238425+08:00||;True|2024-12-04T22:26:10.9572308+08:00||;True|2024-12-04T21:24:20.1913809+08:00||;True|2024-12-04T21:24:02.9590471+08:00||;True|2024-12-04T01:43:54.7646411+08:00||;True|2024-12-04T01:22:11.8117030+08:00||;True|2024-12-04T01:20:06.5770785+08:00||;True|2024-12-04T01:16:31.6391421+08:00||;True|2024-12-04T01:12:43.4697251+08:00||;True|2024-12-04T01:07:04.8333668+08:00||;True|2024-12-04T00:59:23.6611648+08:00||;True|2024-12-04T00:27:05.0229247+08:00||;True|2024-12-03T23:50:48.5712706+08:00||;True|2024-12-03T23:47:47.1095592+08:00||;True|2024-12-03T20:24:57.4098592+08:00||;True|2024-12-03T20:16:36.9886489+08:00||;True|2024-12-03T20:15:52.5482738+08:00||;True|2024-12-02T20:10:07.8192795+08:00||;True|2024-11-28T19:58:55.3995125+08:00||;True|2024-09-14T16:39:29.4677979+08:00||;True|2024-09-14T16:38:22.2398996+08:00||;True|2024-09-13T13:39:28.9591993+08:00||;True|2024-09-12T17:48:43.1521740+08:00||;True|2024-09-12T17:43:57.0504432+08:00||;True|2024-09-12T17:19:48.6392091+08:00||;True|2024-09-12T13:38:45.0141937+08:00||;False|2024-09-12T13:37:57.6131232+08:00||;True|2024-06-28T16:25:59.3159172+08:00||;True|2024-06-28T15:30:49.8257235+08:00||;</History>
|
||||
<LastFailureDetails />
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\net9.0\publish\win-x64\</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<_TargetId>Folder</_TargetId>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>false</SelfContained>
|
||||
<PublishSingleFile>false</PublishSingleFile>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<History>False|2025-01-02T07:36:18.1906464Z||;False|2025-01-02T15:36:06.5622643+08:00||;True|2024-12-27T18:24:49.7554320+08:00||;</History>
|
||||
<LastFailureDetails />
|
||||
</PropertyGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user