diff --git a/core/assets/planets/serpulo.dat b/core/assets/planets/serpulo.dat deleted file mode 100644 index 3a1465dfde..0000000000 Binary files a/core/assets/planets/serpulo.dat and /dev/null differ diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index 68d41a171d..c6a448a642 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -5,11 +5,13 @@ import arc.func.*; import arc.math.*; import arc.math.geom.*; import arc.struct.*; +import arc.struct.ObjectIntMap.*; import arc.util.ArcAnnotate.*; import arc.util.*; import arc.util.noise.*; import mindustry.content.*; import mindustry.core.GameState.*; +import mindustry.ctype.*; import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.game.Teams.*; @@ -19,7 +21,6 @@ import mindustry.maps.*; import mindustry.maps.filters.*; import mindustry.maps.filters.GenerateFilter.*; import mindustry.type.*; -import mindustry.type.Sector.*; import mindustry.type.Weather.*; import mindustry.world.*; import mindustry.world.blocks.environment.*; @@ -261,9 +262,71 @@ public class World{ state.rules.weather.clear(); - if(sector.is(SectorAttribute.rainy)) state.rules.weather.add(new WeatherEntry(Weathers.rain)); - if(sector.is(SectorAttribute.snowy)) state.rules.weather.add(new WeatherEntry(Weathers.snow)); - if(sector.is(SectorAttribute.desert)) state.rules.weather.add(new WeatherEntry(Weathers.sandstorm)); + //apply weather based on terrain + ObjectIntMap floorc = new ObjectIntMap<>(); + ObjectSet content = new ObjectSet<>(); + + float waterFloors = 0, totalFloors = 0; + + for(Tile tile : world.tiles){ + if(world.getDarkness(tile.x, tile.y) >= 3){ + continue; + } + + Liquid liquid = tile.floor().liquidDrop; + if(tile.floor().itemDrop != null) content.add(tile.floor().itemDrop); + if(tile.overlay().itemDrop != null) content.add(tile.overlay().itemDrop); + if(liquid != null) content.add(liquid); + + if(!tile.block().isStatic()){ + totalFloors ++; + if(liquid == Liquids.water){ + waterFloors += tile.floor().isDeep() ? 1f : 0.7f; + } + floorc.increment(tile.floor()); + if(tile.overlay() != Blocks.air){ + floorc.increment(tile.overlay()); + } + } + } + + //sort counts in descending order + Seq> entries = floorc.entries().toArray(); + entries.sort(e -> -e.value); + //remove all blocks occuring < 30 times - unimportant + entries.removeAll(e -> e.value < 30); + + Block[] floors = new Block[entries.size]; + int[] floorCounts = new int[entries.size]; + for(int i = 0; i < entries.size; i++){ + floorCounts[i] = entries.get(i).value; + floors[i] = entries.get(i).key; + } + + //TODO bad code + boolean hasSnow = floors[0].name.contains("ice") || floors[0].name.contains("snow"); + boolean hasRain = !hasSnow && floors[0].name.contains("water"); + boolean hasDesert = !hasSnow && !hasRain && floors[0].name.contains("sand"); + boolean hasSpores = floors[0].name.contains("spore") || floors[0].name.contains("moss") || floors[0].name.contains("tainted"); + + if(hasSnow){ + state.rules.weather.add(new WeatherEntry(Weathers.snow)); + } + + if(hasRain){ + state.rules.weather.add(new WeatherEntry(Weathers.rain)); + } + + if(hasDesert){ + state.rules.weather.add(new WeatherEntry(Weathers.sandstorm)); + } + + if(hasSpores){ + state.rules.weather.add(new WeatherEntry(Weathers.sporestorm)); + } + + state.secinfo.resources = content.asArray(); + state.secinfo.resources.sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))); } diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 7b585890c3..5f61cb26ac 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -2,9 +2,10 @@ package mindustry.game; import arc.math.*; import arc.struct.*; -import arc.util.*; import arc.util.ArcAnnotate.*; +import arc.util.*; import mindustry.content.*; +import mindustry.ctype.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.storage.CoreBlock.*; @@ -32,6 +33,8 @@ public class SectorInfo{ public boolean hasCore = true; /** Sector that was launched from. */ public @Nullable Sector origin; + /** Resources known to occur at this sector. */ + public Seq resources = new Seq<>(); /** Time spent at this sector. Do not use unless you know what you're doing. */ public transient float internalTimeSpent; diff --git a/core/src/mindustry/game/Stats.java b/core/src/mindustry/game/Stats.java index 4a03f6199e..9cea3b582f 100644 --- a/core/src/mindustry/game/Stats.java +++ b/core/src/mindustry/game/Stats.java @@ -39,7 +39,7 @@ public class Stats{ //weigh used fractions float frac = 0f; - Seq obtainable = Seq.select(zone.data.resources, i -> i instanceof Item).as(); + Seq obtainable = zone.save == null ? new Seq<>() : zone.save.meta.secinfo.resources.select(i -> i instanceof Item).as(); for(Item item : obtainable){ frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; } diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java index a8995103d0..e6ea20cf9e 100644 --- a/core/src/mindustry/io/JsonIO.java +++ b/core/src/mindustry/io/JsonIO.java @@ -100,6 +100,20 @@ public class JsonIO{ } }); + json.setSerializer(Liquid.class, new Serializer(){ + @Override + public void write(Json json, Liquid object, Class knownType){ + json.writeValue(object.name); + } + + @Override + public Liquid read(Json json, JsonValue jsonData, Class type){ + if(jsonData.asString() == null) return Liquids.water; + Liquid i = Vars.content.getByName(ContentType.liquid, jsonData.asString()); + return i == null ? Liquids.water : i; + } + }); + json.setSerializer(Item.class, new Serializer(){ @Override public void write(Json json, Item object, Class knownType){ @@ -165,6 +179,21 @@ public class JsonIO{ return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount")); } }); + + json.setSerializer(UnlockableContent.class, new Serializer(){ + @Override + public void write(Json json, UnlockableContent object, Class knownType){ + json.writeValue(object.name); + } + + @Override + public UnlockableContent read(Json json, JsonValue jsonData, Class type){ + String str = jsonData.asString(); + Item item = Vars.content.getByName(ContentType.item, str); + Liquid liquid = Vars.content.getByName(ContentType.liquid, str); + return item != null ? item : liquid; + } + }); } static class CustomJson extends Json{ diff --git a/core/src/mindustry/io/SaveIO.java b/core/src/mindustry/io/SaveIO.java index 3ae3996d23..28202cd94c 100644 --- a/core/src/mindustry/io/SaveIO.java +++ b/core/src/mindustry/io/SaveIO.java @@ -77,6 +77,7 @@ public class SaveIO{ try{ return getMeta(getStream(file)); }catch(Exception e){ + e.printStackTrace(); return getMeta(getBackupStream(file)); } } diff --git a/core/src/mindustry/logic/LogicOp.java b/core/src/mindustry/logic/LogicOp.java index 126f5bd607..d463e51ee1 100644 --- a/core/src/mindustry/logic/LogicOp.java +++ b/core/src/mindustry/logic/LogicOp.java @@ -15,8 +15,8 @@ public enum LogicOp{ greaterThan(">", (a, b) -> a > b ? 1 : 0), greaterThanEq(">=", (a, b) -> a >= b ? 1 : 0), pow("^", Math::pow), - shl(">>", (a, b) -> (long)a >> (long)b), - shr("<<", (a, b) -> (long)a << (long)b), + shl("<<", (a, b) -> (long)a << (long)b), + shr(">>", (a, b) -> (long)a >> (long)b), or("or", (a, b) -> (long)a | (long)b), and("and", (a, b) -> (long)a & (long)b), xor("xor", (a, b) -> (long)a ^ (long)b), diff --git a/core/src/mindustry/maps/generators/FileMapGenerator.java b/core/src/mindustry/maps/generators/FileMapGenerator.java index e0b8bf3946..dab00370ed 100644 --- a/core/src/mindustry/maps/generators/FileMapGenerator.java +++ b/core/src/mindustry/maps/generators/FileMapGenerator.java @@ -3,7 +3,6 @@ package mindustry.maps.generators; import arc.math.*; import arc.math.geom.*; import mindustry.content.*; -import mindustry.ctype.*; import mindustry.game.*; import mindustry.io.*; import mindustry.maps.*; @@ -29,12 +28,13 @@ public class FileMapGenerator implements WorldGenerator{ world.setGenerating(true); tiles = world.tiles; + Item[] items = {Items.blastCompound, Items.pyratite, Items.copper, Items.thorium, Items.copper, Items.lead}; for(Tile tile : tiles){ if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock) && state.hasSector()){ - for(Content content : state.getSector().data.resources){ - if(content instanceof Item && Mathf.chance(0.3)){ - tile.build.items.add((Item)content, Math.min(Mathf.random(500), tile.block().itemCapacity)); + for(Item content : items){ + if(Mathf.chance(0.2)){ + tile.build.items.add(content, Math.min(Mathf.random(500), tile.block().itemCapacity)); } } } diff --git a/core/src/mindustry/maps/generators/PlanetGenerator.java b/core/src/mindustry/maps/generators/PlanetGenerator.java index 2ce0bbae27..6bbc15ed2f 100644 --- a/core/src/mindustry/maps/generators/PlanetGenerator.java +++ b/core/src/mindustry/maps/generators/PlanetGenerator.java @@ -5,7 +5,6 @@ import arc.util.noise.*; import mindustry.graphics.g3d.*; import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.type.*; -import mindustry.type.Sector.*; import mindustry.world.*; public abstract class PlanetGenerator extends BasicGenerator implements HexMesher{ @@ -24,7 +23,7 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe if(noise < 0.15){ for(Ptile other : tile.tiles){ - if(sector.planet.getSector(other).is(SectorAttribute.base)){ + if(sector.planet.getSector(other).generateEnemyBase){ any = false; break; } @@ -32,7 +31,7 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe } if(any){ - sector.data.attributes |= (1 << SectorAttribute.base.ordinal()); + sector.generateEnemyBase = true; } } diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 570671de4f..651c5c7923 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -1,7 +1,6 @@ package mindustry.type; import arc.*; -import arc.files.*; import arc.func.*; import arc.graphics.*; import arc.math.*; @@ -10,15 +9,12 @@ import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; -import arc.util.io.*; import arc.util.noise.*; -import mindustry.*; import mindustry.ctype.*; import mindustry.graphics.*; import mindustry.graphics.g3d.*; import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.maps.generators.*; -import mindustry.type.Sector.*; import static mindustry.Vars.*; @@ -83,25 +79,10 @@ public class Planet extends UnlockableContent{ sectors = new Seq<>(grid.tiles.length); for(int i = 0; i < grid.tiles.length; i++){ - sectors.add(new Sector(this, grid.tiles[i], new SectorData())); + sectors.add(new Sector(this, grid.tiles[i])); } sectorApproxRadius = sectors.first().tile.v.dst(sectors.first().tile.corners[0].v); - - //read data for sectors - Fi data = Vars.tree.get("planets/" + name + ".dat"); - if(data.exists()){ - try{ - try(Reads read = data.reads()){ - short dsize = read.s(); - for(int i = 0; i < dsize; i++){ - sectors.get(i).data.read(read); - } - } - }catch(Throwable t){ - t.printStackTrace(); - } - } }else{ sectors = new Seq<>(); } @@ -196,7 +177,7 @@ public class Planet extends UnlockableContent{ for(Sector sector : sectors){ float sum = 1f; for(Sector other : sector.inRange(2)){ - if(other.is(SectorAttribute.base)){ + if(other.generateEnemyBase){ sum += 1f; } } diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 856dd2219d..137c1b0142 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -7,12 +7,9 @@ import arc.struct.ObjectIntMap.*; import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; -import arc.util.io.*; import mindustry.*; -import mindustry.ctype.*; import mindustry.game.Saves.*; import mindustry.graphics.g3d.PlanetGrid.*; -import mindustry.world.*; import static mindustry.Vars.*; @@ -27,24 +24,22 @@ public class Sector{ public final Ptile tile; public final int id; - public final SectorData data; - public @Nullable SaveSlot save; public @Nullable SectorPreset preset; /** Number 0-1 indicating the difficulty based on nearby bases. */ public float baseCoverage; + public boolean generateEnemyBase; //TODO implement a dynamic launch period public int launchPeriod = 10; - public Sector(Planet planet, Ptile tile, SectorData data){ + public Sector(Planet planet, Ptile tile){ this.planet = planet; this.tile = tile; this.plane = new Plane(); this.rect = makeRect(); this.id = tile.id; - this.data = data; } public Seq inRange(int range){ @@ -100,7 +95,7 @@ public class Sector{ /** @return whether the enemy has a generated base here. */ public boolean hasEnemyBase(){ - return is(SectorAttribute.base) && (save == null || save.meta.rules.waves); + return generateEnemyBase && (save == null || save.meta.rules.waves); } public boolean isBeingPlayed(){ @@ -311,10 +306,6 @@ public class Sector{ return new SectorRect(radius, center, planeTop, planeRight, angle); } - public boolean is(SectorAttribute attribute){ - return (data.attributes & (1 << attribute.ordinal())) != 0; - } - public static class SectorRect{ public final Vec3 center, top, right; public final Vec3 result = new Vec3(); @@ -335,64 +326,4 @@ public class Sector{ return result.set(center).add(right, nx).add(top, ny); } } - - /** Cached data about a sector. */ - public static class SectorData{ - public UnlockableContent[] resources = {}; - public int spawnX, spawnY; - - public Block[] floors = {}; - public int[] floorCounts = {}; - public int attributes; - - public void write(Writes write){ - write.s(resources.length); - for(Content resource : resources){ - write.b(resource.getContentType().ordinal()); - write.s(resource.id); - } - write.s(spawnX); - write.s(spawnY); - write.s(floors.length); - for(int i = 0; i < floors.length; i++){ - write.s(floors[i].id); - write.i(floorCounts[i]); - } - - write.i(attributes); - } - - public void read(Reads read){ - resources = new UnlockableContent[read.s()]; - for(int i = 0; i < resources.length; i++){ - resources[i] = Vars.content.getByID(ContentType.all[read.b()], read.s()); - } - spawnX = read.s(); - spawnY = read.s(); - floors = new Block[read.s()]; - floorCounts = new int[floors.length]; - for(int i = 0; i < floors.length; i++){ - floors[i] = Vars.content.block(read.s()); - floorCounts[i] = read.i(); - } - attributes = read.i(); - } - } - - public enum SectorAttribute{ - /** Requires naval technology to land on, e.g. mostly water */ - naval, - /** Has rain. */ - rainy, - /** Has snow. */ - snowy, - /** Has sandstorms. */ - desert, - /** Has an enemy base. */ - base, - /** Has spore weather. */ - spores, - /** Path from core to spawns requires traversing water. */ - navalPath - } } diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 3462891f6a..022a92b770 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -321,16 +321,25 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.row(); } - stable.add("@sectors.resources").row(); - stable.table(t -> { - t.left(); - int idx = 0; - int max = 5; - for(UnlockableContent c : sector.data.resources){ - t.image(c.icon(Cicon.small)).padRight(3); - if(++idx % max == 0) t.row(); - } - }).fillX().row(); + if(sector.save != null){ + stable.add("@sectors.resources").row(); + stable.table(t -> { + + if(sector.save != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.resources.any()){ + t.left(); + int idx = 0; + int max = 5; + for(UnlockableContent c : sector.save.meta.secinfo.resources){ + t.image(c.icon(Cicon.small)).padRight(3); + if(++idx % max == 0) t.row(); + } + }else{ + t.add("@unknown").color(Color.lightGray); + } + + + }).fillX().row(); + } //production if(sector.hasBase() && sector.save.meta.hasProduction){ diff --git a/tools/build.gradle b/tools/build.gradle index 1b45dd95c0..3266834485 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -409,16 +409,6 @@ task genSprites(dependsOn: classes, type: JavaExec){ workingDir = genFolder } -task genSectorData(dependsOn: classes, type: JavaExec){ - main = "mindustry.tools.SectorDataGenerator" - classpath = sourceSets.main.runtimeClasspath - standardInput = System.in - workingDir = "../core/assets/" -} - -task updateCache(dependsOn: [genSectorData]){ -} - task updateBundles(dependsOn: classes, type: JavaExec){ file(genFolder).mkdirs() diff --git a/tools/src/mindustry/tools/SectorDataGenerator.java b/tools/src/mindustry/tools/SectorDataGenerator.java deleted file mode 100644 index 622a0b2466..0000000000 --- a/tools/src/mindustry/tools/SectorDataGenerator.java +++ /dev/null @@ -1,228 +0,0 @@ -package mindustry.tools; - -import arc.*; -import arc.backend.headless.mock.*; -import arc.files.*; -import arc.math.geom.*; -import arc.mock.*; -import arc.struct.*; -import arc.struct.ObjectIntMap.*; -import arc.util.*; -import arc.util.io.*; -import mindustry.*; -import mindustry.content.*; -import mindustry.core.*; -import mindustry.ctype.*; -import mindustry.game.*; -import mindustry.net.Net; -import mindustry.type.*; -import mindustry.type.Sector.*; -import mindustry.world.*; -import mindustry.world.blocks.storage.*; -import mindustry.world.blocks.storage.CoreBlock.*; - -import static mindustry.Vars.*; - -public class SectorDataGenerator{ - - public static void main(String[] args){ - ArcNativesLoader.load(); - Core.files = new MockFiles(); - Core.app = new MockApplication(); - Core.settings = new MockSettings(); - Core.graphics = new MockGraphics(); - - headless = true; - net = new Net(null); - tree = new FileTree(); - Vars.init(); - content.createBaseContent(); - - logic = new Logic(); - netServer = new NetServer(); - world = new World(); - - content.init(); - - for(Planet planet : content.getBy(ContentType.planet)){ - int[] count = {0}; - if(planet.grid == null) continue; - - Fi fi = Fi.get("planets").child(planet.name + ".dat"); - - Seq list = planet.sectors.map(sector -> { - SectorData data = new SectorData(); - - ObjectIntMap floors = new ObjectIntMap<>(); - ObjectSet content = new ObjectSet<>(); - - logic.reset(); - world.loadSector(sector); - float waterFloors = 0, totalFloors = 0; - state.rules.sector = sector; - - for(Tile tile : world.tiles){ - if(world.getDarkness(tile.x, tile.y) >= 3){ - continue; - } - - Liquid liquid = tile.floor().liquidDrop; - if(tile.floor().itemDrop != null) content.add(tile.floor().itemDrop); - if(tile.overlay().itemDrop != null) content.add(tile.overlay().itemDrop); - if(liquid != null) content.add(liquid); - - if(!tile.block().isStatic()){ - totalFloors ++; - if(liquid == Liquids.water){ - waterFloors += tile.floor().isDeep() ? 1f : 0.7f; - } - floors.increment(tile.floor()); - if(tile.overlay() != Blocks.air){ - floors.increment(tile.overlay()); - } - } - } - - CoreBuild entity = Team.sharded.core(); - int cx = entity.tileX(), cy = entity.tileY(); - - boolean path = pathfind(true); - boolean groundPath = pathfind(false); - - if(!path){ - Log.err("Sector &ly@&lr has no core path!", sector.id); - } - - if(!groundPath){ - Log.debug("&lbSector &ly@&lb is naval-only", sector.id); - - data.attributes |= (1 << SectorAttribute.navalPath.ordinal()); - } - - int nearTiles = 0; - int waterCheckRad = 5; - - //check for water presence - for(int rx = -waterCheckRad; rx <= waterCheckRad; rx++){ - for(int ry = -waterCheckRad; ry <= waterCheckRad; ry++){ - Tile tile = world.tile(cx + rx, cy + ry); - if(tile == null || tile.floor().liquidDrop != null){ - nearTiles ++; - } - } - } - - if(waterFloors / totalFloors >= 0.6f){ - Log.debug("Sector @ has @/@ water -> naval", sector.id, waterFloors, totalFloors); - } - - //naval sector guaranteed - if(nearTiles > 4){ - Log.debug("Sector @ has @ water tiles at @ @ -> naval", sector.id, nearTiles, cx, cy); - waterFloors = totalFloors; - } - - //sort counts in descending order - Seq> entries = floors.entries().toArray(); - entries.sort(e -> -e.value); - //remove all blocks occuring < 30 times - unimportant - entries.removeAll(e -> e.value < 30); - - data.floors = new Block[entries.size]; - data.floorCounts = new int[entries.size]; - for(int i = 0; i < entries.size; i++){ - data.floorCounts[i] = entries.get(i).value; - data.floors[i] = entries.get(i).key; - } - - //TODO bad code - boolean hasSnow = data.floors[0].name.contains("ice") || data.floors[0].name.contains("snow"); - boolean hasRain = !hasSnow && data.floors[0].name.contains("water"); - boolean hasDesert = !hasSnow && !hasRain && data.floors[0].name.contains("sand"); - boolean hasSpores = data.floors[0].name.contains("spore") || data.floors[0].name.contains("moss") || data.floors[0].name.contains("tainted"); - - if(hasSnow){ - data.attributes |= (1 << SectorAttribute.snowy.ordinal()); - } - - if(hasRain){ - data.attributes |= (1 << SectorAttribute.rainy.ordinal()); - } - - if(hasDesert){ - data.attributes |= (1 << SectorAttribute.desert.ordinal()); - } - - if(hasSpores){ - data.attributes |= (1 << SectorAttribute.spores.ordinal()); - } - - data.resources = content.asArray().sort(Structs.comps(Structs.comparing(Content::getContentType), Structs.comparingInt(c -> c.id))).toArray(UnlockableContent.class); - - //50% water -> naval attribute - if(waterFloors / totalFloors >= 0.6f){ - data.attributes |= (1 << SectorAttribute.naval.ordinal()); - } - - if(count[0]++ % 10 == 0){ - Log.info("&ly[ &lg@% &ly] Done with sector &lm@/@ ", (int)((float)count[0] / planet.sectors.size * 100), count[0], planet.sectors.size); - } - - return data; - }); - - //write data - try(Writes write = fi.writes()){ - write.s(list.size); - list.each(s -> s.write(write)); - } - } - } - - private static boolean pathfind(boolean allowWater){ - CoreBuild entity = Team.sharded.core(); - - IntSet enemies = new IntSet(); - world.tiles.eachTile(t -> { - if((t.team() == Team.crux && t.block() instanceof CoreBlock) || t.overlay() == Blocks.spawn){ - enemies.add(t.pos()); - } - }); - - GridBits used = new GridBits(world.width(), world.height()); - - IntQueue queue = new IntQueue(); - queue.addFirst(entity.pos()); - boolean any = false; - - outer: - while(!queue.isEmpty()){ - int pos = queue.removeFirst(); - int x = Point2.x(pos), y = Point2.y(pos); - used.set(x, y); - - for(Point2 p : Geometry.d4){ - int nx = p.x + x, ny = p.y + y; - - if(world.tiles.in(nx, ny) && !used.get(nx, ny)){ - Tile tile = world.tile(nx, ny); - - //skip full solids - if((tile.block().isStatic() && tile.solid()) || (!allowWater && tile.floor().isLiquid)) continue; - - int newpos = Point2.pack(nx, ny); - - used.set(nx, ny); - queue.addLast(newpos); - - if(enemies.contains(newpos)){ - any = true; - break outer; - } - } - } - } - - return any; - } -}