Hydrazine fix + basic pathfinding api

This commit is contained in:
Felix Cravic 2020-07-24 02:31:10 +02:00
parent 2ea4c2d996
commit 7b5107f59d
8 changed files with 79 additions and 98 deletions

View File

@ -26,9 +26,7 @@ import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType; import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material; import net.minestom.server.item.Material;
import net.minestom.server.item.metadata.MapMeta;
import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.server.play.MapDataPacket;
import net.minestom.server.ping.ResponseDataConsumer; import net.minestom.server.ping.ResponseDataConsumer;
import net.minestom.server.timer.TaskRunnable; import net.minestom.server.timer.TaskRunnable;
import net.minestom.server.utils.MathUtils; import net.minestom.server.utils.MathUtils;
@ -54,7 +52,7 @@ public class PlayerInit {
//instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(storageFolder); //instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(storageFolder);
instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.OVERWORLD); instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.OVERWORLD);
instanceContainer.enableAutoChunkLoad(true); instanceContainer.enableAutoChunkLoad(true);
instanceContainer.setChunkGenerator(chunkGeneratorDemo); instanceContainer.setChunkGenerator(noiseTestGenerator);
netherTest = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.NETHER); netherTest = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.NETHER);
netherTest.enableAutoChunkLoad(true); netherTest.enableAutoChunkLoad(true);
@ -247,7 +245,7 @@ public class PlayerInit {
player.getInventory().setItemStack(i, new ItemStack(Material.STONE, (byte) 127)); player.getInventory().setItemStack(i, new ItemStack(Material.STONE, (byte) 127));
}*/ }*/
ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1); /*ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1);
MapMeta mapMeta = (MapMeta) map.getItemMeta(); MapMeta mapMeta = (MapMeta) map.getItemMeta();
mapMeta.setMapId(1); mapMeta.setMapId(1);
player.getInventory().setItemStack(0, map); player.getInventory().setItemStack(0, map);
@ -275,7 +273,7 @@ public class PlayerInit {
player.getPlayerConnection().sendPacket(mapDataPacket); player.getPlayerConnection().sendPacket(mapDataPacket);
} }*/
ItemStack item = new ItemStack(Material.STONE_SWORD, (byte) 1); ItemStack item = new ItemStack(Material.STONE_SWORD, (byte) 1);

View File

@ -1,17 +1,11 @@
package fr.themode.demo.commands; package fr.themode.demo.commands;
import com.extollit.gaming.ai.path.HydrazinePathFinder;
import com.extollit.gaming.ai.path.model.PathObject;
import com.extollit.linalg.immutable.Vec3i;
import fr.themode.demo.entity.ChickenCreature; import fr.themode.demo.entity.ChickenCreature;
import net.minestom.server.command.CommandProcessor; import net.minestom.server.command.CommandProcessor;
import net.minestom.server.command.CommandSender; import net.minestom.server.command.CommandSender;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.hydrazine.PFInstanceSpace;
import net.minestom.server.entity.pathfinding.hydrazine.PFPathingEntity;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
import net.minestom.server.utils.Position;
import java.util.Iterator;
public class SimpleCommand implements CommandProcessor { public class SimpleCommand implements CommandProcessor {
@Override @Override
@ -59,24 +53,10 @@ public class SimpleCommand implements CommandProcessor {
Instance instance = player.getInstance(); Instance instance = player.getInstance();
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition()); ChickenCreature chickenCreature = new ChickenCreature(new Position(-10, 42, -10));
chickenCreature.setInstance(instance); chickenCreature.setInstance(instance);
PFPathingEntity pathingEntity = new PFPathingEntity(chickenCreature); chickenCreature.setPathTo(player.getPosition());
PFInstanceSpace instanceSpace = new PFInstanceSpace(instance);
final HydrazinePathFinder pathFinder = new HydrazinePathFinder(pathingEntity, instanceSpace);
final PathObject path = pathFinder.initiatePathTo(-10, 40, -10);
System.out.println("path: " + path);
for (Iterator<Vec3i> it = path.iterator(); it.hasNext(); ) {
Vec3i ite = it.next();
System.out.println("test: " + ite);
}
return true; return true;
} }

View File

