diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index e7f1539d2f..799e2b2031 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -562,6 +562,7 @@ asset.image.importzip = Import Image Zip asset.image.exportzip = Export Image Zip asset.clearall = Clear All asset.clearall.confirm = Are you sure that you want to clear [red]all[] assets from this map?\nThis includes images, audio, content, etc. +asset.path.invalid = Path is invalid! asset.imports = Import Results asset.imported = [accent]{0} assets imported. asset.import.none = No valid asset files found in zip archive. diff --git a/core/src/mindustry/ai/ControlPathfinder.java b/core/src/mindustry/ai/ControlPathfinder.java index 513810df98..25a3f7b57f 100644 --- a/core/src/mindustry/ai/ControlPathfinder.java +++ b/core/src/mindustry/ai/ControlPathfinder.java @@ -317,6 +317,9 @@ public class ControlPathfinder implements Runnable{ for(var fields : controlPath.fieldList){ try{ + int mx = World.toTile(Core.input.mouseWorldX()); + int my = World.toTile(Core.input.mouseWorldY()); + int hoverValue = -100; for(var entry : fields.fields){ int cx = entry.key % controlPath.cwidth, cy = entry.key / controlPath.cwidth; for(int y = 0; y < clusterSize; y++){ @@ -326,9 +329,15 @@ public class ControlPathfinder implements Runnable{ Lines.stroke(0.8f, Tmp.c1.fromHsv(value * 3f, 1f, 1f)); Draw.alpha(0.5f); Fill.square((x + cx * clusterSize) * tilesize, (y + cy * clusterSize) * tilesize, tilesize / 2f); + if(mx == (x + cx * clusterSize) && my == (y + cy * clusterSize)){ + hoverValue = value; + } } } } + if(hoverValue > -100){ + Drawf.text(hoverValue + " / " + fields.cost.getCost(Team.sharded.id, pathfinder.get(mx, my)), Core.input.mouseWorldX(), Core.input.mouseWorldY(), Color.white); + } }catch(Exception ignored){} //probably has some concurrency issues when iterating but I don't care, this is for debugging } }); @@ -1360,30 +1369,6 @@ public class ControlPathfinder implements Runnable{ return true; } - /** @return 0 if nothing was hit, otherwise the packed coordinates. This is an internal function and will likely be moved - do not use!*/ - public static int raycastFast(int team, PathCost type, int x1, int y1, int x2, int y2){ - int ww = world.width(), wh = world.height(); - int x = x1, dx = Math.abs(x2 - x), sx = x < x2 ? 1 : -1; - int y = y1, dy = Math.abs(y2 - y), sy = y < y2 ? 1 : -1; - int err = dx - dy; - - while(x >= 0 && y >= 0 && x < ww && y < wh){ - if(solid(team, type, x + y * wwidth, true)) return Point2.pack(x, y); - if(x == x2 && y == y2) return 0; - - //no diagonals - if(2 * err + dy > dx - 2 * err){ - err -= dy; - x += sx; - }else{ - err += dx; - y += sy; - } - } - - return 0; - } - /** @return 0 if nothing was hit, otherwise the packed coordinates. This is an internal function and will likely be moved - do not use!*/ public static int raycastFastAvoid(int team, PathCost type, int x1, int y1, int x2, int y2){ int ww = world.width(), wh = world.height(); diff --git a/core/src/mindustry/ai/Pathfinder.java b/core/src/mindustry/ai/Pathfinder.java index 26f6adf602..f2baaaaddb 100644 --- a/core/src/mindustry/ai/Pathfinder.java +++ b/core/src/mindustry/ai/Pathfinder.java @@ -8,6 +8,7 @@ import arc.struct.*; import arc.util.TaskQueue; import arc.util.*; import mindustry.annotations.Annotations.*; +import mindustry.content.*; import mindustry.core.*; import mindustry.game.EventType.*; import mindustry.game.*; @@ -219,18 +220,19 @@ public class Pathfinder implements Runnable{ /** Packs a tile into its internal representation. */ public int packTile(Tile tile){ - boolean nearLiquid = false, nearSolid = false, nearLegSolid = false, nearGround = false, solid = tile.solid(), allDeep = tile.floor().isDeep(), nearDeep = allDeep; + boolean nearLiquid = false, nearSolid = false, nearLegSolid = false, nearGround = false, solid = tile.solid(), allDeep = tile.isDeep(), nearDeep = allDeep; for(int i = 0; i < 4; i++){ Tile other = tile.nearby(i); if(other != null){ Floor floor = other.floor(); boolean osolid = other.solid(); - if(floor.isLiquid && floor.isDeep()) nearLiquid = true; + boolean deep = other.isDeep(); + if(floor.isLiquid && deep) nearLiquid = true; //TODO potentially strange behavior when teamPassable is false for other teams? if(osolid && !other.block().teamPassable) nearSolid = true; if(!floor.isLiquid) nearGround = true; - if(!floor.isDeep()){ + if(!deep){ allDeep = false; }else{ nearDeep = true; @@ -248,7 +250,7 @@ public class Pathfinder implements Runnable{ if(allDeep){ for(int i = 0; i < 4; i++){ Tile other = tile.nearby(Geometry.d8edge[i]); - if(other != null && !other.floor().isDeep()){ + if(other != null && !other.isDeep()){ allDeep = false; break; } @@ -261,13 +263,13 @@ public class Pathfinder implements Runnable{ tile.build == null || !solid || tile.block() instanceof CoreBlock ? 0 : Math.min((int)(tile.build.health / 40), 80), tid == 0 && tile.build != null && state.rules.coreCapture ? 255 : tid, //use teamid = 255 when core capture is enabled to mark out derelict structures solid, - tile.floor().isLiquid, + tile.floor().isLiquid && tile.block() == Blocks.air, tile.legSolid(), nearLiquid, nearGround, nearSolid, nearLegSolid, - tile.floor().isDeep(), + tile.isDeep(), tile.floor().damages(), allDeep, nearDeep, diff --git a/core/src/mindustry/editor/data/MapImagesView.java b/core/src/mindustry/editor/data/MapImagesView.java index 28c880c79d..297e8d3980 100644 --- a/core/src/mindustry/editor/data/MapImagesView.java +++ b/core/src/mindustry/editor/data/MapImagesView.java @@ -263,6 +263,11 @@ public class MapImagesView implements AssetView{ ui.showTextInput("@save.rename", "@patch.path", image.path, res -> { if(!res.endsWith(".png")) res = res + ".png"; + if(!DataAsset.validPath(res)){ + ui.showErrorMessage("@asset.path.invalid"); + return; + } + Fi fi = new Fi(res); String name = fi.nameWithoutExtension(); String path = fi.pathWithoutExtension(); diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index becc951f63..0889862e93 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -169,7 +169,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Unitc{ Color floorColor = tile == null ? Color.clear : tile.getFloorColor(); Floor floor = tile == null ? Blocks.air.asFloor() : tile.floor(); - if(floor.isDeep()){ + if(tile != null && tile.isDeep()){ deeps ++; lastDeepFloor = floor; } @@ -179,7 +179,7 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Unitc{ //create effect when transitioning to a group it can't move in if(!move && (moving || !type.legContinuousMove) && i % div == l.group){ if(!headless && !inFogTo(player.team())){ - if(floor.isLiquid){ + if(floor.isLiquid && tile != null && tile.block() == Blocks.air){ floor.walkEffect.at(l.base.x, l.base.y, type.rippleScale, floorColor); floor.walkSound.at(x, y, 1f, floor.walkSoundVolume); }else{ diff --git a/core/src/mindustry/mod/data/DataAsset.java b/core/src/mindustry/mod/data/DataAsset.java index dde7dea04d..860939ba67 100644 --- a/core/src/mindustry/mod/data/DataAsset.java +++ b/core/src/mindustry/mod/data/DataAsset.java @@ -114,6 +114,15 @@ public abstract class DataAsset implements Comparable{ } } + public static boolean validPath(String path){ + for(String part : path.replace('\\', '/').split("/")){ + if(part.equals("..") || part.equals(".")){ + return false; + } + } + return true; + } + @Override public String toString(){ return getClass().getSimpleName() + "{" + path + "}"; diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java index 000060be03..f63c681e41 100644 --- a/core/src/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/mindustry/ui/fragments/PlacementFragment.java @@ -807,7 +807,7 @@ public class PlacementFragment{ } //if the tile has a drop, display the drop - if((hoverTile.drop() != null && hoverTile.block() == Blocks.air) || hoverTile.wallDrop() != null || hoverTile.floor().liquidDrop != null){ + if((hoverTile.drop() != null && hoverTile.block() == Blocks.air) || hoverTile.wallDrop() != null || (hoverTile.floor().liquidDrop != null && hoverTile.block() == Blocks.air)){ return hoverTile; } } diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index 3db5a8ebcd..7ab828049f 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -467,6 +467,10 @@ public class Tile implements Position, QuadTreeObject, Displayable{ return !block.solid && (floor.isDeep() || floor.damages()); } + public boolean isDeep(){ + return block == Blocks.air && floor.isDeep(); + } + /** * Iterates through the list of all tiles linked to this multiblock, or just itself if it's not a multiblock. * The result contains all linked tiles, including this tile itself.