Emberveil source

tests/EmberveilCheck.java

import com.rs2.game.content.emberveil.Emberveil;
import com.rs2.game.players.Client;
import com.rs2.game.players.PlayerHandler;
import com.rs2.game.players.PlayerSave;
import com.rs2.game.items.ItemDefinitions;
import org.apollo.cache.IndexedFileSystem;
import org.apollo.cache.decoder.ItemDefinitionDecoder;
import java.nio.file.*;
import java.util.Arrays;

/** Integration checks using the real cache, inventory and character serializer. */
public class EmberveilCheck {
    static class TestPlayer extends Client {
        TestPlayer() { super(null, 1); getOutStream().packetEncryption = new org.apollo.util.security.IsaacRandom(new int[] {1,2,3,4}); }
        @Override public void flushOutStream() { getOutStream().currentOffset = 0; }
    }
    static int checks;
    static void check(boolean result, String label) {
        if (!result) throw new AssertionError(label);
        checks++;
    }
    static void command(TestPlayer p, String cmd, String... args) {
        p.getOutStream().currentOffset = 0;
        check(Emberveil.handle(p,cmd,args), "command recognized: " + cmd);
    }
    static void position(TestPlayer p, int x, int y) { p.absX=x; p.absY=y; p.heightLevel=0; }
    static void clear(TestPlayer p) { Arrays.fill(p.playerItems,0); Arrays.fill(p.playerItemsN,0); }
    public static void main(String[] args) throws Exception {
        new ItemDefinitionDecoder(new IndexedFileSystem(Paths.get("data/cache"), true)).run();
        ItemDefinitions.load();
        TestPlayer p = new TestPlayer();
        position(p,0,0);
        command(p,"ember","begin"); check(p.emberStage==0,"cannot begin remotely");
        position(p,3221,3218);
        command(p,"ember","begin"); check(p.emberStage==1,"begin near Hans");
        command(p,"ember","offer"); check(p.emberStage==1,"missing items cannot advance");
        p.getItemAssistant().addItem(1511,5);
        p.inTrade=true;
        command(p,"ember","offer"); check(p.emberStage==1,"trade blocks hand-in");
        p.inTrade=false;
        command(p,"ember","offer"); check(p.emberStage==2,"logs advance story");
        check(!p.getItemAssistant().playerHasItem(1511),"story consumes supplies");
        command(p,"ember","listen"); check(p.emberStage==2,"wrong location cannot advance");
        position(p,3109,3167); command(p,"ember","listen"); check(p.emberStage==3,"tower clue");
        position(p,3087,3335); p.getItemAssistant().addItem(526,3);
        command(p,"ember","offer"); check(p.emberStage==4,"fountain offering");
        position(p,2985,3293); p.getItemAssistant().addItem(2349,3);
        command(p,"ember","offer"); check(p.emberStage==5,"altar offering");
        position(p,3221,3218);
        Arrays.fill(p.playerItems,1512); Arrays.fill(p.playerItemsN,1);
        command(p,"ember","finish"); check(p.emberStage==5 && p.emberSigils==0,"full inventory does not claim story reward");
        clear(p); command(p,"ember","finish");
        check(p.emberStage==6 && p.emberSigils==10 && p.emberReputation==10,"story rewards");
        check(p.getItemAssistant().playerHasItem(995,2000),"story coin payment");
        command(p,"ember","finish"); check(p.emberSigils==10,"story reward cannot repeat");
        command(p,"deliver"); check(p.emberContracts==0,"missing delivery refused");
        p.getItemAssistant().addItem(1511,10); command(p,"deliver");
        check(p.emberContracts==1 && p.emberSigils==12,"contract completion");
        command(p,"deliver"); check(p.emberContracts==1,"contract cannot repeat without next supplies");
        command(p,"redeem","axe"); check(p.emberSigils==0 && p.emberReputation==12,"redeem spends only sigils");
        check(p.getItemAssistant().playerHasItem(1353),"correct reward item");
        command(p,"redeem","axe"); check(p.emberSigils==0,"insufficient sigils refused");
        clear(p); p.playerItems[0]=996; p.playerItemsN[0]=Integer.MAX_VALUE;
        p.getItemAssistant().addItem(315,10);
        command(p,"deliver");
        check(p.emberContracts==1 && p.getItemAssistant().playerHasItem(315,10),"coin overflow rejects delivery without consuming supplies");
        clear(p); p.getItemAssistant().addItem(316,10);
        command(p,"deliver"); check(p.emberContracts==1,"noted supplies cannot satisfy contract");
        clear(p); p.getItemAssistant().addItem(315,10); p.heightLevel=1;
        command(p,"deliver"); check(p.emberContracts==1,"wrong height cannot hand in"); p.heightLevel=0;
        TestPlayer other=new TestPlayer(); position(other,3221,3218);
        command(other,"ember","begin"); check(other.emberStage==1 && p.emberStage==6,"story state is independent between characters");
        clear(p);
        p.tutorialProgress=36; position(p,3109,3167);
        Emberveil.discover(p); Emberveil.discover(p);
        check(p.emberDiscoveries==1 && p.emberSigils==1,"landmark reward only once");
        p.playerName=p.playerName2="emberveil_qa"; p.playerPass="qa-local-only";
        p.saveFile=true; p.newPlayer=false; p.saveCharacter=true;
        PlayerHandler.players[1]=p;
        Path saved=Paths.get("data/characters/emberveil_qa.txt");
        check(!Files.exists(saved),"QA name must not overwrite an existing character");
        try {
            check(PlayerSave.saveGame(p),"save succeeds");
            TestPlayer restored=new TestPlayer(); restored.playerName="emberveil_qa";
            check(PlayerSave.loadPlayerInfo(restored,"emberveil_qa","qa-local-only",false)==1,"load succeeds");
            check(restored.emberStage==6 && restored.emberContracts==1 && restored.emberSigils==1 && restored.emberReputation==13 && restored.emberDiscoveries==1,"all custom progress survives reload");
            check(PlayerSave.loadPlayerInfo(newNamedPlayer(),"emberveil_qa","wrong-password",true)==3,"wrong password rejected");
            check(PlayerSave.loadPlayerInfo(newNamedPlayer(),"emberveil_qa","qa-local-only",true)==1,"correct password accepted");
            p.emberSigils=9;
            check(PlayerSave.saveGame(p),"second save succeeds");
            check(Files.exists(Paths.get(saved.toString()+".bak")),"previous save backed up");
            check(new String(Files.readAllBytes(Paths.get(saved.toString()+".bak")),java.nio.charset.StandardCharsets.UTF_8).contains("ember-sigils = 1"),"backup contains previous committed state");
            check(new String(Files.readAllBytes(saved),java.nio.charset.StandardCharsets.UTF_8).contains("ember-sigils = 9"),"replacement contains new state");
            clear(p); position(p,3221,3218);
            command(p,"charter","claim"); check(p.emberCharter==0,"incomplete atlas cannot claim charter");
            p.emberDiscoveries=63;
            Arrays.fill(p.playerItems,1512); Arrays.fill(p.playerItemsN,1);
            command(p,"charter","claim"); check(p.emberCharter==0,"full inventory preserves charter reward");
            clear(p); command(p,"charter","claim");
            check(p.emberCharter==1 && p.emberSigils==24 && p.emberReputation==28,"charter rewards correct");
            check(p.getItemAssistant().playerHasItem(995,5000) && p.getItemAssistant().playerHasItem(1009),"charter equipment and coins");
            command(p,"charter","claim"); check(p.emberSigils==24,"charter cannot be claimed twice");
            check(PlayerSave.saveGame(p),"charter save succeeds");
            TestPlayer charterReload=newNamedPlayer(); PlayerSave.loadPlayerInfo(charterReload,"emberveil_qa","qa-local-only",false);
            check(charterReload.emberCharter==1,"charter claim survives reload");
            TestPlayer menu=new TestPlayer(); position(menu,3221,3218);
            Emberveil.talk(menu); check(menu.nextChat==Emberveil.WATCH_GREETING,"Hans greeting has continuation");
            menu.getDialogueHandler().sendDialogues(menu.nextChat,0);
            check(Emberveil.handleButton(menu,9190) && menu.emberStage==1,"clickable Hans menu starts story");
            check(!Emberveil.handleButton(menu,9190),"stale dialogue click ignored");
            Emberveil.watchMenu(menu); position(menu,0,0);
            check(Emberveil.handleButton(menu,9192) && menu.emberContracts==0,"menu cannot deliver from another location");
            position(menu,3221,3218); Emberveil.watchMenu(menu);
            check(Emberveil.handleButton(menu,9193),"quartermaster menu opens");
            menu.emberSigils=3;
            check(Emberveil.handleButton(menu,9190) && menu.emberSigils==0 && menu.getItemAssistant().playerHasItem(1061),"clickable quartermaster purchases correctly");
        } finally { Files.deleteIfExists(saved); Files.deleteIfExists(Paths.get(saved.toString()+".bak")); PlayerHandler.players[1]=null; }
        Path stop=Files.createTempFile("emberveil-stop-test-", ".request");
        System.setProperty("emberveil.stopFile",stop.toAbsolutePath().toString());
        try {
            Files.write(stop,"IGNORE".getBytes(java.nio.charset.StandardCharsets.UTF_8));
            check(!com.rs2.game.content.emberveil.ServerControl.poll(),"invalid shutdown signal ignored");
            Files.write(stop,"STOP".getBytes(java.nio.charset.StandardCharsets.UTF_8));
            check(com.rs2.game.content.emberveil.ServerControl.poll() && !Files.exists(stop),"valid local shutdown consumed");
        } finally { Files.deleteIfExists(stop); System.clearProperty("emberveil.stopFile"); }
        System.out.println("PASS: " + checks + " Emberveil integration checks.");
        System.exit(0);
    }
    static TestPlayer newNamedPlayer() { TestPlayer p=new TestPlayer(); p.playerName="emberveil_qa"; return p; }
}