Skip to content

Commit

Permalink
Fix NPE with loaded save games from past versions. (#11783)
Browse files Browse the repository at this point in the history
The issue is that old saved games may save references to the GamePlayer on various objects, including pending battles.

Since 2.6 has an invariant that all GamePlayer objects have a non-null getData(), which was not true in 2.5 and earlier, we need to update these after loading the game. In particular, we need to fix up all references to the null player with the instance from the game data.

This was already being done for units and territories via GameData::fixUpNullPlayers(). This adds it also for pending battles.
  • Loading branch information
asvitkine committed Jul 16, 2023
1 parent 1ce2262 commit c4f9314
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,14 @@ private void fixUpNullPlayers() {
}
}

@RemoveOnNextMajorRelease
public void fixUpNullPlayersInDelegates() {
BattleDelegate battleDelegate = (BattleDelegate) getDelegate("battle");
if (battleDelegate != null) {
battleDelegate.getBattleTracker().fixUpNullPlayers(playerList.getNullPlayer());
}
}

public interface Unlocker extends Closeable {
@Override
void close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public static Optional<GameData> loadGameUncompressed(final InputStream is) {
final GameData data = (GameData) input.readObject();
data.postDeSerialize();
loadDelegates(input, data);
data.fixUpNullPlayersInDelegates();
return Optional.of(data);
} catch (final Throwable e) {
log.warn(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.Getter;
import org.triplea.java.ObjectUtils;
import org.triplea.java.RemoveOnNextMajorRelease;
import org.triplea.java.collections.CollectionUtils;
import org.triplea.java.collections.IntegerMap;
Expand All @@ -42,7 +43,7 @@ abstract class AbstractBattle implements IBattle {
boolean headless = false;

@Getter final Territory battleSite;
final GamePlayer attacker;
GamePlayer attacker;
GamePlayer defender;
final BattleTracker battleTracker;
int round = 1;
Expand Down Expand Up @@ -227,6 +228,16 @@ public GamePlayer getDefender() {
return defender;
}

@Override
public void fixUpNullPlayer(GamePlayer nullPlayer) {
if (attacker.isNull() && !ObjectUtils.referenceEquals(attacker, nullPlayer)) {
attacker = nullPlayer;
}
if (defender.isNull() && !ObjectUtils.referenceEquals(defender, nullPlayer)) {
defender = nullPlayer;
}
}

public void setHeadless(final boolean headless) {
this.headless = headless;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;
import org.triplea.java.RemoveOnNextMajorRelease;
import org.triplea.java.collections.CollectionUtils;
import org.triplea.java.collections.IntegerMap;
import org.triplea.sound.ISound;
Expand Down Expand Up @@ -176,6 +177,13 @@ private boolean didThesePlayersJustGoToWarThisTurn(final GamePlayer p1, final Ga
return false;
}

@RemoveOnNextMajorRelease
public void fixUpNullPlayers(GamePlayer nullPlayer) {
for (var b : pendingBattles) {
b.fixUpNullPlayer(nullPlayer);
}
}

void clearFinishedBattles(final IDelegateBridge bridge) {
for (final IBattle battle : List.copyOf(pendingBattles)) {
if (FinishedBattle.class.isAssignableFrom(battle.getClass())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
import org.triplea.java.RemoveOnNextMajorRelease;

/** Represents a battle. */
public interface IBattle extends Serializable {
Expand Down Expand Up @@ -165,5 +166,8 @@ void unitsLostInPrecedingBattle(

GamePlayer getDefender();

@RemoveOnNextMajorRelease
void fixUpNullPlayer(GamePlayer nullPlayer);

UUID getBattleId();
}

0 comments on commit c4f9314

Please sign in to comment.