Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Point3D/GameLocation #472

Merged
merged 18 commits into from
Jan 16, 2024
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions DOLServer/ConsolePacketLib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using log4net;
using DOL.Database;
using DOL.GS.Profession;
using DOL.GS.Geometry;

namespace DOLGameServerConsole
{
Expand Down Expand Up @@ -163,6 +164,7 @@ public void SendDisableSkill(ICollection<Tuple<Skill, int>> skills) { }
public void SendUpdateIcons(IList changedEffects, ref int lastUpdateEffectsCount) { }
public void SendLevelUpSound() { }
public void SendRegionEnterSound(byte soundId) { }
public void SendSoundEffect(ushort soundId, Position position, ushort radius) { }
public void SendSoundEffect(ushort soundId, ushort zoneId, ushort x, ushort y, ushort z, ushort radius) { }
public void SendDebugMessage(string format, params object[] parameters) { }
public void SendDebugPopupMessage(string format, params object[] parameters) { }
Expand All @@ -179,7 +181,9 @@ public void SendQuestUpdate(AbstractQuest quest) { }
public void SendConcentrationList() { }
public void SendUpdateCraftingSkills() { }
public void SendChangeTarget(GameObject newTarget) { }
[Obsolete("Use .SendChangeGroundTarget(Coordinate) instead!")]
public void SendChangeGroundTarget(Point3D newTarget) { }
public void SendChangeGroundTarget(Coordinate newTarget) { }
public void SendPetWindow(GameLiving pet, ePetWindowAction windowAction, eAggressionState aggroState, eWalkState walkState) { }
public void SendKeepInfo(IGameKeep keep) { }
public void SendKeepRealmUpdate(IGameKeep keep) { }
Expand Down Expand Up @@ -243,6 +247,7 @@ public void SendMarketExplorerWindow(IList<InventoryItem> items, byte page, byte
public void SendConsignmentMerchantMoney(long money) { }
public void SendMinotaurRelicMapRemove(byte id) { }
public void SendMinotaurRelicMapUpdate(byte id, ushort region, int x, int y, int z) { }
public void SendMinotaurRelicMapUpdate(byte id, Position position) { }
public virtual void SendMinotaurRelicWindow(GamePlayer player, int spell, bool flag) { }
public virtual void SendMinotaurRelicBarUpdate(GamePlayer player, int xp) { }
public virtual void SendBlinkPanel(byte flag) { }
Expand Down
15 changes: 4 additions & 11 deletions GameServer/GameClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using DOL.Network;

using log4net;
using DOL.GS.Geometry;

namespace DOL.GS
{
Expand Down Expand Up @@ -723,18 +724,10 @@ public void SavePlayer()
//<**loki**>
if (Properties.KICK_IDLE_PLAYER_STATUS)
{
//Time playing
var connectedtime = DateTime.Now.Subtract(m_account.LastLogin).TotalMinutes;
//Lets get our player from DB.
var getp = GameServer.Database.FindObjectByKey<DOLCharacters>(m_player.InternalID);
//Let get saved poistion from DB.
int[] oldloc = { getp.Xpos, getp.Ypos, getp.Zpos, getp.Direction, getp.Region };
//Lets get current player Gloc.
int[] currentloc = { m_player.X, m_player.Y, m_player.Z, m_player.Heading, m_player.CurrentRegionID };
//Compapre Old and Current.
bool check = oldloc.SequenceEqual(currentloc);
//If match
if (check)
var dbCharacter = GameServer.Database.FindObjectByKey<DOLCharacters>(m_player.InternalID);

if (dbCharacter.GetPosition() == Player.Position)
{
if (connectedtime > Properties.KICK_IDLE_PLAYER_TIME)
{
Expand Down
60 changes: 60 additions & 0 deletions GameServer/Geometry/Angle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;

namespace DOL.GS.Geometry;

public struct Angle
{
private const int STEPS_TO_CIRCUMVOLUTION = 360 * 4096;
private const int HEADING_TO_STEPS = STEPS_TO_CIRCUMVOLUTION / 4096;
private const int DEGREE_TO_STEPS = STEPS_TO_CIRCUMVOLUTION / 360;
private const double RADIANS_TO_STEPS = STEPS_TO_CIRCUMVOLUTION / 2 / Math.PI;

private int steps;

///<remarks>for internal use only</remarks>
private static Angle Steps(int steps)
{
steps %= STEPS_TO_CIRCUMVOLUTION;
if (steps < 0) steps += STEPS_TO_CIRCUMVOLUTION;
return new() { steps = steps };
}

public static Angle Heading(int heading)
=> Steps(heading * HEADING_TO_STEPS);

public static Angle Degrees(int degrees)
=> Steps(degrees * DEGREE_TO_STEPS);

public static Angle Radians(double radians)
=> Steps((int)Math.Round(radians * RADIANS_TO_STEPS));

public double InRadians => steps / RADIANS_TO_STEPS;
public ushort InDegrees => (ushort)(steps / DEGREE_TO_STEPS);
public ushort InHeading => (ushort)(steps / HEADING_TO_STEPS);

public override bool Equals(object obj)
{
if (obj is Angle angle) return angle.steps == steps;
return false;
}

public override int GetHashCode()
=> base.GetHashCode();

public override string ToString()
=> steps.ToString();

public static bool operator ==(Angle a, Angle b)
=> a.Equals(b);

public static bool operator !=(Angle a, Angle b)
=> !a.Equals(b);

public static Angle operator +(Angle a, Angle b)
=> Steps(a.steps + b.steps);

public static Angle operator -(Angle a, Angle b)
=> Steps(a.steps - b.steps);

public static readonly Angle Zero = new() { steps = 0 };
}
63 changes: 63 additions & 0 deletions GameServer/Geometry/Coordinate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace DOL.GS.Geometry;

public struct Coordinate
{
private Vector coordinate { get; init; }

public int X => coordinate.X;
public int Y => coordinate.Y;
public int Z => coordinate.Z;

public static Coordinate Create(int x = 0, int y = 0, int z = 0)
=> new() { coordinate = Vector.Create(x, y, z) };

public Coordinate With(int? x = null, int? y = null, int? z = null)
=> new() { coordinate = Vector.Create(x ?? X, y ?? Y, z ?? Z) };

public double DistanceTo(Position pos, bool ignoreZ = false)
=> DistanceTo(pos.Coordinate, ignoreZ);

public double DistanceTo(Coordinate loc, bool ignoreZ = false)
{
if (Equals(Nowhere) || loc.Equals(Nowhere)) return double.PositiveInfinity;

if (ignoreZ) return (loc - this).Length2D;
else return (loc - this).Length;
}

public Angle GetOrientationTo(Coordinate loc)
=> (loc - this).Orientation;

public static Coordinate operator +(Coordinate loc, Vector v)
=> new() { coordinate = loc.coordinate + v };

public static Coordinate operator -(Coordinate loc, Vector v)
=> new() { coordinate = loc.coordinate - v };

public static Vector operator -(Coordinate locA, Coordinate locB)
=> Vector.Create(x: locA.X - locB.X, y: locA.Y - locB.Y, z: locA.Z - locB.Z);

public static bool operator ==(Coordinate a, Coordinate b)
=> a.Equals(b);

public static bool operator !=(Coordinate a, Coordinate b)
=> !a.Equals(b);

public override bool Equals(object obj)
{
if (obj is Coordinate loc)
{
return X == loc.X && Y == loc.Y && Z == loc.Z;
}
return false;
}

public override int GetHashCode()
=> base.GetHashCode();

public override string ToString()
=> $"{X}, {Y}, {Z}";

public readonly static Coordinate Nowhere = Create(-1, -1, -1);
public readonly static Coordinate Zero = Create(0, 0, 0);
}
14 changes: 14 additions & 0 deletions GameServer/Geometry/CoordinateTransitionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace DOL.GS.Geometry;

public static class CoordinateTransitionExtensions
{
[Obsolete("This extension is transitional and going to be removed.")]
public static Point3D ToPoint3D(this Coordinate coordinate)
=> new Point3D(coordinate.X, coordinate.Y, coordinate.Z);

[Obsolete("This extension is transitional and going to be removed.")]
public static Coordinate ToCoordinate(this IPoint3D point)
=> Coordinate.Create(point.X, point.Y, point.Z);
}
45 changes: 45 additions & 0 deletions GameServer/Geometry/DataObjectPositionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using DOL.Database;

namespace DOL.GS.Geometry;

public static class DataObjectPositionExtensions
{
public static Position GetPosition(this Mob mob)
=> Position.Create(mob.Region, mob.X, mob.Y, mob.Z, Angle.Heading(mob.Heading));

public static Position GetPosition(this Teleport teleport)
=> Position.Create((ushort)teleport.RegionID, teleport.X, teleport.Y, teleport.Z, Angle.Heading(teleport.Heading));

public static Position GetSourcePosition(this ZonePoint zonePoint)
=> Position.Create(zonePoint.SourceRegion, zonePoint.SourceX, zonePoint.SourceY, zonePoint.SourceZ);

public static Position GetTargetPosition(this ZonePoint zonePoint)
=> Position.Create(zonePoint.TargetRegion, zonePoint.TargetX, zonePoint.TargetY, zonePoint.TargetZ, Angle.Heading(zonePoint.TargetHeading));

public static Position GetPosition(this DOLCharacters dolc)
=> Position.Create((ushort)dolc.Region, dolc.Xpos, dolc.Ypos, dolc.Zpos, Angle.Heading(dolc.Direction));

public static void SetPosition(this DOLCharacters dolc, Position pos)
{
dolc.Region = pos.RegionID;
dolc.Xpos = pos.X;
dolc.Ypos = pos.Y;
dolc.Zpos = pos.Z;
dolc.Direction = pos.Orientation.InHeading;
}

public static Position GetBindPosition(this DOLCharacters dolc)
=> Position.Create((ushort)dolc.BindRegion, dolc.BindXpos, dolc.BindYpos, dolc.BindZpos, Angle.Heading(dolc.BindHeading));

public static Position GetPosition(this DBKeep dbKeep)
=> Position.Create(dbKeep.Region, dbKeep.X, dbKeep.Y, dbKeep.Z, Angle.Degrees(dbKeep.Heading));

public static void SetPosition(this DBKeep dbKeep, Position pos)
{
dbKeep.Region = pos.RegionID;
dbKeep.X = pos.X;
dbKeep.Y = pos.Y;
dbKeep.Z = pos.Z;
dbKeep.Heading = (ushort)pos.Orientation.InDegrees;
}
}
23 changes: 23 additions & 0 deletions GameServer/Geometry/LinePath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Linq;

namespace DOL.GS.Geometry;

public class LinePath
{
private Coordinate[] wayPoints = Array.Empty<Coordinate>();
private int indexCounter = 0;

public static LinePath Create(Coordinate[] wayPoints)
=> new LinePath() { wayPoints = wayPoints };

public Coordinate Start => wayPoints.Length == 0 ? Coordinate.Nowhere : wayPoints.First();

public Coordinate End => wayPoints.Length == 0 ? Coordinate.Nowhere : wayPoints.Last();

public void SelectNextWayPoint() => indexCounter++;

public Coordinate CurrentWayPoint => (indexCounter < PointCount - 1) ? wayPoints[indexCounter] : Coordinate.Nowhere;

public int PointCount => wayPoints.Length;
}
32 changes: 32 additions & 0 deletions GameServer/Geometry/Motion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;

namespace DOL.GS.Geometry;

public class Motion
{
public static Motion Create(Position start, Coordinate destination, short withSpeed)
=> new Motion() { Start = start, Destination = destination, Speed = withSpeed };

public int StartTimeInMilliSeconds { get; } = Environment.TickCount;
public Position Start { get; init; } = Position.Nowhere;
public Coordinate Destination { get; init; } = Coordinate.Nowhere;
public short Speed { get; init; } = 0;

public Position CurrentPosition
=> GetPositonAfter(Environment.TickCount - StartTimeInMilliSeconds);
public double FullDistance => Destination.DistanceTo(Start, ignoreZ: true);
public double RemainingDistance => Destination.DistanceTo(CurrentPosition, ignoreZ: true);

public Position GetPositonAfter(int elapsedTimeInMilliSeconds)
{
if (Speed == 0 || Start.Coordinate == Destination) return Start;

var distanceTravelled = Speed * elapsedTimeInMilliSeconds * 0.001;
if (Destination == Coordinate.Nowhere) return Start + Vector.Create(Start.Orientation, distanceTravelled);

var movementVector = Destination - Start.Coordinate;
if (distanceTravelled > FullDistance) return Position.Create(Start.RegionID, Destination, movementVector.Orientation);

return Start.With(movementVector.Orientation) + movementVector * (distanceTravelled / FullDistance);
}
}
82 changes: 82 additions & 0 deletions GameServer/Geometry/Position.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
namespace DOL.GS.Geometry;

public struct Position
{
public ushort RegionID { get; init; } = 0;
public Coordinate Coordinate { get; init; } = Coordinate.Zero;
public Angle Orientation { get; init; } = Angle.Zero;

public int X => Coordinate.X;
public int Y => Coordinate.Y;
public int Z => Coordinate.Z;

public Region Region => WorldMgr.GetRegion(RegionID);

public Position() { }

public static Position Create(ushort regionID, int x, int y, int z, ushort heading)
=> new() { RegionID = regionID, Coordinate = Coordinate.Create(x, y, z), Orientation = Angle.Heading(heading) };

public static Position Create(ushort regionID, int x = 0, int y = 0, int z = 0, Angle? orientation = null)
=> new() { RegionID = regionID, Coordinate = Coordinate.Create(x, y, z), Orientation = orientation ?? Angle.Zero };

public static Position CreateInZone(ushort zoneID, int x = 0, int y = 0, int z = 0, ushort heading = 0)
{
var zone = WorldMgr.GetZone(zoneID);
return Create(zone.ZoneRegion.ID, x + zone.Offset.X, y + zone.Offset.Y, z + zone.Offset.Z, heading);
}

public static Position Create(ushort regionID, Coordinate coordinate, ushort heading = 0)
=> new() { RegionID = regionID, Coordinate = coordinate, Orientation = Angle.Heading(heading) };

public static Position Create(ushort regionID, Coordinate coordinate, Angle orientation)
=> new() { RegionID = regionID, Coordinate = coordinate, Orientation = orientation };

public Position With(ushort? regionID = null, int? x = null, int? y = null, int? z = null, ushort? heading = null)
{
var newOrientation = heading != null ? Angle.Heading((ushort)heading) : Orientation;
var newRegionID = regionID ?? RegionID;
return Create(newRegionID, Coordinate.With(x, y, z), newOrientation);
}

public Position With(Coordinate coordinate)
=> Create(RegionID, coordinate, Orientation);

public Position With(Angle orientation)
=> Create(RegionID, Coordinate, orientation);

public Position TurnedAround()
=> With(orientation: Orientation + Angle.Degrees(180));

public static Position operator +(Position a, Vector b)
=> a.With(coordinate: a.Coordinate + b);

public static Position operator -(Position a, Vector b)
=> a.With(coordinate: a.Coordinate - b);

public static bool operator ==(Position a, Position b)
=> a.Equals(b);

public static bool operator !=(Position a, Position b)
=> !a.Equals(b);

public override bool Equals(object obj)
{
if (obj is Position otherPos)
{
return otherPos.RegionID == RegionID
&& otherPos.Coordinate.Equals(Coordinate)
&& otherPos.Orientation == Orientation;
}
return false;
}

public override int GetHashCode()
=> base.GetHashCode();

public override string ToString()
=> $"({Coordinate}, {Orientation.InHeading})";

public readonly static Position Nowhere = Create(regionID: ushort.MaxValue, Coordinate.Nowhere, Angle.Zero);
public readonly static Position Zero = new();
}
Loading