Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Pathfinder Plugin #32

Open
wants to merge 52 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4453a6a
created MineSharp.Pathfinder
psu-de Jan 3, 2024
0a936a9
created MineSharp.Pathfinder
psu-de Jan 3, 2024
b4b668d
Merge branch 'feature/pathfinder' of github.com:psu-de/MineSharp into…
psu-de Jan 3, 2024
67f8ca5
Merge branch 'main' into feature/pathfinder
psu-de Jan 14, 2024
cd51d79
Merge branch 'main' into feature/pathfinder
psu-de Jan 15, 2024
cf6198d
Merge branch 'main' into feature/pathfinder
psu-de Jan 16, 2024
b78fdd8
improved movement
psu-de Jan 16, 2024
cbe0094
Merge branch 'main' into feature/pathfinder
psu-de Jan 16, 2024
a6c95a6
Merge branch 'main' into feature/pathfinder
psu-de Jan 19, 2024
3221c2e
continue work on pathfinder
psu-de Jan 24, 2024
18f2b5b
Merge branch 'main' into feature/pathfinder
psu-de Jan 24, 2024
b2675c0
Merge branch 'main' into feature/pathfinder
psu-de Jan 24, 2024
5597e03
WIP Pathfinder
psu-de Jan 25, 2024
1554d1d
Finished FallDownMove
psu-de Jan 26, 2024
c9487e9
Merge branch 'main' into feature/pathfinder
psu-de Jan 26, 2024
9686fe5
merge master in feature/pathfinder
psu-de Feb 23, 2024
389cdfa
update pathfinder
psu-de Feb 23, 2024
8be84af
removed test project from solution
psu-de Feb 23, 2024
a9b339e
fix AABB intersects() method
psu-de Feb 24, 2024
ff74f76
improved DirectMove.cs and JumpUpMove.cs
psu-de Feb 24, 2024
b0c5809
Merge branch 'feature/pathfinder' of github.com:psu-de/MineSharp into…
psu-de Feb 24, 2024
51422e8
Merge branch 'feature/pathfinder' of github.com:psu-de/MineSharp into…
psu-de Feb 24, 2024
5f4e30a
improved moves
psu-de Feb 25, 2024
a0573a1
Update DirectMove.cs
psu-de Feb 25, 2024
a1be2c5
improved FallDownMove.cs
psu-de Feb 26, 2024
e9a9a49
Update MovementUtils.cs
psu-de Feb 26, 2024
2400699
added JumpOneBlock move
psu-de Feb 27, 2024
81cd6e8
fixed AStar not updating blocks
psu-de Mar 8, 2024
73eb423
Update PlayerPhysics.cs
psu-de Mar 8, 2024
a8bbcab
fixed AABB
psu-de Mar 8, 2024
22e7046
updated moves, way more reliable
psu-de Mar 8, 2024
c1baa01
improved AStar performance a lot
psu-de Mar 8, 2024
8d2c1b5
Update JumpOneBlock.cs move cost
psu-de Mar 9, 2024
e25c1a9
Made Path node internal
psu-de Mar 9, 2024
6ef580e
restructured and improved moves
psu-de Mar 10, 2024
90eda97
Merge branch 'main' into feature/pathfinder
psu-de Mar 12, 2024
1a29767
updated pathfinder to use Geometry namespace
psu-de Mar 12, 2024
f982b90
Update Program.cs
psu-de Mar 13, 2024
035d31b
Starting positions of path nodes were incorrect
psu-de Mar 13, 2024
ae60fb4
removed MinecraftData from AStar constructor
psu-de Mar 13, 2024
500220d
renamed helper methods to clarify, added MoveWentWrongException
psu-de Mar 13, 2024
b7ef677
trying to clean up a little
psu-de Mar 13, 2024
a529e03
trying to abstract jump moves into a single class
psu-de Mar 15, 2024
9ff96b5
i really have to add immutable vectors, but jumping 1-3 blocks works now
psu-de Mar 20, 2024
948ff08
jump moves work great now
psu-de Mar 22, 2024
c9ca12b
Merge branch 'main' into feature/pathfinder
psu-de Mar 22, 2024
0b3fa77
Update Move.cs
psu-de Mar 22, 2024
aea5c0c
Merge branch 'main' into feature/pathfinder
psu-de Mar 27, 2024
72acc76
Merge branch 'main' into feature/pathfinder
psu-de Mar 27, 2024
3efa7b9
update pathfinder to use the new mutable types
psu-de Mar 27, 2024
f6c1fdf
merge branch main into feature/pathfinder
psu-de Jul 27, 2024
18dc13c
Merge branch 'main' into feature/pathfinder
psu-de Jul 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,22 @@
<LangVersion>12</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\MineSharp.Bot\MineSharp.Bot.csproj"/>
<PackageReference Include="Humanizer" Version="2.14.1"/>
<PackageReference Include="Spectre.Console" Version="0.47.1-preview.0.7"/>
</ItemGroup>

