Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Game.Client/Physics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using System.Collections.Generic;
using System.Text;

using static Source.Engine.StaticPropMgrGlobals;

namespace Game.Client;

[EngineComponent]
Expand Down Expand Up @@ -82,6 +84,6 @@ private void PhysicsLevelInit() {

g_PhysWorldObject = PhysCreateWorld_Shared(C_World.GetClientWorldEntity(), modelinfo.GetVCollide(1), g_PhysDefaultObjectParams)!;

// TODO: staticpropmgr.CreateVPhysicsRepresentations(physenv, g_SolidSetup, NULL);
g_StaticPropMgr.CreateVPhysicsRepresentations(physenv, g_SolidSetup, null);
}
}
4 changes: 3 additions & 1 deletion Game.Server/Physics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
using System.Runtime.CompilerServices;
using System.Text;

using static Source.Engine.StaticPropMgrGlobals;

namespace Game.Server;

[EngineComponent]
Expand Down Expand Up @@ -380,7 +382,7 @@ public override void LevelInitPreEntity() {
}

public static IPhysicsObject? PhysCreateWorld(BaseEntity world){
// todo staticpropmgr
g_StaticPropMgr.CreateVPhysicsRepresentations(physenv, g_SolidSetup, world);
VCollide? worldCollide = modelinfo.GetVCollide(1);
return PhysCreateWorld_Shared(world, worldCollide, g_PhysDefaultObjectParams);
}
Expand Down
29 changes: 27 additions & 2 deletions Game.Shared/PhysicsShared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Source;
using Source.Common;
using Source.Common.Filesystem;
using Source.Common.Formats.BSP;
using Source.Common.Formats.Keyvalues;
using Source.Common.Mathematics;
using Source.Common.Physics;
Expand Down Expand Up @@ -79,6 +80,25 @@ public void Clear() {
}
#endif

public class SolidSetDefaults : IVPhysicsKeyHandler
{
Contents ContentsMask;

public void ParseKeyValue<T>(ref T data, ReadOnlySpan<char> key, ReadOnlySpan<char> value) {
if (stricmp(key, "contents") == 0)
ContentsMask = (Contents)atoi(value);
}

public void SetDefaults<T>(ref T data) {
Assert(typeof(T) == typeof(Solid));
ref Solid solid = ref Unsafe.As<T, Solid>(ref data);
solid.Params = g_PhysDefaultObjectParams;
ContentsMask = Contents.Solid;
}

public Contents GetContentsMask() => ContentsMask;
}

[EngineComponent]
public static class PhysicsSharedGlobals
{
Expand Down Expand Up @@ -116,6 +136,8 @@ public static class PhysicsSharedGlobals
EnableCollisions = true
};

public static readonly SolidSetDefaults g_SolidSetup = new();

