SteamWar/FightSystem
Archiviert
13
1

Pathplanning
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful

Signed-off-by: Lixfel <agga-games@gmx.de>
Dieser Commit ist enthalten in:
Lixfel 2023-09-02 18:23:30 +02:00
Ursprung 4655dbe21b
Commit e7bb1e6669
3 geänderte Dateien mit 154 neuen und 7 gelöschten Zeilen

Datei anzeigen

@ -42,9 +42,7 @@ import org.bukkit.block.data.Powerable;
import org.bukkit.block.data.type.Comparator; import org.bukkit.block.data.type.Comparator;
import org.bukkit.block.data.type.NoteBlock; import org.bukkit.block.data.type.NoteBlock;
import org.bukkit.block.data.type.Repeater; import org.bukkit.block.data.type.Repeater;
import org.bukkit.entity.EntityType; import org.bukkit.entity.*;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@ -149,6 +147,9 @@ public abstract class AI {
queue.add(new Action(1) { queue.add(new Action(1) {
@Override @Override
public void run() { public void run() {
if(FightState.getFightState() != FightState.RUNNING)
return;
Location location = translate(pos, true); Location location = translate(pos, true);
if(interactionDistanceViolation(location)) if(interactionDistanceViolation(location))
return; return;
@ -206,6 +207,9 @@ public abstract class AI {
if(Math.abs(location.getX() - target.getX()) > 1 || Math.abs(location.getY() - target.getY()) > 1 || Math.abs(location.getZ() - target.getZ()) > 1) if(Math.abs(location.getX() - target.getX()) > 1 || Math.abs(location.getY() - target.getY()) > 1 || Math.abs(location.getZ() - target.getZ()) > 1)
return; return;
if(!team.getFightPlayer(entity).canEntern() && !team.getExtendRegion().inRegion(target))
return;
entity.teleport(target); entity.teleport(target);
} }
}); });

Datei anzeigen

@ -23,24 +23,38 @@ import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import org.bukkit.util.Vector;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
public class LixfelAI extends AI { public class LixfelAI extends AI {
public LixfelAI(FightTeam team) {
super(team, SteamwarUser.get("public")); private final Random random = new Random();
private LixfelPathplanner pathplanner;
public LixfelAI(FightTeam team, String user) {
super(team, SteamwarUser.get(user));
} }
@Override @Override
public SchematicNode chooseSchematic() { public SchematicNode chooseSchematic() {
List<SchematicNode> publics = SchematicNode.getAllSchematicsOfType(0, Config.SchematicType.toDB()); List<SchematicNode> publics = SchematicNode.getAllSchematicsOfType(0, Config.SchematicType.toDB());
return publics.get(new Random().nextInt(publics.size())); SchematicNode schem = publics.get(new Random().nextInt(publics.size()));
pathplanner = new LixfelPathplanner(schem);
return schem;
} }
@Override @Override
protected void plan() { protected void plan() {
setReady(); setReady();
getEntity().setAI(true); Vector destination = pathplanner.getWalkable().get(random.nextInt(pathplanner.getWalkable().size()));
List<Vector> path = pathplanner.plan(getPosition(), destination);
if(!path.isEmpty())
chat("Path size: " + path.size());
for(Vector p : path) {
move(p);
}
} }
} }

Datei anzeigen

@ -0,0 +1,129 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.ai;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.block.BlockType;
import de.steamwar.fightsystem.Config;
import de.steamwar.sql.SchematicData;
import de.steamwar.sql.SchematicNode;
import org.bukkit.util.Vector;
import java.io.IOException;
import java.util.*;
public class LixfelPathplanner {
private static BlockType getBlockType(Clipboard clipboard, BlockVector3 vector) {
return clipboard.getBlock(vector).getBlockType();
}
private static boolean nonsolid(Clipboard clipboard, BlockVector3 vector) {
return !getBlockType(clipboard, vector).getMaterial().isSolid();
}
private static Vector toBukkit(BlockVector3 vector) {
return new Vector(vector.getX(), vector.getY(), vector.getZ());
}
private final List<Vector> walkable = new ArrayList<>();
private final Map<Vector, Vector[]> neighbours = new HashMap<>();
public LixfelPathplanner(SchematicNode schem) {
try {
fillWalkable(new SchematicData(schem).load());
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
public List<Vector> getWalkable() {
return walkable;
}
private void fillWalkable(Clipboard clipboard) {
BlockVector3 min = clipboard.getRegion().getMinimumPoint().subtract(Config.PreperationArea, 0, Config.PreperationArea); //TODO assumes nonextended Schematic with maximal size
Region region = clipboard.getRegion();
clipboard.getRegion().forEach(vector -> {
BlockVector3 below = vector.subtract(0, 1, 0);
if(!region.contains(below))
return;
BlockType belowMaterial = getBlockType(clipboard, below);
BlockVector3 above = vector.add(0, 1, 0);
if(
(belowMaterial.getMaterial().isSolid() || belowMaterial.getId().equals("minecraft:ladder")) &&
nonsolid(clipboard, vector) &&
(!region.contains(above) || nonsolid(clipboard, above))
)
walkable.add(toBukkit(vector.subtract(min)));
});
for(Vector vector : walkable) {
neighbours.put(vector, walkable.stream().filter(neighbour -> neighbouring(neighbour, vector)).filter(neighbour -> neighbour != vector).toArray(Vector[]::new));
}
}
public List<Vector> planToAnywhere(Vector start, Vector destination) {
return plan(start, destination); //TODO (destination neighbor search)
}
public List<Vector> plan(Vector start, Vector destination) {
if(neighbouring(start, destination))
return Collections.singletonList(destination);
Map<Vector, Vector> approach = new HashMap<>();
Set<Vector> checking = Collections.singleton(destination);
while(!checking.isEmpty()) {
Set<Vector> toCheck = new HashSet<>();
for(Vector current : checking) {
Vector firstStep = Arrays.stream(neighbours.get(current))
.filter(vector -> !approach.containsKey(vector))
.filter(next -> {
approach.put(next, current);
toCheck.add(next);
return neighbouring(next, start);
})
.findAny().orElse(null);
if(firstStep != null) {
List<Vector> path = new ArrayList<>();
path.add(firstStep);
while(path.get(path.size()-1) != destination) {
path.add(approach.get(path.get(path.size()-1)));
}
return path;
}
}
checking = toCheck;
}
return Collections.emptyList();
}
private boolean neighbouring(Vector a, Vector b) {
return Math.abs(a.getX() - b.getX()) <= 1 && Math.abs(a.getY() - b.getY()) <= 1 && Math.abs(a.getZ() - b.getZ()) <= 1;
}
}