<PropertyGroup>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
<LangVersion>12</LangVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MineSharp.Bot\MineSharp.Bot.csproj" />
<ProjectReference Include="..\Plugins\MineSharp.Pathfinder\MineSharp.Pathfinder.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Humanizer" Version="2.14.1"/>
<PackageReference Include="Spectre.Console" Version="0.47.1-preview.0.7"/>
Expand Down
72 changes: 66 additions & 6 deletions MineSharp.Bot.IntegrationTests/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,67 @@
using MineSharp.Bot.IntegrationTests.Tests;
using MineSharp.Bot;
using MineSharp.Bot.IntegrationTests.Tests;
using MineSharp.Bot.Plugins;
using MineSharp.Core.Common;
using MineSharp.Core.Common.Blocks;
using MineSharp.Core.Common.Effects;
using MineSharp.Core.Common.Entities;
using MineSharp.Core.Geometry;
using MineSharp.Data;
using MineSharp.Pathfinder;
using MineSharp.Physics;
using MineSharp.Physics.Input;
using MineSharp.World;
using MineSharp.World.Chunks;

await PlayerTests.RunAll();
await WindowTests.RunAll();
await WorldTests.RunAll();
await CraftingTests.RunAll();
await PhysicsTests.RunAll();
MineSharpBot.EnableDebugLogs(true);

var bot = await new BotBuilder()
.Host("localhost")
.OfflineSession("MineSharpBot")
.WithPlugin<Pathfinder>()
.WithPlugin<AutoRespawn>()
.AutoConnect()
.CreateAsync();

var chat = bot.GetPlugin<ChatPlugin>();
var physics = bot.GetPlugin<PhysicsPlugin>();
var pathfinder = bot.GetPlugin<Pathfinder>();
var player = bot.GetPlugin<PlayerPlugin>();
var world = bot.GetPlugin<WorldPlugin>();

if (!player.IsAlive!.Value)
await player.Respawn();

chat.OnChatMessageReceived += async (sender, playerUuid, message, position) =>
{
Console.WriteLine(message.GetMessage(bot.Data));
var splits = message.GetMessage(bot.Data).Split(' ').Skip(1).ToArray();

if (splits.Length != 3)
return;

var ints = splits.Select(x => Convert.ToInt32(x)).ToArray();
await pathfinder.Goto(new Position(ints[0], ints[1], ints[2]));
};

while (true)
{
var input = Console.ReadLine();

if (string.IsNullOrEmpty(input))
{
continue;
}

await chat.SendChat(input);
}

