Merge TB update feature branch
This commit is contained in:
commit
a8a451f8e4
30 changed files with 3629 additions and 1849 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using RobocraftX.Blocks;
|
using RobocraftX.Blocks;
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using RobocraftX.GroupTags;
|
||||||
using RobocraftX.PilotSeat;
|
using RobocraftX.PilotSeat;
|
||||||
|
using Svelto.ECS;
|
||||||
using Techblox.EngineBlock;
|
using Techblox.EngineBlock;
|
||||||
using Techblox.ServoBlocksServer;
|
using Techblox.ServoBlocksServer;
|
||||||
using Techblox.WheelRigBlock;
|
using Techblox.WheelRigBlock;
|
||||||
|
@ -11,6 +14,11 @@ namespace CodeGenerator
|
||||||
internal class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
GenerateBlockClasses();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateBlockClasses()
|
||||||
{
|
{
|
||||||
var bcg = new BlockClassGenerator();
|
var bcg = new BlockClassGenerator();
|
||||||
bcg.Generate("Engine", null, new Dictionary<string, string>
|
bcg.Generate("Engine", null, new Dictionary<string, string>
|
||||||
|
|
1574
MakeEverythingPublicInGame/MakeEverythingPublicInGame.csproj
Normal file
1574
MakeEverythingPublicInGame/MakeEverythingPublicInGame.csproj
Normal file
File diff suppressed because it is too large
Load diff
25
MakeEverythingPublicInGame/Program.cs
Normal file
25
MakeEverythingPublicInGame/Program.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Mono.Cecil;
|
||||||
|
|
||||||
|
Console.WriteLine("Starting assembly editing...");
|
||||||
|
var fileRegex =
|
||||||
|
new Regex(".*(Techblox|Gamecraft|RobocraftX|FullGame|RobocraftECS|DataLoader|RCX|GameState|Svelto\\.ECS)[^/]*(\\.dll)");
|
||||||
|
foreach (var file in Directory.EnumerateFiles(@"../../../../../ref/Techblox_Data/Managed"))
|
||||||
|
{
|
||||||
|
if (!fileRegex.IsMatch(file)) continue;
|
||||||
|
Console.WriteLine(file);
|
||||||
|
ProcessAssembly(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessAssembly(string path)
|
||||||
|
{
|
||||||
|
using var mod = ModuleDefinition.ReadModule(path, new(ReadingMode.Immediate) { ReadWrite = true });
|
||||||
|
foreach (var typeDefinition in mod.Types)
|
||||||
|
{
|
||||||
|
typeDefinition.IsPublic = true;
|
||||||
|
foreach (var method in typeDefinition.Methods) method.IsPublic = true;
|
||||||
|
foreach (var field in typeDefinition.Fields) field.IsPublic = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Write();
|
||||||
|
}
|
|
@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TechbloxModdingAPI", "Techb
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeGenerator", "CodeGenerator\CodeGenerator.csproj", "{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeGenerator", "CodeGenerator\CodeGenerator.csproj", "{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MakeEverythingPublicInGame", "MakeEverythingPublicInGame\MakeEverythingPublicInGame.csproj", "{391A3107-E5C6-4A04-9467-6D868AA9A8B4}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -26,6 +28,12 @@ Global
|
||||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Release|Any CPU.Build.0 = Release|Any CPU
|
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Test|Any CPU.Build.0 = Debug|Any CPU
|
{0EBB6400-95A7-4A3D-B2ED-BF31E364CC10}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{391A3107-E5C6-4A04-9467-6D868AA9A8B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{391A3107-E5C6-4A04-9467-6D868AA9A8B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{391A3107-E5C6-4A04-9467-6D868AA9A8B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{391A3107-E5C6-4A04-9467-6D868AA9A8B4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{391A3107-E5C6-4A04-9467-6D868AA9A8B4}.Test|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{391A3107-E5C6-4A04-9467-6D868AA9A8B4}.Test|Any CPU.Build.0 = Debug|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -114,11 +114,6 @@ namespace TechbloxModdingAPI.App
|
||||||
popup.SecondButton();
|
popup.SecondButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CloseBetaPopup()
|
|
||||||
{
|
|
||||||
Game.menuEngine.CloseBetaPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
// this would have been so much simpler if this didn't involve a bunch of internal fields & classes
|
// this would have been so much simpler if this didn't involve a bunch of internal fields & classes
|
||||||
|
|
|
@ -140,18 +140,19 @@ namespace TechbloxModdingAPI.App
|
||||||
{
|
{
|
||||||
var allBlocks = entitiesDB.QueryEntities<BlockTagEntityStruct>();
|
var allBlocks = entitiesDB.QueryEntities<BlockTagEntityStruct>();
|
||||||
List<EGID> blockEGIDs = new List<EGID>();
|
List<EGID> blockEGIDs = new List<EGID>();
|
||||||
foreach (var ((buffer, count), _) in allBlocks)
|
foreach (var ((_, ids, count), group) in allBlocks)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
|
var id = new EGID(ids[i], group);
|
||||||
uint dbid;
|
uint dbid;
|
||||||
if (filter == BlockIDs.Invalid)
|
if (filter == BlockIDs.Invalid)
|
||||||
dbid = (uint)filter;
|
dbid = (uint)filter;
|
||||||
else
|
else
|
||||||
dbid = entitiesDB.QueryEntity<DBEntityStruct>(buffer[i].ID).DBID;
|
dbid = entitiesDB.QueryEntity<DBEntityStruct>(id).DBID;
|
||||||
var ownership = entitiesDB.QueryEntity<BlockOwnershipComponent>(buffer[i].ID).BlockOwnership;
|
var ownership = entitiesDB.QueryEntity<BlockOwnershipComponent>(id).BlockOwnership;
|
||||||
if ((ownership & BlockOwnership.User) != 0 && dbid == (ulong)filter)
|
if ((ownership & BlockOwnership.User) != 0 && dbid == (ulong)filter)
|
||||||
blockEGIDs.Add(buffer[i].ID);
|
blockEGIDs.Add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,16 +154,6 @@ namespace TechbloxModdingAPI.App
|
||||||
{
|
{
|
||||||
return ref entitiesDB.QueryEntity<T>(id);
|
return ref entitiesDB.QueryEntity<T>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CloseBetaPopup()
|
|
||||||
{
|
|
||||||
var (buffer, count) = entitiesDB.QueryEntities<TogglePanelButtonEntityViewStruct>(ExclusiveGroup.Search("BetaPopup"));
|
|
||||||
for (int index = 0; index < count; ++index)
|
|
||||||
{
|
|
||||||
entitiesDB.QueryEntity<GUIEntityViewStruct>(buffer[index].TogglePanelButtonComponent.targetPanel)
|
|
||||||
.guiRoot.enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal : GenericEntityDescriptor<MyGameDataEntityStruct> { }
|
internal class MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal : GenericEntityDescriptor<MyGameDataEntityStruct> { }
|
||||||
|
|
|
@ -302,6 +302,7 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
FloodLight,
|
FloodLight,
|
||||||
SoccerBall,
|
SoccerBall,
|
||||||
CircularWallLight,
|
CircularWallLight,
|
||||||
|
BlueSkyAtmos,
|
||||||
DirtToGrassTransitionTile = 393,
|
DirtToGrassTransitionTile = 393,
|
||||||
DirtToGrassTransitionInnerTile,
|
DirtToGrassTransitionInnerTile,
|
||||||
DirtToGrassTransitionOuterTile,
|
DirtToGrassTransitionOuterTile,
|
||||||
|
@ -362,10 +363,21 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
SmallGridHill,
|
SmallGridHill,
|
||||||
SmallGridHillInnerCorner,
|
SmallGridHillInnerCorner,
|
||||||
SmallGridHillOuterCorner,
|
SmallGridHillOuterCorner,
|
||||||
Vector7SmallJet = 460,
|
AimingAxleServo,
|
||||||
|
AimingHingeServo,
|
||||||
|
WeaponDisabler,
|
||||||
|
Vector7SmallJet,
|
||||||
Vector7MediumJet,
|
Vector7MediumJet,
|
||||||
Vector7LargeJet,
|
Vector7LargeJet,
|
||||||
Vector7XLJet,
|
Vector7XLJet,
|
||||||
Vector7XXLJet
|
Vector7XXLJet,
|
||||||
|
APCWheelRigNoSteering,
|
||||||
|
APCWheelRigWithSteering,
|
||||||
|
APCWheel,
|
||||||
|
APCSeat,
|
||||||
|
APCEngine,
|
||||||
|
DamageScoreBlock,
|
||||||
|
KillScoreBlock,
|
||||||
|
Autocannon = 480
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,13 +33,14 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
WoodRoughGrungy,
|
WoodRoughGrungy,
|
||||||
Boundary,
|
Boundary,
|
||||||
Emissive,
|
Emissive,
|
||||||
AircraftPaneling_Riveted_Painted,
|
AircraftPanelingRivetedPainted,
|
||||||
AircraftPaneling_Riveted_Metallic,
|
AircraftPanelingRivetedMetallic,
|
||||||
Steel_Bodywork_Pearlescent,
|
SteelBodyworkPearlescent,
|
||||||
Steel_Bodywork_RadWrap,
|
SteelBodyworkRadWrap,
|
||||||
Steel_Bodywork_Glitter,
|
SteelBodyworkGlitter,
|
||||||
BouncyRubber,
|
BouncyRubber,
|
||||||
BouncyRubber_TieDye,
|
BouncyRubberTieDye,
|
||||||
FuturisticPaneling_Riveted_Painted = 40
|
BrickPainted,
|
||||||
|
FuturisticPanelingRivetedPainted,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,6 @@ using System.Reflection;
|
||||||
|
|
||||||
using DataLoader;
|
using DataLoader;
|
||||||
using Svelto.Tasks;
|
using Svelto.Tasks;
|
||||||
using Svelto.Tasks.Enumerators;
|
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Tests;
|
using TechbloxModdingAPI.Tests;
|
||||||
|
@ -80,35 +79,50 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
yield break;
|
yield break;
|
||||||
for (var index = 0; index < blocks.Length; index++)
|
for (var index = 0; index < blocks.Length; index++)
|
||||||
{
|
{
|
||||||
if (index % 10 == 0) yield return new WaitForSecondsEnumerator(1f).Continue(); //The material or flipped status can only be changed 130 times per submission
|
|
||||||
var block = blocks[index];
|
var block = blocks[index];
|
||||||
if (!block.Exists) continue;
|
if (!block.Exists) continue;
|
||||||
foreach (var property in block.GetType().GetProperties())
|
foreach (var property in block.GetType().GetProperties())
|
||||||
{
|
{
|
||||||
//Includes specialised block properties
|
//Includes specialised block properties
|
||||||
if (property.SetMethod == null) continue;
|
if (property.SetMethod == null) continue;
|
||||||
var testValues = new (Type, object, Predicate<object>)[]
|
|
||||||
|
bool3 Float3Compare(float3 a, float3 b)
|
||||||
|
{ // From Unity reference code
|
||||||
|
return math.abs(b - a) < math.max(
|
||||||
|
0.000001f * math.max(math.abs(a), math.abs(b)),
|
||||||
|
float.Epsilon * 8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
bool4 Float4Compare(float4 a, float4 b)
|
||||||
|
{ // From Unity reference code
|
||||||
|
return math.abs(b - a) < math.max(
|
||||||
|
0.000001f * math.max(math.abs(a), math.abs(b)),
|
||||||
|
float.Epsilon * 8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var testValues = new (Type, object, Predicate<(object Value, object Default)>)[]
|
||||||
{
|
{
|
||||||
//(type, default value, predicate or null for equality)
|
//(type, default value, predicate or null for equality)
|
||||||
(typeof(long), 3, null),
|
(typeof(long), 3, null),
|
||||||
(typeof(int), 4, null),
|
(typeof(int), 4, null),
|
||||||
(typeof(double), 5.2f, obj => Math.Abs((double) obj - 5.2f) < float.Epsilon),
|
(typeof(double), 5.2f, t => Math.Abs((double) t.Value - (double) t.Default) < float.Epsilon),
|
||||||
(typeof(float), 5.2f, obj => Math.Abs((float) obj - 5.2f) < float.Epsilon),
|
(typeof(float), 5.2f, t => Math.Abs((float) t.Value - (float) t.Default) < float.Epsilon),
|
||||||
(typeof(bool), true, obj => (bool) obj),
|
(typeof(bool), true, t => (bool) t.Value),
|
||||||
(typeof(string), "Test", obj => (string) obj == "Test"), //String equality check
|
(typeof(string), "Test", t => (string) t.Value == "Test"), //String equality check
|
||||||
(typeof(float3), (float3) 2, obj => math.all((float3) obj - 2 < (float3) float.Epsilon)),
|
(typeof(float3), (float3) 20, t => math.all(Float3Compare((float3)t.Value, (float3)t.Default))),
|
||||||
(typeof(BlockColor), new BlockColor(BlockColors.Aqua, 2), null),
|
(typeof(BlockColor), new BlockColor(BlockColors.Aqua, 2), null),
|
||||||
(typeof(float4), (float4) 5, obj => math.all((float4) obj - 5 < (float4) float.Epsilon))
|
(typeof(float4), (float4) 5, t => math.all(Float4Compare((float4)t.Value, (float4)t.Default)))
|
||||||
};
|
};
|
||||||
var propType = property.PropertyType;
|
var propType = property.PropertyType;
|
||||||
if (!propType.IsValueType) continue;
|
if (!propType.IsValueType) continue;
|
||||||
(object valueToUse, Predicate<object> predicateToUse) = (null, null);
|
(object valueToUse, Predicate<(object Value, object Default)> predicateToUse) = (null, null);
|
||||||
foreach (var (type, value, predicate) in testValues)
|
foreach (var (type, value, predicate) in testValues)
|
||||||
{
|
{
|
||||||
if (type.IsAssignableFrom(propType))
|
if (type.IsAssignableFrom(propType))
|
||||||
{
|
{
|
||||||
valueToUse = value;
|
valueToUse = value;
|
||||||
predicateToUse = predicate ?? (obj => Equals(obj, value));
|
predicateToUse = predicate ?? (t => Equals(t.Value, t.Default));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +131,7 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
var values = propType.GetEnumValues();
|
var values = propType.GetEnumValues();
|
||||||
valueToUse = values.GetValue(values.Length / 2);
|
valueToUse = values.GetValue(values.Length / 2);
|
||||||
predicateToUse = val => Equals(val, valueToUse);
|
predicateToUse = t => Equals(t.Value, t.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valueToUse == null)
|
if (valueToUse == null)
|
||||||
|
@ -145,7 +159,7 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var attr = property.GetCustomAttribute<TestValueAttribute>();
|
var attr = property.GetCustomAttribute<TestValueAttribute>();
|
||||||
if (!predicateToUse(got) && (attr == null || !Equals(attr.PossibleValue, got)))
|
if (!predicateToUse((got, valueToUse)) && (attr == null || !Equals(attr.PossibleValue, got)))
|
||||||
{
|
{
|
||||||
Assert.Fail($"Property {block.GetType().Name}.{property.Name} value {got} does not equal {valueToUse} for block {block}.");
|
Assert.Fail($"Property {block.GetType().Name}.{property.Name} value {got} does not equal {valueToUse} for block {block}.");
|
||||||
yield break;
|
yield break;
|
||||||
|
|
|
@ -23,18 +23,18 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/*/// <summary> - TODO: Internal struct access
|
||||||
/// Gets or sets the Engine's On property. May not be saved.
|
/// Gets or sets the Engine's On property. May not be saved.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool On
|
public bool On
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).engineOn = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentGear;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentGear = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,11 +60,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).gearChangeCountdown;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).gearChangeCountdown = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,11 +75,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmAV;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmAV = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,11 +90,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmLV;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentRpmLV = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,11 +105,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmAV;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmAV = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,11 +120,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmLV;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).targetRpmLV = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,11 +135,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentTorque;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).currentTorque = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,11 +150,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityAV;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityAV = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,11 +165,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityLV;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelVelocityLV = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,11 +180,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelCount;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).totalWheelCount = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,11 +195,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearUpInput;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearUpInput = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,11 +210,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearDownInput;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).lastGearDownInput = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,11 +225,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).manualToAutoGearCoolOffCounter;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).manualToAutoGearCoolOffCounter = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,11 +240,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load")));
|
return BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).load;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load", value);
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockComponent>(this).load = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,6 +377,6 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockReadonlyComponent>(this).manualToAutoGearCoolOffTime = value;
|
BlockEngine.GetBlockInfo<Techblox.EngineBlock.EngineBlockReadonlyComponent>(this).manualToAutoGearCoolOffTime = value;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ using Unity.Mathematics;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
|
using PrefabsID = RobocraftX.Common.PrefabsID;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Blocks.Engines
|
namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
{
|
{
|
||||||
|
@ -70,7 +72,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
public float4 ConvertBlockColor(byte index) => index == byte.MaxValue
|
public float4 ConvertBlockColor(byte index) => index == byte.MaxValue
|
||||||
? new float4(-1f, -1f, -1f, -1f)
|
? new float4(-1f, -1f, -1f, -1f)
|
||||||
: entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
|
: entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
|
||||||
CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
|
ColourPaletteExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
|
||||||
|
|
||||||
public OptionalRef<T> GetBlockInfoOptional<T>(Block block) where T : unmanaged, IEntityComponent
|
public OptionalRef<T> GetBlockInfoOptional<T>(Block block) where T : unmanaged, IEntityComponent
|
||||||
{
|
{
|
||||||
|
@ -160,7 +162,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
|
|
||||||
public void UpdateBlockColor(EGID id)
|
public void UpdateBlockColor(EGID id)
|
||||||
{
|
{
|
||||||
entitiesDB.PublishEntityChange<ColourParameterEntityStruct>(id);
|
entitiesDB.PublishEntityChangeDelayed<ColourParameterEntityStruct>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool BlockExists(EGID blockID)
|
public bool BlockExists(EGID blockID)
|
||||||
|
@ -171,14 +173,13 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
public SimBody[] GetSimBodiesFromID(byte id)
|
public SimBody[] GetSimBodiesFromID(byte id)
|
||||||
{
|
{
|
||||||
var ret = new FasterList<SimBody>(4);
|
var ret = new FasterList<SimBody>(4);
|
||||||
var (oids, tags, count) = entitiesDB.QueryEntities<ObjectIdEntityStruct, BlockTagEntityStruct>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP);
|
var oids = entitiesDB.QueryEntitiesOptional<ObjectIdEntityStruct>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP);
|
||||||
EGIDMapper<GridConnectionsEntityStruct>? connections = null;
|
EGIDMapper<GridConnectionsEntityStruct>? connections = null;
|
||||||
for (int i = 0; i < count; i++)
|
foreach (var oid in oids)
|
||||||
{
|
{
|
||||||
if (oids[i].objectId != id) continue;
|
if (oid.Get().objectId != id) continue;
|
||||||
var tag = tags[i];
|
|
||||||
if (!connections.HasValue) //Would need reflection to get the group from the build group otherwise
|
if (!connections.HasValue) //Would need reflection to get the group from the build group otherwise
|
||||||
connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(tag.ID.groupID);
|
connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(oid.EGID.groupID);
|
||||||
//var rid = connections.Value.Entity(tag.ID.entityID).machineRigidBodyId;
|
//var rid = connections.Value.Entity(tag.ID.entityID).machineRigidBodyId;
|
||||||
/*foreach (var rb in ret) - TODO
|
/*foreach (var rb in ret) - TODO
|
||||||
{
|
{
|
||||||
|
@ -278,11 +279,11 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
return Array.Empty<ObjectID>();
|
return Array.Empty<ObjectID>();
|
||||||
|
|
||||||
var ret = new FasterList<ObjectID>(4);
|
var ret = new FasterList<ObjectID>(4);
|
||||||
var (oids, tags, count) = entitiesDB.QueryEntities<ObjectIDTweakableComponent, BlockTagEntityStruct>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP);
|
var oids = entitiesDB.QueryEntitiesOptional<ObjectIDTweakableComponent>(ObjectIDBlockExclusiveGroups.OBJECT_ID_BLOCK_GROUP);
|
||||||
for (var index = 0; index < count; index++)
|
foreach (var oid in oids)
|
||||||
{
|
{
|
||||||
if (oids[index].objectIDToTrigger == id)
|
if (oid.Get().objectIDToTrigger == id)
|
||||||
ret.Add(new ObjectID(tags[index].ID));
|
ret.Add(new ObjectID(oid.EGID));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.ToArray();
|
return ret.ToArray();
|
||||||
|
|
|
@ -21,6 +21,7 @@ using Svelto.ECS.Serialization;
|
||||||
using Techblox.Blocks.Connections;
|
using Techblox.Blocks.Connections;
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Unity.Transforms;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Blocks.Engines
|
namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ using Unity.Mathematics;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Blocks.Engines
|
namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
{
|
{
|
||||||
private static IEntityFunctions _entityFunctions;
|
private static IEntityFunctions _entityFunctions;
|
||||||
private static MachineGraphConnectionEntityFactory _connectionFactory;
|
private static MachineGraphConnectionEntityFactory _connectionFactory;
|
||||||
private NativeHashSet<ulong> removedConnections = new(2000, Allocator.Persistent);
|
private NativeHashSet<ulong> removedConnections;
|
||||||
|
|
||||||
public bool RemoveBlock(EGID target)
|
public bool RemoveBlock(EGID target)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +44,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
|
|
||||||
public void Ready()
|
public void Ready()
|
||||||
{
|
{
|
||||||
|
removedConnections = new(2000, Allocator.Persistent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntitiesDB entitiesDB { get; set; }
|
public EntitiesDB entitiesDB { get; set; }
|
||||||
|
@ -77,7 +78,8 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
|
|
||||||
public JobHandle DeterministicStep(in float deltaTime, JobHandle inputDeps)
|
public JobHandle DeterministicStep(in float deltaTime, JobHandle inputDeps)
|
||||||
{
|
{
|
||||||
removedConnections.Clear();
|
if (removedConnections.IsCreated)
|
||||||
|
removedConnections.Clear();
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using UnityEngine;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Blocks.Engines
|
namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Svelto.ECS;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Blocks.Engines
|
namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
{
|
{
|
||||||
|
@ -41,7 +42,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
|
|
||||||
// implementations for block wiring
|
// implementations for block wiring
|
||||||
|
|
||||||
public WireEntityStruct CreateNewWire(EGID startBlock, byte startPort, EGID endBlock, byte endPort)
|
public (WireEntityStruct Wire, EGID ID) CreateNewWire(EGID startBlock, byte startPort, EGID endBlock, byte endPort)
|
||||||
{
|
{
|
||||||
EGID wireEGID = new EGID(BuildModeWiresGroups.NewWireEntityId, BuildModeWiresGroups.WiresGroup.Group);
|
EGID wireEGID = new EGID(BuildModeWiresGroups.NewWireEntityId, BuildModeWiresGroups.WiresGroup.Group);
|
||||||
EntityInitializer wireInitializer = Factory.BuildEntity<WireEntityDescriptor>(wireEGID);
|
EntityInitializer wireInitializer = Factory.BuildEntity<WireEntityDescriptor>(wireEGID);
|
||||||
|
@ -50,10 +51,9 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
sourceBlockEGID = startBlock,
|
sourceBlockEGID = startBlock,
|
||||||
sourcePortUsage = startPort,
|
sourcePortUsage = startPort,
|
||||||
destinationBlockEGID = endBlock,
|
destinationBlockEGID = endBlock,
|
||||||
destinationPortUsage = endPort,
|
destinationPortUsage = endPort
|
||||||
ID = wireEGID
|
|
||||||
});
|
});
|
||||||
return wireInitializer.Get<WireEntityStruct>();
|
return (wireInitializer.Get<WireEntityStruct>(), wireEGID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref WireEntityStruct GetWire(EGID wire)
|
public ref WireEntityStruct GetWire(EGID wire)
|
||||||
|
@ -226,27 +226,27 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
uint entityID = (output ? ports.firstOutputID : ports.firstInputID) + i;
|
uint entityID = (output ? ports.firstOutputID : ports.firstInputID) + i;
|
||||||
if (!mapper.TryGetArrayAndEntityIndex(entityID, out var index, out var array) ||
|
if (!mapper.TryGetArrayAndEntityIndex(entityID, out var index, out var array) ||
|
||||||
array[index].usage != portUsage) continue;
|
array[index].usage != portUsage) continue;
|
||||||
return new OptionalRef<PortEntityStruct>(array, index);
|
return new OptionalRef<PortEntityStruct>(array, index, new EGID(entityID, group));
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref WireEntityStruct MatchPortToWire(PortEntityStruct port, EGID blockID, out bool exists)
|
public OptionalRef<WireEntityStruct> MatchPortToWire(PortEntityStruct port, EGID blockID, out EGID wireID)
|
||||||
{
|
{
|
||||||
var (wires, count) = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group);
|
var (wires, ids, count) = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group);
|
||||||
for (uint i = 0; i < count; i++)
|
for (uint i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID)
|
if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID)
|
||||||
|| (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID))
|
|| (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID))
|
||||||
{
|
{
|
||||||
exists = true;
|
wireID = new EGID(ids[i], BuildModeWiresGroups.WiresGroup.Group);
|
||||||
return ref wires[i];
|
return new OptionalRef<WireEntityStruct>(wires, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exists = false;
|
|
||||||
WireEntityStruct[] defRef = new WireEntityStruct[1];
|
wireID = default;
|
||||||
return ref defRef[0];
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EGID MatchBlocksToWire(EGID startBlock, EGID endBlock, byte startPort = byte.MaxValue, byte endPort = byte.MaxValue)
|
public EGID MatchBlocksToWire(EGID startBlock, EGID endBlock, byte startPort = byte.MaxValue, byte endPort = byte.MaxValue)
|
||||||
|
@ -275,19 +275,20 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
endPorts = new EGID[] {new EGID(ports.firstInputID + endPort, NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group) };
|
endPorts = new EGID[] {new EGID(ports.firstInputID + endPort, NamedExclusiveGroup<BuildModeWiresGroups.InputPortsGroup>.Group) };
|
||||||
}
|
}
|
||||||
|
|
||||||
var (wires, count) = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group);
|
|
||||||
for (int endIndex = 0; endIndex < endPorts.Length; endIndex++)
|
for (int endIndex = 0; endIndex < endPorts.Length; endIndex++)
|
||||||
{
|
{
|
||||||
PortEntityStruct endPES = entitiesDB.QueryEntity<PortEntityStruct>(endPorts[endIndex]);
|
PortEntityStruct endPES = entitiesDB.QueryEntity<PortEntityStruct>(endPorts[endIndex]);
|
||||||
for (int startIndex = 0; startIndex < startPorts.Length; startIndex++)
|
for (int startIndex = 0; startIndex < startPorts.Length; startIndex++)
|
||||||
{
|
{
|
||||||
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]);
|
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]);
|
||||||
for (int w = 0; w < count; w++)
|
foreach (var wireOpt in entitiesDB.QueryEntitiesOptional<WireEntityStruct>(
|
||||||
|
NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group))
|
||||||
{
|
{
|
||||||
if ((wires[w].destinationPortUsage == endPES.usage && wires[w].destinationBlockEGID == endBlock)
|
var wire = wireOpt.Get();
|
||||||
&& (wires[w].sourcePortUsage == startPES.usage && wires[w].sourceBlockEGID == startBlock))
|
if ((wire.destinationPortUsage == endPES.usage && wire.destinationBlockEGID == endBlock)
|
||||||
|
&& (wire.sourcePortUsage == startPES.usage && wire.sourceBlockEGID == startBlock))
|
||||||
{
|
{
|
||||||
return wires[w].ID;
|
return wireOpt.EGID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,12 +309,12 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
public EGID[] GetElectricBlocks()
|
public EGID[] GetElectricBlocks()
|
||||||
{
|
{
|
||||||
var res = new FasterList<EGID>();
|
var res = new FasterList<EGID>();
|
||||||
foreach (var ((coll, count), _) in entitiesDB.QueryEntities<BlockPortsStruct>())
|
foreach (var ((coll, ids, count), _) in entitiesDB.QueryEntities<BlockPortsStruct>())
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
ref BlockPortsStruct s = ref coll[i];
|
ref BlockPortsStruct s = ref coll[i];
|
||||||
//res.Add(s.ID); - TODO
|
//res.Add(s.ID); - TODO: Would need to search for the groups for each block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,42 +323,18 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
||||||
|
|
||||||
public EGID[] WiredToInput(EGID block, byte port)
|
public EGID[] WiredToInput(EGID block, byte port)
|
||||||
{
|
{
|
||||||
WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group,
|
return entitiesDB
|
||||||
(WireEntityStruct wes) => wes.destinationPortUsage == port && wes.destinationBlockEGID == block);
|
.QueryEntitiesOptional<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group)
|
||||||
EGID[] result = new EGID[wireEntityStructs.Length];
|
.ToArray(wire => wire.ID,
|
||||||
for (uint i = 0; i < wireEntityStructs.Length; i++)
|
wire => wire.Component.destinationPortUsage == port && wire.Component.destinationBlockEGID == block);
|
||||||
{
|
|
||||||
result[i] = wireEntityStructs[i].ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EGID[] WiredToOutput(EGID block, byte port)
|
public EGID[] WiredToOutput(EGID block, byte port)
|
||||||
{
|
{
|
||||||
WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group,
|
return entitiesDB
|
||||||
(WireEntityStruct wes) => wes.sourcePortUsage == port && wes.sourceBlockEGID == block);
|
.QueryEntitiesOptional<WireEntityStruct>(NamedExclusiveGroup<BuildModeWiresGroups.WiresGroup>.Group)
|
||||||
EGID[] result = new EGID[wireEntityStructs.Length];
|
.ToArray(wire => wire.ID,
|
||||||
for (uint i = 0; i < wireEntityStructs.Length; i++)
|
wire => wire.Component.sourcePortUsage == port && wire.Component.sourceBlockEGID == block);
|
||||||
{
|
|
||||||
result[i] = wireEntityStructs[i].ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private T[] Search<T>(ExclusiveGroup group, Func<T, bool> isMatch) where T : unmanaged, IEntityComponent
|
|
||||||
{
|
|
||||||
FasterList<T> results = new FasterList<T>();
|
|
||||||
var (components, count) = entitiesDB.QueryEntities<T>(group);
|
|
||||||
for (uint i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (isMatch(components[i]))
|
|
||||||
{
|
|
||||||
results.Add(components[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityCollection<ChannelDataStruct> GetSignalStruct(uint signalID, out uint index, bool input = true)
|
private EntityCollection<ChannelDataStruct> GetSignalStruct(uint signalID, out uint index, bool input = true)
|
||||||
|
|
|
@ -46,9 +46,9 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
/// <returns>The connected wire.</returns>
|
/// <returns>The connected wire.</returns>
|
||||||
/// <param name="portId">Port identifier.</param>
|
/// <param name="portId">Port identifier.</param>
|
||||||
/// <param name="connected">Whether the port has a wire connected to it.</param>
|
/// <param name="connected">Whether the port has a wire connected to it.</param>
|
||||||
protected ref WireEntityStruct GetConnectedWire(PortEntityStruct port, out bool connected)
|
protected OptionalRef<WireEntityStruct> GetConnectedWire(PortEntityStruct port, out EGID egid)
|
||||||
{
|
{
|
||||||
return ref SignalEngine.MatchPortToWire(port, Id, out connected);
|
return SignalEngine.MatchPortToWire(port, Id, out egid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Svelto.ECS;
|
||||||
using Svelto.ECS.Experimental;
|
using Svelto.ECS.Experimental;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Blocks.Engines;
|
using TechbloxModdingAPI.Blocks.Engines;
|
||||||
|
using TechbloxModdingAPI.Utility;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Blocks
|
namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
|
@ -30,8 +31,8 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
|
|
||||||
public static Wire Connect(SignalingBlock start, byte startPort, SignalingBlock end, byte endPort)
|
public static Wire Connect(SignalingBlock start, byte startPort, SignalingBlock end, byte endPort)
|
||||||
{
|
{
|
||||||
WireEntityStruct wire = signalEngine.CreateNewWire(start.Id, startPort, end.Id, endPort);
|
var (wire, id) = signalEngine.CreateNewWire(start.Id, startPort, end.Id, endPort);
|
||||||
return new Wire(wire, start, end);
|
return new Wire(wire, start, end, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -45,9 +46,9 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
var port = signalEngine.MatchBlockIOToPort(end, endPort, false);
|
var port = signalEngine.MatchBlockIOToPort(end, endPort, false);
|
||||||
if (!port) return null;
|
if (!port) return null;
|
||||||
WireEntityStruct wire = signalEngine.MatchPortToWire(port, end.Id, out var exists);
|
var wire = signalEngine.MatchPortToWire(port, end.Id, out var egid);
|
||||||
return exists
|
return wire
|
||||||
? new Wire(wire.sourceBlockEGID, end.Id, wire.sourcePortUsage, endPort, wire.ID, false)
|
? new Wire(wire.Get().sourceBlockEGID, end.Id, wire.Get().sourcePortUsage, endPort, egid, false)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +63,9 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
var port = signalEngine.MatchBlockIOToPort(start, startPort, true);
|
var port = signalEngine.MatchBlockIOToPort(start, startPort, true);
|
||||||
if (!port) return null;
|
if (!port) return null;
|
||||||
WireEntityStruct wire = signalEngine.MatchPortToWire(port, start.Id, out var exists);
|
var wire = signalEngine.MatchPortToWire(port, start.Id, out var egid);
|
||||||
return exists
|
return wire
|
||||||
? new Wire(start.Id, wire.destinationBlockEGID, startPort, wire.destinationPortUsage, wire.ID, false)
|
? new Wire(start.Id, wire.Get().destinationBlockEGID, startPort, wire.Get().destinationPortUsage, egid, false)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,9 +133,9 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
this.endBlockEGID = endBlock;
|
this.endBlockEGID = endBlock;
|
||||||
this.inputToOutput = inputToOutput;
|
this.inputToOutput = inputToOutput;
|
||||||
this.wireEGID = wire;
|
this.wireEGID = wire;
|
||||||
endPortEGID = signalEngine.MatchBlockIOToPort(startBlock, startPort, inputToOutput).Nullable()?.ID ?? default;
|
endPortEGID = signalEngine.MatchBlockIOToPort(startBlock, startPort, inputToOutput).EGID;
|
||||||
if (endPortEGID == default) throw new WireInvalidException("Wire end port not found");
|
if (endPortEGID == default) throw new WireInvalidException("Wire end port not found");
|
||||||
startPortEGID = signalEngine.MatchBlockIOToPort(endBlock, endPort, !inputToOutput).Nullable()?.ID ?? default;
|
startPortEGID = signalEngine.MatchBlockIOToPort(endBlock, endPort, !inputToOutput).EGID;
|
||||||
if (startPortEGID == default) throw new WireInvalidException("Wire start port not found");
|
if (startPortEGID == default) throw new WireInvalidException("Wire start port not found");
|
||||||
this.startPort = startPort;
|
this.startPort = startPort;
|
||||||
this.endPort = endPort;
|
this.endPort = endPort;
|
||||||
|
@ -151,8 +152,8 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
wireEgid, false);
|
wireEgid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Wire(WireEntityStruct wire, SignalingBlock src, SignalingBlock dest)
|
private Wire(WireEntityStruct wire, SignalingBlock src, SignalingBlock dest, EGID wireEgid)
|
||||||
: this(src, dest, wire.sourcePortUsage, wire.destinationPortUsage, wire.ID, false)
|
: this(src, dest, wire.sourcePortUsage, wire.destinationPortUsage, wireEgid, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using Gamecraft.Wires;
|
using Gamecraft.Wires;
|
||||||
using RobocraftX.Blocks.Ghost;
|
|
||||||
using RobocraftX.Character;
|
using RobocraftX.Character;
|
||||||
using RobocraftX.Character.Movement;
|
using RobocraftX.Character.Movement;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
@ -11,6 +10,7 @@ using RobocraftX.Physics;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Techblox.BuildingDrone;
|
using Techblox.BuildingDrone;
|
||||||
using Techblox.Camera;
|
using Techblox.Camera;
|
||||||
|
using Techblox.Character;
|
||||||
using TechbloxModdingAPI.Blocks;
|
using TechbloxModdingAPI.Blocks;
|
||||||
using TechbloxModdingAPI.Players;
|
using TechbloxModdingAPI.Players;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
@ -214,15 +214,16 @@ namespace TechbloxModdingAPI
|
||||||
/// The player's initial health when entering Simulation (aka Time Running) mode.
|
/// The player's initial health when entering Simulation (aka Time Running) mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The initial health.</value>
|
/// <value>The initial health.</value>
|
||||||
|
[Obsolete("We can no longer get initial health, returns max health.")]
|
||||||
public float InitialHealth
|
public float InitialHealth
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id);
|
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityComponent>(Id);
|
||||||
return opt ? opt.Get().initialHealth : -1f;
|
return opt ? opt.Get().maxHealth : -1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
set => playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get().initialHealth = value;
|
set => playerEngine.GetCharacterStruct<CharacterHealthEntityComponent>(Id).Get().maxHealth = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -233,30 +234,25 @@ namespace TechbloxModdingAPI
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id);
|
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityComponent>(Id);
|
||||||
return opt ? opt.Get().currentHealth : -1f;
|
return opt ? opt.Get().currentHealth : -1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
set => playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get().currentHealth = value;
|
set => playerEngine.GetCharacterStruct<CharacterHealthEntityComponent>(Id).Get().currentHealth = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether this <see cref="T:TechbloxModdingAPI.Player"/> is damageable.
|
/// Whether this <see cref="T:TechbloxModdingAPI.Player"/> is damageable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value>
|
||||||
|
[Obsolete("Players are probably always damageable")]
|
||||||
public bool Damageable
|
public bool Damageable
|
||||||
{
|
{
|
||||||
get
|
get => true;
|
||||||
{
|
|
||||||
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id);
|
|
||||||
return opt.Get().canTakeDamageStat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// ReSharper disable once ValueParameterNotUsed
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
ref var healthStruct = ref playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get();
|
|
||||||
healthStruct.canTakeDamage = value;
|
|
||||||
healthStruct.canTakeDamageStat = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,30 +260,26 @@ namespace TechbloxModdingAPI
|
||||||
/// The player's lives when initially entering Simulation (aka Time Running) mode.
|
/// The player's lives when initially entering Simulation (aka Time Running) mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The initial lives.</value>
|
/// <value>The initial lives.</value>
|
||||||
|
[Obsolete("The player has infinite lives")]
|
||||||
public uint InitialLives
|
public uint InitialLives
|
||||||
{
|
{
|
||||||
get
|
get => uint.MaxValue;
|
||||||
{
|
|
||||||
var opt = playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id);
|
|
||||||
return opt ? opt.Get().initialLives : uint.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
set => playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id).Get().initialLives = value;
|
// ReSharper disable once ValueParameterNotUsed
|
||||||
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The player's current lives in Simulation (aka Time Running) mode.
|
/// The player's current lives in Simulation (aka Time Running) mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The current lives.</value>
|
/// <value>The current lives.</value>
|
||||||
|
[Obsolete("The player has infinite lives")]
|
||||||
public uint CurrentLives
|
public uint CurrentLives
|
||||||
{
|
{
|
||||||
get
|
get => uint.MaxValue;
|
||||||
{
|
|
||||||
var opt = playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id);
|
|
||||||
return opt ? opt.Get().currentLives : uint.MaxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
set => playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id).Get().currentLives = value;
|
// ReSharper disable once ValueParameterNotUsed
|
||||||
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/*/// <summary>
|
/*/// <summary>
|
||||||
|
@ -373,6 +365,9 @@ namespace TechbloxModdingAPI
|
||||||
var group when group == CharacterExclusiveGroups.MachineSpawningGroup => PlayerState.HoldingMachine,
|
var group when group == CharacterExclusiveGroups.MachineSpawningGroup => PlayerState.HoldingMachine,
|
||||||
var group when group == CharacterExclusiveGroups.OnFootGroup => PlayerState.OnFoot,
|
var group when group == CharacterExclusiveGroups.OnFootGroup => PlayerState.OnFoot,
|
||||||
var group when group == CharacterExclusiveGroups.InPilotSeatGroup => PlayerState.InSeat,
|
var group when group == CharacterExclusiveGroups.InPilotSeatGroup => PlayerState.InSeat,
|
||||||
|
var group when group == CharacterExclusiveGroups.DyingOnFootGroup => PlayerState.OnFoot,
|
||||||
|
var group when group == CharacterExclusiveGroups.DyingInPilotSeatGroup => PlayerState.InSeat,
|
||||||
|
var group when group == CharacterExclusiveGroups.DeadGroup => PlayerState.OnFoot,
|
||||||
_ => throw new ArgumentOutOfRangeException("", "Unknown player state")
|
_ => throw new ArgumentOutOfRangeException("", "Unknown player state")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ using Techblox.Character;
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
using TechbloxModdingAPI.Input;
|
using TechbloxModdingAPI.Input;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
using TechbloxModdingAPI.Utility.ECS;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Players
|
namespace TechbloxModdingAPI.Players
|
||||||
{
|
{
|
||||||
|
@ -115,7 +116,7 @@ namespace TechbloxModdingAPI.Players
|
||||||
public bool IsDead(uint playerId)
|
public bool IsDead(uint playerId)
|
||||||
{
|
{
|
||||||
if (entitiesDB == null) return true;
|
if (entitiesDB == null) return true;
|
||||||
return entitiesDB.Exists<RigidBodyEntityStruct>(playerId, CharacterExclusiveGroups.DeadCharacters);
|
return entitiesDB.Exists<RigidBodyEntityStruct>(playerId, CharacterExclusiveGroups.DeadGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reusable methods
|
// reusable methods
|
||||||
|
@ -164,8 +165,9 @@ namespace TechbloxModdingAPI.Players
|
||||||
var opt = GetCameraStruct<PhysicCameraRayCastEntityStruct>(playerId);
|
var opt = GetCameraStruct<PhysicCameraRayCastEntityStruct>(playerId);
|
||||||
if (!opt) return default;
|
if (!opt) return default;
|
||||||
PhysicCameraRayCastEntityStruct rayCast = opt;
|
PhysicCameraRayCastEntityStruct rayCast = opt;
|
||||||
|
EGID physicCameraEgid = new EGID(playerId, CameraExclusiveGroups.PhysicCameraGroup);
|
||||||
float distance = maxDistance < 0
|
float distance = maxDistance < 0
|
||||||
? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast,
|
? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast, physicCameraEgid,
|
||||||
GhostBlockUtils.GhostCastMethod.GhostCastProportionalToBlockSize)
|
GhostBlockUtils.GhostCastMethod.GhostCastProportionalToBlockSize)
|
||||||
: maxDistance;
|
: maxDistance;
|
||||||
if (rayCast.hit && rayCast.distance <= distance)
|
if (rayCast.hit && rayCast.distance <= distance)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -369,8 +369,6 @@ namespace TechbloxModdingAPI.Tests
|
||||||
Logging.CommandLog("Test enabled");
|
Logging.CommandLog("Test enabled");
|
||||||
}).Build();
|
}).Build();
|
||||||
|
|
||||||
Client.EnterMenu += (sender, args) => Scheduler.Schedule(new Once(() => Client.Instance.CloseBetaPopup()));
|
|
||||||
|
|
||||||
Game.Enter += (sender, args) =>
|
Game.Enter += (sender, args) =>
|
||||||
Console.WriteLine(
|
Console.WriteLine(
|
||||||
$"Current game selection data: {FullGameFields._gameSelectionData.gameMode} - {FullGameFields._gameSelectionData.saveType}");
|
$"Current game selection data: {FullGameFields._gameSelectionData.gameMode} - {FullGameFields._gameSelectionData.saveType}");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Svelto.ECS.Hybrid;
|
using Svelto.ECS.Hybrid;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Utility
|
namespace TechbloxModdingAPI.Utility.ECS
|
||||||
{
|
{
|
||||||
public static class ManagedApiExtensions
|
public static class ManagedApiExtensions
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,8 @@ namespace TechbloxModdingAPI.Utility
|
||||||
/// <param name="group">The group of the entity if the object can have multiple</param>
|
/// <param name="group">The group of the entity if the object can have multiple</param>
|
||||||
/// <typeparam name="T">The component to query</typeparam>
|
/// <typeparam name="T">The component to query</typeparam>
|
||||||
/// <returns>A reference to the component or a dummy value</returns>
|
/// <returns>A reference to the component or a dummy value</returns>
|
||||||
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default)
|
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj,
|
||||||
|
ExclusiveGroupStruct group = default)
|
||||||
where T : struct, IEntityViewComponent
|
where T : struct, IEntityViewComponent
|
||||||
{
|
{
|
||||||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
||||||
|
@ -45,7 +46,8 @@ namespace TechbloxModdingAPI.Utility
|
||||||
/// <param name="group">The group of the entity if the object can have multiple</param>
|
/// <param name="group">The group of the entity if the object can have multiple</param>
|
||||||
/// <typeparam name="T">The component to query</typeparam>
|
/// <typeparam name="T">The component to query</typeparam>
|
||||||
/// <returns>A reference to the component or a dummy value</returns>
|
/// <returns>A reference to the component or a dummy value</returns>
|
||||||
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default)
|
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj,
|
||||||
|
ExclusiveGroupStruct group = default)
|
||||||
where T : struct, IEntityViewComponent
|
where T : struct, IEntityViewComponent
|
||||||
{
|
{
|
||||||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
||||||
|
@ -54,5 +56,20 @@ namespace TechbloxModdingAPI.Utility
|
||||||
if (obj.InitData.Valid) return ref obj.InitData.Initializer(id).GetOrAdd<T>();
|
if (obj.InitData.Valid) return ref obj.InitData.Initializer(id).GetOrAdd<T>();
|
||||||
return ref opt.Get(); //Default value
|
return ref opt.Get(); //Default value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query entities as OptionalRefs. The elements always exist, it's just a nice way to encapsulate the data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entitiesDB"></param>
|
||||||
|
/// <param name="group"></param>
|
||||||
|
/// <param name="select"></param>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <typeparam name="TR"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static RefCollection<T> QueryEntitiesOptional<T>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group) where T : struct, IEntityViewComponent
|
||||||
|
{
|
||||||
|
var (buffer, ids, count) = entitiesDB.QueryEntities<T>(group);
|
||||||
|
return new RefCollection<T>(count, buffer, ids, group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Svelto.DataStructures;
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
namespace TechbloxModdingAPI.Utility.ECS
|
||||||
|
{
|
||||||
|
public static partial class NativeApiExtensions
|
||||||
|
{
|
||||||
|
[SuppressMessage("ReSharper", "StaticMemberInGenericType")]
|
||||||
|
private static class EntitiesDBHelper<T> where T : unmanaged, IEntityComponent
|
||||||
|
{ // Each type gets a new set of fields here (that's what the ReSharper warning is about too)
|
||||||
|
public static readonly Lazy<MethodInfo> EntityStream =
|
||||||
|
new(() => AccessTools.PropertyGetter(typeof(EntitiesDB), "_entityStream"));
|
||||||
|
|
||||||
|
public static readonly Lazy<FieldInfo> Streams = new(() =>
|
||||||
|
AccessTools.Field(EntityStream.Value.ReturnType, "_streams"));
|
||||||
|
|
||||||
|
public static readonly Lazy<FieldInfo> Consumers = new(() =>
|
||||||
|
AccessTools.Field(typeof(EntityStream<T>), "_consumers"));
|
||||||
|
|
||||||
|
public static readonly Lazy<MethodInfo> TryGetValue =
|
||||||
|
new(AccessTools.Method(Streams.Value.FieldType, "TryGetValue"));
|
||||||
|
|
||||||
|
public static readonly Lazy<FieldInfo> RingBuffer =
|
||||||
|
new(() => AccessTools.Field(typeof(Consumer<T>), "_ringBuffer"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EntityStream<T> GetEntityStream<T>(this EntitiesDB entitiesDB) where T : unmanaged, IEntityComponent
|
||||||
|
{
|
||||||
|
// EntitiesStreams (internal)
|
||||||
|
var entitiesStreams = EntitiesDBHelper<T>.EntityStream.Value.Invoke(entitiesDB, Array.Empty<object>());
|
||||||
|
// FasterDictionary<RefWrapperType, ITypeSafeStream> (interface is internal)
|
||||||
|
var streams = EntitiesDBHelper<T>.Streams.Value.GetValue(entitiesStreams);
|
||||||
|
|
||||||
|
var parameters = new object[] { TypeRefWrapper<T>.wrapper, null };
|
||||||
|
var success = EntitiesDBHelper<T>.TryGetValue.Value.Invoke(streams, parameters);
|
||||||
|
if (!(bool)success)
|
||||||
|
return null; // There is no entity stream for this type
|
||||||
|
return (EntityStream<T>)parameters[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ThreadSafeFasterList<Consumer<T>> GetConsumers<T>(this EntityStream<T> stream) where T : unmanaged, IEntityComponent
|
||||||
|
{
|
||||||
|
return (ThreadSafeFasterList<Consumer<T>>)EntitiesDBHelper<T>.Consumers.Value.GetValue(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RingBuffer<(T, EGID)> GetRingBuffer<T>(this Consumer<T> consumer) where T : unmanaged, IEntityComponent
|
||||||
|
{
|
||||||
|
return (RingBuffer<(T, EGID)>)EntitiesDBHelper<T>.RingBuffer.Value.GetValue(consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Svelto.DataStructures;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Svelto.Tasks;
|
using Svelto.Tasks;
|
||||||
using Svelto.Tasks.Lean;
|
using Svelto.Tasks.Lean;
|
||||||
using TechbloxModdingAPI.Tasks;
|
using TechbloxModdingAPI.Tasks;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Utility
|
namespace TechbloxModdingAPI.Utility.ECS
|
||||||
{
|
{
|
||||||
public static class NativeApiExtensions
|
public static partial class NativeApiExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attempts to query an entity and returns an optional that contains the result if succeeded.
|
/// Attempts to query an entity and returns an optional that contains the result if succeeded.
|
||||||
|
@ -33,7 +34,8 @@ namespace TechbloxModdingAPI.Utility
|
||||||
/// <param name="group">The group of the entity if the object can have multiple</param>
|
/// <param name="group">The group of the entity if the object can have multiple</param>
|
||||||
/// <typeparam name="T">The component to query</typeparam>
|
/// <typeparam name="T">The component to query</typeparam>
|
||||||
/// <returns>A reference to the component or a dummy value</returns>
|
/// <returns>A reference to the component or a dummy value</returns>
|
||||||
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default)
|
public static OptionalRef<T> QueryEntityOptional<T>(this EntitiesDB entitiesDB, EcsObjectBase obj,
|
||||||
|
ExclusiveGroupStruct group = default)
|
||||||
where T : unmanaged, IEntityComponent
|
where T : unmanaged, IEntityComponent
|
||||||
{
|
{
|
||||||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
||||||
|
@ -49,7 +51,8 @@ namespace TechbloxModdingAPI.Utility
|
||||||
/// <param name="group">The group of the entity if the object can have multiple</param>
|
/// <param name="group">The group of the entity if the object can have multiple</param>
|
||||||
/// <typeparam name="T">The component to query</typeparam>
|
/// <typeparam name="T">The component to query</typeparam>
|
||||||
/// <returns>A reference to the component or a dummy value</returns>
|
/// <returns>A reference to the component or a dummy value</returns>
|
||||||
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj, ExclusiveGroupStruct group = default)
|
public static ref T QueryEntityOrDefault<T>(this EntitiesDB entitiesDB, EcsObjectBase obj,
|
||||||
|
ExclusiveGroupStruct group = default)
|
||||||
where T : unmanaged, IEntityComponent
|
where T : unmanaged, IEntityComponent
|
||||||
{
|
{
|
||||||
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
EGID id = group == ExclusiveGroupStruct.Invalid ? obj.Id : new EGID(obj.Id.entityID, group);
|
||||||
|
@ -64,39 +67,63 @@ namespace TechbloxModdingAPI.Utility
|
||||||
return ref opt.Get(); //Default value
|
return ref opt.Get(); //Default value
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<Type, (int PublishedCount, HashSet<EGID> Changes)> ChangesToPublish = new();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Publishes an entity change, ignoring duplicate publishes and delaying changes as necessary.
|
/// Publishes an entity change, ignoring duplicate publishes and delaying changes as necessary.
|
||||||
/// It will only publish in the next frame.
|
/// It will only publish in the next frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entitiesDB">The entities DB to publish to</param>
|
/// <param name="entitiesDB">The entities DB to publish to</param>
|
||||||
/// <param name="id">The ECS object that got changed</param>
|
/// <param name="id">The ECS object that got changed</param>
|
||||||
/// <param name="limit">Limits how many changes to publish - should be no more than the consumers' capacity that process this component</param>
|
|
||||||
/// <typeparam name="T">The component that changed</typeparam>
|
/// <typeparam name="T">The component that changed</typeparam>
|
||||||
public static void PublishEntityChangeDelayed<T>(this EntitiesDB entitiesDB, EGID id, int limit = 80)
|
public static void PublishEntityChangeDelayed<T>(this EntitiesDB entitiesDB, EGID id)
|
||||||
where T : unmanaged, IEntityComponent
|
where T : unmanaged, IEntityComponent
|
||||||
{ //TODO: Doesn't seem to help
|
{
|
||||||
if(!ChangesToPublish.ContainsKey(typeof(T)))
|
PublishChanges<T>(entitiesDB, id).RunOn(Scheduler.leanRunner);
|
||||||
ChangesToPublish.Add(typeof(T), (0, new HashSet<EGID>()));
|
|
||||||
var changes = ChangesToPublish[typeof(T)].Changes;
|
|
||||||
if (changes.Contains(id)) return;
|
|
||||||
changes.Add(id);
|
|
||||||
PublishChanges<T>(entitiesDB, id, limit).RunOn(Scheduler.leanRunner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerator<TaskContract> PublishChanges<T>(EntitiesDB entitiesDB, EGID id, int limit)
|
private static IEnumerator<TaskContract> PublishChanges<T>(EntitiesDB entitiesDB, EGID id)
|
||||||
where T : unmanaged, IEntityComponent
|
where T : unmanaged, IEntityComponent
|
||||||
{
|
{
|
||||||
yield return Yield.It;
|
yield return Yield.It;
|
||||||
while (ChangesToPublish[typeof(T)].PublishedCount >= limit)
|
var entityStream = entitiesDB.GetEntityStream<T>();
|
||||||
yield return Yield.It;
|
if (entityStream is null)
|
||||||
|
yield break; // There is no entity stream for this type
|
||||||
|
var consumers = entityStream.GetConsumers();
|
||||||
|
if (consumers == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Consumers is null");
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waitForConsumers;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
waitForConsumers = false;
|
||||||
|
for (int i = 0; i < consumers.count; i++)
|
||||||
|
{
|
||||||
|
var buffer = consumers[i].GetRingBuffer();
|
||||||
|
if (buffer.Count + 1 <= buffer.Capacity) continue;
|
||||||
|
waitForConsumers = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitForConsumers) yield return Yield.It;
|
||||||
|
} while (waitForConsumers);
|
||||||
entitiesDB.PublishEntityChange<T>(id);
|
entitiesDB.PublishEntityChange<T>(id);
|
||||||
var (count, changes) = ChangesToPublish[typeof(T)];
|
}
|
||||||
changes.Remove(id);
|
|
||||||
ChangesToPublish[typeof(T)] = (count + 1, changes);
|
/// <summary>
|
||||||
yield return Yield.It;
|
/// Query entities as OptionalRefs. The elements always exist, it's just a nice way to encapsulate the data.
|
||||||
ChangesToPublish[typeof(T)] = (0, changes);
|
/// </summary>
|
||||||
|
/// <param name="entitiesDB"></param>
|
||||||
|
/// <param name="group"></param>
|
||||||
|
/// <param name="select"></param>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <typeparam name="TR"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static RefCollection<T> QueryEntitiesOptional<T>(this EntitiesDB entitiesDB, ExclusiveGroupStruct group) where T : unmanaged, IEntityComponent
|
||||||
|
{
|
||||||
|
var (buffer, ids, count) = entitiesDB.QueryEntities<T>(group);
|
||||||
|
return new RefCollection<T>(count, buffer, ids, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,8 +4,9 @@ using Svelto.ECS;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Utility
|
namespace TechbloxModdingAPI.Utility
|
||||||
{
|
{
|
||||||
public ref struct OptionalRef<T> where T : struct, IEntityComponent
|
public ref struct OptionalRef<T> where T : struct, IBaseEntityComponent
|
||||||
{
|
{
|
||||||
|
private readonly EGID entityId;
|
||||||
private readonly State state;
|
private readonly State state;
|
||||||
private readonly uint index;
|
private readonly uint index;
|
||||||
private NB<T> array;
|
private NB<T> array;
|
||||||
|
@ -13,19 +14,22 @@ namespace TechbloxModdingAPI.Utility
|
||||||
private readonly EntityInitializer initializer;
|
private readonly EntityInitializer initializer;
|
||||||
//The possible fields are: (index && (array || managedArray)) || initializer
|
//The possible fields are: (index && (array || managedArray)) || initializer
|
||||||
|
|
||||||
public OptionalRef(NB<T> array, uint index)
|
public OptionalRef(NB<T> array, uint index, EGID entityId = default)
|
||||||
{
|
{
|
||||||
state = State.Native;
|
state = State.Native;
|
||||||
this.array = array;
|
this.array = array;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
this.entityId = entityId;
|
||||||
initializer = default;
|
initializer = default;
|
||||||
|
managedArray = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionalRef(MB<T> array, uint index)
|
public OptionalRef(MB<T> array, uint index, EGID entityId = default)
|
||||||
{
|
{
|
||||||
state = State.Managed;
|
state = State.Managed;
|
||||||
managedArray = array;
|
managedArray = array;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
this.entityId = entityId;
|
||||||
initializer = default;
|
initializer = default;
|
||||||
this.array = default;
|
this.array = default;
|
||||||
}
|
}
|
||||||
|
@ -35,8 +39,9 @@ namespace TechbloxModdingAPI.Utility
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The object with the initializer</param>
|
/// <param name="obj">The object with the initializer</param>
|
||||||
/// <param name="unmanaged">Whether the struct is unmanaged</param>
|
/// <param name="unmanaged">Whether the struct is unmanaged</param>
|
||||||
public OptionalRef(EcsObjectBase obj, bool unmanaged)
|
public OptionalRef(EcsObjectBase obj, bool unmanaged, EGID entityId = default)
|
||||||
{
|
{
|
||||||
|
this.entityId = entityId;
|
||||||
if (obj.InitData.Valid)
|
if (obj.InitData.Valid)
|
||||||
{
|
{
|
||||||
initializer = obj.InitData.Initializer(obj.Id);
|
initializer = obj.InitData.Initializer(obj.Id);
|
||||||
|
@ -49,6 +54,7 @@ namespace TechbloxModdingAPI.Utility
|
||||||
}
|
}
|
||||||
array = default;
|
array = default;
|
||||||
index = default;
|
index = default;
|
||||||
|
managedArray = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -73,6 +79,11 @@ namespace TechbloxModdingAPI.Utility
|
||||||
set => Get() = value;
|
set => Get() = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ID of the entity this component belongs to or default if it doesn't exist.
|
||||||
|
/// </summary>
|
||||||
|
public EGID EGID => entityId;
|
||||||
|
|
||||||
public bool Exists => state != State.Empty;
|
public bool Exists => state != State.Empty;
|
||||||
public T? Nullable() => this ? Get() : default;
|
public T? Nullable() => this ? Get() : default;
|
||||||
|
|
||||||
|
@ -80,6 +91,8 @@ namespace TechbloxModdingAPI.Utility
|
||||||
|
|
||||||
public static implicit operator bool(OptionalRef<T> opt) => opt.state != State.Empty;
|
public static implicit operator bool(OptionalRef<T> opt) => opt.state != State.Empty;
|
||||||
|
|
||||||
|
public static implicit operator EGID(OptionalRef<T> opt) => opt.entityId;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of a struct T that can be referenced.
|
/// Creates an instance of a struct T that can be referenced.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
94
TechbloxModdingAPI/Utility/RefCollection.cs
Normal file
94
TechbloxModdingAPI/Utility/RefCollection.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
using System;
|
||||||
|
using Svelto.DataStructures;
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Hybrid;
|
||||||
|
using Svelto.ECS.Internal;
|
||||||
|
|
||||||
|
namespace TechbloxModdingAPI.Utility
|
||||||
|
{
|
||||||
|
public readonly ref struct RefCollection<T> where T : struct, IBaseEntityComponent
|
||||||
|
{
|
||||||
|
private readonly bool managed;
|
||||||
|
private readonly int count;
|
||||||
|
private readonly NB<T> nativeArray;
|
||||||
|
private readonly MB<T> managedArray;
|
||||||
|
private readonly NativeEntityIDs nativeIDs;
|
||||||
|
private readonly ManagedEntityIDs managedIDs;
|
||||||
|
private readonly ExclusiveGroupStruct group;
|
||||||
|
|
||||||
|
public RefCollection(int count, MB<T> managedArray, ManagedEntityIDs managedIDs, ExclusiveGroupStruct group)
|
||||||
|
{
|
||||||
|
this.count = count;
|
||||||
|
this.managedArray = managedArray;
|
||||||
|
this.managedIDs = managedIDs;
|
||||||
|
this.group = group;
|
||||||
|
managed = true;
|
||||||
|
nativeArray = default;
|
||||||
|
nativeIDs = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefCollection(int count, NB<T> nativeArray, NativeEntityIDs nativeIDs, ExclusiveGroupStruct group)
|
||||||
|
{
|
||||||
|
this.count = count;
|
||||||
|
this.nativeArray = nativeArray;
|
||||||
|
this.nativeIDs = nativeIDs;
|
||||||
|
this.group = group;
|
||||||
|
managed = false;
|
||||||
|
managedArray = default;
|
||||||
|
managedIDs = default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumerator GetEnumerator() => new(this);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The amount of items in the collection.
|
||||||
|
/// </summary>
|
||||||
|
public int Count => count;
|
||||||
|
|
||||||
|
public T[] ToArray() => ToArray(a => a.Component);
|
||||||
|
|
||||||
|
public TA[] ToArray<TA>(Func<(T Component, EGID ID), TA> transformFunction, Predicate<(T Component, EGID ID)> predicateFunction = null)
|
||||||
|
{
|
||||||
|
var result = new TA[Count];
|
||||||
|
int i = 0;
|
||||||
|
foreach (var opt in this)
|
||||||
|
{
|
||||||
|
if (predicateFunction != null && !predicateFunction((opt.Get(), opt.EGID))) continue;
|
||||||
|
result[i] = transformFunction((opt.Get(), opt.EGID));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref struct Enumerator
|
||||||
|
{
|
||||||
|
private RefCollection<T> coll;
|
||||||
|
private int index;
|
||||||
|
|
||||||
|
public Enumerator(RefCollection<T> collection)
|
||||||
|
{
|
||||||
|
index = -1;
|
||||||
|
coll = collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionalRef<T> Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (coll.count <= index && index >= 0) return default;
|
||||||
|
if (coll.managed)
|
||||||
|
return new OptionalRef<T>(coll.managedArray, (uint)index,
|
||||||
|
new EGID(coll.managedIDs[index], coll.group));
|
||||||
|
return new OptionalRef<T>(coll.nativeArray, (uint)index,
|
||||||
|
new EGID(coll.nativeIDs[index], coll.group));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
return ++index < coll.count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue