Merge branch 'master' into customblocks

# Conflicts:
#	GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
This commit is contained in:
Norbi Peti 2020-12-11 17:16:05 +01:00
commit 56a64daa18
49 changed files with 1782 additions and 287 deletions

0
Automation/gen_csproj.py Normal file → Executable file
View file

View file

@ -46,11 +46,12 @@ namespace GamecraftModdingAPI.App
public Game[] GetMyGames() public Game[] GetMyGames()
{ {
EntityCollection<MyGameDataEntityStruct> mgsevs = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames); EntityCollection<MyGameDataEntityStruct> mgsevs = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames);
var mgsevsB = mgsevs.ToBuffer().buffer;
Game[] games = new Game[mgsevs.count]; Game[] games = new Game[mgsevs.count];
for (int i = 0; i < mgsevs.count; i++) for (int i = 0; i < mgsevs.count; i++)
{ {
Utility.Logging.MetaDebugLog($"Found game named {mgsevs[i].GameName}"); Utility.Logging.MetaDebugLog($"Found game named {mgsevsB[i].GameName}");
games[i] = new Game(mgsevs[i].ID); games[i] = new Game(mgsevsB[i].ID);
} }
return games; return games;
} }

View file

@ -0,0 +1,23 @@
namespace GamecraftModdingAPI.App
{
public enum CurrentGameMode
{
None,
/// <summary>
/// Building a game
/// </summary>
Build,
/// <summary>
/// Playing a game
/// </summary>
Play,
/// <summary>
/// Viewing a prefab
/// </summary>
View,
/// <summary>
/// Viewing a tutorial
/// </summary>
Tutorial
}
}

View file

@ -335,6 +335,18 @@ namespace GamecraftModdingAPI.App
gameEngine.ToggleTimeMode(); gameEngine.ToggleTimeMode();
} }
/// <summary>
/// The mode of the game.
/// </summary>
public CurrentGameMode Mode
{
get
{
if (menuMode || !VerifyMode()) return CurrentGameMode.None;
return (CurrentGameMode) GameMode.CurrentMode;
}
}
/// <summary> /// <summary>
/// Load the game save. /// Load the game save.
/// This happens asynchronously, so when this method returns the game not loaded yet. /// This happens asynchronously, so when this method returns the game not loaded yet.

View file

@ -52,7 +52,7 @@ namespace GamecraftModdingAPI.App
{ {
if (async) if (async)
{ {
ExitCurrentGameAsync().RunOn(Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING); ExitCurrentGameAsync().RunOn(Lean.EveryFrameStepRunner_TimeRunningAndStopped);
} }
else else
{ {
@ -102,16 +102,27 @@ namespace GamecraftModdingAPI.App
if (filter == BlockIDs.Invalid) if (filter == BlockIDs.Invalid)
{ {
foreach (var (blocks, _) in allBlocks) foreach (var (blocks, _) in allBlocks)
foreach (var block in blocks) {
blockEGIDs.Add(block.ID); var buffer = blocks.ToBuffer().buffer;
for (int i = 0; i < buffer.capacity; i++)
blockEGIDs.Add(buffer[i].ID);
}
return blockEGIDs.ToArray(); return blockEGIDs.ToArray();
} }
else else
{ {
foreach (var (blocks, _) in allBlocks) foreach (var (blocks, _) in allBlocks)
foreach (var block in blocks) {
var array = blocks.ToBuffer().buffer;
for (var index = 0; index < array.capacity; index++)
{
var block = array[index];
if (block.DBID == (ulong) filter) if (block.DBID == (ulong) filter)
blockEGIDs.Add(block.ID); blockEGIDs.Add(block.ID);
}
}
return blockEGIDs.ToArray(); return blockEGIDs.ToArray();
} }
} }

View file

@ -61,12 +61,13 @@ namespace GamecraftModdingAPI.App
public uint HighestID() public uint HighestID()
{ {
EntityCollection<MyGameDataEntityStruct> games = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames); EntityCollection<MyGameDataEntityStruct> games = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames);
var gamesB = games.ToBuffer().buffer;
uint max = 0; uint max = 0;
for (int i = 0; i < games.count; i++) for (int i = 0; i < games.count; i++)
{ {
if (games[i].ID.entityID > max) if (gamesB[i].ID.entityID > max)
{ {
max = games[i].ID.entityID; max = gamesB[i].ID.entityID;
} }
} }
return max; return max;
@ -118,11 +119,12 @@ namespace GamecraftModdingAPI.App
{ {
EntityCollection<MyGamesSlotEntityViewStruct> entities = EntityCollection<MyGamesSlotEntityViewStruct> entities =
entitiesDB.QueryEntities<MyGamesSlotEntityViewStruct>(MyGamesScreenExclusiveGroups.GameSlotGuiEntities); entitiesDB.QueryEntities<MyGamesSlotEntityViewStruct>(MyGamesScreenExclusiveGroups.GameSlotGuiEntities);
var entitiesB = entities.ToBuffer().buffer;
for (int i = 0; i < entities.count; i++) for (int i = 0; i < entities.count; i++)
{ {
if (entities[i].ID.entityID == id.entityID) if (entitiesB[i].ID.entityID == id.entityID)
{ {
return ref entities[i]; return ref entitiesB[i];
} }
} }
MyGamesSlotEntityViewStruct[] defRef = new MyGamesSlotEntityViewStruct[1]; MyGamesSlotEntityViewStruct[] defRef = new MyGamesSlotEntityViewStruct[1];

View file

@ -3,12 +3,12 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Emit; using System.Reflection.Emit;
using Gamecraft.Blocks.BlockGroups;
using Svelto.ECS; using Svelto.ECS;
using Svelto.ECS.EntityStructs; using Svelto.ECS.EntityStructs;
using RobocraftX.Common; using RobocraftX.Common;
using RobocraftX.Blocks; using RobocraftX.Blocks;
using Unity.Mathematics; using Unity.Mathematics;
using Unity.Entities;
using Gamecraft.Blocks.GUI; using Gamecraft.Blocks.GUI;
using GamecraftModdingAPI.Blocks; using GamecraftModdingAPI.Blocks;
@ -29,6 +29,7 @@ namespace GamecraftModdingAPI
protected static readonly SignalEngine SignalEngine = new SignalEngine(); protected static readonly SignalEngine SignalEngine = new SignalEngine();
protected static readonly BlockEventsEngine BlockEventsEngine = new BlockEventsEngine(); protected static readonly BlockEventsEngine BlockEventsEngine = new BlockEventsEngine();
protected static readonly ScalingEngine ScalingEngine = new ScalingEngine(); protected static readonly ScalingEngine ScalingEngine = new ScalingEngine();
protected static readonly BlockCloneEngine BlockCloneEngine = new BlockCloneEngine();
protected internal static readonly BlockEngine BlockEngine = new BlockEngine(); protected internal static readonly BlockEngine BlockEngine = new BlockEngine();
@ -36,16 +37,11 @@ namespace GamecraftModdingAPI
/// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position. /// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position.
/// Place blocks next to each other to connect them. /// Place blocks next to each other to connect them.
/// The placed block will be a complete block with a placement grid and collision which will be saved along with the game. /// The placed block will be a complete block with a placement grid and collision which will be saved along with the game.
/// <para></para>
/// <para>When placing multiple blocks, do not access properties immediately after creation as this
/// triggers a sync each time which can affect performance and may cause issues with the game.
/// You may either use AsyncUtils.WaitForSubmission() after placing all of the blocks
/// or simply access the block properties which will trigger the synchronization the first time a property is used.</para>
/// </summary> /// </summary>
/// <param name="block">The block's type</param> /// <param name="block">The block's type</param>
/// <param name="color">The block's color</param> /// <param name="color">The block's color</param>
/// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param> /// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param>
/// <param name="position">The block's position in the grid - default block size is 0.2</param> /// <param name="position">The block's position - default block size is 0.2</param>
/// <param name="rotation">The block's rotation in degrees</param> /// <param name="rotation">The block's rotation in degrees</param>
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param> /// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param>
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param> /// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param>
@ -66,7 +62,7 @@ namespace GamecraftModdingAPI
/// <param name="block">The block's type</param> /// <param name="block">The block's type</param>
/// <param name="color">The block's color</param> /// <param name="color">The block's color</param>
/// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param> /// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param>
/// <param name="position">The block's position in the grid - default block size is 0.2</param> /// <param name="position">The block's position - default block size is 0.2</param>
/// <param name="rotation">The block's rotation in degrees</param> /// <param name="rotation">The block's rotation in degrees</param>
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param> /// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param>
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param> /// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param>
@ -118,25 +114,35 @@ namespace GamecraftModdingAPI
private static Dictionary<Type, Func<EGID, Block>> initializers = new Dictionary<Type, Func<EGID, Block>>(); private static Dictionary<Type, Func<EGID, Block>> initializers = new Dictionary<Type, Func<EGID, Block>>();
private static Dictionary<Type, ExclusiveGroupStruct[]> typeToGroup = private static Dictionary<Type, ExclusiveBuildGroup[]> typeToGroup =
new Dictionary<Type, ExclusiveGroupStruct[]> new Dictionary<Type, ExclusiveBuildGroup[]>
{ {
{typeof(ConsoleBlock), new[] {CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP}}, {typeof(ConsoleBlock), new[] {CommonExclusiveGroups.CONSOLE_BLOCK_GROUP}},
{typeof(LogicGate), new [] {CommonExclusiveGroups.BUILD_LOGIC_BLOCK_GROUP}}, {typeof(LogicGate), new [] {CommonExclusiveGroups.LOGIC_BLOCK_GROUP}},
{typeof(Motor), new[] {CommonExclusiveGroups.BUILD_MOTOR_BLOCK_GROUP}}, {typeof(Motor), new[] {CommonExclusiveGroups.MOTOR_BLOCK_GROUP}},
{typeof(MusicBlock), new[] {CommonExclusiveGroups.BUILD_MUSIC_BLOCK_GROUP}}, {typeof(MusicBlock), new[] {CommonExclusiveGroups.MUSIC_BLOCK_GROUP}},
{typeof(Piston), new[] {CommonExclusiveGroups.BUILD_PISTON_BLOCK_GROUP}}, {typeof(ObjectIdentifier), new[]{CommonExclusiveGroups.OBJID_BLOCK_GROUP}},
{typeof(Servo), new[] {CommonExclusiveGroups.BUILD_SERVO_BLOCK_GROUP}}, {typeof(Piston), new[] {CommonExclusiveGroups.PISTON_BLOCK_GROUP}},
{typeof(Servo), new[] {CommonExclusiveGroups.SERVO_BLOCK_GROUP}},
{ {
typeof(SpawnPoint), typeof(SpawnPoint),
new[] new[]
{ {
CommonExclusiveGroups.BUILD_SPAWNPOINT_BLOCK_GROUP, CommonExclusiveGroups.SPAWNPOINT_BLOCK_GROUP,
CommonExclusiveGroups.BUILD_BUILDINGSPAWN_BLOCK_GROUP CommonExclusiveGroups.BUILDINGSPAWN_BLOCK_GROUP
} }
}, },
{typeof(TextBlock), new[] {CommonExclusiveGroups.BUILD_TEXT_BLOCK_GROUP}}, {
{typeof(Timer), new[] {CommonExclusiveGroups.BUILD_TIMER_BLOCK_GROUP}} typeof(SfxBlock),
new[]
{
CommonExclusiveGroups.SIMPLESFX_BLOCK_GROUP,
CommonExclusiveGroups.LOOPEDSFX_BLOCK_GROUP
}
},
{typeof(DampedSpring), new [] {CommonExclusiveGroups.DAMPEDSPRING_BLOCK_GROUP}},
{typeof(TextBlock), new[] {CommonExclusiveGroups.TEXT_BLOCK_GROUP}},
{typeof(Timer), new[] {CommonExclusiveGroups.TIMER_BLOCK_GROUP}}
}; };
/// <summary> /// <summary>
@ -184,7 +190,7 @@ namespace GamecraftModdingAPI
type); type);
ILGenerator il = dynamic.GetILGenerator(); ILGenerator il = dynamic.GetILGenerator();
il.DeclareLocal(type); //il.DeclareLocal(type);
il.Emit(OpCodes.Ldarg_0); //Load EGID and pass to constructor il.Emit(OpCodes.Ldarg_0); //Load EGID and pass to constructor
il.Emit(OpCodes.Newobj, ctor); //Call constructor il.Emit(OpCodes.Newobj, ctor); //Call constructor
//il.Emit(OpCodes.Stloc_0); - doesn't seem like we need these //il.Emit(OpCodes.Stloc_0); - doesn't seem like we need these
@ -224,6 +230,7 @@ namespace GamecraftModdingAPI
public EGID Id { get; } public EGID Id { get; }
internal BlockEngine.BlockInitData InitData; internal BlockEngine.BlockInitData InitData;
private EGID copiedFrom;
/// <summary> /// <summary>
/// The block's current position or zero if the block no longer exists. /// The block's current position or zero if the block no longer exists.
@ -235,6 +242,9 @@ namespace GamecraftModdingAPI
set set
{ {
MovementEngine.MoveBlock(Id, InitData, value); MovementEngine.MoveBlock(Id, InitData, value);
if (blockGroup != null)
blockGroup.PosAndRotCalculated = false;
BlockEngine.UpdateDisplayedBlock(Id);
} }
} }
@ -247,6 +257,9 @@ namespace GamecraftModdingAPI
set set
{ {
RotationEngine.RotateBlock(Id, InitData, value); RotationEngine.RotateBlock(Id, InitData, value);
if (blockGroup != null)
blockGroup.PosAndRotCalculated = false;
BlockEngine.UpdateDisplayedBlock(Id);
} }
} }
@ -262,6 +275,7 @@ namespace GamecraftModdingAPI
BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, float3 val) => st.scale = val, value); BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, float3 val) => st.scale = val, value);
if (!Exists) return; //UpdateCollision needs the block to exist if (!Exists) return; //UpdateCollision needs the block to exist
ScalingEngine.UpdateCollision(Id); ScalingEngine.UpdateCollision(Id);
BlockEngine.UpdateDisplayedBlock(Id);
} }
} }
@ -307,9 +321,10 @@ namespace GamecraftModdingAPI
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, BlockColor val) => BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, BlockColor val) =>
{ {
color.indexInPalette = (byte) (val.Color + val.Darkness * 10); color.indexInPalette = (byte) (val.Color + val.Darkness * 10);
color.overridePaletteColour = false; //color.overridePaletteColour = false;
color.needsUpdate = true; //color.needsUpdate = true;
BlockEngine.SetBlockColorFromPalette(ref color); color.hasNetworkChange = true;
color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette);
}, value); }, value);
} }
} }
@ -319,14 +334,15 @@ namespace GamecraftModdingAPI
/// </summary> /// </summary>
public float4 CustomColor public float4 CustomColor
{ {
get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.overriddenColour); get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.paletteColour);
set set
{ {
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) => BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) =>
{ {
color.overriddenColour = val; color.paletteColour = val;
color.overridePaletteColour = true; //color.overridePaletteColour = true;
color.needsUpdate = true; //color.needsUpdate = true;
color.hasNetworkChange = true;
}, value); }, value);
} }
} }
@ -347,6 +363,41 @@ namespace GamecraftModdingAPI
} }
} }
private BlockGroup blockGroup;
/// <summary>
/// Returns the block group this block is a part of. Block groups can also be placed using blueprints.
/// Returns null if not part of a group.<br />
/// Setting the group after the block has been initialized will not update everything properly,
/// so you can only set this property on blocks newly placed by your code.<br />
/// To set it for existing blocks, you can use the Copy() method and set the property on the resulting block
/// (and remove this block).
/// </summary>
public BlockGroup BlockGroup
{
get
{
if (blockGroup != null) return blockGroup;
return blockGroup = BlockEngine.GetBlockInfo(this,
(BlockGroupEntityComponent bgec) =>
bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this));
}
set
{
if (Exists)
{
Logging.LogWarning("Attempted to set group of existing block. This is not supported."
+ " Copy the block and set the group of the resulting block.");
return;
}
blockGroup?.RemoveInternal(this);
BlockEngine.SetBlockInfo(this,
(ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1,
value);
value?.AddInternal(this);
blockGroup = value;
}
}
/// <summary> /// <summary>
/// Whether the block exists. The other properties will return a default value if the block doesn't exist. /// Whether the block exists. The other properties will return a default value if the block doesn't exist.
/// If the block was just placed, then this will also return false but the properties will work correctly. /// If the block was just placed, then this will also return false but the properties will work correctly.
@ -368,11 +419,34 @@ namespace GamecraftModdingAPI
/// Returns the rigid body of the chunk of blocks this one belongs to during simulation. /// Returns the rigid body of the chunk of blocks this one belongs to during simulation.
/// Can be used to apply forces or move the block around while the simulation is running. /// Can be used to apply forces or move the block around while the simulation is running.
/// </summary> /// </summary>
/// <returns>The SimBody of the chunk or null if the block doesn't exist.</returns> /// <returns>The SimBody of the chunk or null if the block doesn't exist or not in simulation mode.</returns>
public SimBody GetSimBody() public SimBody GetSimBody()
{ {
return BlockEngine.GetBlockInfo(this, return BlockEngine.GetBlockInfo(this,
(GridConnectionsEntityStruct st) => new SimBody(st.machineRigidBodyId, st.clusterId)); (GridConnectionsEntityStruct st) => st.machineRigidBodyId != uint.MaxValue
? new SimBody(st.machineRigidBodyId, st.clusterId)
: null);
}
/// <summary>
/// Creates a copy of the block in the game with the same properties, stats and wires.
/// </summary>
/// <returns></returns>
public T Copy<T>() where T : Block
{
var block = PlaceNew<T>(Type, Position, Rotation, Color.Color, Color.Darkness, UniformScale, Scale);
block.copiedFrom = Id;
if (Type == BlockIDs.ConsoleBlock
&& (this is ConsoleBlock srcCB || (srcCB = Specialise<ConsoleBlock>()) != null)
&& (block is ConsoleBlock dstCB || (dstCB = block.Specialise<ConsoleBlock>()) != null))
{
//Console block properties are set by a separate engine in the game
dstCB.Arg1 = srcCB.Arg1;
dstCB.Arg2 = srcCB.Arg2;
dstCB.Arg3 = srcCB.Arg3;
dstCB.Command = srcCB.Command;
}
return block;
} }
private void OnPlacedInit(object sender, BlockPlacedRemovedEventArgs e) private void OnPlacedInit(object sender, BlockPlacedRemovedEventArgs e)
@ -380,6 +454,8 @@ namespace GamecraftModdingAPI
if (e.ID != Id) return; if (e.ID != Id) return;
Placed -= OnPlacedInit; //And we can reference it Placed -= OnPlacedInit; //And we can reference it
InitData = default; //Remove initializer as it's no longer valid - if the block gets removed it shouldn't be used again InitData = default; //Remove initializer as it's no longer valid - if the block gets removed it shouldn't be used again
if (copiedFrom != EGID.Empty)
BlockCloneEngine.CopyBlockStats(copiedFrom, Id);
} }
public override string ToString() public override string ToString()
@ -422,6 +498,7 @@ namespace GamecraftModdingAPI
GameEngineManager.AddGameEngine(BlockEventsEngine); GameEngineManager.AddGameEngine(BlockEventsEngine);
GameEngineManager.AddGameEngine(ScalingEngine); GameEngineManager.AddGameEngine(ScalingEngine);
GameEngineManager.AddGameEngine(SignalEngine); GameEngineManager.AddGameEngine(SignalEngine);
GameEngineManager.AddGameEngine(BlockCloneEngine);
Wire.signalEngine = SignalEngine; // requires same functionality, no need to duplicate the engine Wire.signalEngine = SignalEngine; // requires same functionality, no need to duplicate the engine
} }
@ -439,7 +516,12 @@ namespace GamecraftModdingAPI
//Lets improve that using delegates //Lets improve that using delegates
var block = New<T>(Id.entityID, Id.groupID); var block = New<T>(Id.entityID, Id.groupID);
if (this.InitData.Group != null)
{
block.InitData = this.InitData; block.InitData = this.InitData;
Placed += block.OnPlacedInit; //Reset InitData of new object
}
return block; return block;
} }
@ -452,9 +534,5 @@ namespace GamecraftModdingAPI
} }
} }
#endif #endif
internal static void Setup(World physicsWorld)
{
ScalingEngine.Setup(physicsWorld.EntityManager);
}
} }
} }

View file

@ -0,0 +1,216 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Gamecraft.Blocks.BlockGroups;
using Unity.Mathematics;
using UnityEngine;
using GamecraftModdingAPI.Blocks;
using GamecraftModdingAPI.Utility;
namespace GamecraftModdingAPI
{
/// <summary>
/// A group of blocks that can be selected together. The placed version of blueprints. Dispose after usage.
/// </summary>
public class BlockGroup : ICollection<Block>, IDisposable
{
internal static BlueprintEngine _engine = new BlueprintEngine();
public int Id { get; }
private readonly Block sourceBlock;
private readonly List<Block> blocks;
private float3 position, rotation;
internal bool PosAndRotCalculated;
internal BlockGroup(int id, Block block)
{
if (id == BlockGroupUtility.GROUP_UNASSIGNED)
throw new BlockException("Cannot create a block group for blocks without a group!");
Id = id;
sourceBlock = block;
blocks = new List<Block>(GetBlocks());
Block.Removed += OnBlockRemoved;
}
private void OnBlockRemoved(object sender, BlockPlacedRemovedEventArgs e)
{
//blocks.RemoveAll(block => block.Id == e.ID); - Allocation heavy
int index = -1;
for (int i = 0; i < blocks.Count; i++)
{
if (blocks[i].Id == e.ID)
{
index = i;
break;
}
}
if (index != -1) blocks.RemoveAt(index);
}
public void Dispose()
{
Block.Removed -= OnBlockRemoved;
}
/// <summary>
/// The position of the block group (center). Can only be used after initialization is complete.
/// </summary>
public float3 Position
{
get
{
if (!PosAndRotCalculated)
Refresh();
return position;
}
set
{
var diff = value - position;
foreach (var block in blocks)
block.Position += diff;
if (!PosAndRotCalculated) //The condition can only be true if a block has been added/removed manually
Refresh(); //So the blocks array is up to date
else
position += diff;
}
}
/// <summary>
/// The rotation of the block group. Can only be used after initialization is complete.
/// </summary>
public float3 Rotation
{
get
{
if (!PosAndRotCalculated)
Refresh();
return rotation;
}
set
{
var diff = value - rotation;
var qdiff = Quaternion.Euler(diff);
foreach (var block in blocks)
{
block.Rotation += diff;
block.Position = qdiff * block.Position;
}
if (!PosAndRotCalculated)
Refresh();
else
rotation += diff;
}
}
/*/// <summary>
/// Removes all of the blocks in this group from the world.
/// </summary>
public void RemoveBlocks()
{
_engine.RemoveBlockGroup(Id); - TODO: Causes a hard crash
}*/
/// <summary>
/// Creates a new block group consisting of a single block.
/// You can add more blocks using the Add() method or by setting the BlockGroup property of the blocks.<br />
/// Note that only newly placed blocks can be added to groups.
/// </summary>
/// <param name="block">The block to add</param>
/// <returns>A new block group containing the given block</returns>
public static BlockGroup Create(Block block)
{
var bg = new BlockGroup(_engine.CreateBlockGroup(block.Position, Quaternion.Euler(block.Rotation)), block);
block.BlockGroup = bg;
return bg;
}
/// <summary>
/// Collects each block that is a part of this group. Also sets the position and rotation.
/// </summary>
/// <returns>An array of blocks</returns>
private Block[] GetBlocks()
{
if (!sourceBlock.Exists) return new[] {sourceBlock}; //The block must exist to get the others
var ret = _engine.GetBlocksFromGroup(sourceBlock.Id, out var pos, out var rot);
position = pos;
rotation = ((Quaternion) rot).eulerAngles;
PosAndRotCalculated = true;
return ret;
}
private void Refresh()
{
blocks.Clear();
blocks.AddRange(GetBlocks());
}
internal static void Init()
{
GameEngineManager.AddGameEngine(_engine);
}
public IEnumerator<Block> GetEnumerator() => blocks.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => blocks.GetEnumerator();
/// <summary>
/// Adds a block to the group. You can only add newly placed blocks
/// so that the game initializes the group membership properly.
/// </summary>
/// <param name="item"></param>
/// <exception cref="NullReferenceException"></exception>
public void Add(Block item)
{
if (item == null) throw new NullReferenceException("Cannot add null to a block group");
item.BlockGroup = this; //Calls AddInternal
}
internal void AddInternal(Block item)
{
blocks.Add(item);
_engine.AddBlockToGroup(item.Id, Id);
}
/// <summary>
/// Removes all blocks from this group.
/// You cannot remove blocks that have been initialized, only those that you placed recently.
/// </summary>
public void Clear()
{
while (blocks.Count > 0)
Remove(blocks[blocks.Count - 1]);
}
public bool Contains(Block item) => blocks.Contains(item);
public void CopyTo(Block[] array, int arrayIndex) => blocks.CopyTo(array, arrayIndex);
/// <summary>
/// Removes a block from this group.
/// You cannot remove blocks that have been initialized, only those that you placed recently.
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
public bool Remove(Block item)
{
if (item == null) throw new NullReferenceException("Cannot remove null from a block group");
bool ret = item.BlockGroup == this;
if (ret)
item.BlockGroup = null; //Calls RemoveInternal
return ret;
}
internal void RemoveInternal(Block item) => blocks.Remove(item);
public int Count => blocks.Count;
public bool IsReadOnly { get; } = false;
public Block this[int index] => blocks[index]; //Setting is not supported, since the order doesn't matter
public override string ToString()
{
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Rotation)}: {Rotation}, {nameof(Count)}: {Count}";
}
}
}

View file

@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Gamecraft.Wires;
using GamecraftModdingAPI.Engines;
using HarmonyLib;
using RobocraftX.Blocks;
using RobocraftX.Character;
using RobocraftX.Common;
using RobocraftX.Common.Players;
using Svelto.DataStructures;
using Svelto.ECS;
namespace GamecraftModdingAPI.Blocks
{
public class BlockCloneEngine : IApiEngine
{
private static Type copyEngineType =
AccessTools.TypeByName("Gamecraft.GUI.Tweaks.Engines.CopyTweaksOnPickEngine");
private static Type copyWireEngineType =
AccessTools.TypeByName("Gamecraft.Wires.WireConnectionCopyOnPickEngine");
private static Type createWireEngineType =
AccessTools.TypeByName("RobocraftX.GUI.Wires.WireConnectionCreateOnPlaceEngine");
private MethodBase copyFromBlock = AccessTools.Method(copyEngineType, "CopyTweaksFromBlock");
private MethodBase copyToBlock = AccessTools.Method(copyEngineType, "ApplyTweaksToPlacedBlock");
private MethodBase copyWireFromBlock = AccessTools.Method(copyWireEngineType, "CopyWireInputsAndOutputs");
private MethodBase copyWireToBlock = AccessTools.Method(createWireEngineType, "PlaceWiresOnPlaceNewCube");
public void Ready()
{
}
public EntitiesDB entitiesDB { get; set; }
public void Dispose()
{
}
public void CopyBlockStats(EGID sourceID, EGID targetID)
{
var allCharacters = (LocalFasterReadOnlyList<ExclusiveGroupStruct>) CharacterExclusiveGroups.AllCharacters;
foreach (var ((pickedBlockColl, count), _) in entitiesDB.QueryEntities<PickedBlockExtraDataStruct>(allCharacters))
{
for (int i = 0; i < count; ++i)
{
ref PickedBlockExtraDataStruct pickedBlock = ref pickedBlockColl[i];
var oldStruct = pickedBlock;
pickedBlock.pickedBlockEntityID = sourceID;
pickedBlock.placedBlockEntityID = targetID;
pickedBlock.placedBlockTweaksCopied = false;
pickedBlock.placedBlockTweaksMustCopy = true;
if (entitiesDB.Exists<DBEntityStruct>(pickedBlock.pickedBlockEntityID)
&& entitiesDB.Exists<DBEntityStruct>(pickedBlock.placedBlockEntityID))
{
copyFromBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock});
uint playerID = Player.LocalPlayer.Id;
var parameters = new object[] {playerID, pickedBlock};
copyWireFromBlock.Invoke(Patch.copyWireEngine, parameters);
pickedBlock = (PickedBlockExtraDataStruct) parameters[1]; //ref arg
copyToBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock});
ExclusiveGroupStruct group = WiresExclusiveGroups.WIRES_COPY_GROUP + playerID;
copyWireToBlock.Invoke(Patch.createWireEngine, new object[] {group, pickedBlock.ID});
pickedBlock.placedBlockTweaksMustCopy = false;
pickedBlock.placedBlockTweaksCopied = false;
}
pickedBlock = oldStruct; //Make sure to not interfere with the game - Although that might not be the case with the wire copying
}
}
}
[HarmonyPatch]
private static class Patch
{
public static object copyEngine;
public static object copyWireEngine;
public static object createWireEngine;
public static void Postfix(object __instance)
{
if (__instance.GetType() == copyEngineType)
copyEngine = __instance;
else if (__instance.GetType() == copyWireEngineType)
copyWireEngine = __instance;
else if (__instance.GetType() == createWireEngineType)
createWireEngine = __instance;
}
public static IEnumerable<MethodBase> TargetMethods()
{
return new[]
{
AccessTools.GetDeclaredConstructors(copyEngineType)[0],
AccessTools.GetDeclaredConstructors(copyWireEngineType)[0],
AccessTools.GetDeclaredConstructors(createWireEngineType)[0]
};
}
}
public string Name { get; } = "GamecraftModdingAPIBlockCloneGameEngine";
public bool isRemovable { get; } = false;
}
}

View file

