Fix LocalCoordinate, WorldCoordinate

Fix WarMachine
This commit is contained in:
2026-04-18 17:21:53 +02:00
parent 2c44e50846
commit 82a59f772e
10 changed files with 161 additions and 66 deletions
@@ -175,7 +175,7 @@ public abstract class AI {
}
Block block = location.getBlock();
if(block.getType() == Material.AIR)
if(block.getType() == Material.AIR || block.getType() == Material.WATER || block.getType() == Material.LAVA || block.getType() == Material.TNT)
block.setType(Material.TNT);
}
});
@@ -278,6 +278,7 @@ public abstract class AI {
FightSystem.getPlugin().getLogger().log(Level.INFO, "Entity not teleported: " + entity.isValid());
GlobalRecorder.getInstance().entityMoves(entity);
navMesh.update(getPosition().toWorld(team));
}
});
}
@@ -292,6 +293,7 @@ public abstract class AI {
private void interact(Block block) {
BlockData data = block.getBlockData(); //TODO only 1.14+ compatible at the moment
System.out.println(block + " " + data);
if (data instanceof NoteBlock) {
NoteBlock noteBlock = (NoteBlock) data;
Note note = noteBlock.getNote();
@@ -322,6 +324,7 @@ public abstract class AI {
}
powerable.setPowered(!isPowered);
System.out.println(powerable);
}
block.setBlockData(data);
if(data instanceof Switch) {
@@ -350,7 +353,6 @@ public abstract class AI {
private void run() {
if(queue.isEmpty()) {
try {
navMesh.update(getPosition().toWorld(team));
plan();
} catch (Throwable t) {
stop();
@@ -19,10 +19,13 @@
package de.steamwar.fightsystem.ai;
import de.steamwar.fightsystem.ai.schematic.Cannon;
import java.util.ArrayList;
import java.util.List;
public interface Action {
boolean isCompletable();
Result step(AI ai);
enum Result {
@@ -32,6 +35,46 @@ public interface Action {
;
}
class MultiAction implements Action {
protected final List<Action> actions = new ArrayList<>();
@Override
public Result step(AI ai) {
if (!actions.isEmpty()) {
Action.Result result = actions.get(0).step(ai);
if (result == Action.Result.FAILED) {
ai.chat(this + " + " + actions.get(0) + " failed");
actions.clear();
return Result.FAILED;
}
if (result == Action.Result.FINISHED) {
ai.chat(this + " + " + actions.get(0) + " finished");
actions.remove(0);
}
}
return actions.isEmpty() ? Result.FINISHED : Result.ONGOING;
}
}
class WaitAction implements Action {
private int delay;
public WaitAction(int delay) {
this.delay = delay;
}
@Override
public Result step(AI ai) {
if (--delay > 0) {
return Result.ONGOING;
} else {
return Result.FINISHED;
}
}
}
class MoveAction implements Action {
private final WorldCoordinate destination;
@@ -47,11 +90,6 @@ public interface Action {
this.path = ai.navMesh.pathToNearest(ai.getPosition().toWorld(ai.team), destination);
}
@Override
public boolean isCompletable() {
return !path.isEmpty();
}
@Override
public Result step(AI ai) {
if (this.path.isEmpty()) return Result.FAILED;
@@ -95,15 +133,48 @@ public interface Action {
this.destination = destination;
}
@Override
public boolean isCompletable() {
return true;
}
@Override
public Result step(AI ai) {
ai.interact(destination);
return Result.FINISHED;
}
}
class ReadyAction implements Action {
@Override
public Result step(AI ai) {
ai.setReady();
return Result.FINISHED;
}
}
class PlaceTNTAction implements Action {
private final LocalCoordinate destination;
public PlaceTNTAction(LocalCoordinate destination) {
this.destination = destination;
}
@Override
public Result step(AI ai) {
ai.setTNT(destination);
return Result.FINISHED;
}
}
class LoadCannon extends MultiAction {
public LoadCannon(AI ai, Cannon cannon) {
for (LocalCoordinate tntPosition : cannon.getTntPositions()) {
actions.add(new MoveAction(ai, tntPosition.toWorld(ai.team)));
actions.add(new PlaceTNTAction(tntPosition));
}
LocalCoordinate trigger = cannon.getTriggerPositions().iterator().next();
actions.add(new MoveAction(ai, trigger.toWorld(ai.team)));
actions.add(new InteractAction(trigger));
}
}
}
@@ -50,6 +50,9 @@ public class LocalCoordinate {
}
public WorldCoordinate toWorld(FightTeam team) {
// TODO: Fix the of by one blue/red
// Team Red is not correct!
// NightTown is team blue unrotated!
Region extend = team.getExtendRegion();
if(Fight.getUnrotated() == team) {
return new WorldCoordinate(
@@ -59,9 +62,9 @@ public class LocalCoordinate {
);
} else {
return new WorldCoordinate(
extend.getMaxX() - x,
extend.getMaxX() - x - 1,
y + team.getSchemRegion().getMinY(),
extend.getMaxZ() - z
extend.getMaxZ() - z - 1
);
}
}
@@ -306,12 +306,19 @@ public class NavMesh {
Pos to = toPos(toCoordinate);
if (walkable.containsKey(to)) return path(toPos(fromCoordinate), to);
Pos nearestPos = walkable.values()
Pos closestTo = walkable.values()
.stream()
.min(Comparator.comparingDouble(pos -> pos.toWorld().distanceSquared(toCoordinate)))
.filter(pos -> {
double distance = pos.toWorld().distanceSquared(toCoordinate);
return distance < AI.INTERACTION_RANGE * AI.INTERACTION_RANGE && distance > 1.5 * 1.5;
})
.min(Comparator.comparing(pos -> pos.toWorld().distanceSquared(toCoordinate)))
.orElse(null);
if (nearestPos == null) return Collections.emptyList();
return path(toPos(fromCoordinate), nearestPos);
if (closestTo == null) {
return Collections.emptyList();
}
return path(toPos(fromCoordinate), closestTo);
}
public List<WorldCoordinate> path(WorldCoordinate fromCoordinate, WorldCoordinate toCoordinate) {
@@ -61,6 +61,7 @@ public class WorldCoordinate {
}
public LocalCoordinate toLocal(FightTeam team) {
// TODO: Fix the of by one blue/red
Region extend = team.getExtendRegion();
if (Fight.getUnrotated() == team) {
return new LocalCoordinate(
@@ -70,9 +71,9 @@ public class WorldCoordinate {
);
} else {
return new LocalCoordinate(
extend.getMaxX() - x,
extend.getMaxX() - x + 1,
y - team.getSchemRegion().getMinY(),
extend.getMaxZ() - z
extend.getMaxZ() - z + 1
);
}
}
@@ -19,8 +19,8 @@
package de.steamwar.fightsystem.ai.schematic;
import de.steamwar.fightsystem.ai.LocalCoordinate;
import lombok.Getter;
import org.bukkit.util.Vector;
import java.util.HashSet;
import java.util.Set;
@@ -28,16 +28,16 @@ import java.util.Set;
@Getter
public class Bridge {
private final Set<Vector> shieldActivators = new HashSet<>();
private Vector automaticActivator = null;
private final Set<LocalCoordinate> shieldActivators = new HashSet<>();
private LocalCoordinate automaticActivator = null;
private int automaticActivatorTime = 0;
public Bridge addShieldActivator(Vector shieldActivator) {
public Bridge addShieldActivator(LocalCoordinate shieldActivator) {
this.shieldActivators.add(shieldActivator);
return this;
}
public Bridge addAutomaticActivator(Vector automaticActivator, int automaticActivatorTime) {
public Bridge addAutomaticActivator(LocalCoordinate automaticActivator, int automaticActivatorTime) {
this.automaticActivator = automaticActivator;
this.automaticActivatorTime = automaticActivatorTime;
return this;
@@ -19,8 +19,8 @@
package de.steamwar.fightsystem.ai.schematic;
import de.steamwar.fightsystem.ai.LocalCoordinate;
import lombok.Getter;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.HashSet;
@@ -30,15 +30,15 @@ import java.util.Set;
@Getter
public class Cannon {
private final List<Vector> tntPositions = new ArrayList<>();
private final Set<Vector> triggerPositions = new HashSet<>();
private final List<LocalCoordinate> tntPositions = new ArrayList<>();
private final Set<LocalCoordinate> triggerPositions = new HashSet<>();
public Cannon addTnt(Vector tnt) {
public Cannon addTnt(LocalCoordinate tnt) {
tntPositions.add(tnt);
return this;
}
public Cannon addTrigger(Vector trigger) {
public Cannon addTrigger(LocalCoordinate trigger) {
triggerPositions.add(trigger);
return this;
}
@@ -19,9 +19,9 @@
package de.steamwar.fightsystem.ai.schematic;
import de.steamwar.fightsystem.ai.LocalCoordinate;
import lombok.Getter;
import org.bukkit.util.Consumer;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
@@ -32,7 +32,7 @@ public class WarMachine {
private int schematicId = 0;
private Bridge bridge = new Bridge();
private List<Cannon> cannons = new ArrayList<>();
private List<Vector> tntChests = new ArrayList<>();
private List<LocalCoordinate> tntChests = new ArrayList<>();
public WarMachine setSchematicId(int schematicId) {
this.schematicId = schematicId;
@@ -51,7 +51,7 @@ public class WarMachine {
return this;
}
public WarMachine addTnTChest(Vector chest) {
public WarMachine addTnTChest(LocalCoordinate chest) {
tntChests.add(chest);
return this;
}
@@ -19,6 +19,7 @@
package de.steamwar.fightsystem.ai.schematic.impl;
import de.steamwar.fightsystem.ai.LocalCoordinate;
import de.steamwar.fightsystem.ai.schematic.WarMachine;
import org.bukkit.util.Vector;
@@ -38,27 +39,27 @@ public class MiniWarGear20 {
public static final WarMachine DPR_PV1_Reaper = new WarMachine()
.setSchematicId(135745)
.editBridge(bridge -> {
bridge.addShieldActivator(new Vector(23, 16, 19));
bridge.addShieldActivator(new Vector(32, 4, 13));
bridge.addShieldActivator(new Vector(20, 4, 13));
bridge.addShieldActivator(new LocalCoordinate(22, 15, 18));
bridge.addShieldActivator(new LocalCoordinate(31, 3, 12));
bridge.addShieldActivator(new LocalCoordinate(19, 3, 12));
})
.addCannon(cannon -> {
cannon.addTnt(new Vector(30, 2, 22));
cannon.addTnt(new Vector(30, 2, 23));
cannon.addTnt(new Vector(30, 2, 24));
cannon.addTnt(new Vector(31, 2, 23));
cannon.addTnt(new Vector(31, 2, 24));
cannon.addTnt(new Vector(30, 3, 25));
cannon.addTnt(new Vector(31, 3, 25));
cannon.addTnt(new Vector(30, 3, 26));
cannon.addTnt(new Vector(31, 3, 26));
cannon.addTnt(new Vector(30, 4, 25));
cannon.addTnt(new Vector(31, 4, 25));
cannon.addTnt(new Vector(30, 4, 26));
cannon.addTnt(new Vector(31, 4, 26));
cannon.addTrigger(new Vector(31, 4, 20));
cannon.addTrigger(new Vector(32, 4, 19));
cannon.addTrigger(new Vector(32, 4, 21));
cannon.addTnt(new LocalCoordinate(29, 1, 21));
cannon.addTnt(new LocalCoordinate(29, 1, 22));
cannon.addTnt(new LocalCoordinate(29, 1, 23));
cannon.addTnt(new LocalCoordinate(30, 1, 22));
cannon.addTnt(new LocalCoordinate(30, 1, 23));
cannon.addTnt(new LocalCoordinate(29, 2, 24));
cannon.addTnt(new LocalCoordinate(30, 2, 24));
cannon.addTnt(new LocalCoordinate(29, 2, 25));
cannon.addTnt(new LocalCoordinate(30, 2, 25));
cannon.addTnt(new LocalCoordinate(29, 3, 24));
cannon.addTnt(new LocalCoordinate(30, 3, 24));
cannon.addTnt(new LocalCoordinate(29, 3, 25));
cannon.addTnt(new LocalCoordinate(30, 3, 25));
cannon.addTrigger(new LocalCoordinate(30, 3, 19));
cannon.addTrigger(new LocalCoordinate(31, 3, 18));
cannon.addTrigger(new LocalCoordinate(31, 3, 20));
})
.finish(MiniWarGear20);
}
@@ -22,14 +22,13 @@ package de.steamwar.fightsystem.ai.yoyonow;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import de.steamwar.fightsystem.ai.AI;
import de.steamwar.fightsystem.ai.Action;
import de.steamwar.fightsystem.ai.WorldCoordinate;
import de.steamwar.fightsystem.ai.schematic.Cannon;
import de.steamwar.fightsystem.ai.schematic.WarMachine;
import de.steamwar.fightsystem.ai.schematic.impl.MiniWarGear20;
import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.List;
@@ -37,8 +36,6 @@ import java.util.Random;
public class YoyoNowAI extends AI {
private static final World WORLD = Bukkit.getWorlds().get(0);
private WarMachine selectedSchematic;
protected YoyoNowAI(FightTeam team) {
@@ -54,12 +51,14 @@ public class YoyoNowAI extends AI {
@Override
public void schematic(Clipboard clipboard) {
setReady();
}
private Random random = new Random();
private final Random random = new Random();
private List<Action> actions = new ArrayList<>();
private boolean setupDone = false;
@Override
protected void plan() {
if (!navMesh.isReady()) return;
@@ -67,20 +66,31 @@ public class YoyoNowAI extends AI {
if (!actions.isEmpty()) {
Action.Result result = actions.get(0).step(this);
if (result == Action.Result.FAILED) {
chat(actions.get(0) + " failed");
actions.clear();
return;
}
if (result == Action.Result.FINISHED) {
chat(actions.get(0) + " finished");
actions.remove(0);
return;
}
return;
}
List<WorldCoordinate> walkable = navMesh.walkable();
WorldCoordinate destination = walkable.get(random.nextInt(walkable.size()));
Action action = new Action.MoveAction(this, destination);
if (!action.isCompletable()) return;
actions.add(action);
if (!setupDone && FightState.getFightState() == FightState.POST_SCHEM_SETUP) {
chat("Setup actions to perform!");
selectedSchematic.getBridge().getShieldActivators().forEach(localCoordinate -> {
actions.add(new Action.MoveAction(this, localCoordinate.toWorld(getTeam())));
actions.add(new Action.InteractAction(localCoordinate));
});
actions.add(new Action.ReadyAction());
chat("Actions: " + actions.size());
setupDone = true;
}
if (FightState.getFightState() == FightState.RUNNING) {
Cannon cannon = selectedSchematic.getCannons().get(random.nextInt(selectedSchematic.getCannons().size()));
actions.add(new Action.LoadCannon(this, cannon));
}
}
}