diff --git a/src/main/java/com/alterdekim/hearthhack/component/StartupListener.java b/src/main/java/com/alterdekim/hearthhack/component/StartupListener.java index f1c8c01..edab2c5 100644 --- a/src/main/java/com/alterdekim/hearthhack/component/StartupListener.java +++ b/src/main/java/com/alterdekim/hearthhack/component/StartupListener.java @@ -3,9 +3,12 @@ package com.alterdekim.hearthhack.component; import com.alterdekim.hearthhack.config.ObjectConfig; import com.alterdekim.hearthhack.config.FS; import com.alterdekim.hearthhack.config.ServerConfig; +import com.alterdekim.hearthhack.game.GameTag; import com.alterdekim.hearthhack.parser.CardsXmlParser; import com.alterdekim.hearthhack.parser.DBFParser; import com.alterdekim.hearthhack.xml.CardsXML; +import com.alterdekim.hearthhack.xml.XMLEntity; +import com.alterdekim.hearthhack.xml.XMLTag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.jdbc.DataSourceBuilder; diff --git a/src/main/java/com/alterdekim/hearthhack/component/processor/client/request/OpenBooster.java b/src/main/java/com/alterdekim/hearthhack/component/processor/client/request/OpenBooster.java index d232ebc..c9be28a 100644 --- a/src/main/java/com/alterdekim/hearthhack/component/processor/client/request/OpenBooster.java +++ b/src/main/java/com/alterdekim/hearthhack/component/processor/client/request/OpenBooster.java @@ -2,10 +2,17 @@ package com.alterdekim.hearthhack.component.processor.client.request; import com.alterdekim.Protocol; import com.alterdekim.hearthhack.component.TcpConnection; +import com.alterdekim.hearthhack.dbf.DBFCard; +import com.alterdekim.hearthhack.game.GameTag; import com.alterdekim.hearthhack.util.BattleNetPacket; import com.alterdekim.hearthhack.util.ClientRequestBody; +import com.alterdekim.hearthhack.util.Util; import lombok.extern.slf4j.Slf4j; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + import static com.alterdekim.hearthhack.util.GameUtilities.generateNotification; @Slf4j @@ -23,7 +30,29 @@ public class OpenBooster extends ClientRequestParser { .setSec(0) .build(); + // TODO: optimize this + List l = Util.getRandomItems(conn.getDbfConfig().getCardsXML().findEntitiesByTagVal(GameTag.CARD_SET, 3).stream().filter(p -> { + Optional c = conn.getDbfConfig().getCards().findWithMiniGuid(p.getCardId()); + return c.isPresent() && c.get().findField("IS_COLLECTIBLE").isPresent() && c.get().findField("IS_COLLECTIBLE").get().getVal().equals("True"); + }).collect(Collectors.toList()), 5) + .stream() + .map(e -> conn.getDbfConfig().getCards().findWithMiniGuid(e.getCardId())) + .filter(Optional::isPresent) + .map(Optional::get) + .map(c -> Protocol.BoosterCard.newBuilder() + .setCardDef(Protocol.CardDef.newBuilder() + .setAsset(Integer.parseInt( + c.getFields().stream().filter(p -> p.getColumn().equals("ID")).findFirst().get().getVal() + ) + ) + .setPremium(1)) + .setInsertDate(d).build()) + .collect(Collectors.toList()); Protocol.BoosterContent response = Protocol.BoosterContent.newBuilder() + .addAllList(l) + .build(); + + /* Protocol.BoosterContent response = Protocol.BoosterContent.newBuilder() .addList(Protocol.BoosterCard.newBuilder() .setCardDef(Protocol.CardDef.newBuilder() .setAsset(459) @@ -49,7 +78,7 @@ public class OpenBooster extends ClientRequestParser { .setAsset(459) .setPremium(0)) .setInsertDate(d)) - .build(); + .build();*/ Protocol.Notification n = generateNotification(226, response.toByteString(), response.getSerializedSize()); diff --git a/src/main/java/com/alterdekim/hearthhack/dbf/CardsDBF.java b/src/main/java/com/alterdekim/hearthhack/dbf/CardsDBF.java index a483965..d69f903 100644 --- a/src/main/java/com/alterdekim/hearthhack/dbf/CardsDBF.java +++ b/src/main/java/com/alterdekim/hearthhack/dbf/CardsDBF.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import lombok.*; import java.util.List; +import java.util.Optional; @ToString @Getter @@ -26,4 +27,12 @@ public class CardsDBF { @JsonProperty("Record") @JacksonXmlElementWrapper(useWrapping = false) private List records; + + + public Optional findWithMiniGuid(String miniGuid) { + return records.stream() + .filter(r -> r.getFields().stream().anyMatch(c -> c.getColumn().equals("NOTE_MINI_GUID"))) + .filter(r -> r.getFields().stream().filter(c -> c.getColumn().equals("NOTE_MINI_GUID")).findFirst().get().getVal().equals(miniGuid)) + .findFirst(); + } } diff --git a/src/main/java/com/alterdekim/hearthhack/dbf/DBFCard.java b/src/main/java/com/alterdekim/hearthhack/dbf/DBFCard.java index c9e10da..6185e67 100644 --- a/src/main/java/com/alterdekim/hearthhack/dbf/DBFCard.java +++ b/src/main/java/com/alterdekim/hearthhack/dbf/DBFCard.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import lombok.*; import java.util.List; +import java.util.Optional; @Getter @Setter @@ -16,4 +17,8 @@ public class DBFCard { @JsonProperty("Field") @JacksonXmlElementWrapper(useWrapping = false) private List fields; + + public Optional findField(String field) { + return fields.stream().filter(f -> f.getColumn().equals(field)).findFirst(); + } } diff --git a/src/main/java/com/alterdekim/hearthhack/game/GameTag.java b/src/main/java/com/alterdekim/hearthhack/game/GameTag.java index d639c28..4a03ac8 100644 --- a/src/main/java/com/alterdekim/hearthhack/game/GameTag.java +++ b/src/main/java/com/alterdekim/hearthhack/game/GameTag.java @@ -1,5 +1,7 @@ package com.alterdekim.hearthhack.game; +import lombok.Getter; + public enum GameTag { // Token: 0x04000B83 RID: 2947 TAG_SCRIPT_DATA_ENT_1(4), @@ -480,10 +482,18 @@ public enum GameTag { // Token: 0x04000C71 RID: 3185 SEEN_CTHUN(445); + @Getter private final Integer value; GameTag(Integer value) { this.value = value; } + + public static GameTag fromInt(int val) { + for( GameTag t : values() ) { + if(t.value.intValue() == val) return t; + } + return null; + } } diff --git a/src/main/java/com/alterdekim/hearthhack/game/TagCardSet.java b/src/main/java/com/alterdekim/hearthhack/game/TagCardSet.java new file mode 100644 index 0000000..eef36f0 --- /dev/null +++ b/src/main/java/com/alterdekim/hearthhack/game/TagCardSet.java @@ -0,0 +1,51 @@ +package com.alterdekim.hearthhack.game; + +public enum TagCardSet { + // Token: 0x04000B64 RID: 2916 + INVALID, + // Token: 0x04000B65 RID: 2917 + TEST_TEMPORARY, + // Token: 0x04000B66 RID: 2918 + CORE, + // Token: 0x04000B67 RID: 2919 + EXPERT1, + // Token: 0x04000B68 RID: 2920 + REWARD, + // Token: 0x04000B69 RID: 2921 + MISSIONS, + // Token: 0x04000B6A RID: 2922 + DEMO, + // Token: 0x04000B6B RID: 2923 + NONE, + // Token: 0x04000B6C RID: 2924 + CHEAT, + // Token: 0x04000B6D RID: 2925 + BLANK, + // Token: 0x04000B6E RID: 2926 + DEBUG_SP, + // Token: 0x04000B6F RID: 2927 + PROMO, + // Token: 0x04000B70 RID: 2928 + FP1, + // Token: 0x04000B71 RID: 2929 + PE1, + // Token: 0x04000B72 RID: 2930 + BRM, + // Token: 0x04000B73 RID: 2931 + TGT, + // Token: 0x04000B74 RID: 2932 + CREDITS, + // Token: 0x04000B75 RID: 2933 + HERO_SKINS, + // Token: 0x04000B76 RID: 2934 + TB, + // Token: 0x04000B77 RID: 2935 + SLUSH, + // Token: 0x04000B78 RID: 2936 + LOE, + // Token: 0x04000B79 RID: 2937 + OG, + // Token: 0x04000B7A RID: 2938 + OG_RESERVE +} + diff --git a/src/main/java/com/alterdekim/hearthhack/util/Util.java b/src/main/java/com/alterdekim/hearthhack/util/Util.java index 58d6f8d..b8e2bb1 100644 --- a/src/main/java/com/alterdekim/hearthhack/util/Util.java +++ b/src/main/java/com/alterdekim/hearthhack/util/Util.java @@ -18,6 +18,13 @@ import java.security.KeyStore; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; @Slf4j public class Util { @@ -137,4 +144,23 @@ public class Util { String s = Integer.toHexString(i).toUpperCase(); return s.length() % 2 == 0 ? s : "0" + s; } + + public static Collector, T> randomItem() { + final Random RANDOM = new Random(); + return Collector.of(() -> (List) new ArrayList(), + (acc, elem) -> acc.add(elem), + (list1, list2) -> Util.unionLists(list1, list2), + list -> list.isEmpty() ? null : list.get(RANDOM.nextInt(list.size()))); + } + + public static List getRandomItems(List s, Integer lim) { + return IntStream.range(0, lim) + .boxed() + .map(i -> s.get((int) (Math.random() * s.size()))) + .collect(Collectors.toList()); + } + + public static List unionLists(List a, List b) { + return Stream.concat(a.stream(), b.stream()).collect(Collectors.toList()); + } } diff --git a/src/main/java/com/alterdekim/hearthhack/xml/CardsXML.java b/src/main/java/com/alterdekim/hearthhack/xml/CardsXML.java index 65b57e6..d916d29 100644 --- a/src/main/java/com/alterdekim/hearthhack/xml/CardsXML.java +++ b/src/main/java/com/alterdekim/hearthhack/xml/CardsXML.java @@ -1,10 +1,13 @@ package com.alterdekim.hearthhack.xml; +import com.alterdekim.hearthhack.game.GameTag; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import lombok.*; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; @ToString @Getter @@ -15,4 +18,27 @@ public class CardsXML { @JsonProperty("Entity") @JacksonXmlElementWrapper(useWrapping = false) private List entities; + + + public Optional findEntityByCardId(String cardId) { + return this.entities.stream().filter(p -> p.getCardId().equals(cardId)).findFirst(); + } + + public List findEntitiesByTagVal(GameTag tag, Integer val) { + return this.entities.stream() + .filter(p -> p.getTags() + .stream() + .anyMatch(f -> f.getEnumID().intValue() == tag.getValue().intValue() && f.getValue().intValue() == val.intValue()) + ) + .collect(Collectors.toList()); + } + + public List findEntitiesByTagVal(GameTag tag, String val) { + return this.entities.stream() + .filter(p -> p.getTags() + .stream() + .anyMatch(f -> f.getEnumID().intValue() == tag.getValue().intValue() && f.getVal().equals(val)) + ) + .collect(Collectors.toList()); + } }