@ -1,10 +1,17 @@
namespace GamecraftModdingAPI.Blocks using System;
using Unity.Mathematics;
namespace GamecraftModdingAPI.Blocks
{ {
public struct BlockColor public struct BlockColor
{ {
public BlockColors Color; public BlockColors Color;
public byte Darkness; public byte Darkness;
public byte Index => Color == BlockColors.Default
? byte.MaxValue
: (byte) (Darkness * 10 + Color);
public BlockColor(byte index) public BlockColor(byte index)
{ {
if (index == byte.MaxValue) if (index == byte.MaxValue)
@ -14,6 +21,8 @@
} }
else else
{ {
if (index > 99)
throw new ArgumentOutOfRangeException(nameof(index), "Invalid color index. Must be 0-90 or 255.");
Color = (BlockColors) (index % 10); Color = (BlockColors) (index % 10);
Darkness = (byte) (index / 10); Darkness = (byte) (index / 10);
} }
@ -21,10 +30,14 @@
public BlockColor(BlockColors color, byte darkness) public BlockColor(BlockColors color, byte darkness)
{ {
if (darkness > 9)
throw new ArgumentOutOfRangeException(nameof(darkness), "Darkness must be 0-9 where 0 is default.");
Color = color; Color = color;
Darkness = darkness; Darkness = darkness;
} }
public float4 RGBA => Block.BlockEngine.ConvertBlockColor(Index);
public override string ToString() public override string ToString()
{ {
return $"{nameof(Color)}: {Color}, {nameof(Darkness)}: {Darkness}"; return $"{nameof(Color)}: {Color}, {nameof(Darkness)}: {Darkness}";

View file

@ -2,15 +2,19 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Gamecraft.ColourPalette;
using Gamecraft.TimeRunning;
using Gamecraft.Wires; using Gamecraft.Wires;
using RobocraftX.Blocks; using RobocraftX.Blocks;
using RobocraftX.Common; using RobocraftX.Common;
using RobocraftX.GUI.Hotbar.Colours;
using RobocraftX.Physics; using RobocraftX.Physics;
using RobocraftX.Scene.Simulation; using RobocraftX.Rendering;
using Svelto.ECS.EntityStructs;
using Svelto.DataStructures; using Svelto.DataStructures;
using Svelto.ECS; using Svelto.ECS;
using Svelto.ECS.Hybrid; using Svelto.ECS.Hybrid;
using Unity.Mathematics;
using GamecraftModdingAPI.Engines; using GamecraftModdingAPI.Engines;
@ -42,8 +46,14 @@ namespace GamecraftModdingAPI.Blocks
FasterList<EGID> cubes = new FasterList<EGID>(10); FasterList<EGID> cubes = new FasterList<EGID>(10);
var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>(); var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
foreach (var (ecoll, _) in coll) foreach (var (ecoll, _) in coll)
foreach (ref var conn in ecoll) {
var ecollB = ecoll.ToBuffer();
for(int i = 0; i < ecoll.count; i++)
{
ref var conn = ref ecollB.buffer[i];
conn.isProcessed = false; conn.isProcessed = false;
}
}
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes, ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes,
(in GridConnectionsEntityStruct g) => { return false; }); (in GridConnectionsEntityStruct g) => { return false; });
@ -54,12 +64,10 @@ namespace GamecraftModdingAPI.Blocks
return ret; return ret;
} }
public void SetBlockColorFromPalette(ref ColourParameterEntityStruct color) public float4 ConvertBlockColor(byte index) => index == byte.MaxValue
{ ? new float4(-1f, -1f, -1f, -1f)
ref var paletteEntry = ref entitiesDB.QueryEntity<PaletteEntryEntityStruct>(color.indexInPalette, : entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
CommonExclusiveGroups.COLOUR_PALETTE_GROUP); CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
color.paletteColour = paletteEntry.Colour;
}
public ref T GetBlockInfo<T>(EGID blockID) where T : unmanaged, IEntityComponent public ref T GetBlockInfo<T>(EGID blockID) where T : unmanaged, IEntityComponent
{ {
@ -69,17 +77,17 @@ namespace GamecraftModdingAPI.Blocks
return ref structHolder[0]; //Gets a default value automatically return ref structHolder[0]; //Gets a default value automatically
} }
public ref T GetBlockInfoViewStruct<T>(EGID blockID) where T : struct, INeedEGID, IEntityComponent public ref T GetBlockInfoViewStruct<T>(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent
{ {
if (entitiesDB.Exists<T>(blockID)) if (entitiesDB.Exists<T>(blockID))
{ {
// TODO: optimize by using EntitiesDB internal calls instead of iterating over everything // TODO: optimize by using EntitiesDB internal calls instead of iterating over everything
EntityCollection<T> entities = entitiesDB.QueryEntities<T>(blockID.groupID); BT<MB<T>> entities = entitiesDB.QueryEntities<T>(blockID.groupID).ToBuffer();
for (int i = 0; i < entities.count; i++) for (int i = 0; i < entities.count; i++)
{ {
if (entities[i].ID == blockID) if (entities.buffer[i].ID == blockID)
{ {
return ref entities[i]; return ref entities.buffer[i];
} }
} }
} }
@ -143,6 +151,15 @@ namespace GamecraftModdingAPI.Blocks
} }
} }
public void UpdateDisplayedBlock(EGID id)
{
if (!BlockExists(id)) return;
var pos = entitiesDB.QueryEntity<PositionEntityStruct>(id);
var rot = entitiesDB.QueryEntity<RotationEntityStruct>(id);
var scale = entitiesDB.QueryEntity<ScalingEntityStruct>(id);
entitiesDB.QueryEntity<RenderingDataStruct>(id).matrix = float4x4.TRS(pos.position, rot.rotation, scale.scale);
}
public bool BlockExists(EGID blockID) public bool BlockExists(EGID blockID)
{ {
return entitiesDB.Exists<DBEntityStruct>(blockID); return entitiesDB.Exists<DBEntityStruct>(blockID);
@ -161,43 +178,55 @@ namespace GamecraftModdingAPI.Blocks
public SimBody[] GetSimBodiesFromID(byte id) public SimBody[] GetSimBodiesFromID(byte id)
{ {
var ret = new FasterList<SimBody>(4); var ret = new FasterList<SimBody>(4);
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP)) var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>();
return new SimBody[0]; EGIDMapper<GridConnectionsEntityStruct>? connections = null;
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP); foreach (var ((oids, count), _) in oide)
var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP);
foreach (ref ObjectIdEntityStruct oid in oids)
{ {
for (int i = 0; i < count; i++)
{
ref ObjectIdEntityStruct oid = ref oids[i];
if (oid.objectId != id) continue; if (oid.objectId != id) continue;
var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId; if (!connections.HasValue) //Would need reflection to get the group from the build group otherwise
connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(oid.ID.groupID);
var rid = connections.Value.Entity(oid.ID.entityID).machineRigidBodyId;
foreach (var rb in ret) foreach (var rb in ret)
{ {
if (rb.Id.entityID == rid) if (rb.Id.entityID == rid)
goto DUPLICATE; //Multiple Object Identifiers on one rigid body goto DUPLICATE; //Multiple Object Identifiers on one rigid body
} }
ret.Add(new SimBody(rid)); ret.Add(new SimBody(rid));
DUPLICATE: ; DUPLICATE: ;
} }
}
return ret.ToArray(); return ret.ToArray();
} }
public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim) public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim)
{ {
var ret = new FasterList<ObjectIdentifier>(4); var ret = new FasterList<ObjectIdentifier>(4);
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP)) var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>();
return new ObjectIdentifier[0]; foreach (var ((oids, count), _) in oide)
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP); {
foreach (ref ObjectIdEntityStruct oid in oids) for (int i = 0; i < count; i++)
{
ref ObjectIdEntityStruct oid = ref oids[i];
if (sim ? oid.simObjectId == id : oid.objectId == id) if (sim ? oid.simObjectId == id : oid.objectId == id)
ret.Add(new ObjectIdentifier(oid.ID)); ret.Add(new ObjectIdentifier(oid.ID));
}
}
return ret.ToArray(); return ret.ToArray();
} }
public SimBody[] GetConnectedSimBodies(uint id) public SimBody[] GetConnectedSimBodies(uint id)
{ {
var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP); var joints = entitiesDB.QueryEntities<JointEntityStruct>(MachineSimulationGroups.JOINTS_GROUP).ToBuffer();
var list = new FasterList<SimBody>(4); var list = new FasterList<SimBody>(4);
foreach (var joint in joints) for (int i = 0; i < joints.count; i++)
{ {
ref var joint = ref joints.buffer[i];
if (joint.jointState == JointState.Broken) continue; if (joint.jointState == JointState.Broken) continue;
if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB)); if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB));
else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA)); else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA));
@ -212,14 +241,16 @@ namespace GamecraftModdingAPI.Blocks
var bodies = new HashSet<uint>(); var bodies = new HashSet<uint>();
foreach (var (coll, _) in groups) foreach (var (coll, _) in groups)
{ {
foreach (var conn in coll) var array = coll.ToBuffer().buffer;
for (var index = 0; index < array.capacity; index++)
{ {
var conn = array[index];
if (conn.clusterId == cid) if (conn.clusterId == cid)
bodies.Add(conn.machineRigidBodyId); bodies.Add(conn.machineRigidBodyId);
} }
} }
return bodies.Select(id => new SimBody(id)).ToArray(); return bodies.Select(id => new SimBody(id, cid)).ToArray();
} }
public EGID? FindBlockEGID(uint id) public EGID? FindBlockEGID(uint id)
@ -239,9 +270,12 @@ namespace GamecraftModdingAPI.Blocks
var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>(); var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
foreach (var (coll, _) in groups) foreach (var (coll, _) in groups)
{ {
foreach (var conn in coll) var array = coll.ToBuffer().buffer;
for (var index = 0; index < array.capacity; index++)
{ {
if (conn.machineRigidBodyId == sbid) var conn = array[index];
//Static blocks don't have a cluster ID but the cluster destruction manager should have one
if (conn.machineRigidBodyId == sbid && conn.clusterId != uint.MaxValue)
return new Cluster(conn.clusterId); return new Cluster(conn.clusterId);
} }
} }
@ -249,6 +283,24 @@ namespace GamecraftModdingAPI.Blocks
return null; return null;
} }
public Block[] GetBodyBlocks(uint sbid)
{
var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
var set = new HashSet<Block>();
foreach (var (coll, _) in groups)
{
var array = coll.ToBuffer().buffer;
for (var index = 0; index < array.capacity; index++)
{
var conn = array[index];
if (conn.machineRigidBodyId == sbid)
set.Add(new Block(conn.ID));
}
}
return set.ToArray();
}
#if DEBUG #if DEBUG
public EntitiesDB GetEntitiesDB() public EntitiesDB GetEntitiesDB()
{ {

View file

@ -14,10 +14,10 @@ namespace GamecraftModdingAPI.Blocks
/// </summary> /// </summary>
internal struct BlockInitData internal struct BlockInitData
{ {
public FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> Group; public FasterDictionary<RefWrapperType, ITypeSafeDictionary> Group;
} }
internal delegate FasterDictionary<RefWrapper<Type>, ITypeSafeDictionary> GetInitGroup( internal delegate FasterDictionary<RefWrapperType, ITypeSafeDictionary> GetInitGroup(
EntityComponentInitializer initializer); EntityComponentInitializer initializer);
/// <summary> /// <summary>

View file

@ -5,10 +5,11 @@ using Svelto.ECS;
using GamecraftModdingAPI.Engines; using GamecraftModdingAPI.Engines;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
using RobocraftX.Blocks;
namespace GamecraftModdingAPI.Blocks namespace GamecraftModdingAPI.Blocks
{ {
public class BlockEventsEngine : IReactionaryEngine<DBEntityStruct> public class BlockEventsEngine : IReactionaryEngine<BlockTagEntityStruct>
{ {
public event EventHandler<BlockPlacedRemovedEventArgs> Placed; public event EventHandler<BlockPlacedRemovedEventArgs> Placed;
public event EventHandler<BlockPlacedRemovedEventArgs> Removed; public event EventHandler<BlockPlacedRemovedEventArgs> Removed;
@ -27,20 +28,20 @@ namespace GamecraftModdingAPI.Blocks
public bool isRemovable { get; } = false; public bool isRemovable { get; } = false;
private bool shouldAddRemove; private bool shouldAddRemove;
public void Add(ref DBEntityStruct entityComponent, EGID egid) public void Add(ref BlockTagEntityStruct entityComponent, EGID egid)
{ {
if (!(shouldAddRemove = !shouldAddRemove)) if (!(shouldAddRemove = !shouldAddRemove))
return; return;
ExceptionUtil.InvokeEvent(Placed, this, ExceptionUtil.InvokeEvent(Placed, this,
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); new BlockPlacedRemovedEventArgs {ID = egid});
} }
public void Remove(ref DBEntityStruct entityComponent, EGID egid) public void Remove(ref BlockTagEntityStruct entityComponent, EGID egid)
{ {
if (!(shouldAddRemove = !shouldAddRemove)) if (!(shouldAddRemove = !shouldAddRemove))
return; return;
ExceptionUtil.InvokeEvent(Removed, this, ExceptionUtil.InvokeEvent(Removed, this,
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); new BlockPlacedRemovedEventArgs {ID = egid});
} }
} }

View file

@ -228,7 +228,7 @@ namespace GamecraftModdingAPI.Blocks
ObjectiveHUD, ObjectiveHUD,
GameStatsHUD, //231 GameStatsHUD, //231
GameOverBlock, GameOverBlock,
SFXBlockGameplay=240, SFXBlockGameplay = 240,
SFXBlock8Bit, SFXBlock8Bit,
SFXBlockInstrument, SFXBlockInstrument,
SFXBlockSciFi, SFXBlockSciFi,
@ -248,7 +248,92 @@ namespace GamecraftModdingAPI.Blocks
PlasmaCannonBlock, PlasmaCannonBlock,
QuantumRiflePickup = 300, QuantumRiflePickup = 300,
QuantumRifleAmmoPickup, QuantumRifleAmmoPickup,
MagmaRockCube=777, AluminiumSlicedFraction,
AluminiumSlicedSlope,
AluminiumHalfPyramidLeft = 305,
AluminiumHalfPyramidRight,
AluminiumPyramidSliced,
AluminiumTubeCross,
AluminiumTubeT,
AluminiumPlateSquare,
AluminiumPlateCircle,
AluminiumPlateTriangle, //312
OiledSlicedFraction = 314,
OiledSlicedSlope,
OiledHalfPyramidLeft,
OiledHalfPyramidRight,
OiledPyramidSliced,
GlassSlicedFraction,
GlassSlicedSlope,
GlassHalfPyramidLeft,
GlassHalfPyramidRight,
GlassPyramidSliced,
RubberSlicedFraction,
RubberSlicedSlope,
RubberHalfPyramidLeft,
RubberHalfPyramidRight,
RubberPyramidSliced,
WoodSlicedFraction,
WoodSlicedSlope, //330
WoodHalfPyramidLeft,
WoodHalfPyramidRight,
WoodPyramidSliced,
HexNetSlicedFraction,
HexNetSlicedSlope,
HexNetHalfPyramidLeft,
HexNetHalfPyramidRight,
HexNetPyramidSliced,
OiledTubeCross,
OiledTubeT, //340
GlassTubeCross,
GlassTubeT,
RubberTubeCross,
RubberTubeT,
WoodTubeCross,
WoodTubeT,
HexNetTubeCross,
HexNetTubeT,
BouncyCube,
BouncySlicedCube, //350
BouncySlope,
BouncyCorner,
OiledTubeCorner,
GlassTubeCorner,
RubberTubeCorner,
WoodTubeCorner,
Basketball,
BowlingBall,
SoccerBall,
GolfBall, //360
HockeyPuck,
PoolBall,
BouncyBall,
TennisBall,
UnlitCube,
IronSlicedFraction,
IronSlicedSlope,
IronHalfPyramidLeft,
IronHalfPyramidRight,
IronPyramidSliced, //370
IronTubeCross,
IronTubeT,
SFXBlockMob = 374,
PointLight,
SpotLight,
SunLight,
AmbientLight,
UnlitGlowCube = 381,
PointLightInvisible,
SpotLightInvisible,
UnlitSlope,
UnlitGlowSlope,
Fog,
Sky,
GridCube,
GridSlicedCube,
GridSlope,
GridCorner,
MagmaRockCube = 777,
MagmaRockCubeSliced, MagmaRockCubeSliced,
MagmaRockSlope, MagmaRockSlope,
MagmaRockCorner, MagmaRockCorner,
@ -267,7 +352,7 @@ namespace GamecraftModdingAPI.Blocks
HexNetSlopeRounded, HexNetSlopeRounded,
HexNetCornerRounded, //794 HexNetCornerRounded, //794
MagmaRockBulgedInner, MagmaRockBulgedInner,
HexNetCylinder=797, HexNetCylinder = 797,
HexNetHemisphere, HexNetHemisphere,
HexNetSphere, HexNetSphere,
HexNetTubeCorner //800 HexNetTubeCorner //800

View file

@ -0,0 +1,319 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Gamecraft.Blocks.BlockGroups;
using Gamecraft.GUI.Blueprints;
using GamecraftModdingAPI.Engines;
using GamecraftModdingAPI.Utility;
using HarmonyLib;
using RobocraftX.Blocks;
using RobocraftX.Common;
using RobocraftX.CR.MachineEditing.BoxSelect;
using RobocraftX.CR.MachineEditing.BoxSelect.ClipboardOperations;
using Svelto.DataStructures;
using Svelto.ECS;
using Svelto.ECS.DataStructures;
using Svelto.ECS.EntityStructs;
using Svelto.ECS.Serialization;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using Allocator = Svelto.Common.Allocator;
namespace GamecraftModdingAPI.Blocks
{
public class BlueprintEngine : IFactoryEngine
{
private readonly MethodInfo getBlocksFromGroup =
AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup");
private NativeDynamicArray selectedBlocksInGroup;
private NativeHashSet<ulong> removedConnections = new NativeHashSet<ulong>();
private int addingToBlockGroup = -1;
private static readonly Type PlaceBlueprintUtilityType =
AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlueprintUtility");
private static readonly FieldInfo LocalBlockMap =
AccessTools.DeclaredField(PlaceBlueprintUtilityType, "_localBlockMap");
private static readonly MethodInfo BuildBlock = AccessTools.Method(PlaceBlueprintUtilityType, "BuildBlock");
private static readonly MethodInfo BuildWires = AccessTools.Method(PlaceBlueprintUtilityType, "BuildWires");
private static readonly Type SerializeGhostBlueprintType =
AccessTools.TypeByName("RobocraftX.CR.MachineEditing.BoxSelect.SerializeGhostChildrenOnAddEngine");
private static readonly MethodInfo SerializeGhostBlueprint =
AccessTools.Method(SerializeGhostBlueprintType, "SerializeClipboardGhostEntities");
private static NativeEntityRemove nativeRemove;
private static MachineGraphConnectionEntityFactory connectionFactory;
private static IEntityFunctions entityFunctions;
private static ClipboardSerializationDataResourceManager clipboardManager;
private static IEntitySerialization entitySerialization;
private static IEntityFactory entityFactory;
private static FasterList<EGID> globalBlockMap;
private static object SerializeGhostBlueprintInstance;
private static GhostChildEntityFactory BuildGhostBlueprintFactory;
public void Ready()
{
selectedBlocksInGroup = NativeDynamicArray.Alloc<EGID>(Allocator.Persistent);
}
public EntitiesDB entitiesDB { get; set; }
public void Dispose()
{
selectedBlocksInGroup.Dispose();
}
public Block[] GetBlocksFromGroup(EGID blockID, out float3 pos, out quaternion rot)
{
var blockPos = default(float3);
var blockRot = default(quaternion);
var parameters = new object[] {blockID, selectedBlocksInGroup, entitiesDB, blockPos, blockRot};
getBlocksFromGroup.Invoke(null, parameters);
pos = (float3) parameters[3];
rot = (quaternion) parameters[4];
int count = selectedBlocksInGroup.Count<EGID>();
var ret = new Block[count];
for (uint i = 0; i < count; i++)
ret[i] = new Block(selectedBlocksInGroup.Get<EGID>(i));
selectedBlocksInGroup.FastClear();
return ret;
}
public void RemoveBlockGroup(int id)
{
BlockGroupUtility.RemoveAllBlocksInBlockGroup(id, entitiesDB, removedConnections, nativeRemove,
connectionFactory, default).Complete();
}
public int CreateBlockGroup(float3 position, quaternion rotation)
{
int nextFilterId = BlockGroupUtility.NextFilterId;
Factory.BuildEntity<BlockGroupEntityDescriptor>((uint) nextFilterId,
BlockGroupExclusiveGroups.BlockGroupEntityGroup).Init(new BlockGroupTransformEntityComponent
{
blockGroupGridRotation = rotation,
blockGroupGridPosition = position
});
return nextFilterId;
}
public void AddBlockToGroup(EGID blockID, int groupID)
{
if (globalBlockMap == null)
globalBlockMap = FullGameFields._deserialisedBlockMap;
if (groupID != addingToBlockGroup)
{
Logging.MetaDebugLog("Changing current block group from " + addingToBlockGroup + " to " + groupID);
addingToBlockGroup = groupID;
globalBlockMap.Clear();
}
globalBlockMap.Add(blockID);
}
public void SelectBlueprint(uint resourceID)
{
if (resourceID == uint.MaxValue)
BlueprintUtil.UnselectBlueprint(entitiesDB);
else
BlueprintUtil.SelectBlueprint(entitiesDB, resourceID, false, -1);
}
public uint CreateBlueprint()
{
uint index = clipboardManager.AllocateSerializationData();
return index;
}
public void ReplaceBlueprint(uint playerID, uint blueprintID, ICollection<Block> selected, float3 pos, quaternion rot)
{
var blockIDs = new EGID[selected.Count];
using (var enumerator = selected.GetEnumerator())
{
for (var i = 0; enumerator.MoveNext(); i++)
{
var block = enumerator.Current;
blockIDs[i] = block.Id;
}
}
var serializationData = clipboardManager.GetSerializationData(blueprintID);
SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData, -1);
if (selected.Count == 0)
return;
//ref BlockGroupTransformEntityComponent groupTransform = ref EntityNativeDBExtensions.QueryEntity<BlockGroupTransformEntityComponent>(entitiesDb, (uint) local1.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
//ref ColliderAabb collider = ref EntityNativeDBExtensions.QueryEntity<ColliderAabb>(entitiesDB, (uint) groupID, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
//float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider);
//var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition;
//var rootRotation = groupTransform.blockGroupGridRotation;
clipboardManager.SetGhostSerialized(blueprintID, false);
SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB,
serializationData.blueprintData, entitySerialization, entityFactory, blockIDs,
(uint) blockIDs.Length, pos, rot, -1);
BuildGhostBlueprint(selected, pos, rot, playerID);
SerializeGhostBlueprint.Invoke(SerializeGhostBlueprintInstance, new object[] {playerID, blueprintID});
}
private void BuildGhostBlueprint(ICollection<Block> blocks, float3 pos, quaternion rot, uint playerID)
{
GhostChildUtility.ClearGhostChildren(playerID, entitiesDB, entityFunctions);
foreach (var block in blocks)
{
GhostChildUtility.BuildGhostChild(in playerID, block.Id, in pos, in rot, entitiesDB,
BuildGhostBlueprintFactory, false);
}
}
public Block[] PlaceBlueprintBlocks(uint blueprintID, uint playerID, float3 pos, float3 rot)
{ //RobocraftX.CR.MachineEditing.PlaceBlueprintUtility.PlaceBlocksFromSerialisedData
var serializationData = clipboardManager.GetSerializationData(blueprintID);
var blueprintData = serializationData.blueprintData;
blueprintData.dataPos = 0U;
uint selectionSize;
PositionEntityStruct selectionPosition;
RotationEntityStruct selectionRotation;
uint version;
BoxSelectSerializationUtilities.ReadClipboardHeader(blueprintData, out selectionSize, out selectionPosition, out selectionRotation, out version);
((FasterList<EGID>) LocalBlockMap.GetValue(null)).Clear();
if (version <= 1U)
{
uint groupsCount;
BoxSelectSerializationUtilities.ReadBlockGroupData(blueprintData, out groupsCount);
for (int index = 0; (long) index < (long) groupsCount; ++index)
{
int nextFilterId = BlockGroupUtility.NextFilterId;
entitySerialization.DeserializeNewEntity(new EGID((uint) nextFilterId, BlockGroupExclusiveGroups.BlockGroupEntityGroup), blueprintData, 1);
}
}
int nextFilterId1 = BlockGroupUtility.NextFilterId;
entityFactory.BuildEntity<BlockGroupEntityDescriptor>(new EGID((uint) nextFilterId1,
BlockGroupExclusiveGroups.BlockGroupEntityGroup)).Init(new BlockGroupTransformEntityComponent
{
blockGroupGridPosition = selectionPosition.position,
blockGroupGridRotation = selectionRotation.rotation
});
var frot = Quaternion.Euler(rot);
var grid = new GridRotationStruct {position = pos, rotation = frot};
var poss = new PositionEntityStruct {position = pos};
var rots = new RotationEntityStruct {rotation = frot};
for (int index = 0; (long) index < (long) selectionSize; ++index)
BuildBlock.Invoke(null,
new object[]
{
playerID, grid, poss, rots, selectionPosition, selectionRotation, blueprintData,
entitySerialization, nextFilterId1
});
/*
uint playerId, in GridRotationStruct ghostParentGrid,
in PositionEntityStruct ghostParentPosition, in RotationEntityStruct ghostParentRotation,
in PositionEntityStruct selectionPosition, in RotationEntityStruct selectionRotation,
ISerializationData serializationData, EntitiesDB entitiesDb,
IEntitySerialization entitySerialization, int blockGroupId
*/
if (globalBlockMap == null)
globalBlockMap = FullGameFields._deserialisedBlockMap;
var placedBlocks = (FasterList<EGID>) LocalBlockMap.GetValue(null);
globalBlockMap.Clear();
globalBlockMap.AddRange(placedBlocks);
BuildWires.Invoke(null,
new object[] {playerID, blueprintData, entitySerialization, entitiesDB, entityFactory});
var blocks = new Block[placedBlocks.count];
for (int i = 0; i < blocks.Length; i++)
blocks[i] = new Block(placedBlocks[i]);
return blocks;
}
public void GetBlueprintInfo(uint blueprintID, out float3 pos, out quaternion rot, out uint selectionSize)
{
var serializationData = clipboardManager.GetSerializationData(blueprintID);
var blueprintData = serializationData.blueprintData;
blueprintData.dataPos = 0U;
BoxSelectSerializationUtilities.ReadClipboardHeader(blueprintData, out selectionSize, out var posst,
out var rotst, out _);
blueprintData.dataPos = 0U; //Just to be sure, it gets reset when it's read anyway
pos = posst.position;
rot = rotst.rotation;
}
public void InitBlueprint(uint blueprintID)
{
clipboardManager.IncrementRefCount(blueprintID);
}
public void DisposeBlueprint(uint blueprintID)
{
clipboardManager.DecrementRefCount(blueprintID);
}
public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine";
public bool isRemovable { get; } = false;
[HarmonyPatch]
private static class RemoveEnginePatch
{
public static void Prefix(IEntityFunctions entityFunctions,
MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory)
{
nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
connectionFactory = machineGraphConnectionEntityFactory;
BlueprintEngine.entityFunctions = entityFunctions;
}
public static MethodBase TargetMethod()
{
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine"))[0];
}
}
[HarmonyPatch]
private static class SelectEnginePatch
{
public static void Prefix(ClipboardSerializationDataResourceManager clipboardSerializationDataResourceManager,
IEntitySerialization entitySerialization,
IEntityFactory entityFactory)
{
clipboardManager = clipboardSerializationDataResourceManager;
BlueprintEngine.entitySerialization = entitySerialization;
BlueprintEngine.entityFactory = entityFactory;
}
public static MethodBase TargetMethod()
{
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0];
}
}
[HarmonyPatch]
private static class SerializeGhostBlueprintPatch
{
public static void Postfix(object __instance)
{
SerializeGhostBlueprintInstance = __instance;
}
public static MethodBase TargetMethod()
{
return AccessTools.GetDeclaredConstructors(SerializeGhostBlueprintType)[0];
}
}
[HarmonyPatch]
private static class BuildGhostBlueprintPatch
{
public static void Postfix(GhostChildEntityFactory ghostChildEntityFactory)
{
BuildGhostBlueprintFactory = ghostChildEntityFactory;
}
public static MethodBase TargetMethod()
{
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.BuildGhostChildForMultiblockPickEngine"))[0];
}
}
public IEntityFactory Factory { get; set; }
}
}

View file

@ -16,7 +16,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public ConsoleBlock(uint id): base(new EGID(id, CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP)) public ConsoleBlock(uint id): base(new EGID(id, CommonExclusiveGroups.CONSOLE_BLOCK_GROUP))
{ {
} }

View file

@ -0,0 +1,48 @@
using RobocraftX.Blocks;
using RobocraftX.Common;
using Svelto.ECS;
namespace GamecraftModdingAPI.Blocks
{
public class DampedSpring : Block
{
public DampedSpring(EGID id) : base(id)
{
}
public DampedSpring(uint id) : base(new EGID(id, CommonExclusiveGroups.DAMPEDSPRING_BLOCK_GROUP))
{
}
/// <summary>
/// The spring's maximum force. This is known as Stiffness in-game
/// </summary>
public float MaxForce
{
get => BlockEngine.GetBlockInfo(this, (DampedSpringReadOnlyStruct dsrs) => dsrs.maxForce);
set => BlockEngine.SetBlockInfo(this,
(ref DampedSpringReadOnlyStruct dsrs, float val) => dsrs.maxForce = val, value);
}
/// <summary>
/// Alias of MaxForce.
/// </summary>
public float Stiffness
{
get => MaxForce;
set => MaxForce = value;
}
/// <summary>
/// The spring's maximum damping force.
/// </summary>
public float Damping
{
get => BlockEngine.GetBlockInfo(this, (LinearJointForcesReadOnlyStruct ljf) => ljf.dampingForceMagnitude);
set => BlockEngine.SetBlockInfo(this,
(ref LinearJointForcesReadOnlyStruct ljf, float val) => ljf.dampingForceMagnitude = val, value);
}
}
}

View file

@ -9,7 +9,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public LogicGate(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_LOGIC_BLOCK_GROUP)) public LogicGate(uint id) : base(new EGID(id, CommonExclusiveGroups.LOGIC_BLOCK_GROUP))
{ {
} }
} }

