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()
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Gamecraft.Wires;
|
||||
using RobocraftX.Blocks;
|
||||
|
@ -9,6 +10,7 @@ using RobocraftX.Physics;
|
|||
using RobocraftX.Scene.Simulation;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Hybrid;
|
||||
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
||||
|
@ -90,28 +92,19 @@ namespace GamecraftModdingAPI.Blocks
|
|||
{
|
||||
if (entitiesDB.Exists<T>(block.Id))
|
||||
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
||||
if (block.InitData.Group == null) return def;
|
||||
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
||||
if (initializer.Has<T>())
|
||||
return getter(initializer.Get<T>());
|
||||
return def;
|
||||
return GetBlockInitInfo(block, getter, def);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
// TODO: optimize by using EntitiesDB internal calls instead of iterating over everything
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return getter(entitiesDB.QueryEntity<T>(block.Id));
|
||||
return GetBlockInitInfo(block, getter, def);
|
||||
}
|
||||
|
||||
private U GetBlockInitInfo<T, U>(Block block, Func<T, U> getter, U def) where T : struct, IEntityComponent
|
||||
{
|
||||
if (block.InitData.Group == null) return def;
|
||||
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
|
||||
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 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))
|
||||
{
|
||||
EntityCollection<T> entities = entitiesDB.QueryEntities<T>(block.Id.groupID);
|
||||
for (int i = 0; i < entities.count; i++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
setter(ref entitiesDB.QueryEntity<T>(block.Id), value);
|
||||
else
|
||||
SetBlockInitInfo(block, setter, value);
|
||||
}
|
||||
|
||||
public void SetBlockInfo<T, U>(Block block, Setter<T, U> setter, U value) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
if (entitiesDB.Exists<T>(block.Id))
|
||||
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);
|
||||
T component = initializer.Has<T>() ? initializer.Get<T>() : default;
|
||||
|
@ -222,6 +206,22 @@ namespace GamecraftModdingAPI.Blocks
|
|||
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)
|
||||
{
|
||||
var groups = entitiesDB.FindGroups<DBEntityStruct>();
|
||||
|
@ -234,6 +234,21 @@ namespace GamecraftModdingAPI.Blocks
|
|||
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
|
||||
public EntitiesDB GetEntitiesDB()
|
||||
{
|
||||
|
|
|
@ -192,6 +192,9 @@ namespace GamecraftModdingAPI.Blocks
|
|||
PlayerFilter,
|
||||
TeamFilter,
|
||||
Number2Text, //193
|
||||
DestructionManager = 260,
|
||||
ChunkHealthModifier,
|
||||
ClusterHealthModifier, //262
|
||||
BeachTree1 = 200,
|
||||
BeachTree2,
|
||||
BeachTree3,
|
||||
|
@ -243,6 +246,8 @@ namespace GamecraftModdingAPI.Blocks
|
|||
AdvancedRotator,
|
||||
MusicBlock, //256
|
||||
PlasmaCannonBlock,
|
||||
QuantumRiflePickup = 300,
|
||||
QuantumRifleAmmoPickup,
|
||||
MagmaRockCube=777,
|
||||
MagmaRockCubeSliced,
|
||||
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 UnityEngine;
|
||||
|
||||
using Gamecraft.Damage;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Physics;
|
||||
|
||||
|
@ -15,6 +16,14 @@ 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.
|
||||
/// </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)
|
||||
{
|
||||
Id = id;
|
||||
|
@ -24,6 +33,11 @@ namespace GamecraftModdingAPI
|
|||
{
|
||||
}
|
||||
|
||||
internal SimBody(uint id, uint clusterID) : this(id)
|
||||
{
|
||||
clusterId = clusterID;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The position of this body. When setting the position, update the position of the connected bodies as well,
|
||||
/// otherwise unexpected forces may arise.
|
||||
|
@ -70,6 +84,29 @@ namespace GamecraftModdingAPI
|
|||
//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>
|
||||
/// Whether the body can be moved or static.
|
||||
/// </summary>
|
||||
|
|
|
@ -268,6 +268,16 @@ namespace GamecraftModdingAPI.Tests
|
|||
})
|
||||
.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);
|
||||
Block.Placed += (sender, args) =>
|
||||
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Text.Formatting;
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
using GamecraftModdingAPI.Engines;
|
||||
|
@ -46,9 +47,9 @@ namespace GamecraftModdingAPI.Utility
|
|||
var array = new CodeInstruction[]
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -58,13 +59,15 @@ namespace GamecraftModdingAPI.Utility
|
|||
return list;
|
||||
}
|
||||
|
||||
public static void AddInfo(StringBuffer sb)
|
||||
public static void AddInfo(StringBuilder sb)
|
||||
{
|
||||
foreach (var info in _extraInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
sb.Append(info.Value() + "\n");
|
||||
string text = info.Value().Trim();
|
||||
if (text.Length != 0)
|
||||
sb.Append(text + "\n");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue