Seat events, and everything needed to get there
- Added support for seat enter and exit events and a test for them - Added support for entering and exiting seat from code - Changed the Id property of ECS objects to non-abstract, requiring it in the constructor, so that the Player class can inherit EcsObjectBase - Added a weird constructor to EcsObjectBase that allows running code to determine the object Id - Added interface for engines that receive entity functions - Exposed the entity submission scheduler and removed it from FullGameFields because it moved from there - Made the Game.Enter event only fire after the first entity submission so the game is fully initialized and the local player exists - Added all seat groups to the dictionary
This commit is contained in:
parent
4bd636b8ed
commit
6204b226d1
18 changed files with 284 additions and 128 deletions
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using RobocraftX.Common;
|
using RobocraftX.Common;
|
||||||
using RobocraftX.Schedulers;
|
using RobocraftX.Schedulers;
|
||||||
|
@ -11,6 +10,7 @@ using RobocraftX.Blocks;
|
||||||
using RobocraftX.ScreenshotTaker;
|
using RobocraftX.ScreenshotTaker;
|
||||||
using TechbloxModdingAPI.Blocks;
|
using TechbloxModdingAPI.Blocks;
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
|
using TechbloxModdingAPI.Tasks;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.App
|
namespace TechbloxModdingAPI.App
|
||||||
|
@ -35,6 +35,12 @@ namespace TechbloxModdingAPI.App
|
||||||
|
|
||||||
public void Ready()
|
public void Ready()
|
||||||
{
|
{
|
||||||
|
EnteringGame().RunOn(Scheduler.leanRunner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator<TaskContract> EnteringGame()
|
||||||
|
{
|
||||||
|
yield return new WaitForSubmissionEnumerator(GameLoadedEnginePatch.Scheduler).Continue();
|
||||||
EnterGame.Invoke(this, new GameEventArgs { GameName = GameMode.SaveGameDetails.Name, GamePath = GameMode.SaveGameDetails.Folder });
|
EnterGame.Invoke(this, new GameEventArgs { GameName = GameMode.SaveGameDetails.Name, GamePath = GameMode.SaveGameDetails.Folder });
|
||||||
IsInGame = true;
|
IsInGame = true;
|
||||||
}
|
}
|
||||||
|
@ -100,34 +106,23 @@ 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>();
|
||||||
if (filter == BlockIDs.Invalid)
|
|
||||||
{
|
|
||||||
foreach (var (blocks, _) in allBlocks)
|
foreach (var (blocks, _) in allBlocks)
|
||||||
{
|
{
|
||||||
var buffer = blocks.ToBuffer().buffer;
|
var (buffer, count) = blocks.ToBuffer();
|
||||||
for (int i = 0; i < buffer.capacity; i++)
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
uint dbid;
|
||||||
|
if (filter == BlockIDs.Invalid)
|
||||||
|
dbid = (uint)filter;
|
||||||
|
else
|
||||||
|
dbid = entitiesDB.QueryEntity<DBEntityStruct>(buffer[i].ID).DBID;
|
||||||
|
if (dbid == (ulong)filter)
|
||||||
blockEGIDs.Add(buffer[i].ID);
|
blockEGIDs.Add(buffer[i].ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockEGIDs.ToArray();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var (blocks, _) in allBlocks)
|
|
||||||
{
|
|
||||||
var array = blocks.ToBuffer().buffer;
|
|
||||||
for (var index = 0; index < array.capacity; index++)
|
|
||||||
{
|
|
||||||
var block = array[index];
|
|
||||||
uint dbid = entitiesDB.QueryEntity<DBEntityStruct>(block.ID).DBID;
|
|
||||||
if (dbid == (ulong) filter)
|
|
||||||
blockEGIDs.Add(block.ID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockEGIDs.ToArray();
|
return blockEGIDs.ToArray();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void EnableScreenshotTaker()
|
public void EnableScreenshotTaker()
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,12 +99,16 @@ namespace TechbloxModdingAPI
|
||||||
{CommonExclusiveGroups.ENGINE_BLOCK_BUILD_GROUP, (id => new Engine(id), typeof(Engine))},
|
{CommonExclusiveGroups.ENGINE_BLOCK_BUILD_GROUP, (id => new Engine(id), typeof(Engine))},
|
||||||
{CommonExclusiveGroups.LOGIC_BLOCK_GROUP, (id => new LogicGate(id), typeof(LogicGate))},
|
{CommonExclusiveGroups.LOGIC_BLOCK_GROUP, (id => new LogicGate(id), typeof(LogicGate))},
|
||||||
{CommonExclusiveGroups.PISTON_BLOCK_GROUP, (id => new Piston(id), typeof(Piston))},
|
{CommonExclusiveGroups.PISTON_BLOCK_GROUP, (id => new Piston(id), typeof(Piston))},
|
||||||
{SeatGroups.PASSENGER_BLOCK_BUILD_GROUP, (id => new Seat(id), typeof(Seat))},
|
|
||||||
{SeatGroups.PILOTSEAT_BLOCK_BUILD_GROUP, (id => new Seat(id), typeof(Seat))},
|
|
||||||
{CommonExclusiveGroups.SERVO_BLOCK_GROUP, (id => new Servo(id), typeof(Servo))},
|
{CommonExclusiveGroups.SERVO_BLOCK_GROUP, (id => new Servo(id), typeof(Servo))},
|
||||||
{CommonExclusiveGroups.WHEELRIG_BLOCK_BUILD_GROUP, (id => new WheelRig(id), typeof(WheelRig))}
|
{CommonExclusiveGroups.WHEELRIG_BLOCK_BUILD_GROUP, (id => new WheelRig(id), typeof(WheelRig))}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Block()
|
||||||
|
{
|
||||||
|
foreach (var group in SeatGroups.SEATS_BLOCK_GROUPS) // Adds driver and passenger seats, occupied and unoccupied
|
||||||
|
GroupToConstructor.Add(group, (id => new Seat(id), typeof(Seat)));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a correctly typed instance of this block. The instances are shared for a specific block.
|
/// Returns a correctly typed instance of this block. The instances are shared for a specific block.
|
||||||
/// If an instance is no longer referenced a new instance is returned.
|
/// If an instance is no longer referenced a new instance is returned.
|
||||||
|
@ -126,9 +130,8 @@ namespace TechbloxModdingAPI
|
||||||
: GetInstance(egid, e => new Block(e));
|
: GetInstance(egid, e => new Block(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block(EGID id)
|
public Block(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
Id = id;
|
|
||||||
Type expectedType;
|
Type expectedType;
|
||||||
if (GroupToConstructor.ContainsKey(id.groupID) &&
|
if (GroupToConstructor.ContainsKey(id.groupID) &&
|
||||||
!GetType().IsAssignableFrom(expectedType = GroupToConstructor[id.groupID].Type))
|
!GetType().IsAssignableFrom(expectedType = GroupToConstructor[id.groupID].Type))
|
||||||
|
@ -156,17 +159,18 @@ namespace TechbloxModdingAPI
|
||||||
/// <param name="player">The player who placed the block</param>
|
/// <param name="player">The player who placed the block</param>
|
||||||
/// <param name="force">Place even if not in build mode</param>
|
/// <param name="force">Place even if not in build mode</param>
|
||||||
public Block(BlockIDs type, float3 position, bool autoWire = false, Player player = null, bool force = false)
|
public Block(BlockIDs type, float3 position, bool autoWire = false, Player player = null, bool force = false)
|
||||||
|
: base(block =>
|
||||||
{
|
{
|
||||||
if (!PlacementEngine.IsInGame || !GameState.IsBuildMode() && !force)
|
if (!PlacementEngine.IsInGame || !GameState.IsBuildMode() && !force)
|
||||||
throw new BlockException("Blocks can only be placed in build mode.");
|
throw new BlockException("Blocks can only be placed in build mode.");
|
||||||
var initializer = PlacementEngine.PlaceBlock(type, position, player, autoWire);
|
var initializer = PlacementEngine.PlaceBlock(type, position, player, autoWire);
|
||||||
Id = initializer.EGID;
|
block.InitData = initializer;
|
||||||
InitData = initializer;
|
Placed += ((Block)block).OnPlacedInit;
|
||||||
Placed += OnPlacedInit;
|
return initializer.EGID;
|
||||||
|
})
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override EGID Id { get; }
|
|
||||||
|
|
||||||
private EGID copiedFrom;
|
private EGID copiedFrom;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -19,17 +19,16 @@ namespace TechbloxModdingAPI
|
||||||
public class BlockGroup : EcsObjectBase, ICollection<Block>, IDisposable
|
public class BlockGroup : EcsObjectBase, ICollection<Block>, IDisposable
|
||||||
{
|
{
|
||||||
internal static BlueprintEngine _engine = new BlueprintEngine();
|
internal static BlueprintEngine _engine = new BlueprintEngine();
|
||||||
public override EGID Id { get; }
|
|
||||||
private readonly Block sourceBlock;
|
private readonly Block sourceBlock;
|
||||||
private readonly List<Block> blocks;
|
private readonly List<Block> blocks;
|
||||||
private float3 position, rotation;
|
private float3 position, rotation;
|
||||||
internal bool PosAndRotCalculated;
|
internal bool PosAndRotCalculated;
|
||||||
|
|
||||||
internal BlockGroup(int id, Block block)
|
internal BlockGroup(int id, Block block) : base(new EGID((uint)id,
|
||||||
|
BlockGroupExclusiveGroups.BlockGroupEntityGroup))
|
||||||
{
|
{
|
||||||
if (id == BlockGroupUtility.GROUP_UNASSIGNED)
|
if (id == BlockGroupUtility.GROUP_UNASSIGNED)
|
||||||
throw new BlockException("Cannot create a block group for blocks without a group!");
|
throw new BlockException("Cannot create a block group for blocks without a group!");
|
||||||
Id = new EGID((uint) id, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
|
|
||||||
sourceBlock = block;
|
sourceBlock = block;
|
||||||
blocks = new List<Block>(GetBlocks());
|
blocks = new List<Block>(GetBlocks());
|
||||||
Block.Removed += OnBlockRemoved;
|
Block.Removed += OnBlockRemoved;
|
||||||
|
|
|
@ -76,10 +76,11 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
/// <param name="startPort">Starting port number, or guess if omitted.</param>
|
/// <param name="startPort">Starting port number, or guess if omitted.</param>
|
||||||
/// <param name="endPort">Ending port number, or guess if omitted.</param>
|
/// <param name="endPort">Ending port number, or guess if omitted.</param>
|
||||||
/// <exception cref="WireInvalidException">Guessing failed or wire does not exist.</exception>
|
/// <exception cref="WireInvalidException">Guessing failed or wire does not exist.</exception>
|
||||||
public Wire(Block start, Block end, byte startPort = Byte.MaxValue, byte endPort = Byte.MaxValue)
|
public Wire(Block start, Block end, byte startPort = Byte.MaxValue, byte endPort = Byte.MaxValue) : base(ecs =>
|
||||||
{
|
{
|
||||||
startBlockEGID = start.Id;
|
var th = (Wire)ecs;
|
||||||
endBlockEGID = end.Id;
|
th.startBlockEGID = start.Id;
|
||||||
|
th.endBlockEGID = end.Id;
|
||||||
bool flipped = false;
|
bool flipped = false;
|
||||||
// find block ports
|
// find block ports
|
||||||
EGID wire = signalEngine.MatchBlocksToWire(start.Id, end.Id, startPort, endPort);
|
EGID wire = signalEngine.MatchBlocksToWire(start.Id, end.Id, startPort, endPort);
|
||||||
|
@ -94,12 +95,16 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
|
|
||||||
if (wire != default)
|
if (wire != default)
|
||||||
{
|
{
|
||||||
Construct(start.Id, end.Id, startPort, endPort, wire, flipped);
|
th.Construct(start.Id, end.Id, startPort, endPort, wire, flipped);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new WireInvalidException("Wire not found");
|
throw new WireInvalidException("Wire not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return th.wireEGID;
|
||||||
|
})
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -116,7 +121,7 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private Wire(EGID startBlock, EGID endBlock, byte startPort, byte endPort, EGID wire, bool inputToOutput)
|
private Wire(EGID startBlock, EGID endBlock, byte startPort, byte endPort, EGID wire, bool inputToOutput) : base(wire)
|
||||||
{
|
{
|
||||||
Construct(startBlock, endBlock, startPort, endPort, wire, inputToOutput);
|
Construct(startBlock, endBlock, startPort, endPort, wire, inputToOutput);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +144,7 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
/// Construct a wire object from an existing wire connection.
|
/// Construct a wire object from an existing wire connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="wireEgid">The wire ID.</param>
|
/// <param name="wireEgid">The wire ID.</param>
|
||||||
public Wire(EGID wireEgid)
|
public Wire(EGID wireEgid) : base(wireEgid)
|
||||||
{
|
{
|
||||||
WireEntityStruct wire = signalEngine.GetWire(wireEGID);
|
WireEntityStruct wire = signalEngine.GetWire(wireEGID);
|
||||||
Construct(wire.sourceBlockEGID, wire.destinationBlockEGID, wire.sourcePortUsage, wire.destinationPortUsage,
|
Construct(wire.sourceBlockEGID, wire.destinationBlockEGID, wire.sourcePortUsage, wire.destinationPortUsage,
|
||||||
|
@ -151,14 +156,6 @@ namespace TechbloxModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The wire's in-game id.
|
|
||||||
/// </summary>
|
|
||||||
public override EGID Id
|
|
||||||
{
|
|
||||||
get => wireEGID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The wire's signal value, as a float.
|
/// The wire's signal value, as a float.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -10,11 +10,8 @@ namespace TechbloxModdingAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Cluster : EcsObjectBase
|
public class Cluster : EcsObjectBase
|
||||||
{
|
{
|
||||||
public override EGID Id { get; }
|
public Cluster(EGID id) : base(id)
|
||||||
|
|
||||||
public Cluster(EGID id)
|
|
||||||
{
|
{
|
||||||
Id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cluster(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_CLUSTERS_GROUP))
|
public Cluster(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_CLUSTERS_GROUP))
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace TechbloxModdingAPI
|
||||||
{
|
{
|
||||||
public abstract class EcsObjectBase
|
public abstract class EcsObjectBase
|
||||||
{
|
{
|
||||||
public abstract EGID Id { get; } //Abstract to support the 'place' Block constructor
|
public EGID Id { get; }
|
||||||
|
|
||||||
private static readonly Dictionary<Type, WeakDictionary<EGID, EcsObjectBase>> _instances =
|
private static readonly Dictionary<Type, WeakDictionary<EGID, EcsObjectBase>> _instances =
|
||||||
new Dictionary<Type, WeakDictionary<EGID, EcsObjectBase>>();
|
new Dictionary<Type, WeakDictionary<EGID, EcsObjectBase>>();
|
||||||
|
@ -39,7 +39,19 @@ namespace TechbloxModdingAPI
|
||||||
return (T)instance;
|
return (T)instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EcsObjectBase()
|
protected EcsObjectBase(EGID id)
|
||||||
|
{
|
||||||
|
if (!_instances.TryGetValue(GetType(), out var dict))
|
||||||
|
{
|
||||||
|
dict = new WeakDictionary<EGID, EcsObjectBase>();
|
||||||
|
_instances.Add(GetType(), dict);
|
||||||
|
}
|
||||||
|
if (!dict.ContainsKey(id)) // Multiple instances may be created
|
||||||
|
dict.Add(id, this);
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EcsObjectBase(Func<EcsObjectBase, EGID> initializer)
|
||||||
{
|
{
|
||||||
if (!_instances.TryGetValue(GetType(), out var dict))
|
if (!_instances.TryGetValue(GetType(), out var dict))
|
||||||
{
|
{
|
||||||
|
@ -47,11 +59,9 @@ namespace TechbloxModdingAPI
|
||||||
_instances.Add(GetType(), dict);
|
_instances.Add(GetType(), dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable VirtualMemberCallInConstructor
|
var id = initializer(this);
|
||||||
// The ID should not depend on the constructor
|
if (!dict.ContainsKey(id)) // Multiple instances may be created
|
||||||
if (!dict.ContainsKey(Id)) // Multiple instances may be created
|
dict.Add(id, this);
|
||||||
dict.Add(Id, this);
|
|
||||||
// ReSharper enable VirtualMemberCallInConstructor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region ECS initializer stuff
|
#region ECS initializer stuff
|
||||||
|
|
|
@ -5,6 +5,7 @@ using RobocraftX.CR.MainGame;
|
||||||
using RobocraftX.FrontEnd;
|
using RobocraftX.FrontEnd;
|
||||||
using RobocraftX.StateSync;
|
using RobocraftX.StateSync;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Schedulers;
|
||||||
using TechbloxModdingAPI.Utility;
|
using TechbloxModdingAPI.Utility;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Engines
|
namespace TechbloxModdingAPI.Engines
|
||||||
|
@ -12,10 +13,12 @@ namespace TechbloxModdingAPI.Engines
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
class GameLoadedEnginePatch
|
class GameLoadedEnginePatch
|
||||||
{
|
{
|
||||||
|
public static EntitiesSubmissionScheduler Scheduler { get; private set; }
|
||||||
public static void Postfix(StateSyncRegistrationHelper stateSyncReg)
|
public static void Postfix(StateSyncRegistrationHelper stateSyncReg)
|
||||||
{
|
{
|
||||||
// register all game engines, including deterministic
|
// register all game engines, including deterministic
|
||||||
GameEngineManager.RegisterEngines(stateSyncReg);
|
GameEngineManager.RegisterEngines(stateSyncReg);
|
||||||
|
Scheduler = stateSyncReg.enginesRoot.scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodBase TargetMethod()
|
public static MethodBase TargetMethod()
|
||||||
|
|
9
TechbloxModdingAPI/Engines/IFunEngine.cs
Normal file
9
TechbloxModdingAPI/Engines/IFunEngine.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
namespace TechbloxModdingAPI.Engines
|
||||||
|
{
|
||||||
|
public interface IFunEngine : IApiEngine
|
||||||
|
{
|
||||||
|
public IEntityFunctions Functions { set; }
|
||||||
|
}
|
||||||
|
}
|
30
TechbloxModdingAPI/Player.Events.cs
Normal file
30
TechbloxModdingAPI/Player.Events.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using Svelto.ECS;
|
||||||
|
using TechbloxModdingAPI.Blocks;
|
||||||
|
using TechbloxModdingAPI.Utility;
|
||||||
|
|
||||||
|
namespace TechbloxModdingAPI
|
||||||
|
{
|
||||||
|
public partial class Player
|
||||||
|
{
|
||||||
|
internal WrappedHandler<PlayerSeatEventArgs> seatEntered;
|
||||||
|
public event EventHandler<PlayerSeatEventArgs> SeatEntered
|
||||||
|
{
|
||||||
|
add => seatEntered += value;
|
||||||
|
remove => seatEntered -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal WrappedHandler<PlayerSeatEventArgs> seatExited;
|
||||||
|
public event EventHandler<PlayerSeatEventArgs> SeatExited
|
||||||
|
{
|
||||||
|
add => seatExited += value;
|
||||||
|
remove => seatExited -= value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PlayerSeatEventArgs
|
||||||
|
{
|
||||||
|
public EGID SeatId;
|
||||||
|
public Seat Seat => (Seat)Block.New(SeatId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,10 +20,11 @@ namespace TechbloxModdingAPI
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An in-game player character. Any Leo you see is a player.
|
/// An in-game player character. Any Leo you see is a player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Player : IEquatable<Player>, IEquatable<EGID>
|
public partial class Player : EcsObjectBase, IEquatable<Player>, IEquatable<EGID>
|
||||||
{ //TODO: Inherit EcsObjectBase and make Id an EGID, useful for caching
|
{
|
||||||
// static functionality
|
// static functionality
|
||||||
private static PlayerEngine playerEngine = new PlayerEngine();
|
private static PlayerEngine playerEngine = new PlayerEngine();
|
||||||
|
private static PlayerEventsEngine playerEventsEngine = new PlayerEventsEngine();
|
||||||
private static Player localPlayer;
|
private static Player localPlayer;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -79,7 +80,7 @@ namespace TechbloxModdingAPI
|
||||||
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.Player"/> class.
|
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.Player"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The player's unique identifier.</param>
|
/// <param name="id">The player's unique identifier.</param>
|
||||||
public Player(uint id)
|
public Player(uint id) : base(new EGID(id, CharacterExclusiveGroups.OnFootGroup))
|
||||||
{
|
{
|
||||||
this.Id = id;
|
this.Id = id;
|
||||||
if (!Exists(id))
|
if (!Exists(id))
|
||||||
|
@ -93,21 +94,30 @@ namespace TechbloxModdingAPI
|
||||||
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.Player"/> class.
|
/// Initializes a new instance of the <see cref="T:TechbloxModdingAPI.Player"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="player">The player type. Chooses the first available player matching the criteria.</param>
|
/// <param name="player">The player type. Chooses the first available player matching the criteria.</param>
|
||||||
public Player(PlayerType player)
|
public Player(PlayerType player) : base(ecs =>
|
||||||
{
|
{
|
||||||
|
uint id;
|
||||||
switch (player)
|
switch (player)
|
||||||
{
|
{
|
||||||
case PlayerType.Local:
|
case PlayerType.Local:
|
||||||
this.Id = playerEngine.GetLocalPlayer();
|
id = playerEngine.GetLocalPlayer();
|
||||||
break;
|
break;
|
||||||
case PlayerType.Remote:
|
case PlayerType.Remote:
|
||||||
this.Id = playerEngine.GetRemotePlayer();
|
id = playerEngine.GetRemotePlayer();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
id = uint.MaxValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (this.Id == uint.MaxValue)
|
|
||||||
|
if (id == uint.MaxValue)
|
||||||
{
|
{
|
||||||
throw new PlayerNotFoundException($"No player of {player} type exists");
|
throw new PlayerNotFoundException($"No player of {player} type exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new EGID(id, CharacterExclusiveGroups.OnFootGroup);
|
||||||
|
})
|
||||||
|
{
|
||||||
this.Type = player;
|
this.Type = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +134,7 @@ namespace TechbloxModdingAPI
|
||||||
/// The player's unique identifier.
|
/// The player's unique identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The identifier.</value>
|
/// <value>The identifier.</value>
|
||||||
public uint Id { get; }
|
public new uint Id { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The player's current position.
|
/// The player's current position.
|
||||||
|
@ -425,6 +435,16 @@ namespace TechbloxModdingAPI
|
||||||
playerEngine.SetLocation(Id, location, exitSeat: exitSeat);
|
playerEngine.SetLocation(Id, location, exitSeat: exitSeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnterSeat(Seat seat)
|
||||||
|
{
|
||||||
|
playerEngine.EnterSeat(Id, seat.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExitSeat()
|
||||||
|
{
|
||||||
|
playerEngine.ExitSeat(Id);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the block the player is currently looking at in build mode.
|
/// Returns the block the player is currently looking at in build mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -507,6 +527,7 @@ namespace TechbloxModdingAPI
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
Utility.GameEngineManager.AddGameEngine(playerEngine);
|
Utility.GameEngineManager.AddGameEngine(playerEngine);
|
||||||
|
Utility.GameEngineManager.AddGameEngine(playerEventsEngine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Runtime.CompilerServices;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using RobocraftX.Character;
|
using RobocraftX.Character;
|
||||||
using RobocraftX.Character.Movement;
|
using RobocraftX.Character.Movement;
|
||||||
|
@ -8,10 +9,13 @@ using RobocraftX.CR.MachineEditing.BoxSelect;
|
||||||
using RobocraftX.Physics;
|
using RobocraftX.Physics;
|
||||||
using RobocraftX.Blocks.Ghost;
|
using RobocraftX.Blocks.Ghost;
|
||||||
using Gamecraft.GUI.HUDFeedbackBlocks;
|
using Gamecraft.GUI.HUDFeedbackBlocks;
|
||||||
|
using RobocraftX.Blocks;
|
||||||
|
using RobocraftX.PilotSeat;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Techblox.Camera;
|
using Techblox.Camera;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using Svelto.ECS.DataStructures;
|
using Svelto.ECS.DataStructures;
|
||||||
|
using Svelto.ECS.EntityStructs;
|
||||||
using Techblox.BuildingDrone;
|
using Techblox.BuildingDrone;
|
||||||
|
|
||||||
using TechbloxModdingAPI.Engines;
|
using TechbloxModdingAPI.Engines;
|
||||||
|
@ -19,7 +23,7 @@ using TechbloxModdingAPI.Utility;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Players
|
namespace TechbloxModdingAPI.Players
|
||||||
{
|
{
|
||||||
internal class PlayerEngine : IApiEngine, IFactoryEngine
|
internal class PlayerEngine : IFunEngine
|
||||||
{
|
{
|
||||||
public string Name { get; } = "TechbloxModdingAPIPlayerGameEngine";
|
public string Name { get; } = "TechbloxModdingAPIPlayerGameEngine";
|
||||||
|
|
||||||
|
@ -27,7 +31,7 @@ namespace TechbloxModdingAPI.Players
|
||||||
|
|
||||||
public bool isRemovable => false;
|
public bool isRemovable => false;
|
||||||
|
|
||||||
public IEntityFactory Factory { set; private get; }
|
public IEntityFunctions Functions { get; set; }
|
||||||
|
|
||||||
private bool isReady = false;
|
private bool isReady = false;
|
||||||
|
|
||||||
|
@ -101,9 +105,7 @@ namespace TechbloxModdingAPI.Players
|
||||||
return false;
|
return false;
|
||||||
if (group == CharacterExclusiveGroups.InPilotSeatGroup && exitSeat)
|
if (group == CharacterExclusiveGroups.InPilotSeatGroup && exitSeat)
|
||||||
{
|
{
|
||||||
EGID egid = new EGID(playerId, group);
|
ExitSeat(playerId);
|
||||||
entitiesDB.QueryEntity<CharacterPilotSeatEntityStruct>(egid).instantExit = true;
|
|
||||||
entitiesDB.PublishEntityChange<CharacterPilotSeatEntityStruct>(egid);
|
|
||||||
}
|
}
|
||||||
rbesOpt.Get().position = location;
|
rbesOpt.Get().position = location;
|
||||||
return true;
|
return true;
|
||||||
|
@ -183,12 +185,12 @@ namespace TechbloxModdingAPI.Players
|
||||||
{
|
{
|
||||||
if (!entitiesDB.Exists<BoxSelectStateEntityStruct>(playerid,
|
if (!entitiesDB.Exists<BoxSelectStateEntityStruct>(playerid,
|
||||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup))
|
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup))
|
||||||
return new Block[0];
|
return Array.Empty<Block>();
|
||||||
var state = entitiesDB.QueryEntity<BoxSelectStateEntityStruct>(playerid,
|
var state = entitiesDB.QueryEntity<BoxSelectStateEntityStruct>(playerid,
|
||||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup);
|
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup);
|
||||||
var blocks = entitiesDB.QueryEntity<SelectedBlocksStruct>(playerid,
|
var blocks = entitiesDB.QueryEntity<SelectedBlocksStruct>(playerid,
|
||||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup);
|
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup);
|
||||||
if (!state.active) return new Block[0];
|
if (!state.active) return Array.Empty<Block>();
|
||||||
var pointer = (EGID*) blocks.selectedBlocks.ToPointer();
|
var pointer = (EGID*) blocks.selectedBlocks.ToPointer();
|
||||||
var ret = new Block[blocks.count];
|
var ret = new Block[blocks.count];
|
||||||
for (int j = 0; j < blocks.count; j++)
|
for (int j = 0; j < blocks.count; j++)
|
||||||
|
@ -199,5 +201,31 @@ namespace TechbloxModdingAPI.Players
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnterSeat(uint playerId, EGID seatId)
|
||||||
|
{
|
||||||
|
PilotSeatGroupUtils.SwapTagTo<OCCUPIED_TAG>(Functions, seatId);
|
||||||
|
var opt = GetCharacterStruct<CharacterPilotSeatEntityStruct>(playerId, out var group);
|
||||||
|
if (!opt) return;
|
||||||
|
ref CharacterPilotSeatEntityStruct charSeat = ref opt.Get();
|
||||||
|
var charId = new EGID(playerId, group);
|
||||||
|
charSeat.pilotSeatEntity = entitiesDB.GetEntityReference(seatId);
|
||||||
|
charSeat.entryPositionOffset =
|
||||||
|
entitiesDB.QueryEntity<PositionEntityStruct>(charId).position -
|
||||||
|
entitiesDB.QueryEntity<PositionEntityStruct>(seatId).position;
|
||||||
|
ref var seat = ref entitiesDB.QueryEntity<PilotSeatEntityStruct>(seatId);
|
||||||
|
seat.occupyingCharacter = entitiesDB.GetEntityReference(charId);
|
||||||
|
charSeat.followCam = entitiesDB.QueryEntity<SeatFollowCamComponent>(seatId).followCam;
|
||||||
|
Functions.SwapEntityGroup<CharacterEntityDescriptor>(charId, CharacterExclusiveGroups.InPilotSeatGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExitSeat(uint playerId)
|
||||||
|
{
|
||||||
|
EGID egid = new EGID(playerId, CharacterExclusiveGroups.InPilotSeatGroup);
|
||||||
|
var opt = entitiesDB.QueryEntityOptional<CharacterPilotSeatEntityStruct>(egid);
|
||||||
|
if (!opt) return;
|
||||||
|
opt.Get().instantExit = true;
|
||||||
|
entitiesDB.PublishEntityChange<CharacterPilotSeatEntityStruct>(egid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
33
TechbloxModdingAPI/Players/PlayerEventsEngine.cs
Normal file
33
TechbloxModdingAPI/Players/PlayerEventsEngine.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using RobocraftX.Character;
|
||||||
|
using RobocraftX.Character.Movement;
|
||||||
|
using Svelto.ECS;
|
||||||
|
using TechbloxModdingAPI.Engines;
|
||||||
|
|
||||||
|
namespace TechbloxModdingAPI.Players
|
||||||
|
{
|
||||||
|
public class PlayerEventsEngine : IApiEngine, IReactOnSwap<CharacterPilotSeatEntityStruct>
|
||||||
|
{
|
||||||
|
public void Ready()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntitiesDB entitiesDB { get; set; }
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name => "TechbloxModdingAPIPlayerEventsEngine";
|
||||||
|
public bool isRemovable => false;
|
||||||
|
|
||||||
|
public void MovedTo(ref CharacterPilotSeatEntityStruct entityComponent, ExclusiveGroupStruct previousGroup, EGID egid)
|
||||||
|
{
|
||||||
|
var seatId = entityComponent.pilotSeatEntity.ToEGID(entitiesDB);
|
||||||
|
var player = EcsObjectBase.GetInstance(new EGID(egid.entityID, CharacterExclusiveGroups.OnFootGroup),
|
||||||
|
e => new Player(e.entityID));
|
||||||
|
if (previousGroup == CharacterExclusiveGroups.InPilotSeatGroup)
|
||||||
|
player.seatExited.Invoke(this, new PlayerSeatEventArgs { SeatId = seatId});
|
||||||
|
else if (egid.groupID == CharacterExclusiveGroups.InPilotSeatGroup)
|
||||||
|
player.seatEntered.Invoke(this, new PlayerSeatEventArgs { SeatId = seatId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Svelto.Tasks;
|
||||||
|
using Svelto.Tasks.Enumerators;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
|
||||||
using TechbloxModdingAPI;
|
using TechbloxModdingAPI.App;
|
||||||
|
using TechbloxModdingAPI.Blocks;
|
||||||
using TechbloxModdingAPI.Tests;
|
using TechbloxModdingAPI.Tests;
|
||||||
|
|
||||||
namespace TechbloxModdingAPI.Players
|
namespace TechbloxModdingAPI.Players
|
||||||
|
@ -31,6 +34,34 @@ namespace TechbloxModdingAPI.Players
|
||||||
Assert.CloseTo(p.Position, float3.zero + 1, "Player is not close to origin+1 despite being teleported there.", "Player.Position is at origin+1.");
|
Assert.CloseTo(p.Position, float3.zero + 1, "Player is not close to origin+1 despite being teleported there.", "Player.Position is at origin+1.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[APITestCase(TestType.Game)]
|
||||||
|
public static void SeatEventTestBuild()
|
||||||
|
{
|
||||||
|
Player.LocalPlayer.SeatEntered += Assert.CallsBack<PlayerSeatEventArgs>("SeatEntered");
|
||||||
|
Player.LocalPlayer.SeatExited += Assert.CallsBack<PlayerSeatEventArgs>("SeatExited");
|
||||||
|
Block.PlaceNew(BlockIDs.DriverSeat, -1f);
|
||||||
|
}
|
||||||
|
|
||||||
|
[APITestCase(TestType.SimulationMode)]
|
||||||
|
public static IEnumerator<TaskContract> SeatEventTestSim()
|
||||||
|
{
|
||||||
|
var seats = Game.CurrentGame().GetBlocksInGame(BlockIDs.DriverSeat);
|
||||||
|
if (seats.Length == 0)
|
||||||
|
{
|
||||||
|
Assert.Fail("No driver seat found!");
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seats[0] is Seat seat)
|
||||||
|
Assert.Errorless(() => Player.LocalPlayer.EnterSeat(seat), "Failed to enter seat.",
|
||||||
|
"Entered seat successfully.");
|
||||||
|
else
|
||||||
|
Assert.Fail("Found a seat that is not a seat!");
|
||||||
|
yield return new WaitForSecondsEnumerator(1).Continue();
|
||||||
|
Assert.Errorless(() => Player.LocalPlayer.ExitSeat(), "Failed to exit seat.",
|
||||||
|
"Exited seat successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
[APITestCase(TestType.Menu)]
|
[APITestCase(TestType.Menu)]
|
||||||
public static void InvalidStateTest()
|
public static void InvalidStateTest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,8 +14,6 @@ namespace TechbloxModdingAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SimBody : EcsObjectBase, IEquatable<SimBody>, IEquatable<EGID>
|
public class SimBody : EcsObjectBase, IEquatable<SimBody>, IEquatable<EGID>
|
||||||
{
|
{
|
||||||
public override EGID Id { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist.
|
/// The cluster this chunk belongs to, or null if no cluster destruction manager present or the chunk doesn't exist.
|
||||||
/// Get the SimBody from a Block if possible for good performance here.
|
/// Get the SimBody from a Block if possible for good performance here.
|
||||||
|
@ -28,9 +26,8 @@ namespace TechbloxModdingAPI
|
||||||
private Cluster cluster;
|
private Cluster cluster;
|
||||||
private readonly uint clusterId = uint.MaxValue;
|
private readonly uint clusterId = uint.MaxValue;
|
||||||
|
|
||||||
public SimBody(EGID id)
|
public SimBody(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
Id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimBody(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_BODIES_GROUP))
|
public SimBody(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_BODIES_GROUP))
|
||||||
|
|
|
@ -58,6 +58,14 @@ namespace TechbloxModdingAPI.Tests
|
||||||
|
|
||||||
// debug/test handlers
|
// debug/test handlers
|
||||||
Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!");
|
Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!");
|
||||||
|
Client.EnterMenu += (sender, args) => Console.WriteLine("EnterMenu handler after erroring handler");
|
||||||
|
Game.Enter += (s, a) =>
|
||||||
|
{
|
||||||
|
Player.LocalPlayer.SeatEntered += (sender, args) =>
|
||||||
|
Console.WriteLine($"Player {Player.LocalPlayer} entered seat {args.Seat}");
|
||||||
|
Player.LocalPlayer.SeatExited += (sender, args) =>
|
||||||
|
Console.WriteLine($"Player {Player.LocalPlayer} exited seat {args.Seat}");
|
||||||
|
};
|
||||||
|
|
||||||
// debug/test commands
|
// debug/test commands
|
||||||
if (Dependency.Hell("ExtraCommands"))
|
if (Dependency.Hell("ExtraCommands"))
|
||||||
|
|
|
@ -72,14 +72,6 @@ namespace TechbloxModdingAPI.Utility
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimpleEntitiesSubmissionScheduler _mainGameSubmissionScheduler
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (SimpleEntitiesSubmissionScheduler)fgcr?.Field("_sub").Field("_mainGameSubmissionScheduler").GetValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BuildPhysicsWorld _physicsWorldSystem
|
public static BuildPhysicsWorld _physicsWorldSystem
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
@ -26,10 +26,10 @@ namespace TechbloxModdingAPI.Utility
|
||||||
{
|
{
|
||||||
Logging.MetaDebugLog($"Registering Game IApiEngine {engine.Name}");
|
Logging.MetaDebugLog($"Registering Game IApiEngine {engine.Name}");
|
||||||
_lastEngineRoot.AddEngine(engine);
|
_lastEngineRoot.AddEngine(engine);
|
||||||
if (typeof(IFactoryEngine).IsAssignableFrom(engine.GetType()))
|
if (engine is IFactoryEngine factoryEngine)
|
||||||
{
|
factoryEngine.Factory = _lastEngineRoot.GenerateEntityFactory();
|
||||||
((IFactoryEngine)engine).Factory = _lastEngineRoot.GenerateEntityFactory();
|
if (engine is IFunEngine funEngine)
|
||||||
}
|
funEngine.Functions = _lastEngineRoot.GenerateEntityFunctions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,7 @@ namespace TechbloxModdingAPI.Utility
|
||||||
var enginesRoot = helper.enginesRoot;
|
var enginesRoot = helper.enginesRoot;
|
||||||
_lastEngineRoot = enginesRoot;
|
_lastEngineRoot = enginesRoot;
|
||||||
IEntityFactory factory = enginesRoot.GenerateEntityFactory();
|
IEntityFactory factory = enginesRoot.GenerateEntityFactory();
|
||||||
|
IEntityFunctions functions = enginesRoot.GenerateEntityFunctions();
|
||||||
foreach (var key in _gameEngines.Keys)
|
foreach (var key in _gameEngines.Keys)
|
||||||
{
|
{
|
||||||
Logging.MetaDebugLog($"Registering Game IApiEngine {_gameEngines[key].Name}");
|
Logging.MetaDebugLog($"Registering Game IApiEngine {_gameEngines[key].Name}");
|
||||||
|
@ -75,6 +76,8 @@ namespace TechbloxModdingAPI.Utility
|
||||||
enginesRoot.AddEngine(_gameEngines[key]);
|
enginesRoot.AddEngine(_gameEngines[key]);
|
||||||
if (_gameEngines[key] is IFactoryEngine factEngine)
|
if (_gameEngines[key] is IFactoryEngine factEngine)
|
||||||
factEngine.Factory = factory;
|
factEngine.Factory = factory;
|
||||||
|
if (_gameEngines[key] is IFunEngine funEngine)
|
||||||
|
funEngine.Functions = functions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,10 @@ namespace TechbloxModdingAPI.Utility
|
||||||
{
|
{
|
||||||
Logging.MetaDebugLog($"Registering Menu IApiEngine {engine.Name}");
|
Logging.MetaDebugLog($"Registering Menu IApiEngine {engine.Name}");
|
||||||
_lastEngineRoot.AddEngine(engine);
|
_lastEngineRoot.AddEngine(engine);
|
||||||
if (typeof(IFactoryEngine).IsAssignableFrom(engine.GetType()))
|
if (engine is IFactoryEngine factoryEngine)
|
||||||
{
|
factoryEngine.Factory = _lastEngineRoot.GenerateEntityFactory();
|
||||||
((IFactoryEngine)engine).Factory = _lastEngineRoot.GenerateEntityFactory();
|
if (engine is IFunEngine funEngine)
|
||||||
}
|
funEngine.Functions = _lastEngineRoot.GenerateEntityFunctions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,14 +65,13 @@ namespace TechbloxModdingAPI.Utility
|
||||||
{
|
{
|
||||||
_lastEngineRoot = enginesRoot;
|
_lastEngineRoot = enginesRoot;
|
||||||
IEntityFactory factory = enginesRoot.GenerateEntityFactory();
|
IEntityFactory factory = enginesRoot.GenerateEntityFactory();
|
||||||
|
IEntityFunctions functions = enginesRoot.GenerateEntityFunctions();
|
||||||
foreach (var key in _menuEngines.Keys)
|
foreach (var key in _menuEngines.Keys)
|
||||||
{
|
{
|
||||||
Logging.MetaDebugLog($"Registering Menu IApiEngine {_menuEngines[key].Name}");
|
Logging.MetaDebugLog($"Registering Menu IApiEngine {_menuEngines[key].Name}");
|
||||||
enginesRoot.AddEngine(_menuEngines[key]);
|
enginesRoot.AddEngine(_menuEngines[key]);
|
||||||
if (_menuEngines[key] is IFactoryEngine factEngine)
|
if (_menuEngines[key] is IFactoryEngine factEngine) factEngine.Factory = factory;
|
||||||
{
|
if(_menuEngines[key] is IFunEngine funEngine) funEngine.Functions = functions;
|
||||||
factEngine.Factory = factory;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue