first commit

This commit is contained in:
2025-07-06 00:23:46 +02:00
commit 38f50c8819
1788 changed files with 112878 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
using System;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.GameLogic.Bases;
using NitroxModel.DataStructures.Unity;
using NitroxModel.Packets;
using UnityEngine;
namespace NitroxModel_Subnautica.DataStructures;
/// <summary>
/// Contains extension methods for converting Unity types to Nitrox types and vice versa.
/// This is necessary to allow the server to work without a dependency on game models while still being able to represent game models.
/// </summary>
/// <remarks>
/// The abbreviation "DTO" means Data Transfer Object which is a common term used in REST APIs.
/// Its purpose is to be a serializable type and to transfer the least amount of data necessary per request (e.g. API call).
/// </remarks>
public static class DataExtensions
{
public static Int3 ToUnity(this NitroxInt3 v)
{
return new Int3(v.X, v.Y, v.Z);
}
public static NitroxInt3 ToDto(this Int3 v)
{
return new NitroxInt3(v.x, v.y, v.z);
}
public static NitroxVector3 ToDto(this Vector3 v)
{
return new NitroxVector3(v.x, v.y, v.z);
}
public static Vector3 ToUnity(this NitroxVector3 v)
{
return new Vector3(v.X, v.Y, v.Z);
}
public static NitroxVector4 ToDto(this Vector4 v)
{
return new NitroxVector4(v.x, v.y, v.z, v.w);
}
public static Vector4 ToUnity(this NitroxVector4 v)
{
return new Vector4(v.X, v.Y, v.Z, v.W);
}
public static NitroxTechType ToDto(this TechType v)
{
return new NitroxTechType(v.ToString());
}
public static TechType ToUnity(this NitroxTechType v)
{
return (TechType)Enum.Parse(typeof(TechType), v.Name);
}
public static Quaternion ToUnity(this NitroxQuaternion v)
{
return new Quaternion(v.X, v.Y, v.Z, v.W);
}
public static NitroxQuaternion ToDto(this Quaternion v)
{
return new NitroxQuaternion(v.x, v.y, v.z, v.w);
}
public static NitroxColor ToDto(this Color v)
{
return new NitroxColor(v.r, v.g, v.b, v.a);
}
public static Color ToUnity(this NitroxColor v)
{
return new Color(v.R, v.G, v.B, v.A);
}
public static NitroxTransform ToLocalDto(this Transform transform)
{
return new NitroxTransform(transform.localPosition.ToDto(),
transform.localRotation.ToDto(),
transform.localScale.ToDto());
}
public static NitroxTransform ToWorldDto(this Transform transform)
{
return new NitroxTransform(transform.position.ToDto(),
transform.rotation.ToDto(),
transform.localScale.ToDto());
}
public static NitroxColor[] ToDto(this Color[] v)
{
NitroxColor[] result = new NitroxColor[v.Length];
for (int i = 0; i < v.Length; i++)
{
result[i] = v[i].ToDto();
}
return result;
}
public static NitroxVector3[] ToDto(this Vector3[] v)
{
if (v == null)
{
return Array.Empty<NitroxVector3>();
}
NitroxVector3[] result = new NitroxVector3[v.Length];
for (int i = 0; i < v.Length; i++)
{
result[i] = v[i].ToDto();
}
return result;
}
public static Vector3[] ToUnity(this NitroxVector3[] v)
{
if (v == null)
{
return Array.Empty<Vector3>();
}
Vector3[] result = new Vector3[v.Length];
for (int i = 0; i < v.Length; i++)
{
result[i] = v[i].ToUnity();
}
return result;
}
public static StoryGoalExecuted.EventType ToDto(this Story.GoalType goalType)
{
return goalType switch
{
Story.GoalType.PDA => StoryGoalExecuted.EventType.PDA,
Story.GoalType.Radio => StoryGoalExecuted.EventType.RADIO,
Story.GoalType.Encyclopedia => StoryGoalExecuted.EventType.ENCYCLOPEDIA,
Story.GoalType.Story => StoryGoalExecuted.EventType.STORY,
_ => throw new ArgumentException("The provided Story.GoalType doesn't correspond to a StoryEventSend.EventType"),
};
}
public static Story.GoalType ToUnity(this StoryGoalExecuted.EventType eventType)
{
return eventType switch
{
StoryGoalExecuted.EventType.PDA => Story.GoalType.PDA,
StoryGoalExecuted.EventType.RADIO => Story.GoalType.Radio,
StoryGoalExecuted.EventType.ENCYCLOPEDIA => Story.GoalType.Encyclopedia,
StoryGoalExecuted.EventType.STORY => Story.GoalType.Story,
_ => throw new ArgumentException("The provided StoryEventSend.EventType doesn't correspond to a Story.GoalType")
};
}
public static PDAEntry ToDto(this PDAScanner.Entry entry)
{
return new(entry.techType.ToDto(), entry.unlocked);
}
public static PDAScanner.Entry ToUnity(this PDAEntry entry)
{
return new() { techType = entry.TechType.ToUnity(), unlocked = entry.Unlocked };
}
public static Base.Face ToUnity(this NitroxBaseFace baseFace)
{
return new(baseFace.Cell.ToUnity(), (Base.Direction)baseFace.Direction);
}
public static NitroxBaseFace ToDto(this Base.Face face)
{
return new(face.cell.ToDto(), (int)face.direction);
}
}