@ -1,28 +1,26 @@
package net.minestom.server.entity; package net.minestom.server.entity;
import net.minestom.server.attribute.Attribute; import com.extollit.gaming.ai.path.HydrazinePathFinder;
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.EntityPathFinder; import net.minestom.server.entity.pathfinding.hydrazine.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.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.server.play.*; import net.minestom.server.network.packet.server.play.*;
import net.minestom.server.network.player.PlayerConnection; import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position; import net.minestom.server.utils.Position;
import net.minestom.server.utils.Vector; import net.minestom.server.utils.Vector;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.item.ItemStackUtils; import net.minestom.server.utils.item.ItemStackUtils;
import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.utils.time.TimeUnit;
import java.util.LinkedList;
import java.util.function.Consumer;
public abstract class EntityCreature extends LivingEntity { public abstract class EntityCreature extends LivingEntity {
private EntityPathFinder pathFinder = new EntityPathFinder(this); private PFPathingEntity pathingEntity = new PFPathingEntity(this);
private LinkedList<BlockPosition> blockPositions; private HydrazinePathFinder pathFinder;
private Position targetPosition; private PathObject path;
// Equipments // Equipments
private ItemStack mainHandItem; private ItemStack mainHandItem;
@ -53,7 +51,15 @@ public abstract class EntityCreature extends LivingEntity {
super.update(time); super.update(time);
// Path finding // Path finding
pathProgress(); path = pathFinder.update();
if (path != null)
path.update(pathingEntity);
}
@Override
public void setInstance(Instance instance) {
super.setInstance(instance);
this.pathFinder = new HydrazinePathFinder(pathingEntity, instance.getInstanceSpace());
} }
/** /**
@ -128,7 +134,7 @@ public abstract class EntityCreature extends LivingEntity {
@Override @Override
public boolean addViewer(Player player) { public boolean addViewer(Player player) {
boolean result = super.addViewer(player); final boolean result = super.addViewer(player);
if (!result) if (!result)
return false; return false;
@ -251,34 +257,13 @@ public abstract class EntityCreature extends LivingEntity {
public void jump(float height) { public void jump(float height) {
// FIXME magic value // FIXME magic value
Vector velocity = new Vector(0, height * 5, 0); final Vector velocity = new Vector(0, height * 5, 0);
setVelocity(velocity); setVelocity(velocity);
} }
public void setPathTo(Position position, int maxCheck, Consumer<Boolean> resultConsumer) {
pathFinder.getPath(position, maxCheck, blockPositions -> {
if (blockPositions == null || blockPositions.isEmpty()) {
// Didn't find path
if (resultConsumer != null)
resultConsumer.accept(false);
return;
}
blockPositions.pollFirst(); // Remove first entry (where the entity is)
this.blockPositions = blockPositions;
setNextPathPosition();
if (resultConsumer != null)
resultConsumer.accept(true);
});
}
public void setPathTo(Position position, int maxCheck) {
setPathTo(position, maxCheck, null);
}
public void setPathTo(Position position) { public void setPathTo(Position position) {
setPathTo(position, 1000, null); position = position.clone();
this.path = pathFinder.initiatePathTo(position.getX(), position.getY(), position.getZ());
} }
/** /**
@ -295,37 +280,6 @@ public abstract class EntityCreature extends LivingEntity {
move(speedX, 0, speedZ, true); move(speedX, 0, speedZ, true);
} }
private void setNextPathPosition() {
final BlockPosition blockPosition = blockPositions.pollFirst();
if (blockPosition == null) {
this.blockPositions = null;
this.targetPosition = null;
return;
}
this.targetPosition = blockPosition.toPosition();//.add(0.5f, 0, 0.5f);
if (blockPosition.getY() > getPosition().getY())
jump(1);
}
private void pathProgress() {
if (blockPositions != null) {
if (targetPosition != null) {
final float distance = getPosition().getDistance(targetPosition);
//System.out.println("test: "+distance);
if (distance < 1f) {
setNextPathPosition();
pathProgress();
//System.out.println("END TARGET");
} else {
moveTowards(targetPosition, getAttributeValue(Attribute.MOVEMENT_SPEED));
//System.out.println("MOVE TOWARD " + targetPosition);
}
}
}
}
private ItemStack getEquipmentItem(ItemStack itemStack, ArmorEquipEvent.ArmorSlot armorSlot) { private ItemStack getEquipmentItem(ItemStack itemStack, ArmorEquipEvent.ArmorSlot armorSlot) {
itemStack = ItemStackUtils.notNull(itemStack); itemStack = ItemStackUtils.notNull(itemStack);
@ -333,4 +287,15 @@ public abstract class EntityCreature extends LivingEntity {
callEvent(ArmorEquipEvent.class, armorEquipEvent); callEvent(ArmorEquipEvent.class, armorEquipEvent);
return armorEquipEvent.getArmorItem(); return armorEquipEvent.getArmorItem();
} }
/**
* Get the pathfinding entity
* <p>
* Used internally by the pathfinder
*
* @return the pathfinding entity
*/
public PFPathingEntity getPathingEntity() {
return pathingEntity;
}
} }

View File

