Fixes, block IDs, cluster & chunk health support

This commit is contained in:
Norbi Peti 2020-08-13 16:59:13 +02:00
parent 50ebf4f0a6
commit 2172364d26
7 changed files with 154 additions and 43 deletions

View file

@ -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)

View file

@ -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()
{

View file

@ -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,

View 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;
}
}
}

View file

@ -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>

View file

@ -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);

View file

@ -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)
{