diff --git a/README.md b/README.md
index d7f4696..4e372f2 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ HMM使用基于CSV变种的HMM格式文件,便于阅读,以行为单位,
## 对比/补丁文件
-作为专业的地图数据维护工具,HMM支持对地图文件进行对比,查看数据中更改过的地方,选择性的合并数据,并能将变更内容到处为.hmp补丁文件。
+作为专业的地图数据维护工具,HMM支持对地图文件进行对比,查看数据中更改过的地方,选择性的合并数据,并能将变更内容导出为.hmp补丁文件。

diff --git a/code/HellMapManager/Assets/translate.xaml b/code/HellMapManager/Assets/translate.xaml
index 325b7b1..eb7252f 100644
--- a/code/HellMapManager/Assets/translate.xaml
+++ b/code/HellMapManager/Assets/translate.xaml
@@ -25,4 +25,10 @@
{0}个文件已经存在,您是否想替换它?
是
否
+ 使用英文逗号分隔多个关键字。
+可以使用 类型=来进行精确匹配,例如 name=入口 表示只匹配名称完全等于“入口”的项目。
+类型为空可以进行全类型精确匹配。
+前置英文感叹号表示排除。
+支持的类型为:key|name|desc|tag|group|to|command|message|misc。
+支持用\进行转义。
diff --git a/code/HellMapManager/Cores/MapDatabase.API.cs b/code/HellMapManager/Cores/MapDatabase.API.cs
index ff8e25a..9cfc512 100644
--- a/code/HellMapManager/Cores/MapDatabase.API.cs
+++ b/code/HellMapManager/Cores/MapDatabase.API.cs
@@ -741,13 +741,15 @@ public void APIRemoveVariables(List keys)
_lock.ExitWriteLock();
}
}
- public QueryResult? APIQueryPathAny(List from, List target, Context context, MapperOptions options)
+ public QueryResult? APIQueryPathAny(List from, List target, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
return new Walking(new Mapper(Current, context, options)).QueryPathAny(from, target, 0).SuccessOrNull();
}
}
@@ -758,13 +760,15 @@ public void APIRemoveVariables(List keys)
return null;
}
- public QueryResult? APIQueryPathAll(string start, List target, Context context, MapperOptions options)
+ public QueryResult? APIQueryPathAll(string start, List target, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
return new Walking(new Mapper(Current, context, options)).QueryPathAll(start, target).SuccessOrNull();
}
}
@@ -774,13 +778,15 @@ public void APIRemoveVariables(List keys)
}
return null;
}
- public QueryResult? APIQueryPathOrdered(string start, List target, Context context, MapperOptions options)
+ public QueryResult? APIQueryPathOrdered(string start, List target, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
return new Walking(new Mapper(Current, context, options)).QueryPathOrdered(start, target).SuccessOrNull();
}
}
@@ -848,13 +854,15 @@ public List APIQueryRegionRooms(string key)
return [];
}
- public List APIDilate(List src, int iterations, Context context, MapperOptions options)
+ public List APIDilate(List src, int iterations, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
return new Walking(new Mapper(Current, context, options)).Dilate(src, iterations);
}
}
@@ -864,13 +872,15 @@ public List APIDilate(List src, int iterations, Context context,
}
return [];
}
- public string APITrackExit(string start, string command, Context context, MapperOptions options)
+ public string APITrackExit(string start, string command, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
var mapper = new Mapper(Current, context, options);
var room = mapper.GetRoom(start);
if (room is not null)
@@ -911,13 +921,15 @@ public string APIGetVariable(string key)
}
return "";
}
- public Room? APIGetRoom(string key, Context context, MapperOptions options)
+ public Room? APIGetRoom(string key, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
return new Mapper(Current, context, options).GetRoom(key);
}
}
@@ -1147,13 +1159,15 @@ public void APIGroupRoom(string key, string group)
_lock.ExitWriteLock();
}
}
- public List APIGetRoomExits(string key, Context context, MapperOptions options)
+ public List APIGetRoomExits(string key, Context? context, MapperOptions? options)
{
_lock.EnterReadLock();
try
{
if (Current != null)
{
+ context ??= new Context();
+ options ??= new MapperOptions();
var mapper = new Mapper(Current, context, options);
var room = mapper.GetRoom(key);
if (room is not null)
diff --git a/code/HellMapManager/Cores/MapDatabase.cs b/code/HellMapManager/Cores/MapDatabase.cs
index 1e78a0d..42f6eca 100644
--- a/code/HellMapManager/Cores/MapDatabase.cs
+++ b/code/HellMapManager/Cores/MapDatabase.cs
@@ -8,7 +8,7 @@ namespace HellMapManager.Cores;
public partial class MapDatabase()
{
public ReaderWriterLockSlim _lock = new();
- public const int Version = 1003;
+ public const int Version = 1004;
public MapFile? Current;
public Settings Settings = new();
diff --git a/code/HellMapManager/Helpers/FilterHelper.cs b/code/HellMapManager/Helpers/FilterHelper.cs
new file mode 100644
index 0000000..338c7e3
--- /dev/null
+++ b/code/HellMapManager/Helpers/FilterHelper.cs
@@ -0,0 +1,75 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using HellMapManager.Models;
+using HellMapManager.Utils.ControlCode;
+
+namespace HellMapManager.Helpers;
+
+public class FilterHelper
+{
+ const string TypeKey = "key";
+ const string TypeName = "name";
+ const string TypeTo = "to";
+ const string TypeTag = "tag";
+ const string TypeCommand = "command";
+ const string TypeGroup = "group";
+ const string TypeType = "type";
+ const string TypeValue = "value";
+ const string TypeDesc = "desc";
+ const string TypeMisc = "misc";
+
+ const string TypeMessage = "message";
+ static readonly ControlCode escaper = new ControlCode().
+ WithCommand(new Command("\\", "0", "\\\\")).
+ WithCommand(new Command("\n", "1", "\\n")).
+ WithCommand(new Command(",", "2", "\\,")).
+ WithCommand(new Command("=", "3", "\\=")).
+ WithCommand(new Command(" ", "4", "\\ ")).
+ WithCommand(new Command("!", "5", "\\!"));
+
+ public static FilterKeyword ParseKeyword(string unpacked)
+ {
+ var keyword = new FilterKeyword();
+ if (unpacked.StartsWith("!"))
+ {
+ keyword.Not = true;
+ unpacked = unpacked[1..];
+ }
+ var data = unpacked.Split(['='], 2);
+ if (data.Length > 1)
+ {
+ keyword.Type = escaper.Decode(data[0].Trim()) switch
+ {
+ "" => FilterKeywordType.Any,
+ TypeKey => FilterKeywordType.Key,
+ TypeName => FilterKeywordType.Name,
+ TypeTo => FilterKeywordType.To,
+ TypeTag => FilterKeywordType.Tag,
+ TypeCommand => FilterKeywordType.Command,
+ TypeGroup => FilterKeywordType.Group,
+ TypeMisc => FilterKeywordType.Misc,
+ TypeType => FilterKeywordType.Type,
+ TypeDesc => FilterKeywordType.Desc,
+ TypeValue => FilterKeywordType.Value,
+ TypeMessage => FilterKeywordType.Message,
+ _ => FilterKeywordType.Wrong,
+ };
+ keyword.Value = escaper.Decode(data[1]);
+ keyword.PartialMatch = false;
+ }
+ else
+ {
+ keyword.Value = escaper.Decode(data[0]);
+ keyword.PartialMatch = true;
+ }
+ return keyword;
+ }
+ public static List ParseKeywords(string filter)
+ {
+ return escaper.Unpack(filter).Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).ToList().ConvertAll(r => ParseKeyword(r));
+ }
+
+}
+
diff --git a/code/HellMapManager/Misc/AppVersion.cs b/code/HellMapManager/Misc/AppVersion.cs
index b7b579f..fd9013d 100644
--- a/code/HellMapManager/Misc/AppVersion.cs
+++ b/code/HellMapManager/Misc/AppVersion.cs
@@ -2,7 +2,7 @@ namespace HellMapManager.Misc;
public class AppVersion(int major, int minor, int patch)
{
- public static AppVersion Current { get; } = new(0, 20260101, 0);
+ public static AppVersion Current { get; } = new(0, 20260116, 0);
public int Major { get; } = major;
public int Minor { get; } = minor;
public int Patch { get; } = patch;
diff --git a/code/HellMapManager/Misc/Links.cs b/code/HellMapManager/Misc/Links.cs
index de3f21e..c43342f 100644
--- a/code/HellMapManager/Misc/Links.cs
+++ b/code/HellMapManager/Misc/Links.cs
@@ -8,5 +8,5 @@ public class Links
public const string ScriptInro = "https://github.com/hellclient-scripts/hellmapmanager/blob/main/doc/script/index.md";
public const string API = "https://github.com/hellclient-scripts/hellmapmanager/blob/main/doc/api/index.md";
public const string BestPractices = "https://github.com/hellclient-scripts/hellmapmanager/blob/main/doc/bestpractices/index.md";
-
+ public const string Forum = "https://forum.hellclient.com/";
}
\ No newline at end of file
diff --git a/code/HellMapManager/Models/Context.cs b/code/HellMapManager/Models/Context.cs
index 51b0216..d42f2e8 100644
--- a/code/HellMapManager/Models/Context.cs
+++ b/code/HellMapManager/Models/Context.cs
@@ -187,18 +187,21 @@ public bool IsBlocked(string from, string to)
{
return BlockedLinks.ContainsKey(from) && BlockedLinks[from].ContainsKey(to);
}
- public static Context FromEnvironment(Environment env)
+ public static Context FromEnvironment(Environment? env)
{
var context = new Context();
- context.WithTags(env.Tags);
- context.WithRoomConditions(env.RoomConditions);
- context.WithRooms(env.Rooms);
- context.WithWhitelist(env.Whitelist);
- context.WithBlacklist(env.Blacklist);
- context.WithShortcuts(env.Shortcuts);
- context.WithPaths(env.Paths);
- context.WithBlockedLinks(env.BlockedLinks);
- context.WithCommandCosts(env.CommandCosts);
+ if (env != null)
+ {
+ context.WithTags(env.Tags);
+ context.WithRoomConditions(env.RoomConditions);
+ context.WithRooms(env.Rooms);
+ context.WithWhitelist(env.Whitelist);
+ context.WithBlacklist(env.Blacklist);
+ context.WithShortcuts(env.Shortcuts);
+ context.WithPaths(env.Paths);
+ context.WithBlockedLinks(env.BlockedLinks);
+ context.WithCommandCosts(env.CommandCosts);
+ }
return context;
}
public Environment ToEnvironment()
diff --git a/code/HellMapManager/Models/FilterKeyword.cs b/code/HellMapManager/Models/FilterKeyword.cs
new file mode 100644
index 0000000..1ae6496
--- /dev/null
+++ b/code/HellMapManager/Models/FilterKeyword.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace HellMapManager.Models;
+
+public enum FilterKeywordType
+{
+ Any,
+ Wrong,
+ Misc,
+ Message,
+ Key,
+ Name,
+ To,
+ Tag,
+ Command,
+ Group,
+ Type,
+
+ Desc,
+ Value,
+}
+public class FilterKeyword
+{
+ public FilterKeywordType Type = FilterKeywordType.Any;
+ public bool Not = false;
+ public bool PartialMatch = true;
+ public string Value = "";
+ public bool Match(string target, FilterKeywordType type)
+ {
+ if (Type != FilterKeywordType.Any && Type != type)
+ {
+ return false;
+ }
+ return Not != (PartialMatch ? target.Contains(Value) : target == Value);
+ }
+}
\ No newline at end of file
diff --git a/code/HellMapManager/Models/Landmark.cs b/code/HellMapManager/Models/Landmark.cs
index 05bbae5..b8c4971 100644
--- a/code/HellMapManager/Models/Landmark.cs
+++ b/code/HellMapManager/Models/Landmark.cs
@@ -80,9 +80,9 @@ public static void Sort(List list)
public partial class Landmark
{
- public bool Filter(string filter)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(filter) || Type.Contains(filter) || Value.Contains(filter) || Group.Contains(filter) || Desc.Contains(filter))
+ if (keyword.Match(Key, FilterKeywordType.Key) || keyword.Match(Type, FilterKeywordType.Type) || keyword.Match(Value, FilterKeywordType.Value) || keyword.Match(Group, FilterKeywordType.Group) || keyword.Match(Desc, FilterKeywordType.Desc))
{
return true;
}
diff --git a/code/HellMapManager/Models/Marker.cs b/code/HellMapManager/Models/Marker.cs
index 4d5fea2..8661659 100644
--- a/code/HellMapManager/Models/Marker.cs
+++ b/code/HellMapManager/Models/Marker.cs
@@ -62,13 +62,13 @@ public static void Sort(List list)
}
public partial class Marker
{
- public bool Filter(string val)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(val) ||
- Value.Contains(val) ||
- Desc.Contains(val) ||
- Group.Contains(val) ||
- Message.Contains(val)
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Value, FilterKeywordType.Value) ||
+ keyword.Match(Desc, FilterKeywordType.Desc) ||
+ keyword.Match(Group, FilterKeywordType.Group) ||
+ keyword.Match(Message, FilterKeywordType.Message)
)
{
return true;
diff --git a/code/HellMapManager/Models/Region.cs b/code/HellMapManager/Models/Region.cs
index 631fd4e..108ee9d 100644
--- a/code/HellMapManager/Models/Region.cs
+++ b/code/HellMapManager/Models/Region.cs
@@ -107,18 +107,19 @@ public static void Sort(List list)
public partial class Region
{
- public bool Filter(string val)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(val) ||
- Desc.Contains(val) ||
- Group.Contains(val) ||
- Message.Contains(val))
+
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Desc, FilterKeywordType.Desc) ||
+ keyword.Match(Group, FilterKeywordType.Group) ||
+ keyword.Match(Message, FilterKeywordType.Message))
{
return true;
}
foreach (var item in Items)
{
- if (item.Value.Contains(val))
+ if (keyword.Match(item.Value, FilterKeywordType.To))
{
return true;
}
diff --git a/code/HellMapManager/Models/Room.cs b/code/HellMapManager/Models/Room.cs
index 84f91b5..f2d9713 100644
--- a/code/HellMapManager/Models/Room.cs
+++ b/code/HellMapManager/Models/Room.cs
@@ -322,38 +322,38 @@ public void Arrange()
Tags.Sort((x, y) => x.Key.CompareTo(y.Key));
Exits.ForEach(e => e.Arrange());
}
- public bool Filter(string val)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(val) ||
- Name.Contains(val) ||
- Desc.Contains(val) ||
- Group.Contains(val))
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Name, FilterKeywordType.Name) ||
+ keyword.Match(Desc, FilterKeywordType.Desc) ||
+ keyword.Match(Group, FilterKeywordType.Group))
{
return true;
}
foreach (var tag in Tags)
{
- if (tag.Key.Contains(val))
+ if (keyword.Match(tag.Key, FilterKeywordType.Tag))
{
return true;
}
}
foreach (var data in Data)
{
- if (data.Key.Contains(val) || data.Value.Contains(val))
+ if (keyword.Match(data.Key, FilterKeywordType.Misc) || keyword.Match(data.Value, FilterKeywordType.Misc))
{
return true;
}
}
foreach (var exit in Exits)
{
- if (exit.Command.Contains(val) || exit.To.Contains(val))
+ if (keyword.Match(exit.Command, FilterKeywordType.Command) || keyword.Match(exit.To, FilterKeywordType.To))
{
return true;
}
foreach(var cond in exit.Conditions)
{
- if (cond.Key.Contains(val))
+ if (keyword.Match(cond.Key, FilterKeywordType.Tag))
{
return true;
}
diff --git a/code/HellMapManager/Models/Route.cs b/code/HellMapManager/Models/Route.cs
index 8f21ce3..f6101f6 100644
--- a/code/HellMapManager/Models/Route.cs
+++ b/code/HellMapManager/Models/Route.cs
@@ -82,18 +82,18 @@ public string RoomsList
return string.Join("\n", Rooms);
}
}
- public bool Filter(string val)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(val) ||
- Desc.Contains(val) ||
- Group.Contains(val) ||
- Message.Contains(val))
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Desc, FilterKeywordType.Desc) ||
+ keyword.Match(Group, FilterKeywordType.Group) ||
+ keyword.Match(Message, FilterKeywordType.Message))
{
return true;
}
foreach (var room in Rooms)
{
- if (room.Contains(val))
+ if (keyword.Match(room, FilterKeywordType.To))
{
return true;
}
diff --git a/code/HellMapManager/Models/Shortcut.cs b/code/HellMapManager/Models/Shortcut.cs
index de5521a..eb8f95d 100644
--- a/code/HellMapManager/Models/Shortcut.cs
+++ b/code/HellMapManager/Models/Shortcut.cs
@@ -63,22 +63,26 @@ public static Shortcut Decode(string val)
result.Cost = HMMFormatter.UnescapeIntAt(list, 7, 0);
return result;
}
- public bool Filter(string val)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(val) || Command.Contains(val) || To.Contains(val) || Group.Contains(val) || Desc.Contains(val))
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Command, FilterKeywordType.Command) ||
+ keyword.Match(To, FilterKeywordType.To) ||
+ keyword.Match(Group, FilterKeywordType.Group) ||
+ keyword.Match(Desc, FilterKeywordType.Desc))
{
return true;
}
foreach (var cond in Conditions)
{
- if (cond.Key.Contains(val))
+ if (keyword.Match(cond.Key, FilterKeywordType.Tag))
{
return true;
}
}
foreach (var cond in RoomConditions)
{
- if (cond.Key.Contains(val))
+ if (keyword.Match(cond.Key, FilterKeywordType.Tag))
{
return true;
}
diff --git a/code/HellMapManager/Models/Snapshot.cs b/code/HellMapManager/Models/Snapshot.cs
index a490f65..0c2bcba 100644
--- a/code/HellMapManager/Models/Snapshot.cs
+++ b/code/HellMapManager/Models/Snapshot.cs
@@ -87,9 +87,12 @@ public Snapshot Clone()
Count = Count,
};
}
- public bool Filter(string filter)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(filter) || Type.Contains(filter) || Value.Contains(filter) || Group.Contains(filter))
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Type, FilterKeywordType.Type) ||
+ keyword.Match(Value, FilterKeywordType.Value) ||
+ keyword.Match(Group, FilterKeywordType.Group))
{
return true;
}
diff --git a/code/HellMapManager/Models/Trace.cs b/code/HellMapManager/Models/Trace.cs
index 1c3d201..b9dff75 100644
--- a/code/HellMapManager/Models/Trace.cs
+++ b/code/HellMapManager/Models/Trace.cs
@@ -84,18 +84,18 @@ public void AddLocations(List loctions)
}
Arrange();
}
- public bool Filter(string val)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(val) ||
- Desc.Contains(val) ||
- Group.Contains(val) ||
- Message.Contains(val))
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Desc, FilterKeywordType.Desc) ||
+ keyword.Match(Group, FilterKeywordType.Group) ||
+ keyword.Match(Message, FilterKeywordType.Message))
{
return true;
}
foreach (var room in Locations)
{
- if (room.Contains(val))
+ if (keyword.Match(room, FilterKeywordType.To))
{
return true;
}
diff --git a/code/HellMapManager/Models/Variable.cs b/code/HellMapManager/Models/Variable.cs
index 680ce56..44e5d1c 100644
--- a/code/HellMapManager/Models/Variable.cs
+++ b/code/HellMapManager/Models/Variable.cs
@@ -1,4 +1,5 @@
namespace HellMapManager.Models;
+
using System.Collections.Generic;
@@ -47,21 +48,12 @@ public Variable Clone()
Desc = Desc,
};
}
- public bool Filter(string filter)
+ public bool Filter(FilterKeyword keyword)
{
- if (Key.Contains(filter))
- {
- return true;
- }
- if (Value.Contains(filter))
- {
- return true;
- }
- if (Group.Contains(filter))
- {
- return true;
- }
- if (Desc.Contains(filter))
+ if (keyword.Match(Key, FilterKeywordType.Key) ||
+ keyword.Match(Value, FilterKeywordType.Value) ||
+ keyword.Match(Group, FilterKeywordType.Group) ||
+ keyword.Match(Desc, FilterKeywordType.Desc))
{
return true;
}
diff --git a/code/HellMapManager/Services/API/API.cs b/code/HellMapManager/Services/API/API.cs
index c90f537..3814153 100644
--- a/code/HellMapManager/Services/API/API.cs
+++ b/code/HellMapManager/Services/API/API.cs
@@ -331,7 +331,7 @@ public async Task APIQueryPathAny(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var result = Database.APIQueryPathAny(query.From, query.Target, Context.FromEnvironment(query.Environment.ToEnvironment()), query.Options.ToMapperOptions());
+ var result = Database.APIQueryPathAny(query.From, query.Target, Context.FromEnvironment(query?.Environment?.ToEnvironment()), query?.Options?.ToMapperOptions());
await WriteJSON(ctx, QueryResultModel.FromQueryResult(result));
}
public async Task APIQueryPathAll(HttpContext ctx)
@@ -342,7 +342,7 @@ public async Task APIQueryPathAll(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var result = Database.APIQueryPathAll(query.Start, query.Target, Context.FromEnvironment(query.Environment.ToEnvironment()), query.Options.ToMapperOptions());
+ var result = Database.APIQueryPathAll(query.Start, query.Target, Context.FromEnvironment(query?.Environment?.ToEnvironment()), query?.Options?.ToMapperOptions());
await WriteJSON(ctx, QueryResultModel.FromQueryResult(result));
}
public async Task APIQueryPathOrdered(HttpContext ctx)
@@ -353,7 +353,7 @@ public async Task APIQueryPathOrdered(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var result = Database.APIQueryPathOrdered(query.Start, query.Target, Context.FromEnvironment(query.Environment.ToEnvironment()), query.Options.ToMapperOptions());
+ var result = Database.APIQueryPathOrdered(query.Start, query.Target, Context.FromEnvironment(query?.Environment?.ToEnvironment()), query?.Options?.ToMapperOptions());
await WriteJSON(ctx, QueryResultModel.FromQueryResult(result));
}
public async Task APIDilate(HttpContext ctx)
@@ -364,7 +364,7 @@ public async Task APIDilate(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var output = Database.APIDilate(input.Source, input.Iterations, Context.FromEnvironment(input.Environment.ToEnvironment()), input.Options.ToMapperOptions());
+ var output = Database.APIDilate(input.Source, input.Iterations, Context.FromEnvironment(input?.Environment?.ToEnvironment()), input?.Options?.ToMapperOptions());
await WriteJSON(ctx, output);
}
public async Task APITrackExit(HttpContext ctx)
@@ -375,7 +375,7 @@ public async Task APITrackExit(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var output = Database.APITrackExit(input.Start, input.Command, Context.FromEnvironment(input.Environment.ToEnvironment()), input.Options.ToMapperOptions());
+ var output = Database.APITrackExit(input.Start, input.Command, Context.FromEnvironment(input?.Environment?.ToEnvironment()), input?.Options?.ToMapperOptions());
await WriteJSON(ctx, output);
}
public async Task APIGetVariable(HttpContext ctx)
@@ -408,7 +408,7 @@ public async Task APIGetRoom(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var room = Database.APIGetRoom(input.Key, Context.FromEnvironment(input.Environment.ToEnvironment()), input.Options.ToMapperOptions());
+ var room = Database.APIGetRoom(input.Key, Context.FromEnvironment(input?.Environment?.ToEnvironment()), input?.Options?.ToMapperOptions());
await WriteJSON(ctx, RoomModel.From(room));
}
public async Task APIClearSnapshots(HttpContext ctx)
@@ -524,7 +524,7 @@ public async Task APIGetRoomExits(HttpContext ctx)
await InvalidJSONRequest(ctx);
return;
}
- var exits = Database.APIGetRoomExits(input.Key, Context.FromEnvironment(input.Environment.ToEnvironment()), input.Options.ToMapperOptions());
+ var exits = Database.APIGetRoomExits(input.Key, Context.FromEnvironment(input?.Environment?.ToEnvironment()), input?.Options?.ToMapperOptions());
await WriteJSON(ctx, ExitModel.FromList(exits));
}
}
\ No newline at end of file
diff --git a/code/HellMapManager/Services/API/Models.cs b/code/HellMapManager/Services/API/Models.cs
index 2ec1dd8..33b118f 100644
--- a/code/HellMapManager/Services/API/Models.cs
+++ b/code/HellMapManager/Services/API/Models.cs
@@ -1356,8 +1356,8 @@ public class InputQueryPathAny()
}
public List From { get; set; } = [];
public List Target { get; set; } = [];
- public EnvironmentModel Environment { get; set; } = new();
- public MapperOptionsModel Options { get; set; } = new();
+ public EnvironmentModel? Environment { get; set; } = new();
+ public MapperOptionsModel? Options { get; set; } = new();
}
public class InputQueryPath()
@@ -1379,8 +1379,8 @@ public class InputQueryPath()
}
public string Start { get; set; } = "";
public List Target { get; set; } = [];
- public EnvironmentModel Environment { get; set; } = new();
- public MapperOptionsModel Options { get; set; } = new();
+ public EnvironmentModel? Environment { get; set; } = new();
+ public MapperOptionsModel? Options { get; set; } = new();
}
public class InputDilate()
@@ -1401,8 +1401,8 @@ public class InputDilate()
}
public List Source { get; set; } = [];
public int Iterations { get; set; } = 1;
- public EnvironmentModel Environment { get; set; } = new();
- public MapperOptionsModel Options { get; set; } = new();
+ public EnvironmentModel? Environment { get; set; } = new();
+ public MapperOptionsModel? Options { get; set; } = new();
}
public class InputTrackExit()
{
@@ -1422,8 +1422,8 @@ public class InputTrackExit()
}
public string Start { get; set; } = "";
public string Command { get; set; } = "";
- public EnvironmentModel Environment { get; set; } = new();
- public MapperOptionsModel Options { get; set; } = new();
+ public EnvironmentModel? Environment { get; set; } = new();
+ public MapperOptionsModel? Options { get; set; } = new();
}
public class InputKey()
{
@@ -1461,8 +1461,8 @@ public class InputGetRoom()
return null;
}
public string Key { get; set; } = "";
- public EnvironmentModel Environment { get; set; } = new();
- public MapperOptionsModel Options { get; set; } = new();
+ public EnvironmentModel? Environment { get; set; } = new();
+ public MapperOptionsModel? Options { get; set; } = new();
}
diff --git a/code/HellMapManager/Utils/Filter.cs b/code/HellMapManager/Utils/Filter.cs
deleted file mode 100644
index 64a2d09..0000000
--- a/code/HellMapManager/Utils/Filter.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace HellMapManager.Utils;
-
-public class FilterUtil
-{
- public static List SplitFilter(string filter)
- {
- var parts = filter.Split(",", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
- return new List(parts);
- }
-}
\ No newline at end of file
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Landmarks.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Landmarks.cs
index 6a393df..9cc6cb4 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Landmarks.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Landmarks.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredLandmarks
var models = AppKernel.MapDatabase.Current.Map.Landmarks;
if (!string.IsNullOrEmpty(LandmarksFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(LandmarksFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(LandmarksFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Markers.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Markers.cs
index 90460ec..5b8c193 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Markers.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Markers.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredMarkers
var models = AppKernel.MapDatabase.Current.Map.Markers;
if (!string.IsNullOrEmpty(MarkersFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(MarkersFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(MarkersFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Regions.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Regions.cs
index ccc3f41..3887c27 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Regions.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Regions.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredRegions
var models = AppKernel.MapDatabase.Current.Map.Regions;
if (!string.IsNullOrEmpty(RegionsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RegionsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RegionsFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Rooms.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Rooms.cs
index 9620765..dbdf9ac 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Rooms.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Rooms.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredRooms
var models = AppKernel.MapDatabase.Current.Map.Rooms;
if (!string.IsNullOrEmpty(RoomsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RoomsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RoomsFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Routes.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Routes.cs
index 73c822b..87094c2 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Routes.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Routes.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredRoutes
var models = AppKernel.MapDatabase.Current.Map.Routes;
if (!string.IsNullOrEmpty(RoutesFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RoutesFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RoutesFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Snapshot.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Snapshot.cs
index 866a2d7..e75d48d 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Snapshot.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Snapshot.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredSnapshots
var models = AppKernel.MapDatabase.Current.Map.Snapshots;
if (!string.IsNullOrEmpty(SnapshotsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(SnapshotsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(SnapshotsFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Traces.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Traces.cs
index c96bd9c..23be918 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Traces.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Traces.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredTraces
var models = AppKernel.MapDatabase.Current.Map.Traces;
if (!string.IsNullOrEmpty(TracesFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(TracesFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(TracesFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Variables.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Variables.cs
index 6fce5d2..e20f390 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Variables.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Variables.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredVariables
var models = AppKernel.MapDatabase.Current.Map.Variables;
if (!string.IsNullOrEmpty(VariablesFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(VariablesFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(VariablesFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.Welcome.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.Welcome.cs
index e0495b5..28fe096 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.Welcome.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.Welcome.cs
@@ -14,4 +14,11 @@ public static ObservableCollection HelpLinks
new ExternalLink("最佳实践", Misc.Links.API,"了解使用HMM的最佳实践。"),
];
}
+ public static ObservableCollection CommunityLinks
+ {
+ get => [
+ new ExternalLink("Github", Misc.Links.Homepage,"访问HMM的GitHub主页,获取最新版本和发布信息。"),
+ new ExternalLink("社区", Misc.Links.Forum,"加入HellClient社区,参与讨论并获取帮助。"),
+ ];
+ }
}
\ No newline at end of file
diff --git a/code/HellMapManager/ViewModels/MainWindowViewModel.shortcuts.cs b/code/HellMapManager/ViewModels/MainWindowViewModel.shortcuts.cs
index 9c432c0..64f725d 100644
--- a/code/HellMapManager/ViewModels/MainWindowViewModel.shortcuts.cs
+++ b/code/HellMapManager/ViewModels/MainWindowViewModel.shortcuts.cs
@@ -27,7 +27,7 @@ public ObservableCollection FilteredShortcuts
var models = AppKernel.MapDatabase.Current.Map.Shortcuts;
if (!string.IsNullOrEmpty(ShortcutsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(ShortcutsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(ShortcutsFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/HellMapManager/Views/MainWindow.axaml b/code/HellMapManager/Views/MainWindow.axaml
index cc9cbdd..e50d05d 100644
--- a/code/HellMapManager/Views/MainWindow.axaml
+++ b/code/HellMapManager/Views/MainWindow.axaml
@@ -64,7 +64,10 @@
@@ -81,6 +84,8 @@
+
+
diff --git a/code/HellMapManager/Views/MainWindow.axaml.cs b/code/HellMapManager/Views/MainWindow.axaml.cs
index 5d6dab3..c96522b 100644
--- a/code/HellMapManager/Views/MainWindow.axaml.cs
+++ b/code/HellMapManager/Views/MainWindow.axaml.cs
@@ -114,6 +114,11 @@ public void OpenURLHomepage(object? sender, RoutedEventArgs args)
{
TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(new Uri(Links.Homepage));
}
+ public void OpenURLForum(object? sender, RoutedEventArgs args)
+ {
+ TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(new Uri(Links.Forum));
+ }
+
public void OpenURLTerm(object? sender, RoutedEventArgs args)
{
TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(new Uri(Links.Term));
diff --git a/code/HellMapManager/Views/Mapfile/Landmarks/Landmarks.axaml b/code/HellMapManager/Views/Mapfile/Landmarks/Landmarks.axaml
index bb5c33a..005bec8 100644
--- a/code/HellMapManager/Views/Mapfile/Landmarks/Landmarks.axaml
+++ b/code/HellMapManager/Views/Mapfile/Landmarks/Landmarks.axaml
@@ -55,7 +55,7 @@
DockPanel.Dock="Right"
Text="{Binding LandmarksFilter}"
TextChanged="OnFilter"
- Watermark="过滤,逗号分隔关键字" />
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ 沟通
+
+
+
+
+
+
+
+
+
+
+
+
+
+
入门
diff --git a/code/HellMapManager/Windows/PatchWindow/Landmarks.axaml b/code/HellMapManager/Windows/PatchWindow/Landmarks.axaml
index 73d0741..c59cf9e 100644
--- a/code/HellMapManager/Windows/PatchWindow/Landmarks.axaml
+++ b/code/HellMapManager/Windows/PatchWindow/Landmarks.axaml
@@ -26,7 +26,7 @@
DockPanel.Dock="Right"
Text="{Binding LandmarksFilter}"
TextChanged="OnFilter"
- Watermark="过滤,逗号分隔关键字" />
+ Watermark="过滤">
+ Watermark="过滤">
FilteredLandmarks
var models = Patch.Landmarks.Items;
if (!string.IsNullOrEmpty(LandmarksFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(LandmarksFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(LandmarksFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Markers.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Markers.cs
index a016b3f..56dd82f 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Markers.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Markers.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredMarkers
var models = Patch.Markers.Items;
if (!string.IsNullOrEmpty(MarkersFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(MarkersFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(MarkersFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Regions.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Regions.cs
index a0df843..eaa5138 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Regions.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Regions.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredRegions
var models = Patch.Regions.Items;
if (!string.IsNullOrEmpty(RegionsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RegionsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RegionsFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Rooms.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Rooms.cs
index 6bddd7f..b2416af 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Rooms.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Rooms.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredRooms
var models = Patch.Rooms.Items;
if (!string.IsNullOrEmpty(RoomsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RoomsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RoomsFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Routes.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Routes.cs
index a318f65..5aa2f38 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Routes.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Routes.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredRoutes
var models = Patch.Routes.Items;
if (!string.IsNullOrEmpty(RoutesFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RoutesFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RoutesFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Shortcuts.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Shortcuts.cs
index b6e57b9..2fcd68e 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Shortcuts.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Shortcuts.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredShortcuts
var models = Patch.Shortcuts.Items;
if (!string.IsNullOrEmpty(ShortcutsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(ShortcutsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(ShortcutsFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Snapshot.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Snapshot.cs
index 1e6b011..37267e2 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Snapshot.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Snapshot.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredSnapshots
var models = Patch.Snapshots.Items;
if (!string.IsNullOrEmpty(SnapshotsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(SnapshotsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(SnapshotsFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Traces.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Traces.cs
index f460cb7..aac296f 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Traces.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Traces.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredTraces
var models = Patch.Traces.Items;
if (!string.IsNullOrEmpty(TracesFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(TracesFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(TracesFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Variable.cs b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Variable.cs
index 4d39708..cf9caad 100644
--- a/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Variable.cs
+++ b/code/HellMapManager/Windows/PatchWindow/PatchWindowViewModel.Variable.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredVariables
var models = Patch.Variables.Items;
if (!string.IsNullOrEmpty(VariablesFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(VariablesFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(VariablesFilter).ForEach(filter =>
{
models = models.FindAll(r =>
{
diff --git a/code/HellMapManager/Windows/PatchWindow/Regions.axaml b/code/HellMapManager/Windows/PatchWindow/Regions.axaml
index 82d2576..527deb0 100644
--- a/code/HellMapManager/Windows/PatchWindow/Regions.axaml
+++ b/code/HellMapManager/Windows/PatchWindow/Regions.axaml
@@ -26,7 +26,7 @@
DockPanel.Dock="Right"
Text="{Binding RegionsFilter}"
TextChanged="OnFilter"
- Watermark="过滤,逗号分隔关键字" />
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
+ Watermark="过滤">
diff --git a/code/HellMapManager/Windows/PickRoomWindow/PickRoomWindowViewModel.cs b/code/HellMapManager/Windows/PickRoomWindow/PickRoomWindowViewModel.cs
index 1773c57..c5d8637 100644
--- a/code/HellMapManager/Windows/PickRoomWindow/PickRoomWindowViewModel.cs
+++ b/code/HellMapManager/Windows/PickRoomWindow/PickRoomWindowViewModel.cs
@@ -25,7 +25,7 @@ public ObservableCollection FilteredRooms
var models = AppKernel.MapDatabase.Current.Map.Rooms;
if (!string.IsNullOrEmpty(RoomsFilter))
{
- HellMapManager.Utils.FilterUtil.SplitFilter(RoomsFilter).ForEach(filter =>
+ HellMapManager.Helpers.FilterHelper.ParseKeywords(RoomsFilter).ForEach(filter =>
{
models = models.FindAll(r => r.Filter(filter));
});
diff --git a/code/TestProject/APIServerTest.cs b/code/TestProject/APIServerTest.cs
index f80953d..eed4c09 100644
--- a/code/TestProject/APIServerTest.cs
+++ b/code/TestProject/APIServerTest.cs
@@ -37,7 +37,7 @@ public async Task TestVersion()
Assert.Equal(MapDatabase.Version, mapDatabase.APIVersion());
var resp = await Post($"http://localhost:{server.Port}" + "/api/version", typeof(string), "");
var result = JsonSerializer.Deserialize(resp, typeof(int), APIJsonSerializerContext.Default) as int?;
- Assert.Equal(1003, result);
+ Assert.Equal(1004, result);
await server.Stop();
}
[Fact]
diff --git a/code/TestProject/FilterHelperTest.cs b/code/TestProject/FilterHelperTest.cs
new file mode 100644
index 0000000..e1353bc
--- /dev/null
+++ b/code/TestProject/FilterHelperTest.cs
@@ -0,0 +1,86 @@
+namespace TestProject;
+
+using HellMapManager.Helpers;
+using HellMapManager.Models;
+public class FilterHelperTest
+{
+ [Fact]
+ public void TestKeyword()
+ {
+ var keyword = new FilterKeyword
+ {
+ Type = FilterKeywordType.Key,
+ Value = "abc",
+ PartialMatch = false,
+ };
+ Assert.True(keyword.Match("abc", FilterKeywordType.Key));
+ Assert.False(keyword.Match("abcd", FilterKeywordType.Key));
+ Assert.False(keyword.Match("abc", FilterKeywordType.Type));
+ keyword.Type = FilterKeywordType.Any;
+ Assert.True(keyword.Match("abc", FilterKeywordType.Key));
+ Assert.False(keyword.Match("abcd", FilterKeywordType.Key));
+ keyword.PartialMatch = true;
+ Assert.True(keyword.Match("abcd", FilterKeywordType.Key));
+ keyword.Not = true;
+ Assert.False(keyword.Match("abcd", FilterKeywordType.Key));
+ keyword.PartialMatch = false;
+ Assert.True(keyword.Match("abcd", FilterKeywordType.Key));
+ Assert.False(keyword.Match("abc", FilterKeywordType.Key));
+ }
+ [Fact]
+ public void TestFilter()
+ {
+ //分词
+ var input = "abc";
+ var result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { "abc" }, result.ConvertAll(x => x.Value));
+ input = "";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { }, result.ConvertAll(x => x.Value));
+ input = " ";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { }, result.ConvertAll(x => x.Value));
+ input = "abc,def";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { "abc", "def" }, result.ConvertAll(x => x.Value));
+ input = "abc ,, , def,h ij ";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { "abc", "def", "h ij" }, result.ConvertAll(x => x.Value));
+
+ //转义
+ input = @"abc\,def";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { "abc,def" }, result.ConvertAll(x => x.Value));
+ input = @"abc\ \,, ,\ def,h ij\ ";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { "abc ,", " def", "h ij " }, result.ConvertAll(x => x.Value));
+ input = @"\\\n\=\,\ \!";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(new List { "\\\n=, !" }, result.ConvertAll(x => x.Value));
+ input = @"search";
+ var keyword = FilterHelper.ParseKeyword(input);
+ Assert.Equal(FilterKeywordType.Any, keyword.Type);
+ Assert.Equal("search", keyword.Value);
+ Assert.True(keyword.PartialMatch);
+ Assert.False(keyword.Not);
+ input = @"!name=example, notexists=!=value , search";
+ result = FilterHelper.ParseKeywords(input);
+ Assert.Equal(3, result.Count);
+ keyword = result[0];
+ Assert.Equal(FilterKeywordType.Name, keyword.Type);
+ Assert.Equal("example", keyword.Value);
+ Assert.False(keyword.PartialMatch);
+ Assert.True(keyword.Not);
+ keyword = result[1];
+ Assert.Equal(FilterKeywordType.Wrong, keyword.Type);
+ Assert.Equal("!=value", keyword.Value);
+ Assert.False(keyword.PartialMatch);
+ Assert.False(keyword.Not);
+ keyword = result[2];
+ Assert.Equal(FilterKeywordType.Any, keyword.Type);
+ Assert.Equal("search", keyword.Value);
+ Assert.True(keyword.PartialMatch);
+ Assert.False(keyword.Not);
+
+ }
+}
\ No newline at end of file
diff --git a/code/TestProject/FilterUtilTest.cs b/code/TestProject/FilterUtilTest.cs
deleted file mode 100644
index d684a3d..0000000
--- a/code/TestProject/FilterUtilTest.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace TestProject;
-
-using HellMapManager.Utils;
-
-public class FilterUtilTest
-{
- [Fact]
- public void TestFilter()
- {
- var keywords = "abc";
- var result = FilterUtil.SplitFilter(keywords);
- Assert.Equal(new List { "abc" }, result);
- keywords = "";
- result = FilterUtil.SplitFilter(keywords);
- Assert.Equal(new List { }, result);
- keywords = " ";
- result = FilterUtil.SplitFilter(keywords);
- Assert.Equal(new List { }, result);
- keywords = "abc,def";
- result = FilterUtil.SplitFilter(keywords);
- Assert.Equal(new List { "abc", "def" }, result);
- keywords = "abc ,, , def,h ij";
- result = FilterUtil.SplitFilter(keywords);
- Assert.Equal(new List { "abc", "def", "h ij" }, result);
- }
-}
\ No newline at end of file
diff --git a/code/TestProject/MapTest.cs b/code/TestProject/MapTest.cs
index cca7efc..8243680 100644
--- a/code/TestProject/MapTest.cs
+++ b/code/TestProject/MapTest.cs
@@ -517,7 +517,7 @@ public void TestMap()
rooms = mapDatabase.APIDilate(["key6"], 1, ctx, opt);
rooms.Sort();
Assert.Equal("key1;key3;key6", string.Join(";", rooms));
- opt.WithCommandWhitelist(["1>2","1>3","2>1","2>3","3>1","3>3","3>4","4>3","4>5","5>3","6>3","A>6C"]);
+ opt.WithCommandWhitelist(["1>2", "1>3", "2>1", "2>3", "3>1", "3>3", "3>4", "4>3", "4>5", "5>3", "6>3", "A>6C"]);
exit = mapDatabase.APITrackExit("key6", "A>1", ctx, opt);
Assert.Equal("", exit);
qr = mapDatabase.APIQueryPathAll("key6", ["key1", "key5"], ctx, opt);
@@ -534,4 +534,70 @@ public void TestMap()
Assert.Equal("key3;key6", string.Join(";", rooms));
}
+ [Fact]
+ public void TestNullableAPI()
+ {
+ var mapDatabase = new MapDatabase();
+ var ctx = new Context();
+ var opt = new MapperOptions();
+ var qr = mapDatabase.APIQueryPathAll("key1", ["key2"], ctx, opt);
+ Assert.Null(qr);
+ qr = mapDatabase.APIQueryPathAny(["key1"], ["key2"], ctx, opt);
+ Assert.Null(qr);
+ qr = mapDatabase.APIQueryPathOrdered("key1", ["key2"], ctx, opt);
+ Assert.Null(qr);
+ var rooms = mapDatabase.APIDilate(["key1", "key6"], 2, ctx, opt);
+ Assert.Empty(rooms);
+ var exit = mapDatabase.APITrackExit("key1", "1>2", ctx, opt);
+ Assert.Equal("", exit);
+ qr = mapDatabase.APIQueryPathAll("key1", ["key2"], null, null);
+ Assert.Null(qr);
+ qr = mapDatabase.APIQueryPathAny(["key1"], ["key2"], null, null);
+ Assert.Null(qr);
+ qr = mapDatabase.APIQueryPathOrdered("key1", ["key2"], null, null);
+ Assert.Null(qr);
+ rooms = mapDatabase.APIDilate(["key1", "key6"], 2, null, null);
+ Assert.Empty(rooms);
+ exit = mapDatabase.APITrackExit("key1", "1>2", null, null);
+ Assert.Equal("", exit);
+ InitMapDatabase(mapDatabase);
+ qr = mapDatabase.APIQueryPathAll("key1", ["key2"], ctx, opt);
+ Assert.NotNull(qr);
+ Assert.Equal("1>2", Step.JoinCommands(";", qr.Steps));
+ qr = mapDatabase.APIQueryPathAny(["key1"], ["key2"], ctx, opt);
+ Assert.NotNull(qr);
+ Assert.Equal("1>2", Step.JoinCommands(";", qr.Steps));
+ qr = mapDatabase.APIQueryPathOrdered("key1", ["key2"], ctx, opt);
+ Assert.NotNull(qr);
+ Assert.Equal("1>2", Step.JoinCommands(";", qr.Steps));
+ rooms = mapDatabase.APIDilate(["key1", "key6"], 2, ctx, opt);
+ rooms.Sort();
+ Assert.Equal("key1;key2;key3;key4", string.Join(";", rooms));
+ exit = mapDatabase.APITrackExit("key1", "1>2", ctx, opt);
+ Assert.Equal("key2", exit);
+ exit = mapDatabase.APITrackExit("notfound", "1>2", ctx, opt);
+ Assert.Equal("", exit);
+ exit = mapDatabase.APITrackExit("key1", "notfound", ctx, opt);
+ Assert.Equal("", exit);
+
+ qr = mapDatabase.APIQueryPathAll("key1", ["key2"], null, null);
+ Assert.NotNull(qr);
+ Assert.Equal("1>2", Step.JoinCommands(";", qr.Steps));
+ qr = mapDatabase.APIQueryPathAny(["key1"], ["key2"], null, null);
+ Assert.NotNull(qr);
+ Assert.Equal("1>2", Step.JoinCommands(";", qr.Steps));
+ qr = mapDatabase.APIQueryPathOrdered("key1", ["key2"], null, null);
+ Assert.NotNull(qr);
+ Assert.Equal("1>2", Step.JoinCommands(";", qr.Steps));
+ rooms = mapDatabase.APIDilate(["key1", "key6"], 2, null, null);
+ rooms.Sort();
+ Assert.Equal("key1;key2;key3;key4", string.Join(";", rooms));
+ exit = mapDatabase.APITrackExit("key1", "1>2", null, null);
+ Assert.Equal("key2", exit);
+ exit = mapDatabase.APITrackExit("notfound", "1>2", null, null);
+ Assert.Equal("", exit);
+ exit = mapDatabase.APITrackExit("key1", "notfound", null, null);
+ Assert.Equal("", exit);
+
+ }
}
\ No newline at end of file
diff --git a/code/TestProject/ModelTest.cs b/code/TestProject/ModelTest.cs
index 8f4d3fd..e268d5a 100644
--- a/code/TestProject/ModelTest.cs
+++ b/code/TestProject/ModelTest.cs
@@ -1,3 +1,4 @@
+using HellMapManager.Helpers;
using HellMapManager.Models;
namespace TestProject;
@@ -363,16 +364,34 @@ public void TestRoom()
Assert.Equal("", room.GetData("notfound"));
Room room2;
- Assert.False(room.Filter("unknow"));
- Assert.True(room.Filter("key"));
- Assert.True(room.Filter("name"));
- Assert.True(room.Filter("group"));
- Assert.True(room.Filter("tag1"));
- Assert.True(room.Filter("dkey1"));
- Assert.True(room.Filter("dval2"));
- Assert.True(room.Filter("command1"));
- Assert.True(room.Filter("to2"));
- Assert.True(room.Filter("on1"));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("unknow")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("key=ke")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("name")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("name=nam")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("name=name")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("group=gro")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("tag1")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("tag=tag")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("tag=tag1")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("dkey1")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("misc=dkey")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("misc=dkey1")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("dval2")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("misc=dval")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("misc=dval2")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("command1")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("command=command")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("command=command1")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("to2")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("to=to")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("to=to2")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("on1")));
+ Assert.False(room.Filter(FilterHelper.ParseKeyword("tag=con")));
+ Assert.True(room.Filter(FilterHelper.ParseKeyword("tag=con1")));
Assert.Equal(2, room.ExitsCount);
Assert.Equal("tag1,tag2", room.AllTags);
@@ -536,12 +555,22 @@ public void TestMarker()
};
- Assert.True(marker.Filter("key"));
- Assert.True(marker.Filter("value"));
- Assert.True(marker.Filter("group"));
- Assert.True(marker.Filter("desc"));
- Assert.True(marker.Filter("message"));
- Assert.False(marker.Filter("notfound"));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.False(marker.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("value")));
+ Assert.False(marker.Filter(FilterHelper.ParseKeyword("value=value")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("value=value1")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.False(marker.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.False(marker.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("message")));
+ Assert.False(marker.Filter(FilterHelper.ParseKeyword("message=message")));
+ Assert.True(marker.Filter(FilterHelper.ParseKeyword("message=message1")));
+ Assert.False(marker.Filter(FilterHelper.ParseKeyword("notfound")));
Marker marker2;
marker2 = marker.Clone();
Assert.True(marker2.Validated());
@@ -583,12 +612,22 @@ public void TestRoute()
};
Assert.Equal("rid1a\nrid1b", route.RoomsList);
- Assert.True(route.Filter("key"));
- Assert.True(route.Filter("rid1"));
- Assert.True(route.Filter("desc"));
- Assert.True(route.Filter("group"));
- Assert.True(route.Filter("message"));
- Assert.False(route.Filter("NotFound"));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.False(route.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("rid1")));
+ Assert.False(route.Filter(FilterHelper.ParseKeyword("to=rid")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("to=rid1a")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.False(route.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.False(route.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("message")));
+ Assert.False(route.Filter(FilterHelper.ParseKeyword("message=message")));
+ Assert.True(route.Filter(FilterHelper.ParseKeyword("message=message1")));
+ Assert.False(route.Filter(FilterHelper.ParseKeyword("NotFound")));
Assert.Equal("rid1a;rid1b", route.AllRooms);
Assert.Equal(2, route.RoomsCount);
@@ -632,12 +671,22 @@ public void TestTrace()
Message = "message1",
};
Assert.Equal("rid1\nrid2", trace.LocationList);
- Assert.True(trace.Filter("key"));
- Assert.True(trace.Filter("rid"));
- Assert.True(trace.Filter("desc"));
- Assert.True(trace.Filter("group"));
- Assert.True(trace.Filter("message"));
- Assert.False(trace.Filter("NotFound"));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.False(trace.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("rid")));
+ Assert.False(trace.Filter(FilterHelper.ParseKeyword("to=rid")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("to=rid1")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.False(trace.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.False(trace.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("message")));
+ Assert.False(trace.Filter(FilterHelper.ParseKeyword("message=message")));
+ Assert.True(trace.Filter(FilterHelper.ParseKeyword("message=message1")));
+ Assert.False(trace.Filter(FilterHelper.ParseKeyword("NotFound")));
Assert.Equal(2, trace.LocationsCount);
@@ -686,13 +735,25 @@ public void TestRegion()
Message = "message1",
Items = [new RegionItem(RegionItemType.Room, "room1", false), new RegionItem(RegionItemType.Zone, "zone1", true)]
};
- Assert.True(region.Filter("key"));
- Assert.True(region.Filter("room"));
- Assert.True(region.Filter("zone"));
- Assert.True(region.Filter("desc"));
- Assert.True(region.Filter("group"));
- Assert.True(region.Filter("message"));
- Assert.False(region.Filter("NotFound"));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("room")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("to=room")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("to=room1")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("zone")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("to=zone")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("to=zone1")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("message")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("message=message")));
+ Assert.True(region.Filter(FilterHelper.ParseKeyword("message=message1")));
+ Assert.False(region.Filter(FilterHelper.ParseKeyword("NotFound")));
Assert.Equal(2, region.ItemsCount);
Region region2;
@@ -771,12 +832,22 @@ public void TestLandmark()
Group = "group1",
Desc = "desc1"
};
- Assert.True(lm.Filter("key"));
- Assert.True(lm.Filter("type"));
- Assert.True(lm.Filter("value"));
- Assert.True(lm.Filter("group"));
- Assert.True(lm.Filter("desc"));
- Assert.False(lm.Filter("NotFound"));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.False(lm.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("type")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("type=type1")));
+ Assert.False(lm.Filter(FilterHelper.ParseKeyword("type=type")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("value")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("value=value1")));
+ Assert.False(lm.Filter(FilterHelper.ParseKeyword("value=value")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.False(lm.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.True(lm.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.False(lm.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.False(lm.Filter(FilterHelper.ParseKeyword("NotFound")));
Landmark lm2;
lm2 = lm.Clone();
@@ -822,14 +893,28 @@ public void TestShortcut()
RoomConditions = [new ValueCondition("con1", 1, false), new ValueCondition("con2", 1, true)],
Conditions = [new ValueCondition("con3", 1, false), new ValueCondition("con4", 1, true)]
};
- Assert.True(sc.Filter("key"));
- Assert.True(sc.Filter("command"));
- Assert.True(sc.Filter("to"));
- Assert.True(sc.Filter("group"));
- Assert.True(sc.Filter("desc"));
- Assert.True(sc.Filter("on1"));
- Assert.True(sc.Filter("on3"));
- Assert.False(sc.Filter("NotFound"));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("command")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("command=command1")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("command=command")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("to")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("to=to1")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("to=to")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("on1")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("tag=con1")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("tag=con")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("on3")));
+ Assert.True(sc.Filter(FilterHelper.ParseKeyword("tag=con3")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("tag=con")));
+ Assert.False(sc.Filter(FilterHelper.ParseKeyword("NotFound")));
Shortcut sc2;
sc2 = sc.Clone();
Assert.True(sc.Equal(sc2));
@@ -885,11 +970,19 @@ public void TestVariable()
Group = "group1",
Desc = "desc1"
};
- Assert.True(var1.Filter("key"));
- Assert.True(var1.Filter("value"));
- Assert.True(var1.Filter("group"));
- Assert.True(var1.Filter("desc"));
- Assert.False(var1.Filter("NotFound"));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.False(var1.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("value")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("value=value1")));
+ Assert.False(var1.Filter(FilterHelper.ParseKeyword("value=value")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.False(var1.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("desc")));
+ Assert.True(var1.Filter(FilterHelper.ParseKeyword("desc=desc1")));
+ Assert.False(var1.Filter(FilterHelper.ParseKeyword("desc=desc")));
+ Assert.False(var1.Filter(FilterHelper.ParseKeyword("NotFound")));
Variable var2;
var2 = var1.Clone();
@@ -922,11 +1015,19 @@ public void TestSnapshot()
Group = "group1",
Timestamp = 1234567890
};
- Assert.True(snapshot.Filter("key"));
- Assert.True(snapshot.Filter("type"));
- Assert.True(snapshot.Filter("value"));
- Assert.True(snapshot.Filter("group"));
- Assert.False(snapshot.Filter("NotFound"));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("key")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("key=key1")));
+ Assert.False(snapshot.Filter(FilterHelper.ParseKeyword("key=key")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("type")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("type=type1")));
+ Assert.False(snapshot.Filter(FilterHelper.ParseKeyword("type=type")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("value")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("value=value1")));
+ Assert.False(snapshot.Filter(FilterHelper.ParseKeyword("value=value")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("group")));
+ Assert.True(snapshot.Filter(FilterHelper.ParseKeyword("group=group1")));
+ Assert.False(snapshot.Filter(FilterHelper.ParseKeyword("group=group")));
+ Assert.False(snapshot.Filter(FilterHelper.ParseKeyword("NotFound")));
Assert.True(snapshot.Validated());
Snapshot snapshot2;
@@ -1805,7 +1906,7 @@ public void TestSnapshotSearch()
ss.Keywords = ["value3", "value4", "value"];
ss.Any = false;
Assert.False(ss.Validate(snapshot));
- ss.MaxNoise=2;
+ ss.MaxNoise = 2;
Assert.True(ss.Validate(snapshot));
}
[Fact]
diff --git a/doc/api/history.md b/doc/api/history.md
index 112d2e9..bd98fd4 100644
--- a/doc/api/history.md
+++ b/doc/api/history.md
@@ -1,5 +1,10 @@
# API变更记录
+
+## Version 1004
+
+与hellmapmanager.ts的代码同步,对接口无影响。
+
## Version 1003
* SearchSnapshots 接口加入MaxNoise
diff --git a/doc/tutorials/manual.md b/doc/tutorials/manual.md
index 6a36c57..c9d7290 100644
--- a/doc/tutorials/manual.md
+++ b/doc/tutorials/manual.md
@@ -24,10 +24,10 @@
* 名称: 大镇街
* 分组: 佛山
* 出口:
- * 目标:???? 指令 n
- * 目标:???? 指令 e
- * 目标:???? 指令 s
- * 目标:???? 指令 e
+ * 目标:? 指令 n
+ * 目标:? 指令 e
+ * 目标:? 指令 s
+ * 目标:? 指令 e
* 描述: Landmark 大镇街
结果如图
@@ -39,7 +39,7 @@
* 主键设置为不带业务数据的值。为了防止编码问题,建议使用字母数字的组合。
* 名称一般就是房间名,便于管理。
* 分组就是房间的地区。
-* 出口 的目标由于都不知道对应房间的信息,先都设为????,便于之后查遗补缺。
+* 出口 的目标由于都不知道对应房间的信息,先都设为?,便于之后查遗补缺。
* 描述是觉得这个房间可能可以用来定位,先标记下。
添加结束后,应该在房间列表中出现一个单独的房间,如下图
@@ -70,7 +70,7 @@
* 名称:北门
* 分组:佛山
* 出口:
- * 目标 ???? 指令 n
+ * 目标 ? 指令 n
* 目标 foshan-dazhenjie 指令 s
很明显,由于我们知道 s 对应的是之前的房间,所以,可以直接在新建出口窗口里点击 目标右侧的 选取按钮,在选取窗口里选择 房间(或者你手输/复制粘贴也可以):
@@ -89,11 +89,11 @@
回到大镇街,点击 左下方的编辑按钮,编辑n那个出口,指向北门
-保存后,会发现关系地图里两个地图 有了双向箭头
+保存后,会发现关系地图里两个房间有了双向箭头

-这时候双击那个不是????到foshan-beimen的n出口,或者双击地图上的 那个北门\(foshan-beimen\)/佛山的房间,关系地图就跳到北门了。
+这时候双击那个不是?到foshan-beimen的n出口,或者双击地图上的 那个北门\(foshan-beimen\)/佛山的房间,关系地图就跳到北门了。
这时候我们发现,北门也变成双向连接了。
@@ -101,7 +101,7 @@
很好,干得好,下一步,就是继续把这个区域的房间都登记进去了。
-这时候,可不用急着把所有出口都维护正确,这是下一步的工作。
+这时候,并不用急着把所有出口都维护正确,这是下一步的工作。
## 全面检查出口关系
@@ -115,19 +115,19 @@
这时候我们开始继续了。
-还记得我们之前用了很多????的出口吗?
+还记得我们之前用了很多?的出口吗?
然我们搜索下
```
-佛山,????
+佛山,to=?
```
用逗号分割2个关键字,就能找到佛山分组下所有未更新的出口了

-嗯,发现明显有问题,感觉把这些出口的修复正确。
+嗯,发现明显有问题,赶紧把这些出口修复正确。
## 更新定位
@@ -194,4 +194,12 @@ curl -X POST -d '{"From":["foshan-dazhenjie"],"Target":["foshan-linjiandao7"]}'
各种描述,地图,npc等,可以抓取快照。
-手动绘制的部分只是主干,通过代码同步更新的部分才是逐渐生产出来的血肉。
\ No newline at end of file
+手动绘制的部分只是主干,通过代码同步更新的部分才是逐渐生产出来的血肉。
+
+## 修订记录
+
+由于mapper加入了高级关键字搜索功能。
+
+原教程中的????目标改为?目标
+
+搜索的 佛山,???? 改为 佛山,to=?
\ No newline at end of file