View File

@@ -0,0 +1,17 @@
using System;
using UnityEngine;
namespace NitroxModel_Subnautica.DataStructures.GameLogic.Creatures.Actions
{
public interface SerializableCreatureAction
{
CreatureAction GetCreatureAction(GameObject gameObject);
}
// SerializableCreatureAction is not implemented yet but test require that at least one class inherits it
[Serializable]
public class EmptyCreatureAction: SerializableCreatureAction
{
public CreatureAction GetCreatureAction(GameObject gameObject) => null;
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Runtime.Serialization;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.Unity;
using NitroxModel.DataStructures.Util;
namespace NitroxModel_Subnautica.DataStructures.GameLogic
{
[Serializable]
[DataContract]
public class CyclopsDamageInfoData
{
[DataMember(Order = 1)]
public NitroxId ReceiverId { get; set; }
[DataMember(Order = 2)]
public Optional<NitroxId> DealerId { get; set; }
[DataMember(Order = 3)]
public float OriginalDamage { get; set; }
[DataMember(Order = 4)]
public float Damage { get; set; }
[DataMember(Order = 5)]
public NitroxVector3 Position { get; set; }
[DataMember(Order = 6)]
public DamageType Type { get; set; }
protected CyclopsDamageInfoData()
{
// Constructor for serialization. Has to be "protected" for json serialization.
}
public CyclopsDamageInfoData(NitroxId receiverId, Optional<NitroxId> dealerId, float originalDamage, float damage, NitroxVector3 position, DamageType type)
{
ReceiverId = receiverId;
DealerId = dealerId;
OriginalDamage = originalDamage;
Damage = damage;
Position = position;
Type = type;
}
public override string ToString()
{
return $"[CyclopsDamageInfoData - ReceiverId: {ReceiverId} DealerId:{DealerId} OriginalDamage: {OriginalDamage} Damage: {Damage} Position: {Position} Type: {Type}}}]";
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Runtime.Serialization;
using NitroxModel.DataStructures;
namespace NitroxModel_Subnautica.DataStructures.GameLogic
{
[Serializable]
[DataContract]
public class CyclopsFireData
{
[DataMember(Order = 1)]
public NitroxId FireId { get; set; }
[DataMember(Order = 2)]
public NitroxId CyclopsId { get; set; }
[DataMember(Order = 3)]
public CyclopsRooms Room { get; set; }
[DataMember(Order = 4)]
public int NodeIndex { get; set; }
protected CyclopsFireData()
{
// Constructor for serialization. Has to be "protected" for json serialization.
}
public CyclopsFireData(NitroxId fireId, NitroxId cyclopsId, CyclopsRooms room, int nodeIndex)
{
FireId = fireId;
CyclopsId = cyclopsId;
Room = room;
NodeIndex = nodeIndex;
}
public override string ToString()
{
return $"[CyclopsFireData - FireId: {FireId}, CyclopsId: {CyclopsId}, Room: {Room}, FireNodeIndex: {NodeIndex}]";
}
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using LitJson;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.Helper;
using static LootDistributionData;
namespace NitroxModel_Subnautica.DataStructures.GameLogic.Entities;
public class SubnauticaUwePrefabFactory : IUwePrefabFactory
{
private readonly LootDistributionData lootDistributionData;
private readonly Dictionary<string, List<UwePrefab>> cache = new();
public SubnauticaUwePrefabFactory(string lootDistributionJson)
{
lootDistributionData = GetLootDistributionData(lootDistributionJson);
}
public bool TryGetPossiblePrefabs(string biome, out List<UwePrefab> prefabs)
{
if (biome == null)
{
prefabs = null;
return false;
}
if (cache.TryGetValue(biome, out prefabs))
{
return true;
}
prefabs = new();
BiomeType biomeType = (BiomeType)Enum.Parse(typeof(BiomeType), biome);
if (lootDistributionData.GetBiomeLoot(biomeType, out DstData dstData))
{
foreach (PrefabData prefabData in dstData.prefabs)
{
if (lootDistributionData.srcDistribution.TryGetValue(prefabData.classId, out SrcData srcData))
{
// Manually went through the list of those to make this "filter"
// You can verify this by looping through all of SrcData (e.g in LootDistributionData.Initialize)
// print the prefabPath and check the TechType related to the provided classId (WorldEntityDatabase.TryGetInfo) with PDAScanner.IsFragment
bool isFragment = srcData.prefabPath.Contains("Fragment") || srcData.prefabPath.Contains("BaseGlassDome");
prefabs.Add(new(prefabData.classId, prefabData.count, prefabData.probability, isFragment));
}
}
}
cache[biome] = prefabs;
return true;
}
private LootDistributionData GetLootDistributionData(string lootDistributionJson)
{
// LitJson uses the computer's local CultureInfo when parsing the JSON files.
// However, these json files were saved in en_US. Ensure that this is done for the current thread.
CultureManager.ConfigureCultureInfo();
JsonMapper.RegisterImporter((double value) => Convert.ToSingle(value));
Dictionary<string, LootDistributionData.SrcData> result = JsonMapper.ToObject<Dictionary<string, LootDistributionData.SrcData>>(lootDistributionJson);
LootDistributionData lootDistributionData = new LootDistributionData();
lootDistributionData.Initialize(result);
return lootDistributionData;
}
}

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using NitroxModel.DataStructures.GameLogic.Entities;
using UWE;
namespace NitroxModel_Subnautica.DataStructures.GameLogic.Entities;
public class SubnauticaUweWorldEntityFactory : IUweWorldEntityFactory
{
private readonly Dictionary<string, WorldEntityInfo> worldEntitiesByClassId;
public SubnauticaUweWorldEntityFactory(Dictionary<string, WorldEntityInfo> worldEntitiesByClassId)
{
this.worldEntitiesByClassId = worldEntitiesByClassId;
}
public bool TryFind(string classId, out UweWorldEntity uweWorldEntity)
{
if (worldEntitiesByClassId.TryGetValue(classId, out WorldEntityInfo worldEntityInfo))
{
uweWorldEntity = new(worldEntityInfo.classId,
worldEntityInfo.techType.ToDto(),
worldEntityInfo.slotType.ToString(),
worldEntityInfo.prefabZUp,
(int)worldEntityInfo.cellLevel,
worldEntityInfo.localScale.ToDto());
return true;
}
uweWorldEntity = null;
return false;
}
}

View File

@@ -0,0 +1,72 @@
using System.Runtime.Serialization;
using NitroxModel.DataStructures.Surrogates;
using NitroxModel.DataStructures.Unity;
using UnityEngine;
namespace NitroxModel_Subnautica.DataStructures.Surrogates
{
[DataContract]
public class QuaternionSurrogate : SerializationSurrogate<Quaternion>
{
[DataMember(Order = 1)]
public float X { get; private set; }
[DataMember(Order = 2)]
public float Y { get; private set; }
[DataMember(Order = 3)]
public float Z { get; private set; }
[DataMember(Order = 4)]
public float W { get; private set; }
protected override void GetObjectData(Quaternion quaternion, SerializationInfo info)
{
info.AddValue("w", quaternion.w);
info.AddValue("x", quaternion.x);
info.AddValue("y", quaternion.y);
info.AddValue("z", quaternion.z);
}
protected override Quaternion SetObjectData(Quaternion quaternion, SerializationInfo info)
{
quaternion.w = info.GetSingle("w");
quaternion.x = info.GetSingle("x");
quaternion.y = info.GetSingle("y");
quaternion.z = info.GetSingle("z");
return quaternion;
}
public static implicit operator QuaternionSurrogate(Quaternion v)
{
return new QuaternionSurrogate
{
X = v.x,
Y = v.y,
W = v.w,
Z = v.z
};
}
public static implicit operator Quaternion(QuaternionSurrogate surrogate)
{
return new Quaternion(surrogate.X, surrogate.Y, surrogate.Z, surrogate.W);
}
public static implicit operator QuaternionSurrogate(NitroxQuaternion v)
{
return new QuaternionSurrogate
{
X = v.X,
Y = v.Y,
W = v.W,
Z = v.Z
};
}
public static implicit operator NitroxQuaternion(QuaternionSurrogate surrogate)
{
return new NitroxQuaternion(surrogate.X, surrogate.Y, surrogate.Z, surrogate.W);
}
}
}

View File

@@ -0,0 +1,65 @@
using System.Runtime.Serialization;
using NitroxModel.DataStructures.Surrogates;
using NitroxModel.DataStructures.Unity;
using UnityEngine;
namespace NitroxModel_Subnautica.DataStructures.Surrogates
{
[DataContract]
public class Vector3Surrogate : SerializationSurrogate<Vector3>
{
[DataMember(Order = 1)]
public float X { get; private set; }
[DataMember(Order = 2)]
public float Y { get; private set; }
[DataMember(Order = 3)]
public float Z { get; private set; }
protected override void GetObjectData(Vector3 vector3, SerializationInfo info)
{
info.AddValue("x", vector3.x);
info.AddValue("y", vector3.y);
info.AddValue("z", vector3.z);
}
protected override Vector3 SetObjectData(Vector3 vector3, SerializationInfo info)
{
vector3.x = info.GetSingle("x");
vector3.y = info.GetSingle("y");
vector3.z = info.GetSingle("z");
return vector3;
}
public static implicit operator Vector3Surrogate(NitroxVector3 v)
{
return new Vector3Surrogate
{
X = v.X,
Y = v.Y,
Z = v.Z
};
}
public static implicit operator NitroxVector3(Vector3Surrogate surrogate)
{
return new NitroxVector3(surrogate.X, surrogate.Y, surrogate.Z);
}
public static implicit operator Vector3Surrogate(Vector3 v)
{
return new Vector3Surrogate
{
X = v.x,
Y = v.y,
Z = v.z
};
}
public static implicit operator Vector3(Vector3Surrogate surrogate)
{
return new Vector3(surrogate.X, surrogate.Y, surrogate.Z);
}
}
}