Skip to content

Commit

Permalink
Merge pull request StarCoreSE#149 from Jnick-24/Projectile-Guidance
Browse files Browse the repository at this point in the history
netcode update #1230
  • Loading branch information
ari-steas authored Feb 17, 2024
2 parents 4eb1807 + dc075d6 commit 881c9f3
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
using Heart_Module.Data.Scripts.HeartModule.ErrorHandler;
using Heart_Module.Data.Scripts.HeartModule.ExceptionHandler;
using Heart_Module.Data.Scripts.HeartModule.Projectiles;
using Heart_Module.Data.Scripts.HeartModule.Projectiles.ProjectileNetworking;
using Heart_Module.Data.Scripts.HeartModule.Utility;
using Heart_Module.Data.Scripts.HeartModule.Weapons;
using ProtoBuf;
using RichHudFramework.Client;
using Sandbox.ModAPI;
using System;
using VRage.Game.Components;
using VRage.Game.ModAPI;
using VRage.ModAPI;
using VRageMath;
using YourName.ModName.Data.Scripts.HeartModule.Weapons.Setup.Adding;
using YourName.ModName.Data.Scripts.HeartModule.Weapons.Setup.Hiding;

Expand Down Expand Up @@ -68,13 +71,17 @@ public override void LoadData()
{
CriticalHandle.ThrowCriticalException(ex, typeof(HeartLoad));
}

HeartData.I.Log.Log("Small: " + MyAPIGateway.Utilities.SerializeToBinary(new n_SerializableProjectileInfo(1, Vector3.One, Vector3.Forward, 3, 235345645)).Length);
HeartData.I.Log.Log("Large: " + MyAPIGateway.Utilities.SerializeToBinary(new n_SerializableProjectileInfo(1, Vector3.One, Vector3.Forward, 3, 235345645, 345345, 3453454, 124334)).Length);
HeartData.I.Log.Log("Event: " + MyAPIGateway.Utilities.SerializeToBinary(new n_SerializableFireEvent(1, 234, Vector3.One, 12434)).Length);
}

