Emberveil source

tests/ClockTowerCheck.java

import com.rs2.game.content.quests.*;
import com.rs2.game.content.quests.impl.ClockTower;
import com.rs2.game.dialogues.DialogueOptions;
import com.rs2.game.items.ItemDefinitions;
import com.rs2.game.players.*;
import com.rs2.world.GlobalDropsHandler;
import com.rs2.world.clip.*;
import org.apollo.cache.*;
import org.apollo.cache.decoder.*;
import java.nio.file.*;
import java.util.*;
public class ClockTowerCheck {
 static int checks;static String original;static Path saveRoot;
 static class F extends MemberQuestsCheck.Fixture {F(){playerName=playerName2="clocktowerqa";}}
 static void check(boolean ok,String m){checks++;if(!ok)throw new AssertionError(m);}
 static void kojo(F p){p.pos(2568,3248,0);p.getNpcs().firstClickNpc(223);}
 static void accept(F p){kojo(p);p.getDialogueHandler().sendDialogues(p.nextChat,223);DialogueOptions.handleDialogueOptions(p,9157);}
 static F reload(F p)throws Exception{
  p.saveFile=p.saveCharacter=true;p.newPlayer=false;PlayerHandler.players[1]=p;System.setProperty("user.dir",saveRoot.toString());
  try{check(PlayerSave.saveGame(p),"save");F q=new F();check(PlayerSave.loadPlayerInfo(q,q.playerName,"",false)==1,"reload");
   check(q.clockTower==p.clockTower&&q.clockParts==p.clockParts&&q.clockPuzzle==p.clockPuzzle,"all puzzle state persists");
   check(q.questPoints==p.questPoints&&Arrays.equals(q.playerItems,p.playerItems)&&Arrays.equals(q.playerItemsN,p.playerItemsN),"rewards and inventory persist");return q;
  }finally{System.setProperty("user.dir",original);PlayerHandler.players[1]=null;}
 }
 static void world(){
  int[][] objects={{1754,2566,3242,0},{1755,2566,9642,0},{1754,2621,3261,0},{1755,2621,9661,0},
   {1738,2572,3240,0},{1739,2572,3240,1},{1740,2572,3241,2},
   {29,2568,3243,0},{30,2570,9642,0},{31,2567,3241,2},{32,2569,3240,1},
   {33,2591,9661,0},{34,2593,9661,0},{37,2595,9657,0},{39,2579,9656,0},{40,2586,9654,0},{1586,2575,9631,0}};
  for(int[] a:objects)check(Region.objectExists(a[0],a[1],a[2],a[3]),"real object "+Arrays.toString(a));
  int[][] tiles={{2568,3248,0},{2565,3242,0},{2565,9642,0},{2620,3261,0},{2620,9661,0},{2574,3255,0},{2575,9656,0},{2571,3241,0},{2571,3241,1},{2571,3241,2},{2594,9657,0},{2596,9657,0},{2578,9656,0},{2580,9656,0},{2574,9631,0},{2576,9631,0}};
  for(int[] a:tiles)check((Region.getClipping(a[0],a[1],a[2])&0x1280100)==0,"clear landing "+Arrays.toString(a));
  F p=new F();p.pos(2565,3242,0);p.getObjects().firstClickObject(1754,2566,3242);check(p.teleportToX==2565&&p.teleportToY==9642,"main descent");
  p.pos(2565,9642,0);p.getObjects().firstClickObject(1755,2566,9642);check(p.teleportToY==3242,"main ascent");
  p.pos(2571,3241,0);p.getObjects().firstClickObject(1738,2572,3240);check(p.teleportToX==2571&&p.teleportToY==3241,"stairs first floor");
  p.pos(2571,3241,1);p.getObjects().secondClickObject(1739,2572,3240);check(p.teleportToX==2571,"stairs second option up");
  p.pos(2571,3241,1);p.getObjects().thirdClickObject(1739,2572,3240);check(p.teleportToX==2571,"stairs third option down");
 }
 static void story()throws Exception{
  F p=new F();p.pos(0,0,0);p.getNpcs().firstClickNpc(223);check(p.clockTower==0&&p.nextChat==0,"remote introduction blocked");
  kojo(p);p.getDialogueHandler().sendDialogues(p.nextChat,223);DialogueOptions.handleDialogueOptions(p,9158);check(p.clockTower==0,"decline");
  kojo(p);p.getDialogueHandler().sendDialogues(p.nextChat,223);p.pos(0,0,0);DialogueOptions.handleDialogueOptions(p,9157);check(p.clockTower==0,"remote accept blocked");accept(p);check(p.clockTower==1,"start");p=reload(p);
  kojo(p);check(p.questPoints==0,"no early reward");
  p.pos(2574,9633,0);GlobalDropsHandler.load(p);GlobalDropsHandler.pickup(p,22,2574,9633);check(!p.getItemAssistant().playerHasItem(22),"hot black cog rejected");
  p.item(0,1929);p.pos(2574,9633,1);ClockTower.groundItem(p,1929,22,2574,9633);check(p.clockPuzzle==0,"wrong-floor water rejected");
  p.pos(2574,9633,0);p.inTrade=true;ClockTower.groundItem(p,1929,22,2574,9633);check(p.clockPuzzle==0,"trade blocks cooling");p.inTrade=false;
  ClockTower.groundItem(p,1929,22,2574,9633);check((p.clockPuzzle&8)!=0&&p.getItemAssistant().playerHasItem(1925),"cooling replaces water with empty bucket");
  GlobalDropsHandler.pickup(p,22,2574,9633);check(p.getItemAssistant().playerHasItem(22),"actual black global drop obtainable");p=reload(p);
  p.pos(2583,9613,0);check(!ClockTower.canPickup(p,23,2583,9613),"one cog at a time");
  p.pos(2569,9642,0);ClockTower.useItem(p,30,2570,9642,23);check(p.clockParts==0,"wrong item cannot install");ClockTower.useItem(p,30,2570,9642,22);check(p.clockParts==4&&!p.getItemAssistant().playerHasItem(22),"black installed and consumed");p=reload(p);
  p.clear();p.item(0,23);p.pos(2568,3243,1);ClockTower.useItem(p,25,2568,3243,23);check(p.clockParts==4&&p.getItemAssistant().playerHasItem(23),"wrong spindle floor preserves cog");
  p.pos(2568,3242,0);ClockTower.useItem(p,29,2568,3243,23);check(p.clockParts==12,"red installed");
  p.item(0,21);p.pos(2569,3241,1);ClockTower.useItem(p,32,2569,3240,21);check(p.clockParts==14,"blue installed");p=reload(p);
  p.clear();p.item(0,24);p.pos(2587,9655,0);ClockTower.useItem(p,40,2586,9654,24);check((p.clockPuzzle&4)==0&&p.getItemAssistant().playerHasItem(24),"trough requires enclosure levers");
  p.pos(2591,9660,0);p.getObjects().firstClickObject(33,2591,9661);check((p.clockPuzzle&3)==1,"first lever");
  p.pos(2593,9660,0);p.getObjects().firstClickObject(34,2593,9661);check((p.clockPuzzle&3)==3,"second lever");p=reload(p);
  com.rs2.game.npcs.Npc inside=new com.rs2.game.npcs.Npc(100,224),outside=new com.rs2.game.npcs.Npc(101,224);
  inside.absX=2584;inside.absY=9657;inside.HP=12;outside.absX=3000;outside.absY=3000;outside.HP=12;
  com.rs2.game.npcs.NpcHandler.npcs[100]=inside;com.rs2.game.npcs.NpcHandler.npcs[101]=outside;
  try{p.pos(2587,9655,0);ClockTower.useItem(p,40,2586,9654,24);check((p.clockPuzzle&4)!=0&&!p.getItemAssistant().playerHasItem(24),"poison consumed and white gate unlocked");
   check(inside.isDead&&inside.HP==0&&inside.animNumber==141&&inside.animUpdateRequired&&inside.updateRequired,"enclosure rat receives verified death animation");
   check(!outside.isDead&&outside.HP==12,"rats elsewhere are unaffected");
  }finally{com.rs2.game.npcs.NpcHandler.npcs[100]=null;com.rs2.game.npcs.NpcHandler.npcs[101]=null;}p=reload(p);
  p.pos(2578,9655,0);GlobalDropsHandler.load(p);GlobalDropsHandler.pickup(p,20,2578,9655);check(p.getItemAssistant().playerHasItem(20),"white global drop obtainable");
  p.pos(2567,3242,2);ClockTower.useItem(p,31,2567,3241,20);check(p.clockParts==15,"all four repaired");p=reload(p);
  p.clear();for(int i=0;i<28;i++)p.item(i,1511);kojo(p);check(p.clockTower==1&&p.questPoints==0,"full backpack cannot lose reward");p.clear();kojo(p);check(p.clockTower==2&&p.questPoints==1&&p.getItemAssistant().getItemAmount(995)==500,"one QP and500coins");p=reload(p);
  for(int i=0;i<8;i++)kojo(p);check(p.questPoints==1&&p.getItemAssistant().getItemAmount(995)==500,"reward once after save/relog");
  QuestAssistant.questButtons(p,28185);check(QuestAssistant.Quests.CLOCK.questStatus()&&QuestAssistant.MAXIMUM_QUESTPOINTS==Integer.getInteger("emberveil.test.expectedQuestPoints",44),"journal enabled");
  F gloves=new F();gloves.clockTower=1;gloves.pos(2574,9633,0);gloves.playerEquipment[9]=1580;check(ClockTower.canPickup(gloves,22,2574,9633),"ice gloves alternative");
  F other=new F();other.clockTower=1;other.pos(2578,9655,0);check(!ClockTower.canPickup(other,20,2578,9655),"another player cannot bypass personal rat puzzle");
 }
 public static void main(String[] args)throws Exception{
  original=System.getProperty("user.dir");saveRoot=Paths.get(original,"../../runtime/clock-quest-save-check").normalize().toAbsolutePath();check(!Files.exists(saveRoot.resolve("data/characters/clocktowerqa.txt")),"preserve existing fixture");
  IndexedFileSystem c=new IndexedFileSystem(Paths.get("data/cache"),true);new ItemDefinitionDecoder(c).run();ItemDefinitions.load();new NpcDefinitionDecoder(c).run();new ObjectDefinitionDecoder(c).run();RegionFactory.load(c);
  try{world();story();System.out.println("PASS "+checks+" Clock Tower checks");}finally{System.setProperty("user.dir",original);PlayerHandler.players[1]=null;Files.deleteIfExists(saveRoot.resolve("data/characters/clocktowerqa.txt"));Files.deleteIfExists(saveRoot.resolve("data/characters/clocktowerqa.txt.bak"));}
 }
}