Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ency paths and Coordinated spawns #47

Merged
merged 13 commits into from
Nov 6, 2023
6 changes: 3 additions & 3 deletions SCHIZO/Creatures/UnityCreaturePrefab.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics.CodeAnalysis;
using ECCLibrary;
using Nautilus.Handlers;
Expand Down Expand Up @@ -27,9 +27,9 @@ protected override void SetItemProperties()
if (UnityData.acidImmune) CreatureDataUtils.SetAcidImmune(ModItem);
if (UnityData.bioReactorCharge > 0) CreatureDataUtils.SetBioreactorCharge(ModItem, UnityData.bioReactorCharge);

if (UnityData.PDAEncyclopediaInfo)
if (UnityData.pdaEncyInfo)
{
PDAHandler.AddCustomScannerEntry(ModItem, UnityData.PDAEncyclopediaInfo.scanTime, encyclopediaKey: PrefabInfo.ClassID);
PDAHandler.AddCustomScannerEntry(ModItem, UnityData.pdaEncyInfo.scanTime, encyclopediaKey: PrefabInfo.ClassID);
}

if (UnityData.isPickupable)
Expand Down
1 change: 0 additions & 1 deletion SCHIZO/Items/Data/ItemData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ partial class ItemData
public string[] CraftTreePath => RetargetHelpers.Pick(craftTreePathSN, craftTreePathBZ).Split('/');
public TechGroup TechGroup => (TechGroup) RetargetHelpers.Pick(techGroupSN, techGroupBZ);
public TechCategory TechCategory => (TechCategory) RetargetHelpers.Pick(techCategorySN, techCategoryBZ);
public PDAEncyclopediaInfo PDAEncyclopediaInfo => RetargetHelpers.Pick(pdaEncyclopediaInfoSN, pdaEncyclopediaInfoBZ);
public KnownTechInfo KnownTechInfo => RetargetHelpers.Pick(knownTechInfoSN, knownTechInfoBZ);
public bool UnlockAtStart => RetargetHelpers.Pick(unlockAtStartSN, unlockAtStartBZ);
public TechType RequiredForUnlock => RetargetHelpers.Pick(requiredForUnlockSN, requiredForUnlockBZ).GetTechType();
Expand Down
7 changes: 4 additions & 3 deletions SCHIZO/Items/UnityPrefab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,12 @@ protected virtual void SetItemProperties()
CraftDataHandler.AddToGroup(ModItem.ItemData.TechGroup, ModItem.ItemData.TechCategory, ModItem);
}

if (ModItem.ItemData.PDAEncyclopediaInfo)
if (ModItem.ItemData.pdaEncyInfo)
{
PDAEncyclopediaInfo i = ModItem.ItemData.PDAEncyclopediaInfo;
PDAEncyclopediaInfo i = ModItem.ItemData.pdaEncyInfo;
string encyPath = RetargetHelpers.Pick(i.encyPathSN, i.encyPathBZ);

PDAHandler.AddEncyclopediaEntry(ModItem.PrefabInfo.ClassID, i.encyPath, i.title, i.description.text, i.texture, i.unlockSprite,
PDAHandler.AddEncyclopediaEntry(ModItem.PrefabInfo.ClassID, encyPath, i.title, i.description.text, i.texture, i.unlockSprite,
i.isImportantUnlock ? PDAHandler.UnlockImportant : PDAHandler.UnlockBasic);

if (i.scanSounds) ScanSoundHandler.Register(ModItem, i.scanSounds);
Expand Down
21 changes: 21 additions & 0 deletions SCHIZO/Spawns/CoordinatedSpawns.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Nautilus.Handlers;
using NSpawnInfo = Nautilus.Handlers.SpawnInfo;

namespace SCHIZO.Spawns;

partial class CoordinatedSpawns
{
protected override void Register()
{
foreach (SpawnInfo spawnInfo in spawns)
{
if (!spawnInfo.game.HasFlag(GAME)) continue;

foreach (SpawnInfo.SpawnLocation location in spawnInfo.locations)
{
NSpawnInfo nSpawnInfo = new((TechType)spawnInfo.item.techType, location.position, location.rotation);
CoordinatedSpawnsHandler.RegisterCoordinatedSpawn(nSpawnInfo);
}
}
}
}
2 changes: 1 addition & 1 deletion Unity/Assets/Editor/Scripts/Editor.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}
}
8 changes: 8 additions & 0 deletions Unity/Assets/Editor/Scripts/Extensions.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions Unity/Assets/Editor/Scripts/Extensions/GameAttributeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using SCHIZO.Helpers;
using SCHIZO.Registering;
using UnityEditor;

