forked from Cookies_Github_mirror/AquaDX
[O] Rewrite CM chusan apis
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chusan.handler;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserCardPrintStateRepo;
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserGachaRepo;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chusan.model.gamedata.GameGachaCard;
|
||||
import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserGacha;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserGacha;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem;
|
||||
import icu.samnyan.aqua.sega.chusan.service.UserDataService;
|
||||
import icu.samnyan.aqua.sega.chusan.service.UserItemService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Component("ChusanCMUpsertUserGachaHandler")
|
||||
public class CMUpsertUserGachaHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CMUpsertUserGachaHandler.class);
|
||||
private final Chu3UserCardPrintStateRepo userCardPrintStateRepository;
|
||||
private final Chu3UserGachaRepo userGachaRepository;
|
||||
private final UserDataService userDataService;
|
||||
private final UserItemService userItemService;
|
||||
private final BasicMapper mapper;
|
||||
|
||||
@Override
|
||||
public Object handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = String.valueOf(request.get("userId"));
|
||||
int gachaId = ((Number) request.get("gachaId")).intValue();
|
||||
int placeId = ((Number) request.get("placeId")).intValue();
|
||||
|
||||
UpsertUserGacha upsertUserGacha = mapper.convert(request.get("cmUpsertUserGacha"), UpsertUserGacha.class);
|
||||
List<UserCardPrintState> userCardPrintStateList = new ArrayList<>();
|
||||
Chu3UserData userData;
|
||||
|
||||
Optional<Chu3UserData> userOptional = userDataService.getUserByExtId(userId);
|
||||
if (userOptional.isPresent()) {
|
||||
userData = userOptional.get();
|
||||
} else {
|
||||
logger.error("User not found. userId: {}", userId);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (upsertUserGacha.getGameGachaCardList() != null) {
|
||||
for (GameGachaCard gameGachaCard : upsertUserGacha.getGameGachaCardList()) {
|
||||
UserCardPrintState userCardPrintState = new UserCardPrintState();
|
||||
userCardPrintState.setHasCompleted(false);
|
||||
userCardPrintState.setLimitDate(LocalDateTime.of(2029, 01, 01, 0, 0));
|
||||
userCardPrintState.setPlaceId(placeId);
|
||||
userCardPrintState.setCardId(gameGachaCard.getCardId());
|
||||
userCardPrintState.setGachaId(gachaId);
|
||||
userCardPrintState.setUser(userData);
|
||||
userCardPrintStateRepository.save(userCardPrintState);
|
||||
}
|
||||
}
|
||||
|
||||
List<UserItem> userItemListToSave = new ArrayList<>();
|
||||
List<UserItem> userItemList = upsertUserGacha.getUserItemList();
|
||||
|
||||
userItemList.forEach(newUserItem -> {
|
||||
int itemId = newUserItem.getItemId();
|
||||
int itemKind = newUserItem.getItemKind();
|
||||
|
||||
Optional<UserItem> userItemOptional = userItemService.getByUserAndItemIdAndKind(userData, itemId, itemKind);
|
||||
UserItem userItem = userItemOptional.orElseGet(() -> new UserItem());
|
||||
|
||||
newUserItem.setId(userItem.getId());
|
||||
newUserItem.setUser(userItem.getUser());
|
||||
|
||||
userItemListToSave.add(newUserItem);
|
||||
});
|
||||
userItemService.saveAll(userItemListToSave);
|
||||
|
||||
if (upsertUserGacha.getUserGacha() != null) {
|
||||
UserGacha newUserGacha = upsertUserGacha.getUserGacha();
|
||||
newUserGacha.setUser(userData);
|
||||
userGachaRepository.save(newUserGacha);
|
||||
}
|
||||
|
||||
userCardPrintStateList = userCardPrintStateRepository.findByUserAndGachaIdAndHasCompleted(userData, gachaId, false);
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("returnCode", 1);
|
||||
resultMap.put("apiName", "CMUpsertUserGachaApi");
|
||||
resultMap.put("userCardPrintStateList", userCardPrintStateList);
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chusan.handler;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserCardPrintStateRepo;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@Component("ChusanCMUpsertUserPrintCancelHandler")
|
||||
public class CMUpsertUserPrintCancelHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CMUpsertUserPrintCancelHandler.class);
|
||||
private final Chu3UserCardPrintStateRepo userCardPrintStateRepository;
|
||||
private final BasicMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public CMUpsertUserPrintCancelHandler(Chu3UserCardPrintStateRepo userCardPrintStateRepository, BasicMapper mapper) {
|
||||
this.userCardPrintStateRepository = userCardPrintStateRepository;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = String.valueOf(request.get("userId"));
|
||||
List<Integer> orderIdList = mapper.convert(request.get("orderIdList"), new TypeReference<List<Integer>>() {});
|
||||
|
||||
for (Integer orderId : orderIdList) {
|
||||
Optional<UserCardPrintState> userCardPrintStateOptional = userCardPrintStateRepository.findById(orderId.longValue());
|
||||
if (userCardPrintStateOptional.isPresent()) {
|
||||
UserCardPrintState newUserCardPrintState = userCardPrintStateOptional.get();
|
||||
newUserCardPrintState.setHasCompleted(true);
|
||||
userCardPrintStateRepository.save(newUserCardPrintState);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("returnCode", 1);
|
||||
resultMap.put("apiName", "CMUpsertUserPrintCancelApi");
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package icu.samnyan.aqua.sega.chusan.handler;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import icu.samnyan.aqua.sega.chusan.model.Chu3UserCardPrintStateRepo;
|
||||
import icu.samnyan.aqua.sega.general.BaseHandler;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3UserData;
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem;
|
||||
import icu.samnyan.aqua.sega.chusan.service.UserDataService;
|
||||
import icu.samnyan.aqua.sega.chusan.service.UserItemService;
|
||||
import icu.samnyan.aqua.sega.util.jackson.BasicMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author samnyan (privateamusement@protonmail.com)
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Component("ChusanCMUpsertUserPrintSubtractHandler")
|
||||
public class CMUpsertUserPrintSubtractHandler implements BaseHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CMUpsertUserPrintSubtractHandler.class);
|
||||
private final Chu3UserCardPrintStateRepo userCardPrintStateRepository;
|
||||
private final UserItemService userItemService;
|
||||
private final UserDataService userDataService;
|
||||
private final BasicMapper mapper;
|
||||
|
||||
@Override
|
||||
public String handle(Map<String, ?> request) throws JsonProcessingException {
|
||||
String userId = String.valueOf(request.get("userId"));
|
||||
UserCardPrintState userCardPrintState = mapper.convert(request.get("userCardPrintState"), UserCardPrintState.class);
|
||||
List<UserItem> userItemList = mapper.convert(request.get("userItemList"), new TypeReference<List<UserItem>>() {});
|
||||
|
||||
Chu3UserData userData;
|
||||
|
||||
Optional<Chu3UserData> userOptional = userDataService.getUserByExtId(userId);
|
||||
if (userOptional.isPresent()) {
|
||||
userData = userOptional.get();
|
||||
} else {
|
||||
logger.error("User not found. userId: {}", userId);
|
||||
return null;
|
||||
}
|
||||
|
||||
List<UserItem> userItemListToSave = new ArrayList<>();
|
||||
|
||||
userItemList.forEach(newUserItem -> {
|
||||
int itemId = newUserItem.getItemId();
|
||||
int itemKind = newUserItem.getItemKind();
|
||||
|
||||
Optional<UserItem> userItemOptional = userItemService.getByUserAndItemIdAndKind(userData, itemId, itemKind);
|
||||
UserItem userItem = userItemOptional.orElseGet(() -> new UserItem());
|
||||
|
||||
newUserItem.setId(userItem.getId());
|
||||
newUserItem.setUser(userItem.getUser());
|
||||
|
||||
userItemListToSave.add(newUserItem);
|
||||
});
|
||||
userItemService.saveAll(userItemListToSave);
|
||||
|
||||
Optional<UserCardPrintState> userCardPrintStateOptional = userCardPrintStateRepository.findById(userCardPrintState.getId());
|
||||
if (userCardPrintStateOptional.isPresent()) {
|
||||
UserCardPrintState newUserCardPrintState = userCardPrintStateOptional.get();
|
||||
newUserCardPrintState.setHasCompleted(true);
|
||||
userCardPrintStateRepository.save(newUserCardPrintState);
|
||||
}
|
||||
|
||||
Map<String, Object> resultMap = new LinkedHashMap<>();
|
||||
resultMap.put("returnCode", 1);
|
||||
resultMap.put("apiName", "CMUpsertUserPrintSubtractApi");
|
||||
|
||||
String json = mapper.write(resultMap);
|
||||
logger.info("Response: " + json);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
261
src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt
Normal file
261
src/main/java/icu/samnyan/aqua/sega/chusan/handler/ChusanApis.kt
Normal file
@@ -0,0 +1,261 @@
|
||||
package icu.samnyan.aqua.sega.chusan.handler
|
||||
|
||||
import ext.*
|
||||
import icu.samnyan.aqua.sega.allnet.TokenChecker
|
||||
import icu.samnyan.aqua.sega.chusan.ChusanController
|
||||
import icu.samnyan.aqua.sega.chusan.ChusanData
|
||||
import icu.samnyan.aqua.sega.chusan.model.request.UserCMissionResp
|
||||
import icu.samnyan.aqua.sega.chusan.model.request.UserEmoney
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCharge
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserMusicDetail
|
||||
import icu.samnyan.aqua.sega.general.model.response.UserRecentRating
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun ChusanController.chusanInit() {
|
||||
matchingApiInit()
|
||||
cmApiInit()
|
||||
|
||||
// Stub handlers
|
||||
"GetGameRanking" { """{"type":"${data["type"]}","length":"0","gameRankingList":[]}""" }
|
||||
"GetGameIdlist" { """{"type":"${data["type"]}","length":"0","gameIdlistList":[]}""" }
|
||||
|
||||
"GetTeamCourseSetting" { """{"userId":"${data["userId"]}","length":"0","nextIndex":"0","teamCourseSettingList":[]}""" }
|
||||
"GetTeamCourseRule" { """{"userId":"${data["userId"]}","length":"0","nextIndex":"0","teamCourseRuleList":[]}""" }
|
||||
"GetUserCtoCPlay" { """{"userId":"${data["userId"]}","orderBy":"0","count":"0","userCtoCPlayList":[]}""" }
|
||||
"GetUserRivalMusic" { """{"userId":"${data["userId"]}","rivalId":"0","length":"0","nextIndex":"0","userRivalMusicList":[]}""" }
|
||||
"GetUserRivalData" { """{"userId":"${data["userId"]}","length":"0","userRivalData":[]}""" }
|
||||
"GetUserRegion" { """{"userId":"${data["userId"]}","length":"0","userRegionList":[]}""" }
|
||||
"GetUserPrintedCard" { """{"userId":"${data["userId"]}","length":0,"nextIndex":-1,"userPrintedCardList":[]}""" }
|
||||
"GetUserSymbolChatSetting" { """{"userId":"${data["userId"]}","length":"0","symbolChatInfoList":[]}""" }
|
||||
"GetUserNetBattleData" { """{"userId":"${data["userId"]}","userNetBattleData":{"recentNBSelectMusicList":[],"recentNBMusicList":[]}}""" }
|
||||
"GetUserNetBattleRankingInfo" { """{"userId":"${data["userId"]}","length":"0","userNetBattleRankingInfoList":{}}""" }
|
||||
|
||||
"CMUpsertUserPrint" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintApi"}""" }
|
||||
"CMUpsertUserPrintlog" { """{"returnCode":1,"orderId":"0","serialId":"FAKECARDIMAG12345678","apiName":"CMUpsertUserPrintlogApi"}""" }
|
||||
|
||||
// User handlers
|
||||
"GetUserData" {
|
||||
db.userData.findByCard_ExtId(uid)()?.let{ u -> mapOf("userId" to uid, "userData" to u) }
|
||||
}
|
||||
"GetUserOption" {
|
||||
val userGameOption = db.userGameOption.findSingleByUser_Card_ExtId(uid)() ?: (400 - "User not found")
|
||||
mapOf("userId" to uid, "userGameOption" to userGameOption)
|
||||
}
|
||||
|
||||
"RollGacha" {
|
||||
val (gachaId, times) = parsing { data["gachaId"]!!.int to data["times"]!!.int }
|
||||
val lst = db.gameGachaCard.findAllByGachaId(gachaId).shuffled().take(times)
|
||||
mapOf("length" to lst.size, "gameGachaCardList" to lst)
|
||||
}
|
||||
|
||||
"GetGameGachaCardById" {
|
||||
val id = parsing { data["gachaId"]!!.int }
|
||||
db.gameGachaCard.findAllByGachaId(id).let {
|
||||
mapOf("gachaId" to id, "length" to it.size, "isPickup" to false, "gameGachaCardList" to it,
|
||||
"emissionList" to empty, "afterCalcList" to empty
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
"GetUserCMission" {
|
||||
parsing { UserCMissionResp().apply {
|
||||
missionId = parsing { data["missionId"]!!.int }
|
||||
} }.apply {
|
||||
db.userCMission.findByUser_Card_ExtIdAndMissionId(uid, missionId)()?.let {
|
||||
point = it.point
|
||||
userCMissionProgressList = db.userCMissionProgress.findByUser_Card_ExtIdAndMissionId(uid, missionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Paged user list endpoints
|
||||
"GetUserCardPrintError".paged("userCardPrintErrorList") { db.userCardPrintState.findByUser_Card_ExtIdAndHasCompleted(uid, false) }
|
||||
"GetUserCharacter".paged("userCharacterList") { db.userCharacter.findByUser_Card_ExtId(uid) }
|
||||
"GetUserCourse".paged("userCourseList") { db.userCourse.findByUser_Card_ExtId(uid) }
|
||||
"GetUserCharge".paged("userChargeList") { db.userCharge.findByUser_Card_ExtId(uid) }
|
||||
"GetUserDuel".paged("userDuelList") { db.userDuel.findByUser_Card_ExtId(uid) }
|
||||
"GetUserGacha".paged("userGachaList") { db.userGacha.findByUser_Card_ExtId(uid) }
|
||||
|
||||
// Paged user list endpoints that has a kind in their request
|
||||
"GetUserActivity".pagedWithKind("userActivityList") {
|
||||
val kind = parsing { data["kind"]!!.int }
|
||||
mapOf("kind" to kind) grabs {
|
||||
db.userActivity.findAllByUser_Card_ExtIdAndKind(uid, kind).sortedBy { -it.sortNumber }
|
||||
}
|
||||
}
|
||||
|
||||
// Check dev/chusan_dev_notes for more item information
|
||||
val penguins = ls(8000, 8010, 8020, 8030)
|
||||
|
||||
"GetUserItem".pagedWithKind("userItemList") {
|
||||
val rawIndex = data["nextIndex"]!!.long
|
||||
val kind = parsing { (rawIndex / 10000000000L).int }
|
||||
data["nextIndex"] = rawIndex % 10000000000L
|
||||
mapOf("itemKind" to kind) grabs {
|
||||
// TODO: All unlock
|
||||
val items = db.userItem.findAllByUser_Card_ExtIdAndItemKind(uid, kind).toMutableList()
|
||||
|
||||
// Check game options
|
||||
db.userData.findByCard_ExtId(uid)()?.card?.aquaUser?.gameOptions?.let {
|
||||
if (it.chusanInfinitePenguins && kind == 5) {
|
||||
items.removeAll { it.itemId in penguins }
|
||||
items.addAll(penguins.map { UserItem(kind, it, 999, true) })
|
||||
}
|
||||
}
|
||||
|
||||
items
|
||||
} postProcess {
|
||||
val ni = it["nextIndex"]!!.long
|
||||
if (ni != -1L) it["nextIndex"] = ni + (kind * 10000000000L)
|
||||
}
|
||||
}
|
||||
|
||||
"GetUserFavoriteItem".pagedWithKind("userFavoriteItemList") {
|
||||
val kind = parsing { data["kind"]!!.int }
|
||||
mapOf("kind" to kind) grabs {
|
||||
// TODO: Actually store this info at UpsertUserAll
|
||||
val fav = when (kind) {
|
||||
1 -> "favorite_music"
|
||||
3 -> "favorite_chara"
|
||||
else -> null
|
||||
}?.let { db.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(uid, it)() }?.propertyValue
|
||||
|
||||
fav?.ifBlank { null }?.split(",")?.map { it.int } ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
val userPreviewKeys = ("userName,reincarnationNum,level,exp,playerRating,lastGameId,lastRomVersion," +
|
||||
"lastDataVersion,trophyId,classEmblemMedal,classEmblemBase,battleRankId").split(',').toSet()
|
||||
|
||||
"GetUserPreview" api@ {
|
||||
val user = db.userData.findByCard_ExtId(uid)() ?: return@api null
|
||||
val chara = db.userCharacter.findByUserAndCharacterId(user, user.characterId)
|
||||
val option = db.userGameOption.findSingleByUser(user)()
|
||||
val userDict = user.toJson().jsonMap().filterKeys { it in userPreviewKeys }
|
||||
|
||||
mapOf(
|
||||
"userId" to uid, "isLogin" to false, "emoneyBrandId" to 0,
|
||||
"lastLoginDate" to user.lastLoginDate, "lastPlayDate" to user.lastPlayDate,
|
||||
"userCharacter" to chara,
|
||||
"playerLevel" to option?.playerLevel,
|
||||
"rating" to option?.rating,
|
||||
"headphone" to option?.headphone,
|
||||
"chargeState" to 1, "userNameEx" to "", "banState" to 0,
|
||||
) + userDict
|
||||
}
|
||||
|
||||
"GetUserMusic".paged("userMusicList") {
|
||||
// Compatibility: Older chusan uses boolean for isSuccess
|
||||
fun checkAncient(d: List<UserMusicDetail>) =
|
||||
data["version"]?.double?.let { if (it >= 2.15) d else d.map {
|
||||
d.toJson().jsonMap().toMutableMap().apply { this["isSuccess"] = this["isSuccess"].truthy }
|
||||
} } ?: d
|
||||
|
||||
db.userMusicDetail.findByUser_Card_ExtId(uid).groupBy { it.musicId }
|
||||
.mapValues { mapOf("length" to it.value.size, "userMusicDetailList" to checkAncient(it.value)) }
|
||||
.values.toList()
|
||||
}
|
||||
|
||||
"GetUserLoginBonus".paged("userLoginBonusList") {
|
||||
if (!props.loginBonusEnable) empty else db.userLoginBonus.findAllLoginBonus(uid.int, 1, 0)
|
||||
}
|
||||
|
||||
"GetUserRecentRating".paged("userRecentRatingList") {
|
||||
db.userGeneralData.findByUser_Card_ExtIdAndPropertyKey(uid, "recent_rating_list")()
|
||||
?.propertyValue?.ifBlank { null }
|
||||
?.split(',')?.dropLastWhile { it.isEmpty() }?.map { it.split(':') }
|
||||
?.map { (musicId, level, score) -> UserRecentRating(musicId.int, level.int, "2000001", score.int) }
|
||||
?: listOf()
|
||||
}
|
||||
|
||||
"GetUserMapArea" {
|
||||
val maps = parsing { data["mapAreaIdList"] as List<Map<String, String>> }
|
||||
.mapNotNull { it["mapAreaId"]?.toIntOrNull() }
|
||||
|
||||
mapOf("userId" to uid, "userMapAreaList" to db.userMap.findAllByUserCardExtIdAndMapAreaIdIn(uid, maps))
|
||||
}
|
||||
|
||||
"GetUserTeam" {
|
||||
val playDate = parsing { data["playDate"] as String }
|
||||
val team = db.userData.findByCard_ExtId(uid)()?.card?.aquaUser?.gameOptions?.chusanTeamName?.ifBlank { null }
|
||||
?: props.teamName?.ifBlank { null } ?: "一緒に歌おう!"
|
||||
|
||||
mapOf(
|
||||
"userId" to uid, "teamId" to 1, "teamRank" to 1, "teamName" to team,
|
||||
"userTeamPoint" to mapOf("userId" to uid, "teamId" to 1, "orderId" to 1, "teamPoint" to 1, "aggrDate" to playDate)
|
||||
)
|
||||
}
|
||||
|
||||
// Game settings
|
||||
"GetGameSetting" {
|
||||
val version = data["version"].toString()
|
||||
|
||||
// Fixed reboot time triggers chusan maintenance lockout, so let's try minime method which sets it dynamically
|
||||
// Special thanks to skogaby
|
||||
// Hardcode so that the reboot time always started 3 hours ago and ended 2 hours ago
|
||||
val fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss")
|
||||
val now = jstNow()
|
||||
|
||||
// Set the matching & reflector to the one set in the game options, or the external matching server
|
||||
val opts = TokenChecker.getCurrentSession()?.user?.gameOptions
|
||||
val matching = opts?.chusanMatchingServer?.ifBlank { null } ?:
|
||||
props.externalMatching?.ifBlank { null } ?:
|
||||
(req.getHeader("wrapper original url") ?: req.requestURL.toString())
|
||||
.removeSuffix("GetGameSettingApi").removeSuffix("ChuniServlet/")
|
||||
val reflector = opts?.chusanMatchingReflector?.ifBlank { null } ?:
|
||||
props.reflectorUrl
|
||||
|
||||
mapOf(
|
||||
"gameSetting" to mapOf(
|
||||
"romVersion" to "$version.00",
|
||||
"dataVersion" to versionHelper[data["clientId"].toString()],
|
||||
"isMaintenance" to false,
|
||||
"requestInterval" to 0,
|
||||
"rebootStartTime" to now.minusHours(4).format(fmt),
|
||||
"rebootEndTime" to now.minusHours(3).format(fmt),
|
||||
"isBackgroundDistribute" to false,
|
||||
"maxCountCharacter" to 300,
|
||||
"maxCountItem" to 300,
|
||||
"maxCountMusic" to 300,
|
||||
"matchStartTime" to now.minusHours(1).format(fmt),
|
||||
"matchEndTime" to now.plusHours(7).format(fmt),
|
||||
"matchTimeLimit" to 10,
|
||||
"matchErrorLimit" to 10,
|
||||
"matchingUri" to matching.ensureEndingSlash(),
|
||||
"matchingUriX" to matching.ensureEndingSlash(),
|
||||
"udpHolePunchUri" to reflector?.ensureEndingSlash(),
|
||||
"reflectorUri" to reflector?.ensureEndingSlash(),
|
||||
),
|
||||
"isDumpUpload" to false,
|
||||
"isAou" to false
|
||||
)
|
||||
}
|
||||
|
||||
// Upserts
|
||||
"UpsertUserChargelog" {
|
||||
val charge = parsing { mapper.convert<UserCharge>(data["userCharge"] as JDict) }
|
||||
charge.user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
charge.id = db.userCharge.findByUser_Card_ExtIdAndChargeId(uid, charge.chargeId)?.id ?: 0
|
||||
db.userCharge.save(charge)
|
||||
"""{"returnCode":"1"}"""
|
||||
}
|
||||
|
||||
// Static
|
||||
"GetGameEvent" static { db.gameEvent.findByEnable(true).let { mapOf("type" to 1, "length" to it.size, "gameEventList" to it) } }
|
||||
"GetGameCharge" static { db.gameCharge.findAll().let { mapOf("length" to it.size, "gameChargeList" to it) } }
|
||||
"GetGameGacha" static { db.gameGacha.findAll().let { mapOf("length" to it.size, "gameGachaList" to it, "registIdList" to empty) } }
|
||||
"GetGameMapAreaCondition" static { ChusanData.mapAreaCondition }
|
||||
|
||||
// CardMaker (TODO: Somebody test this, I don't have a card maker)
|
||||
"CMGetUserData" {
|
||||
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
user.userEmoney = UserEmoney()
|
||||
mapOf("userId" to uid, "userData" to user, "userEmoney" to user.userEmoney)
|
||||
}
|
||||
"CMGetUserPreview" {
|
||||
val user = db.userData.findByCard_ExtId(uid)() ?: (400 - "User not found")
|
||||
mapOf("userName" to user.userName, "level" to user.level, "medal" to user.medal, "lastDataVersion" to user.lastDataVersion, "isLogin" to false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package icu.samnyan.aqua.sega.chusan.handler
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import ext.int
|
||||
import ext.invoke
|
||||
import ext.mapApply
|
||||
import ext.parsing
|
||||
import icu.samnyan.aqua.sega.chusan.ChusanController
|
||||
import icu.samnyan.aqua.sega.chusan.model.request.UpsertUserGacha
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserCardPrintState
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.UserItem
|
||||
import java.time.LocalDateTime
|
||||
|
||||
fun ChusanController.cmApiInit() {
|
||||
"CMUpsertUserGacha" api@ {
|
||||
val (gachaId, placeId) = parsing { data["gachaId"]!!.int to data["placeId"]!!.int }
|
||||
|
||||
val u = db.userData.findByCard_ExtId(uid)() ?: return@api null
|
||||
val upsertUserGacha = parsing { mapper.convert(data["cmUpsertUserGacha"], UpsertUserGacha::class.java) }
|
||||
|
||||
upsertUserGacha.gameGachaCardList?.let { lst ->
|
||||
db.userCardPrintState.saveAll(lst.map {
|
||||
UserCardPrintState(
|
||||
hasCompleted = false,
|
||||
limitDate = LocalDateTime.of(2029, 1, 1, 0, 0),
|
||||
placeId = placeId,
|
||||
cardId = it.cardId,
|
||||
gachaId = gachaId
|
||||
).apply { user = u }
|
||||
})
|
||||
}
|
||||
|
||||
upsertUserGacha.userItemList?.let {
|
||||
db.userItem.saveAll(it.mapApply {
|
||||
user = u
|
||||
id = db.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0
|
||||
})
|
||||
}
|
||||
|
||||
upsertUserGacha.userGacha?.let {
|
||||
it.user = u
|
||||
db.userGacha.save(it)
|
||||
}
|
||||
|
||||
mapOf(
|
||||
"returnCode" to 1,
|
||||
"apiName" to "CMUpsertUserGachaApi",
|
||||
"userCardPrintStateList" to db.userCardPrintState.findByUserAndGachaIdAndHasCompleted(u, gachaId, false)
|
||||
)
|
||||
}
|
||||
|
||||
"CMUpsertUserPrintCancel" {
|
||||
val orderIdList: List<Long> = cmMapper.convert(data["orderIdList"], object : TypeReference<List<Long>>() {})
|
||||
|
||||
db.userCardPrintState.saveAll(orderIdList.mapNotNull {
|
||||
// TODO: The original code by Eori writes findById but I don't think that is correct...
|
||||
db.userCardPrintState.findById(it)()?.apply {
|
||||
hasCompleted = true
|
||||
}
|
||||
})
|
||||
|
||||
mapOf("returnCode" to 1, "apiName" to "CMUpsertUserPrintCancelApi")
|
||||
}
|
||||
|
||||
"CMUpsertUserPrintSubtract" api@ {
|
||||
val userCardPrintState = cmMapper.convert(data["userCardPrintState"], UserCardPrintState::class.java)
|
||||
val userItemList = cmMapper.convert(data["userItemList"], object : TypeReference<List<UserItem>>() {})
|
||||
|
||||
val u = db.userData.findByCard_ExtId(uid)() ?: return@api null
|
||||
|
||||
db.userItem.saveAll(
|
||||
userItemList.mapApply {
|
||||
id = db.userItem.findByUserAndItemIdAndItemKind(u, itemId, itemKind)?.id ?: 0
|
||||
user = u
|
||||
}
|
||||
)
|
||||
|
||||
// TODO: I also doubt this is correct... it shouldn't be ID
|
||||
db.userCardPrintState.findById(userCardPrintState.id)()?.apply {
|
||||
hasCompleted = true
|
||||
db.userCardPrintState.save(this)
|
||||
}
|
||||
|
||||
mapOf("returnCode" to 1, "apiName" to "CMUpsertUserPrintSubtractApi")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
@file:Suppress("UNCHECKED_CAST")
|
||||
|
||||
package icu.samnyan.aqua.sega.chusan.handler
|
||||
|
||||
import ext.JDict
|
||||
import ext.int
|
||||
import ext.millis
|
||||
import ext.parsing
|
||||
import icu.samnyan.aqua.sega.chusan.ChusanController
|
||||
import icu.samnyan.aqua.sega.chusan.model.request.MatchingWaitState
|
||||
import icu.samnyan.aqua.sega.chusan.model.userdata.Chu3MatchingMemberReq
|
||||
import kotlin.collections.MutableList
|
||||
import kotlin.collections.find
|
||||
import kotlin.collections.indices
|
||||
import kotlin.collections.listOf
|
||||
import kotlin.collections.map
|
||||
import kotlin.collections.mapOf
|
||||
import kotlin.collections.mutableListOf
|
||||
import kotlin.collections.mutableMapOf
|
||||
import kotlin.collections.set
|
||||
|
||||
|
||||
fun ChusanController.matchingApiInit() {
|
||||
if (props.externalMatching.isNullOrBlank()) serverOnlyMatching()
|
||||
}
|
||||
|
||||
/**
|
||||
* Matching implementation that matches you to players in this server only (not tested very well)
|
||||
*/
|
||||
fun ChusanController.serverOnlyMatching() {
|
||||
// Matching
|
||||
data class MatchingRoom(val members: MutableList<Chu3MatchingMemberReq>, val startTime: Long)
|
||||
val matchingRooms = mutableMapOf<Int, MatchingRoom>()
|
||||
var matchingLast = 0
|
||||
val matchingTime = 120 // Seconds
|
||||
|
||||
"BeginMatching" {
|
||||
val memberInfo = parsing { mapper.convert<Chu3MatchingMemberReq>(data["matchingMemberInfo"] as JDict) }
|
||||
|
||||
// Check if there are any room available with less than 4 members and not started
|
||||
var id = matchingRooms.entries.find { it.value.members.size < 4 && it.value.startTime == 0L }?.key
|
||||
if (id == null) {
|
||||
matchingLast += 1
|
||||
id = matchingLast
|
||||
matchingRooms[id] = MatchingRoom(mutableListOf(memberInfo), millis())
|
||||
}
|
||||
|
||||
mapOf("roomId" to id, "matchingWaitState" to MatchingWaitState(listOf(memberInfo)))
|
||||
}
|
||||
|
||||
"GetMatchingState" api@ {
|
||||
val roomId = parsing { data["roomId"]!!.int }
|
||||
val room = matchingRooms[roomId] ?: return@api null
|
||||
val dt = matchingTime - (millis() - room.startTime) / 1000
|
||||
val ended = room.members.size == 4 || dt <= 0
|
||||
|
||||
mapOf("roomId" to roomId, "matchingWaitState" to MatchingWaitState(room.members, ended, dt.int, 1))
|
||||
}
|
||||
|
||||
"EndMatching" api@ {
|
||||
val roomId = parsing { data["roomId"]!!.int }
|
||||
val room = matchingRooms[roomId] ?: return@api null
|
||||
mapOf(
|
||||
"matchingMemberInfoList" to room.members,
|
||||
"matchingMemberRoleList" to room.members.indices.map { mapOf("role" to it) },
|
||||
"matchingResult" to 1,
|
||||
"reflectorUri" to props.reflectorUrl
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user