View file

@ -15,7 +15,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public Motor(uint id): base(new EGID(id, CommonExclusiveGroups.BUILD_MOTOR_BLOCK_GROUP)) public Motor(uint id): base(new EGID(id, CommonExclusiveGroups.MOTOR_BLOCK_GROUP))
{ {
} }

View file

@ -41,9 +41,9 @@ namespace GamecraftModdingAPI.Blocks
{ {
if (data.Group == null) return float3.zero; if (data.Group == null) return float3.zero;
var init = new EntityComponentInitializer(blockID, data.Group); var init = new EntityComponentInitializer(blockID, data.Group);
init.Init(new PositionEntityStruct {position = vector}); init.GetOrCreate<PositionEntityStruct>().position = vector;
init.Init(new GridRotationStruct {position = vector}); init.GetOrCreate<GridRotationStruct>().position = vector;
init.Init(new LocalTransformEntityStruct {position = vector}); init.GetOrCreate<LocalTransformEntityStruct>().position = vector;
return vector; return vector;
} }
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID); ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);

View file

@ -20,7 +20,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public MusicBlock(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_MUSIC_BLOCK_GROUP)) public MusicBlock(uint id) : base(new EGID(id, CommonExclusiveGroups.MUSIC_BLOCK_GROUP))
{ {
} }
@ -97,7 +97,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
get get
{ {
Assert.Log("Block exists: " + Exists); //Assert.Log("Block exists: " + Exists);
return BlockEngine.GetBlockInfo(this, return BlockEngine.GetBlockInfo(this,
(MusicBlockDataEntityStruct msdes) => (ChannelType) msdes.channelType); (MusicBlockDataEntityStruct msdes) => (ChannelType) msdes.channelType);
} }

View file

@ -10,7 +10,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public ObjectIdentifier(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP)) public ObjectIdentifier(uint id) : base(new EGID(id, CommonExclusiveGroups.OBJID_BLOCK_GROUP))
{ {
} }

View file

@ -15,7 +15,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public Piston(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_PISTON_BLOCK_GROUP)) public Piston(uint id) : base(new EGID(id, CommonExclusiveGroups.PISTON_BLOCK_GROUP))
{ {
} }

View file

@ -16,6 +16,7 @@ using UnityEngine;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
using GamecraftModdingAPI.Engines; using GamecraftModdingAPI.Engines;
using GamecraftModdingAPI.Players; using GamecraftModdingAPI.Players;
using RobocraftX.Rendering.GPUI;
namespace GamecraftModdingAPI.Blocks namespace GamecraftModdingAPI.Blocks
{ {
@ -52,15 +53,15 @@ namespace GamecraftModdingAPI.Blocks
private EntityComponentInitializer BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId) private EntityComponentInitializer BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId)
{ {
if (_blockEntityFactory == null) if (_blockEntityFactory == null)
throw new Exception("The factory is null."); throw new BlockException("The factory is null.");
if (uscale < 1) if (uscale < 1)
throw new Exception("Scale needs to be at least 1"); throw new BlockException("Scale needs to be at least 1");
if (scale.x < 4e-5) scale.x = uscale; if (scale.x < 4e-5) scale.x = uscale;
if (scale.y < 4e-5) scale.y = uscale; if (scale.y < 4e-5) scale.y = uscale;
if (scale.z < 4e-5) scale.z = uscale; if (scale.z < 4e-5) scale.z = uscale;
uint dbid = block; uint dbid = block;
if (!PrefabsID.DBIDMAP.ContainsKey(dbid)) if (!PrefabsID.HasPrefabRegistered(dbid, 0))
throw new Exception("Block with ID " + dbid + " not found!"); throw new BlockException("Block with ID " + dbid + " not found!");
//RobocraftX.CR.MachineEditing.PlaceBlockEngine //RobocraftX.CR.MachineEditing.PlaceBlockEngine
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale}; ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale};
Quaternion rotQ = Quaternion.Euler(rot); Quaternion rotQ = Quaternion.Euler(rot);
@ -70,9 +71,7 @@ namespace GamecraftModdingAPI.Blocks
DBEntityStruct dbEntity = new DBEntityStruct {DBID = dbid}; DBEntityStruct dbEntity = new DBEntityStruct {DBID = dbid};
BlockPlacementScaleEntityStruct placementScale = new BlockPlacementScaleEntityStruct BlockPlacementScaleEntityStruct placementScale = new BlockPlacementScaleEntityStruct
{ {
blockPlacementHeight = uscale, blockPlacementWidth = uscale, desiredScaleFactor = uscale, blockPlacementHeight = uscale, blockPlacementWidth = uscale, desiredScaleFactor = uscale
snapGridScale = uscale,
unitSnapOffset = 0, isUsingUnitSize = true
}; };
EquippedColourStruct colour = new EquippedColourStruct {indexInPalette = color}; EquippedColourStruct colour = new EquippedColourStruct {indexInPalette = color};
@ -83,7 +82,7 @@ namespace GamecraftModdingAPI.Blocks
structInitializer.Init(new ColourParameterEntityStruct structInitializer.Init(new ColourParameterEntityStruct
{ {
indexInPalette = colour.indexInPalette, indexInPalette = colour.indexInPalette,
needsUpdate = true hasNetworkChange = true
}); });
uint prefabId = PrefabsID.GetPrefabId(dbid, 0); uint prefabId = PrefabsID.GetPrefabId(dbid, 0);
structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId)); structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId));
@ -102,6 +101,13 @@ namespace GamecraftModdingAPI.Blocks
loadedFromDisk = false, loadedFromDisk = false,
placedBy = playerId placedBy = playerId
}); });
/*structInitializer.Init(new CollisionFilterOverride
{
belongsTo = 32U,
collidesWith = 239532U
});*/
PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer); PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer);
EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup); EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup);
ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity<PickedBlockExtraDataStruct>(playerEGID); ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity<PickedBlockExtraDataStruct>(playerEGID);

View file

@ -20,8 +20,11 @@ namespace GamecraftModdingAPI.Blocks
if (!entitiesDB.Exists<MachineGraphConnectionsEntityStruct>(target)) if (!entitiesDB.Exists<MachineGraphConnectionsEntityStruct>(target))
return false; return false;
var connections = entitiesDB.QueryEntity<MachineGraphConnectionsEntityStruct>(target); var connections = entitiesDB.QueryEntity<MachineGraphConnectionsEntityStruct>(target);
var groups = entitiesDB.FindGroups<MachineGraphConnectionsEntityStruct>();
var connStructMapper =
entitiesDB.QueryNativeMappedEntities<MachineGraphConnectionsEntityStruct>(groups);
for (int i = connections.connections.Count<MachineConnectionStruct>() - 1; i >= 0; i--) for (int i = connections.connections.Count<MachineConnectionStruct>() - 1; i >= 0; i--)
_connectionFactory.RemoveConnection(connections, i, entitiesDB); _connectionFactory.RemoveConnection(connections, i, connStructMapper);
_entityFunctions.RemoveEntity<BlockEntityDescriptor>(target); _entityFunctions.RemoveEntity<BlockEntityDescriptor>(target);
return true; return true;
} }

View file

@ -41,9 +41,9 @@ namespace GamecraftModdingAPI.Blocks
{ {
if (data.Group == null) return float3.zero; if (data.Group == null) return float3.zero;
var init = new EntityComponentInitializer(blockID, data.Group); var init = new EntityComponentInitializer(blockID, data.Group);
init.Init(new RotationEntityStruct {rotation = new Quaternion {eulerAngles = vector}}); init.GetOrCreate<RotationEntityStruct>().rotation = Quaternion.Euler(vector);
init.Init(new GridRotationStruct {rotation = new Quaternion {eulerAngles = vector}}); init.GetOrCreate<GridRotationStruct>().rotation = Quaternion.Euler(vector);
init.Init(new LocalTransformEntityStruct {rotation = new Quaternion {eulerAngles = vector}}); init.GetOrCreate<LocalTransformEntityStruct>().rotation = Quaternion.Euler(vector);
return vector; return vector;
} }
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity<RotationEntityStruct>(blockID); ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity<RotationEntityStruct>(blockID);

View file

@ -27,10 +27,12 @@ namespace GamecraftModdingAPI.Blocks
public string Name { get; } = "GamecraftModdingAPIScalingEngine"; public string Name { get; } = "GamecraftModdingAPIScalingEngine";
public bool isRemovable { get; } = false; public bool isRemovable { get; } = false;
private static EntityManager _entityManager; //Unity entity manager private EntityManager _entityManager; //Unity entity manager
public void UpdateCollision(EGID egid) public void UpdateCollision(EGID egid)
{ {
if (_entityManager == default)
_entityManager = FullGameFields._physicsWorld.EntityManager;
//Assuming the block exists //Assuming the block exists
var entity = entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(egid).uecsEntity; var entity = entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(egid).uecsEntity;
var pes = new UECSPhysicsEntityCreationStruct(); var pes = new UECSPhysicsEntityCreationStruct();
@ -38,11 +40,6 @@ namespace GamecraftModdingAPI.Blocks
_entityManager.DestroyEntity(entity); _entityManager.DestroyEntity(entity);
} }
internal void Setup(EntityManager entityManager)
{
_entityManager = entityManager;
}
[HarmonyPatch] [HarmonyPatch]
public class PhysicsEnginePatch public class PhysicsEnginePatch
{ {

View file

@ -15,7 +15,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public Servo(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_SERVO_BLOCK_GROUP)) public Servo(uint id) : base(new EGID(id, CommonExclusiveGroups.SERVO_BLOCK_GROUP))
{ {
} }

View file

@ -0,0 +1,209 @@
using System;
using FMOD.Studio;
using FMODUnity;
using Gamecraft.Wires;
using RobocraftX.Blocks;
using RobocraftX.Common;
using Svelto.ECS;
namespace GamecraftModdingAPI.Blocks
{
public class SfxBlock : SignalingBlock
{
public SfxBlock(EGID id) : base(id)
{
}
public SfxBlock(uint id) : base(new EGID(id, CommonExclusiveGroups.SIMPLESFX_BLOCK_GROUP /* This could also be BUILD_LOOPEDSFX_BLOCK_GROUP */))
{
}
public float Volume
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakableVolume);
}
set
{
BlockEngine.SetBlockInfo(this,
(ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakableVolume = val, value);
}
}
public float Pitch
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.tweakablePitch);
}
set
{
BlockEngine.SetBlockInfo(this,
(ref SoundSfxBlockDataEntityStruct obj, float val) => obj.tweakablePitch = val, value);
}
}
public bool Is3D
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.is3D);
}
set
{
BlockEngine.SetBlockInfo(this,
(ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.is3D = val, value);
}
}
public ChannelType ChannelType
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => (ChannelType)obj.channelType);
}
set
{
BlockEngine.SetBlockInfo(this,
(ref SoundSfxBlockDataEntityStruct obj, ChannelType val) => obj.tweakableVolume = (byte) val, value);
}
}
public byte TrackIndex
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.soundEffectIndex);
}
set
{
BlockEngine.SetBlockInfo(this,
(ref SoundSfxBlockDataEntityStruct obj, byte val) => obj.soundEffectIndex = val, value);
}
}
// track
public Guid Track
{
get
{
return BlockEngine.GetBlockInfo(this,
(SoundSfxBlockDataEntityStruct obj) => obj.is3D ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex));
}
set
{
BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, Guid val) =>
{
for (byte i = 0; i < obj.fmod2DEventPaths.Count<Guid>(); i++)
{
Guid track = obj.fmod2DEventPaths.Get<Guid>(i);
if (track == val)
{
obj.soundEffectIndex = i;
obj.is3D = false;
return;
}
}
for (byte i = 0; i < obj.fmod3DEventPaths.Count<Guid>(); i++)
{
Guid track = obj.fmod3DEventPaths.Get<Guid>(i);
if (track == val)
{
obj.soundEffectIndex = i;
obj.is3D = true;
return;
}
}
}, value);
}
}
// all tracks
public Guid[] Tracks2D
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) =>
{
Guid[] tracks = new Guid[obj.fmod2DEventPaths.Count<Guid>()];
for (byte i = 0; i < tracks.Length; i++)
{
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
}
return tracks;
});
}
}
public Guid[] Tracks3D
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) =>
{
Guid[] tracks = new Guid[obj.fmod3DEventPaths.Count<Guid>()];
for (byte i = 0; i < tracks.Length; i++)
{
tracks[i] = obj.fmod2DEventPaths.Get<Guid>(i);
}
return tracks;
});
}
}
public bool IsLooped
{
get
{
return BlockEngine.GetBlockInfo(this, (SoundSfxBlockDataEntityStruct obj) => obj.isLoopedBlock);
}
set
{
BlockEngine.SetBlockInfo(this,
(ref SoundSfxBlockDataEntityStruct obj, bool val) => obj.isLoopedBlock = val, value);
}
}
public bool IsPlaying
{
get
{
return BlockEngine.GetBlockInfo(this,
(SoundSfxBlockDataEntityStruct obj) => obj.isPlaying);
}
set
{
BlockEngine.SetBlockInfo(this, (ref SoundSfxBlockDataEntityStruct obj, bool val) =>
{
if (obj.isPlaying == val) return;
if (val)
{
// start playing
EventInstance inst = RuntimeManager.CreateInstance(obj.is3D ? obj.fmod3DEventPaths.Get<Guid>(obj.soundEffectIndex) : obj.fmod2DEventPaths.Get<Guid>(obj.soundEffectIndex));
inst.setVolume(obj.tweakableVolume / 100f);
inst.start();
obj.eventHandle = inst.handle;
}
else
{
// stop playing
EventInstance inst = default(EventInstance);
inst.handle = obj.eventHandle;
inst.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
inst.release();
}
obj.isPlaying = val;
}, value);
}
}
}
}

View file

@ -115,7 +115,8 @@ namespace GamecraftModdingAPI.Blocks
public bool SetSignal(uint signalID, float signal, bool input = true) public bool SetSignal(uint signalID, float signal, bool input = true)
{ {
var array = GetSignalStruct(signalID, out uint index, input); var array = GetSignalStruct(signalID, out uint index, input);
if (array.count > 0) array[index].valueAsFloat = signal; var arrayB = array.ToBuffer();
if (array.count > 0) arrayB.buffer[index].valueAsFloat = signal;
return false; return false;
} }
@ -128,9 +129,10 @@ namespace GamecraftModdingAPI.Blocks
public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true) public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true)
{ {
var array = GetSignalStruct(signalID, out uint index, input); var array = GetSignalStruct(signalID, out uint index, input);
var arrayB = array.ToBuffer();
if (array.count > 0) if (array.count > 0)
{ {
ref var channelData = ref array[index]; ref var channelData = ref arrayB.buffer[index];
channelData.valueAsFloat += signal; channelData.valueAsFloat += signal;
if (clamp) if (clamp)
{ {
@ -159,7 +161,8 @@ namespace GamecraftModdingAPI.Blocks
public float GetSignal(uint signalID, bool input = true) public float GetSignal(uint signalID, bool input = true)
{ {
var array = GetSignalStruct(signalID, out uint index, input); var array = GetSignalStruct(signalID, out uint index, input);
return array.count > 0 ? array[index].valueAsFloat : 0f; var arrayB = array.ToBuffer();
return array.count > 0 ? arrayB.buffer[index].valueAsFloat : 0f;
} }
public uint[] GetSignalIDs(EGID blockID, bool input = true) public uint[] GetSignalIDs(EGID blockID, bool input = true)
@ -244,13 +247,14 @@ namespace GamecraftModdingAPI.Blocks
{ {
ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID); ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group); var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group);
var wiresB = wires.ToBuffer().buffer;
for (uint i = 0; i < wires.count; i++) for (uint i = 0; i < wires.count; i++)
{ {
if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID) if ((wiresB[i].destinationPortUsage == port.usage && wiresB[i].destinationBlockEGID == blockID)
|| (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID)) || (wiresB[i].sourcePortUsage == port.usage && wiresB[i].sourceBlockEGID == blockID))
{ {
exists = true; exists = true;
return ref wires[i]; return ref wiresB[i];
} }
} }
exists = false; exists = false;
@ -286,6 +290,7 @@ namespace GamecraftModdingAPI.Blocks
} }
EntityCollection<WireEntityStruct> wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group); EntityCollection<WireEntityStruct> wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group);
var wiresB = wires.ToBuffer().buffer;
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]);
@ -294,11 +299,11 @@ namespace GamecraftModdingAPI.Blocks
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]); PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]);
for (int w = 0; w < wires.count; w++) for (int w = 0; w < wires.count; w++)
{ {
if ((wires[w].destinationPortUsage == endPES.usage && wires[w].destinationBlockEGID == endBlock) if ((wiresB[w].destinationPortUsage == endPES.usage && wiresB[w].destinationBlockEGID == endBlock)
&& (wires[w].sourcePortUsage == startPES.usage && wires[w].sourceBlockEGID == startBlock)) && (wiresB[w].sourcePortUsage == startPES.usage && wiresB[w].sourceBlockEGID == startBlock))
{ {
exists = true; exists = true;
return ref wires[w]; return ref wiresB[w];
} }
} }
} }
@ -313,10 +318,11 @@ namespace GamecraftModdingAPI.Blocks
{ {
ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID); ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID);
var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group); var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group);
var channelsB = channels.ToBuffer();
if (port.firstChannelIndexCachedInSim < channels.count) if (port.firstChannelIndexCachedInSim < channels.count)
{ {
exists = true; exists = true;
return ref channels[port.firstChannelIndexCachedInSim]; return ref channelsB.buffer[port.firstChannelIndexCachedInSim];
} }
exists = false; exists = false;
ChannelDataStruct[] defRef = new ChannelDataStruct[1]; ChannelDataStruct[] defRef = new ChannelDataStruct[1];
@ -327,8 +333,15 @@ namespace GamecraftModdingAPI.Blocks
{ {
var res = new FasterList<EGID>(); var res = new FasterList<EGID>();
foreach (var (coll, _) in entitiesDB.QueryEntities<BlockPortsStruct>()) foreach (var (coll, _) in entitiesDB.QueryEntities<BlockPortsStruct>())
foreach (ref BlockPortsStruct s in coll) {
var collB = coll.ToBuffer();
for (int i = 0; i < coll.count; i++)
{
ref BlockPortsStruct s = ref collB.buffer[i];
res.Add(s.ID); res.Add(s.ID);
}
}
return res.ToArray(); return res.ToArray();
} }
@ -358,15 +371,16 @@ namespace GamecraftModdingAPI.Blocks
return result; return result;
} }
private T[] Search<T>(ExclusiveGroup group, Func<T, bool> isMatch) where T : struct, IEntityComponent private T[] Search<T>(ExclusiveGroup group, Func<T, bool> isMatch) where T : unmanaged, IEntityComponent
{ {
FasterList<T> results = new FasterList<T>(); FasterList<T> results = new FasterList<T>();
EntityCollection<T> components = entitiesDB.QueryEntities<T>(group); EntityCollection<T> components = entitiesDB.QueryEntities<T>(group);
var componentsB = components.ToBuffer();
for (uint i = 0; i < components.count; i++) for (uint i = 0; i < components.count; i++)
{ {
if (isMatch(components[i])) if (isMatch(componentsB.buffer[i]))
{ {
results.Add(components[i]); results.Add(componentsB.buffer[i]);
} }
} }
return results.ToArray(); return results.ToArray();

View file

@ -17,7 +17,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public SpawnPoint(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_SPAWNPOINT_BLOCK_GROUP)) public SpawnPoint(uint id) : base(new EGID(id, CommonExclusiveGroups.SPAWNPOINT_BLOCK_GROUP))
{ {
} }

View file

@ -16,7 +16,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public TextBlock(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_TEXT_BLOCK_GROUP)) public TextBlock(uint id) : base(new EGID(id, CommonExclusiveGroups.TEXT_BLOCK_GROUP))
{ {
} }
@ -31,6 +31,7 @@ namespace GamecraftModdingAPI.Blocks
set set
{ {
if (value == null) value = "";
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) =>
{ {
tbds.textCurrent.Set(val); tbds.textCurrent.Set(val);
@ -50,6 +51,7 @@ namespace GamecraftModdingAPI.Blocks
set set
{ {
if (value == null) value = "";
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) =>
tbds.textBlockID.Set(val), value); tbds.textBlockID.Set(val), value);
BlockEngine.SetBlockInfo(this, BlockEngine.SetBlockInfo(this,

View file

@ -17,7 +17,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
} }
public Timer(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_TIMER_BLOCK_GROUP)) public Timer(uint id) : base(new EGID(id, CommonExclusiveGroups.TIMER_BLOCK_GROUP))
{ {
} }

View file

@ -0,0 +1,102 @@
using System;
using Unity.Mathematics;
using UnityEngine;
namespace GamecraftModdingAPI
{
/// <summary>
/// Represents a blueprint in the inventory. When placed it becomes a block group.
/// </summary>
public class Blueprint : IDisposable
{
public uint Id { get; }
internal Blueprint(uint id)
{
Id = id;
BlockGroup._engine.InitBlueprint(id);
Refresh();
}
/// <summary>
/// The center of the blueprint. Can only be set using the StoreBlocks() method.
/// </summary>
public float3 Position { get; private set; }
/// <summary>
/// The rotation of the blueprint. Can only be set using the StoreBlocks() method.
/// </summary>
public float3 Rotation { get; private set; }
/// <summary>
/// The amount of blocks in the blueprint. Gan only be set using the StoreBlocks() method.
/// </summary>
public uint BlockCount { get; private set; }
/// <summary>
/// Creates a new, empty blueprint. It will be deleted on disposal unless the game holds a reference to it.
/// </summary>
/// <returns>A blueprint that doesn't have any blocks</returns>
public static Blueprint Create()
{
return new Blueprint(BlockGroup._engine.CreateBlueprint());
}
/// <summary>
/// Set the blocks that the blueprint contains.
/// Use the BlockGroup overload for automatically calculated position and rotation.
/// </summary>
/// <param name="blocks">The array of blocks to use</param>
/// <param name="position">The anchor (center) position of the blueprint</param>
/// <param name="rotation">The base rotation of the blueprint</param>
public void StoreBlocks(Block[] blocks, float3 position, float3 rotation)
{
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, blocks, position,
quaternion.Euler(rotation));
Refresh();
}
/// <summary>
/// Store the blocks from the given group in the blueprint with correct position and rotation for the blueprint.
/// </summary>
/// <param name="group">The block group to store</param>
public void StoreBlocks(BlockGroup group)
{
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, group, group.Position,
Quaternion.Euler(group.Rotation));
Refresh();
}
/// <summary>
/// Places the blocks the blueprint contains at the specified position and rotation.
/// </summary>
/// <param name="position">The position of the blueprint</param>
/// <param name="rotation">The rotation of the blueprint</param>
/// <returns>An array of the placed blocks</returns>
public Block[] PlaceBlocks(float3 position, float3 rotation)
{
return BlockGroup._engine.PlaceBlueprintBlocks(Id, Player.LocalPlayer.Id, position, rotation);
}
/// <summary>
/// Updates the properties based on the blueprint data. Only necessary if the blueprint is changed from the game.
/// </summary>
public void Refresh()
{
BlockGroup._engine.GetBlueprintInfo(Id, out var pos, out var rot, out uint count);
Position = pos;
Rotation = ((Quaternion) rot).eulerAngles;
BlockCount = count;
}
public void Dispose()
{
BlockGroup._engine.DisposeBlueprint(Id);
}
public override string ToString()
{
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Rotation)}: {Rotation}, {nameof(BlockCount)}: {BlockCount}";
}
}
}

View file

@ -6,6 +6,7 @@ namespace GamecraftModdingAPI
{ {
/// <summary> /// <summary>
/// Represnts a cluster of blocks in time running mode, meaning blocks that are connected either directly or via joints. /// Represnts a cluster of blocks in time running mode, meaning blocks that are connected either directly or via joints.
/// Only exists if a cluster destruction manager is present. Static blocks like grass and dirt aren't part of a cluster.
/// </summary> /// </summary>
public class Cluster public class Cluster
{ {
@ -37,5 +38,37 @@ namespace GamecraftModdingAPI
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier; get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier;
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value; set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value;
} }
/// <summary>
/// Returns the simulation-time rigid bodies for the chunks in this cluster.
/// </summary>
/// <returns>An array of sim-bodies</returns>
public SimBody[] GetSimBodies()
{
return Block.BlockEngine.GetClusterBodies(Id.entityID);
}
public override string ToString()
{
return $"{nameof(Id)}: {Id}";
}
protected bool Equals(Cluster other)
{
return Id.Equals(other.Id);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Cluster) obj);
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
} }
} }

View file

@ -31,8 +31,6 @@ namespace GamecraftModdingAPI.Events
GameEngineManager.RegisterEngines(enginesRoot); GameEngineManager.RegisterEngines(enginesRoot);
// initialize AsyncUtils // initialize AsyncUtils
AsyncUtils.Setup(enginesRoot); AsyncUtils.Setup(enginesRoot);
// initialize Block
Block.Setup(physicsWorld);
// A new EnginesRoot is always created when ActivateGame is called // A new EnginesRoot is always created when ActivateGame is called
// so all event emitters and handlers must be re-registered. // so all event emitters and handlers must be re-registered.
EventManager.RegisterEngines(enginesRoot); EventManager.RegisterEngines(enginesRoot);

View file

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Version>1.5.0</Version> <Version>1.7.0</Version>
<Authors>Exmods</Authors> <Authors>Exmods</Authors>
<PackageLicenseExpression>GNU General Public Licence 3+</PackageLicenseExpression> <PackageLicenseExpression>GNU General Public Licence 3+</PackageLicenseExpression>
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl> <PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl>
@ -17,21 +17,18 @@
<DefineConstants>DEBUG;TEST;TRACE</DefineConstants> <DefineConstants>DEBUG;TEST;TRACE</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Lib.Harmony" Version="2.0.0.10" /> <PackageReference Include="Lib.Harmony" Version="2.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<!--Start Dependencies--> <!--Start Dependencies-->
<ItemGroup> <ItemGroup>
<Reference Include="IllusionInjector"> <Reference Include="Accessibility">
<HintPath>..\ref\Gamecraft_Data\Managed\IllusionInjector.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Accessibility.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\IllusionInjector.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Accessibility.dll</HintPath>
</Reference>
<Reference Include="IllusionPlugin">
<HintPath>..\ref\Gamecraft_Data\Managed\IllusionPlugin.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\IllusionPlugin.dll</HintPath>
</Reference> </Reference>
<Reference Include="Analytics"> <Reference Include="Analytics">
<HintPath>..\ref\Gamecraft_Data\Managed\Analytics.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Analytics.dll</HintPath>
@ -77,6 +74,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\DDNA.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\DDNA.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\DDNA.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\DDNA.dll</HintPath>
</Reference> </Reference>
<Reference Include="Facepunch.Steamworks.Win64">
<HintPath>..\ref\Gamecraft_Data\Managed\Facepunch.Steamworks.Win64.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Facepunch.Steamworks.Win64.dll</HintPath>
</Reference>
<Reference Include="FMOD"> <Reference Include="FMOD">
<HintPath>..\ref\Gamecraft_Data\Managed\FMOD.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\FMOD.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\FMOD.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\FMOD.dll</HintPath>
@ -89,14 +90,14 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.AudioBlocks.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.AudioBlocks.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.AudioBlocks.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.AudioBlocks.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.BlockCompositionRoot">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.BlockCompositionRoot.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.BlockCompositionRoot.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.BlockEntityFactory"> <Reference Include="Gamecraft.BlockEntityFactory">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.BlockEntityFactory.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.BlockEntityFactory.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.BlockEntityFactory.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.BlockEntityFactory.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.BlockGroups">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.BlockGroups.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.BlockGroups.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.Blocks.ConsoleBlock"> <Reference Include="Gamecraft.Blocks.ConsoleBlock">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll</HintPath>
@ -145,6 +146,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.ColourPalette">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.ColourPalette.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.ColourPalette.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.Damage"> <Reference Include="Gamecraft.Damage">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.Damage.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.Damage.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.Damage.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.Damage.dll</HintPath>
@ -161,18 +166,74 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GraphicsSettings.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GraphicsSettings.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GraphicsSettings.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GraphicsSettings.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.GUI.BlueprintInventory">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.BlueprintInventory.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.BlueprintInventory.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.BlueprintInventoryMock">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.BlueprintInventoryMock.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.BlueprintInventoryMock.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.Blueprints">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Blueprints.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Blueprints.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.BlueprintSets">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.BlueprintSets.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.BlueprintSets.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.ConsoleBlock"> <Reference Include="Gamecraft.GUI.ConsoleBlock">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.GUI.GameOptionsScreen">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GameOptionsScreen.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GameOptionsScreen.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.GraphicsScreen"> <Reference Include="Gamecraft.GUI.GraphicsScreen">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.GUI.Hotbar.Blocks">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Hotbar.Blocks.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Hotbar.Blocks.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.Hotbar.Colours">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Hotbar.Colours.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Hotbar.Colours.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.HUDFeedbackBlocks"> <Reference Include="Gamecraft.GUI.HUDFeedbackBlocks">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.GUI.ModeBar">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ModeBar.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ModeBar.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.OptionsScreen">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.OptionsScreen.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.OptionsScreen.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.TabsBar.Blocks">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Blocks.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Blocks.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.TabsBar.Blueprints">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Blueprints.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Blueprints.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.TabsBar.Colours">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Colours.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Colours.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.TabsBar.Common">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Common.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TabsBar.Common.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.TimeModeClock">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TimeModeClock.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.TimeModeClock.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.GUI.Tweaks"> <Reference Include="Gamecraft.GUI.Tweaks">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Tweaks.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Tweaks.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Tweaks.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Tweaks.dll</HintPath>
@ -189,6 +250,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll</HintPath>
</Reference> </Reference>
<Reference Include="Gamecraft.GUIs.Hotbar.BlueprintsHotbar">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUIs.Hotbar.BlueprintsHotbar.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUIs.Hotbar.BlueprintsHotbar.dll</HintPath>
</Reference>
<Reference Include="Gamecraft.InventoryTimeRunning"> <Reference Include="Gamecraft.InventoryTimeRunning">
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.InventoryTimeRunning.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.InventoryTimeRunning.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.InventoryTimeRunning.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.InventoryTimeRunning.dll</HintPath>
@ -249,6 +314,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\GameState.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\GameState.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\GameState.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\GameState.dll</HintPath>
</Reference> </Reference>
<Reference Include="GhostShark.Outline">
<HintPath>..\ref\Gamecraft_Data\Managed\GhostShark.Outline.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\GhostShark.Outline.dll</HintPath>
</Reference>
<Reference Include="GPUInstancer"> <Reference Include="GPUInstancer">
<HintPath>..\ref\Gamecraft_Data\Managed\GPUInstancer.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\GPUInstancer.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\GPUInstancer.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\GPUInstancer.dll</HintPath>
@ -261,10 +330,26 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Havok.Physics.Hybrid.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Havok.Physics.Hybrid.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Havok.Physics.Hybrid.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Havok.Physics.Hybrid.dll</HintPath>
</Reference> </Reference>
<Reference Include="IllusionInjector">
<HintPath>..\ref\Gamecraft_Data\Managed\IllusionInjector.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\IllusionInjector.dll</HintPath>
</Reference>
<Reference Include="IllusionPlugin">
<HintPath>..\ref\Gamecraft_Data\Managed\IllusionPlugin.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\IllusionPlugin.dll</HintPath>
</Reference>
<Reference Include="JWT">
<HintPath>..\ref\Gamecraft_Data\Managed\JWT.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\JWT.dll</HintPath>
</Reference>
<Reference Include="LZ4"> <Reference Include="LZ4">
<HintPath>..\ref\Gamecraft_Data\Managed\LZ4.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\LZ4.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\LZ4.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\LZ4.dll</HintPath>
</Reference> </Reference>
<Reference Include="mscorlib">
<HintPath>..\ref\Gamecraft_Data\Managed\mscorlib.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\mscorlib.dll</HintPath>
</Reference>
<Reference Include="MultiplayerNetworking"> <Reference Include="MultiplayerNetworking">
<HintPath>..\ref\Gamecraft_Data\Managed\MultiplayerNetworking.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\MultiplayerNetworking.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\MultiplayerNetworking.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\MultiplayerNetworking.dll</HintPath>
@ -273,10 +358,30 @@
<HintPath>..\ref\Gamecraft_Data\Managed\MultiplayerTest.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\MultiplayerTest.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\MultiplayerTest.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\MultiplayerTest.dll</HintPath>
</Reference> </Reference>
<Reference Include="netstandard">
<HintPath>..\ref\Gamecraft_Data\Managed\netstandard.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\netstandard.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\ref\Gamecraft_Data\Managed\Newtonsoft.Json.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Novell.Directory.Ldap">
<HintPath>..\ref\Gamecraft_Data\Managed\Novell.Directory.Ldap.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Novell.Directory.Ldap.dll</HintPath>
</Reference>
<Reference Include="RCX.ScreenshotTaker"> <Reference Include="RCX.ScreenshotTaker">
<HintPath>..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.dll</HintPath>
</Reference> </Reference>
<Reference Include="Rewired_Core">
<HintPath>..\ref\Gamecraft_Data\Managed\Rewired_Core.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Rewired_Core.dll</HintPath>
</Reference>
<Reference Include="Rewired_Windows">
<HintPath>..\ref\Gamecraft_Data\Managed\Rewired_Windows.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Rewired_Windows.dll</HintPath>
</Reference>
<Reference Include="RobocraftECS"> <Reference Include="RobocraftECS">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftECS.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftECS.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftECS.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftECS.dll</HintPath>
@ -341,6 +446,22 @@
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.dll</HintPath>
</Reference> </Reference>
<Reference Include="RobocraftX.GUI.Hotbar">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Hotbar.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Hotbar.dll</HintPath>
</Reference>
<Reference Include="RobocraftX.GUI.Inventory.BlocksInventory">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Inventory.BlocksInventory.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Inventory.BlocksInventory.dll</HintPath>
</Reference>
<Reference Include="RobocraftX.GUI.Inventory.ColourInventory">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Inventory.ColourInventory.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Inventory.ColourInventory.dll</HintPath>
</Reference>
<Reference Include="RobocraftX.GUI.Inventory">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.Inventory.dll</HintPath>
</Reference>
<Reference Include="RobocraftX.GUI.RemoveBlock"> <Reference Include="RobocraftX.GUI.RemoveBlock">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.RemoveBlock.dll</HintPath>
@ -349,6 +470,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.ScaleGhost.dll</HintPath>
</Reference> </Reference>
<Reference Include="RobocraftX.GUI.TabsBar">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.TabsBar.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.TabsBar.dll</HintPath>
</Reference>
<Reference Include="RobocraftX.GUIs.WorkshopPrefabs"> <Reference Include="RobocraftX.GUIs.WorkshopPrefabs">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll</HintPath>
@ -377,6 +502,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.dll</HintPath>
</Reference> </Reference>
<Reference Include="RobocraftX.Multiplayer.GUI">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.GUI.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.GUI.dll</HintPath>
</Reference>
<Reference Include="RobocraftX.Multiplayer.NetworkEntityStream"> <Reference Include="RobocraftX.Multiplayer.NetworkEntityStream">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll</HintPath>
@ -449,9 +578,9 @@
<HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX_TextBlock.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocraftX_TextBlock.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX_TextBlock.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocraftX_TextBlock.dll</HintPath>
</Reference> </Reference>
<Reference Include="RobocratX.SimulationCompositionRoot"> <Reference Include="RobocratX.SimulationMockCompositionRoot">
<HintPath>..\ref\Gamecraft_Data\Managed\RobocratX.SimulationCompositionRoot.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\RobocratX.SimulationMockCompositionRoot.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocratX.SimulationCompositionRoot.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\RobocratX.SimulationMockCompositionRoot.dll</HintPath>
</Reference> </Reference>
<Reference Include="SpawningPointCompositionRoot"> <Reference Include="SpawningPointCompositionRoot">
<HintPath>..\ref\Gamecraft_Data\Managed\SpawningPointCompositionRoot.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\SpawningPointCompositionRoot.dll</HintPath>
@ -465,9 +594,9 @@
<HintPath>..\ref\Gamecraft_Data\Managed\StringFormatter.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\StringFormatter.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\StringFormatter.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\StringFormatter.dll</HintPath>
</Reference> </Reference>
<Reference Include="Svelto.Common_3"> <Reference Include="Svelto.Common">
<HintPath>..\ref\Gamecraft_Data\Managed\Svelto.Common_3.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Svelto.Common.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Svelto.Common_3.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Svelto.Common.dll</HintPath>
</Reference> </Reference>
<Reference Include="Svelto.ECS"> <Reference Include="Svelto.ECS">
<HintPath>..\ref\Gamecraft_Data\Managed\Svelto.ECS.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Svelto.ECS.dll</HintPath>
@ -489,34 +618,6 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Addressables.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Addressables.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Addressables.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Addressables.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.Animation.Curves">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.Curves.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.Curves.dll</HintPath>
</Reference>
<Reference Include="Unity.Animation.Curves.Hybrid">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.Curves.Hybrid.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.Curves.Hybrid.dll</HintPath>
</Reference>
<Reference Include="Unity.Animation.DefaultGraphPipeline">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.DefaultGraphPipeline.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.DefaultGraphPipeline.dll</HintPath>
</Reference>
<Reference Include="Unity.Animation.DefaultGraphPipeline.Hybrid">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.DefaultGraphPipeline.Hybrid.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.DefaultGraphPipeline.Hybrid.dll</HintPath>
</Reference>
<Reference Include="Unity.Animation">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.dll</HintPath>
</Reference>
<Reference Include="Unity.Animation.Graph">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.Graph.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.Graph.dll</HintPath>
</Reference>
<Reference Include="Unity.Animation.Hybrid">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Animation.Hybrid.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Animation.Hybrid.dll</HintPath>
</Reference>
<Reference Include="Unity.Build.SlimPlayerRuntime"> <Reference Include="Unity.Build.SlimPlayerRuntime">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Build.SlimPlayerRuntime.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Build.SlimPlayerRuntime.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Build.SlimPlayerRuntime.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Build.SlimPlayerRuntime.dll</HintPath>
@ -525,13 +626,17 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Burst.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Burst.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Burst.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Burst.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.Burst.Unsafe">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Burst.Unsafe.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Burst.Unsafe.dll</HintPath>
</Reference>
<Reference Include="Unity.Collections"> <Reference Include="Unity.Collections">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Collections.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Collections.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Collections.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Collections.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.DataFlowGraph"> <Reference Include="Unity.Collections.LowLevel.ILSupport">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.DataFlowGraph.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Collections.LowLevel.ILSupport.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.DataFlowGraph.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Collections.LowLevel.ILSupport.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.Deformations"> <Reference Include="Unity.Deformations">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Deformations.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Deformations.dll</HintPath>
@ -545,6 +650,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Entities.Hybrid.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Entities.Hybrid.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Entities.Hybrid.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Entities.Hybrid.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.InternalAPIEngineBridge.012">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.InternalAPIEngineBridge.012.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.InternalAPIEngineBridge.012.dll</HintPath>
</Reference>
<Reference Include="Unity.Jobs"> <Reference Include="Unity.Jobs">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Jobs.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Jobs.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Jobs.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Jobs.dll</HintPath>
@ -577,10 +686,6 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Platforms.Common.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Platforms.Common.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Platforms.Common.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Platforms.Common.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.Postprocessing.Runtime">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Postprocessing.Runtime.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Postprocessing.Runtime.dll</HintPath>
</Reference>
<Reference Include="Unity.Properties"> <Reference Include="Unity.Properties">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Properties.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Properties.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Properties.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Properties.dll</HintPath>
@ -621,9 +726,9 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.ResourceManager.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.ResourceManager.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.ResourceManager.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.ResourceManager.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.Scenes.Hybrid"> <Reference Include="Unity.Scenes">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Scenes.Hybrid.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.Scenes.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Scenes.Hybrid.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Scenes.dll</HintPath>
</Reference> </Reference>
<Reference Include="Unity.ScriptableBuildPipeline"> <Reference Include="Unity.ScriptableBuildPipeline">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.ScriptableBuildPipeline.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.ScriptableBuildPipeline.dll</HintPath>
@ -653,58 +758,6 @@
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.VisualEffectGraph.Runtime.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\Unity.VisualEffectGraph.Runtime.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.VisualEffectGraph.Runtime.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.VisualEffectGraph.Runtime.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine.UI">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UI.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UI.dll</HintPath>
</Reference>
<Reference Include="uREPL">
<HintPath>..\ref\Gamecraft_Data\Managed\uREPL.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\uREPL.dll</HintPath>
</Reference>
<Reference Include="VisualProfiler">
<HintPath>..\ref\Gamecraft_Data\Managed\VisualProfiler.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\VisualProfiler.dll</HintPath>
</Reference>
<Reference Include="Accessibility">
<HintPath>..\ref\Gamecraft_Data\Managed\Accessibility.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Accessibility.dll</HintPath>
</Reference>
<Reference Include="Facepunch.Steamworks.Win64">
<HintPath>..\ref\Gamecraft_Data\Managed\Facepunch.Steamworks.Win64.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Facepunch.Steamworks.Win64.dll</HintPath>
</Reference>
<Reference Include="JWT">
<HintPath>..\ref\Gamecraft_Data\Managed\JWT.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\JWT.dll</HintPath>
</Reference>
<Reference Include="mscorlib">
<HintPath>..\ref\Gamecraft_Data\Managed\mscorlib.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\mscorlib.dll</HintPath>
</Reference>
<Reference Include="netstandard">
<HintPath>..\ref\Gamecraft_Data\Managed\netstandard.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\netstandard.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\ref\Gamecraft_Data\Managed\Newtonsoft.Json.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Novell.Directory.Ldap">
<HintPath>..\ref\Gamecraft_Data\Managed\Novell.Directory.Ldap.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Novell.Directory.Ldap.dll</HintPath>
</Reference>
<Reference Include="Rewired_Core">
<HintPath>..\ref\Gamecraft_Data\Managed\Rewired_Core.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Rewired_Core.dll</HintPath>
</Reference>
<Reference Include="Rewired_Windows">
<HintPath>..\ref\Gamecraft_Data\Managed\Rewired_Windows.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Rewired_Windows.dll</HintPath>
</Reference>
<Reference Include="Unity.Burst.Unsafe">
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Burst.Unsafe.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Burst.Unsafe.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AccessibilityModule"> <Reference Include="UnityEngine.AccessibilityModule">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.AccessibilityModule.dll</HintPath>
@ -873,10 +926,18 @@
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.TLSModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.TLSModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.TLSModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.TLSModule.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine.UI">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UI.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UI.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIElementsModule"> <Reference Include="UnityEngine.UIElementsModule">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine.UIElementsNativeModule">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsNativeModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsNativeModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIModule"> <Reference Include="UnityEngine.UIModule">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UIModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UIModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UIModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UIModule.dll</HintPath>
@ -933,6 +994,10 @@
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.VideoModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.VideoModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.VideoModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.VideoModule.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine.VirtualTexturingModule">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.VirtualTexturingModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.VirtualTexturingModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VRModule"> <Reference Include="UnityEngine.VRModule">
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.VRModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.VRModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.VRModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.VRModule.dll</HintPath>
@ -945,6 +1010,14 @@
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.XRModule.dll</HintPath> <HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.XRModule.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.XRModule.dll</HintPath> <HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.XRModule.dll</HintPath>
</Reference> </Reference>
<Reference Include="uREPL">
<HintPath>..\ref\Gamecraft_Data\Managed\uREPL.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\uREPL.dll</HintPath>
</Reference>
<Reference Include="VisualProfiler">
<HintPath>..\ref\Gamecraft_Data\Managed\VisualProfiler.dll</HintPath>
<HintPath>..\..\ref\Gamecraft_Data\Managed\VisualProfiler.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<!--End Dependencies--> <!--End Dependencies-->
</Project> </Project>

View file

