diff --git a/vasl_templates/webapp/tests/fixtures/analyze-vsav/hip-concealed.vsav b/vasl_templates/webapp/tests/fixtures/analyze-vsav/hip-concealed.vsav new file mode 100644 index 0000000..11ac2e2 Binary files /dev/null and b/vasl_templates/webapp/tests/fixtures/analyze-vsav/hip-concealed.vsav differ diff --git a/vasl_templates/webapp/tests/test_vassal.py b/vasl_templates/webapp/tests/test_vassal.py index 7620c07..ea81f13 100644 --- a/vasl_templates/webapp/tests/test_vassal.py +++ b/vasl_templates/webapp/tests/test_vassal.py @@ -577,6 +577,33 @@ def test_analyze_vsav( webapp, webdriver ): # run the test against all versions of VASSAL+VASL _run_tests( control_tests, do_test, not pytest.config.option.short_tests ) #pylint: disable=no-member +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +@pytest.mark.skipif( not pytest.config.option.vasl_mods, reason="--vasl-mods not specified" ) #pylint: disable=no-member +@pytest.mark.skipif( not pytest.config.option.vassal, reason="--vassal not specified" ) #pylint: disable=no-member +def test_analyze_vsav_hip_concealed( webapp, webdriver ): + """Test analyzing a scenario that contains HIP and concealed units.""" + + # initialize + control_tests = init_webapp( webapp, webdriver, vsav_persistence=1, scenario_persistence=1, + reset = lambda ct: ct.set_data_dir( dtype="real" ) + ) + + def do_test(): #pylint: disable=missing-docstring + + # NOTE: The test scenario contains hidden/concealed units belonging to the Russians and Germans, + # but because the owning user is test/password, they should be ignored (unless you configure VASSAL + # with these credentials, so don't do that :-/). + new_scenario() + _analyze_vsav( "hip-concealed.vsav", + [ [], [] ], + [ [], [] ], + [ "No vehicles/ordnance were imported." ] + ) + + # run the test against all versions of VASSAL+VASL + _run_tests( control_tests, do_test, not pytest.config.option.short_tests ) #pylint: disable=no-member + # --------------------------------------------------------------------- def _run_tests( control_tests, func, test_all ): diff --git a/vassal-shim/release/vassal-shim.jar b/vassal-shim/release/vassal-shim.jar index 3219a8f..ed55dcf 100644 Binary files a/vassal-shim/release/vassal-shim.jar and b/vassal-shim/release/vassal-shim.jar differ diff --git a/vassal-shim/src/vassal_shim/VassalShim.java b/vassal-shim/src/vassal_shim/VassalShim.java index 7fe2a32..6b36c51 100644 --- a/vassal-shim/src/vassal_shim/VassalShim.java +++ b/vassal-shim/src/vassal_shim/VassalShim.java @@ -57,9 +57,8 @@ import VASSAL.command.AlertCommand ; import VASSAL.build.module.map.boardPicker.Board ; import VASSAL.counters.GamePiece ; import VASSAL.counters.BasicPiece ; +import VASSAL.counters.Decorator ; import VASSAL.counters.DynamicProperty ; -import VASSAL.counters.Hideable ; -import VASSAL.counters.FreeRotator ; import VASSAL.counters.PieceCloner ; import VASSAL.preferences.Prefs ; import VASSAL.tools.DataArchive ; @@ -155,7 +154,31 @@ public class VassalShim // analyze the scenario logger.info( "Analyzing scenario: " + scenarioFilename ) ; HashMap results = new HashMap() ; - analyzeCommand( cmd, results ) ; + for ( GamePiece gamePiece: GameModule.getGameModule().getGameState().getAllPieces() ) { + if ( gamePiece.getProperty(VASSAL.counters.Properties.OBSCURED_BY) != null || gamePiece.getProperty(VASSAL.counters.Properties.HIDDEN_BY) != null ) { + // IMPORTANT: VASSAL blanks out the name of concealed/HIP pieces if they don't belong to the calling user, + // but we still get the GPID, which is enough for the main program to figure out which entry to create. + // This means that people could use this feature to analyze a scenario in progess, to figure out + // what their opponent's concealed/hidden OB is. To avoid this, we exclude these pieces from the report. + continue ; + } + // see if this piece has a GPID + GamePiece gp = Decorator.getInnermost( gamePiece ) ; + if ( !( gp instanceof BasicPiece ) ) + continue ; + // yup - check if it's one we're interested in + String gpid = ((BasicPiece)gp).getGpId() ; + if ( gpid.equals( "" ) || gpid.equals( labelGpid ) ) + continue ; + // yup - add it to the results + if ( ! results.containsKey( gpid ) ) { + logger.debug( "Found new GPID " + gpid + ": " + gamePiece.getName() ) ; + results.put( gpid, new AnalyzeNode( gamePiece.getName() ) ) ; + } else { + int newCount = results.get( gpid ).incrementCount() ; + logger.debug( "Updating count for GPID " + gpid + ": #=" + newCount ) ; + } + } // generate the report Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument() ; @@ -240,6 +263,8 @@ public class VassalShim private void extractLabels( Command cmd, Map ourLabels, ArrayList otherLabels ) { // check if this command is a label we're interested in + // NOTE: We shouldn't really be looking at the object type, see analyzeScenario(). + // http://www.gamesquad.com/forums/index.php?threads/new-program-to-help-set-up-vasl-scenarios.148281/post-1983751 if ( cmd instanceof AddPiece ) { AddPiece addPieceCmd = (AddPiece) cmd ; if ( addPieceCmd.getTarget() instanceof DynamicProperty ) { @@ -811,39 +836,6 @@ public class VassalShim buf.append( ": " + cmd.getAllowedIds() ) ; } - private void analyzeCommand( Command cmd, Map results ) - { - // analyze the command - if ( cmd instanceof AddPiece ) { - GamePiece target = ((AddPiece)cmd).getTarget() ; - logger.debug( "Found piece: " + cmd.getClass().getName() + " ; target=" + target.getClass().getName() ) ; - // NOTE: Hideable's don't seem to be just a thing with old versions of VASSAL. We still get them - // when adding a "46mm granatnik wz. 36" (GPID 2172) using VASL 6.4.4 :-/ This also seems to happen - // with other 1/2" SW counters. - // NOTE: Other pieces also occasionally appear with weird class types e.g. the Japanese Type 88 75 AA Gun - // appears as a FreeRotator?! - if ( target instanceof DynamicProperty || target instanceof Hideable || target instanceof FreeRotator - || target.getClass().getName().equals("VASL.counters.TextInfo") - ) { - int pos = target.getState().lastIndexOf( ";" ) ; - String gpid = target.getState().substring( pos+1 ) ; - if ( ! gpid.equals( labelGpid ) ) { - if ( ! results.containsKey( gpid ) ) { - logger.debug( "Found new GPID " + gpid + ": " + target.getName() ) ; - results.put( gpid, new AnalyzeNode( target.getName() ) ) ; - } else { - int newCount = results.get( gpid ).incrementCount() ; - logger.debug( "Updating count for GPID " + gpid + ": #=" + newCount ) ; - } - } - } - } - - // analyze any sub-commands - for ( Command c: cmd.getSubCommands() ) - analyzeCommand( c, results ) ; - } - private static void parseGamePieceState( String state, ArrayList separators, ArrayList fields ) { // parse the GamePiece state