@ -28,7 +28,7 @@ public class PFBlockDescription implements IBlockDescription {
@Override @Override
public boolean isImpeding() { public boolean isImpeding() {
return false; return block.isSolid();
} }
@Override @Override

View File

@ -37,7 +37,7 @@ public class PFBlockObject implements IBlockObject {
@Override @Override
public boolean isImpeding() { public boolean isImpeding() {
return false; return block.isSolid();
} }
@Override @Override

View File

@ -73,8 +73,16 @@ public class PFPathingEntity implements IPathingEntity {
@Override @Override
public void moveTo(Vec3d position) { public void moveTo(Vec3d position) {
float speed = entity.getAttributeValue(Attribute.MOVEMENT_SPEED); final Position entityPosition = entity.getPosition();
entity.moveTowards(new Position((float) position.x, (float) position.y, (float) position.z), speed); final float entityY = entityPosition.getY();
final float speed = entity.getAttributeValue(Attribute.MOVEMENT_SPEED) / 5;
final float x = (float) position.x;
final float y = (float) position.y;
final float z = (float) position.z;
entity.moveTowards(new Position(x, y, z), speed);
if (entityY < y) {
entity.jump(1);
}
} }
@Override @Override

View File

@ -5,6 +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.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;
@ -75,6 +76,9 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
private Data data; private Data data;
private ExplosionSupplier explosionSupplier; private ExplosionSupplier explosionSupplier;
// Pathfinder
private PFInstanceSpace instanceSpace = new PFInstanceSpace(this);
public Instance(UUID uniqueId, DimensionType dimensionType) { public Instance(UUID uniqueId, DimensionType dimensionType) {
this.uniqueId = uniqueId; this.uniqueId = uniqueId;
this.dimensionType = dimensionType; this.dimensionType = dimensionType;
@ -824,4 +828,15 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
public void setExplosionSupplier(ExplosionSupplier supplier) { public void setExplosionSupplier(ExplosionSupplier supplier) {
this.explosionSupplier = supplier; this.explosionSupplier = supplier;
} }
/**
* Get the instance space
* <p>
* Used by the pathfinder for entities
*
* @return the instance space
*/
public PFInstanceSpace getInstanceSpace() {
return instanceSpace;
}
} }

View File

@ -9,12 +9,17 @@ import java.util.Map;
public class BlockManager { public class BlockManager {
// custom block id -> custom block
private Short2ObjectMap<CustomBlock> customBlocksInternalId = new Short2ObjectOpenHashMap<>(); private Short2ObjectMap<CustomBlock> customBlocksInternalId = new Short2ObjectOpenHashMap<>();
// custom block identifier -> custom block
private Map<String, CustomBlock> customBlocksId = new HashMap<>(); private Map<String, CustomBlock> customBlocksId = new HashMap<>();
// block id -> block placement rule
private Short2ObjectOpenHashMap<BlockPlacementRule> placementRules = new Short2ObjectOpenHashMap<>(); private Short2ObjectOpenHashMap<BlockPlacementRule> placementRules = new Short2ObjectOpenHashMap<>();
/** /**
* Register a custom block
*
* @param customBlock the custom block to register * @param customBlock the custom block to register
*/ */
public void registerCustomBlock(CustomBlock customBlock) { public void registerCustomBlock(CustomBlock customBlock) {
@ -25,6 +30,8 @@ public class BlockManager {
} }
/** /**
* Register a block placement rule
*
* @param blockPlacementRule the block placement rule to register * @param blockPlacementRule the block placement rule to register
*/ */
public void registerBlockPlacementRule(BlockPlacementRule blockPlacementRule) { public void registerBlockPlacementRule(BlockPlacementRule blockPlacementRule) {
@ -32,6 +39,8 @@ public class BlockManager {
} }
/** /**
* Get the block placement rule of the specific block
*
* @param blockId the block id to check * @param blockId the block id to check
* @return the block placement rule associated with the id, null if not any * @return the block placement rule associated with the id, null if not any
*/ */
@ -42,6 +51,8 @@ public class BlockManager {
} }
/** /**
* Get the block placement rule of the specific block
*
* @param block the block to check * @param block the block to check
* @return the block placement rule associated with the block, null if not any * @return the block placement rule associated with the block, null if not any
*/ */
@ -50,6 +61,8 @@ public class BlockManager {
} }
/** /**
* Get the CustomBlock with the specific identifier {@link CustomBlock#getIdentifier()}
*
* @param identifier the custom block identifier * @param identifier the custom block identifier
* @return the {@link CustomBlock} associated with the identifier, null if not any * @return the {@link CustomBlock} associated with the identifier, null if not any
*/ */
@ -58,6 +71,8 @@ public class BlockManager {
} }
/** /**
* Get the CustomBlock with the specific custom block id {@link CustomBlock#getCustomBlockId()}
*
* @param id the custom block id * @param id the custom block id
* @return the {@link CustomBlock} associated with the id, null if not any * @return the {@link CustomBlock} associated with the id, null if not any
*/ */