public static void AddSurfacepropFile(ReadOnlySpan<char> filename, IPhysicsSurfaceProps props, IFileSystem fileSystem) {
using IFileHandle? file = fileSystem.Open(filename, FileOpenOptions.Read | FileOpenOptions.Binary, "GAME");
if (file != null) {
Expand Down Expand Up @@ -367,7 +389,7 @@ public static bool PhysModelParseSolidByIndex(ref Solid solid, BaseEntity entity
Solid tmpSolid = default;
tmpSolid.Params = g_PhysDefaultObjectParams;

parse.ParseSolid(ref tmpSolid, null);
parse.ParseSolid(ref tmpSolid, g_SolidSetup);

if (solidIndex < 0 || tmpSolid.Index == solidIndex) {
parsed = true;
Expand Down Expand Up @@ -441,7 +463,7 @@ public static bool PhysModelParseSolidByIndex(ref Solid solid, BaseEntity entity
if (strcmpi(block, "solid") == 0 || strcmpi(block, "staticsolid") == 0) {
solid = default;
solid.Params = defaultParams;
parse.ParseSolid(ref solid, null);
parse.ParseSolid(ref solid, g_SolidSetup);
solid.Params.EnableCollisions = true;
solid.Params.GameData = world;
solid.Params.Name = "world";
Expand All @@ -457,6 +479,9 @@ public static bool PhysModelParseSolidByIndex(ref Solid solid, BaseEntity entity
if (obj == null)
continue;

Assert(g_SolidSetup.GetContentsMask() != 0);
obj.SetContents((uint)g_SolidSetup.GetContentsMask());

worldPhysics ??= obj;
}
else if (strcmpi(block, "fluid") == 0) {
Expand Down
2 changes: 1 addition & 1 deletion Source.Common/Engine/IStaticPropMgr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public interface IStaticPropMgr
{
void CreateVPhysicsRepresentations(IPhysicsEnvironment physenv, IVPhysicsKeyHandler defaults, object gameData);
void CreateVPhysicsRepresentations(IPhysicsEnvironment physenv, IVPhysicsKeyHandler defaults, object? gameData);

void TraceRayAgainstStaticProp(Ray ray, int staticPropIndex, Trace tr);

Expand Down
67 changes: 64 additions & 3 deletions Source.Engine/StaticPropMgr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,10 @@ public void GetStaticPropMaterialColorAndLighting(Trace trace, int staticPropInd
throw new NotImplementedException();
}

public void CreateVPhysicsRepresentations(IPhysicsEnvironment physenv, IVPhysicsKeyHandler defaults, object gameData) {
throw new NotImplementedException();
public void CreateVPhysicsRepresentations(IPhysicsEnvironment physenv, IVPhysicsKeyHandler defaults, object? gameData) {
int count = StaticProps.Count;
for (int i = count; --i >= 0;)
StaticProps[i].CreateVPhysics(physenv, defaults, gameData);
}

public void GetAllStaticProps(List<ICollideable> output) {
Expand Down Expand Up @@ -575,6 +577,20 @@ void ChangeRenderGroup(StaticProp prop) {

public class StaticProp : IClientUnknown, IClientRenderable, ICollideable
{
static readonly ObjectParams g_PhysDefaultObjectParams = new() {
MassCenterOverrideFn = null,
Mass = 1.0f,
Inertia = 1.0f,
Damping = 0.1f,
RotDamping = 0.1f,
RotInertiaLimit = 0.05f,
Name = "DEFAULT",
GameData = null,
Volume = 0f,
DragCoefficient = 1.0f,
EnableCollisions = true
};

Vector3 Origin;
QAngle Angles;
Model? Model;
Expand Down Expand Up @@ -872,7 +888,52 @@ public void CleanUpRenderHandle() {
public ClientRenderHandle_t GetRenderHandle() => renderHandle;
public void SetAlpha(byte alpha) => Alpha = alpha;

public void CreateVPhysics(IPhysicsEnvironment physenv, IVPhysicsKeyHandler defaults, object gameData) => throw new NotImplementedException();
public void CreateVPhysics(IPhysicsEnvironment physenv, IVPhysicsKeyHandler defaults, object? gameData) {
if (Solid == (byte)SolidType.None)
return;

VCollide? vcollide = null;
Solid solid = default;
PhysCollide? physCollide;

if (Model != null && Solid == (byte)SolidType.VPhysics)
vcollide = CM.VCollideForModel(-1, Model);

if (vcollide != null) {
physCollide = vcollide.Solids![0];

IVPhysicsKeyParser parse = physcollision.VPhysicsKeyParserCreate(vcollide.KeyValues!);
while (!parse.Finished()) {
ReadOnlySpan<char> block = parse.GetCurrentBlockName();
if (strcmpi(block, "solid") == 0) {
parse.ParseSolid(ref solid, defaults);
break;
}
else
parse.SkipBlock();
}
physcollision.VPhysicsKeyParserDestroy(parse);
}
else {
if (Solid != (byte)SolidType.BBox) {
ReadOnlySpan<char> model = Model != null ? modelLoader.GetName(Model) : "unknown model";
Warning($"Map Error: Static prop with bogus solid type {Solid}! ({model})\n");
Solid = (byte)SolidType.None;
return;
}

physCollide = physcollision.BBoxToCollide(Model!.Mins, Model.Maxs);
solid.Params = g_PhysDefaultObjectParams;
}

Assert(physCollide != null);
solid.Params.EnableCollisions = true;
solid.Params.GameData = gameData;
solid.Params.Name = "prop_static";

int surfaceData = (int)physprop.GetSurfaceIndex(((ReadOnlySpan<char>)solid.SurfaceProp).SliceNullTerminatedString());
physenv.CreatePolyObjectStatic(physCollide!, surfaceData, Origin, Angles, ref solid.Params);
}

public float Radius() => radius;
public int Flags() => flags;
Expand Down
Loading