diff --git a/src/Prima.Core.Server/Collections/ValueLinkList.cs b/src/Prima.Core.Server/Collections/ValueLinkList.cs
new file mode 100644
index 0000000..8adcdc8
--- /dev/null
+++ b/src/Prima.Core.Server/Collections/ValueLinkList.cs
@@ -0,0 +1,499 @@
+/*************************************************************************
+ * ModernUO *
+ * Copyright 2019-2023 - ModernUO Development Team *
+ * Email: hi@modernuo.com *
+ * File: ValueLinkList.cs *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ *************************************************************************/
+
+using System.Runtime.CompilerServices;
+
+namespace Prima.Core.Server.Collections;
+
+public interface IValueLinkListNode where T : class
+{
+ public T Next { get; set; }
+ public T Previous { get; set; }
+ public bool OnLinkList { get; set; }
+}
+
+public struct ValueLinkList where T : class, IValueLinkListNode
+{
+ public int Count { get; internal set; }
+ internal T _first;
+ internal T _last;
+
+ public int Version { get; private set; }
+
+ public void Remove(T node)
+ {
+ if (node == null)
+ {
+ return;
+ }
+
+ if (!node.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to remove a node that is not on the list.");
+ }
+
+ if (node.Previous == null)
+ {
+ // If previous is null, then it is the first element.
+ if (_first != node)
+ {
+ throw new ArgumentException("Attempted to remove a node that is not on the list.");
+ }
+
+ if (_first == _last)
+ {
+ _last = null;
+ _first = null;
+ }
+ else
+ {
+ _first = node.Next;
+ }
+
+ if (node.Next != null)
+ {
+ node.Next.Previous = null;
+ }
+ }
+ else
+ {
+ node.Previous.Next = node.Next;
+
+ // If next is null, then it is the last element.
+ if (node.Next == null)
+ {
+ _last = node.Previous;
+ }
+ else
+ {
+ node.Next.Previous = node.Previous;
+ }
+ }
+
+ node.Next = null;
+ node.Previous = null;
+ node.OnLinkList = false;
+ Count--;
+ Version++;
+
+ if (Count < 0)
+ {
+ throw new Exception("Count is negative!");
+ }
+ }
+
+ // Remove all entries before this node, not including this node.
+ public void RemoveAllBefore(T e)
+ {
+ if (e == null)
+ {
+ return;
+ }
+
+ if (!e.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to remove nodes before a node that is not on the list.");
+ }
+
+ if (e.Previous == null)
+ {
+ return;
+ }
+
+ var current = e.Previous;
+ e.Previous = null;
+
+ while (current != null)
+ {
+ var previous = current.Previous;
+
+ current.OnLinkList = false;
+ current.Next = null;
+ current.Previous = null;
+ Count--;
+
+ if (Count < 0)
+ {
+ throw new Exception("Count is negative!");
+ }
+
+ current = previous;
+ }
+
+ _first = e;
+ Version++;
+ }
+
+ // Remove all entries after this node, not including this node.
+ public void RemoveAllAfter(T e)
+ {
+ if (e == null)
+ {
+ return;
+ }
+
+ if (!e.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to remove nodes after a node that is not on the list.");
+ }
+
+ if (e.Next == null)
+ {
+ return;
+ }
+
+ var current = e.Next;
+ e.Next = null;
+
+ while (current != null)
+ {
+ var next = current.Next;
+
+ current.OnLinkList = false;
+ current.Next = null;
+ current.Previous = null;
+ Count--;
+
+ if (Count < 0)
+ {
+ throw new Exception("Count is negative!");
+ }
+
+ current = next;
+ }
+
+ _last = e;
+ Version++;
+ }
+
+ public void AddLast(T e)
+ {
+ if (e == null)
+ {
+ return;
+ }
+
+ if (e.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to add a node that is already on a list.");
+ }
+
+ if (_last != null)
+ {
+ AddAfter(_last, e);
+ }
+ else
+ {
+ _first = e;
+ _last = e;
+ Count = 1;
+ Version++;
+ e.OnLinkList = true;
+ }
+ }
+
+ public void AddFirst(T e)
+ {
+ if (e == null)
+ {
+ return;
+ }
+
+ if (e.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to add a node that is already on a list.");
+ }
+
+ if (_first != null)
+ {
+ AddBefore(_first, e);
+ }
+ else
+ {
+ _first = e;
+ _last = e;
+ Count = 1;
+ Version++;
+ e.OnLinkList = true;
+ }
+ }
+
+ public void AddBefore(T existing, T node)
+ {
+ if (node == null)
+ {
+ return;
+ }
+
+ ArgumentNullException.ThrowIfNull(existing);
+
+ if (!existing.OnLinkList)
+ {
+ throw new ArgumentException($"Argument '{nameof(existing)}' must be a node on a list.");
+ }
+
+ if (node.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to add a node that is already on a list.");
+ }
+
+ node.Next = existing;
+ node.Previous = existing.Previous;
+
+ if (existing.Previous != null)
+ {
+ existing.Previous.Next = node;
+ }
+ else
+ {
+ _first = node;
+ }
+
+ existing.Previous = node;
+ node.OnLinkList = true;
+ Count++;
+ Version++;
+ }
+
+ public void AddAfter(T existing, T node)
+ {
+ if (node == null)
+ {
+ return;
+ }
+
+ ArgumentNullException.ThrowIfNull(existing);
+
+ if (!existing.OnLinkList)
+ {
+ throw new ArgumentException($"Argument '{nameof(existing)}' must be a node on a list.");
+ }
+
+ if (node.OnLinkList)
+ {
+ throw new ArgumentException("Attempted to add a node that is already on a list.");
+ }
+
+ node.Previous = existing;
+ node.Next = existing.Next;
+
+ if (existing.Next != null)
+ {
+ existing.Next.Previous = node;
+ }
+ else
+ {
+ _last = node;
+ }
+
+ existing.Next = node;
+ node.OnLinkList = true;
+ Count++;
+ Version++;
+ }
+
+ public void RemoveAll()
+ {
+ var current = _first;
+ while (current != null)
+ {
+ var next = current.Next;
+
+ current.OnLinkList = false;
+ current.Next = null;
+ current.Previous = null;
+ current = next;
+ }
+
+ _first = null;
+ _last = null;
+ Count = 0;
+ Version++;
+ }
+
+ public void AddLast(ref ValueLinkList otherList, T start, T end)
+ {
+ // Should we check if start and end actually exist on the other list?
+ if (otherList.Count == 0 || otherList.Count == 1 && (start != end || otherList._first != start))
+ {
+ throw new ArgumentException("Attempted to add nodes that are not on the specified linklist.");
+ }
+
+ if (start.Previous != null)
+ {
+ start.Previous.Next = end.Next;
+ }
+ else
+ {
+ // Start is first
+ otherList._first = end.Next;
+ }
+
+ if (end.Next != null)
+ {
+ end.Next.Previous = start.Previous;
+ }
+ else
+ {
+ otherList._last = start.Previous;
+ }
+
+ var count = 1;
+ var current = start;
+
+ // Assume start and end are in the right order, or bad things happen (crash).
+ while (current != end)
+ {
+ count++;
+ current = current.Next;
+ }
+
+ otherList.Count -= count;
+
+ if (otherList.Count < 0)
+ {
+ throw new Exception("Count is negative!");
+ }
+
+ if (_last != null)
+ {
+ _last.Next = start;
+ start.Previous = _last;
+ }
+ else
+ {
+ _first = start;
+ }
+
+ _last = end;
+ Count += count;
+ Version++;
+ }
+
+ public T[] ToArray()
+ {
+ var arr = new T[Count];
+
+ var index = 0;
+ foreach (var t in this)
+ {
+ arr[index++] = t;
+ }
+
+ return arr;
+ }
+
+ public ref struct ValueListEnumerator
+ {
+ private bool _started;
+ private T _current;
+ private ref readonly ValueLinkList _linkList;
+ private int _version;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ValueListEnumerator(in ValueLinkList linkList)
+ {
+ _linkList = ref linkList;
+ _started = false;
+ _current = null;
+ _version = 0;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool MoveNext()
+ {
+ if (!_started)
+ {
+ _current = _linkList._first;
+ _started = true;
+ _version = _linkList.Version;
+ }
+ else if (_linkList.Version != _version)
+ {
+ throw new InvalidOperationException("Collection was modified after the enumerator was instantiated.");
+ }
+ else
+ {
+ _current = _current.Next;
+ }
+
+ return _current != null;
+ }
+
+ public T Current
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _current;
+ }
+ }
+
+ public ref struct DescendingValueListEnumerator
+ {
+ private bool _started;
+ private T _current;
+ private ref readonly ValueLinkList _linkList;
+ private int _version;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public DescendingValueListEnumerator(in ValueLinkList linkList)
+ {
+ _linkList = ref linkList;
+ _started = false;
+ _current = null;
+ _version = 0;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool MoveNext()
+ {
+ if (!_started)
+ {
+ _current = _linkList._last;
+ _started = true;
+ _version = _linkList.Version;
+ }
+ else if (_linkList.Version != _version)
+ {
+ throw new InvalidOperationException("Collection was modified after the enumerator was instantiated.");
+ }
+ else
+ {
+ _current = _current.Previous;
+ }
+
+ return _current != null;
+ }
+
+ public T Current
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _current;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public DescendingValueListEnumerator GetEnumerator() => this;
+ }
+}
+
+public static class ValueLinkListExt
+{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ValueLinkList.ValueListEnumerator GetEnumerator(this in ValueLinkList linkList)
+ where T : class, IValueLinkListNode => new(in linkList);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ValueLinkList.DescendingValueListEnumerator ByDescending(this in ValueLinkList linkList)
+ where T : class, IValueLinkListNode => new(in linkList);
+}
diff --git a/src/Prima.Core.Server/Data/PrimaServerContext.cs b/src/Prima.Core.Server/Data/PrimaServerContext.cs
index 48e445d..d7afd00 100644
--- a/src/Prima.Core.Server/Data/PrimaServerContext.cs
+++ b/src/Prima.Core.Server/Data/PrimaServerContext.cs
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
+using Orion.Core.Server.Data.Directories;
using Orion.Core.Server.Interfaces.Services.System;
using Prima.Core.Server.Data.Session;
using Prima.Core.Server.Data.Uo;
@@ -10,6 +11,8 @@ public static class PrimaServerContext
{
public static IServiceProvider ServiceProvider { get; set; }
+ public static DirectoriesConfig DirectoriesConfig => ServiceProvider.GetRequiredService();
+
public static IEventLoopService EventLoopService => ServiceProvider.GetRequiredService();
public static INetworkSessionService NetworkSessionService => ServiceProvider.GetRequiredService>();
diff --git a/src/Prima.Core.Server/Data/Session/NetworkSession.cs b/src/Prima.Core.Server/Data/Session/NetworkSession.cs
index ea6a31f..aee15a1 100644
--- a/src/Prima.Core.Server/Data/Session/NetworkSession.cs
+++ b/src/Prima.Core.Server/Data/Session/NetworkSession.cs
@@ -1,7 +1,6 @@
using Orion.Core.Server.Interfaces.Sessions;
using Prima.Core.Server.Data.Uo;
using Prima.Network.Interfaces.Packets;
-using Prima.Network.Packets;
namespace Prima.Core.Server.Data.Session;
diff --git a/src/Prima.Core.Server/Handlers/Base/BasePacketListenerHandler.cs b/src/Prima.Core.Server/Handlers/Base/BasePacketListenerHandler.cs
index b6c43f7..3f26dd5 100644
--- a/src/Prima.Core.Server/Handlers/Base/BasePacketListenerHandler.cs
+++ b/src/Prima.Core.Server/Handlers/Base/BasePacketListenerHandler.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging;
using Orion.Core.Server.Interfaces.Services.Base;
using Orion.Core.Server.Interfaces.Services.System;
+using Orion.Core.Server.Listeners.EventBus;
using Prima.Core.Server.Data.Session;
using Prima.Core.Server.Interfaces.Listeners;
using Prima.Core.Server.Interfaces.Services;
@@ -79,4 +80,19 @@ public Task OnPacketReceived(string sessionId, IUoNetworkPacket packet)
{
return _serviceProvider.GetRequiredService>().GetSession(sessionId);
}
+
+ protected Task PublishEvent(TEvent eventArgs) where TEvent : class
+ {
+ return _serviceProvider.GetRequiredService().PublishAsync(eventArgs);
+ }
+
+ protected void SubscribeEvent(Func handler) where TEvent : class
+ {
+ _serviceProvider.GetRequiredService().Subscribe(handler);
+ }
+
+ protected void SubscribeEvent(IEventBusListener listener) where TEvent : class
+ {
+ _serviceProvider.GetRequiredService().Subscribe(listener);
+ }
}
diff --git a/src/Prima.JavaScript.Engine/Services/ScriptEngineService.cs b/src/Prima.JavaScript.Engine/Services/ScriptEngineService.cs
index eb4f681..f4e3471 100644
--- a/src/Prima.JavaScript.Engine/Services/ScriptEngineService.cs
+++ b/src/Prima.JavaScript.Engine/Services/ScriptEngineService.cs
@@ -142,6 +142,7 @@ public Task StartAsync(CancellationToken cancellationToken = default)
File.WriteAllText(Path.Combine(_directoriesConfig["Scripts"], "index.d.ts"), documentation);
+ GenerateEnumDefinitions(TypeScriptDocumentationGenerator.FoundEnums);
ExecuteBootstrap();
@@ -149,6 +150,33 @@ public Task StartAsync(CancellationToken cancellationToken = default)
return Task.CompletedTask;
}
+ private void GenerateEnumDefinitions(List enumTypes)
+ {
+ foreach (var enumType in enumTypes)
+ {
+ var enumName = enumType.Name;
+ var enumDictionary = ConvertEnumToDictionary(enumType);
+
+ _jsEngine.SetValue(enumName, enumDictionary);
+ }
+ }
+
+
+ public static Dictionary ConvertEnumToDictionary(Type enumType)
+ {
+ if (!enumType.IsEnum)
+ {
+ throw new ArgumentException($"Type {enumType.Name} is not an enum", nameof(enumType));
+ }
+
+
+ return Enum.GetNames(enumType)
+ .ToDictionary(
+ name => name.ToSnakeCaseUpper(),
+ name => (object)Enum.Parse(enumType, name)
+ );
+ }
+
public Task StopAsync(CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
diff --git a/src/Prima.JavaScript.Engine/Utils/Scripts/TypeScriptDocumentationGenerator.cs b/src/Prima.JavaScript.Engine/Utils/Scripts/TypeScriptDocumentationGenerator.cs
index a6ad207..a7da7f5 100644
--- a/src/Prima.JavaScript.Engine/Utils/Scripts/TypeScriptDocumentationGenerator.cs
+++ b/src/Prima.JavaScript.Engine/Utils/Scripts/TypeScriptDocumentationGenerator.cs
@@ -18,6 +18,8 @@ public static class TypeScriptDocumentationGenerator
private static readonly StringBuilder _enumsBuilder = new();
private static readonly List _interfaceTypesToGenerate = [];
+ public static List FoundEnums { get; } = [];
+
private static Func _nameResolver = name => name.ToSnakeCase();
public static string GenerateDocumentation(
@@ -499,6 +501,8 @@ private static void GenerateEnumInterface(Type enumType)
return;
}
+ FoundEnums.Add(enumType);
+
_enumsBuilder.AppendLine();
_enumsBuilder.AppendLine($"/**");
_enumsBuilder.AppendLine($" * Generated enum for {enumType.FullName}");
@@ -509,8 +513,20 @@ private static void GenerateEnumInterface(Type enumType)
foreach (var value in enumValues)
{
- var numericValue = (int)Enum.Parse(enumType, value);
- _enumsBuilder.AppendLine($" {value} = {numericValue},");
+ var numericValue = -1;
+ try
+ {
+ numericValue = Convert.ToInt32(Enum.Parse(enumType, value));
+ }
+ catch (InvalidCastException)
+ {
+ // Handle the case where the enum value is not an integer
+ // This can happen if the enum is defined with a different underlying type
+ numericValue = (int)Enum.Parse(enumType, value);
+ }
+
+
+ _enumsBuilder.AppendLine($" {value.ToSnakeCaseUpper()} = {numericValue},");
}
_enumsBuilder.AppendLine("}");
diff --git a/src/Prima.Network/Packets/Base/BaseUoNetworkPacket.cs b/src/Prima.Network/Packets/Base/BaseUoNetworkPacket.cs
index c58f745..7e9de67 100644
--- a/src/Prima.Network/Packets/Base/BaseUoNetworkPacket.cs
+++ b/src/Prima.Network/Packets/Base/BaseUoNetworkPacket.cs
@@ -18,7 +18,7 @@ public abstract class BaseUoNetworkPacket : IUoNetworkPacket
///
/// Gets the length of the packet data.
///
- public int Length { get; }
+ public int Length { get; set; }
///
/// Initializes a new instance of the BaseUoNetworkPacket class with the specified operation code.
diff --git a/src/Prima.Server/Assets/Data/regions.json b/src/Prima.Server/Assets/Data/regions.json
new file mode 100644
index 0000000..005253c
--- /dev/null
+++ b/src/Prima.Server/Assets/Data/regions.json
@@ -0,0 +1,4202 @@
+[
+ {
+ "$type": "GuardedRegion",
+ "Map": "Felucca",
+ "Name": "Moongates",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1330, "y1": 1991, "x2": 1343, "y2": 2004},
+ {"x1": 1494, "y1": 3767, "x2": 1506, "y2": 3778},
+ {"x1": 2694, "y1": 685, "x2": 2709, "y2": 701},
+ {"x1": 1823, "y1": 2943, "x2": 1834, "y2": 2954},
+ {"x1": 761, "y1": 741, "x2": 780, "y2": 762},
+ {"x1": 638, "y1": 2062, "x2": 650, "y2": 2073},
+ {"x1": 4459, "y1": 1276, "x2": 4475, "y2": 1292},
+ {"x1": 3554, "y1": 2132, "x2": 3572, "y2": 2150}
+ ]
+ },
+ {
+ "$type": "GuardedRegion",
+ "Map": "Felucca",
+ "Name": "T2A Arena",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2396, "y1": 197, "x2": 2407, "y2": 220},
+ {"x1": 5717, "y1": 428, "x2": 5755, "y2": 456},
+ {"x1": 6085, "y1": 3674, "x2": 6108, "y2": 3698},
+ {"x1": 6063, "y1": 3698, "x2": 6111, "y2": 3750}
+ ],
+ "GoLocation": {"x": 6103, "y": 3724, "z": 25}
+ },
+ {
+ "$type": "TownRegion",
+ "Entrance": {"x": 535, "y": 995, "z": 0},
+ "Map": "Felucca",
+ "Name": "The Heartwood",
+ "Priority": 50,
+ "Area": [{"x1": 6911, "y1": 255, "x2": 7168, "y2": 512}],
+ "GoLocation": {"x": 6984, "y": 337, "z": 0},
+ "Music": "ElfCity"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 762, "y": 1645, "z": 0},
+ "Map": "Felucca",
+ "Name": "Sanctuary",
+ "Priority": 50,
+ "Area": [{"x1": 6144, "y1": 0, "x2": 6399, "y2": 255}],
+ "GoLocation": {"x": 6174, "y": 23, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1716, "y": 892, "z": 0},
+ "Map": "Felucca",
+ "Name": "The Painted Caves",
+ "Priority": 50,
+ "Area": [{"x1": 6240, "y1": 850, "x2": 6315, "y2": 920}],
+ "GoLocation": {"x": 6308, "y": 892, "z": -1},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 3784, "y": 1097, "z": 14},
+ "Map": "Felucca",
+ "Name": "The Prism of Light",
+ "Priority": 50,
+ "Area": [{"x1": 6400, "y1": 0, "x2": 6621, "y2": 255}],
+ "GoLocation": {"x": 6474, "y": 188, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 587, "y": 1641, "z": -1},
+ "Map": "Felucca",
+ "Name": "Blighted Grove",
+ "Priority": 50,
+ "Area": [{"x1": 6440, "y1": 820, "x2": 6600, "y2": 970}],
+ "GoLocation": {"x": 6478, "y": 863, "z": 11},
+ "Music": "MelisandesLair"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 5574, "y": 3024, "z": 31},
+ "Map": "Felucca",
+ "Name": "The Palace of Paroxysmus",
+ "Priority": 50,
+ "Area": [{"x1": 6191, "y1": 311, "x2": 6561, "y2": 671}],
+ "GoLocation": {"x": 6222, "y": 335, "z": 60},
+ "Music": "ParoxysmusLair"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Bravehorn's drinking pool",
+ "Priority": 50,
+ "Area": [{"x1": 1302, "y1": 2331, "x2": 1340, "y2": 2353}]
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Huntsman's Forest",
+ "Priority": 50,
+ "Area": [{"x1": 1595, "y1": 550, "x2": 1715, "y2": 670}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Cove",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2200, "y1": 1110, "x2": 2250, "y2": 1160},
+ {"x1": 2200, "y1": 1160, "x2": 2286, "y2": 1246}
+ ],
+ "GoLocation": {"x": 2275, "y": 1210, "z": 0},
+ "Music": "Cove"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Britain",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1416, "y1": 1498, "z1": -10, "x2": 1740, "y2": 1777, "z2": 128},
+ {"x1": 1500, "y1": 1408, "z1": 0, "x2": 1546, "y2": 1498, "z2": 128},
+ {"x1": 1385, "y1": 1538, "z1": -10, "x2": 1416, "y2": 1777, "z2": 128},
+ {"x1": 1416, "y1": 1777, "z1": 0, "x2": 1740, "y2": 1837, "z2": 128},
+ {"x1": 1385, "y1": 1777, "z1": 0, "x2": 1416, "y2": 1907, "z2": 128},
+ {"x1": 1093, "y1": 1538, "z1": 0, "x2": 1385, "y2": 1907, "z2": 128}
+ ],
+ "GoLocation": {"x": 1495, "y": 1629, "z": 10},
+ "Music": "Britain1"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 1492, "y1": 1602, "z1": 0, "x2": 1500, "y2": 1621, "z2": 128},
+ {"x1": 1500, "y1": 1610, "z1": 0, "x2": 1508, "y2": 1626, "z2": 128},
+ {"x1": 1576, "y1": 1584, "z1": 0, "x2": 1600, "y2": 1600, "z2": 128},
+ {"x1": 1456, "y1": 1512, "z1": 0, "x2": 1472, "y2": 1528, "z2": 128},
+ {"x1": 1472, "y1": 1512, "z1": 0, "x2": 1480, "y2": 1520, "z2": 128},
+ {"x1": 1486, "y1": 1684, "z1": 0, "x2": 1494, "y2": 1692, "z2": 128},
+ {"x1": 1494, "y1": 1676, "z1": 0, "x2": 1502, "y2": 1700, "z2": 128},
+ {"x1": 1424, "y1": 1712, "z1": 0, "x2": 1432, "y2": 1736, "z2": 128},
+ {"x1": 1432, "y1": 1712, "z1": 0, "x2": 1440, "y2": 1724, "z2": 128},
+ {"x1": 1608, "y1": 1584, "z1": 0, "x2": 1632, "y2": 1592, "z2": 128},
+ {"x1": 1616, "y1": 1576, "z1": 0, "x2": 1624, "y2": 1584, "z2": 128},
+ {"x1": 1544, "y1": 1760, "z1": 0, "x2": 1560, "y2": 1776, "z2": 128},
+ {"x1": 1560, "y1": 1760, "z1": 0, "x2": 1568, "y2": 1768, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Wheatfield in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1120, "y1": 1776, "x2": 1152, "y2": 1808}],
+ "GoLocation": {"x": 1135, "y": 1791, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Wheatfield in Britain 2",
+ "Priority": 50,
+ "Area": [{"x1": 1184, "y1": 1808, "x2": 1216, "y2": 1840}],
+ "GoLocation": {"x": 1199, "y": 1823, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Wheatfield in Britain 3",
+ "Priority": 50,
+ "Area": [{"x1": 1216, "y1": 1872, "x2": 1248, "y2": 1904}],
+ "GoLocation": {"x": 1231, "y": 1887, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Carrot Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1208, "y1": 1712, "x2": 1224, "y2": 1736}],
+ "GoLocation": {"x": 1215, "y": 1723, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "An Onion Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1224, "y1": 1712, "x2": 1240, "y2": 1736}],
+ "GoLocation": {"x": 1231, "y": 1723, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Cabbage Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1176, "y1": 1672, "x2": 1192, "y2": 1695}],
+ "GoLocation": {"x": 1183, "y": 1683, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Turnip Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1192, "y1": 1672, "x2": 1208, "y2": 1696}],
+ "GoLocation": {"x": 1199, "y": 1683, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Wheatfield in Britain 4",
+ "Priority": 50,
+ "Area": [{"x1": 1104, "y1": 1608, "x2": 1136, "y2": 1640}],
+ "GoLocation": {"x": 1120, "y": 1624, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Wheatfield in Britain 5",
+ "Priority": 50,
+ "Area": [{"x1": 1136, "y1": 1560, "x2": 1168, "y2": 1592}],
+ "GoLocation": {"x": 1152, "y": 1576, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Turnip Field in Britain 2",
+ "Priority": 50,
+ "Area": [{"x1": 1208, "y1": 1592, "x2": 1224, "y2": 1616}],
+ "GoLocation": {"x": 1216, "y": 1604, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Britain", "Map": "Felucca" },
+ "Name": "A Carrot Field in Britain 2",
+ "Priority": 50,
+ "Area": [{"x1": 1224, "y1": 1592, "x2": 1240, "y2": 1616}],
+ "GoLocation": {"x": 1232, "y": 1604, "z": 0}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Felucca",
+ "Name": "Britain Graveyard",
+ "Priority": 50,
+ "Area": [{"x1": 1333, "y1": 1441, "x2": 1417, "y2": 1523}],
+ "GoLocation": {"x": 1384, "y": 1492, "z": 10}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Felucca",
+ "Name": "Jhelom Islands",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1111, "y1": 3567, "x2": 1144, "y2": 3588},
+ {"x1": 1078, "y1": 3588, "x2": 1202, "y2": 3709},
+ {"x1": 1224, "y1": 3592, "x2": 1533, "y2": 4065}
+ ],
+ "GoLocation": {"x": 1383, "y": 3815, "z": 0},
+ "Music": "Jhelom"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Parent": { "Name": "Jhelom Islands", "Map": "Felucca" },
+ "Name": "Jhelom",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1303, "y1": 3670, "z1": -20, "x2": 1492, "y2": 3895, "z2": 128},
+ {"x1": 1338, "y1": 3895, "z1": -20, "x2": 1412, "y2": 3923, "z2": 128},
+ {"x1": 1383, "y1": 3951, "z1": -20, "x2": 1492, "y2": 4045, "z2": 128}
+ ],
+ "GoLocation": {"x": 1383, "y": 3815, "z": 0}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Jhelom", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 1352, "y1": 3800, "z1": -20, "x2": 1368, "y2": 3832, "z2": 128},
+ {"x1": 1368, "y1": 3808, "z1": -20, "x2": 1376, "y2": 3824, "z2": 128},
+ {"x1": 1432, "y1": 3768, "z1": -20, "x2": 1464, "y2": 3776, "z2": 128},
+ {"x1": 1440, "y1": 3776, "z1": -20, "x2": 1464, "y2": 3784, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Minoc",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2411, "y1": 366, "x2": 2546, "y2": 607},
+ {"x1": 2548, "y1": 495, "x2": 2620, "y2": 550},
+ {"x1": 2564, "y1": 585, "x2": 2567, "y2": 627},
+ {"x1": 2567, "y1": 585, "x2": 2628, "y2": 646},
+ {"x1": 2499, "y1": 627, "x2": 2567, "y2": 690}
+ ],
+ "GoLocation": {"x": 2466, "y": 544, "z": 0},
+ "Music": "Minoc"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Minoc", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2457, "y1": 397, "x2": 2497, "y2": 405},
+ {"x1": 2465, "y1": 405, "x2": 2473, "y2": 413},
+ {"x1": 2481, "y1": 405, "x2": 2489, "y2": 413}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Ocllo",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3587, "y1": 2456, "x2": 3706, "y2": 2555},
+ {"x1": 3706, "y1": 2460, "x2": 3708, "y2": 2555},
+ {"x1": 3587, "y1": 2555, "x2": 3693, "y2": 2628},
+ {"x1": 3590, "y1": 2628, "x2": 3693, "y2": 2686},
+ {"x1": 3693, "y1": 2555, "x2": 3754, "y2": 2699},
+ {"x1": 3754, "y1": 2558, "x2": 3761, "y2": 2699},
+ {"x1": 3761, "y1": 2555, "z1": -128, "x2": 3768, "y2": 2699, "z2": 50},
+ {"x1": 3695, "y1": 2699, "x2": 3761, "y2": 2712}
+ ],
+ "GoLocation": {"x": 3650, "y": 2519, "z": 0},
+ "Music": "Ocllo"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Ocllo", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 3664, "y1": 2608, "x2": 3680, "y2": 2624},
+ {"x1": 3664, "y1": 2640, "x2": 3672, "y2": 2656},
+ {"x1": 3672, "y1": 2648, "x2": 3680, "y2": 2656}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Trinsic",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1856, "y1": 2636, "x2": 1931, "y2": 2664},
+ {"x1": 1816, "y1": 2664, "x2": 2099, "y2": 2895},
+ {"x1": 2099, "y1": 2782, "x2": 2117, "y2": 2807},
+ {"x1": 1970, "y1": 2895, "x2": 2017, "y2": 2927},
+ {"x1": 1796, "y1": 2696, "z1": 0, "x2": 1816, "y2": 2763, "z2": 128},
+ {"x1": 1800, "y1": 2796, "z1": 0, "x2": 1816, "y2": 2848, "z2": 128}
+ ],
+ "GoLocation": {"x": 1867, "y": 2780, "z": 0},
+ "Music": "Trinsic"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Trinsic", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 1834, "y1": 2728, "x2": 1856, "y2": 2744},
+ {"x1": 2024, "y1": 2784, "x2": 2040, "y2": 2804},
+ {"x1": 2026, "y1": 2804, "x2": 2040, "y2": 2806},
+ {"x1": 2024, "y1": 2806, "x2": 2040, "y2": 2813},
+ {"x1": 1923, "y1": 2786, "x2": 1935, "y2": 2808},
+ {"x1": 1935, "y1": 2786, "x2": 1942, "y2": 2800}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Vesper",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2893, "y1": 598, "x2": 3014, "y2": 648},
+ {"x1": 2816, "y1": 648, "x2": 3065, "y2": 1013},
+ {"x1": 2734, "y1": 944, "x2": 2816, "y2": 948},
+ {"x1": 2728, "y1": 948, "x2": 2816, "y2": 1001}
+ ],
+ "GoLocation": {"x": 2899, "y": 676, "z": 0},
+ "Music": "Vesper"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Vesper", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2952, "y1": 864, "x2": 2968, "y2": 896},
+ {"x1": 2968, "y1": 872, "x2": 2976, "y2": 888},
+ {"x1": 2776, "y1": 952, "x2": 2792, "y2": 984},
+ {"x1": 2768, "y1": 960, "x2": 2776, "y2": 976},
+ {"x1": 2892, "y1": 901, "x2": 2908, "y2": 920},
+ {"x1": 2908, "y1": 904, "x2": 2916, "y2": 912}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Yew",
+ "Priority": 50,
+ "Area": [
+ {"x1": 92, "y1": 656, "z1": 0, "x2": 441, "y2": 881, "z2": 39},
+ {"x1": 441, "y1": 746, "z1": 0, "x2": 657, "y2": 881, "z2": 39},
+ {"x1": 258, "y1": 881, "z1": 0, "x2": 657, "y2": 1261, "z2": 39},
+ {"x1": 657, "y1": 922, "z1": 0, "x2": 699, "y2": 1229, "z2": 39},
+ {"x1": 657, "y1": 806, "z1": 0, "x2": 674, "y2": 834, "z2": 39},
+ {"x1": 718, "y1": 874, "z1": 0, "x2": 756, "y2": 896, "z2": 39}
+ ],
+ "GoLocation": {"x": 546, "y": 992, "z": 0},
+ "Music": "Yew"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Yew", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [{"x1": 600, "y1": 808, "z1": 0, "x2": 624, "y2": 832, "z2": 39}]
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Field of Sheep in Yew",
+ "Map": "Felucca",
+ "Parent": { "Name": "Yew", "Map": "Felucca" },
+ "Name": "A Field of Sheep in Yew 1",
+ "Priority": 50,
+ "Area": [{"x1": 664, "y1": 928, "x2": 686, "y2": 950}],
+ "GoLocation": {"x": 675, "y": 939, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Field of Sheep in Yew",
+ "Map": "Felucca",
+ "Parent": { "Name": "Yew", "Map": "Felucca" },
+ "Name": "A Field of Sheep in Yew 2",
+ "Priority": 50,
+ "Area": [{"x1": 664, "y1": 1168, "x2": 686, "y2": 1190}],
+ "GoLocation": {"x": 675, "y": 1179, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Farm in Yew",
+ "Map": "Felucca",
+ "Parent": { "Name": "Yew", "Map": "Felucca" },
+ "Name": "A Farm in Yew",
+ "Priority": 50,
+ "Area": [{"x1": 560, "y1": 1088, "x2": 582, "y2": 1110}],
+ "GoLocation": {"x": 571, "y": 1099, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Wheatfield in Yew",
+ "Map": "Felucca",
+ "Parent": { "Name": "Yew", "Map": "Felucca" },
+ "Name": "A Wheatfield in Yew 1",
+ "Priority": 50,
+ "Area": [{"x1": 560, "y1": 1232, "x2": 576, "y2": 1248}],
+ "GoLocation": {"x": 567, "y": 1239, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Wheatfield in Yew",
+ "Map": "Felucca",
+ "Parent": { "Name": "Yew", "Map": "Felucca" },
+ "Name": "A Wheatfield in Yew 2",
+ "Priority": 50,
+ "Area": [{"x1": 368, "y1": 1176, "x2": 382, "y2": 1208}],
+ "GoLocation": {"x": 375, "y": 1191, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Wind",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5294, "y1": 19, "x2": 5366, "y2": 139},
+ {"x1": 5132, "y1": 58, "x2": 5213, "y2": 126},
+ {"x1": 5197, "y1": 126, "x2": 5252, "y2": 204},
+ {"x1": 5132, "y1": 3, "x2": 5202, "y2": 58},
+ {"x1": 5252, "y1": 112, "x2": 5294, "y2": 170},
+ {"x1": 5213, "y1": 98, "x2": 5252, "y2": 126},
+ {"x1": 5279, "y1": 57, "x2": 5294, "y2": 112},
+ {"x1": 5252, "y1": 170, "x2": 5284, "y2": 178},
+ {"x1": 5286, "y1": 25, "x2": 5294, "y2": 57},
+ {"x1": 5252, "y1": 178, "x2": 5272, "y2": 183},
+ {"x1": 5252, "y1": 183, "x2": 5262, "y2": 193}
+ ],
+ "GoLocation": {"x": 5223, "y": 190, "z": 5},
+ "Music": "Wind"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Wind", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 5159, "y1": 15, "x2": 5184, "y2": 24},
+ {"x1": 5159, "y1": 24, "x2": 5168, "y2": 40},
+ {"x1": 5175, "y1": 24, "x2": 5184, "y2": 32},
+ {"x1": 5212, "y1": 159, "x2": 5221, "y2": 183},
+ {"x1": 5221, "y1": 171, "x2": 5228, "y2": 183},
+ {"x1": 5206, "y1": 164, "x2": 5212, "y2": 179},
+ {"x1": 5303, "y1": 28, "x2": 5319, "y2": 42}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Serpent's Hold",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2868, "y1": 3324, "z1": 0, "x2": 3073, "y2": 3519, "z2": 128}
+ ],
+ "GoLocation": {"x": 3010, "y": 3371, "z": 15},
+ "Music": "Serpents"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Serpent's Hold", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2960, "y1": 3400, "z1": 0, "x2": 2976, "y2": 3416, "z2": 128},
+ {"x1": 2968, "y1": 3416, "z1": 0, "x2": 2976, "y2": 3432, "z2": 128},
+ {"x1": 3008, "y1": 3450, "z1": 0, "x2": 3022, "y2": 3464, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 538, "y1": 2107, "x2": 688, "y2": 2297}],
+ "GoLocation": {"x": 632, "y": 2233, "z": 0},
+ "Music": "Skarabra"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Skara Brae", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 600, "y1": 2232, "x2": 616, "y2": 2256},
+ {"x1": 592, "y1": 2240, "x2": 600, "y2": 2256},
+ {"x1": 616, "y1": 2240, "x2": 624, "y2": 2256},
+ {"x1": 552, "y1": 2168, "x2": 568, "y2": 2192},
+ {"x1": 568, "y1": 2168, "x2": 576, "y2": 2176}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Nujel'm",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3475, "y1": 1000, "z1": 0, "x2": 3835, "y2": 1435, "z2": 128}
+ ],
+ "GoLocation": {"x": 3732, "y": 1279, "z": 0},
+ "Music": "Nujelm"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Nujel'm", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 3736, "y1": 1184, "z1": 0, "x2": 3752, "y2": 1207, "z2": 128},
+ {"x1": 3728, "y1": 1192, "z1": 0, "x2": 3736, "y2": 1207, "z2": 128},
+ {"x1": 3728, "y1": 1288, "z1": 0, "x2": 3751, "y2": 1303, "z2": 128},
+ {"x1": 3728, "y1": 1303, "z1": 0, "x2": 3744, "y2": 1312, "z2": 128},
+ {"x1": 3728, "y1": 1312, "z1": 0, "x2": 3740, "y2": 1320, "z2": 128},
+ {"x1": 3728, "y1": 1320, "z1": 0, "x2": 3744, "y2": 1343, "z2": 128},
+ {"x1": 3744, "y1": 1328, "z1": 0, "x2": 3751, "y2": 1343, "z2": 128},
+ {"x1": 3760, "y1": 1216, "z1": 0, "x2": 3772, "y2": 1240, "z2": 128},
+ {"x1": 3772, "y1": 1220, "z1": 0, "x2": 3776, "y2": 1236, "z2": 128},
+ {"x1": 3776, "y1": 1224, "z1": 0, "x2": 3784, "y2": 1232, "z2": 128},
+ {"x1": 3728, "y1": 1248, "z1": 0, "x2": 3744, "y2": 1272, "z2": 128},
+ {"x1": 3744, "y1": 1264, "z1": 0, "x2": 3752, "y2": 1272, "z2": 128},
+ {"x1": 3744, "y1": 1248, "z1": 0, "x2": 3752, "y2": 1256, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Moonglow",
+ "Priority": 50,
+ "Area": [
+ {"x1": 4535, "y1": 844, "z1": 0, "x2": 4555, "y2": 847, "z2": 128},
+ {"x1": 4530, "y1": 847, "z1": 0, "x2": 4561, "y2": 908, "z2": 128},
+ {"x1": 4521, "y1": 914, "z1": 0, "x2": 4577, "y2": 963, "z2": 128},
+ {"x1": 4278, "y1": 915, "z1": 0, "x2": 4332, "y2": 934, "z2": 128},
+ {"x1": 4283, "y1": 944, "z1": 0, "x2": 4336, "y2": 1017, "z2": 128},
+ {"x1": 4377, "y1": 1015, "z1": -10, "x2": 4436, "y2": 1052, "z2": 128},
+ {"x1": 4367, "y1": 1050, "z1": 0, "x2": 4509, "y2": 1195, "z2": 128},
+ {"x1": 4539, "y1": 1036, "z1": 0, "x2": 4566, "y2": 1054, "z2": 128},
+ {"x1": 4517, "y1": 1053, "z1": 0, "x2": 4540, "y2": 1075, "z2": 128},
+ {"x1": 4389, "y1": 1198, "z1": 0, "x2": 4436, "y2": 1237, "z2": 128},
+ {"x1": 4466, "y1": 1211, "z1": 0, "x2": 4498, "y2": 1236, "z2": 128},
+ {"x1": 4700, "y1": 1108, "z1": 0, "x2": 4717, "y2": 1126, "z2": 128},
+ {"x1": 4656, "y1": 1127, "z1": 0, "x2": 4682, "y2": 1140, "z2": 128},
+ {"x1": 4678, "y1": 1162, "z1": 0, "x2": 4703, "y2": 1187, "z2": 128},
+ {"x1": 4613, "y1": 1196, "z1": 0, "x2": 4636, "y2": 1218, "z2": 128},
+ {"x1": 4646, "y1": 1212, "z1": 0, "x2": 4660, "y2": 1229, "z2": 128},
+ {"x1": 4677, "y1": 1214, "z1": 0, "x2": 4703, "y2": 1236, "z2": 128},
+ {"x1": 4622, "y1": 1316, "z1": 0, "x2": 4644, "y2": 1340, "z2": 128},
+ {"x1": 4487, "y1": 1353, "z1": 0, "x2": 4546, "y2": 1374, "z2": 128},
+ {"x1": 4477, "y1": 1374, "z1": 0, "x2": 4546, "y2": 1409, "z2": 128},
+ {"x1": 4659, "y1": 1387, "z1": 0, "x2": 4699, "y2": 1427, "z2": 128},
+ {"x1": 4549, "y1": 1482, "z1": 0, "x2": 4578, "y2": 1509, "z2": 128},
+ {"x1": 4405, "y1": 1451, "z1": 0, "x2": 4428, "y2": 1474, "z2": 128},
+ {"x1": 4483, "y1": 1468, "z1": 0, "x2": 4504, "y2": 1481, "z2": 128}
+ ],
+ "GoLocation": {"x": 4442, "y": 1172, "z": 0},
+ "Music": "Moonglow"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Moonglow", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 4384, "y1": 1152, "z1": 0, "x2": 4392, "y2": 1176, "z2": 128},
+ {"x1": 4392, "y1": 1160, "z1": 0, "x2": 4408, "y2": 1168, "z2": 128},
+ {"x1": 4400, "y1": 1152, "z1": 0, "x2": 4408, "y2": 1160, "z2": 128},
+ {"x1": 4480, "y1": 1056, "z1": 0, "x2": 4488, "y2": 1072, "z2": 128},
+ {"x1": 4488, "y1": 1060, "z1": 0, "x2": 4492, "y2": 1068, "z2": 128},
+ {"x1": 4476, "y1": 1060, "z1": 0, "x2": 4480, "y2": 1068, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Magincia",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3653, "y1": 2046, "x2": 3680, "y2": 2094},
+ {"x1": 3752, "y1": 2046, "x2": 3804, "y2": 2094},
+ {"x1": 3680, "y1": 2045, "x2": 3752, "y2": 2094},
+ {"x1": 3652, "y1": 2094, "x2": 3812, "y2": 2274},
+ {"x1": 3649, "y1": 2256, "x2": 3703, "y2": 2303}
+ ],
+ "GoLocation": {"x": 3714, "y": 2220, "z": 20},
+ "Music": "Magincia"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Magincia", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 3680, "y1": 2152, "x2": 3704, "y2": 2160},
+ {"x1": 3720, "y1": 2216, "x2": 3736, "y2": 2232}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Buccaneer's Den",
+ "Priority": 50,
+ "GuardsDisabled": true,
+ "Area": [
+ {"x1": 2612, "y1": 2057, "x2": 2776, "y2": 2267},
+ {"x1": 2604, "y1": 2065, "z1": 0, "x2": 2612, "y2": 2254, "z2": 128}
+ ],
+ "GoLocation": {"x": 2706, "y": 2163, "z": 0},
+ "Music": "Bucsden"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Buccaneer's Den", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2712, "y1": 2080, "x2": 2728, "y2": 2096},
+ {"x1": 2712, "y1": 2096, "x2": 2720, "y2": 2104},
+ {"x1": 2664, "y1": 2232, "x2": 2688, "y2": 2240},
+ {"x1": 2672, "y1": 2240, "x2": 2688, "y2": 2248}
+ ]
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2499, "y": 916, "z": 0},
+ "Map": "Felucca",
+ "Name": "Covetous",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5376, "y1": 1793, "x2": 5577, "y2": 2048},
+ {"x1": 5576, "y1": 1791, "x2": 5633, "y2": 2048}
+ ],
+ "GoLocation": {"x": 5456, "y": 1862, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 4111, "y": 429, "z": 0},
+ "Map": "Felucca",
+ "Name": "Deceit",
+ "Priority": 50,
+ "Area": [{"x1": 5122, "y1": 518, "x2": 5370, "y2": 770}],
+ "GoLocation": {"x": 5187, "y": 635, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1296, "y": 1082, "z": 0},
+ "Map": "Felucca",
+ "Name": "Despise",
+ "Priority": 50,
+ "Area": [{"x1": 5377, "y1": 516, "x2": 5631, "y2": 1022}],
+ "GoLocation": {"x": 5501, "y": 570, "z": 59},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1176, "y": 2635, "z": 0},
+ "Map": "Felucca",
+ "Name": "Destard",
+ "Priority": 50,
+ "Area": [{"x1": 5120, "y1": 770, "x2": 5371, "y2": 1028}],
+ "GoLocation": {"x": 5243, "y": 1004, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 4722, "y": 3814, "z": 0},
+ "Map": "Felucca",
+ "Name": "Hythloth",
+ "Priority": 50,
+ "Area": [{"x1": 5898, "y1": 2, "x2": 6136, "y2": 246}],
+ "GoLocation": {"x": 5905, "y": 22, "z": 44},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 5882, "y": 3819, "z": 0},
+ "Map": "Felucca",
+ "Name": "Khaldun",
+ "Priority": 50,
+ "Area": [{"x1": 5381, "y1": 1284, "x2": 5628, "y2": 1509}],
+ "GoLocation": {"x": 5571, "y": 1302, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "JailRegion",
+ "Map": "Felucca",
+ "Name": "Jail",
+ "Priority": 50,
+ "Area": [{"x1": 5271, "y1": 1159, "x2": 5312, "y2": 1192}],
+ "GoLocation": {"x": 5275, "y": 1163, "z": 0}
+ },
+ {
+ "$type": "GreenAcresRegion",
+ "Map": "Felucca",
+ "Name": "Green Acres",
+ "Priority": 1,
+ "Area": [{"x1": 5376, "y1": 512, "x2": 6143, "y2": 1279}],
+ "GoLocation": {"x": 5445, "y": 1153, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 512, "y": 1559, "z": 0},
+ "Map": "Felucca",
+ "Name": "Shame",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5377, "y1": 2, "x2": 5634, "y2": 262},
+ {"x1": 5635, "y1": 2, "x2": 5895, "y2": 126}
+ ],
+ "GoLocation": {"x": 5395, "y": 126, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2042, "y": 226, "z": 0},
+ "Map": "Felucca",
+ "Name": "Wrong",
+ "Priority": 50,
+ "Area": [{"x1": 5633, "y1": 511, "x2": 5886, "y2": 1021}],
+ "GoLocation": {"x": 5825, "y": 599, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Cave 1",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2373, "y1": 900, "x2": 2395, "y2": 928},
+ {"x1": 2395, "y1": 903, "x2": 2409, "y2": 919},
+ {"x1": 2373, "y1": 928, "x2": 2383, "y2": 937},
+ {"x1": 2359, "y1": 927, "x2": 2373, "y2": 945}
+ ],
+ "GoLocation": {"x": 2367, "y": 942, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Cave 2",
+ "Priority": 50,
+ "Area": [{"x1": 1887, "y1": 354, "x2": 1920, "y2": 377}],
+ "GoLocation": {"x": 1903, "y": 365, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Cave 3",
+ "Priority": 50,
+ "Area": [{"x1": 1925, "y1": 307, "x2": 1943, "y2": 325}],
+ "GoLocation": {"x": 1934, "y": 316, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Cave 4",
+ "Priority": 50,
+ "Area": [{"x1": 2323, "y1": 809, "x2": 2368, "y2": 851}],
+ "GoLocation": {"x": 2345, "y": 830, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Britain Mine 1",
+ "Priority": 50,
+ "Area": [{"x1": 1436, "y1": 1215, "x2": 1465, "y2": 1252}],
+ "GoLocation": {"x": 1443, "y": 1228, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Britain Mine 2",
+ "Priority": 50,
+ "Area": [{"x1": 1611, "y1": 1175, "x2": 1662, "y2": 1204}],
+ "GoLocation": {"x": 1629, "y": 1189, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Minoc Cave 1",
+ "Priority": 50,
+ "Area": [{"x1": 2406, "y1": 168, "x2": 2428, "y2": 184}],
+ "GoLocation": {"x": 2426, "y": 177, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Minoc Cave 2",
+ "Priority": 50,
+ "Area": [{"x1": 2418, "y1": 81, "x2": 2442, "y2": 113}],
+ "GoLocation": {"x": 2440, "y": 94, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Minoc Cave 3",
+ "Priority": 50,
+ "Area": [{"x1": 2447, "y1": 39, "x2": 2489, "y2": 67}],
+ "GoLocation": {"x": 2471, "y": 64, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Minoc Mine",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2556, "y1": 501, "x2": 2562, "y2": 504},
+ {"x1": 2556, "y1": 474, "x2": 2582, "y2": 501}
+ ],
+ "GoLocation": {"x": 2558, "y": 499, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Avatar Isle Cave",
+ "Priority": 50,
+ "Area": [{"x1": 4594, "y1": 3807, "x2": 4617, "y2": 3824}],
+ "GoLocation": {"x": 4605, "y": 3815, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Ice Isle Cave 1",
+ "Priority": 50,
+ "Area": [{"x1": 4018, "y1": 421, "x2": 4067, "y2": 470}],
+ "GoLocation": {"x": 4054, "y": 440, "z": 3}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Ice Isle Cave 2",
+ "Priority": 50,
+ "Area": [
+ {"x1": 4002, "y1": 310, "x2": 4045, "y2": 351},
+ {"x1": 4005, "y1": 298, "x2": 4027, "y2": 310}
+ ],
+ "GoLocation": {"x": 4030, "y": 325, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "North Territory Cave",
+ "Priority": 50,
+ "Area": [{"x1": 1973, "y1": 251, "x2": 1994, "y2": 274}],
+ "GoLocation": {"x": 1984, "y": 262, "z": 8}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Yew Cave",
+ "Priority": 50,
+ "Area": [{"x1": 766, "y1": 1683, "x2": 778, "y2": 1697}],
+ "GoLocation": {"x": 773, "y": 1684, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "North Territory Mine 1",
+ "Priority": 50,
+ "Area": [{"x1": 1713, "y1": 1055, "x2": 1753, "y2": 1080}],
+ "GoLocation": {"x": 1723, "y": 1065, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "North Territory Mine 2",
+ "Priority": 50,
+ "Area": [{"x1": 1604, "y1": 958, "x2": 1650, "y2": 1009}],
+ "GoLocation": {"x": 1638, "y": 974, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Mt Kendall",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2552, "y1": 448, "x2": 2623, "y2": 507},
+ {"x1": 2547, "y1": 380, "x2": 2590, "y2": 448},
+ {"x1": 2590, "y1": 413, "x2": 2623, "y2": 448}
+ ],
+ "GoLocation": {"x": 2593, "y": 477, "z": 60}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "Covetous Mine",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2429, "y1": 866, "x2": 2448, "y2": 911},
+ {"x1": 2448, "y1": 879, "x2": 2475, "y2": 907},
+ {"x1": 2456, "y1": 907, "x2": 2475, "y2": 941}
+ ],
+ "GoLocation": {"x": 2445, "y": 880, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 5426, "y": 3120, "z": 0},
+ "Map": "Felucca",
+ "Name": "Terathan Keep",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5404, "y1": 3099, "x2": 5481, "y2": 3167},
+ {"x1": 5120, "y1": 1530, "x2": 5374, "y2": 1788}
+ ],
+ "GoLocation": {"x": 5451, "y": 3143, "z": -60},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2922, "y": 3402, "z": 0},
+ "Map": "Felucca",
+ "Name": "Fire",
+ "Priority": 50,
+ "Area": [{"x1": 5635, "y1": 1285, "x2": 5880, "y2": 1520}],
+ "GoLocation": {"x": 5760, "y": 2908, "z": 15},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1996, "y": 80, "z": 0},
+ "Map": "Felucca",
+ "Name": "Ice",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5668, "y1": 130, "x2": 5888, "y2": 268},
+ {"x1": 5800, "y1": 319, "x2": 5863, "y2": 384},
+ {"x1": 5654, "y1": 300, "x2": 5708, "y2": 340}
+ ],
+ "GoLocation": {"x": 5210, "y": 2322, "z": 30},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Delucia",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5123, "y1": 3942, "x2": 5315, "y2": 4064},
+ {"x1": 5147, "y1": 4064, "x2": 5272, "y2": 4084},
+ {"x1": 5235, "y1": 3930, "x2": 5315, "y2": 3942}
+ ],
+ "GoLocation": {"x": 5228, "y": 3978, "z": 37}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Delucia", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [{"x1": 5194, "y1": 4053, "x2": 5204, "y2": 4073}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Felucca",
+ "Name": "Papua",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5639, "y1": 3095, "x2": 5831, "y2": 3318},
+ {"x1": 5831, "y1": 3237, "x2": 5851, "y2": 3267}
+ ],
+ "GoLocation": {"x": 5769, "y": 3176, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Felucca",
+ "Parent": { "Name": "Papua", "Map": "Felucca" },
+ "Priority": 50,
+ "Area": [{"x1": 5757, "y1": 3150, "x2": 5781, "y2": 3174}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Felucca",
+ "Name": "Wrong Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 1939, "y1": 215, "x2": 2073, "y2": 352}],
+ "GoLocation": {"x": 2043, "y": 236, "z": 13},
+ "Music": "Mountn_a"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Felucca",
+ "Name": "Covetous Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 2433, "y1": 846, "x2": 2561, "y2": 974}],
+ "GoLocation": {"x": 2499, "y": 918, "z": 0},
+ "Music": "Vesper"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Felucca",
+ "Name": "Despise Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 1289, "y1": 1064, "x2": 1321, "y2": 1101}],
+ "GoLocation": {"x": 1298, "y": 1081, "z": 0}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Felucca",
+ "Name": "Despise Passage",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1338, "y1": 1060, "x2": 1389, "y2": 1122},
+ {"x1": 1354, "y1": 1122, "x2": 1396, "y2": 1243},
+ {"x1": 1349, "y1": 1122, "x2": 1354, "y2": 1224}
+ ],
+ "GoLocation": {"x": 1380, "y": 1114, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1492, "y": 1641, "z": 0},
+ "Map": "Felucca",
+ "Name": "Misc Dungeons",
+ "Priority": 50,
+ "Area": [{"x1": 5886, "y1": 1281, "x2": 6143, "y2": 1535}],
+ "GoLocation": {"x": 6032, "y": 1499, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1014, "y": 1434, "z": 0},
+ "Map": "Felucca",
+ "Name": "Orc Cave",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5281, "y1": 1283, "x2": 5373, "y2": 1386},
+ {"x1": 5267, "y1": 1955, "x2": 5364, "y2": 2046},
+ {"x1": 5127, "y1": 1941, "x2": 5164, "y2": 2024}
+ ],
+ "GoLocation": {"x": 5137, "y": 2015, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "BaseRegion",
+ "RuneName": "A Cotton Field in Moonglow",
+ "Map": "Felucca",
+ "Name": "A Cotton Field in Moonglow",
+ "Priority": 50,
+ "Area": [{"x1": 4557, "y1": 1471, "x2": 4577, "y2": 1481}],
+ "GoLocation": {"x": 4567, "y": 1475, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "RuneName": "A Wheatfield in Skara Brae",
+ "Map": "Felucca",
+ "Name": "A Wheatfield in Skara Brae 1",
+ "Priority": 50,
+ "Area": [{"x1": 796, "y1": 2152, "x2": 832, "y2": 2176}],
+ "GoLocation": {"x": 813, "y": 2163, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "A Carrot Field in Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2251, "x2": 832, "y2": 2259}],
+ "GoLocation": {"x": 823, "y": 2254, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "An Onion Field in Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2261, "x2": 832, "y2": 2269}],
+ "GoLocation": {"x": 823, "y": 2264, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "A Cabbage Field in Skara Brae 1",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2271, "x2": 832, "y2": 2279}],
+ "GoLocation": {"x": 823, "y": 2264, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "A Cabbage Field in Skara Brae 2",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2281, "x2": 832, "y2": 2289}],
+ "GoLocation": {"x": 823, "y": 2274, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "A Wheatfield in Skara Brae 2",
+ "Priority": 50,
+ "Area": [{"x1": 835, "y1": 2344, "x2": 851, "y2": 2360}],
+ "GoLocation": {"x": 843, "y": 2352, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Felucca",
+ "Name": "A Cotton Field in Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2344, "x2": 832, "y2": 2368}],
+ "GoLocation": {"x": 823, "y": 2355, "z": 0}
+ },
+ {
+ "$type": "GuardedRegion",
+ "Map": "Trammel",
+ "Name": "Moongates",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1330, "y1": 1991, "x2": 1343, "y2": 2004},
+ {"x1": 1494, "y1": 3767, "x2": 1506, "y2": 3778},
+ {"x1": 2694, "y1": 685, "x2": 2709, "y2": 701},
+ {"x1": 1823, "y1": 2943, "x2": 1834, "y2": 2954},
+ {"x1": 761, "y1": 741, "x2": 780, "y2": 762},
+ {"x1": 638, "y1": 2062, "x2": 650, "y2": 2073},
+ {"x1": 4459, "y1": 1276, "x2": 4475, "y2": 1292},
+ {"x1": 3554, "y1": 2132, "x2": 3572, "y2": 2150}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Entrance": {"x": 535, "y": 995, "z": 0},
+ "Map": "Trammel",
+ "Name": "The Heartwood",
+ "Priority": 50,
+ "Area": [{"x1": 6911, "y1": 255, "x2": 7168, "y2": 512}],
+ "GoLocation": {"x": 6984, "y": 337, "z": 0},
+ "Music": "ElfCity"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 762, "y": 1645, "z": 0},
+ "Map": "Trammel",
+ "Name": "Sanctuary",
+ "Priority": 50,
+ "Area": [{"x1": 6144, "y1": 0, "x2": 6399, "y2": 255}],
+ "GoLocation": {"x": 6174, "y": 23, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1716, "y": 892, "z": 0},
+ "Map": "Trammel",
+ "Name": "The Painted Caves",
+ "Priority": 50,
+ "Area": [{"x1": 6240, "y1": 850, "x2": 6315, "y2": 920}],
+ "GoLocation": {"x": 6308, "y": 892, "z": -1},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 3784, "y": 1097, "z": 14},
+ "Map": "Trammel",
+ "Name": "The Prism of Light",
+ "Priority": 50,
+ "Area": [{"x1": 6400, "y1": 0, "x2": 6621, "y2": 255}],
+ "GoLocation": {"x": 6474, "y": 188, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 587, "y": 1641, "z": -1},
+ "Map": "Trammel",
+ "Name": "Blighted Grove",
+ "Priority": 50,
+ "Area": [{"x1": 6440, "y1": 820, "x2": 6600, "y2": 970}],
+ "GoLocation": {"x": 6478, "y": 863, "z": 11},
+ "Music": "MelisandesLair"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 5574, "y": 3024, "z": 31},
+ "Map": "Trammel",
+ "Name": "The Palace of Paroxysmus",
+ "Priority": 50,
+ "Area": [{"x1": 6191, "y1": 311, "x2": 6561, "y2": 671}],
+ "GoLocation": {"x": 6222, "y": 335, "z": 60},
+ "Music": "ParoxysmusLair"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Bravehorn's drinking pool",
+ "Priority": 50,
+ "Area": [{"x1": 1302, "y1": 2331, "x2": 1340, "y2": 2353}]
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Huntsman's Forest",
+ "Priority": 50,
+ "Area": [{"x1": 1595, "y1": 550, "x2": 1715, "y2": 670}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Cove",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2200, "y1": 1110, "z1": 0, "x2": 2250, "y2": 1160, "z2": 128},
+ {"x1": 2200, "y1": 1160, "z1": 0, "x2": 2286, "y2": 1246, "z2": 128}
+ ],
+ "GoLocation": {"x": 2275, "y": 1210, "z": 0},
+ "Music": "Cove"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Britain",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1416, "y1": 1498, "z1": -10, "x2": 1740, "y2": 1777, "z2": 128},
+ {"x1": 1500, "y1": 1408, "z1": 0, "x2": 1546, "y2": 1498, "z2": 128},
+ {"x1": 1385, "y1": 1538, "z1": -10, "x2": 1416, "y2": 1777, "z2": 128},
+ {"x1": 1416, "y1": 1777, "z1": 0, "x2": 1740, "y2": 1837, "z2": 128},
+ {"x1": 1385, "y1": 1777, "z1": 0, "x2": 1416, "y2": 1907, "z2": 128},
+ {"x1": 1093, "y1": 1538, "z1": 0, "x2": 1385, "y2": 1907, "z2": 128}
+ ],
+ "GoLocation": {"x": 1495, "y": 1629, "z": 10},
+ "Music": "Britain1"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 1492, "y1": 1602, "z1": 0, "x2": 1500, "y2": 1621, "z2": 128},
+ {"x1": 1500, "y1": 1610, "z1": 0, "x2": 1508, "y2": 1626, "z2": 128},
+ {"x1": 1576, "y1": 1584, "z1": 0, "x2": 1600, "y2": 1600, "z2": 128},
+ {"x1": 1456, "y1": 1512, "z1": 0, "x2": 1472, "y2": 1528, "z2": 128},
+ {"x1": 1472, "y1": 1512, "z1": 0, "x2": 1480, "y2": 1520, "z2": 128},
+ {"x1": 1424, "y1": 1712, "z1": 0, "x2": 1432, "y2": 1736, "z2": 128},
+ {"x1": 1432, "y1": 1712, "z1": 0, "x2": 1440, "y2": 1724, "z2": 128},
+ {"x1": 1486, "y1": 1684, "z1": 0, "x2": 1494, "y2": 1692, "z2": 128},
+ {"x1": 1494, "y1": 1676, "z1": 0, "x2": 1502, "y2": 1700, "z2": 128},
+ {"x1": 1608, "y1": 1584, "z1": 0, "x2": 1632, "y2": 1592, "z2": 128},
+ {"x1": 1616, "y1": 1576, "z1": 0, "x2": 1624, "y2": 1584, "z2": 128},
+ {"x1": 1544, "y1": 1760, "z1": 0, "x2": 1560, "y2": 1776, "z2": 128},
+ {"x1": 1560, "y1": 1760, "z1": 0, "x2": 1568, "y2": 1768, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Wheatfield in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1120, "y1": 1776, "x2": 1152, "y2": 1808}],
+ "GoLocation": {"x": 1135, "y": 1791, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Wheatfield in Britain 2",
+ "Priority": 50,
+ "Area": [{"x1": 1184, "y1": 1808, "x2": 1216, "y2": 1840}],
+ "GoLocation": {"x": 1199, "y": 1823, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Wheatfield in Britain 3",
+ "Priority": 50,
+ "Area": [{"x1": 1216, "y1": 1872, "x2": 1248, "y2": 1904}],
+ "GoLocation": {"x": 1231, "y": 1887, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Carrot Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1208, "y1": 1712, "x2": 1224, "y2": 1736}],
+ "GoLocation": {"x": 1215, "y": 1723, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "An Onion Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1224, "y1": 1712, "x2": 1240, "y2": 1736}],
+ "GoLocation": {"x": 1231, "y": 1723, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Cabbage Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1176, "y1": 1672, "x2": 1192, "y2": 1695}],
+ "GoLocation": {"x": 1183, "y": 1683, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Turnip Field in Britain 1",
+ "Priority": 50,
+ "Area": [{"x1": 1192, "y1": 1672, "x2": 1208, "y2": 1696}],
+ "GoLocation": {"x": 1199, "y": 1683, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Wheatfield in Britain 4",
+ "Priority": 50,
+ "Area": [{"x1": 1104, "y1": 1608, "x2": 1136, "y2": 1640}],
+ "GoLocation": {"x": 1120, "y": 1624, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Wheatfield in Britain 5",
+ "Priority": 50,
+ "Area": [{"x1": 1136, "y1": 1560, "x2": 1168, "y2": 1592}],
+ "GoLocation": {"x": 1152, "y": 1576, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Turnip Field in Britain 2",
+ "Priority": 50,
+ "Area": [{"x1": 1208, "y1": 1592, "x2": 1224, "y2": 1616}],
+ "GoLocation": {"x": 1216, "y": 1604, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Britain", "Map": "Trammel" },
+ "Name": "A Carrot Field in Britain 2",
+ "Priority": 50,
+ "Area": [{"x1": 1224, "y1": 1592, "x2": 1240, "y2": 1616}],
+ "GoLocation": {"x": 1232, "y": 1604, "z": 0}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Britain Graveyard",
+ "Priority": 50,
+ "Area": [{"x1": 1333, "y1": 1441, "x2": 1417, "y2": 1523}],
+ "GoLocation": {"x": 1384, "y": 1492, "z": 10}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Jhelom Islands",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1111, "y1": 3567, "x2": 1144, "y2": 3588},
+ {"x1": 1078, "y1": 3588, "x2": 1202, "y2": 3709},
+ {"x1": 1224, "y1": 3592, "x2": 1533, "y2": 4065}
+ ],
+ "GoLocation": {"x": 1383, "y": 3815, "z": 0},
+ "Music": "Jhelom"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Jhelom Islands", "Map": "Trammel" },
+ "Name": "Jhelom",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1303, "y1": 3670, "z1": -20, "x2": 1492, "y2": 3895, "z2": 128},
+ {"x1": 1338, "y1": 3895, "z1": -20, "x2": 1412, "y2": 3923, "z2": 128},
+ {"x1": 1383, "y1": 3951, "z1": -20, "x2": 1492, "y2": 4045, "z2": 128}
+ ],
+ "GoLocation": {"x": 1383, "y": 3815, "z": 0}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Jhelom", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 1352, "y1": 3800, "z1": -20, "x2": 1368, "y2": 3832, "z2": 128},
+ {"x1": 1368, "y1": 3808, "z1": -20, "x2": 1376, "y2": 3824, "z2": 128},
+ {"x1": 1432, "y1": 3768, "z1": -20, "x2": 1464, "y2": 3776, "z2": 128},
+ {"x1": 1440, "y1": 3776, "z1": -20, "x2": 1464, "y2": 3784, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Minoc",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2411, "y1": 366, "x2": 2546, "y2": 607},
+ {"x1": 2548, "y1": 495, "x2": 2620, "y2": 550},
+ {"x1": 2564, "y1": 585, "x2": 2567, "y2": 627},
+ {"x1": 2567, "y1": 585, "x2": 2628, "y2": 646},
+ {"x1": 2499, "y1": 627, "x2": 2567, "y2": 690}
+ ],
+ "GoLocation": {"x": 2466, "y": 544, "z": 0},
+ "Music": "Minoc"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Minoc", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2457, "y1": 397, "x2": 2497, "y2": 405},
+ {"x1": 2465, "y1": 405, "x2": 2473, "y2": 413},
+ {"x1": 2481, "y1": 405, "x2": 2489, "y2": 413}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Haven Island",
+ "Priority": 50,
+ "Area": [{"x1": 3314, "y1": 2345, "x2": 3814, "y2": 3095}],
+ "GoLocation": {"x": 3627, "y": 2606, "z": 0}
+ },
+ {
+ "$type": "GuardedRegion",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven Island", "Map": "Trammel" },
+ "Name": "New Haven Moongate",
+ "Priority": 50,
+ "Area": [{"x1": 3446, "y1": 2674, "x2": 3456, "y2": 2684}]
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven Island", "Map": "Trammel" },
+ "Name": "New Haven",
+ "Priority": 50,
+ "Area": [{"x1": 3416, "y1": 2480, "x2": 3545, "y2": 2648}],
+ "GoLocation": {"x": 3503, "y": 2574, "z": 14},
+ "Music": "Ocllo"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Little Shop of Alchemy in New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Alchemist",
+ "Priority": 50,
+ "Area": [{"x1": 3457, "y1": 2563, "x2": 3466, "y2": 2572}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Bardic Guild in New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Bard",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3410, "y1": 2598, "x2": 3419, "y2": 2607},
+ {"x1": 3419, "y1": 2599, "x2": 3421, "y2": 2606},
+ {"x1": 3408, "y1": 2607, "x2": 3415, "y2": 2612}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Warrior Guild Hall in New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "Warrior's Guild Hall",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3520, "y1": 2528, "x2": 3543, "y2": 2552},
+ {"x1": 3520, "y1": 2552, "x2": 3534, "y2": 2563}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "Warrior's Guild Hall", "Map": "Trammel" },
+ "Name": "the New Haven Warrior",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3523, "y1": 2546, "x2": 3529, "y2": 2562},
+ {"x1": 3529, "y1": 2550, "x2": 3533, "y2": 2562}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "Warrior's Guild Hall", "Map": "Trammel" },
+ "Name": "the New Haven Bowyer",
+ "Priority": 50,
+ "Area": [{"x1": 3529, "y1": 2531, "x2": 3541, "y2": 2550}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "A Stitch In Time in New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Tailor",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3492, "y1": 2546, "x2": 3502, "y2": 2557},
+ {"x1": 3502, "y1": 2546, "x2": 3505, "y2": 2550}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Carpenters of New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Carpenter",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3439, "y1": 2632, "x2": 3448, "y2": 2643},
+ {"x1": 3440, "y1": 2643, "x2": 3447, "y2": 2648}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Mapmakers of New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Mapmaker",
+ "Priority": 50,
+ "Area": [{"x1": 3490, "y1": 2588, "x2": 3497, "y2": 2595}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "New Haven Magery School",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Mage",
+ "Priority": 50,
+ "Area": [{"x1": 3464, "y1": 2488, "x2": 3491, "y2": 2504}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Bountiful Harvest Inn in New Haven",
+ "NoLogoutDelay": true,
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Inn",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3493, "y1": 2513, "x2": 3503, "y2": 2523},
+ {"x1": 3503, "y1": 2513, "x2": 3510, "y2": 2530}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the docks in New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Docks",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3500, "y1": 2592, "x2": 3508, "y2": 2617},
+ {"x1": 3508, "y1": 2592, "x2": 3516, "y2": 2599},
+ {"x1": 3516, "y1": 2592, "x2": 3524, "y2": 2608}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the First Bank of New Haven",
+ "MinExpansion": "ML",
+ "Map": "Trammel",
+ "Parent": { "Name": "New Haven", "Map": "Trammel" },
+ "Name": "the New Haven Bank",
+ "Priority": 50,
+ "Area": [{"x1": 3479, "y1": 2565, "x2": 3492, "y2": 2580}]
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "Haven City",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven Island", "Map": "Trammel" },
+ "Name": "Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3590, "y1": 2460, "x2": 3708, "y2": 2685},
+ {"x1": 3568, "y1": 2552, "x2": 3590, "y2": 2631},
+ {"x1": 3708, "y1": 2558, "x2": 3761, "y2": 2712},
+ {"x1": 3695, "y1": 2685, "x2": 3708, "y2": 2712}
+ ],
+ "GoLocation": {"x": 3650, "y": 2519, "z": 0},
+ "Music": "Ocllo"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Woodsman in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Woodsman in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3736, "y1": 2680, "x2": 3744, "y2": 2696},
+ {"x1": 3744, "y1": 2680, "x2": 3752, "y2": 2688}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Prime Cut Butcher Shop in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Prime Cut Butcher Shop in Haven",
+ "Priority": 50,
+ "Area": [{"x1": 3704, "y1": 2648, "x2": 3720, "y2": 2656}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "a farm in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [{"x1": 3728, "y1": 2632, "x2": 3736, "y2": 2640}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "a farm in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [{"x1": 3704, "y1": 2584, "x2": 3712, "y2": 2592}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "a farm in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [{"x1": 3736, "y1": 2561, "x2": 3744, "y2": 2568}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Mapmakers of Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "Mapmakers of Haven",
+ "Priority": 50,
+ "Area": [{"x1": 3624, "y1": 2632, "x2": 3640, "y2": 2640}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Haven Blacksmith",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "The Haven Blacksmith",
+ "Priority": 50,
+ "Area": [{"x1": 3641, "y1": 2613, "x2": 3646, "y2": 2624}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Second Bank of Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Second Bank of Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3615, "y1": 2614, "x2": 3631, "y2": 2623},
+ {"x1": 3615, "y1": 2609, "x2": 3624, "y2": 2614}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Uzeraan's Mansion",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "Uzeraan's Mansion",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3583, "y1": 2567, "x2": 3608, "y2": 2608},
+ {"x1": 3608, "y1": 2572, "x2": 3613, "y2": 2603},
+ {"x1": 3572, "y1": 2592, "x2": 3583, "y2": 2603},
+ {"x1": 3575, "y1": 2582, "x2": 3583, "y2": 2592}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Uzeraan's Mansion", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 3592, "y1": 2595, "x2": 3612, "y2": 2599},
+ {"x1": 3595, "y1": 2599, "x2": 3612, "y2": 2602},
+ {"x1": 3595, "y1": 2602, "x2": 3607, "y2": 2607}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Last Chance Provisioners in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "Last Chance Provisioners in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3666, "y1": 2592, "x2": 3681, "y2": 2600},
+ {"x1": 3673, "y1": 2587, "x2": 3681, "y2": 2592}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Healers of Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Healers of Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3659, "y1": 2577, "x2": 3674, "y2": 2584},
+ {"x1": 3661, "y1": 2576, "x2": 3672, "y2": 2577},
+ {"x1": 3663, "y1": 2575, "x2": 3670, "y2": 2576},
+ {"x1": 3661, "y1": 2584, "x2": 3672, "y2": 2585},
+ {"x1": 3663, "y1": 2585, "x2": 3670, "y2": 2586}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Little Shop of Magic in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "The Little Shop of Magic in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3623, "y1": 2565, "x2": 3642, "y2": 2577},
+ {"x1": 3623, "y1": 2577, "x2": 3628, "y2": 2581},
+ {"x1": 3637, "y1": 2577, "x2": 3642, "y2": 2581}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Shakin' Bakery in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "The Shakin' Bakery in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3624, "y1": 2528, "x2": 3632, "y2": 2552},
+ {"x1": 3632, "y1": 2528, "x2": 3640, "y2": 2536},
+ {"x1": 3632, "y1": 2544, "x2": 3640, "y2": 2552}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Bardic Guild in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Bardic Guild in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3672, "y1": 2528, "x2": 3679, "y2": 2544},
+ {"x1": 3655, "y1": 2528, "x2": 3672, "y2": 2536}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Carpenters of Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "Carpenters of Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3632, "y1": 2496, "x2": 3648, "y2": 2504},
+ {"x1": 3640, "y1": 2504, "x2": 3648, "y2": 2512}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "Haven Clockworks and Tinker Shop",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "Haven Clockworks and Tinker Shop",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3656, "y1": 2504, "x2": 3672, "y2": 2512},
+ {"x1": 3664, "y1": 2495, "x2": 3672, "y2": 2504}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Haven Thieves' Guild",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "The Haven Thieves' Guild",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3688, "y1": 2504, "x2": 3696, "y2": 2520},
+ {"x1": 3696, "y1": 2504, "x2": 3704, "y2": 2512}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "A Stitch in Time in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "A Stitch in Time in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3688, "y1": 2464, "x2": 3696, "y2": 2488},
+ {"x1": 3680, "y1": 2472, "x2": 3704, "y2": 2480}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Haven Public Library",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Haven Public Library",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3608, "y1": 2464, "x2": 3616, "y2": 2480},
+ {"x1": 3616, "y1": 2472, "x2": 3624, "y2": 2480}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Gentle Rest Inn in New Haven",
+ "NoLogoutDelay": true,
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "The Gentle Rest Inn in New Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3493, "y1": 2513, "x2": 3509, "y2": 2520},
+ {"x1": 3503, "y1": 2513, "x2": 3510, "y2": 2529}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "The Albatross Bar and Grill in Haven",
+ "NoLogoutDelay": true,
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "The Albatross Bar and Grill in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3664, "y1": 2640, "x2": 3672, "y2": 2656},
+ {"x1": 3672, "y1": 2648, "x2": 3680, "y2": 2656}
+ ],
+ "Music": "Tavern01"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Proving Grounds in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Proving Grounds in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3728, "y1": 2575, "x2": 3736, "y2": 2592},
+ {"x1": 3736, "y1": 2575, "x2": 3737, "y2": 2582}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Bullseye Marksmen in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Bullseye Marksmen in Haven",
+ "Priority": 50,
+ "Area": [{"x1": 3742, "y1": 2575, "x2": 3750, "y2": 2586}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the docks in Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the docks in Haven",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3645, "y1": 2657, "x2": 3672, "y2": 2666},
+ {"x1": 3645, "y1": 2666, "x2": 3651, "y2": 2684},
+ {"x1": 3659, "y1": 2666, "x2": 3665, "y2": 2684}
+ ]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "RuneName": "the Mystic Mines of Haven",
+ "MaxExpansion": "SE",
+ "Map": "Trammel",
+ "Parent": { "Name": "Haven", "Map": "Trammel" },
+ "Name": "the Mystic Mines of Haven",
+ "Priority": 50,
+ "Area": [{"x1": 3752, "y1": 2698, "x2": 3757, "y2": 2707}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Trinsic",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1856, "y1": 2636, "x2": 1931, "y2": 2664},
+ {"x1": 1816, "y1": 2664, "x2": 2099, "y2": 2895},
+ {"x1": 2099, "y1": 2782, "x2": 2117, "y2": 2807},
+ {"x1": 1970, "y1": 2895, "x2": 2017, "y2": 2927},
+ {"x1": 1796, "y1": 2696, "z1": 0, "x2": 1816, "y2": 2763, "z2": 128},
+ {"x1": 1800, "y1": 2796, "z1": 0, "x2": 1816, "y2": 2848, "z2": 128}
+ ],
+ "GoLocation": {"x": 1867, "y": 2780, "z": 0},
+ "Music": "Trinsic"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Trinsic", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 1834, "y1": 2728, "x2": 1856, "y2": 2744},
+ {"x1": 2024, "y1": 2784, "x2": 2040, "y2": 2804},
+ {"x1": 2026, "y1": 2804, "x2": 2040, "y2": 2806},
+ {"x1": 2024, "y1": 2806, "x2": 2040, "y2": 2813},
+ {"x1": 1923, "y1": 2786, "x2": 1935, "y2": 2808},
+ {"x1": 1935, "y1": 2786, "x2": 1942, "y2": 2800}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Vesper",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2893, "y1": 598, "x2": 3014, "y2": 648},
+ {"x1": 2816, "y1": 648, "x2": 3065, "y2": 1013},
+ {"x1": 2734, "y1": 944, "x2": 2816, "y2": 948},
+ {"x1": 2728, "y1": 948, "x2": 2816, "y2": 1001}
+ ],
+ "GoLocation": {"x": 2899, "y": 676, "z": 0},
+ "Music": "Vesper"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Vesper", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2952, "y1": 864, "x2": 2968, "y2": 896},
+ {"x1": 2968, "y1": 872, "x2": 2976, "y2": 888},
+ {"x1": 2776, "y1": 952, "x2": 2792, "y2": 984},
+ {"x1": 2768, "y1": 960, "x2": 2776, "y2": 976},
+ {"x1": 2892, "y1": 901, "x2": 2908, "y2": 920},
+ {"x1": 2908, "y1": 904, "x2": 2916, "y2": 912}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Yew",
+ "Priority": 50,
+ "Area": [
+ {"x1": 92, "y1": 656, "z1": 0, "x2": 441, "y2": 881, "z2": 39},
+ {"x1": 441, "y1": 746, "z1": 0, "x2": 657, "y2": 881, "z2": 39},
+ {"x1": 258, "y1": 881, "z1": 0, "x2": 657, "y2": 1261, "z2": 39},
+ {"x1": 657, "y1": 922, "z1": 0, "x2": 699, "y2": 1229, "z2": 39},
+ {"x1": 657, "y1": 806, "z1": 0, "x2": 674, "y2": 834, "z2": 39},
+ {"x1": 718, "y1": 874, "z1": 0, "x2": 756, "y2": 896, "z2": 39}
+ ],
+ "GoLocation": {"x": 546, "y": 992, "z": 0},
+ "Music": "Yew"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Yew", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [{"x1": 600, "y1": 808, "z1": 0, "x2": 624, "y2": 832, "z2": 39}]
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Field of Sheep in Yew",
+ "Map": "Trammel",
+ "Parent": { "Name": "Yew", "Map": "Trammel" },
+ "Name": "A Field of Sheep in Yew 1",
+ "Priority": 50,
+ "Area": [{"x1": 664, "y1": 928, "x2": 686, "y2": 950}],
+ "GoLocation": {"x": 675, "y": 939, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Field of Sheep in Yew",
+ "Map": "Trammel",
+ "Parent": { "Name": "Yew", "Map": "Trammel" },
+ "Name": "A Field of Sheep in Yew 2",
+ "Priority": 50,
+ "Area": [{"x1": 664, "y1": 1168, "x2": 686, "y2": 1190}],
+ "GoLocation": {"x": 675, "y": 1179, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Farm in Yew",
+ "Map": "Trammel",
+ "Parent": { "Name": "Yew", "Map": "Trammel" },
+ "Name": "A Farm in Yew",
+ "Priority": 50,
+ "Area": [{"x1": 560, "y1": 1088, "x2": 582, "y2": 1110}],
+ "GoLocation": {"x": 571, "y": 1099, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Wheatfield in Yew",
+ "Map": "Trammel",
+ "Parent": { "Name": "Yew", "Map": "Trammel" },
+ "Name": "A Wheatfield in Yew 1",
+ "Priority": 50,
+ "Area": [{"x1": 560, "y1": 1232, "x2": 576, "y2": 1248}],
+ "GoLocation": {"x": 567, "y": 1239, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "RuneName": "A Wheatfield in Yew",
+ "Map": "Trammel",
+ "Parent": { "Name": "Yew", "Map": "Trammel" },
+ "Name": "A Wheatfield in Yew 2",
+ "Priority": 50,
+ "Area": [{"x1": 368, "y1": 1176, "x2": 382, "y2": 1208}],
+ "GoLocation": {"x": 375, "y": 1191, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Wind",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5294, "y1": 19, "x2": 5366, "y2": 139},
+ {"x1": 5132, "y1": 58, "x2": 5213, "y2": 126},
+ {"x1": 5197, "y1": 126, "x2": 5252, "y2": 204},
+ {"x1": 5132, "y1": 3, "x2": 5202, "y2": 58},
+ {"x1": 5252, "y1": 112, "x2": 5294, "y2": 170},
+ {"x1": 5213, "y1": 98, "x2": 5252, "y2": 126},
+ {"x1": 5279, "y1": 57, "x2": 5294, "y2": 112},
+ {"x1": 5252, "y1": 170, "x2": 5284, "y2": 178},
+ {"x1": 5286, "y1": 25, "x2": 5294, "y2": 57},
+ {"x1": 5252, "y1": 178, "x2": 5272, "y2": 183},
+ {"x1": 5252, "y1": 183, "x2": 5262, "y2": 193}
+ ],
+ "GoLocation": {"x": 5223, "y": 190, "z": 5},
+ "Music": "Wind"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Wind", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 5159, "y1": 15, "x2": 5184, "y2": 24},
+ {"x1": 5159, "y1": 24, "x2": 5168, "y2": 40},
+ {"x1": 5175, "y1": 24, "x2": 5184, "y2": 32},
+ {"x1": 5212, "y1": 159, "x2": 5221, "y2": 183},
+ {"x1": 5221, "y1": 171, "x2": 5228, "y2": 183},
+ {"x1": 5206, "y1": 164, "x2": 5212, "y2": 179},
+ {"x1": 5303, "y1": 28, "x2": 5319, "y2": 42}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Serpent's Hold",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2868, "y1": 3324, "z1": 0, "x2": 3073, "y2": 3519, "z2": 128}
+ ],
+ "GoLocation": {"x": 3010, "y": 3371, "z": 15},
+ "Music": "Serpents"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Serpent's Hold", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2960, "y1": 3400, "z1": 0, "x2": 2976, "y2": 3416, "z2": 128},
+ {"x1": 2968, "y1": 3416, "z1": 0, "x2": 2976, "y2": 3432, "z2": 128},
+ {"x1": 3008, "y1": 3450, "z1": 0, "x2": 3022, "y2": 3464, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 538, "y1": 2107, "x2": 688, "y2": 2297}],
+ "GoLocation": {"x": 632, "y": 2233, "z": 0},
+ "Music": "Skarabra"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Skara Brae", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 600, "y1": 2232, "x2": 616, "y2": 2256},
+ {"x1": 592, "y1": 2240, "x2": 600, "y2": 2256},
+ {"x1": 616, "y1": 2240, "x2": 624, "y2": 2256},
+ {"x1": 552, "y1": 2168, "x2": 568, "y2": 2192},
+ {"x1": 568, "y1": 2168, "x2": 576, "y2": 2176}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Nujel'm",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3475, "y1": 1000, "z1": 0, "x2": 3835, "y2": 1435, "z2": 128}
+ ],
+ "GoLocation": {"x": 3732, "y": 1279, "z": 0},
+ "Music": "Nujelm"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Nujel'm", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 3736, "y1": 1184, "z1": 0, "x2": 3752, "y2": 1207, "z2": 128},
+ {"x1": 3728, "y1": 1192, "z1": 0, "x2": 3736, "y2": 1207, "z2": 128},
+ {"x1": 3728, "y1": 1288, "z1": 0, "x2": 3751, "y2": 1303, "z2": 128},
+ {"x1": 3728, "y1": 1303, "z1": 0, "x2": 3744, "y2": 1312, "z2": 128},
+ {"x1": 3728, "y1": 1312, "z1": 0, "x2": 3740, "y2": 1320, "z2": 128},
+ {"x1": 3728, "y1": 1320, "z1": 0, "x2": 3744, "y2": 1343, "z2": 128},
+ {"x1": 3744, "y1": 1328, "z1": 0, "x2": 3751, "y2": 1343, "z2": 128},
+ {"x1": 3760, "y1": 1216, "z1": 0, "x2": 3772, "y2": 1240, "z2": 128},
+ {"x1": 3772, "y1": 1220, "z1": 0, "x2": 3776, "y2": 1236, "z2": 128},
+ {"x1": 3776, "y1": 1224, "z1": 0, "x2": 3784, "y2": 1232, "z2": 128},
+ {"x1": 3728, "y1": 1248, "z1": 0, "x2": 3744, "y2": 1272, "z2": 128},
+ {"x1": 3744, "y1": 1248, "z1": 0, "x2": 3752, "y2": 1256, "z2": 128},
+ {"x1": 3744, "y1": 1264, "z1": 0, "x2": 3752, "y2": 1272, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Moonglow",
+ "Priority": 50,
+ "Area": [
+ {"x1": 4535, "y1": 844, "z1": 0, "x2": 4555, "y2": 847, "z2": 128},
+ {"x1": 4530, "y1": 847, "z1": 0, "x2": 4561, "y2": 908, "z2": 128},
+ {"x1": 4521, "y1": 914, "z1": 0, "x2": 4577, "y2": 963, "z2": 128},
+ {"x1": 4278, "y1": 915, "z1": 0, "x2": 4332, "y2": 934, "z2": 128},
+ {"x1": 4283, "y1": 944, "z1": 0, "x2": 4336, "y2": 1017, "z2": 128},
+ {"x1": 4377, "y1": 1015, "z1": -10, "x2": 4436, "y2": 1052, "z2": 128},
+ {"x1": 4367, "y1": 1050, "z1": 0, "x2": 4509, "y2": 1195, "z2": 128},
+ {"x1": 4539, "y1": 1036, "z1": 0, "x2": 4566, "y2": 1054, "z2": 128},
+ {"x1": 4517, "y1": 1053, "z1": 0, "x2": 4540, "y2": 1075, "z2": 128},
+ {"x1": 4389, "y1": 1198, "z1": 0, "x2": 4436, "y2": 1237, "z2": 128},
+ {"x1": 4466, "y1": 1211, "z1": 0, "x2": 4498, "y2": 1236, "z2": 128},
+ {"x1": 4700, "y1": 1108, "z1": 0, "x2": 4717, "y2": 1126, "z2": 128},
+ {"x1": 4656, "y1": 1127, "z1": 0, "x2": 4682, "y2": 1140, "z2": 128},
+ {"x1": 4678, "y1": 1162, "z1": 0, "x2": 4703, "y2": 1187, "z2": 128},
+ {"x1": 4613, "y1": 1196, "z1": 0, "x2": 4636, "y2": 1218, "z2": 128},
+ {"x1": 4646, "y1": 1212, "z1": 0, "x2": 4660, "y2": 1229, "z2": 128},
+ {"x1": 4677, "y1": 1214, "z1": 0, "x2": 4703, "y2": 1236, "z2": 128},
+ {"x1": 4622, "y1": 1316, "z1": 0, "x2": 4644, "y2": 1340, "z2": 128},
+ {"x1": 4487, "y1": 1353, "z1": 0, "x2": 4546, "y2": 1374, "z2": 128},
+ {"x1": 4477, "y1": 1374, "z1": 0, "x2": 4546, "y2": 1409, "z2": 128},
+ {"x1": 4659, "y1": 1387, "z1": 0, "x2": 4699, "y2": 1427, "z2": 128},
+ {"x1": 4549, "y1": 1482, "z1": 0, "x2": 4578, "y2": 1509, "z2": 128},
+ {"x1": 4405, "y1": 1451, "z1": 0, "x2": 4428, "y2": 1474, "z2": 128},
+ {"x1": 4483, "y1": 1468, "z1": 0, "x2": 4504, "y2": 1481, "z2": 128}
+ ],
+ "GoLocation": {"x": 4442, "y": 1172, "z": 0},
+ "Music": "Moonglow"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Moonglow", "Map": "Trammel" },
+ "Name": "The Scholar's Inn",
+ "Priority": 50,
+ "Area": [
+ {"x1": 4384, "y1": 1152, "z1": 0, "x2": 4392, "y2": 1176, "z2": 128},
+ {"x1": 4392, "y1": 1160, "z1": 0, "x2": 4408, "y2": 1168, "z2": 128},
+ {"x1": 4400, "y1": 1152, "z1": 0, "x2": 4408, "y2": 1160, "z2": 128},
+ {"x1": 4480, "y1": 1056, "z1": 0, "x2": 4488, "y2": 1072, "z2": 128},
+ {"x1": 4488, "y1": 1060, "z1": 0, "x2": 4492, "y2": 1068, "z2": 128},
+ {"x1": 4476, "y1": 1060, "z1": 0, "x2": 4480, "y2": 1068, "z2": 128}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Magincia",
+ "Priority": 50,
+ "Area": [
+ {"x1": 3653, "y1": 2046, "x2": 3680, "y2": 2094},
+ {"x1": 3752, "y1": 2046, "x2": 3804, "y2": 2094},
+ {"x1": 3680, "y1": 2045, "x2": 3752, "y2": 2094},
+ {"x1": 3652, "y1": 2094, "x2": 3812, "y2": 2274},
+ {"x1": 3649, "y1": 2256, "x2": 3703, "y2": 2303}
+ ],
+ "GoLocation": {"x": 3714, "y": 2220, "z": 20},
+ "Music": "Magincia"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Magincia", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 3680, "y1": 2152, "x2": 3704, "y2": 2160},
+ {"x1": 3720, "y1": 2216, "x2": 3736, "y2": 2232}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Buccaneer's Den",
+ "Priority": 50,
+ "GuardsDisabled": true,
+ "Area": [
+ {"x1": 2612, "y1": 2057, "x2": 2776, "y2": 2267},
+ {"x1": 2604, "y1": 2065, "z1": 0, "x2": 2612, "y2": 2254, "z2": 128}
+ ],
+ "GoLocation": {"x": 2706, "y": 2163, "z": 0},
+ "Music": "Bucsden"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Buccaneer's Den", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [
+ {"x1": 2712, "y1": 2080, "x2": 2728, "y2": 2096},
+ {"x1": 2712, "y1": 2096, "x2": 2720, "y2": 2104},
+ {"x1": 2664, "y1": 2232, "x2": 2688, "y2": 2240},
+ {"x1": 2672, "y1": 2240, "x2": 2688, "y2": 2248}
+ ]
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2499, "y": 916, "z": 0},
+ "Map": "Trammel",
+ "Name": "Covetous",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5376, "y1": 1793, "x2": 5577, "y2": 2048},
+ {"x1": 5576, "y1": 1791, "x2": 5633, "y2": 2048}
+ ],
+ "GoLocation": {"x": 5456, "y": 1862, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 4111, "y": 429, "z": 0},
+ "Map": "Trammel",
+ "Name": "Deceit",
+ "Priority": 50,
+ "Area": [{"x1": 5122, "y1": 518, "x2": 5370, "y2": 770}],
+ "GoLocation": {"x": 5187, "y": 635, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1296, "y": 1082, "z": 0},
+ "Map": "Trammel",
+ "Name": "Despise",
+ "Priority": 50,
+ "Area": [{"x1": 5377, "y1": 516, "x2": 5631, "y2": 1022}],
+ "GoLocation": {"x": 5501, "y": 570, "z": 59},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1176, "y": 2635, "z": 0},
+ "Map": "Trammel",
+ "Name": "Destard",
+ "Priority": 50,
+ "Area": [{"x1": 5120, "y1": 770, "x2": 5371, "y2": 1028}],
+ "GoLocation": {"x": 5243, "y": 1004, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 4722, "y": 3814, "z": 0},
+ "Map": "Trammel",
+ "Name": "Hythloth",
+ "Priority": 50,
+ "Area": [{"x1": 5898, "y1": 2, "x2": 6136, "y2": 246}],
+ "GoLocation": {"x": 5905, "y": 22, "z": 44},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "JailRegion",
+ "Map": "Trammel",
+ "Name": "Jail",
+ "Priority": 50,
+ "Area": [{"x1": 5271, "y1": 1159, "x2": 5312, "y2": 1192}],
+ "GoLocation": {"x": 5275, "y": 1163, "z": 0}
+ },
+ {
+ "$type": "GreenAcresRegion",
+ "Map": "Trammel",
+ "Name": "Green Acres",
+ "Priority": 1,
+ "Area": [{"x1": 5376, "y1": 512, "x2": 6143, "y2": 1279}],
+ "GoLocation": {"x": 5445, "y": 1153, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 512, "y": 1559, "z": 0},
+ "Map": "Trammel",
+ "Name": "Shame",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5377, "y1": 2, "x2": 5634, "y2": 262},
+ {"x1": 5635, "y1": 2, "x2": 5895, "y2": 126}
+ ],
+ "GoLocation": {"x": 5395, "y": 126, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2042, "y": 226, "z": 0},
+ "Map": "Trammel",
+ "Name": "Wrong",
+ "Priority": 50,
+ "Area": [{"x1": 5633, "y1": 511, "x2": 5886, "y2": 1021}],
+ "GoLocation": {"x": 5825, "y": 599, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Cave 1",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2373, "y1": 900, "x2": 2395, "y2": 928},
+ {"x1": 2395, "y1": 903, "x2": 2409, "y2": 919},
+ {"x1": 2373, "y1": 928, "x2": 2383, "y2": 937},
+ {"x1": 2359, "y1": 927, "x2": 2373, "y2": 945}
+ ],
+ "GoLocation": {"x": 2367, "y": 942, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Cave 2",
+ "Priority": 50,
+ "Area": [{"x1": 1887, "y1": 354, "x2": 1920, "y2": 377}],
+ "GoLocation": {"x": 1903, "y": 365, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Cave 3",
+ "Priority": 50,
+ "Area": [{"x1": 1925, "y1": 307, "x2": 1943, "y2": 325}],
+ "GoLocation": {"x": 1934, "y": 316, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Cave 4",
+ "Priority": 50,
+ "Area": [{"x1": 2323, "y1": 809, "x2": 2368, "y2": 851}],
+ "GoLocation": {"x": 2345, "y": 830, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Britain Mine 1",
+ "Priority": 50,
+ "Area": [{"x1": 1436, "y1": 1215, "x2": 1465, "y2": 1252}],
+ "GoLocation": {"x": 1443, "y": 1228, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Britain Mine 2",
+ "Priority": 50,
+ "Area": [{"x1": 1611, "y1": 1175, "x2": 1662, "y2": 1204}],
+ "GoLocation": {"x": 1629, "y": 1189, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Minoc Cave 1",
+ "Priority": 50,
+ "Area": [{"x1": 2406, "y1": 168, "x2": 2428, "y2": 184}],
+ "GoLocation": {"x": 2426, "y": 177, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Minoc Cave 2",
+ "Priority": 50,
+ "Area": [{"x1": 2418, "y1": 81, "x2": 2442, "y2": 113}],
+ "GoLocation": {"x": 2440, "y": 94, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Minoc Cave 3",
+ "Priority": 50,
+ "Area": [{"x1": 2447, "y1": 39, "x2": 2489, "y2": 67}],
+ "GoLocation": {"x": 2471, "y": 64, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Minoc Mine",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2556, "y1": 501, "x2": 2562, "y2": 504},
+ {"x1": 2556, "y1": 474, "x2": 2582, "y2": 501}
+ ],
+ "GoLocation": {"x": 2558, "y": 499, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Avatar Isle Cave",
+ "Priority": 50,
+ "Area": [{"x1": 4594, "y1": 3807, "x2": 4617, "y2": 3824}],
+ "GoLocation": {"x": 4605, "y": 3815, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Ice Isle Cave 1",
+ "Priority": 50,
+ "Area": [{"x1": 4018, "y1": 421, "x2": 4067, "y2": 470}],
+ "GoLocation": {"x": 4054, "y": 440, "z": 3}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Ice Isle Cave 2",
+ "Priority": 50,
+ "Area": [
+ {"x1": 4002, "y1": 310, "x2": 4045, "y2": 351},
+ {"x1": 4005, "y1": 298, "x2": 4027, "y2": 310}
+ ],
+ "GoLocation": {"x": 4030, "y": 325, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "North Territory Cave",
+ "Priority": 50,
+ "Area": [{"x1": 1973, "y1": 251, "x2": 1994, "y2": 274}],
+ "GoLocation": {"x": 1984, "y": 262, "z": 8}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Yew Cave",
+ "Priority": 50,
+ "Area": [{"x1": 766, "y1": 1683, "x2": 778, "y2": 1697}],
+ "GoLocation": {"x": 773, "y": 1684, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "North Territory Mine 1",
+ "Priority": 50,
+ "Area": [{"x1": 1713, "y1": 1055, "x2": 1753, "y2": 1080}],
+ "GoLocation": {"x": 1723, "y": 1065, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "North Territory Mine 2",
+ "Priority": 50,
+ "Area": [{"x1": 1604, "y1": 958, "x2": 1650, "y2": 1009}],
+ "GoLocation": {"x": 1638, "y": 974, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Mt Kendall",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2552, "y1": 448, "x2": 2623, "y2": 507},
+ {"x1": 2547, "y1": 380, "x2": 2590, "y2": 448},
+ {"x1": 2590, "y1": 413, "x2": 2623, "y2": 448}
+ ],
+ "GoLocation": {"x": 2593, "y": 477, "z": 60}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "Covetous Mine",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2429, "y1": 866, "x2": 2448, "y2": 911},
+ {"x1": 2448, "y1": 879, "x2": 2475, "y2": 907},
+ {"x1": 2456, "y1": 907, "x2": 2475, "y2": 941}
+ ],
+ "GoLocation": {"x": 2445, "y": 880, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 5426, "y": 3120, "z": 0},
+ "Map": "Trammel",
+ "Name": "Terathan Keep",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5404, "y1": 3099, "x2": 5481, "y2": 3167},
+ {"x1": 5120, "y1": 1530, "x2": 5374, "y2": 1788}
+ ],
+ "GoLocation": {"x": 5451, "y": 3143, "z": -60},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2922, "y": 3402, "z": 0},
+ "Map": "Trammel",
+ "Name": "Fire",
+ "Priority": 50,
+ "Area": [{"x1": 5635, "y1": 1285, "x2": 5880, "y2": 1520}],
+ "GoLocation": {"x": 5760, "y": 2908, "z": 15},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1996, "y": 80, "z": 0},
+ "Map": "Trammel",
+ "Name": "Ice",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5668, "y1": 130, "x2": 5888, "y2": 268},
+ {"x1": 5800, "y1": 319, "x2": 5863, "y2": 384},
+ {"x1": 5654, "y1": 300, "x2": 5708, "y2": 340}
+ ],
+ "GoLocation": {"x": 5210, "y": 2322, "z": 30},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Delucia",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5123, "y1": 3942, "x2": 5315, "y2": 4064},
+ {"x1": 5147, "y1": 4064, "x2": 5272, "y2": 4084},
+ {"x1": 5235, "y1": 3930, "x2": 5315, "y2": 3942}
+ ],
+ "GoLocation": {"x": 5228, "y": 3978, "z": 37}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Delucia", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [{"x1": 5194, "y1": 4053, "x2": 5204, "y2": 4073}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Trammel",
+ "Name": "Papua",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5639, "y1": 3095, "x2": 5831, "y2": 3318},
+ {"x1": 5831, "y1": 3237, "x2": 5851, "y2": 3267}
+ ],
+ "GoLocation": {"x": 5769, "y": 3176, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Trammel",
+ "Parent": { "Name": "Papua", "Map": "Trammel" },
+ "Priority": 50,
+ "Area": [{"x1": 5757, "y1": 3150, "x2": 5781, "y2": 3174}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Wrong Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 1939, "y1": 215, "x2": 2073, "y2": 352}],
+ "GoLocation": {"x": 2043, "y": 236, "z": 13},
+ "Music": "Mountn_a"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Covetous Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 2433, "y1": 846, "x2": 2561, "y2": 974}],
+ "GoLocation": {"x": 2499, "y": 918, "z": 0},
+ "Music": "Vesper"
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Despise Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 1289, "y1": 1064, "x2": 1321, "y2": 1101}],
+ "GoLocation": {"x": 1298, "y": 1081, "z": 0}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Trammel",
+ "Name": "Despise Passage",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1338, "y1": 1060, "x2": 1389, "y2": 1122},
+ {"x1": 1354, "y1": 1122, "x2": 1396, "y2": 1243},
+ {"x1": 1349, "y1": 1122, "x2": 1354, "y2": 1224}
+ ],
+ "GoLocation": {"x": 1380, "y": 1114, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1492, "y": 1641, "z": 0},
+ "Map": "Trammel",
+ "Name": "Misc Dungeons",
+ "Priority": 50,
+ "Area": [{"x1": 5886, "y1": 1281, "x2": 6143, "y2": 1535}],
+ "GoLocation": {"x": 6032, "y": 1499, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1014, "y": 1434, "z": 0},
+ "Map": "Trammel",
+ "Name": "Orc Cave",
+ "Priority": 50,
+ "Area": [
+ {"x1": 5281, "y1": 1283, "x2": 5373, "y2": 1386},
+ {"x1": 5267, "y1": 1955, "x2": 5364, "y2": 2046},
+ {"x1": 5127, "y1": 1941, "x2": 5164, "y2": 2024}
+ ],
+ "GoLocation": {"x": 5137, "y": 2015, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "BaseRegion",
+ "RuneName": "A Cotton Field in Moonglow",
+ "Map": "Trammel",
+ "Name": "A Cotton Field in Moonglow",
+ "Priority": 50,
+ "Area": [{"x1": 4557, "y1": 1471, "x2": 4577, "y2": 1481}],
+ "GoLocation": {"x": 4567, "y": 1475, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "RuneName": "A Wheatfield in Skara Brae",
+ "Map": "Trammel",
+ "Name": "A Wheatfield in Skara Brae 1",
+ "Priority": 50,
+ "Area": [{"x1": 796, "y1": 2152, "x2": 832, "y2": 2176}],
+ "GoLocation": {"x": 813, "y": 2163, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "A Carrot Field in Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2251, "x2": 832, "y2": 2259}],
+ "GoLocation": {"x": 823, "y": 2254, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "An Onion Field in Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2261, "x2": 832, "y2": 2269}],
+ "GoLocation": {"x": 823, "y": 2264, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "A Cabbage Field in Skara Brae 1",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2271, "x2": 832, "y2": 2279}],
+ "GoLocation": {"x": 823, "y": 2264, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "A Cabbage Field in Skara Brae 2",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2281, "x2": 832, "y2": 2289}],
+ "GoLocation": {"x": 823, "y": 2274, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "A Wheatfield in Skara Brae 2",
+ "Priority": 50,
+ "Area": [{"x1": 835, "y1": 2344, "x2": 851, "y2": 2360}],
+ "GoLocation": {"x": 843, "y": 2352, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Trammel",
+ "Name": "A Cotton Field in Skara Brae",
+ "Priority": 50,
+ "Area": [{"x1": 816, "y1": 2344, "x2": 832, "y2": 2368}],
+ "GoLocation": {"x": 823, "y": 2355, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1450, "y": 1473, "z": -23},
+ "Map": "Ilshenar",
+ "Name": "Twisted Weald",
+ "Priority": 50,
+ "Area": [{"x1": 2107, "y1": 1145, "x2": 2254, "y2": 1280}],
+ "GoLocation": {"x": 2189, "y": 1253, "z": 0},
+ "Music": "DreadHornArea"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Sheep Farm",
+ "Priority": 50,
+ "Area": [{"x1": 1298, "y1": 1307, "x2": 1336, "y2": 1344}]
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Valor",
+ "Priority": 37,
+ "Area": [{"x1": 512, "y1": 200, "x2": 544, "y2": 232}],
+ "GoLocation": {"x": 539, "y": 221, "z": -36}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Chaos Shrine",
+ "Priority": 50,
+ "Area": [{"x1": 1736, "y1": 224, "x2": 1760, "y2": 248}],
+ "GoLocation": {"x": 1748, "y": 236, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Sacrifice",
+ "Priority": 50,
+ "Area": [{"x1": 1160, "y1": 1280, "x2": 1192, "y2": 1296}],
+ "GoLocation": {"x": 1196, "y": 1290, "z": -25}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Honesty",
+ "Priority": 37,
+ "Area": [{"x1": 712, "y1": 1344, "x2": 736, "y2": 1376}],
+ "GoLocation": {"x": 725, "y": 1355, "z": -61}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Compassion",
+ "Priority": 50,
+ "Area": [{"x1": 1200, "y1": 448, "x2": 1232, "y2": 488}],
+ "GoLocation": {"x": 1223, "y": 475, "z": -16}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Spirituality",
+ "Priority": 50,
+ "Area": [{"x1": 1520, "y1": 1336, "x2": 1536, "y2": 1352}],
+ "GoLocation": {"x": 1528, "y": 1344, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Humility",
+ "Priority": 50,
+ "Area": [{"x1": 272, "y1": 1008, "x2": 296, "y2": 1024}],
+ "GoLocation": {"x": 284, "y": 1016, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of Honor",
+ "Priority": 50,
+ "Area": [{"x1": 736, "y1": 712, "x2": 760, "y2": 744}],
+ "GoLocation": {"x": 748, "y": 728, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Terort Skitas",
+ "Priority": 11,
+ "Area": [{"x1": 528, "y1": 376, "x2": 624, "y2": 464}],
+ "GoLocation": {"x": 568, "y": 430, "z": 41}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Gargoyle City",
+ "Priority": 50,
+ "Area": [
+ {"x1": 824, "y1": 552, "x2": 856, "y2": 728},
+ {"x1": 752, "y1": 576, "x2": 824, "y2": 704},
+ {"x1": 856, "y1": 576, "x2": 904, "y2": 704},
+ {"x1": 904, "y1": 624, "x2": 928, "y2": 656}
+ ],
+ "GoLocation": {"x": 840, "y": 571, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Ilshenar",
+ "Parent": { "Name": "Gargoyle City", "Map": "Ilshenar" },
+ "Priority": 50,
+ "Area": [{"x1": 827, "y1": 694, "x2": 853, "y2": 727}]
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Pormir Harm",
+ "Priority": 50,
+ "Area": [{"x1": 736, "y1": 480, "x2": 768, "y2": 504}],
+ "GoLocation": {"x": 745, "y": 492, "z": -66},
+ "Music": "Stones2"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Pormir Felwis",
+ "Priority": 50,
+ "Area": [{"x1": 472, "y1": 336, "x2": 512, "y2": 368}],
+ "GoLocation": {"x": 472, "y": 352, "z": -78}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Cyclops Temple",
+ "Priority": 50,
+ "Area": [{"x1": 880, "y1": 1256, "x2": 936, "y2": 1368}],
+ "GoLocation": {"x": 901, "y": 1297, "z": -71}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Rat Fort",
+ "Priority": 50,
+ "Area": [{"x1": 616, "y1": 792, "x2": 672, "y2": 848}],
+ "GoLocation": {"x": 642, "y": 845, "z": -58}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Rat Fort Cellar",
+ "Priority": 50,
+ "Area": [{"x1": 160, "y1": 736, "x2": 192, "y2": 768}],
+ "GoLocation": {"x": 171, "y": 750, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance to Central Ilshenar 1",
+ "Priority": 50,
+ "Area": [{"x1": 1136, "y1": 584, "x2": 1152, "y2": 600}],
+ "GoLocation": {"x": 1141, "y": 594, "z": -80}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance to Central Ilshenar 2",
+ "Priority": 50,
+ "Area": [{"x1": 1232, "y1": 576, "x2": 1240, "y2": 592}],
+ "GoLocation": {"x": 1238, "y": 583, "z": -19}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Montor",
+ "Priority": 41,
+ "GuardsDisabled": true,
+ "Area": [
+ {"x1": 1576, "y1": 272, "x2": 1720, "y2": 368},
+ {"x1": 1616, "y1": 200, "x2": 1696, "y2": 272},
+ {"x1": 1696, "y1": 144, "x2": 1736, "y2": 272},
+ {"x1": 1736, "y1": 144, "x2": 1768, "y2": 208}
+ ],
+ "GoLocation": {"x": 1646, "y": 319, "z": 48}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Termir Flam",
+ "Priority": 40,
+ "Area": [
+ {"x1": 1520, "y1": 368, "x2": 1752, "y2": 496},
+ {"x1": 1520, "y1": 296, "x2": 1576, "y2": 368},
+ {"x1": 1752, "y1": 440, "x2": 1776, "y2": 480}
+ ],
+ "GoLocation": {"x": 1636, "y": 432, "z": 0}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Ancient Citadel",
+ "Priority": 11,
+ "GuardsDisabled": true,
+ "Area": [{"x1": 1448, "y1": 496, "x2": 1552, "y2": 600}],
+ "GoLocation": {"x": 1516, "y": 542, "z": 85}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Alexandretta's Bowl",
+ "Priority": 41,
+ "GuardsDisabled": true,
+ "Area": [{"x1": 1272, "y1": 352, "x2": 1440, "y2": 592}],
+ "GoLocation": {"x": 1396, "y": 432, "z": -17}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance to Rock Dungeon",
+ "Priority": 2,
+ "Area": [{"x1": 1784, "y1": 560, "x2": 1792, "y2": 576}],
+ "GoLocation": {"x": 1784, "y": 568, "z": 100}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1788, "y": 571, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Rock Dungeon",
+ "Priority": 2,
+ "Area": [
+ {"x1": 2176, "y1": 288, "x2": 2200, "y2": 328},
+ {"x1": 2088, "y1": 8, "x2": 2248, "y2": 184}
+ ],
+ "GoLocation": {"x": 2187, "y": 316, "z": -7}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Lenmir Anfinmotas",
+ "Priority": 5,
+ "GuardsDisabled": true,
+ "Area": [{"x1": 1560, "y1": 792, "x2": 1792, "y2": 912}],
+ "GoLocation": {"x": 1673, "y": 876, "z": -25}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance to Spider Cave",
+ "Priority": 2,
+ "Area": [{"x1": 1400, "y1": 896, "x2": 1440, "y2": 920}],
+ "GoLocation": {"x": 1418, "y": 915, "z": -19}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1420, "y": 910, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Spider Cave",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1752, "y1": 952, "x2": 1864, "y2": 1000},
+ {"x1": 1480, "y1": 864, "x2": 1528, "y2": 896}
+ ],
+ "GoLocation": {"x": 1785, "y": 991, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Twin Oaks",
+ "Priority": 48,
+ "Area": [{"x1": 1536, "y1": 1032, "x2": 1584, "y2": 1072}],
+ "GoLocation": {"x": 1560, "y": 1052, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "NoLogoutDelay": true,
+ "Map": "Ilshenar",
+ "Parent": { "Name": "Twin Oaks", "Map": "Ilshenar" },
+ "Priority": 48,
+ "Area": [{"x1": 1546, "y1": 1037, "x2": 1567, "y2": 1057}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Reg Volon",
+ "Priority": 50,
+ "GuardsDisabled": true,
+ "Area": [{"x1": 1328, "y1": 1008, "x2": 1408, "y2": 1120}],
+ "GoLocation": {"x": 1363, "y": 1055, "z": -13}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Spectre Dungeon",
+ "Priority": 2,
+ "Area": [{"x1": 1360, "y1": 1030, "x2": 1366, "y2": 1034}],
+ "GoLocation": {"x": 1363, "y": 1033, "z": -8}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1362, "y": 1031, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Spectre Dungeon",
+ "Priority": 2,
+ "Area": [{"x1": 1936, "y1": 1000, "x2": 2032, "y2": 1120}],
+ "GoLocation": {"x": 1983, "y": 1107, "z": -18}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Blood Dungeon",
+ "Priority": 2,
+ "Area": [{"x1": 1736, "y1": 1224, "x2": 1760, "y2": 1240}],
+ "GoLocation": {"x": 1747, "y": 1227, "z": -1}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1745, "y": 1236, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Blood Dungeon",
+ "Priority": 2,
+ "Area": [{"x1": 2032, "y1": 808, "x2": 2200, "y2": 1064}],
+ "GoLocation": {"x": 2114, "y": 839, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Mushroom Cave",
+ "Priority": 2,
+ "Area": [{"x1": 1448, "y1": 1320, "x2": 1464, "y2": 1336}],
+ "GoLocation": {"x": 1460, "y": 1329, "z": -25}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Mushroom Cave",
+ "Priority": 11,
+ "Area": [{"x1": 1392, "y1": 1448, "x2": 1496, "y2": 1568}],
+ "GoLocation": {"x": 1476, "y": 1494, "z": -28}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Lake Shire",
+ "Priority": 48,
+ "GuardsDisabled": true,
+ "Area": [{"x1": 1144, "y1": 1072, "x2": 1264, "y2": 1200}],
+ "GoLocation": {"x": 1212, "y": 1144, "z": -25}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Rat Cave",
+ "Priority": 2,
+ "Area": [{"x1": 1024, "y1": 1152, "x2": 1032, "y2": 1160}],
+ "GoLocation": {"x": 1031, "y": 1154, "z": -24}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Rat Cave Territory",
+ "Priority": 2,
+ "Area": [{"x1": 1144, "y1": 1440, "x2": 1368, "y2": 1584}],
+ "GoLocation": {"x": 1345, "y": 1511, "z": -3}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Ratman Cave",
+ "Priority": 2,
+ "Area": [
+ {"x1": 1264, "y1": 1448, "x2": 1360, "y2": 1576},
+ {"x1": 1152, "y1": 1456, "x2": 1256, "y2": 1560}
+ ],
+ "GoLocation": {"x": 1348, "y": 1511, "z": -3}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Bet-Lem Reg",
+ "Priority": 48,
+ "GuardsDisabled": true,
+ "Area": [{"x1": 1232, "y1": 936, "x2": 1272, "y2": 984}],
+ "GoLocation": {"x": 1238, "y": 974, "z": -34}
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Ilshenar",
+ "Name": "Mistas",
+ "Priority": 48,
+ "GuardsDisabled": true,
+ "Area": [
+ {"x1": 744, "y1": 984, "x2": 912, "y2": 1152},
+ {"x1": 744, "y1": 1152, "x2": 792, "y2": 1176}
+ ],
+ "GoLocation": {"x": 818, "y": 1073, "z": -30}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Ilshenar",
+ "Parent": { "Name": "Mistas", "Map": "Ilshenar" },
+ "Priority": 48,
+ "Area": [{"x1": 752, "y1": 1131, "x2": 768, "y2": 1152}]
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Serpentine Passage",
+ "Priority": 2,
+ "Area": [{"x1": 800, "y1": 864, "x2": 816, "y2": 880}],
+ "GoLocation": {"x": 808, "y": 872, "z": 5}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Serpentine Passage",
+ "Priority": 11,
+ "Area": [{"x1": 368, "y1": 1488, "x2": 560, "y2": 1592}],
+ "GoLocation": {"x": 533, "y": 1526, "z": -25}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 668, "y": 928, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Ankh Dungeon",
+ "Priority": 2,
+ "Area": [
+ {"x1": 0, "y1": 1248, "x2": 176, "y2": 1592},
+ {"x1": 568, "y1": 1152, "x2": 584, "y2": 1160}
+ ],
+ "GoLocation": {"x": 156, "y": 1484, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Kirin passage",
+ "Priority": 11,
+ "Area": [{"x1": 0, "y1": 800, "x2": 192, "y2": 1200}],
+ "GoLocation": {"x": 11, "y": 881, "z": -29}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Lizards Passage",
+ "Priority": 2,
+ "Area": [{"x1": 312, "y1": 1328, "x2": 320, "y2": 1336}],
+ "GoLocation": {"x": 314, "y": 1331, "z": -37}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 652, "y": 1301, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Wisp Dungeon",
+ "Priority": 2,
+ "Area": [
+ {"x1": 616, "y1": 1480, "x2": 704, "y2": 1576},
+ {"x1": 704, "y1": 1544, "x2": 728, "y2": 1576},
+ {"x1": 704, "y1": 1480, "x2": 744, "y2": 1520},
+ {"x1": 816, "y1": 1448, "x2": 912, "y2": 1584},
+ {"x1": 944, "y1": 1416, "x2": 1000, "y2": 1456},
+ {"x1": 912, "y1": 1456, "x2": 1024, "y2": 1584},
+ {"x1": 832, "y1": 1424, "x2": 880, "y2": 1448},
+ {"x1": 744, "y1": 1504, "x2": 816, "y2": 1584},
+ {"x1": 744, "y1": 1456, "x2": 800, "y2": 1504}
+ ],
+ "GoLocation": {"x": 628, "y": 1524, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Lizard Passage",
+ "Priority": 11,
+ "Area": [{"x1": 256, "y1": 1560, "x2": 336, "y2": 1592}],
+ "GoLocation": {"x": 285, "y": 1585, "z": -27}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 827, "y": 777, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Exodus Dungeon",
+ "Priority": 50,
+ "Area": [{"x1": 1832, "y1": 16, "x2": 2080, "y2": 216}],
+ "GoLocation": {"x": 1966, "y": 117, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Lizard Man's Huts",
+ "Priority": 48,
+ "Area": [{"x1": 264, "y1": 1280, "x2": 320, "y2": 1376}],
+ "GoLocation": {"x": 298, "y": 1336, "z": -24}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Nox Tereg",
+ "Priority": 50,
+ "Area": [{"x1": 344, "y1": 1112, "x2": 488, "y2": 1240}],
+ "GoLocation": {"x": 416, "y": 1176, "z": 0}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 546, "y": 455, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Sorcerer's Dungeon",
+ "Priority": 2,
+ "Area": [
+ {"x1": 368, "y1": 0, "x2": 488, "y2": 120},
+ {"x1": 200, "y1": 0, "x2": 368, "y2": 112},
+ {"x1": 256, "y1": 120, "x2": 288, "y2": 152},
+ {"x1": 48, "y1": 0, "x2": 184, "y2": 136},
+ {"x1": 224, "y1": 112, "x2": 248, "y2": 144}
+ ],
+ "GoLocation": {"x": 429, "y": 108, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Entrance Ancient Lair",
+ "Priority": 50,
+ "Area": [{"x1": 936, "y1": 488, "x2": 944, "y2": 496}],
+ "GoLocation": {"x": 940, "y": 503, "z": -30}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 938, "y": 494, "z": 0},
+ "Map": "Ilshenar",
+ "Name": "Ancient Lair",
+ "Priority": 2,
+ "Area": [{"x1": 24, "y1": 664, "x2": 136, "y2": 760}],
+ "GoLocation": {"x": 86, "y": 744, "z": -28}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp",
+ "Priority": 50,
+ "Area": [{"x1": 480, "y1": 520, "x2": 536, "y2": 568}],
+ "GoLocation": {"x": 504, "y": 536, "z": -60}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp 1",
+ "Priority": 50,
+ "Area": [{"x1": 1480, "y1": 600, "x2": 1536, "y2": 640}],
+ "GoLocation": {"x": 1508, "y": 620, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp 2",
+ "Priority": 48,
+ "Area": [{"x1": 1592, "y1": 528, "x2": 1632, "y2": 568}],
+ "GoLocation": {"x": 1612, "y": 548, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "NoLogoutDelay": true,
+ "Map": "Ilshenar",
+ "Parent": { "Name": "Gypsy Camp 2", "Map": "Ilshenar" },
+ "Priority": 48,
+ "Area": [{"x1": 1617, "y1": 546, "x2": 1629, "y2": 554}]
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Juka Camp",
+ "Priority": 50,
+ "Area": [{"x1": 1192, "y1": 656, "x2": 1304, "y2": 792}],
+ "GoLocation": {"x": 1248, "y": 724, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp 3",
+ "Priority": 50,
+ "Area": [{"x1": 928, "y1": 408, "x2": 968, "y2": 448}],
+ "GoLocation": {"x": 948, "y": 428, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp 4",
+ "Priority": 50,
+ "Area": [{"x1": 840, "y1": 440, "x2": 880, "y2": 488}],
+ "GoLocation": {"x": 860, "y": 464, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp 5",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1216, "y1": 520, "x2": 1240, "y2": 568},
+ {"x1": 1248, "y1": 568, "x2": 1264, "y2": 592}
+ ],
+ "GoLocation": {"x": 1228, "y": 544, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Gypsy Camp 6",
+ "Priority": 50,
+ "Area": [{"x1": 1376, "y1": 416, "x2": 1408, "y2": 448}],
+ "GoLocation": {"x": 1392, "y": 432, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Lord Blackthorn's Ilshenar Castle",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1048, "y1": 616, "x2": 1120, "y2": 688},
+ {"x1": 1080, "y1": 688, "x2": 1104, "y2": 712}
+ ],
+ "GoLocation": {"x": 1084, "y": 652, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Shrine of the Virtues",
+ "Priority": 50,
+ "Area": [{"x1": 1072, "y1": 376, "x2": 1136, "y2": 432}],
+ "GoLocation": {"x": 1104, "y": 404, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Pass of Karnaugh",
+ "Priority": 50,
+ "Area": [
+ {"x1": 848, "y1": 288, "x2": 968, "y2": 336},
+ {"x1": 936, "y1": 232, "x2": 968, "y2": 288},
+ {"x1": 968, "y1": 248, "x2": 1088, "y2": 304},
+ {"x1": 1000, "y1": 304, "x2": 1024, "y2": 320},
+ {"x1": 1048, "y1": 304, "x2": 1184, "y2": 360},
+ {"x1": 1184, "y1": 336, "x2": 1248, "y2": 392}
+ ],
+ "GoLocation": {"x": 908, "y": 312, "z": 0}
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Ilshenar",
+ "Name": "Vinculum Inn",
+ "Priority": 50,
+ "Area": [{"x1": 658, "y1": 654, "x2": 671, "y2": 678}],
+ "GoLocation": {"x": 656, "y": 666, "z": -36}
+ },
+ {
+ "$type": "BaseRegion",
+ "NoLogoutDelay": true,
+ "Map": "Ilshenar",
+ "Parent": { "Name": "Vinculum Inn", "Map": "Ilshenar" },
+ "Priority": 50,
+ "Area": [{"x1": 658, "y1": 654, "x2": 671, "y2": 678}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Malas",
+ "Name": "Ilse of the Divide",
+ "Priority": 50,
+ "Area": [{"x1": 1532, "y1": 857, "x2": 1832, "y2": 1057}],
+ "GoLocation": {"x": 1731, "y": 981, "z": -79}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2068, "y": 1372, "z": -75},
+ "Map": "Malas",
+ "Name": "Bedlam",
+ "Priority": 50,
+ "Area": [{"x1": 75, "y1": 1590, "x2": 210, "y2": 1760}],
+ "GoLocation": {"x": 117, "y": 1681, "z": 0},
+ "Music": "GrizzleDungeon"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1349, "y": 769, "z": 14},
+ "Map": "Malas",
+ "Name": "The Citadel",
+ "Priority": 50,
+ "Area": [{"x1": 60, "y1": 1855, "x2": 195, "y2": 1990}],
+ "GoLocation": {"x": 106, "y": 1884, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Malas",
+ "Name": "Luna",
+ "Priority": 50,
+ "Area": [{"x1": 945, "y1": 490, "x2": 1036, "y2": 551}],
+ "GoLocation": {"x": 989, "y": 520, "z": -50},
+ "Music": "Tavern04"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Malas",
+ "Parent": { "Name": "Luna", "Map": "Malas" },
+ "Priority": 50,
+ "Area": [{"x1": 986, "y1": 509, "x2": 1004, "y2": 530}]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Malas",
+ "Name": "Umbra",
+ "Priority": 50,
+ "Area": [
+ {"x1": 2042, "y1": 1265, "x2": 2090, "y2": 1278},
+ {"x1": 1960, "y1": 1278, "x2": 2106, "y2": 1413},
+ {"x1": 2004, "y1": 1413, "x2": 2040, "y2": 1419}
+ ],
+ "GoLocation": {"x": 2049, "y": 1344, "z": -85}
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Malas",
+ "Parent": { "Name": "Umbra", "Map": "Malas" },
+ "Priority": 50,
+ "Area": [{"x1": 2031, "y1": 1311, "x2": 2046, "y2": 1325}]
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 1731, "y": 981, "z": -79},
+ "Map": "Malas",
+ "Name": "Labyrinth",
+ "Priority": 50,
+ "Area": [{"x1": 256, "y1": 1795, "x2": 499, "y2": 2025}],
+ "GoLocation": {"x": 336, "y": 1970, "z": 0},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2357, "y": 1268, "z": 0},
+ "Map": "Malas",
+ "Name": "Doom",
+ "Priority": 50,
+ "Area": [{"x1": 256, "y1": 0, "x2": 512, "y2": 304}],
+ "GoLocation": {"x": 2366, "y": 1268, "z": -85},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 2357, "y": 1268, "z": 0},
+ "Map": "Malas",
+ "Name": "Doom Gauntlet",
+ "Priority": 50,
+ "Area": [{"x1": 256, "y1": 304, "x2": 512, "y2": 560}],
+ "GoLocation": {"x": 429, "y": 340, "z": -1},
+ "Music": "Dungeon9"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Malas",
+ "Name": "Orc Fortress",
+ "Priority": 50,
+ "Area": [{"x1": 1295, "y1": 1189, "x2": 1395, "y2": 1294}],
+ "GoLocation": {"x": 1340, "y": 1226, "z": -90}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Malas",
+ "Name": "Crystal Cave Entrance",
+ "Priority": 50,
+ "Area": [{"x1": 1176, "y1": 509, "x2": 1219, "y2": 522}],
+ "GoLocation": {"x": 1195, "y": 515, "z": -90}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Malas",
+ "Name": "Protected Island",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1976, "y1": 101, "x2": 2448, "y2": 345},
+ {"x1": 2051, "y1": 345, "x2": 2356, "y2": 382},
+ {"x1": 2026, "y1": 345, "x2": 2051, "y2": 370},
+ {"x1": 2069, "y1": 382, "x2": 2144, "y2": 396},
+ {"x1": 2254, "y1": 382, "x2": 2352, "y2": 420},
+ {"x1": 2222, "y1": 382, "x2": 2254, "y2": 402}
+ ],
+ "GoLocation": {"x": 2104, "y": 380, "z": -90}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Malas",
+ "Name": "Grand Arena",
+ "Priority": 50,
+ "Area": [{"x1": 919, "y1": 622, "x2": 962, "y2": 652}],
+ "GoLocation": {"x": 961, "y": 637, "z": -90}
+ },
+ {
+ "$type": "BaseRegion",
+ "NoLogoutDelay": true,
+ "Map": "Malas",
+ "Name": "Hanse's Hostel",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1049, "y1": 1420, "x2": 1062, "y2": 1445},
+ {"x1": 1062, "y1": 1420, "x2": 1065, "y2": 1431},
+ {"x1": 1062, "y1": 1439, "x2": 1065, "y2": 1445}
+ ],
+ "GoLocation": {"x": 1063, "y": 1435, "z": -90}
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 259, "y": 783, "z": 0},
+ "Map": "Malas",
+ "Name": "Yomotsu Mines",
+ "Priority": 50,
+ "Area": [{"x1": 0, "y1": 0, "x2": 129, "y2": 129}],
+ "GoLocation": {"x": 6, "y": 118, "z": 0},
+ "Music": "TokunoDungeon"
+ },
+ {
+ "$type": "DungeonRegion",
+ "Entrance": {"x": 977, "y": 223, "z": 0},
+ "Map": "Malas",
+ "Name": "Fan Dancer's Dojo",
+ "Priority": 50,
+ "Area": [{"x1": 40, "y1": 320, "x2": 210, "y2": 720}],
+ "GoLocation": {"x": 71, "y": 337, "z": 0},
+ "Music": "TokunoDungeon"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Malas",
+ "Name": "Samurai start location",
+ "Priority": 50,
+ "Area": [{"x1": 320, "y1": 690, "x2": 435, "y2": 790}],
+ "Music": "Zento"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Malas",
+ "Name": "Ninja start location",
+ "Priority": 50,
+ "Area": [{"x1": 360, "y1": 795, "x2": 440, "y2": 835}],
+ "Music": "Zento"
+ },
+ {
+ "$type": "BaseRegion",
+ "Map": "Malas",
+ "Name": "Ninja cave",
+ "Priority": 50,
+ "Area": [{"x1": 360, "y1": 960, "x2": 460, "y2": 1175}]
+ },
+ {
+ "$type": "GuardedRegion",
+ "Map": "Tokuno",
+ "Name": "Moongates",
+ "Priority": 50,
+ "Area": [
+ {"x1": 1167, "y1": 996, "x2": 1171, "y2": 1000},
+ {"x1": 799, "y1": 1201, "x2": 805, "y2": 1207},
+ {"x1": 267, "y1": 625, "x2": 274, "y2": 632}
+ ]
+ },
+ {
+ "$type": "TownRegion",
+ "Map": "Tokuno",
+ "Name": "Zento",
+ "Priority": 50,
+ "Area": [{"x1": 656, "y1": 1192, "x2": 816, "y2": 1320}],
+ "GoLocation": {"x": 736, "y": 1256, "z": 30},
+ "Music": "Zento"
+ },
+ {
+ "$type": "TownRegion",
+ "NoLogoutDelay": true,
+ "Map": "Tokuno",
+ "Parent": { "Name": "Zento", "Map": "Tokuno" },
+ "Priority": 50,
+ "Area": [{"x1": 674, "y1": 1203, "x2": 699, "y2": 1219}]
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Tokuno",
+ "Name": "Fan Dancer's Dojo",
+ "Priority": 50,
+ "Area": [{"x1": 969, "y1": 194, "x2": 992, "y2": 224}],
+ "GoLocation": {"x": 977, "y": 223, "z": 23}
+ },
+ {
+ "$type": "NoHousingRegion",
+ "Map": "Tokuno",
+ "Name": "Bushido Dojo",
+ "Priority": 50,
+ "Area": [{ "x1": 283, "y1": 361, "x2": 351, "y2": 463 }],
+ "GoLocation": { "x": 320, "y": 408, "z": 32 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Abyss",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Music": "StygianAbyss",
+ "Area": [
+ { "x1": 301, "y1": 328, "x2": 1076, "y2": 802 },
+ { "x1": 780, "y1": 32, "x2": 1076, "y2": 328 },
+ { "x1": 436, "y1": 802, "x2": 740, "y2": 980 },
+ { "x1": 754, "y1": 881, "x2": 862, "y2": 974 },
+ { "x1": 756, "y1": 1049, "x2": 860, "y2": 1142 },
+ { "x1": 756, "y1": 1214, "x2": 861, "y2": 1313 },
+ { "x1": 0, "y1": 684, "x2": 134, "y2": 860 },
+ { "x1": 0, "y1": 485, "x2": 134, "y2": 647 },
+ { "x1": 0, "y1": 286, "x2": 137, "y2": 445 },
+ { "x1": 254, "y1": 70, "x2": 500, "y2": 253 }
+ ],
+ "GoLocation": { "x": 946, "y": 72, "z": 72 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Abyssal Lair",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 931, "y1": 314, "x2": 1031, "y2": 454 }],
+ "GoLocation": { "x": 985, "y": 366, "z": -11 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Medusas Lair",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 100,
+ "Area": [
+ { "x1": 764, "y1": 894, "x2": 833, "y2": 983 },
+ { "x1": 816, "y1": 749, "x2": 829, "y2": 765 }
+ ],
+ "GoLocation": { "x": 771, "y": 928, "z": 0 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "NPC Encampment",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 100,
+ "LogoutDelay": false,
+ "GuardsDisabled": true,
+ "Area": [{ "x1": 1087, "y1": 1127, "z1": -42, "x2": 1096, "y2": 1133, "z2": 128 }],
+ "GoLocation": { "x": 1090, "y": 1130, "z": -42 },
+ "Entrance": { "x": 1090, "y": 1132 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Cavern of the Discarded",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [
+ { "x1": 887, "y1": 475, "x2": 1000, "y2": 575 },
+ { "x1": 926, "y1": 533, "x2": 971, "y2": 553 },
+ { "x1": 928, "y1": 543, "x2": 970, "y2": 573 },
+ { "x1": 929, "y1": 536, "x2": 970, "y2": 564 },
+ { "x1": 936, "y1": 559, "x2": 972, "y2": 573 },
+ { "x1": 938, "y1": 541, "x2": 958, "y2": 572 },
+ { "x1": 961, "y1": 527, "x2": 983, "y2": 559 }
+ ],
+ "GoLocation": { "x": 912, "y": 501, "z": -12 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Chamber of Virtue",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 739, "y1": 465, "x2": 760, "y2": 486 }],
+ "GoLocation": { "x": 747, "y": 474, "z": -17 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Crimson Veins",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 931, "y1": 135, "x2": 996, "y2": 200 }],
+ "GoLocation": { "x": 974, "y": 164, "z": -11 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Enslaved Goblins",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [
+ { "x1": 538, "y1": 806, "x2": 613, "y2": 856 },
+ { "x1": 539, "y1": 790, "x2": 614, "y2": 840 },
+ { "x1": 553, "y1": 791, "x2": 613, "y2": 841 },
+ { "x1": 560, "y1": 796, "x2": 581, "y2": 817 },
+ { "x1": 570, "y1": 773, "x2": 613, "y2": 857 },
+ { "x1": 571, "y1": 788, "x2": 596, "y2": 813 }
+ ],
+ "GoLocation": { "x": 581, "y": 815, "z": -45 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Fairy Dragon Lair",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 849, "y1": 254, "x2": 916, "y2": 297 }],
+ "GoLocation": { "x": 888, "y": 277, "z": 3 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Fire Temple Ruins",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [
+ { "x1": 474, "y1": 766, "x2": 563, "y2": 789 },
+ { "x1": 485, "y1": 760, "x2": 553, "y2": 789 },
+ { "x1": 495, "y1": 750, "x2": 560, "y2": 779 },
+ { "x1": 506, "y1": 750, "x2": 572, "y2": 782 },
+ { "x1": 520, "y1": 739, "x2": 584, "y2": 771 }
+ ],
+ "GoLocation": { "x": 519, "y": 765, "z": -92 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Fractured City",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [
+ { "x1": 664, "y1": 439, "x2": 731, "y2": 527 },
+ { "x1": 726, "y1": 505, "x2": 771, "y2": 527 },
+ { "x1": 712, "y1": 402, "x2": 820, "y2": 460 },
+ { "x1": 720, "y1": 504, "x2": 746, "y2": 527 },
+ { "x1": 771, "y1": 460, "x2": 810, "y2": 518 },
+ { "x1": 808, "y1": 480, "x2": 820, "y2": 512 }
+ ],
+ "GoLocation": { "x": 780, "y": 445, "z": -15 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Lands of the Lich",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [
+ { "x1": 499, "y1": 575, "x2": 570, "y2": 695 },
+ { "x1": 554, "y1": 600, "x2": 628, "y2": 642 }
+ ],
+ "GoLocation": { "x": 538, "y": 656, "z": 8 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Lava Caldera",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 553, "y1": 860, "x2": 639, "y2": 948 }],
+ "GoLocation": { "x": 587, "y": 895, "z": -73 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Passage of Tears",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 638, "y1": 530, "x2": 738, "y2": 635 }],
+ "GoLocation": { "x": 685, "y": 579, "z": -15 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Secret Garden",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 413, "y1": 678, "x2": 489, "y2": 749 }],
+ "GoLocation": { "x": 462, "y": 719, "z": 22 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Serpents Lair",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [
+ { "x1": 681, "y1": 679, "x2": 849, "y2": 790 },
+ { "x1": 703, "y1": 656, "x2": 850, "y2": 789 },
+ { "x1": 785, "y1": 640, "x2": 850, "y2": 775 }
+ ],
+ "GoLocation": { "x": 711, "y": 720, "z": -11 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Silver Sapling",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 311, "y1": 582, "x2": 379, "y2": 650 }],
+ "GoLocation": { "x": 341, "y": 619, "z": 26 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Skeletal Dragon",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 643, "y1": 809, "x2": 698, "y2": 872 }],
+ "GoLocation": { "x": 675, "y": 828, "z": -109 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Sutek the Mage",
+ "Map": "TerMur",
+ "Parent": { "Name": "Abyss", "Map": "TerMur" },
+ "Priority": 50,
+ "Area": [{ "x1": 901, "y1": 574, "x2": 954, "y2": 614 }],
+ "GoLocation": { "x": 924, "y": 595, "z": -14 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Underworld",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Music": "HumanLevel",
+ "Area": [{ "x1": 898, "y1": 808, "x2": 1280, "y2": 1231 }],
+ "GoLocation": { "x": 1128, "y": 1207, "z": -2 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Atoll Bend",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 1027, "y1": 3311, "x2": 1224, "y2": 3514 }],
+ "GoLocation": { "x": 1118, "y": 3408, "z": -42 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Chicken Chase",
+ "Map": "TerMur",
+ "Priority": 50,
+ "rune": "Chicken Chase",
+ "Area": [{ "x1": 448, "y1": 3352, "x2": 613, "y2": 3480 }],
+ "GoLocation": { "x": 560, "y": 3412, "z": 37 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Fishermans Reach",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 547, "y1": 2835, "x2": 745, "y2": 3102 }],
+ "GoLocation": { "x": 631, "y": 3035, "z": 36 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Gated Isle",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 603, "y1": 3836, "x2": 815, "y2": 4043 }],
+ "GoLocation": { "x": 703, "y": 3934, "z": -31 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "High Plain",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 748, "y1": 2843, "x2": 981, "y2": 3050 }],
+ "GoLocation": { "x": 863, "y": 2931, "z": 38 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Holy City",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Music": "Holycity",
+ "Area": [{ "x1": 922, "y1": 3838, "x2": 1071, "y2": 3965 }],
+ "GoLocation": { "x": 997, "y": 3869, "z": -42 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Kepetch Waste",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 356, "y1": 3143, "x2": 523, "y2": 3224 }],
+ "GoLocation": { "x": 447, "y": 3188, "z": 20 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Lost Settlement",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 454, "y1": 3708, "x2": 648, "y2": 3957 }],
+ "GoLocation": { "x": 526, "y": 3822, "z": -44 }
+ },
+ {
+ "$type": "GuardedRegion",
+ "Name": "Moongates",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [
+ { "x1": 852, "y1": 3525, "x2": 867, "y2": 3540 },
+ { "x1": 925, "y1": 3988, "x2": 940, "y2": 4003 }
+ ]
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Northern Steppes",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 694, "y1": 3020, "x2": 954, "y2": 3148 }],
+ "GoLocation": { "x": 822, "y": 3063, "z": 61 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Raptor Island",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [
+ { "x1": 712, "y1": 3765, "x2": 879, "y2": 3829 },
+ { "x1": 728, "y1": 3809, "x2": 839, "y2": 3923 },
+ { "x1": 769, "y1": 3721, "x2": 972, "y2": 3768 },
+ { "x1": 808, "y1": 3692, "x2": 930, "y2": 3732 }
+ ],
+ "GoLocation": { "x": 816, "y": 3778, "z": -42 }
+ },
+ {
+ "$type": "TownRegion",
+ "Name": "Royal City",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Music": "RoyalCity",
+ "Area": [{ "x1": 624, "y1": 3296, "x2": 927, "y2": 3583 }],
+ "GoLocation": { "x": 750, "y": 3440, "z": -20 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Queen's Palace",
+ "Map": "TerMur",
+ "Parent": { "Name": "Royal City", "Map": "TerMur" },
+ "Music": "QueenPalace",
+ "Area": [{ "x1": 717, "y1": 3339, "x2": 785, "y2": 3412 }],
+ "GoLocation": { "x": 748, "y": 3357, "z": 55 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Royal City Inn",
+ "Map": "TerMur",
+ "Parent": { "Name": "Royal City", "Map": "TerMur" },
+ "LogoutDelay": false,
+ "Area": [
+ { "x1": 724, "y1": 3463, "x2": 761, "y2": 3483 },
+ { "x1": 747, "y1": 3480, "x2": 760, "y2": 3493 }
+ ]
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Royal Park",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [
+ { "x1": 632, "y1": 3233, "x2": 808, "y2": 3268 },
+ { "x1": 753, "y1": 3161, "x2": 990, "y2": 3292 }
+ ],
+ "GoLocation": { "x": 711, "y": 3255, "z": -42 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Slith Valley",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 1028, "y1": 3263, "x2": 1221, "y2": 3404 }],
+ "GoLocation": { "x": 1078, "y": 3331, "z": -42 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Spider Island",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 1063, "y1": 3695, "x2": 1181, "y2": 3779 }],
+ "GoLocation": { "x": 1115, "y": 3730, "z": -42 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Stygian Dragon Lair",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Music": "StygianDragon",
+ "Area": [{ "x1": 258, "y1": 90, "x2": 489, "y2": 245 }],
+ "GoLocation": { "x": 367, "y": 155, "z": 0 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Talon Point",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [
+ { "x1": 632, "y1": 3830, "x2": 730, "y2": 3885 },
+ { "x1": 629, "y1": 3786, "x2": 705, "y2": 3826 },
+ { "x1": 656, "y1": 3750, "x2": 707, "y2": 3791 }
+ ],
+ "GoLocation": { "x": 676, "y": 3831, "z": -39 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Toxic Desert",
+ "Map": "TerMur",
+ "Priority": 50,
+ "rune": "Toxic Desert",
+ "Area": [{ "x1": 1010, "y1": 2929, "z1": 37, "x2": 1156, "y2": 3049, "z2": 128 }],
+ "GoLocation": { "x": 1047, "y": 2980, "z": 62 },
+ "Entrance": { "x": 1051, "y": 3022 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Void Island",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 314, "y1": 3473, "x2": 581, "y2": 3699 }],
+ "GoLocation": { "x": 440, "y": 3577, "z": 38 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Volcano",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 298, "y1": 2895, "x2": 499, "y2": 3117 }],
+ "GoLocation": { "x": 407, "y": 3010, "z": -24 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Walled Circus",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 291, "y1": 3207, "x2": 445, "y2": 3354 }],
+ "GoLocation": { "x": 370, "y": 3273, "z": 0 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Waterfall Point",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 635, "y1": 2862, "x2": 731, "y2": 2926 }],
+ "GoLocation": { "x": 661, "y": 2894, "z": 39 }
+ },
+ {
+ "$type": "BaseRegion",
+ "Name": "Shrine of Singularity",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Music": "CodexShrine",
+ "Area": [{ "x1": 978, "y1": 3786, "x2": 1018, "y2": 3838 }],
+ "GoLocation": { "x": 995, "y": 3806, "z": 0 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Great Ape Lair",
+ "Map": "TerMur",
+ "Priority": 100,
+ "Area": [{ "x1": 832, "y1": 1363, "z1": -25, "x2": 938, "y2": 1474, "z2": 128 }],
+ "GoLocation": { "x": 926, "y": 1464, "z": 0 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Zipactriotl Lair",
+ "Map": "TerMur",
+ "Priority": 100,
+ "Area": [{ "x1": 831, "y1": 2239, "z1": -25, "x2": 959, "y2": 2367, "z2": 128 }],
+ "GoLocation": { "x": 896, "y": 2304, "z": -19 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Myrmidex Queen Lair",
+ "Map": "TerMur",
+ "Priority": 100,
+ "Area": [{ "x1": 704, "y1": 2248, "z1": -25, "x2": 828, "y2": 2363, "z2": 128 }],
+ "GoLocation": { "x": 766, "y": 2306, "z": 0 }
+ },
+ {
+ "$type": "DungeonRegion",
+ "Name": "Kotl City",
+ "Map": "TerMur",
+ "Priority": 50,
+ "Area": [{ "x1": 435, "y1": 2270, "z1": -25, "x2": 675, "y2": 2490, "z2": 128 }],
+ "GoLocation": { "x": 542, "y": 2473, "z": 0 }
+ }
+]
diff --git a/src/Prima.Server/Handlers/CharacterHandler.cs b/src/Prima.Server/Handlers/CharacterHandler.cs
index 1a7ec55..2ef1597 100644
--- a/src/Prima.Server/Handlers/CharacterHandler.cs
+++ b/src/Prima.Server/Handlers/CharacterHandler.cs
@@ -9,6 +9,7 @@
using Prima.UOData.Data.EventData;
using Prima.UOData.Entities;
using Prima.UOData.Entities.Db;
+using Prima.UOData.Events.Login;
using Prima.UOData.Id;
using Prima.UOData.Interfaces.Services;
using Prima.UOData.Packets;
@@ -59,6 +60,7 @@ public async Task OnPacketReceived(NetworkSession session, CharacterCreation pac
playerMobile.Name = packet.Name;
+
_worldManagerService.AddWorldEntity(playerMobile);
await _databaseService.InsertAsync(characterEntity);
@@ -66,6 +68,8 @@ public async Task OnPacketReceived(NetworkSession session, CharacterCreation pac
TriggerCharacterCreatedEvent(packet);
await session.SendPacketAsync(new ClientVersionReq());
+
+ await PublishEvent(new LoginCompleteEvent(session.Id));
}
private void TriggerCharacterCreatedEvent(CharacterCreation packet)
@@ -102,11 +106,13 @@ public async Task OnPacketReceived(NetworkSession session, CharacterLogin packet
// TODO: Check if character exists
- session.SetProperty(character.MobileId, "mobileId");
-
var mobile = _worldManagerService.GetEntityBySerial(character.MobileId);
+ session.SetProperty(mobile);
+
await session.SendPacketAsync(new ClientVersionReq());
+
+ await PublishEvent(new LoginCompleteEvent(session.Id));
}
public async Task OnPacketReceived(NetworkSession session, CharacterDelete packet)
diff --git a/src/Prima.Server/Handlers/LoginCompleteHandler.cs b/src/Prima.Server/Handlers/LoginCompleteHandler.cs
new file mode 100644
index 0000000..9152e41
--- /dev/null
+++ b/src/Prima.Server/Handlers/LoginCompleteHandler.cs
@@ -0,0 +1,45 @@
+using Orion.Core.Server.Listeners.EventBus;
+using Prima.Core.Server.Handlers.Base;
+using Prima.Core.Server.Interfaces.Services;
+using Prima.Network.Packets;
+using Prima.Network.Types;
+using Prima.UOData.Entities;
+using Prima.UOData.Events.Login;
+using Prima.UOData.Packets;
+using Prima.UOData.Types;
+
+namespace Prima.Server.Handlers;
+
+public class LoginCompleteHandler : BasePacketListenerHandler, IEventBusListener
+{
+ public LoginCompleteHandler(
+ ILogger logger, INetworkService networkService, IServiceProvider serviceProvider
+ ) : base(logger, networkService, serviceProvider)
+ {
+ }
+
+
+ protected override void RegisterHandlers()
+ {
+ SubscribeEvent(this);
+ }
+
+ public async Task HandleAsync(LoginCompleteEvent @event, CancellationToken cancellationToken = default)
+ {
+ var session = SessionService.GetSession(@event.SessionId);
+ var mobile = session.GetProperty();
+
+ // Login confirmation packet
+ await session.SendPacketAsync(new CharLocaleAndBody(mobile));
+ // GeneralInformation packet
+ await session.SendPacketAsync(new SeasonalInformation(Season.Spring, true));
+ await session.SendPacketAsync(new DrawGamePlayer(mobile));
+ await session.SendPacketAsync(new CharacterDraw(mobile));
+
+ await session.SendPacketAsync(new GlobalLightLevel(0xFF));
+ await session.SendPacketAsync(new PersonalLightLevel(mobile, 0xFF));
+ await session.SendPacketAsync(new FeatureFlagsResponse(FeatureFlags.UOR | FeatureFlags.AOS));
+ await session.SendPacketAsync(new CharacterWarMode(false));
+ await session.SendPacketAsync(new LoginComplete());
+ }
+}
diff --git a/src/Prima.UOData/Context/UOContext.cs b/src/Prima.UOData/Context/UOContext.cs
index 8092946..a8fe161 100644
--- a/src/Prima.UOData/Context/UOContext.cs
+++ b/src/Prima.UOData/Context/UOContext.cs
@@ -1,7 +1,10 @@
using System.Runtime.CompilerServices;
+using Microsoft.Extensions.DependencyInjection;
+using Prima.Core.Server.Data;
using Prima.Core.Server.Data.Uo;
using Prima.Core.Server.Types.Uo;
using Prima.UOData.Data;
+using Prima.UOData.Interfaces.Services;
using Prima.UOData.Types;
namespace Prima.UOData.Context;
@@ -16,6 +19,9 @@ public static class UOContext
public static ExpansionInfo ExpansionInfo { get; set; }
+ public static IWorldManagerService WorldManagerService =>
+ PrimaServerContext.ServiceProvider.GetRequiredService();
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasProtocolChanges(ProtocolChanges changes) => (ClientVersion.ProtocolChanges & changes) != 0;
diff --git a/src/Prima.UOData/Data/Tiles/LandTile.cs b/src/Prima.UOData/Data/Tiles/LandTile.cs
new file mode 100644
index 0000000..9d5fa2e
--- /dev/null
+++ b/src/Prima.UOData/Data/Tiles/LandTile.cs
@@ -0,0 +1,34 @@
+using System.Runtime.InteropServices;
+
+namespace Prima.UOData.Data.Tiles;
+
+[StructLayout(LayoutKind.Sequential, Pack = 1)]
+public struct LandTile
+{
+ internal short m_ID;
+ internal sbyte m_Z;
+
+ public int ID => m_ID;
+
+ public int Z
+ {
+ get => m_Z;
+ set => m_Z = (sbyte)value;
+ }
+
+ public int Height => 0;
+
+ public bool Ignored => m_ID is 2 or 0x1DB or >= 0x1AE and <= 0x1B5;
+
+ public LandTile(short id, sbyte z)
+ {
+ m_ID = id;
+ m_Z = z;
+ }
+
+ public void Set(short id, sbyte z)
+ {
+ m_ID = id;
+ m_Z = z;
+ }
+}
diff --git a/src/Prima.UOData/Data/Tiles/TileMatrix.cs b/src/Prima.UOData/Data/Tiles/TileMatrix.cs
new file mode 100644
index 0000000..b71d1ae
--- /dev/null
+++ b/src/Prima.UOData/Data/Tiles/TileMatrix.cs
@@ -0,0 +1,467 @@
+using System.Runtime.CompilerServices;
+using Prima.Core.Server.Data.Uo;
+using Prima.UOData.Context;
+using Prima.UOData.Data.Geometry;
+using Prima.UOData.Mul;
+using Serilog;
+
+namespace Prima.UOData.Data.Tiles;
+
+public class TileMatrix
+{
+ public const int SectorShift = 3;
+
+ private static readonly ILogger logger = Log.ForContext();
+ private static readonly List _instances = new();
+
+ private readonly StaticTile[][][][][] _staticTiles;
+ private readonly LandTile[][][] _landTiles;
+ private readonly LandTile[] _invalidLandBlock;
+ private readonly StaticTile[][][] _emptyStaticBlock;
+ private readonly UOPEntry[] _uopMapEntries;
+
+ private readonly int _fileIndex;
+
+ //private readonly Map _map;
+ private readonly int[][] _staticPatches;
+ private readonly int[][] _landPatches;
+ private readonly List _fileShare = new();
+
+ public TileMatrixPatch Patch { get; }
+ public int BlockWidth { get; }
+ public int BlockHeight { get; }
+ public FileStream MapStream { get; }
+ public FileStream IndexStream { get; }
+ public FileStream DataStream { get; }
+ public BinaryReader IndexReader { get; }
+
+ public static bool Pre6000ClientSupport { get; private set; }
+
+ public static void Configure()
+ {
+ // Set to true to support < 6.0.0 clients where map0.mul is both Felucca & Trammel
+ var isPre6000Trammel = UOContext.ClientVersion != null && UOContext.ClientVersion < ClientVersion.Version6000;
+ Pre6000ClientSupport =
+ isPre6000Trammel; //ServerConfiguration.GetSetting("maps.enablePre6000Trammel", isPre6000Trammel);
+ }
+
+// public TileMatrix(Map owner, int fileIndex, int mapID, int width, int height)
+
+ public TileMatrix(int fileIndex, int mapID, int width, int height)
+ {
+ lock (_instances)
+ {
+ for (var i = 0; i < _instances.Count; ++i)
+ {
+ var tm = _instances[i];
+
+ if (tm._fileIndex == fileIndex)
+ {
+ lock (_fileShare)
+ {
+ lock (tm._fileShare)
+ {
+ tm._fileShare.Add(this);
+ _fileShare.Add(tm);
+ }
+ }
+ }
+ }
+
+ _instances.Add(this);
+ }
+
+ _fileIndex = fileIndex;
+ BlockWidth = width >> SectorShift;
+ BlockHeight = height >> SectorShift;
+
+ // _map = owner;
+
+ if (fileIndex != 0x7F)
+ {
+ var mapFileIndex = Pre6000ClientSupport && mapID == 1 ? 0 : fileIndex;
+
+ var mapPath = UoFiles.FindDataFile($"map{mapFileIndex}.mul", false);
+
+ if (mapPath != null)
+ {
+ MapStream = new FileStream(mapPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ }
+ else
+ {
+ mapPath = UoFiles.FindDataFile($"map{mapFileIndex}LegacyMUL.uop", false);
+
+ if (mapPath != null)
+ {
+ MapStream = new FileStream(mapPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+
+ var uopEntries = UOPFiles.ReadUOPIndexes(MapStream, ".dat", 0x14000, 5);
+
+ _uopMapEntries = GC.AllocateUninitializedArray(uopEntries.Count);
+ uopEntries.Values.CopyTo(_uopMapEntries, 0);
+
+ ConvertToMapEntries(MapStream);
+ }
+ else
+ {
+ logger.Warning("{File} was not found.", $"map{mapFileIndex}.mul");
+ }
+ }
+
+ var indexPath = UoFiles.FindDataFile($"staidx{mapFileIndex}.mul", false);
+
+ if (indexPath != null)
+ {
+ IndexStream = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ IndexReader = new BinaryReader(IndexStream);
+ }
+ else
+ {
+ logger.Warning("{File} was not found.", $"staidx{mapFileIndex}.mul");
+ }
+
+ var staticsPath = UoFiles.FindDataFile($"statics{mapFileIndex}.mul", false);
+
+ if (staticsPath != null)
+ {
+ DataStream = new FileStream(staticsPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ }
+ else
+ {
+ logger.Warning("{File} was not found.", $"statics{fileIndex}.mul");
+ }
+ }
+
+ _emptyStaticBlock = new StaticTile[8][][];
+
+ for (var i = 0; i < 8; ++i)
+ {
+ _emptyStaticBlock[i] = new StaticTile[8][];
+
+ for (var j = 0; j < 8; ++j)
+ {
+ _emptyStaticBlock[i][j] = new StaticTile[0];
+ }
+ }
+
+ _invalidLandBlock = new LandTile[196];
+
+ _landTiles = new LandTile[BlockWidth][][];
+ _staticTiles = new StaticTile[BlockWidth][][][][];
+ _staticPatches = new int[BlockWidth][];
+ _landPatches = new int[BlockWidth][];
+
+ Patch = new TileMatrixPatch(this, fileIndex);
+ }
+
+ public StaticTile[][][] EmptyStaticBlock => _emptyStaticBlock;
+
+ public void SetStaticBlock(int x, int y, StaticTile[][][] value)
+ {
+ if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight)
+ {
+ return;
+ }
+
+ _staticTiles[x] ??= new StaticTile[BlockHeight][][][];
+ _staticTiles[x][y] = value;
+
+ _staticPatches[x] ??= new int[(BlockHeight + 31) >> 5];
+ _staticPatches[x][y >> 5] |= 1 << (y & 0x1F);
+ }
+
+ public StaticTile[][][] GetStaticBlock(int x, int y)
+ {
+ if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight || DataStream == null || IndexStream == null)
+ {
+ return _emptyStaticBlock;
+ }
+
+ _staticTiles[x] ??= new StaticTile[BlockHeight][][][];
+
+ var tiles = _staticTiles[x][y];
+
+ if (tiles == null)
+ {
+ for (var i = 0; tiles == null && i < _fileShare.Count; ++i)
+ {
+ var shared = _fileShare[i];
+
+ lock (shared)
+ {
+ if (x < shared.BlockWidth && y < shared.BlockHeight)
+ {
+ var theirTiles = shared._staticTiles[x];
+
+ if (theirTiles != null)
+ {
+ tiles = theirTiles[y];
+ }
+
+ if (tiles != null)
+ {
+ var theirBits = shared._staticPatches[x];
+
+ if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0)
+ {
+ tiles = null;
+ }
+ }
+ }
+ }
+ }
+
+ tiles ??= ReadStaticBlock(x, y);
+
+ _staticTiles[x][y] = tiles;
+ }
+
+ return tiles;
+ }
+
+ // [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ // public Map.StaticTileEnumerable GetStaticTiles(int x, int y) => new(_map, new Point2D(x, y), includeMultis: false);
+ //
+ // [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ // public Map.StaticTileEnumerable GetStaticAndMultiTiles(int x, int y) => new(_map, new Point2D(x, y));
+ //
+ // [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ // public Map.StaticTileEnumerable GetMultiTiles(int x, int y) => new(_map, new Point2D(x, y), false);
+
+ public void SetLandBlock(int x, int y, LandTile[] value)
+ {
+ if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight)
+ {
+ return;
+ }
+
+ _landTiles[x] ??= new LandTile[BlockHeight][];
+ _landTiles[x][y] = value;
+
+ _landPatches[x] ??= new int[(BlockHeight + 31) >> 5];
+ _landPatches[x][y >> 5] |= 1 << (y & 0x1F);
+ }
+
+ public LandTile[] GetLandBlock(int x, int y)
+ {
+ if (x < 0 || y < 0 || x >= BlockWidth || y >= BlockHeight || MapStream == null)
+ {
+ return _invalidLandBlock;
+ }
+
+ _landTiles[x] ??= new LandTile[BlockHeight][];
+
+ var tiles = _landTiles[x][y];
+
+ if (tiles != null)
+ {
+ return tiles;
+ }
+
+ for (var i = 0; tiles == null && i < _fileShare.Count; ++i)
+ {
+ var shared = _fileShare[i];
+
+ if (x < shared.BlockWidth && y < shared.BlockHeight)
+ {
+ var theirTiles = shared._landTiles[x];
+
+ if (theirTiles != null)
+ {
+ tiles = theirTiles[y];
+ }
+
+ if (tiles != null)
+ {
+ var theirBits = shared._landPatches[x];
+
+ if (theirBits != null && (theirBits[y >> 5] & (1 << (y & 0x1F))) != 0)
+ {
+ tiles = null;
+ }
+ }
+ }
+ }
+
+ tiles ??= ReadLandBlock(x, y);
+
+ _landTiles[x][y] = tiles;
+
+ return tiles;
+ }
+
+ public LandTile GetLandTile(int x, int y)
+ {
+ var tiles = GetLandBlock(x >> SectorShift, y >> SectorShift);
+
+ return tiles[((y & 0x7) << 3) + (x & 0x7)];
+ }
+
+ private TileList[][] m_Lists;
+
+ private StaticTile[] m_TileBuffer = new StaticTile[128];
+
+ private unsafe StaticTile[][][] ReadStaticBlock(int x, int y)
+ {
+ try
+ {
+ IndexReader.BaseStream.Seek((x * BlockHeight + y) * 12, SeekOrigin.Begin);
+
+ var lookup = IndexReader.ReadInt32();
+ var length = IndexReader.ReadInt32();
+
+ if (lookup < 0 || length <= 0)
+ {
+ return _emptyStaticBlock;
+ }
+
+ var count = length / 7;
+
+ DataStream.Seek(lookup, SeekOrigin.Begin);
+
+ if (m_TileBuffer.Length < count)
+ {
+ m_TileBuffer = new StaticTile[count];
+ }
+
+ var staTiles = m_TileBuffer;
+
+ fixed (StaticTile* pTiles = staTiles)
+ {
+ _ = DataStream.Read(new Span(pTiles, length));
+
+ if (m_Lists == null)
+ {
+ m_Lists = new TileList[8][];
+
+ for (var i = 0; i < 8; ++i)
+ {
+ m_Lists[i] = new TileList[8];
+
+ for (var j = 0; j < 8; ++j)
+ {
+ m_Lists[i][j] = new TileList();
+ }
+ }
+ }
+
+ var lists = m_Lists;
+
+ StaticTile* pCur = pTiles, pEnd = pTiles + count;
+
+ while (pCur < pEnd)
+ {
+ lists[pCur->m_X & 0x7][pCur->m_Y & 0x7].Add(pCur);
+
+ pCur = pCur + 1;
+ }
+
+ var tiles = new StaticTile[8][][];
+
+ for (var i = 0; i < 8; ++i)
+ {
+ tiles[i] = new StaticTile[8][];
+
+ for (var j = 0; j < 8; ++j)
+ {
+ tiles[i][j] = lists[i][j].ToArray();
+ }
+ }
+
+ return tiles;
+ }
+ }
+ catch (EndOfStreamException ex)
+ {
+ if (DateTime.Now >= m_NextStaticWarning)
+ {
+ // logger.Warning("Warning: Static EOS for {0} ({1}, {2})", _map, x, y);
+ m_NextStaticWarning = DateTime.Now + TimeSpan.FromMinutes(1.0);
+ }
+
+ return _emptyStaticBlock;
+ }
+ }
+
+ private DateTime m_NextStaticWarning;
+ private DateTime m_NextLandWarning;
+
+
+ private unsafe LandTile[] ReadLandBlock(int x, int y)
+ {
+ try
+ {
+ long offset = (x * BlockHeight + y) * 196 + 4;
+
+ if (_uopMapEntries != null)
+ {
+ offset = FindOffset(offset);
+ }
+
+ MapStream.Seek(offset, SeekOrigin.Begin);
+
+ var tiles = new LandTile[64];
+
+ fixed (LandTile* pTiles = tiles)
+ {
+ _ = MapStream.Read(new Span(pTiles, 192));
+ }
+
+ return tiles;
+ }
+ catch (Exception ex)
+ {
+ if (DateTime.Now >= m_NextLandWarning)
+ {
+ // logger.Warning("Warning: Land EOS for {0} ({1}, {2})", _map, x, y);
+ m_NextLandWarning = DateTime.Now + TimeSpan.FromMinutes(1.0);
+ }
+
+ return _invalidLandBlock;
+ }
+ }
+
+ public long FindOffset(long offset)
+ {
+ var total = 0;
+
+ for (var i = 0; i < _uopMapEntries.Length; ++i)
+ {
+ var entry = _uopMapEntries[i];
+ var newTotal = total + entry.Size;
+
+ if (offset < newTotal)
+ {
+ return entry.Offset + (offset - total);
+ }
+
+ total = newTotal;
+ }
+
+ return -1;
+ }
+
+ private void ConvertToMapEntries(FileStream stream)
+ {
+ // Sorting by offset to make seeking faster
+ Array.Sort(_uopMapEntries, (a, b) => a.Offset.CompareTo(b.Offset));
+
+ var reader = new BinaryReader(stream);
+
+ for (var i = 0; i < _uopMapEntries.Length; ++i)
+ {
+ var entry = _uopMapEntries[i];
+ stream.Seek(entry.Offset, SeekOrigin.Begin);
+ _uopMapEntries[i].Extra = reader.ReadInt32(); // order
+ }
+
+ Array.Sort(_uopMapEntries, (a, b) => a.Extra.CompareTo(b.Extra));
+ }
+
+ public void Dispose()
+ {
+ MapStream?.Close();
+ DataStream?.Close();
+ IndexReader?.Close();
+ }
+}
diff --git a/src/Prima.UOData/Data/Tiles/TileMatrixPatch.cs b/src/Prima.UOData/Data/Tiles/TileMatrixPatch.cs
new file mode 100644
index 0000000..16c6b17
--- /dev/null
+++ b/src/Prima.UOData/Data/Tiles/TileMatrixPatch.cs
@@ -0,0 +1,162 @@
+using Prima.Core.Server.Data.Uo;
+using Prima.UOData.Context;
+using Prima.UOData.Mul;
+using Prima.UOData.Types;
+
+namespace Prima.UOData.Data.Tiles;
+
+public class TileMatrixPatch
+{
+ private StaticTile[] _tileBuffer = new StaticTile[128];
+
+ public static bool PatchLandEnabled { get; private set; }
+ public static bool PatchStaticsEnabled { get; private set; }
+
+ public int LandBlocks { get; }
+ public int StaticBlocks { get; }
+
+ public TileMatrixPatch(TileMatrix matrix, int index)
+ {
+ if (PatchLandEnabled)
+ {
+ var mapDataPath = UoFiles.FindDataFile($"mapdif{index}.mul", false);
+ var mapIndexPath = UoFiles.FindDataFile($"mapdifl{index}.mul", false);
+
+ if (mapDataPath != null && mapIndexPath != null)
+ {
+ LandBlocks = PatchLand(matrix, mapDataPath, mapIndexPath);
+ }
+ }
+
+ if (PatchStaticsEnabled)
+ {
+ var staDataPath = UoFiles.FindDataFile($"stadif{index}.mul", false);
+ var staIndexPath = UoFiles.FindDataFile($"stadifl{index}.mul", false);
+ var staLookupPath = UoFiles.FindDataFile($"stadifi{index}.mul", false);
+
+ if (staDataPath != null && staIndexPath != null && staLookupPath != null)
+ {
+ StaticBlocks = PatchStatics(matrix, staDataPath, staIndexPath, staLookupPath);
+ }
+ }
+ }
+
+ public static void Configure()
+ {
+ if (UOContext.ClientVersion != null)
+ {
+ PatchLandEnabled =
+ UOContext.ClientVersion < ClientVersion.Version6000;
+
+ // TODO: Should this be enabled for 6.0 through <7.0.9?
+ PatchStaticsEnabled = UOContext.ClientVersion < ClientVersion.Version6000;
+ }
+ }
+
+ private unsafe int PatchLand(TileMatrix matrix, string dataPath, string indexPath)
+ {
+ using var fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var fsIndex = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var indexReader = new BinaryReader(fsIndex);
+
+ var count = (int)(indexReader.BaseStream.Length / 4);
+
+ for (var i = 0; i < count; i++)
+ {
+ var blockID = indexReader.ReadInt32();
+ var x = Math.DivRem(blockID, matrix.BlockHeight, out var y);
+
+ fsData.Seek(4, SeekOrigin.Current);
+
+ var tiles = new LandTile[64];
+ fixed (LandTile* pTiles = tiles)
+ {
+ _ = fsData.Read(new Span(pTiles, 192));
+ }
+
+ matrix.SetLandBlock(x, y, tiles);
+ }
+
+ return count;
+ }
+
+ private unsafe int PatchStatics(TileMatrix matrix, string dataPath, string indexPath, string lookupPath)
+ {
+ using var fsData = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var fsIndex = new FileStream(indexPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var fsLookup = new FileStream(lookupPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ using var indexReader = new BinaryReader(fsIndex);
+ using var lookupReader = new BinaryReader(fsLookup);
+
+ var count = (int)(indexReader.BaseStream.Length / 4);
+
+ var lists = new TileList[8][];
+
+ for (var x = 0; x < 8; ++x)
+ {
+ lists[x] = new TileList[8];
+
+ for (var y = 0; y < 8; ++y)
+ {
+ lists[x][y] = new TileList();
+ }
+ }
+
+ for (var i = 0; i < count; ++i)
+ {
+ var blockID = indexReader.ReadInt32();
+ var blockX = blockID / matrix.BlockHeight;
+ var blockY = blockID % matrix.BlockHeight;
+
+ var offset = lookupReader.ReadInt32();
+ var length = lookupReader.ReadInt32();
+ lookupReader.ReadInt32(); // Extra
+
+ if (offset < 0 || length <= 0)
+ {
+ matrix.SetStaticBlock(blockX, blockY, matrix.EmptyStaticBlock);
+ continue;
+ }
+
+ fsData.Seek(offset, SeekOrigin.Begin);
+
+ var tileCount = length / 7;
+
+ if (_tileBuffer.Length < tileCount)
+ {
+ _tileBuffer = new StaticTile[tileCount];
+ }
+
+ var staTiles = _tileBuffer;
+
+ fixed (StaticTile* pTiles = staTiles)
+ {
+ _ = fsData.Read(new Span(pTiles, length));
+
+ StaticTile* pCur = pTiles, pEnd = pTiles + tileCount;
+
+ while (pCur < pEnd)
+ {
+ lists[pCur->m_X & 0x7][pCur->m_Y & 0x7].Add(pCur);
+ pCur += 1;
+ }
+
+ var tiles = new StaticTile[8][][];
+
+ for (var x = 0; x < 8; ++x)
+ {
+ tiles[x] = new StaticTile[8][];
+
+ for (var y = 0; y < 8; ++y)
+ {
+ tiles[x][y] = lists[x][y].ToArray();
+ }
+ }
+
+ matrix.SetStaticBlock(blockX, blockY, tiles);
+ }
+ }
+
+ return count;
+ }
+}
diff --git a/src/Prima.UOData/Entities/ItemEntity.cs b/src/Prima.UOData/Entities/ItemEntity.cs
index f88b3d3..d1f20d9 100644
--- a/src/Prima.UOData/Entities/ItemEntity.cs
+++ b/src/Prima.UOData/Entities/ItemEntity.cs
@@ -9,6 +9,8 @@ namespace Prima.UOData.Entities;
[SerializableHeader(0x02)]
public class ItemEntity : BaseWorldEntity
{
+ public short ModelId { get; set; }
+
public string Name { get; set; }
public int Hue { get; set; }
diff --git a/src/Prima.UOData/Entities/MobileEntity.cs b/src/Prima.UOData/Entities/MobileEntity.cs
index 1044878..9cd6913 100644
--- a/src/Prima.UOData/Entities/MobileEntity.cs
+++ b/src/Prima.UOData/Entities/MobileEntity.cs
@@ -1,5 +1,6 @@
using MessagePack;
using Prima.Core.Server.Attributes;
+using Prima.Core.Server.Data.Session;
using Prima.Core.Server.Types;
using Prima.UOData.Data.Geometry;
using Prima.UOData.Entities.Base;
@@ -11,22 +12,57 @@ namespace Prima.UOData.Entities;
[SerializableHeader(0x01)]
public class MobileEntity : BaseWorldEntity
{
+ public Serial ModelId { get; set; }
public string Name { get; set; }
+ public string Title { get; set; }
+
+ public CharacterStatus StatusFlag { get; set; } = CharacterStatus.Normal;
+
+ public NetworkSession? NetworkSession { get; set; }
public bool IsPlayer { get; set; }
+ public bool IsRunning { get; set; }
+
public CommandPermissionType AccessLevel { get; set; }
+ public Notoriety Notoriety { get; set; } = Notoriety.Friend;
+
public int Hue { get; set; }
public Point3D Position { get; set; }
-
public Direction Direction { get; set; }
+ public Dictionary Items { get; set; } = new();
+
public MobileEntity()
{
}
+ public void MoveForward(int distance)
+ {
+ var x = Position.X;
+ var y = Position.Y;
+
+ switch (Direction)
+ {
+ case Direction.North:
+ y -= distance;
+ break;
+ case Direction.East:
+ x += distance;
+ break;
+ case Direction.South:
+ y += distance;
+ break;
+ case Direction.West:
+ x -= distance;
+ break;
+ }
+
+ Position = new Point3D(x, y, Position.Z);
+ }
+
public MobileEntity(Serial serial)
{
Id = serial;
diff --git a/src/Prima.UOData/Events/Login/LoginCompleteEvent.cs b/src/Prima.UOData/Events/Login/LoginCompleteEvent.cs
new file mode 100644
index 0000000..e420353
--- /dev/null
+++ b/src/Prima.UOData/Events/Login/LoginCompleteEvent.cs
@@ -0,0 +1,3 @@
+namespace Prima.UOData.Events.Login;
+
+public record LoginCompleteEvent(string SessionId);
diff --git a/src/Prima.UOData/Extensions/SpanExtensions.cs b/src/Prima.UOData/Extensions/SpanExtensions.cs
new file mode 100644
index 0000000..3dba314
--- /dev/null
+++ b/src/Prima.UOData/Extensions/SpanExtensions.cs
@@ -0,0 +1,12 @@
+using Orion.Foundations.Spans;
+using Prima.UOData.Id;
+
+namespace Prima.UOData.Extensions;
+
+public static class SpanExtensions
+{
+ public static void Write(this SpanWriter writer, Serial serial)
+ {
+ writer.Write((uint)serial);
+ }
+}
diff --git a/src/Prima.UOData/Extensions/StreamWriterExtension.cs b/src/Prima.UOData/Extensions/StreamWriterExtension.cs
index 99cbc96..94236b4 100644
--- a/src/Prima.UOData/Extensions/StreamWriterExtension.cs
+++ b/src/Prima.UOData/Extensions/StreamWriterExtension.cs
@@ -82,6 +82,7 @@ public static Direction ReadDirection(this BinaryReader reader)
}
+
public static void Write(this BinaryWriter writer, IHaveSerial serial)
{
writer.Write(serial.Id.Value);
diff --git a/src/Prima.UOData/Js/Items/JSItemObject.cs b/src/Prima.UOData/Js/Items/JSItemObject.cs
index fb1a0b3..09d2080 100644
--- a/src/Prima.UOData/Js/Items/JSItemObject.cs
+++ b/src/Prima.UOData/Js/Items/JSItemObject.cs
@@ -1,3 +1,5 @@
+using Prima.UOData.Types;
+
namespace Prima.UOData.Js.Items;
public class JSItemObject
@@ -10,7 +12,7 @@ public class JSItemObject
public double Weight { get; set; }
- public string Layer { get; set; }
+ public Layer Layer { get; set; }
public int Amount { get; set; }
diff --git a/src/Prima.UOData/Mul/UoFiles.cs b/src/Prima.UOData/Mul/UoFiles.cs
index 838c870..45e7505 100644
--- a/src/Prima.UOData/Mul/UoFiles.cs
+++ b/src/Prima.UOData/Mul/UoFiles.cs
@@ -52,6 +52,7 @@ public static void ReLoadDirectory()
ScanForFiles(RootDir);
}
+
public static void ScanForFiles(string path = "")
{
RootDir = path;
@@ -87,10 +88,20 @@ public static void SetMulPath(string path, string key)
public static string GetFilePath(string fileName)
{
-
return MulPath.GetValueOrDefault(fileName.ToLower());
}
+ public static string? FindDataFile(string fileName, bool throwError = true)
+ {
+ var filePath = MulPath.GetValueOrDefault(fileName.ToLower());
+ if (filePath == null && throwError)
+ {
+ throw new FileNotFoundException($"File {fileName} not found in {RootDir}");
+ }
+
+ return filePath;
+ }
+
///
/// Compares given MD5 hash with hash of given file
///
diff --git a/src/Prima.UOData/Packets/CharLocaleAndBody.cs b/src/Prima.UOData/Packets/CharLocaleAndBody.cs
new file mode 100644
index 0000000..55c63a6
--- /dev/null
+++ b/src/Prima.UOData/Packets/CharLocaleAndBody.cs
@@ -0,0 +1,56 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+using Prima.UOData.Data.Geometry;
+using Prima.UOData.Entities;
+using Prima.UOData.Id;
+using Prima.UOData.Types;
+
+namespace Prima.UOData.Packets;
+
+public class CharLocaleAndBody : BaseUoNetworkPacket
+{
+ public Serial MobileId { get; set; }
+ public short BodyType { get; set; }
+ public Point3D Position { get; set; }
+ public Direction Direction { get; set; }
+
+ public Point2D MapSize { get; set; }
+
+
+ public CharLocaleAndBody(MobileEntity mobile) : this()
+ {
+ MobileId = mobile.Id;
+ BodyType = 0x190;
+ Position = mobile.Position;
+ Direction = mobile.Direction;
+ MapSize = new Point2D(7168, 4096);
+ }
+
+ public CharLocaleAndBody() : base(0x1B, 37)
+ {
+ }
+
+ public override Span Write()
+ {
+ using var packetWriter = new SpanWriter(stackalloc byte[36], true);
+
+ packetWriter.Write((uint)MobileId);
+ packetWriter.Write((int)0);
+ packetWriter.Write((short)BodyType);
+ packetWriter.Write((short)Position.X);
+ packetWriter.Write((short)Position.Y);
+ packetWriter.Write((byte)0);
+ packetWriter.Write((short)Position.Z);
+ packetWriter.Write((byte)Direction);
+ packetWriter.Write((int)0);
+ packetWriter.Write((int)0);
+ packetWriter.Write((byte)0);
+ packetWriter.Write((short)MapSize.X);
+ packetWriter.Write((short)MapSize.Y);
+ packetWriter.Write((short)0);
+ packetWriter.Write((int)0);
+
+
+ return packetWriter.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/CharacterDraw.cs b/src/Prima.UOData/Packets/CharacterDraw.cs
new file mode 100644
index 0000000..1d893e8
--- /dev/null
+++ b/src/Prima.UOData/Packets/CharacterDraw.cs
@@ -0,0 +1,104 @@
+using System.Runtime.CompilerServices;
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+using Prima.UOData.Data.Geometry;
+using Prima.UOData.Entities;
+using Prima.UOData.Extensions;
+using Prima.UOData.Id;
+using Prima.UOData.Types;
+
+namespace Prima.UOData.Packets;
+
+public class CharacterDraw : BaseUoNetworkPacket
+{
+ public Serial Serial { get; set; }
+
+ public Serial ModelId { get; set; }
+
+ public Point3D Position { get; set; }
+
+ public Direction Direction { get; set; }
+
+ public short Hue { get; set; }
+
+ public Notoriety Notoriety { get; set; }
+
+ public CharacterStatus StatusFlag { get; set; }
+
+ public int ItemCount { get; set; } = 0;
+
+ public readonly Dictionary Items = new();
+
+ public CharacterDraw(MobileEntity mobile) : this()
+ {
+ Serial = mobile.Id;
+ ModelId = mobile.ModelId;
+ Position = mobile.Position;
+ Direction = mobile.Direction;
+ StatusFlag = mobile.StatusFlag;
+ Hue = (short)mobile.Hue;
+ Notoriety = mobile.Notoriety;
+ StatusFlag = 0x00;
+ ItemCount = mobile.Items.Count;
+
+ foreach (var item in mobile.Items)
+ {
+ Items.Add(item.Key, item.Value);
+ }
+ }
+
+ public CharacterDraw() : base(0x78, -1)
+ {
+ }
+
+ public override Span Write()
+ {
+ using var writer = new SpanWriter(stackalloc byte[10], true);
+
+ writer.Write(Serial);
+ writer.Write(ModelId);
+ writer.Write((short)Position.X);
+ writer.Write((short)Position.Y);
+ writer.Write((short)Position.Z);
+ writer.Write((byte)Direction);
+ writer.Write(Hue);
+ writer.Write((byte)StatusFlag);
+ writer.Write((byte)Notoriety);
+
+ if (ItemCount == 0)
+ {
+ writer.Write((int)0);
+ writer.Write((byte)0);
+ }
+ else
+ {
+ writer.Write(ItemCount);
+
+ foreach (var (layer, item) in Items)
+ {
+ writer.Write(item.Id);
+
+ var modelId = item.ModelId & 0x7FFF;
+ var writeHue = item.Hue != 0;
+
+ if (writeHue)
+ {
+ modelId |= 0x8000;
+ }
+
+ writer.Write(modelId);
+ writer.Write((byte)layer);
+
+ if (writeHue)
+ {
+ writer.Write((short)item.Hue);
+ }
+ }
+
+ writer.Write(0);
+ }
+
+
+ return writer.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/CharacterWarMode.cs b/src/Prima.UOData/Packets/CharacterWarMode.cs
new file mode 100644
index 0000000..81cee5b
--- /dev/null
+++ b/src/Prima.UOData/Packets/CharacterWarMode.cs
@@ -0,0 +1,31 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+
+namespace Prima.UOData.Packets;
+
+public class CharacterWarMode : BaseUoNetworkPacket
+{
+ public bool IsWarMode { get; set; }
+
+ public CharacterWarMode() : base(0x72, 5)
+ {
+ }
+
+ public CharacterWarMode(bool isWarMode = false) : this()
+ {
+ IsWarMode = isWarMode;
+ }
+
+
+ public override Span Write()
+ {
+ using var packetWriter = new SpanWriter(stackalloc byte[Length - 4], true);
+
+ packetWriter.Write(IsWarMode);
+ packetWriter.Write((byte)0);
+ packetWriter.Write((byte)0x32);
+ packetWriter.Write((byte)0);
+
+ return packetWriter.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/DrawGamePlayer.cs b/src/Prima.UOData/Packets/DrawGamePlayer.cs
new file mode 100644
index 0000000..04b5819
--- /dev/null
+++ b/src/Prima.UOData/Packets/DrawGamePlayer.cs
@@ -0,0 +1,54 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+using Prima.UOData.Data.Geometry;
+using Prima.UOData.Entities;
+using Prima.UOData.Id;
+using Prima.UOData.Types;
+
+namespace Prima.UOData.Packets;
+
+public class DrawGamePlayer : BaseUoNetworkPacket
+{
+ public Serial MobileId { get; set; }
+
+ public short BodyType { get; set; }
+
+ public int Hue { get; set; }
+
+ public byte StatusFlag { get; set; } = 0x00;
+
+ public Point3D Position { get; set; }
+
+ public Direction Direction { get; set; }
+
+ public DrawGamePlayer(MobileEntity mobile) : this()
+ {
+ MobileId = mobile.Id;
+ BodyType = 0x190;
+ Position = mobile.Position;
+ Direction = mobile.Direction;
+ Hue = mobile.Hue;
+ }
+
+ public DrawGamePlayer() : base(0x20, 19)
+ {
+ }
+
+ public override Span Write()
+ {
+ using var writer = new SpanWriter(stackalloc byte[Length - 1]);
+
+ writer.Write((uint)MobileId);
+ writer.Write((short)BodyType);
+ writer.Write((byte)0);
+ writer.Write((short)Hue);
+ writer.Write((byte)StatusFlag);
+ writer.Write((short)Position.X);
+ writer.Write((short)Position.Y);
+ writer.Write((short)0);
+ writer.Write((byte)Direction);
+ writer.Write((short)Position.Z);
+
+ return writer.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/GeneralInfoPacket.cs b/src/Prima.UOData/Packets/GeneralInfoPacket.cs
new file mode 100644
index 0000000..294ae44
--- /dev/null
+++ b/src/Prima.UOData/Packets/GeneralInfoPacket.cs
@@ -0,0 +1,108 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+
+namespace Prima.UOData.Packets;
+
+///
+/// Represents a General Information packet (0xBF) used for various extended functionality in the UO protocol.
+/// This packet serves as a container for numerous different sub-packets identified by a subcommand.
+///
+///
+/// OpCode: 0xBF
+/// The General Information packet has a variable length and can contain different data
+/// based on the subcommand value. It's one of the most versatile packets in the UO protocol
+/// and is used for features added after the initial protocol design.
+///
+public class GeneralInfoPacket : BaseUoNetworkPacket
+{
+ ///
+ /// Gets or sets the subcommand that identifies the specific type of information being sent.
+ ///
+ public ushort Subcommand { get; set; }
+
+ ///
+ /// Gets or sets the raw payload data for this packet.
+ /// The content varies based on the subcommand.
+ ///
+ public byte[] Payload { get; set; } = [];
+
+ ///
+ /// Initializes a new instance of the GeneralInfoPacket class.
+ ///
+ public GeneralInfoPacket() : base(0xBF, -1) // Variable length packet
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the GeneralInfoPacket class with the specified subcommand and payload.
+ ///
+ /// The subcommand value that identifies the specific type of information.
+ /// The raw payload data for this packet.
+ public GeneralInfoPacket(ushort subcommand, byte[] payload) : this()
+ {
+ Subcommand = subcommand;
+ Payload = payload ?? Array.Empty();
+ }
+
+ ///
+ /// Reads the packet data from the provided packet reader.
+ ///
+ /// The packet reader containing the packet data.
+ public override void Read(SpanReader reader)
+ {
+ // Skip the first 3 bytes (already read: opcode and packet length)
+ // if this causes issues, you may need to not skip them depending on how your reader is implemented
+
+ // Read the subcommand
+ Subcommand = reader.ReadUInt16();
+
+ // Read remaining bytes as payload
+ var remainingLength = reader.Remaining;
+ if (remainingLength > 0)
+ {
+ Payload = new byte[remainingLength];
+ Payload = reader.ReadBytes(remainingLength);
+ }
+ else
+ {
+ Payload = [];
+ }
+ }
+
+ ///
+ /// Writes the packet data to a byte span.
+ ///
+ /// A span containing the serialized packet data.
+ public override Span Write()
+ {
+ // Calculate the total packet length
+ // 5 = 1 (opcode) + 2 (length) + 2 (subcommand)
+ int packetLength = 5 + Payload.Length;
+
+ // Create a writer with the calculated capacity
+ using var writer = new SpanWriter(stackalloc byte[packetLength], true);
+
+ // Write packet length (big endian)
+ writer.Write((ushort)packetLength);
+
+ // Write subcommand
+ writer.Write(Subcommand);
+
+ // Write payload
+ if (Payload.Length > 0)
+ {
+ writer.Write(Payload);
+ }
+
+ return writer.ToSpan().Span;
+ }
+
+ ///
+ /// Returns a string representation of this packet for debugging purposes.
+ ///
+ /// A string containing the packet type, OpCode, subcommand, and payload length.
+ public override string ToString()
+ {
+ return base.ToString() + $" {{ Subcommand: 0x{Subcommand:X4}, PayloadLength: {Payload.Length} }}";
+ }
+}
diff --git a/src/Prima.UOData/Packets/GeneralInfoSubPacket.cs b/src/Prima.UOData/Packets/GeneralInfoSubPacket.cs
new file mode 100644
index 0000000..843825b
--- /dev/null
+++ b/src/Prima.UOData/Packets/GeneralInfoSubPacket.cs
@@ -0,0 +1,35 @@
+using Orion.Foundations.Spans;
+
+namespace Prima.UOData.Packets;
+
+///
+/// Base class for specialized sub-packets of the 0xBF General Information packet.
+///
+public abstract class GeneralInfoSubPacket
+{
+ ///
+ /// Gets the subcommand value that identifies this specific type of information.
+ ///
+ public abstract ushort Subcommand { get; }
+
+ ///
+ /// Serializes the sub-packet data to a byte array.
+ ///
+ /// A byte array containing the serialized sub-packet data.
+ public abstract byte[] Serialize();
+
+ ///
+ /// Deserializes the sub-packet data from a packet reader.
+ ///
+ /// The packet reader containing the sub-packet data.
+ public abstract void Deserialize(SpanReader reader);
+
+ ///
+ /// Creates a General Information packet containing this sub-packet's data.
+ ///
+ /// A GeneralInfoPacket instance ready to be sent.
+ public GeneralInfoPacket CreatePacket()
+ {
+ return new GeneralInfoPacket(Subcommand, Serialize());
+ }
+}
diff --git a/src/Prima.UOData/Packets/GlobalLightLevel.cs b/src/Prima.UOData/Packets/GlobalLightLevel.cs
new file mode 100644
index 0000000..24c7999
--- /dev/null
+++ b/src/Prima.UOData/Packets/GlobalLightLevel.cs
@@ -0,0 +1,26 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+
+namespace Prima.UOData.Packets;
+
+public class GlobalLightLevel : BaseUoNetworkPacket
+{
+ public int LightLevel { get; set; }
+
+ public GlobalLightLevel() : base(0x4F, 2)
+ {
+ }
+
+
+ public GlobalLightLevel(int lightLevel) : this()
+ {
+ LightLevel = lightLevel;
+ }
+
+ public override Span Write()
+ {
+ using var packetWriter = new SpanWriter(stackalloc byte[2], true);
+ packetWriter.Write((sbyte)LightLevel);
+ return packetWriter.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/LoginComplete.cs b/src/Prima.UOData/Packets/LoginComplete.cs
new file mode 100644
index 0000000..a4cd63b
--- /dev/null
+++ b/src/Prima.UOData/Packets/LoginComplete.cs
@@ -0,0 +1,10 @@
+using Prima.Network.Packets.Base;
+
+namespace Prima.UOData.Packets;
+
+public class LoginComplete : BaseUoNetworkPacket
+{
+ public LoginComplete() : base(0x55, 1)
+ {
+ }
+}
diff --git a/src/Prima.UOData/Packets/PersonalLightLevel.cs b/src/Prima.UOData/Packets/PersonalLightLevel.cs
new file mode 100644
index 0000000..1c6c1f7
--- /dev/null
+++ b/src/Prima.UOData/Packets/PersonalLightLevel.cs
@@ -0,0 +1,39 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+using Prima.UOData.Id;
+using Prima.UOData.Interfaces.Entities;
+
+namespace Prima.UOData.Packets;
+
+public class PersonalLightLevel : BaseUoNetworkPacket
+{
+ public Serial Serial { get; set; }
+
+ public int LightLevel { get; set; }
+
+
+
+ public PersonalLightLevel() : base(0x4E, 6)
+ {
+ }
+
+ public PersonalLightLevel(IHaveSerial serial, int lightLevel) : this()
+ {
+ Serial = serial.Id;
+ LightLevel = lightLevel;
+ }
+
+ public PersonalLightLevel(Serial serial, int lightLevel) : this()
+ {
+ Serial = serial;
+ LightLevel = lightLevel;
+ }
+
+ public override Span Write()
+ {
+ using var packetWriter = new SpanWriter(stackalloc byte[Length -1]);
+ packetWriter.Write((uint)Serial);
+ packetWriter.Write((sbyte)LightLevel);
+ return packetWriter.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/SeasonalInformation.cs b/src/Prima.UOData/Packets/SeasonalInformation.cs
new file mode 100644
index 0000000..c27fa7e
--- /dev/null
+++ b/src/Prima.UOData/Packets/SeasonalInformation.cs
@@ -0,0 +1,30 @@
+using Orion.Foundations.Spans;
+using Prima.Network.Packets.Base;
+using Prima.UOData.Types;
+
+namespace Prima.UOData.Packets;
+
+public class SeasonalInformation : BaseUoNetworkPacket
+{
+ public Season Season { get; set; }
+
+ public bool PlaySound { get; set; }
+
+ public SeasonalInformation(Season season, bool playSound) : this()
+ {
+ }
+
+ public SeasonalInformation() : base(0xBC, 3)
+ {
+ }
+
+ public override Span Write()
+ {
+ using var packetWriter = new SpanWriter(stackalloc byte[3]);
+
+ packetWriter.Write((byte)Season);
+ packetWriter.Write((byte)(PlaySound ? 1 : 0));
+
+ return packetWriter.Span.ToArray();
+ }
+}
diff --git a/src/Prima.UOData/Packets/SubCommands/ScreenSizePacket.cs b/src/Prima.UOData/Packets/SubCommands/ScreenSizePacket.cs
new file mode 100644
index 0000000..ebacbdf
--- /dev/null
+++ b/src/Prima.UOData/Packets/SubCommands/ScreenSizePacket.cs
@@ -0,0 +1,68 @@
+using Orion.Foundations.Spans;
+
+namespace Prima.UOData.Packets.SubCommands;
+
+///
+/// Represents a Screen Size sub-packet of the General Information packet.
+/// This packet is used to inform the server about the client's screen dimensions.
+///
+///
+/// Subcommand: 0x05
+///
+public class ScreenSizePacket : GeneralInfoSubPacket
+{
+ ///
+ /// Gets the subcommand value for Screen Size information.
+ ///
+ public override ushort Subcommand => 0x05;
+
+ ///
+ /// Gets or sets the client screen width in pixels.
+ ///
+ public ushort Width { get; set; }
+
+ ///
+ /// Gets or sets the client screen height in pixels.
+ ///
+ public ushort Height { get; set; }
+
+ ///
+ /// Initializes a new instance of the ScreenSizePacket class.
+ ///
+ public ScreenSizePacket()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the ScreenSizePacket class with the specified dimensions.
+ ///
+ /// The client screen width in pixels.
+ /// The client screen height in pixels.
+ public ScreenSizePacket(ushort width, ushort height)
+ {
+ Width = width;
+ Height = height;
+ }
+
+ ///
+ /// Serializes the screen size data to a byte array.
+ ///
+ /// A byte array containing the serialized screen size data.
+ public override byte[] Serialize()
+ {
+ using var writer = new SpanWriter(stackalloc byte[4], true);
+ writer.Write(Width);
+ writer.Write(Height);
+ return writer.ToSpan().Span.ToArray();
+ }
+
+ ///
+ /// Deserializes the screen size data from a packet reader.
+ ///
+ /// The packet reader containing the screen size data.
+ public override void Deserialize(SpanReader reader)
+ {
+ Width = reader.ReadUInt16();
+ Height = reader.ReadUInt16();
+ }
+}
diff --git a/src/Prima.UOData/Prima.UOData.csproj b/src/Prima.UOData/Prima.UOData.csproj
index 10a7524..eeb9940 100644
--- a/src/Prima.UOData/Prima.UOData.csproj
+++ b/src/Prima.UOData/Prima.UOData.csproj
@@ -16,6 +16,10 @@
+
+
+
+
diff --git a/src/Prima.UOData/Serializers/Base/BaseEntitySerializer.cs b/src/Prima.UOData/Serializers/Base/BaseEntitySerializer.cs
index ae451e4..f3b1d55 100644
--- a/src/Prima.UOData/Serializers/Base/BaseEntitySerializer.cs
+++ b/src/Prima.UOData/Serializers/Base/BaseEntitySerializer.cs
@@ -8,10 +8,8 @@ namespace Prima.UOData.Serializers.Base;
public abstract class BaseEntitySerializer : IEntitySerializer where TEntity : class, ISerializableEntity
{
public Type EntityType => typeof(TEntity);
-
public byte Header { get; }
-
protected BaseEntitySerializer()
{
var attribute = typeof(TEntity).GetCustomAttribute();
diff --git a/src/Prima.UOData/Serializers/Binary/BinaryItemSerializer.cs b/src/Prima.UOData/Serializers/Binary/BinaryItemSerializer.cs
index ba7afef..310e227 100644
--- a/src/Prima.UOData/Serializers/Binary/BinaryItemSerializer.cs
+++ b/src/Prima.UOData/Serializers/Binary/BinaryItemSerializer.cs
@@ -32,4 +32,5 @@ public override byte[] Serialize(ItemEntity entity)
return buffer.ToArray();
}
+
}
diff --git a/src/Prima.UOData/Serializers/Binary/BinaryMobileSerializer.cs b/src/Prima.UOData/Serializers/Binary/BinaryMobileSerializer.cs
index acef406..66f3e53 100644
--- a/src/Prima.UOData/Serializers/Binary/BinaryMobileSerializer.cs
+++ b/src/Prima.UOData/Serializers/Binary/BinaryMobileSerializer.cs
@@ -1,6 +1,7 @@
using Prima.UOData.Entities;
using Prima.UOData.Extensions;
using Prima.UOData.Serializers.Base;
+using Prima.UOData.Types;
namespace Prima.UOData.Serializers.Binary;
@@ -21,6 +22,17 @@ public override object Deserialize(byte[] data)
Direction = stream.ReadDirection()
};
+ // Read items count
+ var itemsCount = stream.ReadInt32();
+
+ for (var i = 0; i < itemsCount; i++)
+ {
+ var itemId = stream.ReadSerial();
+ var layer = (Layer)stream.ReadByte();
+ var item = new ItemEntity(itemId);
+ mobile.Items.Add(layer, item);
+ }
+
return mobile;
}
@@ -35,6 +47,15 @@ public override byte[] Serialize(MobileEntity entity)
stream.Write(entity.Hue);
stream.Write(entity.Position);
stream.Write(entity.Direction);
+ // Start to write items
+ stream.Write(entity.Items.Count);
+
+ foreach (var item in entity.Items)
+ {
+ stream.Write((byte)item.Key);
+ stream.Write(item.Value.Id);
+ }
+
return buffer.ToArray();
}
diff --git a/src/Prima.UOData/Types/CharacterStatus.cs b/src/Prima.UOData/Types/CharacterStatus.cs
new file mode 100644
index 0000000..11cee9f
--- /dev/null
+++ b/src/Prima.UOData/Types/CharacterStatus.cs
@@ -0,0 +1,13 @@
+namespace Prima.UOData.Types;
+
+public enum CharacterStatus : byte
+{
+ Normal = 0x00,
+ Unknown = 0x01,
+ CanAlterPaperdoll = 0x02,
+ Poisoned = 0x04,
+ GoldenHealth = 0x08,
+ Unknown0x10 = 0x10,
+ Unknown0x20 = 0x20,
+ WarMode = 0x40
+}
diff --git a/src/Prima.UOData/Types/GeneralInformationPacketSubcommand.cs b/src/Prima.UOData/Types/GeneralInformationPacketSubcommand.cs
new file mode 100644
index 0000000..7f887d4
--- /dev/null
+++ b/src/Prima.UOData/Types/GeneralInformationPacketSubcommand.cs
@@ -0,0 +1,37 @@
+namespace Prima.UOData.Types;
+
+public enum GeneralInformationPacketSubcommand : byte
+{
+ InitializeFastWalkPrevention = 0x01,
+ AddKeyToFastWalkStack = 0x02,
+ CloseGenericGump = 0x04,
+ ScreenSize = 0x05,
+ PartySystem = 0x06,
+ SetCursorHueSetMep = 0x08,
+ SetCursorHue = 0x09,
+ ClientLanguage = 0x0B,
+ ClosedStatusGump = 0x0C,
+ ThreeDClientAction = 0x0e,
+ ClientType = 0x0F,
+ RequestPopupMenu = 0x13,
+ DisplayPopupMenu = 0x14,
+ PopupEntrySelection = 0x15,
+ CloseUserInterfaceWindows = 0x16,
+ CodexOfWisdom = 0x17,
+ EnableMapDiff = 0x18,
+ ExtendedStats = 0x19,
+ ExtendedStats2 = 0x1A,
+ NewSpellbook = 0x1B,
+ SpellSelectedClientSide = 0x1C,
+ SendHouseRevisionState = 0x1D,
+ CustomHousing = 0x20,
+ AOS_AbilityIconConfirm = 0x21,
+ Damage = 0x22,
+ SEAbilityChange = 0x25,
+ MountSpeed = 0x26,
+ ServerChangeRaceRequest = 0x2A,
+ ChangeRaceResponse = 0x2A,
+ UseTargetedItem = 0x2C,
+ CastTargetedSpell = 0x2D,
+ UseTargetedSkill = 0x2E,
+}
diff --git a/src/Prima.UOData/Types/Layer.cs b/src/Prima.UOData/Types/Layer.cs
new file mode 100644
index 0000000..88f8261
--- /dev/null
+++ b/src/Prima.UOData/Types/Layer.cs
@@ -0,0 +1,169 @@
+namespace Prima.UOData.Types;
+
+public enum Layer : byte
+{
+ ///
+ /// Invalid layer.
+ ///
+ Invalid = 0x00,
+
+ ///
+ /// First valid layer. Equivalent to Layer.OneHanded.
+ ///
+ FirstValid = 0x01,
+
+ ///
+ /// One handed weapon.
+ ///
+ OneHanded = 0x01,
+
+ ///
+ /// Two handed weapon or shield.
+ ///
+ TwoHanded = 0x02,
+
+ ///
+ /// Shoes.
+ ///
+ Shoes = 0x03,
+
+ ///
+ /// Pants.
+ ///
+ Pants = 0x04,
+
+ ///
+ /// Shirts.
+ ///
+ Shirt = 0x05,
+
+ ///
+ /// Helmets, hats, and masks.
+ ///
+ Helm = 0x06,
+
+ ///
+ /// Gloves.
+ ///
+ Gloves = 0x07,
+
+ ///
+ /// Rings.
+ ///
+ Ring = 0x08,
+
+ ///
+ /// Talismans.
+ ///
+ Talisman = 0x09,
+
+ ///
+ /// Gorgets and necklaces.
+ ///
+ Neck = 0x0A,
+
+ ///
+ /// Hair.
+ ///
+ Hair = 0x0B,
+
+ ///
+ /// Half aprons.
+ ///
+ Waist = 0x0C,
+
+ ///
+ /// Torso, inner layer.
+ ///
+ InnerTorso = 0x0D,
+
+ ///
+ /// Bracelets.
+ ///
+ Bracelet = 0x0E,
+
+ ///
+ /// Unused.
+ ///
+ Unused_xF = 0x0F,
+
+ ///
+ /// Beards and mustaches.
+ ///
+ FacialHair = 0x10,
+
+ ///
+ /// Torso, outer layer.
+ ///
+ MiddleTorso = 0x11,
+
+ ///
+ /// Earings.
+ ///
+ Earrings = 0x12,
+
+ ///
+ /// Arms and sleeves.
+ ///
+ Arms = 0x13,
+
+ ///
+ /// Cloaks.
+ ///
+ Cloak = 0x14,
+
+ ///
+ /// Backpacks.
+ ///
+ Backpack = 0x15,
+
+ ///
+ /// Torso, outer layer.
+ ///
+ OuterTorso = 0x16,
+
+ ///
+ /// Leggings, outer layer.
+ ///
+ OuterLegs = 0x17,
+
+ ///
+ /// Leggings, inner layer.
+ ///
+ InnerLegs = 0x18,
+
+ ///
+ /// Last valid non-internal layer. Equivalent to Layer.InnerLegs.
+ ///
+ LastUserValid = 0x18,
+
+ ///
+ /// Mount item layer.
+ ///
+ Mount = 0x19,
+
+ ///
+ /// Vendor 'buy pack' layer.
+ ///
+ ShopBuy = 0x1A,
+
+ ///
+ /// Vendor 'resale pack' layer.
+ ///
+ ShopResale = 0x1B,
+
+ ///
+ /// Vendor 'sell pack' layer.
+ ///
+ ShopSell = 0x1C,
+
+ ///
+ /// Bank box layer.
+ ///
+ Bank = 0x1D,
+
+ ///
+ /// Last valid layer. Equivalent to Layer.Bank.
+ ///
+ LastValid = 0x1D
+}
diff --git a/src/Prima.UOData/Types/MusicName.cs b/src/Prima.UOData/Types/MusicName.cs
new file mode 100644
index 0000000..c2f8b6e
--- /dev/null
+++ b/src/Prima.UOData/Types/MusicName.cs
@@ -0,0 +1,110 @@
+namespace Prima.UOData.Types;
+
+public enum MusicName
+{
+ Invalid = -1,
+ OldUlt01 = 0,
+ Create1,
+ DragFlit,
+ OldUlt02,
+ OldUlt03,
+ OldUlt04,
+ OldUlt05,
+ OldUlt06,
+ Stones2,
+ Britain1,
+ Britain2,
+ Bucsden,
+ Jhelom,
+ LBCastle,
+ Linelle,
+ Magincia,
+ Minoc,
+ Ocllo,
+ Samlethe,
+ Serpents,
+ Skarabra,
+ Trinsic,
+ Vesper,
+ Wind,
+ Yew,
+ Cave01,
+ Dungeon9,
+ Forest_a,
+ InTown01,
+ Jungle_a,
+ Mountn_a,
+ Plains_a,
+ Sailing,
+ Swamp_a,
+ Tavern01,
+ Tavern02,
+ Tavern03,
+ Tavern04,
+ Combat1,
+ Combat2,
+ Combat3,
+ Approach,
+ Death,
+ Victory,
+ BTCastle,
+ Nujelm,
+ Dungeon2,
+ Cove,
+ Moonglow,
+ Zento,
+ TokunoDungeon,
+ Taiko,
+ DreadHornArea,
+ ElfCity,
+ GrizzleDungeon,
+ MelisandesLair,
+ ParoxysmusLair,
+ GwennoConversation,
+ GoodEndGame,
+ GoodVsEvil,
+ GreatEarthSerpents,
+ Humanoids_U9,
+ MinocNegative,
+ Paws,
+ SelimsBar,
+ SerpentIsleCombat_U7,
+ ValoriaShips,
+ TheWanderer,
+ Castle,
+ Festival,
+ Honor,
+ Medieval,
+ BattleOnStones,
+ Docktown,
+ GargoyleQueen,
+ GenericCombat,
+ Holycity,
+ HumanLevel,
+ LoginLoop,
+ NorthernForestBattleonStones,
+ PrimevalLich,
+ QueenPalace,
+ RoyalCity,
+ SlasherVeil,
+ StygianAbyss,
+ StygianDragon,
+ Void,
+ CodexShrine,
+ AnvilStrikeInMinoc,
+ ASkaranLullaby,
+ BlackthornsMarch,
+ DupresNightInTrinsic,
+ FayaxionAndTheSix,
+ FlightOfTheNexus,
+ GalehavenJaunt,
+ JhelomToArms,
+ MidnightInYew,
+ MoonglowSonata,
+ NewMaginciaMarch,
+ NujelmWaltz,
+ SherrysSong,
+ StarlightInBritain,
+ TheVesperMist,
+ NoMusic = 0x1FFF
+}
diff --git a/src/Prima.UOData/Types/Notoriety.cs b/src/Prima.UOData/Types/Notoriety.cs
new file mode 100644
index 0000000..855275c
--- /dev/null
+++ b/src/Prima.UOData/Types/Notoriety.cs
@@ -0,0 +1,12 @@
+namespace Prima.UOData.Types;
+
+public enum Notoriety : byte
+{
+ Innocent = 0x01,
+ Friend = 0x02,
+ Animal = 0x03,
+ Criminal = 0x04,
+ Enemy = 0x05,
+ Murdered = 0x06,
+ Invulnerable = 0x07,
+}
diff --git a/src/Prima.UOData/Types/Season.cs b/src/Prima.UOData/Types/Season.cs
new file mode 100644
index 0000000..d7cda70
--- /dev/null
+++ b/src/Prima.UOData/Types/Season.cs
@@ -0,0 +1,10 @@
+namespace Prima.UOData.Types;
+
+public enum Season : byte
+{
+ Spring = 0,
+ Summer = 1,
+ Fall = 2,
+ Winter = 3,
+ Desolation = 4,
+}