From 2b73e0c55373eeb3e2d40527b656511f0a15075e Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 21 Apr 2017 15:07:26 +1000 Subject: [PATCH] Ensure access is threadsafe --- MCGalaxy/Entity/Entity.cs | 16 +++++------ MCGalaxy/Entity/Structs.cs | 35 +++++++++++++++++++++++- MCGalaxy/Player/Group/GroupProperties.cs | 5 ++-- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/MCGalaxy/Entity/Entity.cs b/MCGalaxy/Entity/Entity.cs index 3b2cf7344..002e05643 100644 --- a/MCGalaxy/Entity/Entity.cs +++ b/MCGalaxy/Entity/Entity.cs @@ -16,21 +16,21 @@ permissions and limitations under the Licenses. */ using System; +using System.Threading; namespace MCGalaxy { /// Represents a player or an NPC. public abstract class Entity { - // Raw orientation/position - NOT threadsafe - protected Orientation _rot; - protected Position _pos; + // Raw orientation/position - access must be threadsafe + int _rot; + long _pos; // Last sent orientation/position, for delta calculation protected internal Orientation lastRot; protected internal Position lastPos; internal bool supportsExtPositions; - // TODO: struct assignment needs to be THREADSAFE /// Model name of this entity. @@ -45,14 +45,14 @@ namespace MCGalaxy { /// Gets or sets the orientation of this entity. public Orientation Rot { - get { return _rot; } - set { _rot = value; OnSetRot(); } + get { return Orientation.Unpack(Thread.VolatileRead(ref _rot)); } + set { Thread.VolatileWrite(ref _rot, value.Pack()); OnSetRot(); } } /// Gets or sets the position of this entity. public Position Pos { - get { return _pos; } - set { _pos = value; OnSetPos(); } + get { return Position.Unpack(Thread.VolatileRead(ref _pos)); } + set { Thread.VolatileWrite(ref _pos, value.Pack()); OnSetPos(); } } /// Sets only the yaw and pitch of the orientation of this entity. diff --git a/MCGalaxy/Entity/Structs.cs b/MCGalaxy/Entity/Structs.cs index b4a06177f..f1bd5f49f 100644 --- a/MCGalaxy/Entity/Structs.cs +++ b/MCGalaxy/Entity/Structs.cs @@ -18,7 +18,7 @@ using System; namespace MCGalaxy { - + /// Represents the position of an entity in the world. public struct Position: IEquatable { @@ -62,6 +62,27 @@ namespace MCGalaxy { public static bool operator == (Position a, Position b) { return a.Equals(b); } public static bool operator != (Position a, Position b) { return !a.Equals(b); } + + + const long mask = 0x1FFFFF; + internal long Pack() { + return (X & mask) | ((Y & mask) << 21) | ((Z & mask) << 42); + } + + internal static Position Unpack(long raw) { + Position pos; + pos.X = SignExtend(raw); + pos.Y = SignExtend(raw >> 21); + pos.Z = SignExtend(raw >> 42); + return pos; + } + + static int SignExtend(long parts) { + int value = (int)(parts & mask); + value <<= (32 - 21); + value >>= (32 - 21); + return value; + } } @@ -92,5 +113,17 @@ namespace MCGalaxy { public static byte DegreesToPacked(int degrees) { return (byte)(degrees * 256 / 360); } + + + internal int Pack() { + return RotX | (RotY << 8) | (RotZ << 16) | HeadX; + } + + internal static Orientation Unpack(int raw) { + Orientation rot; + rot.RotX = (byte)raw; rot.RotY = (byte)(raw >> 8); + rot.RotZ = (byte)(raw >> 16); rot.HeadX = (byte)(raw >> 24); + return rot; + } } } diff --git a/MCGalaxy/Player/Group/GroupProperties.cs b/MCGalaxy/Player/Group/GroupProperties.cs index 67d828abe..e7f52522c 100644 --- a/MCGalaxy/Player/Group/GroupProperties.cs +++ b/MCGalaxy/Player/Group/GroupProperties.cs @@ -23,10 +23,9 @@ using System.IO; namespace MCGalaxy { public sealed class GroupProperties { - const string filename = "properties/ranks.properties"; public static void InitAll() { Group grp = null; - PropertiesFile.Read(filename, ref grp, ParseProperty, '=', false); + PropertiesFile.Read(Paths.RankPropsFile, ref grp, ParseProperty, '=', false); if (grp != null) AddGroup(ref grp); } @@ -115,7 +114,7 @@ namespace MCGalaxy { /// Save givenList group /// The list of groups to save public static void SaveGroups(List givenList) { - using (StreamWriter w = new StreamWriter(filename)) { + using (StreamWriter w = new StreamWriter(Paths.RankPropsFile)) { w.WriteLine("#Version 3"); w.WriteLine("#RankName = string"); w.WriteLine("#\tThe name of the rank, use capitalization.");