diff --git a/PolarisServer/ConsoleSystem.cs b/PolarisServer/ConsoleSystem.cs index 753823f..acd4d49 100644 --- a/PolarisServer/ConsoleSystem.cs +++ b/PolarisServer/ConsoleSystem.cs @@ -85,7 +85,8 @@ public class ConsoleSystem ConsoleKey.RightArrow, ConsoleKey.Home, ConsoleKey.End, - ConsoleKey.Delete + ConsoleKey.Delete, + ConsoleKey.Escape }; private const string Prompt = "Polaris> "; @@ -112,7 +113,11 @@ public ConsoleSystem() { Console.Title = "Polaris"; Console.CursorVisible = true; - SetSize(80, 24); + Console.Clear(); + + Width = Console.WindowWidth; + Height = Console.WindowHeight; + _maxCommandLineSize = Width - Prompt.Length; timer = new Timer(1000); timer.Elapsed += TimerRefresh; @@ -126,12 +131,18 @@ public ConsoleSystem() public void SetSize(int width, int height) { - Width = width; - Height = height; - - _maxCommandLineSize = width - Prompt.Length; + try + { + Console.SetWindowSize(width, height); - Console.SetWindowSize(width, height); + Width = width; + Height = height; + _maxCommandLineSize = width - Prompt.Length; + } + catch (Exception) + { + Logger.WriteWarning("[WRN] Failed to set console size to ({0},{1}).", width, height); + } } public void AddLine(ConsoleColor color, string text) @@ -143,7 +154,6 @@ public void AddLine(ConsoleColor color, string text) var useColors = PolarisApp.Config.UseConsoleColors; var saveColor = Console.ForegroundColor; - Console.SetCursorPosition(0, _commandRowInConsole); if (useColors) Console.ForegroundColor = color; Console.WriteLine(text); @@ -151,8 +161,7 @@ public void AddLine(ConsoleColor color, string text) if (useColors) Console.ForegroundColor = saveColor; - Console.WriteLine(); - _commandRowInConsole = Console.CursorTop - 1; + _commandRowInConsole = Console.CursorTop; RefreshCommandLine(); FixCursorPosition(); @@ -169,6 +178,8 @@ private void BlankDrawnCommandLine() Console.Write(' '); _lastDrawnCommandLineSize = 0; + + Console.CursorLeft = 0; } } @@ -176,7 +187,6 @@ private void RefreshCommandLine() { BlankDrawnCommandLine(); - Console.SetCursorPosition(0, _commandRowInConsole); Console.Write(Prompt); Console.Write(_commandLine); @@ -414,6 +424,13 @@ public void CheckInput() _commandIndex--; } + // Escape + if (_key.Key == ConsoleKey.Escape) + { + _commandLine = string.Empty; + _commandIndex = 0; + } + // Cursor movement if (_key.Key == ConsoleKey.LeftArrow && _commandLine.Length > 0 && _commandIndex > 0) _commandIndex--; diff --git a/PolarisServer/Models/PSOObject.cs b/PolarisServer/Models/PSOObject.cs index 749318c..d07420e 100644 --- a/PolarisServer/Models/PSOObject.cs +++ b/PolarisServer/Models/PSOObject.cs @@ -88,7 +88,7 @@ public override byte[] GenerateSpawnBlob() { PacketWriter writer = new PacketWriter(); writer.WriteStruct(Header); - writer.WritePosition(Position); + writer.Write(Position); writer.Write((UInt16)0); writer.WriteFixedLengthASCII(Name, 0x20); diff --git a/PolarisServer/Object/ObjectManager.cs b/PolarisServer/Object/ObjectManager.cs index d2ae32e..9112fcb 100644 --- a/PolarisServer/Object/ObjectManager.cs +++ b/PolarisServer/Object/ObjectManager.cs @@ -14,9 +14,7 @@ class ObjectManager { private static readonly ObjectManager instance = new ObjectManager(); - private Dictionary> zoneObjects = new Dictionary>(); - - private Dictionary allTheObjects = new Dictionary(); + private List> object_list = new List>(); private ObjectManager() { } @@ -34,10 +32,9 @@ public PSOObject[] GetObjectsForZone(string zone) { return new PSOObject[0]; } - if (!zoneObjects.ContainsKey(zone)) - { - Dictionary objects = new Dictionary(); + if (!object_list.Exists(o => o.Item1 == zone)) // Make sure objects for a zone are only loaded once + { // Collect from db using (var db = new PolarisEf()) { @@ -45,77 +42,78 @@ public PSOObject[] GetObjectsForZone(string zone) where dbo.ZoneName == zone select dbo; - foreach(var dbObject in dbObjects) + if (dbObjects.Count() > 0) { - var newObject = PSOObject.FromDBObject(dbObject); - objects.Add(newObject.Header.ID, newObject); - allTheObjects.Add(newObject.Header.ID, newObject); - Logger.WriteInternal("[OBJ] Loaded object {0} for zone {1} from the DB.", newObject.Name, zone); - } - } - - // Fallback - if (objects.Count < 1 && Directory.Exists("Resources/objects/" + zone)) - { - Logger.WriteWarning("[OBJ] No objects defined for zone {0} in the database, falling back to filesystem!", zone); - var objectPaths = Directory.GetFiles("Resources/objects/" + zone); - Array.Sort(objectPaths); - foreach (var path in objectPaths) - { - if (Path.GetExtension(path) == ".bin") + foreach (var dbObject in dbObjects) { - var newObject = PSOObject.FromPacketBin(File.ReadAllBytes(path)); - objects.Add(newObject.Header.ID, newObject); - allTheObjects.Add(newObject.Header.ID, newObject); - Logger.WriteInternal("[OBJ] Loaded object ID {0} with name {1} pos: ({2}, {3}, {4})", newObject.Header.ID, newObject.Name, newObject.Position.PosX, - newObject.Position.PosY, newObject.Position.PosZ); + var newObject = PSOObject.FromDBObject(dbObject); + object_list.Add(new Tuple(zone, newObject)); + Logger.WriteInternal("[OBJ] Loaded object {0} for zone {1} from the DB.", newObject.Name, zone); } - else if (Path.GetExtension(path) == ".json") + } + // Fallback + else if (Directory.Exists("Resources/objects/" + zone)) + { + Logger.WriteWarning("[OBJ] No objects defined for zone {0} in the database, falling back to filesystem!", zone); + var objectPaths = Directory.GetFiles("Resources/objects/" + zone); + Array.Sort(objectPaths); + foreach (var path in objectPaths) { - var newObject = JsonConvert.DeserializeObject(File.ReadAllText(path)); - objects.Add(newObject.Header.ID, newObject); - allTheObjects.Add(newObject.Header.ID, newObject); - Logger.WriteInternal("[OBJ] Loaded object ID {0} with name {1} pos: ({2}, {3}, {4})", newObject.Header.ID, newObject.Name, newObject.Position.PosX, - newObject.Position.PosY, newObject.Position.PosZ); + if (Path.GetExtension(path) == ".bin") + { + var newObject = PSOObject.FromPacketBin(File.ReadAllBytes(path)); + object_list.Add(new Tuple(zone, newObject)); + Logger.WriteInternal("[OBJ] Loaded object ID {0} with name {1} pos: ({2}, {3}, {4})", newObject.Header.ID, newObject.Name, newObject.Position.PosX, + newObject.Position.PosY, newObject.Position.PosZ); + } + else if (Path.GetExtension(path) == ".json") + { + var newObject = JsonConvert.DeserializeObject(File.ReadAllText(path)); + object_list.Add(new Tuple(zone, newObject)); + Logger.WriteInternal("[OBJ] Loaded object ID {0} with name {1} pos: ({2}, {3}, {4})", newObject.Header.ID, newObject.Name, newObject.Position.PosX, + newObject.Position.PosY, newObject.Position.PosZ); + } } - } + } + else + { + Logger.WriteWarning("[OBJ] Filesystem directory for zone {0} does not exist!", zone); + } } - - zoneObjects.Add(zone, objects); - } - return zoneObjects[zone].Values.ToArray(); - + // TODO: returning an IEnumerable looks more favorable than converting to an array + return (from o in object_list + where o.Item1 == zone + select o.Item2).ToArray(); } internal PSONPC[] getNPCSForZone(string zone) { - List npcs = new List(); - using (var db = new PolarisEf()) + if (!object_list.Exists(o => o.Item1 == zone && o.Item2 as PSONPC != null)) // Make sure NPCs for a zone are only loaded once { - var dbNpcs = from n in db.NPCs - where n.ZoneName == zone - select n; - - foreach (NPC npc in dbNpcs) + using (var db = new PolarisEf()) { - PSONPC dNpc = new PSONPC(); - dNpc.Header = new ObjectHeader((uint)npc.EntityID, EntityType.Object); - dNpc.Position = new PSOLocation(npc.RotX, npc.RotY, npc.RotZ, npc.RotW, npc.PosX, npc.PosY, npc.PosZ); - dNpc.Name = npc.NPCName; + var dbNpcs = from n in db.NPCs + where n.ZoneName == zone + select n; - npcs.Add(dNpc); - if (!zoneObjects[zone].ContainsKey(dNpc.Header.ID)) + foreach (NPC npc in dbNpcs) { - zoneObjects[zone].Add(dNpc.Header.ID, dNpc); + PSONPC dNpc = new PSONPC(); + dNpc.Header = new ObjectHeader((uint)npc.EntityID, EntityType.Object); + dNpc.Position = new PSOLocation(npc.RotX, npc.RotY, npc.RotZ, npc.RotW, npc.PosX, npc.PosY, npc.PosZ); + dNpc.Name = npc.NPCName; + + object_list.Add(new Tuple(zone, dNpc)); } - if (!allTheObjects.ContainsKey(dNpc.Header.ID)) - allTheObjects.Add(dNpc.Header.ID, dNpc); } } - return npcs.ToArray(); + // TODO: returning an IEnumerable looks more favorable than converting to an array + return (from o in object_list + where o.Item1 == zone + select o.Item2 as PSONPC).ToArray(); } internal PSOObject getObjectByID(string zone, uint ID) @@ -127,18 +125,37 @@ internal PSOObject getObjectByID(string zone, uint ID) //} //return zoneObjects[zone][ID]; - return getObjectByID(ID); - } - internal PSOObject getObjectByID(uint ID) - { - if (!allTheObjects.ContainsKey(ID)) + + // TODO: Per above old comments, do shared object errors still occur? Is an object 1 edge case still an issue? + PSOObject obj = null; + try { + if (string.IsNullOrEmpty(zone)) // Lookup by ID alone when no zone is specified + { + obj = object_list.SingleOrDefault(o => o.Item2.Header.ID == ID).Item2; + } + else + { + obj = object_list.SingleOrDefault(o => o.Item1 == zone && o.Item2.Header.ID == ID).Item2; + } + } + catch (InvalidOperationException) + { + Logger.WriteWarning("[OBJ] Multiple objects with ID {0} exist, unknown which is intended.", ID); + } + catch (NullReferenceException) + { + // SingleOrDefault returns null when no object is found, access .Item2 anyway and catch null to simplify things Logger.WriteWarning("[OBJ] Client requested object {0} which we don't know about. Investigate.", ID); - return new PSOObject() { Header = new ObjectHeader(ID, EntityType.Object), Name = "Unknown" }; } - return allTheObjects[ID]; + return obj != null ? obj : new PSOObject() { Header = new ObjectHeader(ID, EntityType.Object), Name = "Unknown" }; + } + + internal PSOObject getObjectByID(uint ID) + { + return getObjectByID(null, ID); } } } diff --git a/PolarisServer/Packets/PSOPackets/TeleportTransferPacket.cs b/PolarisServer/Packets/PSOPackets/TeleportTransferPacket.cs index 5cdcb21..952622e 100644 --- a/PolarisServer/Packets/PSOPackets/TeleportTransferPacket.cs +++ b/PolarisServer/Packets/PSOPackets/TeleportTransferPacket.cs @@ -19,7 +19,7 @@ public override byte[] Build() PacketWriter writer = new PacketWriter(); writer.Write(new byte[12]); writer.WriteStruct(src.Header); - writer.WritePosition(dst); + writer.Write(dst); writer.Write(new byte[2]); return writer.ToArray(); } diff --git a/PolarisServer/Packets/PacketWriter.cs b/PolarisServer/Packets/PacketWriter.cs index b460dc0..da34282 100644 --- a/PolarisServer/Packets/PacketWriter.cs +++ b/PolarisServer/Packets/PacketWriter.cs @@ -44,17 +44,6 @@ public void WriteAscii(string str, uint xor, uint sub) } } - internal void WritePosition(PSOLocation location) - { - Write(Helper.FloatToHalfPrecision(location.RotX)); - Write(Helper.FloatToHalfPrecision(location.RotY)); - Write(Helper.FloatToHalfPrecision(location.RotZ)); - Write(Helper.FloatToHalfPrecision(location.RotW)); - Write(Helper.FloatToHalfPrecision(location.PosX)); - Write(Helper.FloatToHalfPrecision(location.PosY)); - Write(Helper.FloatToHalfPrecision(location.PosZ)); - } - public void WriteUtf16(string str, uint xor, uint sub) { if (str.Length == 0) diff --git a/PolarisServer/Program.cs b/PolarisServer/Program.cs index d842fbf..e0e47c2 100644 --- a/PolarisServer/Program.cs +++ b/PolarisServer/Program.cs @@ -56,19 +56,20 @@ public static void Main(string[] args) case "-s": case "--size": var splitArgs = args[++i].Split(','); - var width = int.Parse(splitArgs[0]); - var height = int.Parse(splitArgs[1]); - if (width < ConsoleSystem.Width) + int width; + int height; + try { - Logger.WriteWarning("[ARG] Capping console width to {0} columns", ConsoleSystem.Width); - width = ConsoleSystem.Width; + width = int.Parse(splitArgs[0]); + height = int.Parse(splitArgs[1]); + Logger.WriteWarning("[ARG] Setting console width to {0} columns", width); + Logger.WriteWarning("[ARG] Setting console height to {0} rows", height); + ConsoleSystem.SetSize(width, height); } - if (height < ConsoleSystem.Height) + catch (Exception) { - Logger.WriteWarning("[ARG] Capping console height to {0} rows", ConsoleSystem.Height); - height = ConsoleSystem.Height; + Logger.WriteWarning("[WRN] Failed to set console size to ({0}).", args[i]); } - ConsoleSystem.SetSize(width, height); break; } }