Fixes, block IDs, cluster & chunk health support
This commit is contained in:
parent
50ebf4f0a6
commit
2172364d26
7 changed files with 154 additions and 43 deletions
|
@ -372,7 +372,7 @@ namespace GamecraftModdingAPI
|
||||||
public SimBody GetSimBody()
|
public SimBody GetSimBody()
|
||||||
{
|
{
|
||||||
return BlockEngine.GetBlockInfo(this,
|
return BlockEngine.GetBlockInfo(this,
|
||||||
(GridConnectionsEntityStruct st) => new SimBody(st.machineRigidBodyId));
|
(GridConnectionsEntityStruct st) => new SimBody(st.machineRigidBodyId, st.clusterId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlacedInit(object sender, BlockPlacedRemovedEventArgs e)
|
private void OnPlacedInit(object sender, BlockPlacedRemovedEventArgs e)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
using Gamecraft.Wires;
|
using Gamecraft.Wires;
|
||||||
using RobocraftX.Blocks;
|
using RobocraftX.Blocks;
|
||||||
|
@ -9,6 +10,7 @@ using RobocraftX.Physics;
|
||||||
using RobocraftX.Scene.Simulation;
|
using RobocraftX.Scene.Simulation;
|
||||||
using Svelto.DataStructures;
|
using Svelto.DataStructures;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Hybrid;
|
||||||
|
|
||||||
using GamecraftModdingAPI.Engines;
|
using GamecraftModdingAPI.Engines;
|
||||||
|
|
||||||
|
@ -90,28 +92,19 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
if (entitiesDB.Exists<T>(block.Id))
|
if (entitiesDB.Exists<T>(block.Id))
|
||||||
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
||||||
if (block.InitData.Group == null) return def;
|
return GetBlockInitInfo(block, getter, def);
|
||||||
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
|
||||||
if (initializer.Has<T>())
|
|
||||||
return getter(initializer.Get<T>());
|
|
||||||
return def;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public U GetBlockInfoViewStruct<T, U>(Block block, Func<T, U> getter,
|
public U GetBlockInfoViewStruct<T, U>(Block block, Func<T, U> getter,
|
||||||
U def = default) where T : struct, INeedEGID, IEntityComponent
|
U def = default) where T : struct, IEntityViewComponent
|
||||||
{
|
{
|
||||||
if (entitiesDB.Exists<T>(block.Id))
|
if (entitiesDB.Exists<T>(block.Id))
|
||||||
{
|
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
||||||
// TODO: optimize by using EntitiesDB internal calls instead of iterating over everything
|
return GetBlockInitInfo(block, getter, def);
|
||||||
EntityCollection<T> entities = entitiesDB.QueryEntities<T>(block.Id.groupID);
|
|
||||||
for (int i = 0; i < entities.count; i++)
|
|
||||||
{
|
|
||||||
if (entities[i].ID == block.Id)
|
|
||||||
{
|
|
||||||
return getter(entities[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private U GetBlockInitInfo<T, U>(Block block, Func<T, U> getter, U def) where T : struct, IEntityComponent
|
||||||
|
{
|
||||||
if (block.InitData.Group == null) return def;
|
if (block.InitData.Group == null) return def;
|
||||||
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
||||||
if (initializer.Has<T>())
|
if (initializer.Has<T>())
|
||||||
|
@ -121,35 +114,26 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
|
|
||||||
public delegate void Setter<T, U>(ref T component, U value) where T : struct, IEntityComponent;
|
public delegate void Setter<T, U>(ref T component, U value) where T : struct, IEntityComponent;
|
||||||
|
|
||||||
public void SetBlockInfoViewStruct<T, U>(Block block, Setter<T, U> setter, U value) where T : struct, INeedEGID, IEntityComponent
|
public void SetBlockInfoViewStruct<T, U>(Block block, Setter<T, U> setter, U value) where T : struct, IEntityViewComponent
|
||||||
{
|
{
|
||||||
if (entitiesDB.Exists<T>(block.Id))
|
if (entitiesDB.Exists<T>(block.Id))
|
||||||
{
|
setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
|
||||||
EntityCollection<T> entities = entitiesDB.QueryEntities<T>(block.Id.groupID);
|
else
|
||||||
for (int i = 0; i < entities.count; i++)
|
SetBlockInitInfo(block, setter, value);
|
||||||
{
|
|
||||||
if (entities[i].ID == block.Id)
|
|
||||||
{
|
|
||||||
setter(ref entities[i], value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (block.InitData.Group != null)
|
|
||||||
{
|
|
||||||
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
|
||||||
T component = initializer.Has<T>() ? initializer.Get<T>() : default;
|
|
||||||
ref T structRef = ref component;
|
|
||||||
setter(ref structRef, value);
|
|
||||||
initializer.Init(structRef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBlockInfo<T, U>(Block block, Setter<T, U> setter, U value) where T : unmanaged, IEntityComponent
|
public void SetBlockInfo<T, U>(Block block, Setter<T, U> setter, U value) where T : unmanaged, IEntityComponent
|
||||||
{
|
{
|
||||||
if (entitiesDB.Exists<T>(block.Id))
|
if (entitiesDB.Exists<T>(block.Id))
|
||||||
setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
|
setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
|
||||||
else if (block.InitData.Group != null)
|
else
|
||||||
|
SetBlockInitInfo(block, setter, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetBlockInitInfo<T, U>(Block block, Setter<T, U> setter, U value)
|
||||||
|
where T : struct, IEntityComponent
|
||||||
|
{
|
||||||
|
if (block.InitData.Group != null)
|
||||||
{
|
{
|
||||||
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
||||||
T component = initializer.Has<T>() ? initializer.Get<T>() : default;
|
T component = initializer.Has<T>() ? initializer.Get<T>() : default;
|
||||||
|
@ -222,6 +206,22 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
return list.ToArray();
|
return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SimBody[] GetClusterBodies(uint cid)
|
||||||
|
{
|
||||||
|
var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
|
||||||
|
var bodies = new HashSet<uint>();
|
||||||
|
foreach (var (coll, _) in groups)
|
||||||
|
{
|
||||||
|
foreach (var conn in coll)
|
||||||
|
{
|
||||||
|
if (conn.clusterId == cid)
|
||||||
|
bodies.Add(conn.machineRigidBodyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bodies.Select(id => new SimBody(id)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
public EGID? FindBlockEGID(uint id)
|
public EGID? FindBlockEGID(uint id)
|
||||||
{
|
{
|
||||||
var groups = entitiesDB.FindGroups<DBEntityStruct>();
|
var groups = entitiesDB.FindGroups<DBEntityStruct>();
|
||||||
|
@ -234,6 +234,21 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cluster GetCluster(uint sbid)
|
||||||
|
{
|
||||||
|
var groups = entitiesDB.QueryEntities<GridConnectionsEntityStruct>();
|
||||||
|
foreach (var (coll, _) in groups)
|
||||||
|
{
|
||||||
|
foreach (var conn in coll)
|
||||||
|
{
|
||||||
|
if (conn.machineRigidBodyId == sbid)
|
||||||
|
return new Cluster(conn.clusterId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public EntitiesDB GetEntitiesDB()
|
public EntitiesDB GetEntitiesDB()
|
||||||
{
|
{
|
||||||
|
|
|
@ -192,6 +192,9 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
PlayerFilter,
|
PlayerFilter,
|
||||||
TeamFilter,
|
TeamFilter,
|
||||||
Number2Text, //193
|
Number2Text, //193
|
||||||
|
DestructionManager = 260,
|
||||||
|
ChunkHealthModifier,
|
||||||
|
ClusterHealthModifier, //262
|
||||||
BeachTree1 = 200,
|
BeachTree1 = 200,
|
||||||
BeachTree2,
|
BeachTree2,
|
||||||
BeachTree3,
|
BeachTree3,
|
||||||
|
@ -243,6 +246,8 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
AdvancedRotator,
|
AdvancedRotator,
|
||||||
MusicBlock, //256
|
MusicBlock, //256
|
||||||
PlasmaCannonBlock,
|
PlasmaCannonBlock,
|
||||||
|
QuantumRiflePickup = 300,
|
||||||
|
QuantumRifleAmmoPickup,
|
||||||
MagmaRockCube=777,
|
MagmaRockCube=777,
|
||||||
MagmaRockCubeSliced,
|
MagmaRockCubeSliced,
|
||||||
MagmaRockSlope,
|
MagmaRockSlope,
|
||||||
|
|
41
GamecraftModdingAPI/Cluster.cs
Normal file
41
GamecraftModdingAPI/Cluster.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
using Gamecraft.Damage;
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represnts a cluster of blocks in time running mode, meaning blocks that are connected either directly or via joints.
|
||||||
|
/// </summary>
|
||||||
|
public class Cluster
|
||||||
|
{
|
||||||
|
public EGID Id { get; }
|
||||||
|
|
||||||
|
public Cluster(EGID id)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cluster(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_CLUSTERS_GROUP))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public float InitialHealth
|
||||||
|
{
|
||||||
|
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth;
|
||||||
|
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float CurrentHealth
|
||||||
|
{
|
||||||
|
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth;
|
||||||
|
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float HealthMultiplier
|
||||||
|
{
|
||||||
|
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier;
|
||||||
|
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ using Svelto.ECS;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
using Gamecraft.Damage;
|
||||||
using RobocraftX.Common;
|
using RobocraftX.Common;
|
||||||
using RobocraftX.Physics;
|
using RobocraftX.Physics;
|
||||||
|
|
||||||
|
@ -15,6 +16,14 @@ namespace GamecraftModdingAPI
|
||||||
{
|
{
|
||||||
public EGID Id { get; }
|
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.
|
||||||
|
/// </summary>
|
||||||
|
public Cluster Cluster => cluster ?? (cluster = clusterId == uint.MaxValue ? Block.BlockEngine.GetCluster(Id.entityID) : new Cluster(clusterId));
|
||||||
|
|
||||||
|
private Cluster cluster;
|
||||||
|
private uint clusterId;
|
||||||
|
|
||||||
public SimBody(EGID id)
|
public SimBody(EGID id)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
|
@ -24,6 +33,11 @@ namespace GamecraftModdingAPI
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal SimBody(uint id, uint clusterID) : this(id)
|
||||||
|
{
|
||||||
|
clusterId = clusterID;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The position of this body. When setting the position, update the position of the connected bodies as well,
|
/// The position of this body. When setting the position, update the position of the connected bodies as well,
|
||||||
/// otherwise unexpected forces may arise.
|
/// otherwise unexpected forces may arise.
|
||||||
|
@ -70,6 +84,29 @@ namespace GamecraftModdingAPI
|
||||||
//set => GetStruct().physicsMass.CenterOfMass = value;
|
//set => GetStruct().physicsMass.CenterOfMass = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float Volume
|
||||||
|
{
|
||||||
|
get => GetStruct().volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float InitialHealth
|
||||||
|
{
|
||||||
|
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth;
|
||||||
|
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).initialHealth = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float CurrentHealth
|
||||||
|
{
|
||||||
|
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth;
|
||||||
|
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).currentHealth = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float HealthMultiplier
|
||||||
|
{
|
||||||
|
get => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier;
|
||||||
|
set => Block.BlockEngine.GetBlockInfo<HealthEntityComponent>(Id).healthMultiplier = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the body can be moved or static.
|
/// Whether the body can be moved or static.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -268,6 +268,16 @@ namespace GamecraftModdingAPI.Tests
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
CommandBuilder.Builder("TestChunkHealth", "Sets the chunk looked at to the given health.")
|
||||||
|
.Action((float val, float max) =>
|
||||||
|
{
|
||||||
|
var body = new Player(PlayerType.Local).GetSimBodyLookedAt();
|
||||||
|
if (body == null) return;
|
||||||
|
body.CurrentHealth = val;
|
||||||
|
body.InitialHealth = max;
|
||||||
|
Logging.CommandLog("Health set to: " + val);
|
||||||
|
}).Build();
|
||||||
|
|
||||||
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
||||||
Block.Placed += (sender, args) =>
|
Block.Placed += (sender, args) =>
|
||||||
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Formatting;
|
using System.Text.Formatting;
|
||||||
using GamecraftModdingAPI.Blocks;
|
using GamecraftModdingAPI.Blocks;
|
||||||
using GamecraftModdingAPI.Engines;
|
using GamecraftModdingAPI.Engines;
|
||||||
|
@ -46,9 +47,9 @@ namespace GamecraftModdingAPI.Utility
|
||||||
var array = new CodeInstruction[]
|
var array = new CodeInstruction[]
|
||||||
{
|
{
|
||||||
new CodeInstruction(OpCodes.Ldloc_0), //StringBuffer
|
new CodeInstruction(OpCodes.Ldloc_0), //StringBuffer
|
||||||
new CodeInstruction(OpCodes.Call, ((Action<StringBuffer>)AddInfo).Method)
|
new CodeInstruction(OpCodes.Call, ((Action<StringBuilder>)AddInfo).Method)
|
||||||
};
|
};
|
||||||
list.InsertRange(index, array);
|
list.InsertRange(index - 1, array); //-1: ldloc.1 ("local") before ldfld
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -58,13 +59,15 @@ namespace GamecraftModdingAPI.Utility
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddInfo(StringBuffer sb)
|
public static void AddInfo(StringBuilder sb)
|
||||||
{
|
{
|
||||||
foreach (var info in _extraInfo)
|
foreach (var info in _extraInfo)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sb.Append(info.Value() + "\n");
|
string text = info.Value().Trim();
|
||||||
|
if (text.Length != 0)
|
||||||
|
sb.Append(text + "\n");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue