public static LandblockInstance CreateLandblockInstance(WorldObject wo, bool isLinkChild = false) { var instance = new LandblockInstance(); instance.Guid = wo.Guid.Full; instance.Landblock = (int)wo.Location.Landblock; instance.WeenieClassId = wo.WeenieClassId; instance.ObjCellId = wo.Location.Cell; instance.OriginX = wo.Location.PositionX; instance.OriginY = wo.Location.PositionY; instance.OriginZ = wo.Location.PositionZ; instance.AnglesW = wo.Location.RotationW; instance.AnglesX = wo.Location.RotationX; instance.AnglesY = wo.Location.RotationY; instance.AnglesZ = wo.Location.RotationZ; instance.IsLinkChild = isLinkChild; instance.LastModified = DateTime.Now; return(instance); }
public HouseListResults(Weenie weenie, LandblockInstance landblockInstance) { Weenie = weenie; LandblockInstance = landblockInstance; HouseType = GetHouseType(Weenie.ClassName); }
/// <summary> /// Default is formed from: (input.ObjCellId >> 16).ToString("X4") /// </summary> public string GetDefaultFileName(LandblockInstance input) { string fileName = (input.ObjCellId >> 16).ToString("X4"); fileName = IllegalInFileName.Replace(fileName, "_"); fileName += ".sql"; return(fileName); }
/// <summary> /// Converts GDLE spawn map -> ACE landblock instances /// /// This will not alter the Guid. To sanitize the Guid for ACE usage, you should use GDLELoader.TryLoadWorldSpawnsConverted() instead. /// </summary> public static bool TryConvert(Models.Landblock input, out List <LandblockInstance> results, out List <LandblockInstanceLink> links) { try { results = new List <LandblockInstance>(); links = new List <LandblockInstanceLink>(); foreach (var value in input.value.weenies) { var result = new LandblockInstance(); result.Guid = value.id; // Collisions and other errors can be caused by invalid input. Data should be sanitized by the running ACE server. //result.Landblock = input.key; ACE uses a virtual column here of (result.ObjCellId >> 16) result.WeenieClassId = value.wcid; result.ObjCellId = value.pos.objcell_id; result.OriginX = value.pos.frame.origin.x; result.OriginY = value.pos.frame.origin.y; result.OriginZ = value.pos.frame.origin.z; result.AnglesW = value.pos.frame.angles.w; result.AnglesX = value.pos.frame.angles.x; result.AnglesY = value.pos.frame.angles.y; result.AnglesZ = value.pos.frame.angles.z; results.Add(result); } if (input.value.links != null) { foreach (var value in input.value.links) { var result = new LandblockInstanceLink(); result.ParentGuid = value.target; result.ChildGuid = value.source; links.Add(result); } } // reguid if needed var landblockId = (ushort)(input.key >> 16); ReGuidAndConvertLandblocks(results, links, landblockId); return(true); } catch { results = null; links = null; return(false); } }
/// <summary> /// This will not alter the Guid. To sanitize the Guid for ACE usage, you should use GDLELoader.TryLoadWorldSpawnsConverted() instead. /// </summary> public static bool TryConvert(Models.Landblock input, out List <Database.Models.World.LandblockInstance> results, out List <Database.Models.World.LandblockInstanceLink> links) { try { results = new List <LandblockInstance>(); links = new List <LandblockInstanceLink>(); foreach (var value in input.Value.Weenies) { var result = new LandblockInstance(); result.Guid = value.Id; // Collisions and other errors can be caused by invalid input. Data should be sanitized by the running ACE server. //result.Landblock = input.key; ACE uses a virtual column here of (result.ObjCellId >> 16) result.WeenieClassId = value.WCID; result.ObjCellId = value.Position.ObjCellId; result.OriginX = (float)value.Position.Frame.Origin.X; result.OriginY = (float)value.Position.Frame.Origin.Y; result.OriginZ = (float)value.Position.Frame.Origin.Z; result.AnglesW = (float)value.Position.Frame.Angles.W; result.AnglesX = (float)value.Position.Frame.Angles.X; result.AnglesY = (float)value.Position.Frame.Angles.Y; result.AnglesZ = (float)value.Position.Frame.Angles.Z; results.Add(result); } if (input.Value.Links != null) { foreach (var value in input.Value.Links) { var result = new LandblockInstanceLink(); result.ParentGuid = value.Target; result.ChildGuid = value.Source; links.Add(result); } } return(true); } catch { results = null; links = null; return(false); } }
private void AddRecord(List <string> fields) { if (CurrentTable == Table.LandblockInstance) { var record = new LandblockInstance(); PopulateFields(record, fields); LandblockInstances.Add(record); } else if (CurrentTable == Table.LandblockInstanceLink) { var record = new LandblockInstanceLink(); PopulateFields(record, fields); LandblockInstanceLinks.Add(record); } }
public static void HandleCreateInst(Session session, params string[] parameters) { var loc = new Position(session.Player.Location); var param = parameters[0]; Weenie weenie = null; uint?parentGuid = null; var landblock = session.Player.CurrentLandblock.Id.Landblock; var firstStaticGuid = 0x70000000 | (uint)landblock << 12; if (parameters.Length > 1) { var allParams = string.Join(" ", parameters); var match = Regex.Match(allParams, @"-p ([\S]+) -c ([\S]+)", RegexOptions.IgnoreCase); if (match.Success) { var parentGuidStr = match.Groups[1].Value; param = match.Groups[2].Value; if (parentGuidStr.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { parentGuidStr = parentGuidStr.Substring(2); } if (!uint.TryParse(parentGuidStr, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var _parentGuid)) { session.Network.EnqueueSend(new GameMessageSystemChat($"Couldn't parse parent guid {match.Groups[1].Value}", ChatMessageType.Broadcast)); return; } parentGuid = _parentGuid; if (parentGuid <= 0xFFF) { parentGuid = firstStaticGuid | parentGuid; } } else if (parameters[1].StartsWith("-c", StringComparison.OrdinalIgnoreCase)) { // get parent from last appraised object var parent = CommandHandlerHelper.GetLastAppraisedObject(session); if (parent == null) { session.Network.EnqueueSend(new GameMessageSystemChat($"Couldn't find parent object", ChatMessageType.Broadcast)); return; } parentGuid = parent.Guid.Full; } } if (uint.TryParse(param, out var wcid)) { weenie = DatabaseManager.World.GetCachedWeenie(wcid); // wcid } else { weenie = DatabaseManager.World.GetCachedWeenie(param); // classname } if (weenie == null) { session.Network.EnqueueSend(new GameMessageSystemChat($"Couldn't find weenie {param}", ChatMessageType.Broadcast)); return; } // clear any cached instances for this landblock DatabaseManager.World.ClearCachedInstancesByLandblock(landblock); var instances = DatabaseManager.World.GetCachedInstancesByLandblock(landblock); // for link mode, ensure parent guid instance exists WorldObject parentObj = null; LandblockInstance parentInstance = null; if (parentGuid != null) { parentInstance = instances.FirstOrDefault(i => i.Guid == parentGuid); if (parentInstance == null) { session.Network.EnqueueSend(new GameMessageSystemChat($"Couldn't find landblock instance for parent guid 0x{parentGuid:X8}", ChatMessageType.Broadcast)); return; } parentObj = session.Player.CurrentLandblock.GetObject(parentGuid.Value); if (parentObj == null) { session.Network.EnqueueSend(new GameMessageSystemChat($"Couldn't find parent object 0x{parentGuid:X8}", ChatMessageType.Broadcast)); return; } } var nextStaticGuid = GetNextStaticGuid(landblock, instances); var maxStaticGuid = firstStaticGuid | 0xFFF; // manually specify a start guid? if (parameters.Length == 2) { if (uint.TryParse(parameters[1].Replace("0x", ""), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var startGuid)) { if (startGuid <= 0xFFF) { startGuid = firstStaticGuid | startGuid; } if (startGuid < firstStaticGuid || startGuid > maxStaticGuid) { session.Network.EnqueueSend(new GameMessageSystemChat($"Landblock instance guid {startGuid:X8} must be between {firstStaticGuid:X8} and {maxStaticGuid:X8}", ChatMessageType.Broadcast)); return; } var existing = instances.FirstOrDefault(i => i.Guid == startGuid); if (existing != null) { session.Network.EnqueueSend(new GameMessageSystemChat($"Landblock instance guid {startGuid:X8} already exists", ChatMessageType.Broadcast)); return; } nextStaticGuid = startGuid; } } if (nextStaticGuid >= maxStaticGuid) { session.Network.EnqueueSend(new GameMessageSystemChat($"Landblock {landblock:X4} has reached the maximum # of static guids", ChatMessageType.Broadcast)); return; } // create and spawn object var wo = WorldObjectFactory.CreateWorldObject(weenie, new ObjectGuid(nextStaticGuid)); if (wo == null) { session.Network.EnqueueSend(new GameMessageSystemChat($"Failed to create new object for {weenie.ClassId} - {weenie.ClassName}", ChatMessageType.Broadcast)); return; } if (!wo.Stuck) { session.Network.EnqueueSend(new GameMessageSystemChat($"{weenie.ClassId} - {weenie.ClassName} is missing PropertyBool.Stuck, cannot spawn as landblock instance", ChatMessageType.Broadcast)); return; } // spawn as ethereal temporarily, to spawn directly on player position wo.Ethereal = true; wo.Location = new Position(loc); // even on flat ground, objects can sometimes fail to spawn at the player's current Z // Position.Z has some weird thresholds when moving around, but i guess the same logic doesn't apply when trying to spawn in... wo.Location.PositionZ += 0.05f; var isLinkChild = parentInstance != null; session.Network.EnqueueSend(new GameMessageSystemChat($"Creating new landblock instance {(isLinkChild ? "child object " : "")}@ {loc.ToLOCString()}\n{wo.WeenieClassId} - {wo.Name} ({nextStaticGuid:X8})", ChatMessageType.Broadcast)); if (!wo.EnterWorld()) { session.Network.EnqueueSend(new GameMessageSystemChat("Failed to spawn new object at this location", ChatMessageType.Broadcast)); return; } // create new landblock instance var instance = CreateLandblockInstance(wo, isLinkChild); instances.Add(instance); if (isLinkChild) { var link = new LandblockInstanceLink(); link.ParentGuid = parentGuid.Value; link.ChildGuid = wo.Guid.Full; link.LastModified = DateTime.Now; parentInstance.LandblockInstanceLink.Add(link); parentObj.LinkedInstances.Add(instance); // ActivateLinks? parentObj.SetLinkProperties(wo); parentObj.ChildLinks.Add(wo); wo.ParentLink = parentObj; } SyncInstances(session, landblock, instances); }
public static List <LandblockInstance> ConvertToACE(this List <Seg6_LandBlockExtendedData.Landblock> input) { var results = new List <LandblockInstance>(); foreach (var value in input) { if (value.Weenies != null) { foreach (var weenie in value.Weenies) { var result = new LandblockInstance { Guid = weenie.ID, WeenieClassId = weenie.WCID, ObjCellId = weenie.Position.ObjCellID, OriginX = weenie.Position.Origin.X, OriginY = weenie.Position.Origin.Y, OriginZ = weenie.Position.Origin.Z, AnglesW = weenie.Position.Angles.W, AnglesX = weenie.Position.Angles.X, AnglesY = weenie.Position.Angles.Y, AnglesZ = weenie.Position.Angles.Z, }; // Somebody goofed and a guid was used in two places... I'm not sure that it ultimately was a problem on retail worlds but this fixes it for ACE if (result.Guid == 1975799995) { if (result.WeenieClassId == 22775) { result.Guid = 1975799994; // Unused guid. } } if (value.Links != null) { foreach (var link in value.Links) { if (result.Guid == link.Source) { result.IsLinkChild = true; } if (result.Guid == link.Target) { // This code prevents duplicates. There are a few duplicate entries in the cache.bin bool found = false; foreach (var record in result.LandblockInstanceLink) { if (record.ChildGuid == link.Source) { found = true; break; } } if (!found) { result.LandblockInstanceLink.Add(new LandblockInstanceLink { ParentGuid = result.Guid, ChildGuid = link.Source }); } } } } results.Add(result); } } } return(results); }
public static WorldObject ProcessInstance(uint lbid, LandblockInstance instance, Dictionary <uint, LandblockInstance> lookupTable) { var wo = WorldObjectFactory.CreateNewWorldObject(instance.WeenieClassId); if (wo == null) { return(null); } wo.InitPhysicsObj(); var objCellId = instance.ObjCellId; if ((objCellId & 0xFFFF) == 0) { // get the outdoor landcell for this position var cellX = (uint)(instance.OriginX / 24); var cellY = (uint)(instance.OriginY / 24); var cellID = cellX * 8 + cellY + 1; objCellId |= cellID; } var location = new Position(); location.ObjCellID = objCellId; location.Frame.Origin = new Vector3(instance.OriginX, instance.OriginY, instance.OriginZ); location.Frame.Orientation = new Quaternion(instance.AnglesX, instance.AnglesY, instance.AnglesZ, instance.AnglesW); var success = wo.AddPhysicsObj(location); if (!success) { Console.WriteLine($"LoadInstances({lbid:X8}).AddPhysicsObj({wo.Name}, {location}) - failed to spawn"); return(null); } Console.WriteLine($"Spawned {instance.WeenieClassId} - {wo.Name} @ {location}"); AddInstance(wo); foreach (var link in instance.LandblockInstanceLink) { if (!lookupTable.TryGetValue(link.ChildGuid, out var childInstance)) { Console.WriteLine($"Server.ProcessInstance({lbid:X8}, {instance.Guid:X8}, {link.ChildGuid:X8}) - couldn't find child guid!"); continue; } var child = ProcessInstance(lbid, childInstance, lookupTable); if (child == null) { continue; } child.ParentLink = wo; wo.ChildLinks.Add(child); } return(wo); }