# Conflicts: # GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cstags/v1.8.0
@@ -46,11 +46,12 @@ namespace GamecraftModdingAPI.App | |||
public Game[] GetMyGames() | |||
{ | |||
EntityCollection<MyGameDataEntityStruct> mgsevs = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames); | |||
var mgsevsB = mgsevs.ToBuffer().buffer; | |||
Game[] games = new Game[mgsevs.count]; | |||
for (int i = 0; i < mgsevs.count; i++) | |||
{ | |||
Utility.Logging.MetaDebugLog($"Found game named {mgsevs[i].GameName}"); | |||
games[i] = new Game(mgsevs[i].ID); | |||
Utility.Logging.MetaDebugLog($"Found game named {mgsevsB[i].GameName}"); | |||
games[i] = new Game(mgsevsB[i].ID); | |||
} | |||
return games; | |||
} | |||
@@ -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 | |||
} | |||
} |
@@ -335,6 +335,18 @@ namespace GamecraftModdingAPI.App | |||
gameEngine.ToggleTimeMode(); | |||
} | |||
/// <summary> | |||
/// The mode of the game. | |||
/// </summary> | |||
public CurrentGameMode Mode | |||
{ | |||
get | |||
{ | |||
if (menuMode || !VerifyMode()) return CurrentGameMode.None; | |||
return (CurrentGameMode) GameMode.CurrentMode; | |||
} | |||
} | |||
/// <summary> | |||
/// Load the game save. | |||
/// This happens asynchronously, so when this method returns the game not loaded yet. | |||
@@ -52,7 +52,7 @@ namespace GamecraftModdingAPI.App | |||
{ | |||
if (async) | |||
{ | |||
ExitCurrentGameAsync().RunOn(Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING); | |||
ExitCurrentGameAsync().RunOn(Lean.EveryFrameStepRunner_TimeRunningAndStopped); | |||
} | |||
else | |||
{ | |||
@@ -102,16 +102,27 @@ namespace GamecraftModdingAPI.App | |||
if (filter == BlockIDs.Invalid) | |||
{ | |||
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(); | |||
} | |||
else | |||
{ | |||
foreach (var (blocks, _) in allBlocks) | |||
foreach (var block in blocks) | |||
if (block.DBID == (ulong) filter) | |||
blockEGIDs.Add(block.ID); | |||
{ | |||
var array = blocks.ToBuffer().buffer; | |||
for (var index = 0; index < array.capacity; index++) | |||
{ | |||
var block = array[index]; | |||
if (block.DBID == (ulong) filter) | |||
blockEGIDs.Add(block.ID); | |||
} | |||
} | |||
return blockEGIDs.ToArray(); | |||
} | |||
} | |||
@@ -61,12 +61,13 @@ namespace GamecraftModdingAPI.App | |||
public uint HighestID() | |||
{ | |||
EntityCollection<MyGameDataEntityStruct> games = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames); | |||
var gamesB = games.ToBuffer().buffer; | |||
uint max = 0; | |||
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; | |||
@@ -118,11 +119,12 @@ namespace GamecraftModdingAPI.App | |||
{ | |||
EntityCollection<MyGamesSlotEntityViewStruct> entities = | |||
entitiesDB.QueryEntities<MyGamesSlotEntityViewStruct>(MyGamesScreenExclusiveGroups.GameSlotGuiEntities); | |||
var entitiesB = entities.ToBuffer().buffer; | |||
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]; | |||
@@ -3,12 +3,12 @@ using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Reflection.Emit; | |||
using Gamecraft.Blocks.BlockGroups; | |||
using Svelto.ECS; | |||
using Svelto.ECS.EntityStructs; | |||
using RobocraftX.Common; | |||
using RobocraftX.Blocks; | |||
using Unity.Mathematics; | |||
using Unity.Entities; | |||
using Gamecraft.Blocks.GUI; | |||
using GamecraftModdingAPI.Blocks; | |||
@@ -29,6 +29,7 @@ namespace GamecraftModdingAPI | |||
protected static readonly SignalEngine SignalEngine = new SignalEngine(); | |||
protected static readonly BlockEventsEngine BlockEventsEngine = new BlockEventsEngine(); | |||
protected static readonly ScalingEngine ScalingEngine = new ScalingEngine(); | |||
protected static readonly BlockCloneEngine BlockCloneEngine = new BlockCloneEngine(); | |||
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 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. | |||
/// <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> | |||
/// <param name="block">The block's type</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="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="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> | |||
@@ -66,7 +62,7 @@ namespace GamecraftModdingAPI | |||
/// <param name="block">The block's type</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="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="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> | |||
@@ -118,25 +114,35 @@ namespace GamecraftModdingAPI | |||
private static Dictionary<Type, Func<EGID, Block>> initializers = new Dictionary<Type, Func<EGID, Block>>(); | |||
private static Dictionary<Type, ExclusiveGroupStruct[]> typeToGroup = | |||
new Dictionary<Type, ExclusiveGroupStruct[]> | |||
private static Dictionary<Type, ExclusiveBuildGroup[]> typeToGroup = | |||
new Dictionary<Type, ExclusiveBuildGroup[]> | |||
{ | |||
{typeof(ConsoleBlock), new[] {CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP}}, | |||
{typeof(LogicGate), new [] {CommonExclusiveGroups.BUILD_LOGIC_BLOCK_GROUP}}, | |||
{typeof(Motor), new[] {CommonExclusiveGroups.BUILD_MOTOR_BLOCK_GROUP}}, | |||
{typeof(MusicBlock), new[] {CommonExclusiveGroups.BUILD_MUSIC_BLOCK_GROUP}}, | |||
{typeof(Piston), new[] {CommonExclusiveGroups.BUILD_PISTON_BLOCK_GROUP}}, | |||
{typeof(Servo), new[] {CommonExclusiveGroups.BUILD_SERVO_BLOCK_GROUP}}, | |||
{typeof(ConsoleBlock), new[] {CommonExclusiveGroups.CONSOLE_BLOCK_GROUP}}, | |||
{typeof(LogicGate), new [] {CommonExclusiveGroups.LOGIC_BLOCK_GROUP}}, | |||
{typeof(Motor), new[] {CommonExclusiveGroups.MOTOR_BLOCK_GROUP}}, | |||
{typeof(MusicBlock), new[] {CommonExclusiveGroups.MUSIC_BLOCK_GROUP}}, | |||
{typeof(ObjectIdentifier), new[]{CommonExclusiveGroups.OBJID_BLOCK_GROUP}}, | |||
{typeof(Piston), new[] {CommonExclusiveGroups.PISTON_BLOCK_GROUP}}, | |||
{typeof(Servo), new[] {CommonExclusiveGroups.SERVO_BLOCK_GROUP}}, | |||
{ | |||
typeof(SpawnPoint), | |||
new[] | |||
{ | |||
CommonExclusiveGroups.BUILD_SPAWNPOINT_BLOCK_GROUP, | |||
CommonExclusiveGroups.BUILD_BUILDINGSPAWN_BLOCK_GROUP | |||
CommonExclusiveGroups.SPAWNPOINT_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> | |||
@@ -184,7 +190,7 @@ namespace GamecraftModdingAPI | |||
type); | |||
ILGenerator il = dynamic.GetILGenerator(); | |||
il.DeclareLocal(type); | |||
//il.DeclareLocal(type); | |||
il.Emit(OpCodes.Ldarg_0); //Load EGID and pass to constructor | |||
il.Emit(OpCodes.Newobj, ctor); //Call constructor | |||
//il.Emit(OpCodes.Stloc_0); - doesn't seem like we need these | |||
@@ -224,6 +230,7 @@ namespace GamecraftModdingAPI | |||
public EGID Id { get; } | |||
internal BlockEngine.BlockInitData InitData; | |||
private EGID copiedFrom; | |||
/// <summary> | |||
/// The block's current position or zero if the block no longer exists. | |||
@@ -235,6 +242,9 @@ namespace GamecraftModdingAPI | |||
set | |||
{ | |||
MovementEngine.MoveBlock(Id, InitData, value); | |||
if (blockGroup != null) | |||
blockGroup.PosAndRotCalculated = false; | |||
BlockEngine.UpdateDisplayedBlock(Id); | |||
} | |||
} | |||
@@ -247,6 +257,9 @@ namespace GamecraftModdingAPI | |||
set | |||
{ | |||
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); | |||
if (!Exists) return; //UpdateCollision needs the block to exist | |||
ScalingEngine.UpdateCollision(Id); | |||
BlockEngine.UpdateDisplayedBlock(Id); | |||
} | |||
} | |||
@@ -307,9 +321,10 @@ namespace GamecraftModdingAPI | |||
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, BlockColor val) => | |||
{ | |||
color.indexInPalette = (byte) (val.Color + val.Darkness * 10); | |||
color.overridePaletteColour = false; | |||
color.needsUpdate = true; | |||
BlockEngine.SetBlockColorFromPalette(ref color); | |||
//color.overridePaletteColour = false; | |||
//color.needsUpdate = true; | |||
color.hasNetworkChange = true; | |||
color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); | |||
}, value); | |||
} | |||
} | |||
@@ -319,14 +334,15 @@ namespace GamecraftModdingAPI | |||
/// </summary> | |||
public float4 CustomColor | |||
{ | |||
get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.overriddenColour); | |||
get => BlockEngine.GetBlockInfo(this, (ColourParameterEntityStruct st) => st.paletteColour); | |||
set | |||
{ | |||
BlockEngine.SetBlockInfo(this, (ref ColourParameterEntityStruct color, float4 val) => | |||
{ | |||
color.overriddenColour = val; | |||
color.overridePaletteColour = true; | |||
color.needsUpdate = true; | |||
color.paletteColour = val; | |||
//color.overridePaletteColour = true; | |||
//color.needsUpdate = true; | |||
color.hasNetworkChange = true; | |||
}, 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> | |||
/// 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. | |||
@@ -368,11 +419,34 @@ namespace GamecraftModdingAPI | |||
/// 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. | |||
/// </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() | |||
{ | |||
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) | |||
@@ -380,6 +454,8 @@ namespace GamecraftModdingAPI | |||
if (e.ID != Id) return; | |||
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 | |||
if (copiedFrom != EGID.Empty) | |||
BlockCloneEngine.CopyBlockStats(copiedFrom, Id); | |||
} | |||
public override string ToString() | |||
@@ -422,6 +498,7 @@ namespace GamecraftModdingAPI | |||
GameEngineManager.AddGameEngine(BlockEventsEngine); | |||
GameEngineManager.AddGameEngine(ScalingEngine); | |||
GameEngineManager.AddGameEngine(SignalEngine); | |||
GameEngineManager.AddGameEngine(BlockCloneEngine); | |||
Wire.signalEngine = SignalEngine; // requires same functionality, no need to duplicate the engine | |||
} | |||
@@ -439,7 +516,12 @@ namespace GamecraftModdingAPI | |||
//Lets improve that using delegates | |||
var block = New<T>(Id.entityID, Id.groupID); | |||
block.InitData = this.InitData; | |||
if (this.InitData.Group != null) | |||
{ | |||
block.InitData = this.InitData; | |||
Placed += block.OnPlacedInit; //Reset InitData of new object | |||
} | |||
return block; | |||
} | |||
@@ -452,9 +534,5 @@ namespace GamecraftModdingAPI | |||
} | |||
} | |||
#endif | |||
internal static void Setup(World physicsWorld) | |||
{ | |||
ScalingEngine.Setup(physicsWorld.EntityManager); | |||
} | |||
} | |||
} |
@@ -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}"; | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -1,10 +1,17 @@ | |||
namespace GamecraftModdingAPI.Blocks | |||
using System; | |||
using Unity.Mathematics; | |||
namespace GamecraftModdingAPI.Blocks | |||
{ | |||
public struct BlockColor | |||
{ | |||
public BlockColors Color; | |||
public byte Darkness; | |||
public byte Index => Color == BlockColors.Default | |||
? byte.MaxValue | |||
: (byte) (Darkness * 10 + Color); | |||
public BlockColor(byte index) | |||
{ | |||
if (index == byte.MaxValue) | |||
@@ -14,6 +21,8 @@ | |||
} | |||
else | |||
{ | |||
if (index > 99) | |||
throw new ArgumentOutOfRangeException(nameof(index), "Invalid color index. Must be 0-90 or 255."); | |||
Color = (BlockColors) (index % 10); | |||
Darkness = (byte) (index / 10); | |||
} | |||
@@ -21,10 +30,14 @@ | |||
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; | |||
Darkness = darkness; | |||
} | |||
public float4 RGBA => Block.BlockEngine.ConvertBlockColor(Index); | |||
public override string ToString() | |||
{ | |||
return $"{nameof(Color)}: {Color}, {nameof(Darkness)}: {Darkness}"; | |||
@@ -2,15 +2,19 @@ using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using Gamecraft.ColourPalette; | |||
using Gamecraft.TimeRunning; | |||
using Gamecraft.Wires; | |||
using RobocraftX.Blocks; | |||
using RobocraftX.Common; | |||
using RobocraftX.GUI.Hotbar.Colours; | |||
using RobocraftX.Physics; | |||
using RobocraftX.Scene.Simulation; | |||
using RobocraftX.Rendering; | |||
using Svelto.ECS.EntityStructs; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Hybrid; | |||
using Unity.Mathematics; | |||
using GamecraftModdingAPI.Engines; | |||
@@ -42,8 +46,14 @@ namespace GamecraftModdingAPI.Blocks | |||
FasterList<EGID> cubes = new FasterList<EGID>(10); | |||
var coll = entitiesDB.QueryEntities<GridConnectionsEntityStruct>(); | |||
foreach (var (ecoll, _) in coll) | |||
foreach (ref var conn in ecoll) | |||
conn.isProcessed = false; | |||
{ | |||
var ecollB = ecoll.ToBuffer(); | |||
for(int i = 0; i < ecoll.count; i++) | |||
{ | |||
ref var conn = ref ecollB.buffer[i]; | |||
conn.isProcessed = false; | |||
} | |||
} | |||
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubes, | |||
(in GridConnectionsEntityStruct g) => { return false; }); | |||
@@ -54,12 +64,10 @@ namespace GamecraftModdingAPI.Blocks | |||
return ret; | |||
} | |||
public void SetBlockColorFromPalette(ref ColourParameterEntityStruct color) | |||
{ | |||
ref var paletteEntry = ref entitiesDB.QueryEntity<PaletteEntryEntityStruct>(color.indexInPalette, | |||
CommonExclusiveGroups.COLOUR_PALETTE_GROUP); | |||
color.paletteColour = paletteEntry.Colour; | |||
} | |||
public float4 ConvertBlockColor(byte index) => index == byte.MaxValue | |||
? new float4(-1f, -1f, -1f, -1f) | |||
: entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index, | |||
CommonExclusiveGroups.COLOUR_PALETTE_GROUP).Colour; | |||
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 | |||
} | |||
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)) | |||
{ | |||
// 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++) | |||
{ | |||
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) | |||
{ | |||
return entitiesDB.Exists<DBEntityStruct>(blockID); | |||
@@ -161,43 +178,55 @@ namespace GamecraftModdingAPI.Blocks | |||
public SimBody[] GetSimBodiesFromID(byte id) | |||
{ | |||
var ret = new FasterList<SimBody>(4); | |||
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP)) | |||
return new SimBody[0]; | |||
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP); | |||
var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP); | |||
foreach (ref ObjectIdEntityStruct oid in oids) | |||
var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>(); | |||
EGIDMapper<GridConnectionsEntityStruct>? connections = null; | |||
foreach (var ((oids, count), _) in oide) | |||
{ | |||
if (oid.objectId != id) continue; | |||
var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId; | |||
foreach (var rb in ret) | |||
{ | |||
if (rb.Id.entityID == rid) | |||
goto DUPLICATE; //Multiple Object Identifiers on one rigid body | |||
for (int i = 0; i < count; i++) | |||
{ | |||
ref ObjectIdEntityStruct oid = ref oids[i]; | |||
if (oid.objectId != id) continue; | |||
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) | |||
{ | |||
if (rb.Id.entityID == rid) | |||
goto DUPLICATE; //Multiple Object Identifiers on one rigid body | |||
} | |||
ret.Add(new SimBody(rid)); | |||
DUPLICATE: ; | |||
} | |||
ret.Add(new SimBody(rid)); | |||
DUPLICATE: ; | |||
} | |||
return ret.ToArray(); | |||
} | |||
public ObjectIdentifier[] GetObjectIDsFromID(byte id, bool sim) | |||
{ | |||
var ret = new FasterList<ObjectIdentifier>(4); | |||
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP)) | |||
return new ObjectIdentifier[0]; | |||
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.BUILD_OBJID_BLOCK_GROUP); | |||
foreach (ref ObjectIdEntityStruct oid in oids) | |||
if (sim ? oid.simObjectId == id : oid.objectId == id) | |||
ret.Add(new ObjectIdentifier(oid.ID)); | |||
var oide = entitiesDB.QueryEntities<ObjectIdEntityStruct>(); | |||
foreach (var ((oids, count), _) in oide) | |||
{ | |||
for (int i = 0; i < count; i++) | |||
{ | |||
ref ObjectIdEntityStruct oid = ref oids[i]; | |||
if (sim ? oid.simObjectId == id : oid.objectId == id) | |||
ret.Add(new ObjectIdentifier(oid.ID)); | |||
} | |||
} | |||
return ret.ToArray(); | |||
} | |||
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); | |||
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.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB)); | |||
else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA)); | |||
@@ -212,14 +241,16 @@ namespace GamecraftModdingAPI.Blocks | |||
var bodies = new HashSet<uint>(); | |||
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) | |||
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) | |||
@@ -239,9 +270,12 @@ namespace GamecraftModdingAPI.Blocks | |||
var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>(); | |||
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); | |||
} | |||
} | |||
@@ -249,6 +283,24 @@ namespace GamecraftModdingAPI.Blocks | |||
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 | |||
public EntitiesDB GetEntitiesDB() | |||
{ | |||
@@ -14,10 +14,10 @@ namespace GamecraftModdingAPI.Blocks | |||
/// </summary> | |||
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); | |||
/// <summary> | |||
@@ -5,10 +5,11 @@ using Svelto.ECS; | |||
using GamecraftModdingAPI.Engines; | |||
using GamecraftModdingAPI.Utility; | |||
using RobocraftX.Blocks; | |||
namespace GamecraftModdingAPI.Blocks | |||
{ | |||
public class BlockEventsEngine : IReactionaryEngine<DBEntityStruct> | |||
public class BlockEventsEngine : IReactionaryEngine<BlockTagEntityStruct> | |||
{ | |||
public event EventHandler<BlockPlacedRemovedEventArgs> Placed; | |||
public event EventHandler<BlockPlacedRemovedEventArgs> Removed; | |||
@@ -27,20 +28,20 @@ namespace GamecraftModdingAPI.Blocks | |||
public bool isRemovable { get; } = false; | |||
private bool shouldAddRemove; | |||
public void Add(ref DBEntityStruct entityComponent, EGID egid) | |||
public void Add(ref BlockTagEntityStruct entityComponent, EGID egid) | |||
{ | |||
if (!(shouldAddRemove = !shouldAddRemove)) | |||
return; | |||
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)) | |||
return; | |||
ExceptionUtil.InvokeEvent(Removed, this, | |||
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); | |||
new BlockPlacedRemovedEventArgs {ID = egid}); | |||
} | |||
} | |||
@@ -228,7 +228,7 @@ namespace GamecraftModdingAPI.Blocks | |||
ObjectiveHUD, | |||
GameStatsHUD, //231 | |||
GameOverBlock, | |||
SFXBlockGameplay=240, | |||
SFXBlockGameplay = 240, | |||
SFXBlock8Bit, | |||
SFXBlockInstrument, | |||
SFXBlockSciFi, | |||
@@ -248,7 +248,92 @@ namespace GamecraftModdingAPI.Blocks | |||
PlasmaCannonBlock, | |||
QuantumRiflePickup = 300, | |||
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, | |||
MagmaRockSlope, | |||
MagmaRockCorner, | |||
@@ -267,7 +352,7 @@ namespace GamecraftModdingAPI.Blocks | |||
HexNetSlopeRounded, | |||
HexNetCornerRounded, //794 | |||
MagmaRockBulgedInner, | |||
HexNetCylinder=797, | |||
HexNetCylinder = 797, | |||
HexNetHemisphere, | |||
HexNetSphere, | |||
HexNetTubeCorner //800 | |||
@@ -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; } | |||
} | |||
} |
@@ -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)) | |||
{ | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} |
@@ -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)) | |||
{ | |||
} | |||
} |
@@ -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)) | |||
{ | |||
} | |||
@@ -41,9 +41,9 @@ namespace GamecraftModdingAPI.Blocks | |||
{ | |||
if (data.Group == null) return float3.zero; | |||
var init = new EntityComponentInitializer(blockID, data.Group); | |||
init.Init(new PositionEntityStruct {position = vector}); | |||
init.Init(new GridRotationStruct {position = vector}); | |||
init.Init(new LocalTransformEntityStruct {position = vector}); | |||
init.GetOrCreate<PositionEntityStruct>().position = vector; | |||
init.GetOrCreate<GridRotationStruct>().position = vector; | |||
init.GetOrCreate<LocalTransformEntityStruct>().position = vector; | |||
return vector; | |||
} | |||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID); | |||
@@ -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 | |||
{ | |||
Assert.Log("Block exists: " + Exists); | |||
//Assert.Log("Block exists: " + Exists); | |||
return BlockEngine.GetBlockInfo(this, | |||
(MusicBlockDataEntityStruct msdes) => (ChannelType) msdes.channelType); | |||
} | |||
@@ -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)) | |||
{ | |||
} | |||
@@ -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)) | |||
{ | |||
} | |||
@@ -16,6 +16,7 @@ using UnityEngine; | |||
using GamecraftModdingAPI.Utility; | |||
using GamecraftModdingAPI.Engines; | |||
using GamecraftModdingAPI.Players; | |||
using RobocraftX.Rendering.GPUI; | |||
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) | |||
{ | |||
if (_blockEntityFactory == null) | |||
throw new Exception("The factory is null."); | |||
throw new BlockException("The factory is null."); | |||
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.y < 4e-5) scale.y = uscale; | |||
if (scale.z < 4e-5) scale.z = uscale; | |||
uint dbid = block; | |||
if (!PrefabsID.DBIDMAP.ContainsKey(dbid)) | |||
throw new Exception("Block with ID " + dbid + " not found!"); | |||
if (!PrefabsID.HasPrefabRegistered(dbid, 0)) | |||
throw new BlockException("Block with ID " + dbid + " not found!"); | |||
//RobocraftX.CR.MachineEditing.PlaceBlockEngine | |||
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale}; | |||
Quaternion rotQ = Quaternion.Euler(rot); | |||
@@ -70,9 +71,7 @@ namespace GamecraftModdingAPI.Blocks | |||
DBEntityStruct dbEntity = new DBEntityStruct {DBID = dbid}; | |||
BlockPlacementScaleEntityStruct placementScale = new BlockPlacementScaleEntityStruct | |||
{ | |||
blockPlacementHeight = uscale, blockPlacementWidth = uscale, desiredScaleFactor = uscale, | |||
snapGridScale = uscale, | |||
unitSnapOffset = 0, isUsingUnitSize = true | |||
blockPlacementHeight = uscale, blockPlacementWidth = uscale, desiredScaleFactor = uscale | |||
}; | |||
EquippedColourStruct colour = new EquippedColourStruct {indexInPalette = color}; | |||
@@ -83,7 +82,7 @@ namespace GamecraftModdingAPI.Blocks | |||
structInitializer.Init(new ColourParameterEntityStruct | |||
{ | |||
indexInPalette = colour.indexInPalette, | |||
needsUpdate = true | |||
hasNetworkChange = true | |||
}); | |||
uint prefabId = PrefabsID.GetPrefabId(dbid, 0); | |||
structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId)); | |||
@@ -102,6 +101,13 @@ namespace GamecraftModdingAPI.Blocks | |||
loadedFromDisk = false, | |||
placedBy = playerId | |||
}); | |||
/*structInitializer.Init(new CollisionFilterOverride | |||
{ | |||
belongsTo = 32U, | |||
collidesWith = 239532U | |||
});*/ | |||
PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer); | |||
EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup); | |||
ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity<PickedBlockExtraDataStruct>(playerEGID); | |||
@@ -20,8 +20,11 @@ namespace GamecraftModdingAPI.Blocks | |||
if (!entitiesDB.Exists<MachineGraphConnectionsEntityStruct>(target)) | |||
return false; | |||
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--) | |||
_connectionFactory.RemoveConnection(connections, i, entitiesDB); | |||
_connectionFactory.RemoveConnection(connections, i, connStructMapper); | |||
_entityFunctions.RemoveEntity<BlockEntityDescriptor>(target); | |||
return true; | |||
} | |||
@@ -41,9 +41,9 @@ namespace GamecraftModdingAPI.Blocks | |||
{ | |||
if (data.Group == null) return float3.zero; | |||
var init = new EntityComponentInitializer(blockID, data.Group); | |||
init.Init(new RotationEntityStruct {rotation = new Quaternion {eulerAngles = vector}}); | |||
init.Init(new GridRotationStruct {rotation = new Quaternion {eulerAngles = vector}}); | |||
init.Init(new LocalTransformEntityStruct {rotation = new Quaternion {eulerAngles = vector}}); | |||
init.GetOrCreate<RotationEntityStruct>().rotation = Quaternion.Euler(vector); | |||
init.GetOrCreate<GridRotationStruct>().rotation = Quaternion.Euler(vector); | |||
init.GetOrCreate<LocalTransformEntityStruct>().rotation = Quaternion.Euler(vector); | |||
return vector; | |||
} | |||
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity<RotationEntityStruct>(blockID); | |||
@@ -27,10 +27,12 @@ namespace GamecraftModdingAPI.Blocks | |||
public string Name { get; } = "GamecraftModdingAPIScalingEngine"; | |||
public bool isRemovable { get; } = false; | |||
private static EntityManager _entityManager; //Unity entity manager | |||
private EntityManager _entityManager; //Unity entity manager | |||
public void UpdateCollision(EGID egid) | |||
{ | |||
if (_entityManager == default) | |||
_entityManager = FullGameFields._physicsWorld.EntityManager; | |||
//Assuming the block exists | |||
var entity = entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(egid).uecsEntity; | |||
var pes = new UECSPhysicsEntityCreationStruct(); | |||
@@ -38,11 +40,6 @@ namespace GamecraftModdingAPI.Blocks | |||
_entityManager.DestroyEntity(entity); | |||
} | |||
internal void Setup(EntityManager entityManager) | |||
{ | |||
_entityManager = entityManager; | |||
} | |||
[HarmonyPatch] | |||
public class PhysicsEnginePatch | |||
{ | |||
@@ -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)) | |||
{ | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} | |||
} |
@@ -115,7 +115,8 @@ namespace GamecraftModdingAPI.Blocks | |||
public bool SetSignal(uint signalID, float signal, bool input = true) | |||
{ | |||
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; | |||
} | |||
@@ -128,9 +129,10 @@ namespace GamecraftModdingAPI.Blocks | |||
public float AddSignal(uint signalID, float signal, bool clamp = true, bool input = true) | |||
{ | |||
var array = GetSignalStruct(signalID, out uint index, input); | |||
var arrayB = array.ToBuffer(); | |||
if (array.count > 0) | |||
{ | |||
ref var channelData = ref array[index]; | |||
ref var channelData = ref arrayB.buffer[index]; | |||
channelData.valueAsFloat += signal; | |||
if (clamp) | |||
{ | |||
@@ -159,7 +161,8 @@ namespace GamecraftModdingAPI.Blocks | |||
public float GetSignal(uint signalID, bool input = true) | |||
{ | |||
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) | |||
@@ -244,13 +247,14 @@ namespace GamecraftModdingAPI.Blocks | |||
{ | |||
ref PortEntityStruct port = ref entitiesDB.QueryEntity<PortEntityStruct>(portID); | |||
var wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group); | |||
var wiresB = wires.ToBuffer().buffer; | |||
for (uint i = 0; i < wires.count; i++) | |||
{ | |||
if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID) | |||
|| (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID)) | |||
if ((wiresB[i].destinationPortUsage == port.usage && wiresB[i].destinationBlockEGID == blockID) | |||
|| (wiresB[i].sourcePortUsage == port.usage && wiresB[i].sourceBlockEGID == blockID)) | |||
{ | |||
exists = true; | |||
return ref wires[i]; | |||
return ref wiresB[i]; | |||
} | |||
} | |||
exists = false; | |||
@@ -286,6 +290,7 @@ namespace GamecraftModdingAPI.Blocks | |||
} | |||
EntityCollection<WireEntityStruct> wires = entitiesDB.QueryEntities<WireEntityStruct>(NamedExclusiveGroup<WiresGroup>.Group); | |||
var wiresB = wires.ToBuffer().buffer; | |||
for (int endIndex = 0; endIndex < endPorts.Length; endIndex++) | |||
{ | |||
PortEntityStruct endPES = entitiesDB.QueryEntity<PortEntityStruct>(endPorts[endIndex]); | |||
@@ -294,11 +299,11 @@ namespace GamecraftModdingAPI.Blocks | |||
PortEntityStruct startPES = entitiesDB.QueryEntity<PortEntityStruct>(startPorts[startIndex]); | |||
for (int w = 0; w < wires.count; w++) | |||
{ | |||
if ((wires[w].destinationPortUsage == endPES.usage && wires[w].destinationBlockEGID == endBlock) | |||
&& (wires[w].sourcePortUsage == startPES.usage && wires[w].sourceBlockEGID == startBlock)) | |||
if ((wiresB[w].destinationPortUsage == endPES.usage && wiresB[w].destinationBlockEGID == endBlock) | |||
&& (wiresB[w].sourcePortUsage == startPES.usage && wiresB[w].sourceBlockEGID == startBlock)) | |||
{ | |||
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); | |||
var channels = entitiesDB.QueryEntities<ChannelDataStruct>(NamedExclusiveGroup<ChannelDataGroup>.Group); | |||
var channelsB = channels.ToBuffer(); | |||
if (port.firstChannelIndexCachedInSim < channels.count) | |||
{ | |||
exists = true; | |||
return ref channels[port.firstChannelIndexCachedInSim]; | |||
return ref channelsB.buffer[port.firstChannelIndexCachedInSim]; | |||
} | |||
exists = false; | |||
ChannelDataStruct[] defRef = new ChannelDataStruct[1]; | |||
@@ -327,8 +333,15 @@ namespace GamecraftModdingAPI.Blocks | |||
{ | |||
var res = new FasterList<EGID>(); | |||
foreach (var (coll, _) in entitiesDB.QueryEntities<BlockPortsStruct>()) | |||
foreach (ref BlockPortsStruct s in coll) | |||
res.Add(s.ID); | |||
{ | |||
var collB = coll.ToBuffer(); | |||
for (int i = 0; i < coll.count; i++) | |||
{ | |||
ref BlockPortsStruct s = ref collB.buffer[i]; | |||
res.Add(s.ID); | |||
} | |||
} | |||
return res.ToArray(); | |||
} | |||
@@ -358,15 +371,16 @@ namespace GamecraftModdingAPI.Blocks | |||
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>(); | |||
EntityCollection<T> components = entitiesDB.QueryEntities<T>(group); | |||
var componentsB = components.ToBuffer(); | |||
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(); | |||
@@ -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)) | |||
{ | |||
} | |||
@@ -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 | |||
{ | |||
if (value == null) value = ""; | |||
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => | |||
{ | |||
tbds.textCurrent.Set(val); | |||
@@ -50,6 +51,7 @@ namespace GamecraftModdingAPI.Blocks | |||
set | |||
{ | |||
if (value == null) value = ""; | |||
BlockEngine.SetBlockInfo(this, (ref TextBlockDataStruct tbds, string val) => | |||
tbds.textBlockID.Set(val), value); | |||
BlockEngine.SetBlockInfo(this, | |||
@@ -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)) | |||
{ | |||
} | |||
@@ -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}"; | |||
} | |||
} | |||
} |
@@ -6,6 +6,7 @@ namespace GamecraftModdingAPI | |||
{ | |||
/// <summary> | |||
/// 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> | |||
public class Cluster | |||
{ | |||
@@ -37,5 +38,37 @@ namespace GamecraftModdingAPI | |||
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier; | |||
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(); | |||
} | |||
} | |||
} |
@@ -31,8 +31,6 @@ namespace GamecraftModdingAPI.Events | |||
GameEngineManager.RegisterEngines(enginesRoot); | |||
// initialize AsyncUtils | |||
AsyncUtils.Setup(enginesRoot); | |||
// initialize Block | |||
Block.Setup(physicsWorld); | |||
// A new EnginesRoot is always created when ActivateGame is called | |||
// so all event emitters and handlers must be re-registered. | |||
EventManager.RegisterEngines(enginesRoot); | |||
@@ -2,7 +2,7 @@ | |||
<PropertyGroup> | |||
<TargetFramework>net472</TargetFramework> | |||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | |||
<Version>1.5.0</Version> | |||
<Version>1.7.0</Version> | |||
<Authors>Exmods</Authors> | |||
<PackageLicenseExpression>GNU General Public Licence 3+</PackageLicenseExpression> | |||
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl> | |||
@@ -17,21 +17,18 @@ | |||
<DefineConstants>DEBUG;TEST;TRACE</DefineConstants> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Lib.Harmony" Version="2.0.0.10" /> | |||
<PackageReference Include="Lib.Harmony" Version="2.0.4" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Reference Include="Microsoft.CSharp" /> | |||
</ItemGroup> | |||
<!--Start Dependencies--> | |||
<ItemGroup> | |||
<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 Include="Accessibility"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Accessibility.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Accessibility.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Analytics"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.BlockEntityFactory.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.BlockEntityFactory.dll</HintPath> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll</HintPath> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll</HintPath> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll</HintPath> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\LZ4.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\LZ4.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="MultiplayerNetworking"> | |||
<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> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.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="RobocraftECS"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</Reference> | |||
<Reference Include="RobocratX.SimulationCompositionRoot"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\RobocratX.SimulationCompositionRoot.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocratX.SimulationCompositionRoot.dll</HintPath> | |||
<Reference Include="RobocratX.SimulationMockCompositionRoot"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\RobocratX.SimulationMockCompositionRoot.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\RobocratX.SimulationMockCompositionRoot.dll</HintPath> | |||
</Reference> | |||
<Reference Include="SpawningPointCompositionRoot"> | |||
<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> | |||
</Reference> | |||
<Reference Include="Svelto.Common_3"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Svelto.Common_3.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Svelto.Common_3.dll</HintPath> | |||
<Reference Include="Svelto.Common"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Svelto.Common.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Svelto.Common.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Svelto.ECS"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Collections.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Collections.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Unity.DataFlowGraph"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.DataFlowGraph.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.DataFlowGraph.dll</HintPath> | |||
<Reference Include="Unity.Collections.LowLevel.ILSupport"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Collections.LowLevel.ILSupport.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Collections.LowLevel.ILSupport.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Unity.Deformations"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</Reference> | |||
<Reference Include="Unity.Scenes.Hybrid"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Scenes.Hybrid.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Scenes.Hybrid.dll</HintPath> | |||
<Reference Include="Unity.Scenes"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\Unity.Scenes.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\Unity.Scenes.dll</HintPath> | |||
</Reference> | |||
<Reference Include="Unity.ScriptableBuildPipeline"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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"> | |||
<HintPath>..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath> | |||
<HintPath>..\..\ref\Gamecraft_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath> | |||
</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"> | |||
<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> | |||
</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"> | |||
<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> | |||
</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> | |||
<!--End Dependencies--> | |||
</Project> |
@@ -76,7 +76,7 @@ namespace GamecraftModdingAPI.Input | |||
case 9: currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Hotbar_9; 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 (enter) currentInput.guiMask |= RobocraftX.Common.Input.GuiInput.Return; | |||
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 (primaryHeld) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.PrimaryActionHeld; | |||
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 (toggleColourMode) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ToggleColourMode; | |||
if (scaleBlockUp) currentInput.actionMask |= RobocraftX.Common.Input.ActionInput.ScaleBlockUp; | |||
@@ -36,13 +36,13 @@ namespace GamecraftModdingAPI.Inventory | |||
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; | |||
for (int i = 0; i < inputs.count; i++) | |||
{ | |||
if (inputs[i].ID.entityID == playerID) { | |||
inputs[i].cubeSelectedByPick = cubeSelectedByPick; | |||
inputs[i].selectedCube = block; | |||
if (inputs.buffer[i].ID.entityID == playerID) { | |||
inputs.buffer[i].cubeSelectedByPick = cubeSelectedByPick; | |||
inputs.buffer[i].selectedCube = block; | |||
return true; | |||
} | |||
} | |||
@@ -1,8 +1,6 @@ | |||
using System; | |||
using System.Reflection; | |||
using RobocraftX.GUI; | |||
using RobocraftX.GUI.Hotbar; | |||
using Svelto.ECS; | |||
using HarmonyLib; | |||
@@ -17,7 +15,7 @@ namespace GamecraftModdingAPI.Inventory | |||
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) | |||
{ | |||
@@ -1,17 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Reflection; | |||
using GamecraftModdingAPI.Blocks; | |||
using HarmonyLib; | |||
using RobocraftX; | |||
using RobocraftX.Services; | |||
using Svelto.Context; | |||
using GamecraftModdingAPI.Utility; | |||
using GamecraftModdingAPI.Events; | |||
using GamecraftModdingAPI.Players; | |||
using GamecraftModdingAPI.Tasks; | |||
using uREPL; | |||
namespace GamecraftModdingAPI | |||
{ | |||
@@ -46,7 +44,20 @@ namespace GamecraftModdingAPI | |||
Logging.MetaDebugLog($"Patching Gamecraft"); | |||
var currentAssembly = Assembly.GetExecutingAssembly(); | |||
harmony = new Harmony(currentAssembly.GetName().Name); | |||
harmony.PatchAll(currentAssembly); | |||
try | |||
{ | |||
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 | |||
Logging.MetaDebugLog($"Initializing Utility"); | |||
#pragma warning disable 0612,0618 | |||
@@ -72,6 +83,7 @@ namespace GamecraftModdingAPI | |||
// init object-oriented classes | |||
Player.Init(); | |||
Block.Init(); | |||
BlockGroup.Init(); | |||
Wire.Init(); | |||
GameClient.Init(); | |||
AsyncUtils.Init(); | |||
@@ -102,5 +114,11 @@ namespace GamecraftModdingAPI | |||
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."); | |||
} | |||
} | |||
} |
@@ -1,5 +1,4 @@ | |||
using System; | |||
using Unity.Mathematics; | |||
using RobocraftX.Common; | |||
using RobocraftX.Common.Players; | |||
@@ -17,6 +16,7 @@ namespace GamecraftModdingAPI | |||
{ | |||
// static functionality | |||
private static PlayerEngine playerEngine = new PlayerEngine(); | |||
private static Player localPlayer; | |||
/// <summary> | |||
/// Checks if the specified player exists. | |||
@@ -54,6 +54,19 @@ namespace GamecraftModdingAPI | |||
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> | |||
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.Player"/> class. | |||
/// </summary> | |||
@@ -329,7 +342,24 @@ namespace GamecraftModdingAPI | |||
} | |||
} | |||
// object methods | |||
/// <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 | |||
/// <summary> | |||
/// Teleport the player to the specified coordinates. | |||
@@ -0,0 +1,10 @@ | |||
namespace GamecraftModdingAPI.Players | |||
{ | |||
public enum PlayerBuildingMode | |||
{ | |||
BlockMode, | |||
ColourMode, | |||
ConfigMode, | |||
BlueprintMode | |||
} | |||
} |
@@ -50,10 +50,10 @@ namespace GamecraftModdingAPI.Players | |||
public uint GetLocalPlayer() | |||
{ | |||
if (!isReady) return uint.MaxValue; | |||
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers); | |||
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers).ToBuffer(); | |||
if (localPlayers.count > 0) | |||
{ | |||
return localPlayers[0].ID.entityID; | |||
return localPlayers.buffer[0].ID.entityID; | |||
} | |||
return uint.MaxValue; | |||
} | |||
@@ -61,10 +61,10 @@ namespace GamecraftModdingAPI.Players | |||
public uint GetRemotePlayer() | |||
{ | |||
if (!isReady) return uint.MaxValue; | |||
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.RemotePlayers); | |||
var localPlayers = entitiesDB.QueryEntities<PlayerIDStruct>(PlayersExclusiveGroups.RemotePlayers).ToBuffer(); | |||
if (localPlayers.count > 0) | |||
{ | |||
return localPlayers[0].ID.entityID; | |||
return localPlayers.buffer[0].ID.entityID; | |||
} | |||
return uint.MaxValue; | |||
} | |||
@@ -17,12 +17,13 @@ namespace GamecraftModdingAPI | |||
public EGID Id { get; } | |||
/// <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> | |||
public Cluster Cluster => cluster ?? (cluster = clusterId == uint.MaxValue ? Block.BlockEngine.GetCluster(Id.entityID) : new Cluster(clusterId)); | |||
private Cluster cluster; | |||
private uint clusterId; | |||
private readonly uint clusterId = uint.MaxValue; | |||
public SimBody(EGID id) | |||
{ | |||
@@ -120,6 +121,15 @@ namespace GamecraftModdingAPI | |||
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() | |||
{ | |||
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id); | |||
@@ -1,18 +1,22 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Reflection.Emit; | |||
using System.Text; | |||
using HarmonyLib; | |||
using IllusionInjector; | |||
// test | |||
using GPUInstancer; | |||
using Svelto.ECS; | |||
using RobocraftX.Blocks; | |||
using RobocraftX.Common; | |||
using RobocraftX.SimulationModeState; | |||
using RobocraftX.FrontEnd; | |||
using Unity.Mathematics; | |||
using UnityEngine; | |||
using RobocraftX.Schedulers; | |||
using Svelto.Tasks.ExtraLean; | |||
using uREPL; | |||
@@ -22,6 +26,7 @@ using GamecraftModdingAPI.Events; | |||
using GamecraftModdingAPI.Utility; | |||
using GamecraftModdingAPI.Blocks; | |||
using GamecraftModdingAPI.Players; | |||
using EventType = GamecraftModdingAPI.Events.EventType; | |||
namespace GamecraftModdingAPI.Tests | |||
{ | |||
@@ -176,11 +181,6 @@ namespace GamecraftModdingAPI.Tests | |||
Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms"); | |||
}) | |||
.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; | |||
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); | |||
}).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); | |||
Block.Placed += (sender, args) => | |||
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID); | |||
@@ -65,7 +65,7 @@ namespace GamecraftModdingAPI.Tests | |||
_testsCountPassed = 0; | |||
_testsCountFailed = 0; | |||
// 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"; | |||
Client.EnterMenu += (sender, args) => | |||
{ | |||
@@ -12,8 +12,9 @@ using RobocraftX.GUI; | |||
using RobocraftX.Multiplayer; | |||
using RobocraftX.Rendering; | |||
using Svelto.Context; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Schedulers.Unity; | |||
using Svelto.ECS.Schedulers; | |||
using UnityEngine; | |||
using Unity.Entities; | |||
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; | |||
public static void Init(FullGameCompositionRoot instance) | |||
@@ -38,7 +38,7 @@ PROJECT_NAME = "GamecraftModdingAPI" | |||
# could be handy for archiving the generated documentation or if some version | |||
# 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 | |||
# for a project that appears at the top of each page and should give viewer a | |||