备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,396 @@
using System;
using System.Security.Cryptography;
using System.Text;
using GameCore;
using UnityEngine;
public class ConvertTools
{
public static string ConvertTime2(int d, int h, int m, int s)
{
string str = "";
int showCount = 0;
int maxShowCount = 2;
if (d > 0)
{
showCount++;
str = $"{d}d ";
}
if (h > 0)
{
showCount++;
str += $"{h}h ";
}
if (showCount >= maxShowCount)
{
return str;
}
else if (m > 0)
{
showCount++;
str += $"{m}m ";
}
if (showCount >= maxShowCount)
{
return str;
}
else if (s > 0)
{
str += $"{s}s ";
}
return str;
}
public static string ConvertTime2(TimeSpan timer)
{
return ConvertTime2(timer.Days, timer.Hours, timer.Minutes, timer.Seconds);
}
/// <summary>
/// Only One Number, negative time will be considered as 0.
/// </summary>
/// <param name="timer"></param>
/// <returns></returns>
public static string ConvertTime3(TimeSpan timer)
{
if (timer.Days > 0)
{
return $"{timer.Days}d ";
}
if (timer.Hours > 0)
{
return $"{timer.Hours}h ";
}
if (timer.Minutes > 0)
{
return $"{timer.Minutes}m ";
}
if (timer.Seconds > 0)
{
return $"{timer.Seconds}s ";
}
return "0s ";
}
/// <summary>
/// hh:mm:ss
/// </summary>
/// <param name="timer"></param>
/// <returns></returns>
public static string ConvertTime(TimeSpan timer)
{
return timer.ToString(@"hh\:mm\:ss"); ;
}
public static DateTime GetDateTimeYMD(DateTime date)
{
return new DateTime(date.Year, date.Month, date.Day);
}
public static DateTime GetDateTimeSunDay(DateTime date)
{
var dayOfWeek = (int)date.DayOfWeek;
int offset = 7 - (dayOfWeek == 0 ? 7 : dayOfWeek);
return GetDateTimeYMD(date.AddDays(Mathf.Abs(offset)));
}
/// <summary>
/// ("#,##0.#")
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString(ulong num, bool keep = false)
{
string format = keep ? "#,##0.0" : "#,##0.#";
string str;
if (num < 1000)
{
str = num.ToString("#,##0");
}
else if (num < 1000000)
{
str = (num / 1000f).ToString(format) + "K";
}
else if (num < 1000000000)
{
str = (num / 1000000f).ToString(format) + "M";
}
else
{
str = (num / 1000000000f).ToString(format) + "G";
}
return str;
}
/* public static ulong KeepThreeSignificantDigits(ulong value)
{
if (value == 0) return 0;
// ulong absValue = Math.Abs(value);
ulong digits = (ulong)Math.Floor(Math.Log10(value)) + 1;
if (digits <= 3)
return value;
ulong digitsToRemove = digits - 3;
ulong factor = (ulong)Math.Pow(10, digitsToRemove);
ulong rounded = (value / factor) * factor;
return rounded;
} */
public static int KeepThreeSignificantDigits(int value)
{
if (value <= 0) return 0;
int digits = (int)Math.Floor(Math.Log10(value)) + 1;
if (digits <= 3)
return value;
int digitsToRemove = digits - 3;
int factor = (int)Math.Pow(10, digitsToRemove);
int rounded = value / factor * factor;
return rounded;
}
/// <summary>
/// ("#,##0.#")
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString(int num, bool keep = false)
{
string format = keep ? "#,##0.0" : "#,##0.#";
string str;
if (num < 1000)
{
str = num.ToString("#,##0");
}
else if (num < 1000000)
{
str = (num / 1000f).ToString(format) + "K";
}
else
{
str = (num / 1000000f).ToString(format) + "M";
}
return str;
}
/// <summary>
/// 折扣显示
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString3(float num)
{
string str = "";
if (num <= 1)
{
var discount = (1 - num) * 100;
var decimalPart = discount - (int)discount;
// if ( decimalPart < 0.001f )
str = discount.ToString("F0");
// else
// str = discount.ToString("F1");
}
else
Debug.LogError("[ConverTools::GetNumberString3] Discount Exceeds 1");
return str + "%";
}
public static string GetNumberStringRetain(double num, bool keep)
{
string str = "";
if (num < 0.1)
{
str = num.ToString("##0.00");
}
else if (keep)
{
str = num.ToString("##0.0");
}
else
{
str = num.ToString("##0.#");
}
return str;
}
/// <summary>
/// ("#,##0")
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString2(ulong num)
{
//输出类似713,999,999
return num.ToString("#,##0");
}
/// <summary>
/// ("#,##0")
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString2(long num)
{
//输出类似713,999,999
return num.ToString("#,##0");
}
/// <summary>
/// ("#,##0")
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString2(int num)
{
//输出类似713,999,999
return num.ToString("#,##0");
}
/// <summary>
/// 场景到UI 的坐标转换
/// </summary>
/// <param name="pos">场景中的全局坐标</param>
/// <param name="local">是否转换成相对于UIRoot的局部坐标</param>
/// <returns></returns>
public static Vector3 WorldToScreenPoint(Vector3 pos, bool local = true)
{
Vector3 targetPos = Camera.main.WorldToScreenPoint(pos);
Vector2 sizeDelta = UIManager.Instance.RectTrans.sizeDelta;
//先获取主画布下的分辨率宽高:
float resolutionRatioWidth = sizeDelta.x;
float resolutionRatioHeight = sizeDelta.y;
//计算主画布分辨率下的宽高和屏幕的宽高的比列:
float widthRatio = resolutionRatioWidth / Screen.width;
float heightRatio = resolutionRatioHeight / Screen.height;
//先分别乘以宽高比值
targetPos.x *= widthRatio;
targetPos.y *= heightRatio;
//计算在中心点的屏幕坐标
targetPos.x -= resolutionRatioWidth * 0.5f;
targetPos.y -= resolutionRatioHeight * 0.5f;
if (local)
{
return targetPos;
}
return UIManager.Instance.RectTrans.transform.TransformPoint(targetPos);
}
/// <summary>
/// 将3D场景的坐标转化为某个UI组件下的局部坐标。
/// </summary>
/// <param name="worldPosition">3D场景下的坐标</param>
/// <param name="uiRectTransform">目标UI组件默认为UIRoot但UIRoot可能会有刘海屏适配bug。</param>
/// <returns>相对于uiRectTransform的局部UI坐标</returns>
public static Vector2 WorldToUiLocalPosition(Vector3 worldPosition, RectTransform uiRectTransform = null)
{
// uiRectTransform ??= UIManager.Instance.RectTrans;
var screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, worldPosition);
return screenPoint;
// Debug.Log($"ScreenPoint: {screenPoint}");
// RectTransformUtility.ScreenPointToLocalPointInRectangle(uiRectTransform, screenPoint, Camera.main, out var localHitPosition);
// Debug.Log($"localHitPosition: {localHitPosition}");
// return localHitPosition;
}
public static string Encrypt(string text, string key)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Key = Encoding.ASCII.GetBytes(key);
des.IV = Encoding.ASCII.GetBytes(key);
ICryptoTransform encryptor = des.CreateEncryptor(des.Key, des.IV);
byte[] inputBytes = Encoding.UTF8.GetBytes(text);
byte[] outputBytes = encryptor.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
return Convert.ToBase64String(outputBytes);
}
const string RTMKey = "tbambooz";
public static string Decrypt(string text)
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Key = Encoding.ASCII.GetBytes(RTMKey);
des.IV = Encoding.ASCII.GetBytes(RTMKey);
ICryptoTransform decryptor = des.CreateDecryptor(des.Key, des.IV);
byte[] inputBytes = Convert.FromBase64String(text);
byte[] outputBytes = decryptor.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
return Encoding.UTF8.GetString(outputBytes);
}
/// <summary>
/// 计算相机偏转限制
/// </summary>
/// <param name="configuredRotationAngle">为正数0-180</param>
/// <returns></returns>
public static float CalculateActualRotationAngle(float configuredRotationAngle)
{
float fovRad = 30 * Mathf.Deg2Rad;
float rotationAngleRad = configuredRotationAngle * Mathf.Deg2Rad;
float aspectRatio = Screen.width / (float)Screen.height;
aspectRatio = Mathf.Clamp(aspectRatio, 0.45f, 1);
aspectRatio = Mathf.Atan(Mathf.Tan(fovRad) * aspectRatio);
float actualRotationAngleRad = Mathf.Max(0, rotationAngleRad - aspectRatio);
float actualRotationAngle = actualRotationAngleRad * Mathf.Rad2Deg;
return actualRotationAngle;
}
public static string ConvertActiveTime(TimeSpan t)
{
if (t.Days > 0)
{
return "";
}
if (t.Hours > 0)
{
return $"{t.Hours}h";
}
if (t.Minutes > 0)
{
return $"{t.Minutes}m";
}
if (t.Seconds > 0)
{
return $"{t.Seconds}s";
}
return "0s";
}
static public void SetFSBlur(bool isActive, float depth = 6)
{
var feature = zzwater.URPHelper.FindAndCacheRendererFeature("FSBlur");
if (feature == null)
Debug.LogError($"Feature FSWave not found");
else
{
feature.SetActive(isActive);
if (isActive)
{
FullScreenPassRendererFeature fullScreenPassRendererFeature = feature as FullScreenPassRendererFeature;
Material material = fullScreenPassRendererFeature.passMaterial;
if (material != null)
{
material.SetFloat("_DepthThreshold", depth);
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e0d31e6c27a64041821743c06361aee8
timeCreated: 1692100847

View File

@@ -0,0 +1,43 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class FileLogger : MonoBehaviour
{
private string logFilePath;
// Start is called before the first frame update
void Start()
{
// 定义日志文件路径
logFilePath = Application.persistentDataPath + "/game_log.txt";
// 删除旧日志文件(如果存在)
if (File.Exists(logFilePath))
{
File.Delete(logFilePath);
}
// 注册自定义日志处理器
Application.logMessageReceived += HandleLog;
}
void OnDestroy()
{
// 注销自定义日志处理器
Application.logMessageReceived -= HandleLog;
}
void HandleLog(string logString, string stackTrace, LogType type)
{
// 将日志信息写入文件
using (StreamWriter writer = new StreamWriter(logFilePath, true))
{
writer.WriteLine($"[{type}] {logString}");
if (type == LogType.Error || type == LogType.Exception)
{
writer.WriteLine(stackTrace); // 如果是错误或异常,写入堆栈跟踪
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7059e1f13854ccf4297d334c3af811bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,251 @@
using System.Collections.Generic;
using System.Linq;
using UnityRandom = UnityEngine.Random;
using SystemRandom = System.Random;
using UnityEngine;
public static class FtMathUtils
{
/// <summary>
/// Split number into count pieces randomly.
/// </summary>
/// <param name="number">Number to split.</param>
/// <param name="count">Number of pieces.</param>
/// <param name="res">Result. Meaningless if result if false.</param>
/// <returns>False if fail to split.</returns>
public static bool RandomSplit(int number, int count, out List<int> res)
{
res = new List<int>();
if (number < count || number <= 0 || count <= 0)
return false;
var baseNumbers = new HashSet<int> { 0 };
while (baseNumbers.Count < count)
baseNumbers.Add(UnityRandom.Range(1, number - 1));
var baseList = baseNumbers.OrderBy(e => e).ToList();
for (int i = 1; i < baseList.Count; i++)
res.Add(baseList[i] - baseList[i - 1]);
res.Add(number - baseList[^1]);
return res.Count == count;
}
public static bool ScaleByBase(int num, int baseNum, out int res)
{
res = baseNum;
if (num <= 0 || baseNum <= 0)
return false;
if (num <= baseNum)
return true;
res = num / baseNum * baseNum;
return true;
}
public static int GetRandomIdxFromWeightList(IEnumerable<int> weightList)
{
// Check for null or empty list
if (weightList == null || !weightList.Any())
{
Debug.LogError("[GetRandomIdxFromWeightList]: Weight list is null or empty. Returning 0.");
return 0;
}
var accWeightList = new List<int>();
int tmp = 0;
foreach (int w in weightList)
{
// Check for negative weights
if (w < 0)
{
Debug.LogError($"[GetRandomIdxFromWeightList]: Negative weight detected: {w}. Returning 0.");
return 0;
}
tmp += w;
accWeightList.Add(tmp);
}
// Check for all zero weights
if (accWeightList[^1] <= 0)
{
Debug.LogError("[GetRandomIdxFromWeightList]: Total weight is zero or negative. Returning 0.");
return 0;
}
tmp = UnityRandom.Range(0, accWeightList[^1]);
for (int i = 0; i < accWeightList.Count; i++)
{
if (tmp < accWeightList[i])
return i;
}
return accWeightList.Count - 1;
}
public static int GetRandomIdxFromWeightList(IEnumerable<int> weightList, SystemRandom rng)
{
// Check for null or empty list
if (weightList == null || !weightList.Any())
{
Debug.LogError("[GetRandomIdxFromWeightList]: Weight list is null or empty. Returning 0.");
return 0;
}
var accWeightList = new List<int>();
int tmp = 0;
foreach (int w in weightList)
{
// Check for negative weights
if (w < 0)
{
Debug.LogError("[GetRandomIdxFromWeightList]: Negative weight detected. Returning 0.");
return 0;
}
tmp += w;
accWeightList.Add(tmp);
}
// Check for all zero weights
if (accWeightList[^1] <= 0)
{
Debug.LogError("[GetRandomIdxFromWeightList]: Total weight is zero or negative. Returning 0.");
return 0;
}
tmp = rng.Next(0, accWeightList[^1]);
for (int i = 0; i < accWeightList.Count; i++)
{
if (tmp < accWeightList[i])
return i;
}
return accWeightList.Count - 1;
}
public static int GetRandomIdxFromWeightList(IEnumerable<float> weightList, SystemRandom rng)
{
// Check for null or empty list
if (weightList == null || !weightList.Any())
{
Debug.LogError("[GetRandomIdxFromWeightList]: Weight list is null or empty. Returning 0.");
return 0;
}
var accWeightList = new List<float>();
double tmp = 0d;
foreach (float w in weightList)
{
// Check for negative weights
if (w < 0)
{
Debug.LogError("[GetRandomIdxFromWeightList]: Negative weight detected. Returning 0.");
return 0;
}
tmp += w;
accWeightList.Add((float)tmp);
}
// Check for all zero weights
if (accWeightList[^1] <= 0)
{
Debug.LogError("[GetRandomIdxFromWeightList]: Total weight is zero or negative. Returning 0.");
return 0;
}
tmp = rng.NextDouble() * accWeightList[^1];
for (int i = 0; i < accWeightList.Count; i++)
{
if (tmp < accWeightList[i])
return i;
}
return accWeightList.Count - 1;
}
public static T PickRandomItemWithWeight<T>(IEnumerable<T> items, SystemRandom rng, System.Func<int, float> weightGetter)
{
var weightList = items.Select((x, i) => weightGetter(i)).ToList();
return items.ElementAt(GetRandomIdxFromWeightList(weightList, rng));
}
public static T PickRandomItemWithWeight<T>(IEnumerable<T> items, System.Func<int, int> weightGetter)
{
var weightList = items.Select((x, i) => weightGetter(i)).ToList();
return items.ElementAt(GetRandomIdxFromWeightList(weightList));
}
public static Vector2 CalculateBezierCurve(float t, Vector2 p0, Vector2 p1, Vector2 p2)
{
if (t < 0 || t > 1)
return Vector2.zero;
Vector2 a = Vector2.Lerp(p0, p1, t);
Vector2 b = Vector2.Lerp(p1, p2, t);
return Vector2.Lerp(a, b, t);
}
/// <summary>
/// ("#,##0") Display number with comma, integer part only.
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public static string GetNumberString(float num)
{
string str;
if (num < 1000)
{
str = num.ToString("#,##0");
}
else if (num < 1000000)
{
str = (num / 1000f).ToString("#,##0") + "K";
}
else if (num < 1000000000)
{
str = (num / 1000000f).ToString("#,##0") + "M";
}
else
{
str = (num / 1000000000f).ToString("#,##0") + "G";
}
return str;
}
public static int[] BitWisePositionScan(int num)
{
var res = new List<int>();
int idx = 0;
while (num != 0)
{
if ((num & 1) == 1)
res.Add(idx);
num >>= 1;
idx++;
}
return res.ToArray();
}
public static void ShuffleList<T>(IList<T> list, System.Random rng)
{
for (int i = list.Count - 1; i > 0; i--)
{
int j = rng.Next(i + 1);
(list[j], list[i]) = (list[i], list[j]);
}
}
/// <summary>
/// Get a random point in a corn-shaped spread.
/// </summary>
/// <param name="spreadHalfAngle">In degree.</param>
/// <param name="spreadNearRange">Close range.</param>
/// <param name="spreadFarRange">Far range.</param>
/// <param name="direction">In radians. Default is upward vertical, 90 degrees.</param>
/// <returns>A random delta</returns>
public static Vector2 GetCornSpread(float spreadHalfAngle, float spreadNearRange, float spreadFarRange, float direction = 90)
{
var halfAngleRadians = Mathf.Deg2Rad * spreadHalfAngle;
var angle = UnityRandom.Range(-halfAngleRadians, halfAngleRadians);
angle += Mathf.Deg2Rad * direction;
var radius = UnityRandom.Range(spreadNearRange, spreadFarRange);
return new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * radius;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 494ccf553197cfd47abb1e4a4544586c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using asap.core;
using game;
using GameCore;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveMainCameraToThisLocation : MonoBehaviour
{
[SerializeField]
public bool m_IsSolo = true;
private Vector3 originalLocalScale;
private Quaternion originalRotation;
private Vector3 originalPosition;
void Awake()
{
if (m_IsSolo)
{
Camera camera = this.transform.GetComponent<Camera>();
camera.tag = "MainCamera";
}
else
{
Camera main = Camera.main;
main.transform.localScale = originalLocalScale = this.transform.localScale;
main.transform.rotation = originalRotation = this.transform.rotation;
main.transform.position = originalPosition = this.transform.position;
gameObject.SetActive(false);
}
}
private void OnDestroy()
{
Camera cameraMain = Camera.main;
if (cameraMain != null)
{
cameraMain.transform.localScale = originalLocalScale;
cameraMain.transform.rotation = originalRotation;
cameraMain.transform.position = originalPosition;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1a5d1e8f6f54ba747abbd4bd1b98d47e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
using UnityEngine;
using System.Collections.Generic;
public class Triangulator
{
private List<Vector2> m_points = new List<Vector2>();
public Triangulator(Vector2[] points)
{
m_points = new List<Vector2>(points);
}
public int[] Triangulate()
{
List<int> indices = new List<int>();
int n = m_points.Count;
if (n < 3)
return indices.ToArray();
int[] V = new int[n];
if (Area() > 0)//如果逆时针选点点的index正向记录
{
for (int v = 0; v < n; v++)
V[v] = v;
}
else
{//如果顺时针选点点的index反向记录
for (int v = 0; v < n; v++)
V[v] = (n - 1) - v;
}
int nv = n;
int count = 2 * nv;
for (int v = nv - 1; nv > 2;)
{
if ((count--) <= 0)
return indices.ToArray();
int u = v;
if (nv <= u)
u = 0;
v = u + 1;
if (nv <= v)
v = 0;
int w = v + 1;
if (nv <= w)
w = 0;
if (Snip(u, v, w, nv, V))//u,v,w三点是否能构成三角面
{
int a, b, c, s, t;
a = V[u];
b = V[v];
c = V[w];
indices.Add(a);
indices.Add(b);
indices.Add(c);
for (s = v, t = v + 1; t < nv; s++, t++)//增加一个三角数据,把这个三角剪去
V[s] = V[t];
nv--;
count = 2 * nv;
}
}
indices.Reverse();//翻转法线
return indices.ToArray();
}
private float Area()
{
int n = m_points.Count;
float A = 0.0f;
for (int p = n - 1, q = 0; q < n; p = q++)
{
Vector2 pval = m_points[p];
Vector2 qval = m_points[q];
A += pval.x * qval.y - qval.x * pval.y;//两向量叉乘只取z值如果为负则顺时针
}
return (A * 0.5f);
}
private bool Snip(int u, int v, int w, int n, int[] V)
{
int p;
Vector2 A = m_points[V[u]];
Vector2 B = m_points[V[v]];
Vector2 C = m_points[V[w]];
if (Mathf.Epsilon > (((B.x - A.x) * (C.y - A.y)) - ((B.y - A.y) * (C.x - A.x))))//判断三点是否为顺时针排列,如果是的话是凹陷,不计算三角
return false;
for (p = 0; p < n; p++)
{
if ((p == u) || (p == v) || (p == w))
continue;
Vector2 P = m_points[V[p]];
if (InsideTriangle(A, B, C, P))//是否有其他的点在三角形内部,是,不计算三角
return false;
}
return true;
}
private bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P)
{
float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
float cCROSSap, bCROSScp, aCROSSbp;
ax = C.x - B.x; ay = C.y - B.y;
bx = A.x - C.x; by = A.y - C.y;
cx = B.x - A.x; cy = B.y - A.y;
apx = P.x - A.x; apy = P.y - A.y;
bpx = P.x - B.x; bpy = P.y - B.y;
cpx = P.x - C.x; cpy = P.y - C.y;
aCROSSbp = ax * bpy - ay * bpx;
cCROSSap = cx * apy - cy * apx;
bCROSScp = bx * cpy - by * cpx;
return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));//都是逆时针P在ABC内
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7061521568a2c1a4196b1aa20722b9f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: