mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-31 20:41:29 +01:00
Cleanup
This commit is contained in:
parent
7b5107f59d
commit
b54599a1f1
@ -69,9 +69,6 @@ public class MinecraftServer {
|
|||||||
public static final String THREAD_NAME_BLOCK_BATCH = "Ms-BlockBatchPool";
|
public static final String THREAD_NAME_BLOCK_BATCH = "Ms-BlockBatchPool";
|
||||||
public static final int THREAD_COUNT_BLOCK_BATCH = 2;
|
public static final int THREAD_COUNT_BLOCK_BATCH = 2;
|
||||||
|
|
||||||
public static final String THREAD_NAME_ENTITIES_PATHFINDING = "Ms-EntitiesPathFinding";
|
|
||||||
public static final int THREAD_COUNT_ENTITIES_PATHFINDING = 2;
|
|
||||||
|
|
||||||
public static final String THREAD_NAME_SCHEDULER = "Ms-SchedulerPool";
|
public static final String THREAD_NAME_SCHEDULER = "Ms-SchedulerPool";
|
||||||
public static final int THREAD_COUNT_SCHEDULER = 1;
|
public static final int THREAD_COUNT_SCHEDULER = 1;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ public enum Attribute {
|
|||||||
MAX_HEALTH("generic.max_health", 20, 1024),
|
MAX_HEALTH("generic.max_health", 20, 1024),
|
||||||
FOLLOW_RANGE("generic.follow_range", 32, 2048),
|
FOLLOW_RANGE("generic.follow_range", 32, 2048),
|
||||||
KNOCKBACK_RESISTANCE("generic.knockback_resistance", 0, 1),
|
KNOCKBACK_RESISTANCE("generic.knockback_resistance", 0, 1),
|
||||||
MOVEMENT_SPEED("generic.movement_speed", 0.7f, 1024),
|
MOVEMENT_SPEED("generic.movement_speed", 0.2f, 1024),
|
||||||
ATTACK_DAMAGE("generic.attack_damage", 2, 2048),
|
ATTACK_DAMAGE("generic.attack_damage", 2, 2048),
|
||||||
ATTACK_SPEED("generic.attack_speed", 4, 1024),
|
ATTACK_SPEED("generic.attack_speed", 4, 1024),
|
||||||
FLYING_SPEED("generic.flying_speed", 0.4f, 1024),
|
FLYING_SPEED("generic.flying_speed", 0.4f, 1024),
|
||||||
|
@ -24,7 +24,6 @@ public class BenchmarkManager {
|
|||||||
threads.add(THREAD_NAME_MAIN_UPDATE);
|
threads.add(THREAD_NAME_MAIN_UPDATE);
|
||||||
threads.add(THREAD_NAME_PACKET_WRITER);
|
threads.add(THREAD_NAME_PACKET_WRITER);
|
||||||
threads.add(THREAD_NAME_BLOCK_BATCH);
|
threads.add(THREAD_NAME_BLOCK_BATCH);
|
||||||
threads.add(THREAD_NAME_ENTITIES_PATHFINDING);
|
|
||||||
threads.add(THREAD_NAME_SCHEDULER);
|
threads.add(THREAD_NAME_SCHEDULER);
|
||||||
threads.add(THREAD_NAME_TICK);
|
threads.add(THREAD_NAME_TICK);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package net.minestom.server.entity;
|
|||||||
import com.extollit.gaming.ai.path.HydrazinePathFinder;
|
import com.extollit.gaming.ai.path.HydrazinePathFinder;
|
||||||
import com.extollit.gaming.ai.path.model.PathObject;
|
import com.extollit.gaming.ai.path.model.PathObject;
|
||||||
import net.minestom.server.collision.CollisionUtils;
|
import net.minestom.server.collision.CollisionUtils;
|
||||||
import net.minestom.server.entity.pathfinding.hydrazine.PFPathingEntity;
|
import net.minestom.server.entity.pathfinding.PFPathingEntity;
|
||||||
import net.minestom.server.event.entity.EntityAttackEvent;
|
import net.minestom.server.event.entity.EntityAttackEvent;
|
||||||
import net.minestom.server.event.item.ArmorEquipEvent;
|
import net.minestom.server.event.item.ArmorEquipEvent;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
@ -52,8 +52,12 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
|
|
||||||
// Path finding
|
// Path finding
|
||||||
path = pathFinder.update();
|
path = pathFinder.update();
|
||||||
if (path != null)
|
if (path != null) {
|
||||||
path.update(pathingEntity);
|
path.update(pathingEntity);
|
||||||
|
if (path.done()) {
|
||||||
|
pathFinder.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -261,6 +265,14 @@ public abstract class EntityCreature extends LivingEntity {
|
|||||||
setVelocity(velocity);
|
setVelocity(velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the path to {@code position} and ask the entity to follow the path
|
||||||
|
* <p>
|
||||||
|
* The position is cloned, if you want the entity to continually follow this position object
|
||||||
|
* you need to call this when you want the path to update
|
||||||
|
*
|
||||||
|
* @param position the position to find the path to
|
||||||
|
*/
|
||||||
public void setPathTo(Position position) {
|
public void setPathTo(Position position) {
|
||||||
position = position.clone();
|
position = position.clone();
|
||||||
this.path = pathFinder.initiatePathTo(position.getX(), position.getY(), position.getZ());
|
this.path = pathFinder.initiatePathTo(position.getX(), position.getY(), position.getZ());
|
||||||
|
@ -1,187 +0,0 @@
|
|||||||
package net.minestom.server.entity.pathfinding;
|
|
||||||
|
|
||||||
import net.minestom.server.instance.Instance;
|
|
||||||
import net.minestom.server.instance.block.Block;
|
|
||||||
import net.minestom.server.utils.BlockPosition;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class AStarPathfinder {
|
|
||||||
|
|
||||||
// TODO ladder, jump, etc...
|
|
||||||
// TODO include BoundingBox support
|
|
||||||
|
|
||||||
private boolean canClimbLadder;
|
|
||||||
private boolean canSwim;
|
|
||||||
private boolean canJump;
|
|
||||||
|
|
||||||
public static LinkedList<BlockPosition> getPath(Instance instance,
|
|
||||||
BlockPosition start, BlockPosition end,
|
|
||||||
int maxCheck) {
|
|
||||||
long time = System.nanoTime();
|
|
||||||
List<Node> open = new ArrayList<>();
|
|
||||||
List<Node> closed = new ArrayList<>();
|
|
||||||
|
|
||||||
Node startNode = Node.fromBlockPosition(start);
|
|
||||||
Node endNode = Node.fromBlockPosition(end);
|
|
||||||
|
|
||||||
open.add(startNode);
|
|
||||||
|
|
||||||
int checkCount = 0;
|
|
||||||
|
|
||||||
while (!open.isEmpty()) {
|
|
||||||
Node current = getCurrentNode(open);
|
|
||||||
open.remove(current);
|
|
||||||
closed.add(current);
|
|
||||||
|
|
||||||
if (isTargetNode(end, current)) {
|
|
||||||
System.out.println("found in: " + (System.nanoTime() - time) + " ns");
|
|
||||||
return buildPath(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Node neighbor : getNeighbors(instance, current)) {
|
|
||||||
if (isInList(closed, neighbor))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
boolean isInOpen = isInList(open, neighbor);
|
|
||||||
if (isShorter(neighbor, current) || !isInOpen) {
|
|
||||||
|
|
||||||
neighbor.parent = current;
|
|
||||||
neighbor.g = getTentativeGScore(neighbor, current);
|
|
||||||
neighbor.f = neighbor.g + getDistance(neighbor, endNode);
|
|
||||||
if (!isInOpen) {
|
|
||||||
open.add(neighbor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// To do not check the whole world
|
|
||||||
checkCount++;
|
|
||||||
if (checkCount >= maxCheck)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Node> getNeighbors(Instance instance, Node current) {
|
|
||||||
List<Node> result = new ArrayList<>();
|
|
||||||
BlockPosition currentBlockPosition = current.getBlockPosition();
|
|
||||||
|
|
||||||
for (int x = -1; x < 2; x++) {
|
|
||||||
for (int y = -1; y < 2; y++) {
|
|
||||||
for (int z = -1; z < 2; z++) {
|
|
||||||
if (x == 0 && y == 0 && z == 0)
|
|
||||||
continue;
|
|
||||||
BlockPosition neighbor = currentBlockPosition.clone().add(x, y, z);
|
|
||||||
if (canAccessBlock(instance, currentBlockPosition, neighbor)) {
|
|
||||||
Node node = Node.fromBlockPosition(neighbor);
|
|
||||||
result.add(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Node getCurrentNode(List<Node> open) {
|
|
||||||
Node closest = null;
|
|
||||||
|
|
||||||
for (Node node : open) {
|
|
||||||
if (closest == null || node.f < closest.f) {
|
|
||||||
closest = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closest;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isTargetNode(BlockPosition target, Node node) {
|
|
||||||
return target.getX() == node.getX() &&
|
|
||||||
target.getY() == node.getY() &&
|
|
||||||
target.getZ() == node.getZ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean canAccessBlock(Instance instance, BlockPosition current, BlockPosition target) {
|
|
||||||
if (instance.getChunkAt(target) == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Block targetBlock = Block.fromId(instance.getBlockId(target));
|
|
||||||
Block belowBlock = Block.fromId(instance.getBlockId(target.clone().add(0, -1, 0)));
|
|
||||||
|
|
||||||
boolean result = !targetBlock.isSolid() && belowBlock.isSolid();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isInList(List<Node> list, Node node) {
|
|
||||||
for (Node close : list) {
|
|
||||||
if (close.getX() == node.getX() &&
|
|
||||||
close.getY() == node.getY() &&
|
|
||||||
close.getZ() == node.getZ())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getDistance(Node node1, Node node2) {
|
|
||||||
return node1.blockPosition.getDistance(node2.blockPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getTentativeGScore(Node neighbor, Node current) {
|
|
||||||
return neighbor.g + getDistance(neighbor, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isShorter(Node neighbor, Node current) {
|
|
||||||
return getTentativeGScore(neighbor, current) < neighbor.g;
|
|
||||||
}
|
|
||||||
private static LinkedList<BlockPosition> buildPath(Node finalNode) {
|
|
||||||
LinkedList<BlockPosition> result = new LinkedList<>();
|
|
||||||
Node cache = finalNode;
|
|
||||||
while (cache != null) {
|
|
||||||
result.add(cache.blockPosition);
|
|
||||||
cache = cache.parent;
|
|
||||||
}
|
|
||||||
// Make the list start->end
|
|
||||||
Collections.reverse(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Node {
|
|
||||||
public int g, f;
|
|
||||||
public Node parent;
|
|
||||||
private int x, y, z;
|
|
||||||
private BlockPosition blockPosition;
|
|
||||||
|
|
||||||
public Node(BlockPosition blockPosition) {
|
|
||||||
this.x = blockPosition.getX();
|
|
||||||
this.y = blockPosition.getY();
|
|
||||||
this.z = blockPosition.getZ();
|
|
||||||
this.blockPosition = blockPosition.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Node fromBlockPosition(BlockPosition blockPosition) {
|
|
||||||
Node node = new Node(blockPosition);
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getZ() {
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockPosition getBlockPosition() {
|
|
||||||
return blockPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package net.minestom.server.entity.pathfinding;
|
|
||||||
|
|
||||||
import net.minestom.server.MinecraftServer;
|
|
||||||
import net.minestom.server.entity.Entity;
|
|
||||||
import net.minestom.server.instance.Instance;
|
|
||||||
import net.minestom.server.utils.BlockPosition;
|
|
||||||
import net.minestom.server.utils.Position;
|
|
||||||
import net.minestom.server.utils.thread.MinestomThread;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class EntityPathFinder {
|
|
||||||
|
|
||||||
private static ExecutorService pathfindingPool = new MinestomThread(MinecraftServer.THREAD_COUNT_ENTITIES_PATHFINDING, MinecraftServer.THREAD_NAME_ENTITIES_PATHFINDING);
|
|
||||||
|
|
||||||
|
|
||||||
private Entity entity;
|
|
||||||
|
|
||||||
public EntityPathFinder(Entity entity) {
|
|
||||||
this.entity = entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getPath(Position target, int maxCheck, Consumer<LinkedList<BlockPosition>> consumer) {
|
|
||||||
pathfindingPool.execute(() -> {
|
|
||||||
Instance instance = entity.getInstance();
|
|
||||||
BlockPosition start = entity.getPosition().toBlockPosition();
|
|
||||||
BlockPosition end = target.toBlockPosition();
|
|
||||||
|
|
||||||
consumer.accept(AStarPathfinder.getPath(instance, start, end, maxCheck));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package net.minestom.server.entity.pathfinding.hydrazine;
|
package net.minestom.server.entity.pathfinding;
|
||||||
|
|
||||||
import com.extollit.gaming.ai.path.model.IBlockDescription;
|
import com.extollit.gaming.ai.path.model.IBlockDescription;
|
||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
@ -1,4 +1,4 @@
|
|||||||
package net.minestom.server.entity.pathfinding.hydrazine;
|
package net.minestom.server.entity.pathfinding;
|
||||||
|
|
||||||
import com.extollit.gaming.ai.path.model.IBlockObject;
|
import com.extollit.gaming.ai.path.model.IBlockObject;
|
||||||
import com.extollit.linalg.immutable.AxisAlignedBBox;
|
import com.extollit.linalg.immutable.AxisAlignedBBox;
|
@ -1,4 +1,4 @@
|
|||||||
package net.minestom.server.entity.pathfinding.hydrazine;
|
package net.minestom.server.entity.pathfinding;
|
||||||
|
|
||||||
import com.extollit.gaming.ai.path.model.ColumnarOcclusionFieldList;
|
import com.extollit.gaming.ai.path.model.ColumnarOcclusionFieldList;
|
||||||
import com.extollit.gaming.ai.path.model.IBlockDescription;
|
import com.extollit.gaming.ai.path.model.IBlockDescription;
|
@ -1,4 +1,4 @@
|
|||||||
package net.minestom.server.entity.pathfinding.hydrazine;
|
package net.minestom.server.entity.pathfinding;
|
||||||
|
|
||||||
import com.extollit.gaming.ai.path.model.IBlockObject;
|
import com.extollit.gaming.ai.path.model.IBlockObject;
|
||||||
import com.extollit.gaming.ai.path.model.IColumnarSpace;
|
import com.extollit.gaming.ai.path.model.IColumnarSpace;
|
@ -1,4 +1,4 @@
|
|||||||
package net.minestom.server.entity.pathfinding.hydrazine;
|
package net.minestom.server.entity.pathfinding;
|
||||||
|
|
||||||
import com.extollit.gaming.ai.path.model.IPathingEntity;
|
import com.extollit.gaming.ai.path.model.IPathingEntity;
|
||||||
import com.extollit.linalg.immutable.Vec3d;
|
import com.extollit.linalg.immutable.Vec3d;
|
||||||
@ -75,7 +75,7 @@ public class PFPathingEntity implements IPathingEntity {
|
|||||||
public void moveTo(Vec3d position) {
|
public void moveTo(Vec3d position) {
|
||||||
final Position entityPosition = entity.getPosition();
|
final Position entityPosition = entity.getPosition();
|
||||||
final float entityY = entityPosition.getY();
|
final float entityY = entityPosition.getY();
|
||||||
final float speed = entity.getAttributeValue(Attribute.MOVEMENT_SPEED) / 5;
|
final float speed = entity.getAttributeValue(Attribute.MOVEMENT_SPEED);
|
||||||
final float x = (float) position.x;
|
final float x = (float) position.x;
|
||||||
final float y = (float) position.y;
|
final float y = (float) position.y;
|
||||||
final float z = (float) position.z;
|
final float z = (float) position.z;
|
@ -5,7 +5,7 @@ import net.minestom.server.MinecraftServer;
|
|||||||
import net.minestom.server.data.Data;
|
import net.minestom.server.data.Data;
|
||||||
import net.minestom.server.data.DataContainer;
|
import net.minestom.server.data.DataContainer;
|
||||||
import net.minestom.server.entity.*;
|
import net.minestom.server.entity.*;
|
||||||
import net.minestom.server.entity.pathfinding.hydrazine.PFInstanceSpace;
|
import net.minestom.server.entity.pathfinding.PFInstanceSpace;
|
||||||
import net.minestom.server.event.Event;
|
import net.minestom.server.event.Event;
|
||||||
import net.minestom.server.event.EventCallback;
|
import net.minestom.server.event.EventCallback;
|
||||||
import net.minestom.server.event.handler.EventHandler;
|
import net.minestom.server.event.handler.EventHandler;
|
||||||
|
Loading…
Reference in New Issue
Block a user