mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-07 05:50:54 +07:00
Set cleanup
This commit is contained in:
parent
603d8b16d0
commit
a240c00ebf
@ -4,6 +4,7 @@ import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.EnumSet;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
@ -15,6 +16,8 @@ import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** Class used for indexing special target blocks for AI. */
|
||||
@ -28,22 +31,21 @@ public class BlockIndexer{
|
||||
private final IntSet intSet = new IntSet();
|
||||
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
||||
/** Stores all ore quadtrants on the map. */
|
||||
private ObjectMap<Item, ObjectSet<Tile>> ores = new ObjectMap<>();
|
||||
private ObjectMap<Item, TileArray> ores = new ObjectMap<>();
|
||||
/** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */
|
||||
private GridBits[] structQuadrants;
|
||||
/** Stores all damaged tile entities by team. */
|
||||
private ObjectSet<Tile>[] damagedTiles = new ObjectSet[Team.all().length];
|
||||
private TileArray[] damagedTiles = new TileArray[Team.all().length];
|
||||
/**All ores available on this map.*/
|
||||
private ObjectSet<Item> allOres = new ObjectSet<>();
|
||||
/**Stores teams that are present here as tiles.*/
|
||||
private ObjectSet<Team> activeTeams = new ObjectSet<>();
|
||||
|
||||
private Array<Team> activeTeams = new Array<>();
|
||||
/** Maps teams to a map of flagged tiles by type. */
|
||||
private ObjectSet<Tile>[][] flagMap = new ObjectSet[Team.all().length][BlockFlag.all.length];
|
||||
private TileArray[][] flagMap = new TileArray[Team.all().length][BlockFlag.all.length];
|
||||
/** Maps tile positions to their last known tile index data. */
|
||||
private IntMap<TileIndex> typeMap = new IntMap<>();
|
||||
/** Empty set used for returning. */
|
||||
private ObjectSet<Tile> emptySet = new ObjectSet<>();
|
||||
private TileArray emptySet = new TileArray();
|
||||
/** Array used for returning and reusing. */
|
||||
private Array<Tile> returnArray = new Array<>();
|
||||
|
||||
@ -62,12 +64,12 @@ public class BlockIndexer{
|
||||
Events.on(WorldLoadEvent.class, event -> {
|
||||
scanOres.clear();
|
||||
scanOres.addAll(Item.getAllOres());
|
||||
damagedTiles = new ObjectSet[Team.all().length];
|
||||
flagMap = new ObjectSet[Team.all().length][BlockFlag.all.length];
|
||||
damagedTiles = new TileArray[Team.all().length];
|
||||
flagMap = new TileArray[Team.all().length][BlockFlag.all.length];
|
||||
|
||||
for(int i = 0; i < flagMap.length; i++){
|
||||
for(int j = 0; j < BlockFlag.all.length; j++){
|
||||
flagMap[i][j] = new ObjectSet<>();
|
||||
flagMap[i][j] = new TileArray();
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +100,7 @@ public class BlockIndexer{
|
||||
});
|
||||
}
|
||||
|
||||
private ObjectSet<Tile>[] getFlagged(Team team){
|
||||
private TileArray[] getFlagged(Team team){
|
||||
return flagMap[team.id];
|
||||
}
|
||||
|
||||
@ -130,14 +132,14 @@ public class BlockIndexer{
|
||||
}
|
||||
|
||||
/** Returns all damaged tiles by team. */
|
||||
public ObjectSet<Tile> getDamaged(Team team){
|
||||
public TileArray getDamaged(Team team){
|
||||
returnArray.clear();
|
||||
|
||||
if(damagedTiles[team.id] == null){
|
||||
damagedTiles[team.id] = new ObjectSet<>();
|
||||
damagedTiles[team.id] = new TileArray();
|
||||
}
|
||||
|
||||
ObjectSet<Tile> set = damagedTiles[team.id];
|
||||
TileArray set = damagedTiles[team.id];
|
||||
for(Tile tile : set){
|
||||
if((tile.entity == null || tile.entity.team() != team || !tile.entity.damaged()) || tile.block() instanceof BuildBlock){
|
||||
returnArray.add(tile);
|
||||
@ -152,7 +154,7 @@ public class BlockIndexer{
|
||||
}
|
||||
|
||||
/** Get all allied blocks with a flag. */
|
||||
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
||||
public TileArray getAllied(Team team, BlockFlag type){
|
||||
return flagMap[team.id][type.ordinal()];
|
||||
}
|
||||
|
||||
@ -194,7 +196,7 @@ public class BlockIndexer{
|
||||
returnArray.clear();
|
||||
for(Team enemy : team.enemies()){
|
||||
if(state.teams.isActive(enemy)){
|
||||
ObjectSet<Tile> set = getFlagged(enemy)[type.ordinal()];
|
||||
TileArray set = getFlagged(enemy)[type.ordinal()];
|
||||
if(set != null){
|
||||
for(Tile tile : set){
|
||||
returnArray.add(tile);
|
||||
@ -207,10 +209,10 @@ public class BlockIndexer{
|
||||
|
||||
public void notifyTileDamaged(Tilec entity){
|
||||
if(damagedTiles[(int)entity.team().id] == null){
|
||||
damagedTiles[(int)entity.team().id] = new ObjectSet<>();
|
||||
damagedTiles[(int)entity.team().id] = new TileArray();
|
||||
}
|
||||
|
||||
ObjectSet<Tile> set = damagedTiles[(int)entity.team().id];
|
||||
TileArray set = damagedTiles[(int)entity.team().id];
|
||||
set.add(entity.tile());
|
||||
}
|
||||
|
||||
@ -273,7 +275,7 @@ public class BlockIndexer{
|
||||
* each tile will at least have an ore within {@link #quadrantSize} / 2 blocks of it.
|
||||
* Only specific ore types are scanned. See {@link #scanOres}.
|
||||
*/
|
||||
public ObjectSet<Tile> getOrePositions(Item item){
|
||||
public TileArray getOrePositions(Item item){
|
||||
return ores.get(item, emptySet);
|
||||
}
|
||||
|
||||
@ -297,11 +299,11 @@ public class BlockIndexer{
|
||||
|
||||
private void process(Tile tile){
|
||||
if(tile.block().flags.size() > 0 && tile.team() != Team.derelict){
|
||||
ObjectSet<Tile>[] map = getFlagged(tile.team());
|
||||
TileArray[] map = getFlagged(tile.team());
|
||||
|
||||
for(BlockFlag flag : tile.block().flags){
|
||||
|
||||
ObjectSet<Tile> arr = map[flag.ordinal()];
|
||||
TileArray arr = map[flag.ordinal()];
|
||||
|
||||
arr.add(tile);
|
||||
|
||||
@ -309,7 +311,9 @@ public class BlockIndexer{
|
||||
}
|
||||
typeMap.put(tile.pos(), new TileIndex(tile.block().flags, tile.team()));
|
||||
}
|
||||
activeTeams.add(tile.team());
|
||||
if(!activeTeams.contains(tile.team())){
|
||||
activeTeams.add(tile.team());
|
||||
}
|
||||
|
||||
if(ores == null) return;
|
||||
|
||||
@ -331,7 +335,7 @@ public class BlockIndexer{
|
||||
|
||||
//update quadrant at this position
|
||||
for(Item item : scanOres){
|
||||
ObjectSet<Tile> set = ores.get(item);
|
||||
TileArray set = ores.get(item);
|
||||
|
||||
//update quadrant status depending on whether the item is in it
|
||||
if(!itemSet.contains(item)){
|
||||
@ -391,7 +395,7 @@ public class BlockIndexer{
|
||||
|
||||
//initialize ore map with empty sets
|
||||
for(Item item : scanOres){
|
||||
ores.put(item, new ObjectSet<>());
|
||||
ores.put(item, new TileArray());
|
||||
}
|
||||
|
||||
for(Tile tile : world.tiles){
|
||||
@ -417,4 +421,34 @@ public class BlockIndexer{
|
||||
this.team = team;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TileArray implements Iterable<Tile>{
|
||||
private Array<Tile> tiles = new Array<>(false, 16);
|
||||
private IntSet contained = new IntSet();
|
||||
|
||||
public void add(Tile tile){
|
||||
if(contained.add(tile.pos())){
|
||||
tiles.add(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(Tile tile){
|
||||
if(contained.remove(tile.pos())){
|
||||
tiles.remove(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return tiles.size;
|
||||
}
|
||||
|
||||
public Tile first(){
|
||||
return tiles.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Tile> iterator(){
|
||||
return tiles.iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
50
core/src/mindustry/ai/NewBlockIndexer.java
Normal file
50
core/src/mindustry/ai/NewBlockIndexer.java
Normal file
@ -0,0 +1,50 @@
|
||||
package mindustry.ai;
|
||||
|
||||
//new indexer implementation, uses quadtrees
|
||||
public class NewBlockIndexer{
|
||||
|
||||
/*
|
||||
public ObjectSet<Tile> getOrePositions(Item item){
|
||||
|
||||
}
|
||||
|
||||
public Tile findClosestOre(float xp, float yp, Item item){
|
||||
|
||||
}
|
||||
|
||||
public ObjectSet<Tile> getDamaged(Team team){
|
||||
|
||||
}
|
||||
|
||||
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
||||
|
||||
}
|
||||
|
||||
public boolean eachBlock(Teamc team, float range, Boolf<Tilec> pred, Cons<Tilec> cons){
|
||||
return eachBlock(team.team(), team.getX(), team.getY(), range, pred, cons);
|
||||
}
|
||||
|
||||
public boolean eachBlock(Team team, float wx, float wy, float range, Boolf<Tilec> pred, Cons<Tilec> cons){
|
||||
|
||||
}
|
||||
|
||||
public Array<Tile> getEnemy(Team team, BlockFlag type){
|
||||
|
||||
}
|
||||
|
||||
public void notifyTileDamaged(Tilec entity){
|
||||
|
||||
}
|
||||
|
||||
public Tilec findEnemyTile(Team team, float x, float y, float range, Boolf<Tilec> pred){
|
||||
|
||||
}
|
||||
|
||||
public Tilec findTile(Team team, float x, float y, float range, Boolf<Tilec> pred, boolean usePriority){
|
||||
|
||||
}
|
||||
|
||||
public Tilec findTile(Team team, float x, float y, float range, Boolf<Tilec> pred){
|
||||
return findTile(team, x, y, range, pred, false);
|
||||
}*/
|
||||
}
|
@ -8,6 +8,7 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.math.geom.QuadTree.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
@ -34,7 +35,7 @@ import static mindustry.Vars.*;
|
||||
|
||||
@EntityDef(value = {Tilec.class}, isFinal = false, genio = false, serialize = false)
|
||||
@Component
|
||||
abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
|
||||
abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTreeObject{
|
||||
//region vars and initialization
|
||||
static final float timeToSleep = 60f * 1;
|
||||
static final ObjectSet<Tilec> tmpTiles = new ObjectSet<>();
|
||||
@ -996,5 +997,10 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc{
|
||||
updateFlow = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitbox(Rect out){
|
||||
out.setCentered(x, y, block.size * tilesize, block.size * tilesize);
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class Team implements Comparable<Team>{
|
||||
}
|
||||
|
||||
public static Team get(int id){
|
||||
return all[Pack.u((byte)id)];
|
||||
return all[((byte)id) & 0xff];
|
||||
}
|
||||
|
||||
/** @return the 6 base team colors. */
|
||||
|
@ -3,6 +3,7 @@ package mindustry.world;
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.math.geom.QuadTree.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
@ -15,7 +16,7 @@ import mindustry.world.modules.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Tile implements Position{
|
||||
public class Tile implements Position, QuadTreeObject{
|
||||
/** Tile traversal cost. */
|
||||
public byte cost = 1;
|
||||
/** Tile entity, usually null. */
|
||||
@ -377,7 +378,12 @@ public class Tile implements Position{
|
||||
}
|
||||
|
||||
public Rect getHitbox(Rect rect){
|
||||
return rect.setSize(block().size * tilesize).setCenter(drawx(), drawy());
|
||||
return rect.setCentered(drawx(), drawy(), block.size * tilesize, block.size * tilesize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hitbox(Rect rect){
|
||||
getHitbox(rect);
|
||||
}
|
||||
|
||||
public Tile getNearby(Point2 relative){
|
||||
|
@ -9,6 +9,7 @@ import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.ai.BlockIndexer.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.units.*;
|
||||
@ -94,9 +95,9 @@ public class CommandCenter extends Block{
|
||||
@Override
|
||||
public void placed(){
|
||||
super.placed();
|
||||
ObjectSet<Tile> set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
TileArray set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
|
||||
if(set.size > 0){
|
||||
if(set.size() > 0){
|
||||
CommandCenterEntity oe = set.first().ent();
|
||||
command = oe.command;
|
||||
}
|
||||
@ -106,9 +107,9 @@ public class CommandCenter extends Block{
|
||||
public void onRemoved(){
|
||||
super.onRemoved();
|
||||
|
||||
ObjectSet<Tile> set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
TileArray set = indexer.getAllied(team, BlockFlag.comandCenter);
|
||||
|
||||
if(set.size == 1){
|
||||
if(set.size() == 1){
|
||||
Groups.unit.each(t -> t.team() == team, u -> u.controller().command(UnitCommand.all[0]));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import arc.*;
|
||||
import arc.backend.headless.*;
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
@ -277,6 +279,72 @@ public class ApplicationTests{
|
||||
world.tile(0, 0).entity.acceptStack(Items.copper, 1000, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexingBasic(){
|
||||
resetWorld();
|
||||
SaveIO.load(Core.files.internal("77.msav"));
|
||||
|
||||
//test basic method.
|
||||
Rand r = new Rand(0);
|
||||
Tilec[] res = {null};
|
||||
|
||||
Cons<Tilec> assigner = t -> res[0] = t;
|
||||
|
||||
int iterations = 100;
|
||||
|
||||
r.setSeed(0);
|
||||
|
||||
//warmup.
|
||||
for(int i = 0; i < iterations; i++){
|
||||
int x = r.random(0, world.width()), y = r.random(0, world.height());
|
||||
float range = r.random(tilesize * 30);
|
||||
|
||||
indexer.eachBlock(Team.sharded, x * tilesize, y * tilesize, range, t -> true, assigner);
|
||||
}
|
||||
|
||||
//TODO impl
|
||||
/*
|
||||
r.setSeed(0);
|
||||
|
||||
for(int i = 0; i < iterations; i++){
|
||||
int x = r.random(0, world.width()), y = r.random(0, world.height());
|
||||
float range = r.random(tilesize * 30);
|
||||
|
||||
indexer.eachBlock2(Team.sharded, x * tilesize, y * tilesize, range, t -> true, assigner);
|
||||
}*/
|
||||
|
||||
//benchmark.
|
||||
|
||||
r.setSeed(0);
|
||||
|
||||
Time.mark();
|
||||
|
||||
for(int i = 0; i < iterations; i++){
|
||||
int x = r.random(0, world.width()), y = r.random(0, world.height());
|
||||
float range = r.random(tilesize * 30);
|
||||
|
||||
indexer.eachBlock(Team.sharded, x * tilesize, y * tilesize, range, t -> true, assigner);
|
||||
}
|
||||
|
||||
Log.info("Time for basic indexing: {0}", Time.elapsed());
|
||||
|
||||
r.setSeed(0);
|
||||
|
||||
/*
|
||||
Time.mark();
|
||||
|
||||
for(int i = 0; i < iterations; i++){
|
||||
int x = r.random(0, world.width()), y = r.random(0, world.height());
|
||||
float range = r.random(tilesize * 30);
|
||||
|
||||
indexer.eachBlock2(Team.sharded, x * tilesize, y * tilesize, range, t -> true, assigner);
|
||||
}
|
||||
|
||||
Log.info("Time for quad: {0}", Time.elapsed());
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void conveyorBench(){
|
||||
int[] itemsa = {0};
|
||||
|
Loading…
Reference in New Issue
Block a user