@ -76,7 +76,7 @@ namespace GamecraftModdingAPI.Input
case 9: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_9; break; case 9: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_9; break;
default: break; default: break;
} }
if (commandLine) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.ToggleCommandLine; //if (commandLine) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.ToggleCommandLine; - TODO
if (escape) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Escape; if (escape) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Escape;
if (enter) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Return; if (enter) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Return;
if (debug) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.ToggleDebugDisplay; if (debug) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.ToggleDebugDisplay;
@ -125,7 +125,7 @@ namespace GamecraftModdingAPI.Input
if (tertiary) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.TertiaryAction; if (tertiary) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.TertiaryAction;
if (primaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.PrimaryActionHeld; if (primaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.PrimaryActionHeld;
if (secondaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.SecondaryActionHeld; if (secondaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.SecondaryActionHeld;
if (toggleUnitGrid) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleUnitGrid; //if (toggleUnitGrid) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleUnitGrid;
if (ctrl) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.CtrlAction; if (ctrl) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.CtrlAction;
if (toggleColourMode) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleColourMode; if (toggleColourMode) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleColourMode;
if (scaleBlockUp) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ScaleBlockUp; if (scaleBlockUp) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ScaleBlockUp;

View file

@ -36,13 +36,13 @@ namespace GamecraftModdingAPI.Inventory
public bool SelectBlock(int block, uint playerID, bool cubeSelectedByPick = false) public bool SelectBlock(int block, uint playerID, bool cubeSelectedByPick = false)
{ {
var inputs = entitiesDB.QueryEntities<LocalInputEntityStruct>(InputExclusiveGroups.LocalPlayers); var inputs = entitiesDB.QueryEntities<LocalInputEntityStruct>(InputExclusiveGroups.LocalPlayers).ToBuffer();
if (inputs.count == 0) return false; if (inputs.count == 0) return false;
for (int i = 0; i < inputs.count; i++) for (int i = 0; i < inputs.count; i++)
{ {
if (inputs[i].ID.entityID == playerID) { if (inputs.buffer[i].ID.entityID == playerID) {
inputs[i].cubeSelectedByPick = cubeSelectedByPick; inputs.buffer[i].cubeSelectedByPick = cubeSelectedByPick;
inputs[i].selectedCube = block; inputs.buffer[i].selectedCube = block;
return true; return true;
} }
} }

View file

@ -1,8 +1,6 @@
using System; using System;
using System.Reflection; using System.Reflection;
using RobocraftX.GUI;
using RobocraftX.GUI.Hotbar;
using Svelto.ECS; using Svelto.ECS;
using HarmonyLib; using HarmonyLib;
@ -17,7 +15,7 @@ namespace GamecraftModdingAPI.Inventory
public static BlockIDs EquippedPartID { get => (BlockIDs)selectedBlockInt; } public static BlockIDs EquippedPartID { get => (BlockIDs)selectedBlockInt; }
private static MethodInfo PatchedMethod { get; } = AccessTools.Method(AccessTools.TypeByName("RobocraftX.GUI.Hotbar.HotbarSlotSelectionHandlerEngine"), "ActivateSlotForCube", parameters: new Type[] { typeof(uint), typeof(int), typeof(ExclusiveGroupStruct) }); private static MethodInfo PatchedMethod { get; } = AccessTools.Method("Gamecraft.GUI.Hotbar.Blocks.SyncHotbarSlotSelectedToEquippedPartEngine:ActivateSlotForCube", parameters: new Type[] { typeof(uint), typeof(int), typeof(ExclusiveGroupStruct) });
public static void Prefix(uint playerID, int selectedDBPartID, ExclusiveGroupStruct groupID) public static void Prefix(uint playerID, int selectedDBPartID, ExclusiveGroupStruct groupID)
{ {

View file

@ -1,17 +1,15 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection; using System.Reflection;
using GamecraftModdingAPI.Blocks; using GamecraftModdingAPI.Blocks;
using HarmonyLib; using HarmonyLib;
using RobocraftX;
using RobocraftX.Services;
using Svelto.Context;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
using GamecraftModdingAPI.Events; using GamecraftModdingAPI.Events;
using GamecraftModdingAPI.Players;
using GamecraftModdingAPI.Tasks; using GamecraftModdingAPI.Tasks;
using uREPL;
namespace GamecraftModdingAPI namespace GamecraftModdingAPI
{ {
@ -46,7 +44,20 @@ namespace GamecraftModdingAPI
Logging.MetaDebugLog($"Patching Gamecraft"); Logging.MetaDebugLog($"Patching Gamecraft");
var currentAssembly = Assembly.GetExecutingAssembly(); var currentAssembly = Assembly.GetExecutingAssembly();
harmony = new Harmony(currentAssembly.GetName().Name); harmony = new Harmony(currentAssembly.GetName().Name);
try
{
harmony.PatchAll(currentAssembly); harmony.PatchAll(currentAssembly);
}
catch (Exception e)
{ //Can't use ErrorBuilder or Logging.LogException (which eventually uses ErrorBuilder) yet
Logging.Log(e.ToString());
Logging.LogWarning("Failed to patch Gamecraft. Attempting to patch to display error...");
harmony.Patch(AccessTools.Method(typeof(FullGameCompositionRoot), "OnContextInitialized")
.MakeGenericMethod(typeof(UnityContext<FullGameCompositionRoot>)),
new HarmonyMethod(((Action) OnPatchError).Method)); //Can't use lambdas here :(
return;
}
// init utility // init utility
Logging.MetaDebugLog($"Initializing Utility"); Logging.MetaDebugLog($"Initializing Utility");
#pragma warning disable 0612,0618 #pragma warning disable 0612,0618
@ -72,6 +83,7 @@ namespace GamecraftModdingAPI
// init object-oriented classes // init object-oriented classes
Player.Init(); Player.Init();
Block.Init(); Block.Init();
BlockGroup.Init();
Wire.Init(); Wire.Init();
GameClient.Init(); GameClient.Init();
AsyncUtils.Init(); AsyncUtils.Init();
@ -102,5 +114,11 @@ namespace GamecraftModdingAPI
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown"); Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
} }
} }
private static void OnPatchError()
{
ErrorBuilder.DisplayMustQuitError("Failed to patch Gamecraft!\n" +
"Make sure you're using the latest version of GamecraftModdingAPI or disable mods if the API isn't released yet.");
}
} }
} }

View file

@ -1,5 +1,4 @@
using System; using System;
using Unity.Mathematics; using Unity.Mathematics;
using RobocraftX.Common; using RobocraftX.Common;
using RobocraftX.Common.Players; using RobocraftX.Common.Players;
@ -17,6 +16,7 @@ namespace GamecraftModdingAPI
{ {
// static functionality // static functionality
private static PlayerEngine playerEngine = new PlayerEngine(); private static PlayerEngine playerEngine = new PlayerEngine();
private static Player localPlayer;
/// <summary> /// <summary>
/// Checks if the specified player exists. /// Checks if the specified player exists.
@ -54,6 +54,19 @@ namespace GamecraftModdingAPI
return (uint) playerEngine.GetAllPlayerCount(); return (uint) playerEngine.GetAllPlayerCount();
} }
/// <summary>
/// Returns the current player belonging to this client.
/// </summary>
public static Player LocalPlayer
{
get
{
if (localPlayer == null || localPlayer.Id != playerEngine.GetLocalPlayer())
localPlayer = new Player(PlayerType.Local);
return localPlayer;
}
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class. /// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class.
/// </summary> /// </summary>
@ -329,6 +342,23 @@ namespace GamecraftModdingAPI
} }
} }
/// <summary>
/// The player's selected blueprint in their hand. Set to null to clear. Dispose after usage.
/// </summary>
public Blueprint SelectedBlueprint
{
get => playerEngine.GetPlayerStruct(Id, out LocalBlueprintInputStruct lbis)
? new Blueprint(lbis.selectedBlueprintId)
: null;
set => BlockGroup._engine.SelectBlueprint(value?.Id ?? uint.MaxValue);
}
/// <summary>
/// The player's mode in time stopped mode, determining what they place.
/// </summary>
public PlayerBuildingMode BuildingMode => (PlayerBuildingMode) playerEngine
.GetCharacterStruct<PlayerInputTimeStoppedContextStruct>(Id, out _).timeStoppedContext;
// object methods // object methods
/// <summary> /// <summary>

View file

@ -0,0 +1,10 @@
namespace GamecraftModdingAPI.Players
{
public enum PlayerBuildingMode
{
BlockMode,
ColourMode,
ConfigMode,
BlueprintMode
}
}

View file

@ -50,10 +50,10 @@ namespace GamecraftModdingAPI.Players
public uint GetLocalPlayer() public uint GetLocalPlayer()
{ {
if (!isReady) return uint.MaxValue; if (!isReady) return uint.MaxValue;
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers); var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers).ToBuffer();
if (localPlayers.count > 0) if (localPlayers.count > 0)
{ {
return localPlayers[0].ID.entityID; return localPlayers.buffer[0].ID.entityID;
} }
return uint.MaxValue; return uint.MaxValue;
} }
@ -61,10 +61,10 @@ namespace GamecraftModdingAPI.Players
public uint GetRemotePlayer() public uint GetRemotePlayer()
{ {
if (!isReady) return uint.MaxValue; if (!isReady) return uint.MaxValue;
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.RemotePlayers); var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.RemotePlayers).ToBuffer();
if (localPlayers.count > 0) if (localPlayers.count > 0)
{ {
return localPlayers[0].ID.entityID; return localPlayers.buffer[0].ID.entityID;
} }
return uint.MaxValue; return uint.MaxValue;
} }

View file

@ -17,12 +17,13 @@ namespace GamecraftModdingAPI
public EGID Id { get; } public EGID Id { get; }
/// <summary> /// <summary>
/// The cluster this chunk belongs to, or null if the chunk doesn't exist. Get the SimBody from a Block if possible for good performance here. /// 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.
/// </summary> /// </summary>
public Cluster Cluster => cluster ?? (cluster = clusterId == uint.MaxValue ? Block.BlockEngine.GetCluster(Id.entityID) : new Cluster(clusterId)); public Cluster Cluster => cluster ?? (cluster = clusterId == uint.MaxValue ? Block.BlockEngine.GetCluster(Id.entityID) : new Cluster(clusterId));
private Cluster cluster; private Cluster cluster;
private uint clusterId; private readonly uint clusterId = uint.MaxValue;
public SimBody(EGID id) public SimBody(EGID id)
{ {
@ -120,6 +121,15 @@ namespace GamecraftModdingAPI
return Block.BlockEngine.GetConnectedSimBodies(Id.entityID); return Block.BlockEngine.GetConnectedSimBodies(Id.entityID);
} }
/// <summary>
/// The blocks that form this rigid body.
/// </summary>
/// <returns></returns>
public Block[] GetBlocks()
{
return Block.BlockEngine.GetBodyBlocks(Id.entityID);
}
private ref RigidBodyEntityStruct GetStruct() private ref RigidBodyEntityStruct GetStruct()
{ {
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id); return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id);

View file

@ -1,18 +1,22 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit;
using System.Text; using System.Text;
using HarmonyLib; using HarmonyLib;
using IllusionInjector; using IllusionInjector;
// test // test
using GPUInstancer;
using Svelto.ECS; using Svelto.ECS;
using RobocraftX.Blocks; using RobocraftX.Blocks;
using RobocraftX.Common; using RobocraftX.Common;
using RobocraftX.SimulationModeState; using RobocraftX.SimulationModeState;
using RobocraftX.FrontEnd; using RobocraftX.FrontEnd;
using Unity.Mathematics; using Unity.Mathematics;
using UnityEngine;
using RobocraftX.Schedulers; using RobocraftX.Schedulers;
using Svelto.Tasks.ExtraLean; using Svelto.Tasks.ExtraLean;
using uREPL; using uREPL;
@ -22,6 +26,7 @@ using GamecraftModdingAPI.Events;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
using GamecraftModdingAPI.Blocks; using GamecraftModdingAPI.Blocks;
using GamecraftModdingAPI.Players; using GamecraftModdingAPI.Players;
using EventType = GamecraftModdingAPI.Events.EventType;
namespace GamecraftModdingAPI.Tests namespace GamecraftModdingAPI.Tests
{ {
@ -176,11 +181,6 @@ namespace GamecraftModdingAPI.Tests
Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms"); Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms");
}) })
.Build(); .Build();
//With Sync(): 1135ms
//Without Sync(): 134ms
//Async: 348 794ms, doesn't freeze game
//Without Sync() but wait for submission: 530ms
//With Sync() at the end: 380ms
Block b = null; Block b = null;
CommandBuilder.Builder("moveBlockInSim", "Run in build mode first while looking at a block, then in sim to move it up") CommandBuilder.Builder("moveBlockInSim", "Run in build mode first while looking at a block, then in sim to move it up")
@ -277,6 +277,20 @@ namespace GamecraftModdingAPI.Tests
Logging.CommandLog("Health set to: " + val); Logging.CommandLog("Health set to: " + val);
}).Build(); }).Build();
CommandBuilder.Builder("placeBlockGroup", "Places some blocks in a group")
.Action((float x, float y, float z) =>
{
var pos = new float3(x, y, z);
var group = BlockGroup.Create(Block.PlaceNew(BlockIDs.AluminiumCube, pos,
color: BlockColors.Aqua));
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Blue)
.BlockGroup = group;
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Green)
.BlockGroup = group;
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Lime)
.BlockGroup = group;
}).Build();
GameClient.SetDebugInfo("InstalledMods", InstalledMods); GameClient.SetDebugInfo("InstalledMods", InstalledMods);
Block.Placed += (sender, args) => Block.Placed += (sender, args) =>
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID); Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);

View file

@ -65,7 +65,7 @@ namespace GamecraftModdingAPI.Tests
_testsCountPassed = 0; _testsCountPassed = 0;
_testsCountFailed = 0; _testsCountFailed = 0;
// flow control // flow control
Game.Enter += (sender, args) => { GameTests().RunOn(RobocraftX.Schedulers.Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING); }; Game.Enter += (sender, args) => { GameTests().RunOn(RobocraftX.Schedulers.Lean.EveryFrameStepRunner_TimeRunningAndStopped); };
Game.Exit += (s, a) => state = "ReturningFromGame"; Game.Exit += (s, a) => state = "ReturningFromGame";
Client.EnterMenu += (sender, args) => Client.EnterMenu += (sender, args) =>
{ {

View file

@ -12,8 +12,9 @@ using RobocraftX.GUI;
using RobocraftX.Multiplayer; using RobocraftX.Multiplayer;
using RobocraftX.Rendering; using RobocraftX.Rendering;
using Svelto.Context; using Svelto.Context;
using Svelto.DataStructures;
using Svelto.ECS; using Svelto.ECS;
using Svelto.ECS.Schedulers.Unity; using Svelto.ECS.Schedulers;
using UnityEngine; using UnityEngine;
using Unity.Entities; using Unity.Entities;
using Unity.Physics.Systems; using Unity.Physics.Systems;
@ -159,6 +160,14 @@ namespace GamecraftModdingAPI.Utility
} }
} }
public static FasterList<EGID> _deserialisedBlockMap
{
get
{
return (FasterList<EGID>) fgcr?.Field("_deserialisedBlockMap").GetValue();
}
}
private static Traverse fgcr; private static Traverse fgcr;
public static void Init(FullGameCompositionRoot instance) public static void Init(FullGameCompositionRoot instance)

View file

@ -38,7 +38,7 @@ PROJECT_NAME = "GamecraftModdingAPI"
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = "v1.5.0" PROJECT_NUMBER = "v1.7.0"
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a