Skip to content

Instantly share code, notes, and snippets.

@Daomephsta
Last active September 29, 2017 04:06
Show Gist options
  • Save Daomephsta/5d0176f3465c1f60a8f90fecb07c8f62 to your computer and use it in GitHub Desktop.
Save Daomephsta/5d0176f3465c1f60a8f90fecb07c8f62 to your computer and use it in GitHub Desktop.
PingTool Server Packet Serialiser
namespace Leviathan.PingTool
{
public class PingCollection
{
public struct Ping
{
public enum PingType : byte
{
LOOK
}
public class RecipientType
{
public static readonly RecipientType ANY = new RecipientType((sender, recipient) => true);
public static readonly RecipientType FACTION_AND_ALLIES = new RecipientType((sender, recipient) => true);
public static readonly RecipientType FACTION = new RecipientType((sender, recipient) => true);
private static readonly RecipientType[] TYPES = { ANY, FACTION, FACTION_AND_ALLIES };
private Func<IMyCharacter, IMyCharacter, bool> matcher;
public RecipientType(Func<IMyCharacter, IMyCharacter, bool> matcher)
{
this.matcher = matcher;
}
public static RecipientType[] Types()
{
return TYPES;
}
public bool Matches(IMyCharacter recipient)
{
return matcher(MyAPIGateway.Session.Player.Character, recipient);
}
public int Ordinal()
{
return Array.FindIndex(TYPES, type => type == this);
}
}
public PingType Type
{
get;
set;
}
public RecipientType RecipentMatcher
{
get;
set;
}
public double SendDistance
{
get;
set;
}
public TimeSpan DespawnTime
{
get;
set;
}
public static Ping Create(PingType type, RecipientType recipient, double sendDistance)
{
return Create(type, TimeSpan.FromSeconds(5), recipient, sendDistance);
}
public static Ping Create(PingType type, TimeSpan despawnTime, RecipientType recipient, double sendDistance)
{
Ping ping = new Ping();
ping.Type = type;
ping.DespawnTime = despawnTime;
ping.RecipentMatcher = recipient;
ping.SendDistance = sendDistance;
return ping;
}
}
private List<Ping> pings = new List<Ping>();
public void AddPing(Ping ping)
{
//Add ping to local ping list
this.pings.Add(ping);
//Determine recipients of this ping
VRageMath.BoundingSphereD boundingSphere = new VRageMath.BoundingSphereD(MyAPIGateway.Session.Player.GetPosition(), ping.SendDistance);
List<IMyCharacter> recipients = MyAPIGateway.Entities.GetEntitiesInSphere(ref boundingSphere).Where(entity => entity is IMyCharacter && entity != MyAPIGateway.Session.Player.Character)
.Select(entity => (IMyCharacter)entity).Where(character => ping.RecipentMatcher.Matches(character)).ToList();
//Serialise ping and recipients into bytes
//Recipients, ping type, ping recipient matcher, ping send distance, ping despawn time in seconds
int byteCount = recipients.Count * sizeof(ulong) + sizeof(byte) + sizeof(byte) + sizeof(double) + sizeof(double);
int offset = 0;
byte[] bytes = new byte[byteCount];
//Recipients
foreach (IMyCharacter recipient in recipients)
{
long controllerIdentity = recipient.ControllerInfo.ControllingIdentityId;
ulong steamID = MyAPIGateway.Players.TryGetSteamId(controllerIdentity);
if (steamID != 0)
{
bytes.ArrayAdd(BitConverter.GetBytes(controllerIdentity), offset);
offset += sizeof(ulong);
}
}
//Ping type
bytes[offset++] = (byte) ping.Type;
//Recipient matcher
bytes[offset++] = Convert.ToByte(ping.RecipentMatcher.Ordinal());
//Send distance
bytes.ArrayAdd(BitConverter.GetBytes(ping.SendDistance), offset);
offset += sizeof(double);
//Despawn time in seconds
bytes.ArrayAdd(BitConverter.GetBytes(ping.DespawnTime.TotalSeconds), offset);
offset += sizeof(double);
//Send bytes to server
MyAPIGateway.Multiplayer.SendMessageToServer(PingSyncHandler.SERVER_SYNC_PACKET, bytes);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment