Files
2026-02-21 16:45:37 +08:00

214 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Moonlit.Utils;
using UnityEngine;
namespace Moonlit.IceFishing
{
internal class HolesController : Singleton<HolesController>
{
[Serializable]
public enum HitResult
{
Occupied = 0,
Terrain = 1,
Unoccupied = 2
}
[Serializable]
public class HitInfo
{
public HitResult Result = HitResult.Unoccupied;
public List<Hole> FoundHoles;
}
[Serializable]
private class SaveData
{
public List<HoleData> holes = new List<HoleData>();
}
[Header("Hole")]
public GameObject HolePrefab;
[SerializeField]
private GameObject _HolesParent;
public Material iceMaterial;
[Header("Random snow to draw")]
[SerializeField]
private List<GameObject> _DrilledSnowList;
[Header("Settings")]
public float MinWaterDepth = 1f;
public float WaterRaiseTime = 0.2f;
public int MaxHoleCount = 100;
private string _HoleTag = "Hole";
private string _TerrainTag = "Terrain";
private string _IceTag = "Ice";
private List<Hole> _Pool = new List<Hole>();
public string HoleTag
{
get
{
return _HoleTag;
}
}
public string TerrainTag
{
get
{
return _TerrainTag;
}
}
public string IceTag
{
get
{
return _IceTag;
}
}
public string Save()
{
SaveData saveData = new SaveData();
saveData.holes = (from x in _Pool
select x.Data into x
where x.IsFinished
select x).ToList();
string text = JsonUtility.ToJson(saveData, true);
if (string.IsNullOrEmpty(text))
{
Debug.LogError("Save data is empty!");
return null;
}
return text;
}
public void Load(string saveJson)
{
RemoveAll();
SaveData saveData = JsonUtility.FromJson<SaveData>(saveJson);
for (int i = 0; i < saveData.holes.Count; i++)
{
Create(saveData.holes[i]);
}
}
public Hole Create(HoleData data)
{
Hole hole = null;
GameObject gameObject = null;
if (MaxHoleCount >= 0)
{
while (_Pool.Count > MaxHoleCount)
{
UnityEngine.Object.Destroy(_Pool.First().gameObject);
_Pool.RemoveAt(0);
}
if (_Pool.Count == MaxHoleCount)
{
hole = _Pool.First();
_Pool.RemoveAt(0);
gameObject = hole.gameObject;
_Pool.Add(hole);
}
else
{
gameObject = UnityEngine.Object.Instantiate(HolePrefab, data.Position, Quaternion.identity);
gameObject.transform.parent = base.transform;
gameObject.name = "Hole";
hole = gameObject.GetComponent<Hole>();
_Pool.Add(hole);
}
}
hole.Set(data);
return hole;
}
public void Remove(Hole hole)
{
UnityEngine.Object.Destroy(hole.gameObject);
_Pool.Remove(hole);
}
public void RemoveAll()
{
foreach (Hole item in _Pool)
{
UnityEngine.Object.Destroy(item.gameObject);
}
_Pool.Clear();
}
public HitInfo HitCheck(Vector3 position, float radius)
{
HitInfo hitInfo = new HitInfo();
hitInfo.Result = HitResult.Unoccupied;
Vector3 point = position - Vector3.up * Singleton<HolesController>.Instance.MinWaterDepth;
Vector3 point2 = position + Vector3.up * 1f;
RaycastHit[] source = Physics.CapsuleCastAll(point, point2, radius, Vector3.up);
List<RaycastHit> list = source.Where((RaycastHit x) => x.collider.CompareTag(_HoleTag)).ToList();
if (list.Count > 0)
{
hitInfo.FoundHoles = list.Select((RaycastHit x) => x.collider.GetComponent<Hole>()).ToList();
hitInfo.Result = HitResult.Occupied;
return hitInfo;
}
List<RaycastHit> list2 = source.Where((RaycastHit x) => x.collider.CompareTag(_TerrainTag)).ToList();
List<RaycastHit> list3 = source.Where((RaycastHit x) => x.collider.gameObject.layer == LayerMask.NameToLayer("Default") || x.collider.gameObject.layer == LayerMask.NameToLayer("Terrain")).ToList();
if (list2.Count > 0 || list3.Count > 0)
{
hitInfo.Result = HitResult.Terrain;
}
return hitInfo;
}
public Vector3 FindIcePosition(Vector3 point)
{
RaycastHit[] source = (from x in Physics.RaycastAll(point, Vector3.down)
where x.collider.CompareTag(_IceTag)
select x).ToArray();
if (source.Count() != 0)
{
point.y = source.Max((RaycastHit x) => x.point.y);
return point;
}
source = (from x in Physics.RaycastAll(point, Vector3.up)
where x.collider.CompareTag(_IceTag)
select x).ToArray();
if (source.Count() != 0)
{
point.y = source.Max((RaycastHit x) => x.point.y);
return point;
}
return Vector3.zero;
}
public float GetIceThickness(Vector3 point)
{
float num = Math.Abs((Mathf.Sin((point.x + point.y + point.x * point.y) * 0.1f) + 1f) * 0.2f + 0.4f);
num = 0.6f;
Debug.Log("Ice Thickness: " + num);
return num;
}
public GameObject GetRandomSnowPrefab()
{
return _DrilledSnowList[UnityEngine.Random.Range(0, _DrilledSnowList.Count)];
}
}
}