Emberveil sourcetests/LostCityCheck.java
import com.rs2.game.content.quests.QuestRewards;
import com.rs2.game.players.*;
import com.rs2.game.items.ItemDefinitions;
import org.apollo.cache.IndexedFileSystem;
import org.apollo.cache.decoder.*;
import java.nio.file.*;
/** Inherited Lost City completion boundaries through real object/reward/save paths. */
public final class LostCityCheck {
static int checks;
static void check(boolean ok,String label){checks++;if(!ok)throw new AssertionError(label);}
static GertrudesCatCheck.Fixture player(int stage,boolean spirit){GertrudesCatCheck.Fixture p=new GertrudesCatCheck.Fixture();p.lostCity=stage;p.spiritTree=spirit;p.playerEquipment[p.playerWeapon]=772;p.absX=3202;p.absY=3169;return p;}
static void door(Player p){p.getObjects().firstClickObject(2406,3202,3169);}
public static void main(String[] args)throws Exception {
IndexedFileSystem cache=new IndexedFileSystem(Paths.get("data/cache"),true);new ItemDefinitionDecoder(cache).run();ItemDefinitions.load();new ObjectDefinitionDecoder(cache).run();
for(int stage=0;stage<=2;stage++){
GertrudesCatCheck.Fixture p=player(stage,false);door(p);check(p.lostCity==stage&&p.questPoints==0&&!p.isTeleporting,"borrowed staff cannot bypass stage "+stage);
QuestRewards.lostCityReward(p);check(p.lostCity==stage&&p.questPoints==0,"direct reward cannot bypass spirit at stage "+stage);
}
GertrudesCatCheck.Fixture p=player(1,true);door(p);check(p.lostCity==1&&!p.isTeleporting,"spirit flag alone cannot skip leprechaun stage");
p=player(2,true);p.playerEquipment[p.playerWeapon]=0;door(p);check(p.lostCity==2&&!p.isTeleporting&&p.questPoints==0,"staff must be equipped");
p=player(2,true);p.inTrade=true;door(p);check(p.lostCity==2&&!p.isTeleporting&&p.questPoints==0,"rejected teleport cannot award quest during trade");
p=player(2,true);p.isDead=true;door(p);check(p.lostCity==2&&p.questPoints==0,"dead player cannot claim reward");
p=player(2,true);p.teleTimer=5;door(p);check(p.questPoints==0&&p.lostCity==2,"already teleporting cannot claim completion");
p=player(2,true);
String original=System.getProperty("user.dir");Path root=Paths.get(original,"../../runtime/lostcity-save-check").normalize().toAbsolutePath();p.playerName=p.playerName2="lostcityregression";
Path save=root.resolve("data/characters/lostcityregression.txt");check(!Files.exists(save),"cannot overwrite existing save");
try{
System.setProperty("user.dir",root.toString());p.saveFile=p.saveCharacter=true;p.newPlayer=false;PlayerHandler.players[1]=p;
check(PlayerSave.saveGame(p),"spirit defeat saves");GertrudesCatCheck.Fixture q=player(0,false);q.playerName=q.playerName2=p.playerName;
check(PlayerSave.loadPlayerInfo(q,q.playerName,"",false)==1,"spirit defeat reloads");check(q.spiritTree&&q.lostCity==2,"persisted spirit defeat and journal stage retained");p=q;
}finally{System.setProperty("user.dir",original);PlayerHandler.players[1]=null;Files.deleteIfExists(save);Files.deleteIfExists(Paths.get(save+".bak"));}
p.absX=3202;p.absY=3169;p.playerEquipment[p.playerWeapon]=772;door(p);
check(p.isTeleporting&&p.teleX==2452&&p.teleY==4470&&p.teleHeight==0,"legitimate shed entry schedules Zanaris teleport");
check(p.lostCity==3&&p.questPoints==3,"successful discovery awards exactly three QP");
QuestRewards.lostCityReward(p);check(p.questPoints==3,"direct repeated reward rejected");
p.teleTimer=0;p.isTeleporting=false;door(p);check(p.questPoints==3&&p.isTeleporting,"completed quest permits repeat travel without repeat rewards");
p=player(3,false);door(p);check(p.isTeleporting&&p.lostCity==3&&p.questPoints==0,"legacy completed characters retain access even without old spirit flag");
System.out.println("PASS: "+checks+" Lost City completion checks");
}
}