diff --git a/Assets/_Zombie/Scenes/Company1Floor.unity b/Assets/_Zombie/Scenes/Company1Floor.unity index a3b756c6..d1323925 100644 --- a/Assets/_Zombie/Scenes/Company1Floor.unity +++ b/Assets/_Zombie/Scenes/Company1Floor.unity @@ -6708,7 +6708,7 @@ MonoBehaviour: IncludeChildColliders: 0 RuntimeFollower: {fileID: 0} colliderMaxDistance: 100 - lastTimeMaxDistanceCalced: 638975240374295256 + lastTimeMaxDistanceCalced: 639040145455162885 --- !u!1 &679496949 GameObject: m_ObjectHideFlags: 0 @@ -8680,6 +8680,37 @@ Transform: m_Children: [] m_Father: {fileID: 370075175} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &929547485 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 929547486} + m_Layer: 0 + m_Name: HttpServer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &929547486 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 929547485} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -21.29961, y: -10.195702, z: 14.243967} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &959961076 GameObject: m_ObjectHideFlags: 0 @@ -64615,3 +64646,4 @@ SceneRoots: - {fileID: 370075175} - {fileID: 1611275467} - {fileID: 1055672620} + - {fileID: 929547486} diff --git a/Assets/_Zombie/Scripts/GameLocal.cs b/Assets/_Zombie/Scripts/GameLocal.cs index 462e8ef5..1b5e9d5f 100644 --- a/Assets/_Zombie/Scripts/GameLocal.cs +++ b/Assets/_Zombie/Scripts/GameLocal.cs @@ -5,6 +5,22 @@ using DarkTonic.MasterAudio; using Unity.XR.PXR; using UnityEngine; +public enum GameKey +{ + DinosaurPark2=0,//重返侏罗纪 + SpongeBob=1,//深海冒险 + XMen=2,//银河守护者 + KOF=3,//幻影交锋 + Valheim=4,//小小幻宠 + FutureMen=5,//未来战警 + AliceBall=6,//爱丽丝的舞会 + Zombie=7,//僵尸来了 + DefendNJ=8,//保卫金陵 + Loong=9, //巨龙猎人 + MRCS=10,//火力对决 + SXDMystery=11,//三星堆之谜 +} + public enum Place { Company1Floor= 0, @@ -101,6 +117,8 @@ public class GameLocal : MonoBehaviour [Header("场地")] public Place place = Place.Company1Floor; + public GameKey gameId; + [NonSerialized] public int GameMode = 0; @@ -121,6 +139,7 @@ public class GameLocal : MonoBehaviour Ins = this; Application.targetFrameRate = 60; AuthorPanel.Show(); + gameId = GameKey.Zombie; BGMState.StateChange(0); #if !UNITY_EDITOR && UNITY_ANDROID && PICO ChangeMaterial(true); diff --git a/Assets/_Zombie/Scripts/GameManager.cs b/Assets/_Zombie/Scripts/GameManager.cs index f1d02be4..ccf82504 100644 --- a/Assets/_Zombie/Scripts/GameManager.cs +++ b/Assets/_Zombie/Scripts/GameManager.cs @@ -117,7 +117,9 @@ public class GameManager : NetworkBehaviour [SyncVar] public long vistEnd = 0; // 总游玩时长 - private int vistAllTime = (int)(60 * 15); + public int vistAllTime = (int)(60 * 15); + + public float curGameTime = 0; [SyncVar] public string settleData = ""; @@ -162,6 +164,15 @@ public class GameManager : NetworkBehaviour { // 更新指引箭头位置 UpdateGuideArrowPosition(); + if (gameState == GameState.Playing) + { + curGameTime+=Time.deltaTime; + } + } + + public int GetNowTime() + { + return Mathf.RoundToInt(curGameTime); } /// diff --git a/Assets/_Zombie/Scripts/HttpServer.cs b/Assets/_Zombie/Scripts/HttpServer.cs new file mode 100644 index 00000000..cbf6dd93 --- /dev/null +++ b/Assets/_Zombie/Scripts/HttpServer.cs @@ -0,0 +1,305 @@ +using System; +using System.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Collections.Concurrent; +using UnityEngine; +using Valheim; + +[Serializable] +public class IntentMessage +{ + public string intent; +} + +[Serializable] +public class PlayingStatusResponse +{ + public int code; + public ServerData data; + public string message; +} + +[Serializable] +public class ServerData +{ + public string gameName; + public int gameTotalTime; + public int currentPlayTime; +} + +public class HttpServer : MonoBehaviour +{ + private HttpListener listener; + private Thread serverThread; + private volatile bool isRunning; + + private const string SERVER_URL = "http://+:12345/"; + + // 子线程 → 主线程 + private static ConcurrentQueue messageQueue = new ConcurrentQueue(); + + void Awake() + { + DontDestroyOnLoad(gameObject); + } + + void Start() + { + StartServer(); + } + + #region HTTP Server + + private void StartServer() + { + try + { + listener = new HttpListener(); + listener.Prefixes.Add(SERVER_URL); + listener.Start(); + + isRunning = true; + serverThread = new Thread(ListenLoop) + { + IsBackground = true + }; + serverThread.Start(); + + Debug.Log($"✅ HTTP Server 启动成功:{SERVER_URL}"); + } + catch (Exception e) + { + Debug.LogError("❌ HTTP Server 启动失败:" + e); + } + } + + private void ListenLoop() + { + while (isRunning && listener.IsListening) + { + try + { + var context = listener.GetContext(); + ThreadPool.QueueUserWorkItem(ProcessRequest, context); + } + catch (HttpListenerException) + { + break; + } + catch (Exception e) + { + Debug.LogError(e); + } + } + } + + private void ProcessRequest(object state) + { + var context = (HttpListenerContext)state; + var request = context.Request; + var response = context.Response; + + response.AddHeader("Access-Control-Allow-Origin", "*"); + response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS"); + response.AddHeader("Access-Control-Allow-Headers", "Content-Type"); + response.ContentType = "application/json; charset=utf-8"; + + try + { + if (request.HttpMethod == "POST") + { + string raw; + using (var reader = new StreamReader( + request.InputStream, + request.ContentEncoding ?? Encoding.UTF8)) + { + raw = reader.ReadToEnd(); + } + + Debug.Log($"📩 收到原始 JSON:{raw}"); + + // 解析 intent + IntentMessage intentMsg = null; + try + { + intentMsg = JsonUtility.FromJson(raw); + } + catch (Exception e) + { + Debug.LogError("JSON 解析失败:" + e); + } + + // 只处理 is_playing + if (intentMsg != null && intentMsg.intent == "is_playing") + { + var resp = new PlayingStatusResponse + { + code = 200, + data = new ServerData() + { + gameName = GetCurrentGameName(), + gameTotalTime = GetGameTotalTime(), + currentPlayTime = GetCurrentPlayTime() + }, + message = "请求成功" + }; + + string json = JsonUtility.ToJson(resp); + byte[] data = Encoding.UTF8.GetBytes(json); + response.OutputStream.Write(data, 0, data.Length); + } + else + { + // 未知 intent + string err = "{\"code\":400,\"msg\":\"unknown intent\"}"; + byte[] data = Encoding.UTF8.GetBytes(err); + response.OutputStream.Write(data, 0, data.Length); + } + + response.Close(); + return; + } + } + catch (Exception e) + { + Debug.LogError(e); + WriteResponse(response, 500, "error"); + } + finally + { + response.Close(); + } + } + + private void WriteResponse(HttpListenerResponse response, int code, string msg) + { + string json = $"{{\"code\":{code},\"msg\":\"{msg}\"}}"; + byte[] data = Encoding.UTF8.GetBytes(json); + response.OutputStream.Write(data, 0, data.Length); + } + + #endregion + + #region Unity Main Thread + + void Update() + { + while (messageQueue.TryDequeue(out var msg)) + { + Debug.Log($"📩 来自 [{msg.sender}] 指令 [{msg.command}]"); + HandleMessage(msg); + } + } + + #endregion + + #region Message Logic + + [Serializable] + public class NetMessage + { + public string sender; + public string command; + } + + private NetMessage ParseMessage(string raw) + { + if (string.IsNullOrEmpty(raw)) + return null; + + try + { + raw = raw.Replace("\"", "").Trim(); + var parts = raw.Split(':'); + if (parts.Length != 2) + { + Debug.LogWarning($"消息格式错误:{raw}"); + return null; + } + + return new NetMessage + { + sender = parts[0].Trim(), + command = parts[1].Trim() + }; + } + catch (Exception e) + { + Debug.LogError($"解析失败:{raw}\n{e}"); + return null; + } + } + + private void HandleMessage(NetMessage msg) + { + switch (msg.command) + { + case "isStart": + OnStartCommand(msg.sender); + break; + + default: + Debug.LogWarning($"未知指令:{msg.command}"); + break; + } + } + + private void OnStartCommand(string sender) + { + Debug.Log($"🚀 Start 指令来自:{sender}"); + + // ✅ 在这里安全调用 Unity API + // GameManager.Ins.QuitGame(); + } + + + private string GetCurrentGameName() + { + return GameLocal.Ins.gameId.ToString(); // 或你自己的 GameManager + } + + private int GetGameTotalTime() + { + return Mathf.FloorToInt(GameManager.Ins.vistAllTime); // 举例:1 小时(秒) + } + + private int GetCurrentPlayTime() + { + return GameManager.Ins.GetNowTime(); + } + + + #endregion + + #region Shutdown + + void OnDestroy() + { + StopServer(); + } + + private void StopServer() + { + isRunning = false; + + try + { + listener?.Stop(); + listener?.Close(); + } + catch { } + + try + { + if (serverThread != null && serverThread.IsAlive) + serverThread.Join(300); + } + catch { } + + Debug.Log("🛑 HTTP Server 已关闭"); + } + + #endregion +} diff --git a/Assets/_Zombie/Scripts/HttpServer.cs.meta b/Assets/_Zombie/Scripts/HttpServer.cs.meta new file mode 100644 index 00000000..3a088d74 --- /dev/null +++ b/Assets/_Zombie/Scripts/HttpServer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8a0de683bcf8bae408b2ed43e059e04d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 102ae42d..4af27060 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -5,7 +5,7 @@ EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 m_Scenes: - - enabled: 0 + - enabled: 1 path: Assets/_Zombie/Scenes/Company1Floor.unity guid: 386a8fdea01af8a4e8d4a9835407ddec - enabled: 0 @@ -92,9 +92,6 @@ EditorBuildSettings: - enabled: 0 path: Assets/_Zombie/Scenes/Hebei_Tangshan_Qianan_Tianyuangu.unity guid: 16ae4845ded7ba848aa2668b4d9e37af - - enabled: 0 - path: Assets/_Zombie/Scenes/Zhejiang_Hangzhou_Linping_Yintaicheng.unity - guid: 736e70df4955ee340a5f8502762c3607 - enabled: 0 path: Assets/_Zombie/Scenes/Guangdong_Guangzhou_Yanghaiyan.unity guid: 9e724d594fa47884096ceb515c8198f6 @@ -182,7 +179,7 @@ EditorBuildSettings: - enabled: 0 path: Assets/_Zombie/Scenes/Zhejiang_Wenzhou_Cangnan_Yintaicheng.unity guid: 99eb5858976e04742a32945251a36abf - - enabled: 1 + - enabled: 0 path: Assets/_Zombie/Scenes/Shandong_Weifang_Linqu_WandaGuangchang.unity guid: 011be3366ec2d0e449cbcf5b7d6e0832 - enabled: 0 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index cd0099e3..30590656 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -142,7 +142,9 @@ PlayerSettings: visionOSBundleVersion: 1.0 tvOSBundleVersion: 1.0 bundleVersion: 1.0.2 - preloadedAssets: [] + preloadedAssets: + - {fileID: 1814176829808956018, guid: 58f40b12bbc864f3c96c6505a9a1e1e3, type: 2} + - {fileID: 11400000, guid: d0f8149c48842b4488cf6fb974cff9a2, type: 2} metroInputSource: 0 wsaTransparentSwapchain: 0 m_HolographicPauseOnTrackingLoss: 1 @@ -163,7 +165,7 @@ PlayerSettings: androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.1 applicationIdentifier: - Android: com.pineappletech.zombie.shandongweifanglinquwandaguangchang + Android: com.pineappletech.zombie.gongsi1lou Standalone: com.DefaultCompany.com.unity.template.ar buildNumber: Standalone: 0