diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml new file mode 100644 index 0000000000..dc50a787fd --- /dev/null +++ b/.github/workflows/dependencies.yml @@ -0,0 +1,18 @@ +name: build +on: + push: + branches: + - develop # run the action on your projects default branch + +jobs: + build: + name: Dependencies + runs-on: ubuntu-latest + permissions: # The Dependency Submission API requires write permission + contents: write + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v3 + + - name: Run snapshot action + uses: mikepenz/gradle-dependency-submission@v0.9.1 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8be4069a15..44a8af9ccf 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ plugins { id "application" id "base" id "java" - id "org.ajoberstar.grgit" version "5.2.0" + id "org.ajoberstar.grgit" version "5.2.1" id "com.diffplug.spotless" version "6.22.0" id 'org.openjfx.javafxplugin' version '0.0.13' id 'org.beryx.runtime' version '1.13.0' @@ -343,7 +343,7 @@ dependencies { // Image processing lib implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-core', version: '3.10.1' // https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-core - implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-jpeg', version: '3.8.2' // https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-core + implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-jpeg', version: '3.10.1' // https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-core implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-psd', version: '3.10.1' // https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-psd implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-tiff', version: '3.10.1' implementation group: 'com.twelvemonkeys.imageio', name: 'imageio-batik', version: '3.10.1' @@ -366,7 +366,7 @@ dependencies { // ftp client implementation 'commons-net:commons-net:3.10.0' // commandline parsing - implementation 'commons-cli:commons-cli:1.5.0' + implementation 'commons-cli:commons-cli:1.6.0' // needed for preference dialog at runtime implementation 'commons-beanutils:commons-beanutils:1.9.4' @@ -388,9 +388,9 @@ dependencies { implementation group: 'com.jidesoft', name: 'jide-shortcut', version: '3.7.9' // webserver for old webapp that is scheduled for removal - implementation 'org.eclipse.jetty:jetty-server:9.4.42.v20210604' + implementation 'org.eclipse.jetty:jetty-server:9.4.51.v20230217' implementation 'org.eclipse.jetty:jetty-servlet:9.4.42.v20210604' - implementation 'org.eclipse.jetty:jetty-webapp:9.4.42.v20210604' + implementation 'org.eclipse.jetty:jetty-webapp:9.4.44.v20210927' implementation 'org.eclipse.jetty:jetty-continuation:9.4.42.v20210604' implementation 'org.eclipse.jetty.websocket:websocket-client:9.4.53.v20231009' implementation 'org.eclipse.jetty.websocket:websocket-server:9.4.53.v20231009' @@ -433,13 +433,13 @@ dependencies { implementation 'com.jayway.jsonpath:json-path:2.8.0' // For PDF image extraction - implementation 'org.apache.pdfbox:pdfbox:2.0.28' - implementation 'org.apache.pdfbox:pdfbox-tools:2.0.28' + implementation 'org.apache.pdfbox:pdfbox:3.0.0' + implementation 'org.apache.pdfbox:pdfbox-tools:3.0.0' implementation 'org.bouncycastle:bcmail-jdk15on:1.70' // To decrypt passworded/secured pdf's implementation 'com.github.jai-imageio:jai-imageio-core:1.4.0' // For pdf image extraction, specifically for jpeg2000 (jpx) support. implementation 'com.github.jai-imageio:jai-imageio-jpeg2000:1.4.0' // For pdf image extraction, specifically for jpeg2000 (jpx) support. - implementation 'com.github.gotson:webp-imageio:0.2.1' // webp support https://search.maven.org/artifact/com.github.gotson/webp-imageio/0.2.1/jar + implementation 'com.github.gotson:webp-imageio:0.2.2' // webp support https://search.maven.org/artifact/com.github.gotson/webp-imageio/0.2.2/jar // For syntax highlighting in macro editor implementation "com.fifesoft:rsyntaxtextarea:3.3.4" // https://mvnrepository.com/artifact/com.fifesoft/rsyntaxtextarea @@ -471,7 +471,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.1' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.1' // For mocking features during unit tests testImplementation group: 'org.mockito', name: 'mockito-core', version: '5.7.0' @@ -486,7 +486,7 @@ dependencies { implementation 'com.github.cwisniew:NoiseLib:1.0.0' // The most recent version, 1.0.0 is build for a later java version: major version 55 is newer than 54, the highest major version supported by this compiler // webrtc - implementation group: 'org.java-websocket', name: 'Java-WebSocket', version: '1.5.3' + implementation group: 'org.java-websocket', name: 'Java-WebSocket', version: '1.5.4' implementation 'dev.onvoid.webrtc:webrtc-java:0.8.0' if (osdetector.os.is('windows')) implementation 'dev.onvoid.webrtc:webrtc-java:0.8.0:windows-x86_64' diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaContainer.java b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaContainer.java index 054af1c106..b4d92d5eeb 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaContainer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaContainer.java @@ -24,6 +24,7 @@ import org.locationtech.jts.geom.prep.PreparedGeometry; public interface AreaContainer { + public Area getBounds(); /** @@ -38,24 +39,20 @@ public interface AreaContainer { /** * Find sections of the container's boundary that block vision. * - *

Each returned segment is a sequence of connected faces which constitute an unbroken section - * of the container's boundary that would block vision. Each segment is aware of `origin` so that - * it can construct areas that cannot be seen from `origin`. + *

Each returned segment is a sequence of connected line segments which constitute an unbroken + * section of the container's boundary, where each segment faces the direction chosen by {@code + * facing}. * *

The segments that are returned depend on `origin`, and `frontSegments`. * * @param geometryFactory The strategy for creating geometries, which is used by the * `VisibleAreaSegment` in creating areas of blocked vision. * @param origin The point from which visibility is calculated. - * @param frontSegments If `true`, only front-facing boundary segments are returned. Otherwise, - * only back-facing boundary segments are returned. Due to winding order, back-facing and - * front-facing are interpreted differently for oceans and islands. + * @param facing Whether the returned segments must have their island side or their ocean side + * facing the origin. * @return A list of segments, which together represent the complete set of boundary faces that * block vision. */ public List getVisionBlockingBoundarySegments( - GeometryFactory geometryFactory, - Coordinate origin, - boolean frontSegments, - PreparedGeometry vision); + GeometryFactory geometryFactory, Coordinate origin, Facing facing, PreparedGeometry vision); } diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaIsland.java b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaIsland.java index 16c4dd5f2c..6f52e922a6 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaIsland.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaIsland.java @@ -88,10 +88,7 @@ public Area getBounds() { @Override public List getVisionBlockingBoundarySegments( - GeometryFactory geometryFactory, - Coordinate origin, - boolean frontSegments, - PreparedGeometry vision) { - return meta.getFacingSegments(geometryFactory, origin, !frontSegments, vision); + GeometryFactory geometryFactory, Coordinate origin, Facing facing, PreparedGeometry vision) { + return meta.getFacingSegments(geometryFactory, origin, facing, vision); } } diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaMeta.java b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaMeta.java index 5b951aaa7a..f7bbc1fc18 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaMeta.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaMeta.java @@ -56,16 +56,29 @@ public boolean isEmpty() { } /** - * @param origin - * @param faceAway If `true`, only return segments facing away from origin. - * @return + * Returns all line segments in the boundary that face the requested direction. + * + *

For each line segment, the exterior region will be on one side of the segment while the + * interior region will be on the other side. One of these regions will be an island and one will + * be an ocean depending on {@link #isHole()}. The {@code facing} parameter uses this fact to + * control whether a segment should be included in the result, based on whether the origin is on + * the island-side of the line segment or on its ocean-side. + * + *

If {@code origin} is colinear with a line segment, that segment will never be returned. + * + * @param origin The vision origin, which is the point by which line segment orientation is + * measured. + * @param facing Whether the island-side or the ocean-side of the returned segments must face + * {@code origin}. + * @return All line segments with a facing that matches {@code facing} based on the position of + * {@code origin}. The line segments are joined into continguous line strings where possible. */ public List getFacingSegments( - GeometryFactory geometryFactory, - Coordinate origin, - boolean faceAway, - PreparedGeometry vision) { - final var requiredOrientation = faceAway ? Orientation.CLOCKWISE : Orientation.COUNTERCLOCKWISE; + GeometryFactory geometryFactory, Coordinate origin, Facing facing, PreparedGeometry vision) { + final var requiredOrientation = + facing == Facing.ISLAND_SIDE_FACES_ORIGIN + ? Orientation.CLOCKWISE + : Orientation.COUNTERCLOCKWISE; List segments = new ArrayList<>(); List currentSegmentPoints = new ArrayList<>(); diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaOcean.java b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaOcean.java index 04868d97d5..020c773e6b 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaOcean.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/AreaOcean.java @@ -58,15 +58,12 @@ public void setParentIsland(AreaIsland parentIsland) { @Override public List getVisionBlockingBoundarySegments( - GeometryFactory geometryFactory, - Coordinate origin, - boolean frontSegments, - PreparedGeometry vision) { + GeometryFactory geometryFactory, Coordinate origin, Facing facing, PreparedGeometry vision) { if (meta == null) { return Collections.emptyList(); } - return meta.getFacingSegments(geometryFactory, origin, frontSegments, vision); + return meta.getFacingSegments(geometryFactory, origin, facing, vision); } @Override diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/Facing.java b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/Facing.java new file mode 100644 index 0000000000..5d3d9af7f6 --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/Facing.java @@ -0,0 +1,20 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code 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. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client.ui.zone.vbl; + +public enum Facing { + OCEAN_SIDE_FACES_ORIGIN, + ISLAND_SIDE_FACES_ORIGIN +} diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/VisionBlockingAccumulator.java b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/VisionBlockingAccumulator.java index 428c899734..52365adbdd 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/vbl/VisionBlockingAccumulator.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/vbl/VisionBlockingAccumulator.java @@ -17,7 +17,6 @@ import java.awt.Point; import java.util.ArrayList; import java.util.List; -import javax.annotation.Nullable; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; @@ -49,24 +48,19 @@ public List getVisionBlockingSegments() { return visionBlockingSegments; } - private void addVisionBlockingSegments(AreaContainer areaContainer, boolean frontSide) { + private void addVisionBlockingSegments(AreaContainer areaContainer, Facing facing) { var segments = areaContainer.getVisionBlockingBoundarySegments( - geometryFactory, originCoordinate, frontSide, vision); + geometryFactory, originCoordinate, facing, vision); visionBlockingSegments.addAll(segments); } - private void addIslandForHillBlocking( - AreaIsland blockingIsland, @Nullable AreaOcean excludeChildOcean) { + private void addIslandForHillBlocking(AreaIsland blockingIsland) { // The back side of the island blocks. - addVisionBlockingSegments(blockingIsland, false); + addVisionBlockingSegments(blockingIsland, Facing.ISLAND_SIDE_FACES_ORIGIN); // The front side of each contained ocean also acts as a back side boundary of the island. for (var blockingOcean : blockingIsland.getOceans()) { - if (blockingOcean == excludeChildOcean) { - continue; - } - - addVisionBlockingSegments(blockingOcean, true); + addVisionBlockingSegments(blockingOcean, Facing.ISLAND_SIDE_FACES_ORIGIN); } } @@ -91,15 +85,14 @@ public boolean addWallBlocking(AreaTree topology) { final var parentIsland = ocean.getParentIsland(); if (parentIsland != null) { // The near edge of the island blocks vision, which is the same as the boundary of this - // ocean. Since we're inside the ocean, the facing edges of the parent island are like the - // back side. - addVisionBlockingSegments(ocean, false); + // ocean, which we're inside. + addVisionBlockingSegments(ocean, Facing.OCEAN_SIDE_FACES_ORIGIN); } // Check each contained island. for (var containedIsland : ocean.getIslands()) { // The front side of wall VBL blocks vision. - addVisionBlockingSegments(containedIsland, true); + addVisionBlockingSegments(containedIsland, Facing.OCEAN_SIDE_FACES_ORIGIN); } } @@ -133,14 +126,13 @@ public boolean addHillBlocking(AreaTree topology) { * 1. The back side of the parent ocean's parent island. * 2. The back side of any sibling islands (other children of the parent ocean). * 3. The back side of any child ocean's islands. - * 4. For each island in the above, any child ocean provided it's not the parent of the - * current island. + * 4. For each island in the above, the front side of any child ocean. */ final var parentOcean = island.getParentOcean(); final var grandparentIsland = parentOcean.getParentIsland(); if (grandparentIsland != null) { - addIslandForHillBlocking(grandparentIsland, parentOcean); + addIslandForHillBlocking(grandparentIsland); } for (final var siblingIsland : parentOcean.getIslands()) { @@ -151,12 +143,12 @@ public boolean addHillBlocking(AreaTree topology) { continue; } - addIslandForHillBlocking(siblingIsland, null); + addIslandForHillBlocking(siblingIsland); } for (final var childOcean : island.getOceans()) { for (final var grandchildIsland : childOcean.getIslands()) { - addIslandForHillBlocking(grandchildIsland, null); + addIslandForHillBlocking(grandchildIsland); } } } else if (container instanceof final AreaOcean ocean) { @@ -168,11 +160,11 @@ public boolean addHillBlocking(AreaTree topology) { */ final var parentIsland = ocean.getParentIsland(); if (parentIsland != null) { - addIslandForHillBlocking(parentIsland, null); + addIslandForHillBlocking(parentIsland); } // Check each contained island. for (var containedIsland : ocean.getIslands()) { - addIslandForHillBlocking(containedIsland, null); + addIslandForHillBlocking(containedIsland); } } @@ -201,13 +193,10 @@ public boolean addPitBlocking(AreaTree topology) { */ if (container instanceof final AreaIsland island) { - /* - * Since we're in an island, vision is blocked by: - * 1. The back side of the island. - * 2. The front side of any child ocean. - */ - // These are actually the same rules as for the hill case, it's just the context that differs. - addIslandForHillBlocking(island, null); + addVisionBlockingSegments(island, Facing.ISLAND_SIDE_FACES_ORIGIN); + for (var childOcean : island.getOceans()) { + addVisionBlockingSegments(childOcean, Facing.ISLAND_SIDE_FACES_ORIGIN); + } } return true; @@ -238,28 +227,21 @@ public boolean addCoverBlocking(AreaTree topology) { final var parentOcean = island.getParentOcean(); for (final var siblingIsland : parentOcean.getIslands()) { - if (siblingIsland == island) { - continue; - } - addVisionBlockingSegments(siblingIsland, true); + addVisionBlockingSegments(siblingIsland, Facing.OCEAN_SIDE_FACES_ORIGIN); } for (final var childOcean : island.getOceans()) { for (final var grandchildIsland : childOcean.getIslands()) { - addVisionBlockingSegments(grandchildIsland, true); + addVisionBlockingSegments(grandchildIsland, Facing.OCEAN_SIDE_FACES_ORIGIN); } - addVisionBlockingSegments(childOcean, false); + addVisionBlockingSegments(childOcean, Facing.OCEAN_SIDE_FACES_ORIGIN); } - addVisionBlockingSegments(parentOcean, false); - addVisionBlockingSegments(island, true); - + addVisionBlockingSegments(parentOcean, Facing.OCEAN_SIDE_FACES_ORIGIN); + addVisionBlockingSegments(island, Facing.OCEAN_SIDE_FACES_ORIGIN); } else if (container instanceof AreaOcean ocean) { - final var parentIsland = ocean.getParentIsland(); - if (parentIsland != null) { - addVisionBlockingSegments(ocean, true); - } + addVisionBlockingSegments(ocean, Facing.OCEAN_SIDE_FACES_ORIGIN); for (var containedIsland : ocean.getIslands()) { - addVisionBlockingSegments(containedIsland, true); + addVisionBlockingSegments(containedIsland, Facing.OCEAN_SIDE_FACES_ORIGIN); } } diff --git a/src/main/java/net/rptools/maptool/util/ExtractImagesFromPDF.java b/src/main/java/net/rptools/maptool/util/ExtractImagesFromPDF.java index f89c4d26b8..e3fccde10c 100644 --- a/src/main/java/net/rptools/maptool/util/ExtractImagesFromPDF.java +++ b/src/main/java/net/rptools/maptool/util/ExtractImagesFromPDF.java @@ -34,6 +34,7 @@ import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.pdfbox.Loader; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.pdmodel.PDDocument; @@ -105,7 +106,7 @@ public ExtractImagesFromPDF(File pdfFile, boolean forceRescan, boolean extractRe return; } - document = PDDocument.load(pdfFile); + document = Loader.loadPDF(pdfFile); if (extractRenderedPages) { renderer = new PDFRenderer(document);