//#define EDITOR_TEST using UnityEngine; using Game; using FairyGUI; using LuaInterface; using System.Collections; using UnityEngine.Networking; using System.IO; using taurus.client; using taurus.unity; using System.Runtime.InteropServices; using System; public class GameApplication : MonoBehaviour { public static GameApplication Instance; public bool buildApp; public bool printLog=false; public bool accountTest=false; [HideInInspector] public bool isAndroid64bit = false; public AudioSource musicSource; public AudioSource voiceSource; DSLuaClient _luaClient; public int StopMusic { get; set; } public string GameInfo { get; set; } int _musicValue, _soundValue; bool _musicMute, _soundMute; private TestConsole _console=null; ExceptionReporter _ex_reporter=null; private LuaFunction _share_callback; private LuaFunction _wxlogin_callback; // === Gallery / Pick Image === private LuaFunction _pick_image_callback; private int _pick_max_size = 1024; // 长边最大像素 private int _pick_jpg_quality = 80; // JPG质量 1~100 void Awake() { TaurusUnity.init(); #if Build_App buildApp = true; #endif #if UNITY_STANDALONE_WIN accountTest = true; #endif #if NOT_ACCOUT_TEST accountTest = false; #endif Instance = this; Screen.sleepTimeout = SleepTimeout.NeverSleep; Application.targetFrameRate = 60; Application.runInBackground = true; Screen.fullScreen = true; UnityEngine.Debug.developerConsoleVisible = false; Input.multiTouchEnabled = false; Stage.inst.soundVolume = 0; MusicValue = PlayerPrefs.GetInt("music", 50); SoundValue = PlayerPrefs.GetInt("sound", 50); MusicMute = PlayerPrefs.GetInt("musicMute", 1) == 1; SoundMute = PlayerPrefs.GetInt("soundMute", 1) == 1; NetManager.TIMEOUT_TIME = 10; NetManager.debug_print = false; // UIConfig.depthSupportForPaintingMode = false; // Singleton.GetInstance(); } // Use this for initialization void Start() { SDKCallBack.Instance.AuthCallback = __OnWXCallBack; SDKCallBack.Instance.ShareCallback = _OnSharecallback; } internal void StartGame() { _luaClient = gameObject.AddComponent(); // _console = new TestConsole(); // _ex_reporter = new ExceptionReporter(); } public void RestartGame() { _luaClient = null; Voice.CrealRecord(); //_console.Close(); //_console = null; VerCheck.Instance.ResetGame(); } void Update() { TaurusUnity.update(); __PlayMusic(); //if (_console != null) //{ // if (printLog) // { // _console.Open(); // } // else // { // _console.Close(); // } //} } #if EDITOR_TEST //void OnApplicationFocus(bool state) //{ // if (state) // { // if (_luaClient != null) _luaClient.OnApplicationActive(); // } // else // { // //BestHTTP.HTTPManager.ClearRequestQueue(); // if (_luaClient != null) // _luaClient.OnApplicationPause1(); // } //} #else void OnApplicationPause(bool state) { #if UNITY_IPHONE || UNITY_ANDROID || UNITY_STANDALONE if (!state) { if (_luaClient != null) _luaClient.OnApplicationActive(); } else { Debug.Log("UNITY Pause"); //NetManager.KillAllConnection(); if (_luaClient != null) _luaClient.OnApplicationPause1(); } #endif } #endif void OnApplicationQuit() { TaurusUnity.destroy(); } public void UnExtendLua(LuaTable game_data) { var bundle = (string)game_data["bundle"]; var asset_path = bundle.Replace('.', '/'); #if UNITY_EDITOR && !PACK var lua_dir = LuaConst.luaDir + "/extend_project/"; #else var lua_dir = LuaConst.luaResDir+"/"; #endif var luas = Directory.GetFiles(lua_dir+ asset_path, "*.lua", SearchOption.AllDirectories); foreach(string lua in luas) { var moduleFileName = bundle+"." + Path.GetFileNameWithoutExtension(lua); ((DSLuaClient)LuaClient.Instance).Reload(moduleFileName); } } public void ShareLink(int id,string json_data, LuaFunction callback) { if (!buildApp) return; #if UNITY_EDITOR || UNITY_STANDALONE return; #else _share_callback = callback; #if UNITY_IPHONE PlatformIOS.ShareLink(id, json_data); #elif UNITY_ANDROID PlatformAndroid.Instance.ShareLink(id, json_data); #endif #endif } public void ShareLink(int id, string json_data, LuaFunction callback,bool screenshot) { if (!buildApp) return; #if UNITY_EDITOR || UNITY_STANDALONE return; #else _share_callback = callback; if (screenshot) { StartCoroutine(CaptureScreenshotCoroutine(()=>{ #if UNITY_IPHONE PlatformIOS.ShareLink(id, json_data); #elif UNITY_ANDROID PlatformAndroid.Instance.ShareLink(id, json_data); #endif })); } #endif } private IEnumerator CaptureScreenshotCoroutine(Action onComplete = null) { string folder = Path.Combine(Application.persistentDataPath, "share"); if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); string filename = "share_screenshot"; string fullpath = Path.Combine(folder, filename + ".jpg"); string thumbPath = Path.Combine(folder, filename + "_thumb.jpg"); yield return new WaitForEndOfFrame(); int width = Screen.width; int height = Screen.height; // 截取全屏 Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false); tex.ReadPixels(new Rect(0, 0, width, height), 0, 0); tex.Apply(); // 保存主图 File.WriteAllBytes(fullpath, tex.EncodeToJPG(90)); Debug.Log("[CaptureScreenshotCoroutine] 主图已保存:" + fullpath); // 生成缩略图(150x150) Texture2D thumb = ScaleTexture(tex, 150, 150); File.WriteAllBytes(thumbPath, thumb.EncodeToJPG(75)); Debug.Log("[CaptureScreenshotCoroutine] 缩略图已保存:" + thumbPath); GameObject.Destroy(tex); GameObject.Destroy(thumb); // 通知完成 onComplete?.Invoke(); } // 缩放工具 private Texture2D ScaleTexture(Texture2D src, int width, int height) { Texture2D dst = new Texture2D(width, height, src.format, false); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { dst.SetPixel(x, y, src.GetPixelBilinear((float)x / width, (float)y / height)); } } dst.Apply(); return dst; } void _OnSharecallback() { if (_share_callback != null) { _share_callback.Call(1); _share_callback.Dispose(); } } public void CopyToClipboard(string input) { #if UNITY_EDITOR || UNITY_STANDALONE TextEditor t = new TextEditor(); t.text = input; t.OnFocus(); t.Copy(); #elif UNITY_IPHONE PlatformIOS.CopyToClipboard(input); #elif UNITY_ANDROID PlatformAndroid.Instance.CopyTextToClipboard(input); #endif } public int GetBatteryLevel() { if (!buildApp) return 100; #if UNITY_EDITOR || UNITY_STANDALONE return 100; #else #if UNITY_IPHONE return Mathf.FloorToInt(PlatformIOS.GetBatteryLevel() * 100); #elif UNITY_ANDROID var lev = Mathf.FloorToInt(PlatformAndroid.Instance.GetBatteryLevel()); return lev; #endif #endif } public void InitBugly(string androidID,string iosID){ if (_ex_reporter != null) { _ex_reporter.init (androidID,iosID); } } public void SetBuglyUserID(string userid){ if (_ex_reporter != null) { _ex_reporter.setUserID (userid); } } public void AddBuglyUserValue(string key,string value){ if (_ex_reporter != null) { _ex_reporter.AddUserValue(key, value); } } void __OnWXCallBack(int result, string json) { if (_wxlogin_callback != null) { _wxlogin_callback.Call(result, json); if (result != 10) _wxlogin_callback.Dispose(); } if (result != 10) _wxlogin_callback = null; } [DllImport("native-lib")] private static extern IntPtr getAppIdCSharp(); public void WXLogin(LuaFunction callback) { if (!buildApp) return; #if UNITY_EDITOR || UNITY_STANDALONE var json = "{\"headimgurl\":\"\",\"unionid\":\"mwxtest1000001\",\"\":1,\"nickname\":\"mwxtest1000001\",\"sex\":2}"; callback.Call(0, json); #else _wxlogin_callback = callback; #if UNITY_IPHONE PlatformIOS.WXLogin(); #elif UNITY_ANDROID PlatformAndroid.Instance.WXLogin(); #endif #endif } public void WXOnlyOpen(int id, LuaFunction callback) { if (!buildApp) return; #if UNITY_EDITOR || UNITY_STANDALONE return; #else _share_callback = callback; #if UNITY_IPHONE //PlatformIOS.ShareLink(); #elif UNITY_ANDROID PlatformAndroid.Instance.WXOnlyOpen(); #endif #endif } public string GetRoomID() { #if UNITY_EDITOR || UNITY_STANDALONE return string.Empty; #else #if UNITY_IPHONE return PlatformIOS.GetRoomID(); #elif UNITY_ANDROID return PlatformAndroid.Instance.GetRoomID(); #endif #endif } public void PlayMuisc(string path) { var clip = ResourcesManager.LoadObject(path); musicSource.clip = clip; } public void PlayMuisc(string groupName,string path) { var clip = ResourcesManager.LoadObjectByGroup(path,groupName); musicSource.clip = clip; } public void PlayVoice(AudioClip clip) { voiceSource.PlayOneShot(clip, 1f); } public void PlayVoice(AudioClip clip,float volume) { voiceSource.PlayOneShot(clip, volume); } public void PlaySound(string path) { if (_soundValue < 5) return; var clip = ResourcesManager.LoadObject(path); Stage.inst.PlayOneShotSound(clip); } public void PlaySound(string groupName, string path) { if (_soundValue < 5) return; var clip = ResourcesManager.LoadObjectByGroup(path, groupName); Stage.inst.PlayOneShotSound(clip); } public void GetPublicIP(Action callback) { StartCoroutine(GetPublicIPSend(callback)); } IEnumerator GetPublicIPSend(Action callback) { string url = "https://ipv4.icanhazip.com"; using (UnityWebRequest req = UnityWebRequest.Get(url)) { yield return req.SendWebRequest(); #if UNITY_2020_1_OR_NEWER if (req.result != UnityWebRequest.Result.Success) #else if (req.isNetworkError || req.isHttpError) #endif { Debug.LogError("获取公网 IP 失败: " + req.error); callback?.Invoke("获取公网 IP 失败"); } else { string publicIP = req.downloadHandler.text.Trim(); Debug.Log("公网 IP: " + publicIP); callback?.Invoke(publicIP); } } } void __PlayMusic() { if (_musicValue >= 5) { if (StopMusic > 0) { if (musicSource.isPlaying) musicSource.Pause(); } else { if (!musicSource.isPlaying) musicSource.Play(); } } else { if (musicSource.isPlaying) musicSource.Stop(); } } public int MusicValue { get { return _musicValue; } set { if (_musicValue != value) { _musicValue = value; musicSource.volume = _musicValue / 100f; PlayerPrefs.SetInt("music", _musicValue); PlayerPrefs.Save(); } } } public int SoundValue { get { return _soundValue; } set { if (_soundValue != value) { _soundValue = value; Stage.inst.soundVolume = _soundValue / 100f; PlayerPrefs.SetInt("sound", _soundValue); PlayerPrefs.Save(); } } } public bool SoundMute { get { return _soundMute; } set { if(_soundMute != value) { _soundMute = value; //Stage.inst.mute = _soundMute; PlayerPrefs.SetInt("soundMute", _soundMute ? 1 : 0); PlayerPrefs.Save(); } } } public bool MusicMute { get { return _musicMute; } set { if (_musicMute != value) { _musicMute = value; musicSource.mute = _musicMute; PlayerPrefs.SetInt("musicMute", _musicMute ? 1 : 0); PlayerPrefs.Save(); } } } public void InitBaiduMap(string id) { #if UNITY_ANDROID #elif UNITY_IPHONE #endif } [LuaInterface.NoToLua] /// /// 版本号 /// public static readonly Version AppVersion = new Version("1.0.0"); /// /// 审核用于隐藏相关内容 /// public static bool HideSdk = false; public void QuitGameOnUnity() { Application.Quit(); } private const string UPLOAD_IMAGE_URL = "http://8.138.255.70:9898/api/common/uploadimage"; /// Lua: GameApplication.Instance:PickAndUploadImage(function(ok, json) end) /// 返回 json: /// - 选图信息: localPath,width,height,mime,orientation /// - 上传结果: url, fullurl, size, ext, serverName public void PickAndUploadImage(LuaFunction cb) { #if UNITY_EDITOR SafeLuaCallback(cb, false, "{\"err\":\"UNITY_EDITOR\"}"); return; #else // 1) 先选图 try { NativeGallery.RequestPermissionAsync((perm) => { if (perm != NativeGallery.Permission.Granted) { SafeLuaCallback(cb, false, "{\"err\":\"PERMISSION_DENIED\"}"); return; } NativeGallery.GetImageFromGallery((path) => { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { SafeLuaCallback(cb, false, "{\"err\":\"CANCEL_OR_NOT_FOUND\"}"); return; } // 2) 拿图片属性(可选) NativeGallery.ImageProperties prop; try { prop = NativeGallery.GetImageProperties(path); } catch { prop = new NativeGallery.ImageProperties(0, 0, "", NativeGallery.ImageOrientation.Unknown); } // 3) 上传 StartCoroutine(CoUploadPickedImage(path, prop, cb)); }, "请选择一张图片", "image/*"); }, NativeGallery.PermissionType.Read, NativeGallery.MediaType.Image); } catch (Exception e) { SafeLuaCallback(cb, false, "{\"err\":\"EXCEPTION\",\"msg\":\"" + EscapeJson(e.ToString()) + "\"}"); } #endif } private IEnumerator CoUploadPickedImage(string localPath, NativeGallery.ImageProperties prop, LuaFunction cb) { byte[] bytes; try { bytes = File.ReadAllBytes(localPath); } catch (Exception e) { SafeLuaCallback(cb, false, "{\"err\":\"READ_FILE_FAIL\",\"msg\":\"" + EscapeJson(e.Message) + "\"}"); yield break; } string fileName = Path.GetFileName(localPath); if (string.IsNullOrEmpty(Path.GetExtension(fileName))) fileName += ".jpg"; // 防御:没后缀就补一个 WWWForm form = new WWWForm(); form.AddBinaryData("file", bytes, fileName, "application/octet-stream"); // 服务端字段名是 file using (UnityWebRequest req = UnityWebRequest.Post(UPLOAD_IMAGE_URL, form)) { req.timeout = 60; yield return req.SendWebRequest(); #if UNITY_2020_2_OR_NEWER bool ok = req.result == UnityWebRequest.Result.Success; #else bool ok = !(req.isNetworkError || req.isHttpError); #endif string body = req.downloadHandler != null ? req.downloadHandler.text : ""; if (!ok) { string errJson = "{" + "\"err\":\"UPLOAD_FAIL\"," + "\"http\":\"" + EscapeJson(req.error ?? "") + "\"," + "\"resp\":\"" + EscapeJson(body) + "\"" + "}"; SafeLuaCallback(cb, false, errJson); yield break; } // 把选图信息 + 服务器返回一起打包给 Lua(不解析服务端 JSON,直接原样塞回,Lua 自己 decode) string resultJson = "{" + "\"localPath\":\"" + EscapeJson(localPath) + "\"," + "\"width\":" + prop.width + "," + "\"height\":" + prop.height + "," + "\"mime\":\"" + EscapeJson(prop.mimeType ?? "") + "\"," + "\"orientation\":" + (int)prop.orientation + "," + "\"serverResp\":" + SafeJsonObject(body) + "}"; SafeLuaCallback(cb, true, resultJson); } } private void SafeLuaCallback(LuaFunction fn, bool ok, string json) { if (fn == null) return; try { fn.Call(ok, json); } catch (Exception e) { Debug.LogException(e); } finally { fn.Dispose(); } } private string EscapeJson(string s) { if (string.IsNullOrEmpty(s)) return ""; return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "\\r"); } // 服务端返回一般是 {"code":1,...},这里确保拼接时是合法 json private string SafeJsonObject(string s) { if (string.IsNullOrEmpty(s)) return "{}"; s = s.Trim(); if (s.StartsWith("{") && s.EndsWith("}")) return s; // 看起来像对象 return "{\"raw\":\"" + EscapeJson(s) + "\"}"; } }