public override void UpdateAfterSimulation()
{
// This has the power to shut down the server. Afaik the only way to do this is throwing an exception. Yeah.
handle.Update();

byte[] a = BitConverter.GetBytes(1.2f);
try
{
if (HeartData.I.IsSuspended)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,10 @@ public float CheckHits()

public void UpdateFromSerializable(n_SerializableProjectile projectile)
{
QueuedDispose = !projectile.IsActive;
if (projectile.IsActive.HasValue)
QueuedDispose = !projectile.IsActive.Value;

LastUpdate = projectile.Timestamp;
LastUpdate = DateTime.Now.Date.AddMilliseconds(projectile.TimestampFromMidnight).Ticks;
float delta = (DateTime.Now.Ticks - LastUpdate) / (float)TimeSpan.TicksPerSecond;

// The following values may be null to save network load
Expand Down Expand Up @@ -342,14 +343,14 @@ public n_SerializableProjectile AsSerializable(int DetailLevel = 1)
{
n_SerializableProjectile projectile = new n_SerializableProjectile()
{
IsActive = !QueuedDispose,
Id = Id,
Timestamp = DateTime.Now.Ticks,
TimestampFromMidnight = (uint) DateTime.Now.TimeOfDay.TotalMilliseconds, // Surely this will not bite me in the ass later
};

switch (DetailLevel)
{
case 0:
projectile.IsActive = !QueuedDispose;
projectile.DefinitionId = DefinitionId;
projectile.Position = Position;
projectile.Direction = Direction;
Expand All @@ -358,12 +359,20 @@ public n_SerializableProjectile AsSerializable(int DetailLevel = 1)
//projectile.Velocity = Velocity;
break;
case 1:
projectile.IsActive = !QueuedDispose;
projectile.Position = Position;
if (IsHitscan || Definition.Guidance.Length > 0)
projectile.Direction = Direction;
if (!IsHitscan && Definition.PhysicalProjectile.Acceleration > 0)
projectile.Velocity = Velocity;
break;
case 3:
projectile.DefinitionId = DefinitionId;
projectile.Position = Position;
projectile.Direction = Direction;
projectile.InheritedVelocity = InheritedVelocity;
projectile.Firer = Firer;
break;
}

return projectile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void UpdateProjectileSync(n_SerializableProjectile projectile)
if (MyAPIGateway.Session.IsServer)
return;

if (IsIdAvailable(projectile.Id) && projectile.IsActive && projectile.DefinitionId.HasValue)
if (IsIdAvailable(projectile.Id) && projectile.DefinitionId.HasValue)
{
if (projectile.Firer != null)
{
Expand All @@ -116,7 +116,7 @@ public void UpdateProjectileSync(n_SerializableProjectile projectile)
Projectile p = GetProjectile(projectile.Id);
if (p != null)
p.UpdateFromSerializable(projectile);
else if (projectile.IsActive)
else if (projectile.IsActive ?? false)
HeartData.I.Net.SendToServer(new n_ProjectileRequest(projectile.Id));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ namespace Heart_Module.Data.Scripts.HeartModule.Projectiles
{
partial class ProjectileManager
{
const int MaxProjectilesSynced = 50; // This value should result in ~100kB/s up per player.
const int MaxProjectilesSynced = 100; // This value should result in ~100kB/s up per player.
const int NetworkInterval = 2;

public Dictionary<ulong, LinkedList<n_SerializableProjectile>> SyncStream = new Dictionary<ulong, LinkedList<n_SerializableProjectile>>();

Expand Down Expand Up @@ -40,9 +41,10 @@ public void QueueSync(Projectile projectile, IMyPlayer Player, int DetailLevel =
SyncStream[Player.SteamUserId].AddLast(sP); // Queue other projectile updates last
}

int tick = 0;
public void UpdateSync()
{
if (MyAPIGateway.Session.IsServer && MyAPIGateway.Multiplayer.MultiplayerActive)
if (MyAPIGateway.Session.IsServer && MyAPIGateway.Multiplayer.MultiplayerActive && tick % NetworkInterval == 0)
{
foreach (var player in HeartData.I.Players) // Ensure that all players are being synced
{
Expand Down Expand Up @@ -71,6 +73,8 @@ public void UpdateSync()
}
}
}

tick++;
}

private void SyncPlayerProjectiles(IMyPlayer player)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using VRageMath;

namespace Heart_Module.Data.Scripts.HeartModule.Projectiles.ProjectileNetworking
{
[ProtoContract]
internal class n_SerializableProjectileInfo
{
public n_SerializableProjectileInfo() { }

public n_SerializableProjectileInfo(uint uniqueProjectileId, Vector3 positionRelativeToPlayer, Vector3 direction, int definitionId, int msFromMidnight, long? firerEntityId = null, long? targetEntityId = null, uint? projectileAge = null)
{
UniqueProjectileId = uniqueProjectileId;
playerRelativeX = positionRelativeToPlayer.X;
playerRelativeY = positionRelativeToPlayer.Y;
playerRelativeZ = positionRelativeToPlayer.Z;
directionX = direction.X;
directionY = direction.Y;
directionZ = direction.Z;
DefinitionId = definitionId;
MillisecondsFromMidnight = msFromMidnight;
FirerEntityId = firerEntityId;
TargetEntityId = targetEntityId;
ProjectileAge = projectileAge;
}

[ProtoMember(21)] public uint UniqueProjectileId;

[ProtoMember(22)] private float playerRelativeX;
[ProtoMember(23)] private float playerRelativeY;
[ProtoMember(24)] private float playerRelativeZ;
public Vector3 PlayerRelativePosition => new Vector3(playerRelativeX, playerRelativeY, playerRelativeZ); // just using a Vector3 adds 2 extra bytes (!!!)

[ProtoMember(25)] private float directionX;
[ProtoMember(26)] private float directionY;
[ProtoMember(27)] private float directionZ;
public Vector3 Direction => new Vector3(directionX, directionY, directionZ); // just using a Vector3 adds 2 extra bytes (!!!)

[ProtoMember(28)] public int DefinitionId;
[ProtoMember(29)] public int MillisecondsFromMidnight;
[ProtoMember(30)] public long? FirerEntityId;

[ProtoMember(31)] public long? TargetEntityId;
[ProtoMember(32)] public uint? ProjectileAge;
}

[ProtoContract]
internal class n_SerializableFireEvent
{
public n_SerializableFireEvent() { }

public n_SerializableFireEvent(int firerWeaponId, uint uniqueProjectileId, Vector3 direction, int millisecondsFromMidnight)
{
FirerWeaponId = firerWeaponId;
UniqueProjectileId = uniqueProjectileId;
directionX = direction.X;
directionY = direction.Y;
directionZ = direction.Z;
MillisecondsFromMidnight = millisecondsFromMidnight;
}

[ProtoMember(21)] int FirerWeaponId;
[ProtoMember(22)] uint UniqueProjectileId;

[ProtoMember(23)] float directionX;
[ProtoMember(24)] float directionY;
[ProtoMember(25)] float directionZ;
public Vector3 Direction => new Vector3(directionX, directionY, directionZ); // just using a Vector3 adds 2 extra bytes (!!!)


[ProtoMember(26)] int MillisecondsFromMidnight;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace Heart_Module.Data.Scripts.HeartModule.Projectiles.StandardClasses
public class n_SerializableProjectile : PacketBase
{
// ProtoMember IDs are high to avoid collisions
[ProtoMember(22)] public bool IsActive = true;
[ProtoMember(22)] public bool? IsActive = true;
[ProtoMember(23)] public uint Id;
[ProtoMember(211)] public long Timestamp;
[ProtoMember(211)] public uint TimestampFromMidnight; // surely this will not bite me in the ass later

// All non-required values are nullable
[ProtoMember(24)] public int? DefinitionId;
Expand Down

0 comments on commit 881c9f3

Please sign in to comment.