Console.ReadKey();
//
// return;
//
// await PlayerTests.RunAll();
// await WindowTests.RunAll();
// await WorldTests.RunAll();
// await CraftingTests.RunAll();
// await PhysicsTests.RunAll();
91 changes: 46 additions & 45 deletions MineSharp.Bot.IntegrationTests/TestServer/server.properties
Original file line number Diff line number Diff line change
@@ -1,59 +1,60 @@
#Minecraft server properties
#Sun Dec 31 14:58:40 UTC 2023
enable-jmx-monitoring=false
level-seed=
rcon.port=25575
#Sat Jul 27 19:16:19 UTC 2024
allow-flight=false
allow-nether=true
broadcast-console-to-ops=true
broadcast-rcon-to-ops=true
difficulty=easy
enable-command-block=true
gamemode=survival
enable-jmx-monitoring=false
enable-query=false
generator-settings={"lakes"\:false,"features"\:false,"layers"\:[{"block"\:"minecraft\:air","height"\:1}],"structures"\:{"structures"\:{}}}
enable-rcon=true
enable-status=true
enforce-secure-profile=true
level-name=world
motd=A Minecraft Server
query.port=25565
pvp=true
enforce-whitelist=false
entity-broadcast-range-percentage=100
force-gamemode=false
function-permission-level=2
gamemode=survival
generate-structures=true
generator-settings={"lakes"\:false,"features"\:false,"layers"\:[{"block"\:"minecraft\:air","height"\:1}],"structures"\:{"structures"\:{}}}
hardcore=false
hide-online-players=false
initial-disabled-packs=
initial-enabled-packs=vanilla
level-name=world
level-seed=
level-type=minecraft\:flat
log-ips=true
max-chained-neighbor-updates=1000000
difficulty=easy
network-compression-threshold=256
max-tick-time=60000
require-resource-pack=false
max-players=20
use-native-transport=true
enable-status=true
max-tick-time=60000
max-world-size=29999984
motd=A Minecraft Server
network-compression-threshold=256
online-mode=false
allow-flight=false
initial-disabled-packs=
broadcast-rcon-to-ops=true
view-distance=10
resource-pack-prompt=
server-ip=
allow-nether=true
server-port=25565
enable-rcon=true
sync-chunk-writes=true
op-permission-level=4
player-idle-timeout=0
prevent-proxy-connections=false
hide-online-players=false
previews-chat=false
pvp=true
query.port=25565
rate-limit=0
rcon.password=334112116bfed9b372e17e2a
rcon.port=25575
require-resource-pack=false
resource-pack=
entity-broadcast-range-percentage=100
resource-pack-prompt=
resource-pack-sha1=
server-ip=
server-port=25565
simulation-distance=10
player-idle-timeout=0
rcon.password=fc05569cfd3a32bb829d3fd8
force-gamemode=false
rate-limit=0
hardcore=false
white-list=false
broadcast-console-to-ops=true
spawn-npcs=true
previews-chat=false
spawn-animals=true
function-permission-level=2
initial-enabled-packs=vanilla
level-type=MINECRAFT\:FLAT
text-filtering-config=
spawn-monsters=true
enforce-whitelist=false
resource-pack-sha1=
spawn-monsters=false
spawn-npcs=true
spawn-protection=16
max-world-size=29999984
sync-chunk-writes=true
text-filtering-config=
use-native-transport=true
view-distance=10
white-list=false
Binary file not shown.
Binary file modified MineSharp.Bot.IntegrationTests/TestServer/world/level.dat
Binary file not shown.
Binary file modified MineSharp.Bot.IntegrationTests/TestServer/world/region/r.-1.-1.mca
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified MineSharp.Bot.IntegrationTests/TestServer/world/region/r.0.0.mca
100644 → 100755
Binary file not shown.
12 changes: 2 additions & 10 deletions MineSharp.Bot/Plugins/PhysicsPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public override Task OnTick()
{
Logger.Error(e.ToString());
}

tickCounter++;
});

Expand All @@ -277,15 +277,7 @@ public override Task OnTick()

private async Task UpdateServerPositionIfNeeded()
{
if (Math.Abs(lastPlayerState.X - self!.Entity!.Position.X) > PositionThreshold
|| Math.Abs(lastPlayerState.Y - self!.Entity!.Position.Y) > PositionThreshold
|| Math.Abs(lastPlayerState.Z - self!.Entity!.Position.Z) > PositionThreshold
|| Math.Abs(lastPlayerState.Yaw - self!.Entity!.Yaw) > PositionThreshold
|| Math.Abs(lastPlayerState.Pitch - self!.Entity!.Pitch) > PositionThreshold
|| lastPlayerState.OnGround != self!.Entity!.IsOnGround)
{
await UpdateServerPos();
}
await UpdateServerPos();
}

