boosters fix2; collection

This commit is contained in:
Michael Wain 2024-06-17 04:08:35 +03:00
parent 56a127aafc
commit fdb3579ea1
13 changed files with 228 additions and 58 deletions

View File

@ -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.dbf.CardsDBF;
import com.alterdekim.hearthhack.game.GameTag;
import com.alterdekim.hearthhack.parser.CardsXmlParser;
import com.alterdekim.hearthhack.parser.DBFParser;
import com.alterdekim.hearthhack.util.CardsObject;
import com.alterdekim.hearthhack.util.FormattedCards;
import com.alterdekim.hearthhack.xml.CardsXML;
import com.alterdekim.hearthhack.xml.XMLEntity;
import com.alterdekim.hearthhack.xml.XMLTag;
@ -21,7 +24,10 @@ import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
@ -54,11 +60,23 @@ public class StartupListener {
if( !Path.of(serverConfig.getWorkDir() + File.separator + FS.dataDir).toFile().exists() ) initXml();
dbfConfig.setCards(DBFParser.parseCards(serverConfig.getWorkDir() + File.separator + FS.dbfDir));
dbfConfig.setCardsXML(DBFParser.parse(serverConfig.getWorkDir() + File.separator + FS.dataDir + File.separator + "enUS.xml", CardsXML.class));
unionCards();
} catch (Exception e) {
log.error(e.getMessage());
}
}
private void unionCards() {
CardsDBF dbf = dbfConfig.getCards();
CardsXML xml = dbfConfig.getCardsXML();
List<CardsObject> objs = xml.getEntities()
.stream()
.map(e -> new CardsObject(e, dbf.findWithMiniGuid(e.getCardId()).orElse(null)))
.filter(c -> c.getDbfCard() != null)
.collect(Collectors.toList());
dbfConfig.setFormattedCards(new FormattedCards(objs));
}
private void initDbf() throws Exception {
makeDir(FS.dbfDir);
Files.walk(Path.of(serverConfig.getDbfPath()))

View File

@ -2,7 +2,6 @@ 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;
@ -10,45 +9,50 @@ 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
public class OpenBooster extends ClientRequestParser {
private final Protocol.Date d = Protocol.Date.newBuilder()
.setYear(2023)
.setMonth(1)
.setDay(3)
.setHours(0)
.setMin(0)
.setSec(0)
.build();
@Override
public void parse(BattleNetPacket packet, ClientRequestBody body, TcpConnection conn) throws Exception {
// 226 BoosterContent
log.info("BoosterContent: got");
Protocol.Date d = Protocol.Date.newBuilder()
.setYear(2023)
.setMonth(1)
.setDay(3)
.setHours(0)
.setMin(0)
.setSec(0)
.build();
Protocol.OpenBooster ob = Protocol.OpenBooster.parseFrom(body.getBody());
// TODO: optimize this
// TODO: union dbf cards and cardsxml0 into one list
List<Protocol.BoosterCard> l = Util.getRandomItems(conn.getDbfConfig().getCardsXML().findEntitiesByTagVal(GameTag.CARD_SET, 3).stream().filter(p -> {
Optional<DBFCard> 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()
List<Protocol.BoosterCard> l = Util.getRandomItems(
conn.getDbfConfig()
.getFormattedCards()
.findEntitiesByTagVal(GameTag.CARD_SET, 3)
.stream()
.filter(p -> p.getDbfCard().findField("IS_COLLECTIBLE").isPresent() && p.getDbfCard().findField("IS_COLLECTIBLE").get().getVal().equals("True"))
.collect(Collectors.toList()), 5)
.stream()
.map(c -> Protocol.BoosterCard.newBuilder()
.setCardDef(Protocol.CardDef.newBuilder()
.setAsset(Integer.parseInt(
c.getFields().stream().filter(p -> p.getColumn().equals("ID")).findFirst().get().getVal()
)
)
c.getDbfCard().getFields().stream().filter(p -> p.getColumn().equals("ID")).findFirst().get().getVal()
))
.setPremium(1))
.setInsertDate(d).build())
.collect(Collectors.toList());
.setInsertDate(d)
.build()
)
.peek(c -> conn.getUserService().addCardToCollection(conn.getUserId(), (long) c.getCardDef().getAsset(), c.getCardDef().getPremium() != 0, false))
.collect(Collectors.toList());
conn.getUserService().removeBooster(conn.getUserId(), ob.getBoosterType());
Protocol.BoosterContent response = Protocol.BoosterContent.newBuilder()
.addAllList(l)
.build();

View File

@ -3,16 +3,48 @@ package com.alterdekim.hearthhack.component.processor.client.request.generic;
import com.alterdekim.Protocol;
import com.alterdekim.hearthhack.component.TcpConnection;
import com.alterdekim.hearthhack.util.BattleNetPacket;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.stream.Collectors;
import static com.alterdekim.hearthhack.util.GameUtilities.generateEmptyNotification;
import static com.alterdekim.hearthhack.util.GetAccountInfoRequest.COLLECTION;
@Slf4j
public class Collection extends GenericParser {
private final Protocol.Date d = Protocol.Date.newBuilder()
.setYear(2023)
.setMonth(1)
.setDay(3)
.setHours(0)
.setMin(0)
.setSec(0)
.build();
@Override
public void parseGenericRequest(int token, TcpConnection conn) throws Exception {
// my collection
Protocol.Collection collection = Protocol.Collection.newBuilder().build();
List<Protocol.CardStack> l = conn.getUserService().getCollectionOfUser(conn.getUserId())
.stream()
.map(p -> Protocol.CardStack.newBuilder()
.setCount(p.getCount())
.setLatestInsertDate(d)
.setNumSeen(p.getHasSeen() ? 1 : 0)
.setCardDef(Protocol.CardDef.newBuilder()
.setPremium(p.getIsPremium() ? 1 : 0)
.setAsset(p.getAssetId().intValue()))
.build())
.collect(Collectors.toList());
log.info("Collection: {}", l);
Protocol.Collection collection = Protocol.Collection.newBuilder()
.addAllStacks(l)
.build();
Protocol.Notification n = generateEmptyNotification(207);

View File

@ -1,6 +1,8 @@
package com.alterdekim.hearthhack.config;
import com.alterdekim.hearthhack.dbf.CardsDBF;
import com.alterdekim.hearthhack.util.CardsObject;
import com.alterdekim.hearthhack.util.FormattedCards;
import com.alterdekim.hearthhack.xml.CardsXML;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
@ -10,5 +12,6 @@ import org.springframework.context.annotation.Configuration;
public class ObjectConfig {
private CardsDBF cards;
private CardsXML cardsXML;
private FormattedCards formattedCards;
private String clientConfig;
}

View File

@ -0,0 +1,18 @@
package com.alterdekim.hearthhack.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class UserCardDTO {
private Long assetId;
private Boolean isPremium;
private Integer count;
private Boolean hasSeen;
}

View File

@ -1,25 +0,0 @@
package com.alterdekim.hearthhack.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "card_stack")
public class CardStack {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable=false)
private Integer asset;
@Column(nullable=false)
private Integer premium;
}

View File

@ -1,5 +1,7 @@
package com.alterdekim.hearthhack.entity;
import com.alterdekim.hearthhack.dto.BoosterDTO;
import com.alterdekim.hearthhack.dto.UserCardDTO;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -12,6 +14,25 @@ import lombok.Setter;
@AllArgsConstructor
@Entity
@Table(name = "ucards")
@SqlResultSetMapping(
name = "ucardEntityMapping",
classes = {
@ConstructorResult(
targetClass = UserCardDTO.class,
columns = {
@ColumnResult(name = "assetId", type = Long.class),
@ColumnResult(name = "isPremium", type = Boolean.class),
@ColumnResult(name = "count", type = Integer.class),
@ColumnResult(name = "hasSeen", type = Boolean.class)
}
)
}
)
@NamedNativeQuery(
name = "UserCard.getCollectionOfUser",
query = "SELECT u.asset_id as assetId, u.is_premium as isPremium, COUNT(u.id) as count, MIN(u.has_seen) as hasSeen FROM ucards u WHERE u.user_id = :userId GROUP BY u.asset_id, u.is_premium",
resultSetMapping = "ucardEntityMapping"
)
public class UserCard {
@Id
@ -22,5 +43,18 @@ public class UserCard {
private Long userId;
@Column(nullable = false)
private Long cardStackId;
private Long assetId;
@Column(nullable = false)
private Boolean isPremium;
@Column(nullable = false)
private Boolean hasSeen = false;
public UserCard(Long userId, Long assetId, Boolean isPremium, Boolean hasSeen) {
this.userId = userId;
this.assetId = assetId;
this.isPremium = isPremium;
this.hasSeen = hasSeen;
}
}

View File

@ -4,9 +4,11 @@ import com.alterdekim.hearthhack.dto.BoosterDTO;
import com.alterdekim.hearthhack.entity.Booster;
import com.alterdekim.hearthhack.entity.HeroXP;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@ -14,4 +16,9 @@ import java.util.List;
public interface BoosterRepository extends JpaRepository<Booster, Long> {
@Query(nativeQuery = true)
List<BoosterDTO> findBoostersByUserId(@Param("userId") Long userId);
@Transactional
@Modifying
@Query(value = "DELETE FROM Booster a WHERE a.id IN (SELECT c.lid FROM (SELECT MAX(b.id) AS lid FROM Booster b WHERE b.userId = :userId AND b.type = :type) c)")
void deleteOneByType(@Param("userId") Long userId, @Param("type") Integer type);
}

View File

@ -0,0 +1,18 @@
package com.alterdekim.hearthhack.repository;
import com.alterdekim.hearthhack.dto.UserCardDTO;
import com.alterdekim.hearthhack.entity.User;
import com.alterdekim.hearthhack.entity.UserCard;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserCardRepository extends JpaRepository<UserCard, Long> {
@Query(nativeQuery = true)
List<UserCardDTO> getCollectionOfUser(@Param("userId") Long userId);
}

View File

@ -15,6 +15,8 @@ import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import static org.springframework.boot.autoconfigure.security.servlet.PathRequest.toH2Console;
@Configuration
@EnableWebSecurity
public class SpringSecurity {
@ -36,6 +38,7 @@ public class SpringSecurity {
.requestMatchers("/login").permitAll()
.requestMatchers("/rules").permitAll()
.requestMatchers("/static/**").permitAll()
.requestMatchers(toH2Console()).permitAll()
).formLogin(
form -> form
.loginPage("/login")
@ -55,7 +58,8 @@ public class SpringSecurity {
)
.exceptionHandling((exc) -> exc
.accessDeniedHandler(accessDeniedHandler())
.accessDeniedPage("/403"));
.accessDeniedPage("/403"))
.headers().frameOptions().disable();
return http.build();
}

View File

@ -1,11 +1,9 @@
package com.alterdekim.hearthhack.service;
import com.alterdekim.hearthhack.dto.BoosterDTO;
import com.alterdekim.hearthhack.dto.UserCardDTO;
import com.alterdekim.hearthhack.dto.UserDTO;
import com.alterdekim.hearthhack.entity.Booster;
import com.alterdekim.hearthhack.entity.CardBack;
import com.alterdekim.hearthhack.entity.Role;
import com.alterdekim.hearthhack.entity.User;
import com.alterdekim.hearthhack.entity.*;
import com.alterdekim.hearthhack.repository.*;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.units.qual.C;
@ -28,6 +26,7 @@ public class UserService implements IService {
private final DeckRepository deckRepository;
private final CardBackRepository cardBackRepository;
private final BoosterRepository boosterRepository;
private final UserCardRepository userCardRepository;
public void saveUser(UserDTO userDto) {
@ -91,6 +90,18 @@ public class UserService implements IService {
return boosterRepository.findBoostersByUserId(userId);
}
public void removeBooster(Long userId, Integer boosterType) {
boosterRepository.deleteOneByType(userId, boosterType);
}
public void addCardToCollection(Long userId, Long assetId, Boolean isPremium, Boolean hasSeen) {
this.userCardRepository.save(new UserCard(userId, assetId, isPremium, hasSeen));
}
public List<UserCardDTO> getCollectionOfUser(Long userId) {
return this.userCardRepository.getCollectionOfUser(userId);
}
public List<UserDTO> findAllUsers() {
List<User> users = userRepository.findAll();
return users.stream().map(this::convertEntityToDto)

View File

@ -0,0 +1,11 @@
package com.alterdekim.hearthhack.util;
import com.alterdekim.hearthhack.dbf.DBFCard;
import com.alterdekim.hearthhack.xml.XMLEntity;
import lombok.*;
@Data
public class CardsObject {
private final XMLEntity entity;
private final DBFCard dbfCard;
}

View File

@ -0,0 +1,35 @@
package com.alterdekim.hearthhack.util;
import com.alterdekim.hearthhack.game.GameTag;
import lombok.*;
import java.util.List;
import java.util.stream.Collectors;
@ToString
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class FormattedCards {
private List<CardsObject> objects;
public List<CardsObject> findEntitiesByTagVal(GameTag tag, Integer val) {
return this.objects.stream()
.filter(o -> o.getEntity().getTags()
.stream()
.anyMatch(f -> f.getEnumID().intValue() == tag.getValue().intValue() && f.getValue().intValue() == val.intValue())
)
.collect(Collectors.toList());
}
public List<CardsObject> findEntitiesByTagVal(GameTag tag, String val) {
return this.objects.stream()
.filter(o -> o.getEntity().getTags()
.stream()
.anyMatch(f -> f.getEnumID().intValue() == tag.getValue().intValue() && val.equals(f.getVal()))
)
.collect(Collectors.toList());
}
}