View Issue Details

IDProjectCategoryLast Update
0025700AI War 2Crash/ExceptionNov 5, 2021 7:26 pm
ReporterDaniexpert Assigned ToChris_McElligottPark  
Severityminor 
Status resolvedResolutionfixed 
Product VersionBeta 3.740 Code Panopticon 
Fixed in VersionBeta 3.746 Phantom Ship Syndrome 
Summary0025700: Sappers, exception in UpdateConstructors
Description10/28/2021 7:25:35 PM 3.740 SINGLEP DELAYED8: Hit exception in UpdateConstructors debugCode 200 System.NullReferenceException: Object reference not set to an instance of an object
  at Arcen.AIW2.External.SappersFactionDeepInfo.BuildStructureIfPossible (Arcen.AIW2.Core.GameEntity_Squad sapper, Arcen.AIW2.External.SappersPerUnitBaseInfo data, Arcen.AIW2.Core.ArcenHostOnlySimContext Context) [0x0026a] in <083113ac50124e9ea7b6220dddc142b1>:0
  at Arcen.AIW2.External.SappersFactionDeepInfo.UpdateConstructors (Arcen.AIW2.Core.ArcenHostOnlySimContext Context) [0x000f4] in <083113ac50124e9ea7b6220dddc142b1>:0
TagsNo tags attached.

Activities

BadgerBadger

Oct 29, 2021 9:10 pm

manager   ~0063044

Chris, this is very confusing. Here's the code:
        public bool BuildStructureIfPossible( GameEntity_Squad sapper, SappersPerUnitBaseInfo data, ArcenHostOnlySimContext Context )
....
                debugCode = 100;
                if ( data == null )
                    throw new Exception("SappersPerUnitBaseInfo is null");
                if ( data.UnitToBuild != null && data.PlanetToBuildOn != null
                     && data.LocationToBuild != ArcenPoint.ZeroZeroPoint )
                {
                    debugCode = 200; <=== so we know that data is not null, data.PlanetToBuildOn is not null. sapper can't be null because we dereferenced it in the previous function (before passing it in here) in order to get the data object
                    int dist = -1;
                    if ( data.PlanetToBuildOn == sapper.Planet )
                    {
                        debugCode = 300;
                        if ( sapper.Planet.GetIsPointOutsideGravWell_SlowButCorrect( data.LocationToBuild ) )
                        {
                            debugCode = 400;
                            //There was a bug with variable gravwell sizes that could wind up with a LocationToBuild being
                            //outside the gravity well. This code will fix that bug. Remove it at some point
                            data.LocationToBuild = sapper.Planet.GetSafePlacementPointAroundPlanetCenter( Context, data.UnitToBuild, FInt.FromParts( 0, 100 ), FInt.FromParts( 0, 650 ) );
                            if ( sapper.Orders != null )
                                sapper.Orders.ClearOrders( ClearBehavior.DoNotClearBehaviors, ClearDecollisionOnParent.YesClear_AndAlsoClearDecollisionMoveOrders, ClearSource.YesClearAnyOrders_IncludingFromHumans, "Discarding bad orders" );
                        }
                        debugCode = 500;
                        dist = Mat.DistanceBetweenPointsImprecise( sapper.WorldLocation, data.LocationToBuild );
                    }
                    if ( tracing )
                        tracingBuffer.Add(sapper.ToString() + " at " + sapper.WorldLocation + " is going to build a " + data.UnitToBuild.GetDisplayName() + " at " + data.LocationToBuild + ". The distance to build location is " + dist +"\n");
                    debugCode = 600;

I suspect we're hitting some sort of threading problem, but I'm not sure where. The sapper entity in the above code is passed in from this for-loop in UpdateConstructors:
                List<GameEntity_Squad> constructors = this.BaseInfo.Constructors.GetDisplayList();
                for ( int i = 0; i < constructors.Count; i++ )
                {
                    debugCode = 200;
                    GameEntity_Squad entity = constructors[i];
                    SappersPerUnitBaseInfo data = entity.CreateExternalBaseInfo<SappersPerUnitBaseInfo>( "SappersPerUnitBaseInfo" );
....
                    //If we are at our target location, transform into a suitable turret
                    bool buildDone = BuildStructureIfPossible( entity, data, Context );

BadgerBadger

Oct 29, 2021 9:11 pm

manager   ~0063045

I think we have at some point checked all the dereferenced objects, so that implies some sort of threading issue. I thought GetDisplayList() was supposed to be safe though?

Chris_McElligottPark

Nov 5, 2021 7:26 pm

administrator   ~0063225

Thanks!

* Fixed a fairly funky bug in Sappers UpdateConstructors, which actually was in BuildStructureIfPossible, but because of its placement must have been related to the tracing buffers or something. Or more code has changed since the original report than I realized.
** At any rate, there's now a lot more instrumentation, so if the bug recurs, then we'll have a much more detailed idea of where it is. This is a whole class of bug that should largely be fixed by this release now, though.

Issue History

Date Modified Username Field Change
Oct 28, 2021 2:30 pm Daniexpert New Issue
Oct 29, 2021 9:10 pm BadgerBadger Note Added: 0063044
Oct 29, 2021 9:10 pm BadgerBadger Assigned To => Chris_McElligottPark
Oct 29, 2021 9:10 pm BadgerBadger Status new => assigned
Oct 29, 2021 9:11 pm BadgerBadger Note Added: 0063045
Nov 5, 2021 7:26 pm Chris_McElligottPark Status assigned => resolved
Nov 5, 2021 7:26 pm Chris_McElligottPark Resolution open => fixed
Nov 5, 2021 7:26 pm Chris_McElligottPark Fixed in Version => Beta 3.746 Phantom Ship Syndrome
Nov 5, 2021 7:26 pm Chris_McElligottPark Note Added: 0063225