private async Task UpdateServerPos()
Expand Down
14 changes: 8 additions & 6 deletions MineSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MineSharp.SourceGenerator",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MineSharp.ChatComponent", "Components\MineSharp.ChatComponent\MineSharp.ChatComponent.csproj", "{6CFF9878-00D1-4FE3-9146-B6B2EE746A0C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MineSharp.Data.Tests", "Data\MineSharp.Data.Tests\MineSharp.Data.Tests.csproj", "{1B36A1EF-2A07-4606-B748-B6E708C697E3}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{4B55DF69-1176-4CB6-878C-5EE8A14134B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MineSharp.Pathfinder", "Plugins\MineSharp.Pathfinder\MineSharp.Pathfinder.csproj", "{043D339E-C2F8-4243-9B0B-4F7C689BCA39}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -98,10 +100,10 @@ Global
{6CFF9878-00D1-4FE3-9146-B6B2EE746A0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CFF9878-00D1-4FE3-9146-B6B2EE746A0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CFF9878-00D1-4FE3-9146-B6B2EE746A0C}.Release|Any CPU.Build.0 = Release|Any CPU
{1B36A1EF-2A07-4606-B748-B6E708C697E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B36A1EF-2A07-4606-B748-B6E708C697E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B36A1EF-2A07-4606-B748-B6E708C697E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B36A1EF-2A07-4606-B748-B6E708C697E3}.Release|Any CPU.Build.0 = Release|Any CPU
{043D339E-C2F8-4243-9B0B-4F7C689BCA39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{043D339E-C2F8-4243-9B0B-4F7C689BCA39}.Debug|Any CPU.Build.0 = Debug|Any CPU
{043D339E-C2F8-4243-9B0B-4F7C689BCA39}.Release|Any CPU.ActiveCfg = Release|Any CPU
{043D339E-C2F8-4243-9B0B-4F7C689BCA39}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{63B60BB4-DB86-423A-9585-82FD060089F2} = {CAB43D13-C4AC-4D69-AB04-ECF9B514115D}
Expand All @@ -116,6 +118,6 @@ Global
{D6F1AE8D-ACA3-4E2A-A103-13BE9579A70D} = {7441DE2E-3B7A-42F5-B3FC-FD25FCF46B8F}
{A1AC37F2-6209-473B-A787-0F1601998BEB} = {7441DE2E-3B7A-42F5-B3FC-FD25FCF46B8F}
{6CFF9878-00D1-4FE3-9146-B6B2EE746A0C} = {CAB43D13-C4AC-4D69-AB04-ECF9B514115D}
{1B36A1EF-2A07-4606-B748-B6E708C697E3} = {7441DE2E-3B7A-42F5-B3FC-FD25FCF46B8F}
{043D339E-C2F8-4243-9B0B-4F7C689BCA39} = {4B55DF69-1176-4CB6-878C-5EE8A14134B8}
EndGlobalSection
EndGlobal
128 changes: 128 additions & 0 deletions Plugins/MineSharp.Pathfinder/Algorithm/AStar.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System.Diagnostics;
using MineSharp.Core.Common;
using MineSharp.Core.Geometry;
using MineSharp.Data;
using MineSharp.Pathfinder.Exceptions;
using MineSharp.Pathfinder.Moves;
using MineSharp.World;
using NLog;
using Priority_Queue;

namespace MineSharp.Pathfinder.Algorithm;

public class AStar(IWorld world, Movements movements, MinecraftData data)

Check warning on line 13 in Plugins/MineSharp.Pathfinder/Algorithm/AStar.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'AStar'

Check warning on line 13 in Plugins/MineSharp.Pathfinder/Algorithm/AStar.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'AStar.AStar(IWorld, Movements, MinecraftData)'
{
public Movements Movements = movements;

Check warning on line 15 in Plugins/MineSharp.Pathfinder/Algorithm/AStar.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'AStar.Movements'

public Path FindPath(Position start, Position end, int maxNodes = 5000)

Check warning on line 17 in Plugins/MineSharp.Pathfinder/Algorithm/AStar.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'AStar.FindPath(Position, Position, int)'
{
var sw = Stopwatch.StartNew();
var nodes = new Dictionary<ulong, Node>();
var openSet = new FastPriorityQueue<Node>(maxNodes);
var closedSet = new HashSet<Node>();

var startNode = this.GetNode(start, end, ref nodes);
var endNode = this.GetNode(end, end, ref nodes);

if (!endNode.Walkable)
throw new InvalidOperationException("End position is not walkable!");

openSet.Enqueue(startNode, startNode.FCost);

while (openSet.Count > 0)
{
var node = openSet.Dequeue();

if (node.Position == end)
{
sw.Stop();
LogManager.GetCurrentClassLogger().Debug($"Checked {nodes.Count} nodes in {sw.ElapsedMilliseconds}ms");
return RetracePath(startNode, endNode);
}

closedSet.Add(node);

foreach (var neighbor in this.GetNeighbors(node, end, ref nodes))
{
if (!neighbor.Node.Walkable || closedSet.Contains(neighbor.Node))
continue;

var newCost = node.GCost + this.Distance(node.Position, end) + neighbor.Move.Cost;
if (newCost >= neighbor.Node.GCost && openSet.Contains(neighbor.Node))
continue;

neighbor.Node.Parent = node;
neighbor.Node.GCost = newCost;
neighbor.Node.HCost = this.Distance(neighbor.Node.Position, end);
neighbor.Node.Move = neighbor.Move;

if (openSet.Contains(neighbor.Node))
openSet.UpdatePriority(neighbor.Node, neighbor.Node.FCost);
else
openSet.Enqueue(neighbor.Node, neighbor.Node.FCost);
}
}

sw.Stop();
LogManager.GetCurrentClassLogger().Debug($"Checked {nodes.Count} nodes in {sw.ElapsedMilliseconds}ms");
throw new PathNotFoundException($"Could not find a path.");
}

private Path RetracePath(Node startNode, Node endNode)
{
var path = new List<Node>();
var currentNode = endNode;

while (currentNode != startNode)
{
path.Add(currentNode!);
currentNode = currentNode!.Parent!;
}
path.Add(startNode);
path.Reverse();

var moves = path.Skip(1).Select(x => x.Move!).ToArray();
return Path.FromMoves(startNode.Position, moves);
}

private float Distance(Position a, Position b)
{
var dX = a.X - b.X;
var dY = a.Y - b.Y;
var dZ = a.Z - b.Z;
return MathF.Sqrt(dX * dX + dY * dY + dZ * dZ);
}

private (Node Node, Move Move)[] GetNeighbors(Node node, Position end, ref Dictionary<ulong, Node> nodes)
{
var neighbors = new List<(Node, Move)>();

foreach (var move in this.Movements.PossibleMoves)
{
var pos = move.Motion.Plus(node.Position);
var neighbor = this.GetNode((Position)pos, end, ref nodes);
if (!neighbor.Walkable || !move.IsMovePossible(node.Position, world, data))
continue;

neighbors.Add((neighbor, move));
}

return neighbors.ToArray();
}

private Node GetNode(Position position, Position end, ref Dictionary<ulong, Node> nodes)
{
var idx = position.ToULong();
if (nodes.TryGetValue(idx, out var node))
return node;

var block = world.GetBlockAt(position);
var blockBelow = world.GetBlockAt((Position)Vector3.Down.Plus(position));

var walkable = blockBelow.IsSolid() && !blockBelow.IsFluid() && !block.IsSolid(); // TODO: Waterlike blocks
node = new Node(position, walkable, 0, this.Distance(position, end));
nodes.Add(idx, node);

return node;
}
}
Loading
Loading