namespace Editor.Scripts.Extensions
{
public static class GameAttributeExtensions
{
public static bool TryGetGame(this GameAttribute attr, out Game game) => TryGetGame(attr, null, out game);
public static bool TryGetGame(this GameAttribute attr, SerializedProperty property, out Game game)
{
game = attr.game;
if (game > 0 || string.IsNullOrEmpty(attr.gameMember)) return true;
if (property == null) return false;

object target = property.GetParent().GetSerializedValue<object>();
game = ReflectionHelpers.GetMemberValue<Game>(target, attr.gameMember);
return true;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using SCHIZO.Helpers;
using UnityEditor;

namespace Editor.Scripts.Extensions
{
public static class SerializedPropertyExtensions
{
// most (all) of the code is adapted from this thread: https://forum.unity.com/threads/get-a-general-object-value-from-serializedproperty.327098/
private delegate FieldInfo GetFieldInfo(SerializedProperty prop, out Type type);
private static readonly GetFieldInfo fieldInfoGetter = Setup();

public static FieldInfo GetFieldInfoAndStaticType(this SerializedProperty prop, out Type type)
{
return fieldInfoGetter(prop, out type);
}

private static GetFieldInfo Setup()
{
Type t = Type.GetType("UnityEditor.ScriptAttributeUtility, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
MethodInfo mi = t.GetMethod("GetFieldInfoAndStaticTypeFromProperty", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
return (GetFieldInfo) Delegate.CreateDelegate(typeof(GetFieldInfo), mi);
}

public static T GetCustomAttribute<T>(this SerializedProperty prop) where T : Attribute
{
FieldInfo info = prop.GetFieldInfoAndStaticType(out _);
return info.GetCustomAttribute<T>();
}

public static bool TryGetAttributeInHierarchy<T>(this SerializedProperty prop, out T attribute, out SerializedProperty ancestorWithAttribute) where T : Attribute
{
attribute = null;
ancestorWithAttribute = null;
foreach (SerializedProperty ancestor in prop.WalkHierarchy())
{
attribute = ancestor.GetCustomAttribute<T>();
if (attribute != null)
{
ancestorWithAttribute = ancestor;
return true;
}
}
return false;
}

public static SerializedProperty GetParent(this SerializedProperty property)
{
int i = property.propertyPath.LastIndexOf('.');
return i < 0 ? null
: property.serializedObject.FindProperty(property.propertyPath.Substring(0, i));
}

public static IEnumerable<SerializedProperty> WalkHierarchy(this SerializedProperty prop)
{
for (SerializedProperty curr = prop; curr != null; curr = curr.GetParent())
yield return curr;
}

public static T GetSerializedValue<T>(this SerializedProperty property)
{
// adapted from https://github.com/lordofduct/spacepuppy-unity-framework-4.0/blob/679088a9fca826764de39390b4e08c6feaa06b52/Framework/com.spacepuppy.core/Editor/src/EditorHelper.cs#L278
string path = property.propertyPath.Replace(".Array.data[", "[");
object obj = property.serializedObject.targetObject;

foreach (string elem in path.Split('.'))
{
if (elem[elem.Length - 1] == ']')
{
string memberName = elem.Substring(0, elem.LastIndexOf('['));
string indexer = elem.Substring(memberName.Length, elem.Length - memberName.Length);
int index = int.Parse(indexer.Substring(1, indexer.Length - 2));
IList valueList = ReflectionHelpers.GetMemberValue<IList>(obj, memberName);
obj = valueList[index];
}
else
{
obj = ReflectionHelpers.GetMemberValue<object>(obj, elem);
}
}

return (T)obj;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Editor.Scripts.Extensions;
using Editor.Scripts.PropertyDrawers.Utilities;
using SCHIZO.Registering;
using UnityEditor;
Expand All @@ -12,16 +13,35 @@ namespace Editor.Scripts.PropertyDrawers.Enums
public abstract class GameSpecificEnumDrawer<T> : PropertyDrawer where T : Enum
{
protected static readonly List<string> SubnauticaValues = typeof(T).GetEnumNames()
.Where(n => typeof(T).GetField(n).GetCustomAttribute<GameAttribute>().game.HasFlag(Game.Subnautica)).ToList();
.Where(n => typeof(T).GetField(n).GetCustomAttribute<GameAttribute>().TryGetGame(out Game game) && game.HasFlag(Game.Subnautica))
.ToList();

protected static readonly List<string> BelowZeroValues = typeof(T).GetEnumNames()
.Where(n => typeof(T).GetField(n).GetCustomAttribute<GameAttribute>().game.HasFlag(Game.BelowZero)).ToList();
.Where(n => typeof(T).GetField(n).GetCustomAttribute<GameAttribute>().TryGetGame(out Game game) && game.HasFlag(Game.BelowZero)).ToList();

protected virtual bool IsValueAcceptable(string entry, string propertyPath)
protected bool? hasGameAttr;
protected GameAttribute gameAttribute;
protected SerializedProperty parentWithGameAttribute;
protected virtual bool IsValueAcceptable(SerializedProperty property, string entry)
{
if (propertyPath.ToLower().Contains("sn")) return SubnauticaValues.Contains(entry);
if (propertyPath.ToLower().Contains("bz")) return BelowZeroValues.Contains(entry);
return SubnauticaValues.Contains(entry) || BelowZeroValues.Contains(entry);
Game game = default;
if (!hasGameAttr.HasValue)
{
hasGameAttr = property.TryGetAttributeInHierarchy(out gameAttribute, out parentWithGameAttribute);
}

gameAttribute?.TryGetGame(parentWithGameAttribute, out game);
// todo replace with attributes to be explicit?
if (property.propertyPath.EndsWith("SN")) game = Game.Subnautica;
if (property.propertyPath.EndsWith("BZ")) game = Game.BelowZero;

return IsValueAcceptable(entry, game);
}

protected bool IsValueAcceptable(string value, Game game)
{
return (!game.HasFlag(Game.Subnautica) || SubnauticaValues.Contains(value))
&& (!game.HasFlag(Game.BelowZero) || BelowZeroValues.Contains(value));
}

public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
Expand All @@ -45,11 +65,11 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten
protected void DrawDropdownButton(SerializedProperty property, int controlid, Rect position)
{
Color oldColor = GUI.backgroundColor;
if (!IsValueAcceptable(property.enumNames[property.enumValueIndex], property.propertyPath)) GUI.backgroundColor = Color.red;
if (!IsValueAcceptable(property, property.enumNames[property.enumValueIndex])) GUI.backgroundColor = Color.red;

if (DropdownButton(controlid, position, new GUIContent(property.enumDisplayNames[property.enumValueIndex])))
{
SearchablePopup.Show(position, property.enumDisplayNames, property.enumNames, property.enumValueIndex, property.propertyPath, IsValueAcceptable, i =>
SearchablePopup.Show(position, property, IsValueAcceptable, i =>
{
property.enumValueIndex = i;
property.serializedObject.ApplyModifiedProperties();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using SCHIZO.Interop.Subnautica.Enums;
using Editor.Scripts.Extensions;
using SCHIZO.Helpers;
using SCHIZO.Interop.Subnautica.Enums;
using SCHIZO.Registering;
using UnityEditor;
using UnityEngine;
Expand All @@ -8,32 +10,21 @@ namespace Editor.Scripts.PropertyDrawers.Enums
[CustomPropertyDrawer(typeof(TechType_All))]
public sealed class TechType_AllDrawer : GameSpecificEnumDrawer<TechType_All>
{
public static Game TargetGame = 0;
public static Game TargetGame;

protected override bool IsValueAcceptable(string entry, string propertyPath)
protected override bool IsValueAcceptable(SerializedProperty property, string entry)
{
switch (TargetGame)
{
case 0:
return base.IsValueAcceptable(entry, propertyPath);

case Game.Subnautica:
return SubnauticaValues.Contains(entry);

case Game.BelowZero:
return BelowZeroValues.Contains(entry);

case Game.Subnautica | Game.BelowZero:
return SubnauticaValues.Contains(entry) && BelowZeroValues.Contains(entry);

default:
return false;
}
return TargetGame != default
? IsValueAcceptable(entry, TargetGame)
: base.IsValueAcceptable(property, entry);
}

public static void DrawDropdownButtonStatic(SerializedProperty property, int controlid, Rect position)
{
new TechType_AllDrawer().DrawDropdownButton(property, controlid, position);
TechType_AllDrawer drawer = new();
ReflectionCache.GetField(typeof(PropertyDrawer), "m_FieldInfo")
.SetValue(drawer, property.GetFieldInfoAndStaticType(out _));
drawer.DrawDropdownButton(property, controlid, position);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ private static bool IsOk(SerializedProperty property)

Recipe recipe = (Recipe) property.objectReferenceValue;

if (property.propertyPath.ToLower().Contains("sn") && !recipe.game.HasFlag(Game.Subnautica)) return false;
if (property.propertyPath.ToLower().Contains("bz") && !recipe.game.HasFlag(Game.BelowZero)) return false;
if (property.propertyPath.EndsWith("SN") && !recipe.game.HasFlag(Game.Subnautica)) return false;
if (property.propertyPath.EndsWith("BZ") && !recipe.game.HasFlag(Game.BelowZero)) return false;
return true;
}

Expand Down
Loading