mirror of
https://github.com/BillyCool/MariesWonderland.git
synced 2026-05-06 20:53:42 +02:00
Simplify userdb access
This commit is contained in:
@@ -10,6 +10,8 @@ namespace MariesWonderland.Data;
|
||||
/// </summary>
|
||||
public class DarkUserMemoryDatabase
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
|
||||
public List<EntityIUser> EntityIUser { get; set; } = [];
|
||||
|
||||
public List<EntityIUserApple> EntityIUserApple { get; set; } = [];
|
||||
|
||||
@@ -26,8 +26,8 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
var userId = GenerateUserId();
|
||||
_uuidToUserId[uuid] = userId;
|
||||
var db = new DarkUserMemoryDatabase();
|
||||
SeedInitialUserData(db, userId);
|
||||
var db = new DarkUserMemoryDatabase { UserId = userId };
|
||||
SeedInitialUserData(db);
|
||||
_users[userId] = db;
|
||||
return (userId, true);
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
if (!_users.TryGetValue(userId, out var db))
|
||||
{
|
||||
db = new DarkUserMemoryDatabase();
|
||||
db = new DarkUserMemoryDatabase { UserId = userId };
|
||||
_users[userId] = db;
|
||||
}
|
||||
return db;
|
||||
@@ -96,7 +96,10 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
/// Stores a user database, replacing any existing one for that userId.
|
||||
/// </summary>
|
||||
public void Set(long userId, DarkUserMemoryDatabase db)
|
||||
=> _users[userId] = db;
|
||||
{
|
||||
db.UserId = userId;
|
||||
_users[userId] = db;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<long, DarkUserMemoryDatabase> All => _users;
|
||||
|
||||
@@ -141,7 +144,10 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
_sessions.Clear();
|
||||
|
||||
foreach (var (userId, db) in snapshot.Users)
|
||||
{
|
||||
db.UserId = userId;
|
||||
_users[userId] = db;
|
||||
}
|
||||
|
||||
foreach (var (uuid, userId) in snapshot.UuidToUserId)
|
||||
_uuidToUserId[uuid] = userId;
|
||||
@@ -173,13 +179,13 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
/// <summary>
|
||||
/// Populates a new user database with default records (profile, status, starting weapons, etc.).
|
||||
/// </summary>
|
||||
private void SeedInitialUserData(DarkUserMemoryDatabase db, long userId)
|
||||
private void SeedInitialUserData(DarkUserMemoryDatabase db)
|
||||
{
|
||||
var nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
db.EntityIUser.Add(new EntityIUser
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
PlayerId = GeneratePlayerId(),
|
||||
OsType = 2,
|
||||
PlatformType = PlatformType.GOOGLE_PLAY_STORE,
|
||||
@@ -190,13 +196,13 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserSetting.Add(new EntityIUserSetting
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
IsNotifyPurchaseAlert = false
|
||||
});
|
||||
|
||||
db.EntityIUserStatus.Add(new EntityIUserStatus
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
Level = 1,
|
||||
Exp = 0,
|
||||
StaminaMilliValue = 60000,
|
||||
@@ -205,7 +211,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserProfile.Add(new EntityIUserProfile
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
Name = string.Empty,
|
||||
NameUpdateDatetime = nowMs,
|
||||
Message = string.Empty,
|
||||
@@ -216,7 +222,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserLogin.Add(new EntityIUserLogin
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
TotalLoginCount = 1,
|
||||
ContinualLoginCount = 1,
|
||||
MaxContinualLoginCount = 1,
|
||||
@@ -226,7 +232,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserLoginBonus.Add(new EntityIUserLoginBonus
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
LoginBonusId = 1,
|
||||
CurrentPageNumber = 1,
|
||||
CurrentStampNumber = 0,
|
||||
@@ -235,7 +241,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserTutorialProgress.Add(new EntityIUserTutorialProgress
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
TutorialType = TutorialType.GAME_START,
|
||||
ProgressPhase = 0,
|
||||
ChoiceId = 0
|
||||
@@ -247,7 +253,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserWeapon.Add(new EntityIUserWeapon
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserWeaponUuid = uuid,
|
||||
WeaponId = weaponId,
|
||||
Level = 1,
|
||||
@@ -259,7 +265,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserWeaponNote.Add(new EntityIUserWeaponNote
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
WeaponId = weaponId,
|
||||
MaxLevel = 1,
|
||||
MaxLimitBreakCount = 0,
|
||||
@@ -268,7 +274,7 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
db.EntityIUserWeaponStory.Add(new EntityIUserWeaponStory
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
WeaponId = weaponId,
|
||||
ReleasedMaxStoryIndex = 1
|
||||
});
|
||||
@@ -277,10 +283,10 @@ public class UserDataStore(DarkMasterMemoryDatabase masterDb)
|
||||
if (masterWeapon != null)
|
||||
{
|
||||
foreach (EntityMWeaponAbilityGroup ag in _masterDb.EntityMWeaponAbilityGroup.Where(g => g.WeaponAbilityGroupId == masterWeapon.WeaponAbilityGroupId))
|
||||
db.EntityIUserWeaponAbility.Add(new EntityIUserWeaponAbility { UserId = userId, UserWeaponUuid = uuid, SlotNumber = ag.SlotNumber, Level = 1 });
|
||||
db.EntityIUserWeaponAbility.Add(new EntityIUserWeaponAbility { UserId = db.UserId, UserWeaponUuid = uuid, SlotNumber = ag.SlotNumber, Level = 1 });
|
||||
|
||||
foreach (EntityMWeaponSkillGroup sg in _masterDb.EntityMWeaponSkillGroup.Where(g => g.WeaponSkillGroupId == masterWeapon.WeaponSkillGroupId))
|
||||
db.EntityIUserWeaponSkill.Add(new EntityIUserWeaponSkill { UserId = userId, UserWeaponUuid = uuid, SlotNumber = sg.SlotNumber, Level = 1 });
|
||||
db.EntityIUserWeaponSkill.Add(new EntityIUserWeaponSkill { UserId = db.UserId, UserWeaponUuid = uuid, SlotNumber = sg.SlotNumber, Level = 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public static class PossessionHelper
|
||||
/// <summary>
|
||||
/// Grants a possession to the user by type, delegating to type-specific handlers.
|
||||
/// </summary>
|
||||
public static void Apply(DarkUserMemoryDatabase userDb, long userId, PossessionType type, int id, int count, DarkMasterMemoryDatabase masterDb)
|
||||
public static void Apply(DarkUserMemoryDatabase userDb, PossessionType type, int id, int count, DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
@@ -29,7 +29,7 @@ public static class PossessionHelper
|
||||
{
|
||||
EntityIUserMaterial? mat = userDb.EntityIUserMaterial.FirstOrDefault(m => m.MaterialId == id);
|
||||
if (mat == null)
|
||||
userDb.EntityIUserMaterial.Add(new EntityIUserMaterial { UserId = userId, MaterialId = id, Count = count, FirstAcquisitionDatetime = nowMs });
|
||||
userDb.EntityIUserMaterial.Add(new EntityIUserMaterial { UserId = userDb.UserId, MaterialId = id, Count = count, FirstAcquisitionDatetime = nowMs });
|
||||
else
|
||||
mat.Count += count;
|
||||
break;
|
||||
@@ -38,7 +38,7 @@ public static class PossessionHelper
|
||||
{
|
||||
EntityIUserConsumableItem? item = userDb.EntityIUserConsumableItem.FirstOrDefault(c => c.ConsumableItemId == id);
|
||||
if (item == null)
|
||||
userDb.EntityIUserConsumableItem.Add(new EntityIUserConsumableItem { UserId = userId, ConsumableItemId = id, Count = count, FirstAcquisitionDatetime = nowMs });
|
||||
userDb.EntityIUserConsumableItem.Add(new EntityIUserConsumableItem { UserId = userDb.UserId, ConsumableItemId = id, Count = count, FirstAcquisitionDatetime = nowMs });
|
||||
else
|
||||
item.Count += count;
|
||||
break;
|
||||
@@ -47,7 +47,7 @@ public static class PossessionHelper
|
||||
{
|
||||
EntityIUserImportantItem? item = userDb.EntityIUserImportantItem.FirstOrDefault(c => c.ImportantItemId == id);
|
||||
if (item == null)
|
||||
userDb.EntityIUserImportantItem.Add(new EntityIUserImportantItem { UserId = userId, ImportantItemId = id, Count = count, FirstAcquisitionDatetime = nowMs });
|
||||
userDb.EntityIUserImportantItem.Add(new EntityIUserImportantItem { UserId = userDb.UserId, ImportantItemId = id, Count = count, FirstAcquisitionDatetime = nowMs });
|
||||
else
|
||||
item.Count += count;
|
||||
break;
|
||||
@@ -56,24 +56,24 @@ public static class PossessionHelper
|
||||
{
|
||||
EntityIUserPremiumItem? item = userDb.EntityIUserPremiumItem.FirstOrDefault(p => p.PremiumItemId == id);
|
||||
if (item == null)
|
||||
userDb.EntityIUserPremiumItem.Add(new EntityIUserPremiumItem { UserId = userId, PremiumItemId = id, AcquisitionDatetime = nowMs });
|
||||
userDb.EntityIUserPremiumItem.Add(new EntityIUserPremiumItem { UserId = userDb.UserId, PremiumItemId = id, AcquisitionDatetime = nowMs });
|
||||
else
|
||||
item.AcquisitionDatetime = nowMs;
|
||||
break;
|
||||
}
|
||||
case PossessionType.WEAPON:
|
||||
case PossessionType.WEAPON_ENHANCED:
|
||||
WeaponHelper.GrantWeapon(userDb, userId, id, masterDb);
|
||||
WeaponHelper.GrantWeapon(userDb, id, masterDb);
|
||||
break;
|
||||
case PossessionType.COSTUME:
|
||||
case PossessionType.COSTUME_ENHANCED:
|
||||
GrantCostume(userDb, userId, id, masterDb);
|
||||
GrantCostume(userDb, id, masterDb);
|
||||
break;
|
||||
case PossessionType.COMPANION:
|
||||
GrantCompanion(userDb, userId, id);
|
||||
GrantCompanion(userDb, id);
|
||||
break;
|
||||
case PossessionType.PARTS:
|
||||
GrantParts(userDb, userId, id, masterDb);
|
||||
GrantParts(userDb, id, masterDb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -81,14 +81,14 @@ public static class PossessionHelper
|
||||
/// <summary>
|
||||
/// Grants a costume to the user, unlocking the associated character if not already owned.
|
||||
/// </summary>
|
||||
public static void GrantCostume(DarkUserMemoryDatabase userDb, long userId, int costumeId, DarkMasterMemoryDatabase masterDb)
|
||||
public static void GrantCostume(DarkUserMemoryDatabase userDb, int costumeId, DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
string uuid = Guid.NewGuid().ToString();
|
||||
|
||||
userDb.EntityIUserCostume.Add(new EntityIUserCostume
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
UserCostumeUuid = uuid,
|
||||
CostumeId = costumeId,
|
||||
Level = 1,
|
||||
@@ -99,22 +99,22 @@ public static class PossessionHelper
|
||||
// Auto-unlock the character tied to this costume if not already owned
|
||||
EntityMCostume? masterCostume = masterDb.EntityMCostume.FirstOrDefault(c => c.CostumeId == costumeId);
|
||||
if (masterCostume != null && !userDb.EntityIUserCharacter.Any(c => c.CharacterId == masterCostume.CharacterId))
|
||||
userDb.EntityIUserCharacter.Add(new EntityIUserCharacter { UserId = userId, CharacterId = masterCostume.CharacterId, Level = 1 });
|
||||
userDb.EntityIUserCharacter.Add(new EntityIUserCharacter { UserId = userDb.UserId, CharacterId = masterCostume.CharacterId, Level = 1 });
|
||||
|
||||
userDb.EntityIUserCostumeActiveSkill.Add(new EntityIUserCostumeActiveSkill { UserId = userId, UserCostumeUuid = uuid, Level = 1, AcquisitionDatetime = nowMs });
|
||||
userDb.EntityIUserCostumeActiveSkill.Add(new EntityIUserCostumeActiveSkill { UserId = userDb.UserId, UserCostumeUuid = uuid, Level = 1, AcquisitionDatetime = nowMs });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grants a companion to the user. Skips if the companion is already owned.
|
||||
/// </summary>
|
||||
public static void GrantCompanion(DarkUserMemoryDatabase userDb, long userId, int companionId)
|
||||
public static void GrantCompanion(DarkUserMemoryDatabase userDb, int companionId)
|
||||
{
|
||||
if (userDb.EntityIUserCompanion.Any(c => c.CompanionId == companionId)) return;
|
||||
|
||||
long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
userDb.EntityIUserCompanion.Add(new EntityIUserCompanion
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
UserCompanionUuid = Guid.NewGuid().ToString(),
|
||||
CompanionId = companionId,
|
||||
Level = 1,
|
||||
@@ -126,7 +126,7 @@ public static class PossessionHelper
|
||||
/// <summary>
|
||||
/// Grants a single Parts item to the user. Skips if the user already owns a part with the same PartsId.
|
||||
/// </summary>
|
||||
public static void GrantParts(DarkUserMemoryDatabase userDb, long userId, int partsId, DarkMasterMemoryDatabase masterDb)
|
||||
public static void GrantParts(DarkUserMemoryDatabase userDb, int partsId, DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
if (userDb.EntityIUserParts.Any(p => p.PartsId == partsId)) return;
|
||||
|
||||
@@ -148,7 +148,7 @@ public static class PossessionHelper
|
||||
{
|
||||
userDb.EntityIUserPartsGroupNote.Add(new EntityIUserPartsGroupNote
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
PartsGroupId = partsDef.PartsGroupId,
|
||||
FirstAcquisitionDatetime = nowMs
|
||||
});
|
||||
@@ -157,7 +157,7 @@ public static class PossessionHelper
|
||||
|
||||
userDb.EntityIUserParts.Add(new EntityIUserParts
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
UserPartsUuid = Guid.NewGuid().ToString(),
|
||||
PartsId = partsId,
|
||||
Level = 1,
|
||||
|
||||
@@ -14,14 +14,14 @@ public static class WeaponHelper
|
||||
/// Grants a weapon to the user: creates EntityIUserWeapon, EntityIUserWeaponNote (if new),
|
||||
/// ability/skill slots, and unlocks weapon stories for the ACQUISITION condition.
|
||||
/// </summary>
|
||||
public static void GrantWeapon(DarkUserMemoryDatabase userDb, long userId, int weaponId, DarkMasterMemoryDatabase masterDb)
|
||||
public static void GrantWeapon(DarkUserMemoryDatabase userDb, int weaponId, DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
string uuid = Guid.NewGuid().ToString();
|
||||
|
||||
userDb.EntityIUserWeapon.Add(new EntityIUserWeapon
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
UserWeaponUuid = uuid,
|
||||
WeaponId = weaponId,
|
||||
Level = 1,
|
||||
@@ -33,7 +33,7 @@ public static class WeaponHelper
|
||||
{
|
||||
userDb.EntityIUserWeaponNote.Add(new EntityIUserWeaponNote
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
WeaponId = weaponId,
|
||||
MaxLevel = 1,
|
||||
FirstAcquisitionDatetime = nowMs
|
||||
@@ -46,11 +46,11 @@ public static class WeaponHelper
|
||||
|
||||
// Create one ability slot per entry in the weapon's ability group
|
||||
foreach (EntityMWeaponAbilityGroup ag in masterDb.EntityMWeaponAbilityGroup.Where(g => g.WeaponAbilityGroupId == masterWeapon.WeaponAbilityGroupId))
|
||||
userDb.EntityIUserWeaponAbility.Add(new EntityIUserWeaponAbility { UserId = userId, UserWeaponUuid = uuid, SlotNumber = ag.SlotNumber, Level = 1 });
|
||||
userDb.EntityIUserWeaponAbility.Add(new EntityIUserWeaponAbility { UserId = userDb.UserId, UserWeaponUuid = uuid, SlotNumber = ag.SlotNumber, Level = 1 });
|
||||
|
||||
// Create one skill slot per entry in the weapon's skill group
|
||||
foreach (EntityMWeaponSkillGroup sg in masterDb.EntityMWeaponSkillGroup.Where(g => g.WeaponSkillGroupId == masterWeapon.WeaponSkillGroupId))
|
||||
userDb.EntityIUserWeaponSkill.Add(new EntityIUserWeaponSkill { UserId = userId, UserWeaponUuid = uuid, SlotNumber = sg.SlotNumber, Level = 1 });
|
||||
userDb.EntityIUserWeaponSkill.Add(new EntityIUserWeaponSkill { UserId = userDb.UserId, UserWeaponUuid = uuid, SlotNumber = sg.SlotNumber, Level = 1 });
|
||||
|
||||
// Unlock weapon stories for ACQUISITION condition
|
||||
if (masterWeapon.WeaponStoryReleaseConditionGroupId != 0)
|
||||
@@ -60,17 +60,17 @@ public static class WeaponHelper
|
||||
&& c.WeaponStoryReleaseConditionType == WeaponStoryReleaseConditionType.ACQUISITION
|
||||
&& c.ConditionValue == 0))
|
||||
{
|
||||
GrantWeaponStory(userDb, masterWeapon.WeaponId, condRow.StoryIndex, userId);
|
||||
GrantWeaponStory(userDb, masterWeapon.WeaponId, condRow.StoryIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Creates or updates a weapon story unlock record.</summary>
|
||||
public static void GrantWeaponStory(DarkUserMemoryDatabase userDb, int weaponId, int storyIndex, long userId)
|
||||
public static void GrantWeaponStory(DarkUserMemoryDatabase userDb, int weaponId, int storyIndex)
|
||||
{
|
||||
EntityIUserWeaponStory? existing = userDb.EntityIUserWeaponStory.FirstOrDefault(s => s.WeaponId == weaponId);
|
||||
if (existing == null)
|
||||
userDb.EntityIUserWeaponStory.Add(new EntityIUserWeaponStory { UserId = userId, WeaponId = weaponId, ReleasedMaxStoryIndex = storyIndex });
|
||||
userDb.EntityIUserWeaponStory.Add(new EntityIUserWeaponStory { UserId = userDb.UserId, WeaponId = weaponId, ReleasedMaxStoryIndex = storyIndex });
|
||||
else
|
||||
existing.ReleasedMaxStoryIndex = Math.Max(existing.ReleasedMaxStoryIndex, storyIndex);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class AutoSaveInterceptor(UserDataStore store, ILogger<AutoSaveIntercepto
|
||||
{
|
||||
string[] parts = context.Method.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||
string methodSuffix = parts.Length >= 2 ? $"{parts[^2]}_{parts[^1]}" : context.Method.TrimStart('/').Replace('/', '_');
|
||||
_ = Task.Run(() => SaveUser(userId, userDb, methodSuffix));
|
||||
_ = Task.Run(() => SaveUser(userDb, methodSuffix));
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -40,20 +40,20 @@ public class AutoSaveInterceptor(UserDataStore store, ILogger<AutoSaveIntercepto
|
||||
/// <summary>
|
||||
/// Serializes and writes a user's database to a timestamped JSON file.
|
||||
/// </summary>
|
||||
private void SaveUser(long userId, DarkUserMemoryDatabase userDb, string methodSuffix)
|
||||
private void SaveUser(DarkUserMemoryDatabase userDb, string methodSuffix)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(SavesDirectory);
|
||||
string timestamp = DateTime.UtcNow.ToString("yyyyMMdd_HHmmss");
|
||||
string filePath = Path.Combine(SavesDirectory, $"{userId}_{timestamp}_{methodSuffix}.json");
|
||||
string filePath = Path.Combine(SavesDirectory, $"{userDb.UserId}_{timestamp}_{methodSuffix}.json");
|
||||
string json = JsonSerializer.Serialize(userDb, JsonOptions);
|
||||
File.WriteAllText(filePath, json);
|
||||
//logger.LogDebug("Auto-saved user {UserId} to {FilePath}", userId, filePath);
|
||||
//logger.LogDebug("Auto-saved user {UserId} to {FilePath}", userDb.UserId, filePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "AutoSaveInterceptor failed to save user {UserId}", userId);
|
||||
logger.LogError(ex, "AutoSaveInterceptor failed to save user {UserId}", userDb.UserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,22 +30,22 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
|
||||
if (bhQuest is not null)
|
||||
{
|
||||
HandleBigHuntQuestStart(userDb, userId, bhQuest.QuestId, request.UserDeckNumber, nowMs);
|
||||
HandleBigHuntQuestStart(userDb, bhQuest.QuestId, request.UserDeckNumber, nowMs);
|
||||
}
|
||||
|
||||
// Set progress status
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb, userId);
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb);
|
||||
progress.CurrentBigHuntBossQuestId = request.BigHuntBossQuestId;
|
||||
progress.CurrentBigHuntQuestId = request.BigHuntQuestId;
|
||||
progress.CurrentQuestSceneId = 0;
|
||||
progress.IsDryRun = request.IsDryRun;
|
||||
|
||||
// Store deck number in server-side session
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb, userId);
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb);
|
||||
session.DeckNumber = request.UserDeckNumber;
|
||||
|
||||
// Update per-boss-quest status
|
||||
EntityIUserBigHuntStatus status = GetOrCreateStatus(userDb, userId, request.BigHuntBossQuestId);
|
||||
EntityIUserBigHuntStatus status = GetOrCreateStatus(userDb, request.BigHuntBossQuestId);
|
||||
status.DailyChallengeCount++;
|
||||
status.LatestChallengeDatetime = nowMs;
|
||||
|
||||
@@ -60,7 +60,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
long userId = context.GetUserId();
|
||||
DarkUserMemoryDatabase userDb = _store.GetOrCreate(userId);
|
||||
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb, userId);
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb);
|
||||
progress.CurrentQuestSceneId = request.QuestSceneId;
|
||||
|
||||
return Task.FromResult(new UpdateBigHuntQuestSceneProgressResponse());
|
||||
@@ -87,11 +87,11 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
|
||||
if (bhQuest is not null)
|
||||
{
|
||||
HandleBigHuntQuestFinish(userDb, userId, bhQuest.QuestId, request.IsRetired, nowMs);
|
||||
HandleBigHuntQuestFinish(userDb, bhQuest.QuestId, request.IsRetired, nowMs);
|
||||
}
|
||||
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb, userId);
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb, userId);
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb);
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb);
|
||||
|
||||
// Retired or dry run — clear progress and return empty score info.
|
||||
if (request.IsRetired || progress.IsDryRun)
|
||||
@@ -246,7 +246,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
List<(PossessionType Type, int Id, int Count)> newItems = CollectNewRewards(rewardGroupId, oldMaxScore, userScore);
|
||||
foreach ((PossessionType type, int id, int count) in newItems)
|
||||
{
|
||||
GrantPossessionViaPossessionHelper(userDb, userId, type, id, count);
|
||||
GrantPossessionViaPossessionHelper(userDb, type, id, count);
|
||||
scoreRewards.Add(new BigHuntReward
|
||||
{
|
||||
PossessionType = (int)type,
|
||||
@@ -289,23 +289,23 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
EntityMBigHuntQuest? bhQuest = _masterDb.EntityMBigHuntQuest
|
||||
.FirstOrDefault(q => q.BigHuntQuestId == request.BigHuntQuestId);
|
||||
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb, userId);
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb);
|
||||
|
||||
if (bhQuest is not null)
|
||||
{
|
||||
HandleBigHuntQuestStart(userDb, userId, bhQuest.QuestId, session.DeckNumber, nowMs);
|
||||
HandleBigHuntQuestStart(userDb, bhQuest.QuestId, session.DeckNumber, nowMs);
|
||||
}
|
||||
|
||||
// Reset scene progress
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb, userId);
|
||||
EntityIUserBigHuntProgressStatus progress = GetOrCreateProgress(userDb);
|
||||
progress.CurrentQuestSceneId = 0;
|
||||
|
||||
// Increment daily challenge count
|
||||
EntityIUserBigHuntStatus status = GetOrCreateStatus(userDb, userId, request.BigHuntBossQuestId);
|
||||
EntityIUserBigHuntStatus status = GetOrCreateStatus(userDb, request.BigHuntBossQuestId);
|
||||
status.DailyChallengeCount++;
|
||||
status.LatestChallengeDatetime = nowMs;
|
||||
|
||||
RestartBigHuntQuestResponse response = new()
|
||||
RestartBigHuntQuestResponse response= new()
|
||||
{
|
||||
BattleBinary = Google.Protobuf.ByteString.CopyFrom(session.BattleBinary),
|
||||
DeckNumber = session.DeckNumber
|
||||
@@ -324,7 +324,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
DarkUserMemoryDatabase userDb = _store.GetOrCreate(userId);
|
||||
long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
EntityIUserBigHuntStatus status = GetOrCreateStatus(userDb, userId, request.BigHuntBossQuestId);
|
||||
EntityIUserBigHuntStatus status = GetOrCreateStatus(userDb, request.BigHuntBossQuestId);
|
||||
status.DailyChallengeCount += request.SkipCount;
|
||||
status.LatestChallengeDatetime = nowMs;
|
||||
|
||||
@@ -343,8 +343,8 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
long userId = context.GetUserId();
|
||||
DarkUserMemoryDatabase userDb = _store.GetOrCreate(userId);
|
||||
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb, userId);
|
||||
session.BattleBinary = request.BattleBinary.ToByteArray();
|
||||
EntitySBigHuntSession session = GetOrCreateSession(userDb);
|
||||
session.BattleBinary= request.BattleBinary.ToByteArray();
|
||||
|
||||
if (request.BigHuntBattleDetail is not null)
|
||||
{
|
||||
@@ -412,11 +412,11 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
.FirstOrDefault(s => s.BigHuntWeeklyVersion == weeklyVersion);
|
||||
|
||||
// Resolve current week rewards
|
||||
List<BigHuntReward> weeklyRewards = ResolveWeeklyRewards(userDb, userId, weeklyVersion, nowMs);
|
||||
List<BigHuntReward> weeklyRewards = ResolveWeeklyRewards(userDb, weeklyVersion, nowMs);
|
||||
|
||||
// Resolve last week rewards
|
||||
long lastWeekVersion = weeklyVersion - (7L * 24 * 60 * 60 * 1000);
|
||||
List<BigHuntReward> lastWeekRewards = ResolveWeeklyRewards(userDb, userId, lastWeekVersion, nowMs);
|
||||
List<BigHuntReward> lastWeekRewards = ResolveWeeklyRewards(userDb, lastWeekVersion, nowMs);
|
||||
|
||||
GetBigHuntTopDataResponse response = new()
|
||||
{
|
||||
@@ -434,13 +434,13 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
/// <summary>
|
||||
/// Initializes quest and mission state for the underlying quest, and transitions its state to active.
|
||||
/// </summary>
|
||||
private void HandleBigHuntQuestStart(DarkUserMemoryDatabase userDb, long userId, int questId, int deckNumber, long nowMs)
|
||||
private void HandleBigHuntQuestStart(DarkUserMemoryDatabase userDb, int questId, int deckNumber, long nowMs)
|
||||
{
|
||||
EntityMQuest? masterQuest = _masterDb.EntityMQuest.FirstOrDefault(q => q.QuestId == questId);
|
||||
|
||||
EntityIUserQuest userQuest = userDb.EntityIUserQuest
|
||||
.FirstOrDefault(q => q.QuestId == questId)
|
||||
?? AddEntity(userDb.EntityIUserQuest, new EntityIUserQuest { UserId = userId, QuestId = questId });
|
||||
?? AddEntity(userDb.EntityIUserQuest, new EntityIUserQuest { UserId = userDb.UserId, QuestId = questId });
|
||||
|
||||
// Initialize quest missions
|
||||
if (masterQuest is not null && masterQuest.QuestMissionGroupId != 0)
|
||||
@@ -449,7 +449,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
.Where(g => g.QuestMissionGroupId == masterQuest.QuestMissionGroupId))
|
||||
{
|
||||
if (!userDb.EntityIUserQuestMission.Any(m => m.QuestId == questId && m.QuestMissionId == missionGroupRow.QuestMissionId))
|
||||
userDb.EntityIUserQuestMission.Add(new EntityIUserQuestMission { UserId = userId, QuestId = questId, QuestMissionId = missionGroupRow.QuestMissionId });
|
||||
userDb.EntityIUserQuestMission.Add(new EntityIUserQuestMission { UserId = userDb.UserId, QuestId = questId, QuestMissionId = missionGroupRow.QuestMissionId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
/// Marks the quest cleared, applies first-clear and drop rewards on success,
|
||||
/// and clears quest missions.
|
||||
/// </summary>
|
||||
private void HandleBigHuntQuestFinish(DarkUserMemoryDatabase userDb, long userId, int questId, bool isRetired, long nowMs)
|
||||
private void HandleBigHuntQuestFinish(DarkUserMemoryDatabase userDb, int questId, bool isRetired, long nowMs)
|
||||
{
|
||||
EntityMQuest? masterQuest = _masterDb.EntityMQuest.FirstOrDefault(q => q.QuestId == questId);
|
||||
EntityIUserQuest? userQuest = userDb.EntityIUserQuest
|
||||
@@ -486,7 +486,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
foreach (EntityMQuestFirstClearRewardGroup reward in _masterDb.EntityMQuestFirstClearRewardGroup
|
||||
.Where(r => r.QuestFirstClearRewardGroupId == rewardGroupId))
|
||||
{
|
||||
PossessionHelper.Apply(userDb, userId, reward.PossessionType, reward.PossessionId, reward.Count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, reward.PossessionType, reward.PossessionId, reward.Count, _masterDb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
EntityMBattleDropReward? drop = _masterDb.EntityMBattleDropReward
|
||||
.FirstOrDefault(d => d.BattleDropRewardId == pickup.BattleDropRewardId);
|
||||
if (drop != null)
|
||||
PossessionHelper.Apply(userDb, userId, drop.PossessionType, drop.PossessionId, drop.Count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, drop.PossessionType, drop.PossessionId, drop.Count, _masterDb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
.FirstOrDefault(m => m.QuestId == questId && m.QuestMissionId == missionGroupRow.QuestMissionId);
|
||||
if (userMission is null)
|
||||
{
|
||||
userMission = new EntityIUserQuestMission { UserId = userId, QuestId = questId, QuestMissionId = missionGroupRow.QuestMissionId };
|
||||
userMission = new EntityIUserQuestMission { UserId = userDb.UserId, QuestId = questId, QuestMissionId = missionGroupRow.QuestMissionId };
|
||||
userDb.EntityIUserQuestMission.Add(userMission);
|
||||
}
|
||||
userMission.IsClear = true;
|
||||
@@ -656,7 +656,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
/// Builds the list of weekly reward items earned across all boss attributes for a given week version,
|
||||
/// based on the player's weekly max scores.
|
||||
/// </summary>
|
||||
private List<BigHuntReward> ResolveWeeklyRewards(DarkUserMemoryDatabase userDb, long userId, long weeklyVersion, long nowMs)
|
||||
private List<BigHuntReward> ResolveWeeklyRewards(DarkUserMemoryDatabase userDb, long weeklyVersion, long nowMs)
|
||||
{
|
||||
List<BigHuntReward> rewards = [];
|
||||
|
||||
@@ -669,7 +669,7 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
}
|
||||
|
||||
EntityIUserBigHuntWeeklyMaxScore? ws = userDb.EntityIUserBigHuntWeeklyMaxScore
|
||||
.FirstOrDefault(m => m.UserId == userId
|
||||
.FirstOrDefault(m => m.UserId == userDb.UserId
|
||||
&& m.BigHuntWeeklyVersion == weeklyVersion
|
||||
&& m.AttributeType == boss.AttributeType);
|
||||
|
||||
@@ -694,23 +694,23 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
/// <summary>
|
||||
/// Gets or initialises the player's BigHunt in-progress quest status record.
|
||||
/// </summary>
|
||||
private static EntityIUserBigHuntProgressStatus GetOrCreateProgress(DarkUserMemoryDatabase userDb, long userId)
|
||||
private static EntityIUserBigHuntProgressStatus GetOrCreateProgress(DarkUserMemoryDatabase userDb)
|
||||
{
|
||||
return userDb.EntityIUserBigHuntProgressStatus
|
||||
.FirstOrDefault(p => p.UserId == userId)
|
||||
?? AddEntity(userDb.EntityIUserBigHuntProgressStatus, new EntityIUserBigHuntProgressStatus { UserId = userId });
|
||||
.FirstOrDefault(p => p.UserId == userDb.UserId)
|
||||
?? AddEntity(userDb.EntityIUserBigHuntProgressStatus, new EntityIUserBigHuntProgressStatus { UserId = userDb.UserId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or initialises the player's per-boss-quest challenge status record.
|
||||
/// </summary>
|
||||
private static EntityIUserBigHuntStatus GetOrCreateStatus(DarkUserMemoryDatabase userDb, long userId, int bossQuestId)
|
||||
private static EntityIUserBigHuntStatus GetOrCreateStatus(DarkUserMemoryDatabase userDb, int bossQuestId)
|
||||
{
|
||||
return userDb.EntityIUserBigHuntStatus
|
||||
.FirstOrDefault(s => s.BigHuntBossQuestId == bossQuestId)
|
||||
?? AddEntity(userDb.EntityIUserBigHuntStatus, new EntityIUserBigHuntStatus
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
BigHuntBossQuestId = bossQuestId
|
||||
});
|
||||
}
|
||||
@@ -718,11 +718,11 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
/// <summary>
|
||||
/// Gets or initialises the player's server-side battle session record.
|
||||
/// </summary>
|
||||
private static EntitySBigHuntSession GetOrCreateSession(DarkUserMemoryDatabase userDb, long userId)
|
||||
private static EntitySBigHuntSession GetOrCreateSession(DarkUserMemoryDatabase userDb)
|
||||
{
|
||||
return userDb.EntitySBigHuntSession
|
||||
.FirstOrDefault(s => s.UserId == userId)
|
||||
?? AddEntity(userDb.EntitySBigHuntSession, new EntitySBigHuntSession { UserId = userId });
|
||||
.FirstOrDefault(s => s.UserId == userDb.UserId)
|
||||
?? AddEntity(userDb.EntitySBigHuntSession, new EntitySBigHuntSession { UserId = userDb.UserId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -741,9 +741,9 @@ public class BigHuntService(UserDataStore store, DarkMasterMemoryDatabase master
|
||||
/// <summary>
|
||||
/// Routes possession grants through PossessionHelper.Apply for consistent handling.
|
||||
/// </summary>
|
||||
private void GrantPossessionViaPossessionHelper(DarkUserMemoryDatabase userDb, long userId, PossessionType possessionType, int possessionId, int count)
|
||||
private void GrantPossessionViaPossessionHelper(DarkUserMemoryDatabase userDb, PossessionType possessionType, int possessionId, int count)
|
||||
{
|
||||
PossessionHelper.Apply(userDb, userId, possessionType, possessionId, count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, possessionType, possessionId, count, _masterDb);
|
||||
}
|
||||
|
||||
// ────────── Time helpers ──────────
|
||||
|
||||
@@ -53,7 +53,7 @@ public class CageOrnamentService(UserDataStore store, DarkMasterMemoryDatabase m
|
||||
});
|
||||
}
|
||||
|
||||
PossessionHelper.Apply(userDb, userId, reward.PossessionType, reward.PossessionId, reward.Count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, reward.PossessionType, reward.PossessionId, reward.Count, _masterDb);
|
||||
|
||||
ReceiveRewardResponse response = new();
|
||||
response.CageOrnamentReward.Add(new CageOrnamentReward
|
||||
|
||||
@@ -37,8 +37,8 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
}
|
||||
|
||||
ConsumeCosts(userDb, panel);
|
||||
SetReleaseBit(userDb, userId, panel);
|
||||
ApplyEffects(userDb, userId, panel);
|
||||
SetReleaseBit(userDb, panel);
|
||||
ApplyEffects(userDb, panel);
|
||||
}
|
||||
|
||||
return Task.FromResult(new ReleasePanelResponse());
|
||||
@@ -129,7 +129,7 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
}
|
||||
|
||||
/// <summary>Sets the release bit for a panel on the user's character board, using bitfield-packed storage (32 panels per field).</summary>
|
||||
private static void SetReleaseBit(DarkUserMemoryDatabase userDb, long userId, EntityMCharacterBoardPanel panel)
|
||||
private static void SetReleaseBit(DarkUserMemoryDatabase userDb, EntityMCharacterBoardPanel panel)
|
||||
{
|
||||
int boardId = panel.CharacterBoardId;
|
||||
|
||||
@@ -147,7 +147,7 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
{
|
||||
board = new EntityIUserCharacterBoard
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
CharacterBoardId = boardId
|
||||
};
|
||||
userDb.EntityIUserCharacterBoard.Add(board);
|
||||
@@ -175,7 +175,7 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
}
|
||||
|
||||
/// <summary>Applies the panel's release effects (ability unlocks or stat boosts) to the character.</summary>
|
||||
private void ApplyEffects(DarkUserMemoryDatabase userDb, long userId, EntityMCharacterBoardPanel panel)
|
||||
private void ApplyEffects(DarkUserMemoryDatabase userDb, EntityMCharacterBoardPanel panel)
|
||||
{
|
||||
foreach (EntityMCharacterBoardPanelReleaseEffectGroup eff in _masterDb.EntityMCharacterBoardPanelReleaseEffectGroup)
|
||||
{
|
||||
@@ -187,17 +187,17 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
switch (eff.CharacterBoardEffectType)
|
||||
{
|
||||
case CharacterBoardEffectType.ABILITY:
|
||||
ApplyAbilityEffect(userDb, userId, eff);
|
||||
ApplyAbilityEffect(userDb, eff);
|
||||
break;
|
||||
case CharacterBoardEffectType.STATUS_UP:
|
||||
ApplyStatusUpEffect(userDb, userId, eff);
|
||||
ApplyStatusUpEffect(userDb, eff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Grants or levels up a character ability from a board panel release, capped by the master-defined max level.</summary>
|
||||
private void ApplyAbilityEffect(DarkUserMemoryDatabase userDb, long userId, EntityMCharacterBoardPanelReleaseEffectGroup eff)
|
||||
private void ApplyAbilityEffect(DarkUserMemoryDatabase userDb, EntityMCharacterBoardPanelReleaseEffectGroup eff)
|
||||
{
|
||||
EntityMCharacterBoardAbility? ability = null;
|
||||
foreach (EntityMCharacterBoardAbility a in _masterDb.EntityMCharacterBoardAbility)
|
||||
@@ -235,7 +235,7 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
{
|
||||
state = new EntityIUserCharacterBoardAbility
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
CharacterId = characterId,
|
||||
AbilityId = ability.AbilityId,
|
||||
Level = 0
|
||||
@@ -260,7 +260,7 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
}
|
||||
|
||||
/// <summary>Applies a stat increase (HP, ATK, AGI, VIT, CRIT) to a character from a board panel release.</summary>
|
||||
private void ApplyStatusUpEffect(DarkUserMemoryDatabase userDb, long userId, EntityMCharacterBoardPanelReleaseEffectGroup eff)
|
||||
private void ApplyStatusUpEffect(DarkUserMemoryDatabase userDb, EntityMCharacterBoardPanelReleaseEffectGroup eff)
|
||||
{
|
||||
EntityMCharacterBoardStatusUp? statusUp = null;
|
||||
foreach (EntityMCharacterBoardStatusUp s in _masterDb.EntityMCharacterBoardStatusUp)
|
||||
@@ -300,7 +300,7 @@ public class CharacterBoardService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
{
|
||||
state = new EntityIUserCharacterBoardStatusUp
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
CharacterId = characterId,
|
||||
StatusCalculationType = calcType
|
||||
};
|
||||
|
||||
@@ -70,14 +70,14 @@ public class ConsumableItemService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
|
||||
if (totalGold > 0)
|
||||
{
|
||||
AddGold(userDb, userId, totalGold);
|
||||
AddGold(userDb, totalGold);
|
||||
}
|
||||
|
||||
return Task.FromResult(new SellResponse());
|
||||
}
|
||||
|
||||
/// <summary>Adds gold (consumable item ID 1) to the user's inventory, creating the entry if needed.</summary>
|
||||
private void AddGold(DarkUserMemoryDatabase userDb, long userId, int amount)
|
||||
private void AddGold(DarkUserMemoryDatabase userDb, int amount)
|
||||
{
|
||||
foreach (EntityIUserConsumableItem ci in userDb.EntityIUserConsumableItem)
|
||||
{
|
||||
@@ -90,7 +90,7 @@ public class ConsumableItemService(DarkMasterMemoryDatabase masterDb, UserDataSt
|
||||
|
||||
userDb.EntityIUserConsumableItem.Add(new EntityIUserConsumableItem
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
ConsumableItemId = _gameConfig.ConsumableItemIdForGold,
|
||||
Count = amount,
|
||||
FirstAcquisitionDatetime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
|
||||
@@ -461,12 +461,12 @@ public class CostumeService(DarkMasterMemoryDatabase masterDb, UserDataStore sto
|
||||
switch (effect.CostumeAwakenEffectType)
|
||||
{
|
||||
case CostumeAwakenEffectType.STATUS_UP:
|
||||
ApplyAwakenStatusUp(userDb, userId, request.UserCostumeUuid, effect.CostumeAwakenEffectId);
|
||||
ApplyAwakenStatusUp(userDb, request.UserCostumeUuid, effect.CostumeAwakenEffectId);
|
||||
break;
|
||||
case CostumeAwakenEffectType.ABILITY:
|
||||
break;
|
||||
case CostumeAwakenEffectType.ITEM_ACQUIRE:
|
||||
ApplyAwakenItemAcquire(userDb, userId, effect.CostumeAwakenEffectId);
|
||||
ApplyAwakenItemAcquire(userDb, effect.CostumeAwakenEffectId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -668,7 +668,7 @@ public class CostumeService(DarkMasterMemoryDatabase masterDb, UserDataStore sto
|
||||
/// <summary>
|
||||
/// Applies awakening stat bonuses (HP, ATK, VIT, AGI, CRIT, etc.) to the costume's awaken status record.
|
||||
/// </summary>
|
||||
private void ApplyAwakenStatusUp(DarkUserMemoryDatabase userDb, long userId, string userCostumeUuid, int statusUpGroupId)
|
||||
private void ApplyAwakenStatusUp(DarkUserMemoryDatabase userDb, string userCostumeUuid, int statusUpGroupId)
|
||||
{
|
||||
foreach (EntityMCostumeAwakenStatusUpGroup row in _masterDb.EntityMCostumeAwakenStatusUpGroup)
|
||||
{
|
||||
@@ -691,7 +691,7 @@ public class CostumeService(DarkMasterMemoryDatabase masterDb, UserDataStore sto
|
||||
{
|
||||
state = new EntityIUserCostumeAwakenStatusUp
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
UserCostumeUuid = userCostumeUuid,
|
||||
StatusCalculationType = row.StatusCalculationType,
|
||||
};
|
||||
@@ -728,7 +728,7 @@ public class CostumeService(DarkMasterMemoryDatabase masterDb, UserDataStore sto
|
||||
/// <summary>
|
||||
/// Grants a thought item as an awakening reward, creating a new inventory entry if not already owned.
|
||||
/// </summary>
|
||||
private void ApplyAwakenItemAcquire(DarkUserMemoryDatabase userDb, long userId, int itemAcquireId)
|
||||
private void ApplyAwakenItemAcquire(DarkUserMemoryDatabase userDb, int itemAcquireId)
|
||||
{
|
||||
EntityMCostumeAwakenItemAcquire? acq = null;
|
||||
foreach (EntityMCostumeAwakenItemAcquire a in _masterDb.EntityMCostumeAwakenItemAcquire)
|
||||
@@ -756,7 +756,7 @@ public class CostumeService(DarkMasterMemoryDatabase masterDb, UserDataStore sto
|
||||
|
||||
userDb.EntityIUserThought.Add(new EntityIUserThought
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
UserThoughtUuid = uuid,
|
||||
ThoughtId = acq.PossessionId,
|
||||
AcquisitionDatetime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
|
||||
|
||||
@@ -34,14 +34,14 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
|
||||
if (request.Deck != null)
|
||||
{
|
||||
ApplyDeckReplacement(userDb, userId, (DeckType)request.DeckType, request.UserDeckNumber, request.Deck);
|
||||
ApplyDeckReplacement(userDb, (DeckType)request.DeckType, request.UserDeckNumber, request.Deck);
|
||||
}
|
||||
|
||||
return Task.FromResult(new ReplaceDeckResponse());
|
||||
}
|
||||
|
||||
/// <summary>Creates a deck character record from a DeckCharacter slot proto and returns the new UUID.</summary>
|
||||
private static string CreateDeckCharacter(DarkUserMemoryDatabase db, long userId, DeckCharacter? slot)
|
||||
private static string CreateDeckCharacter(DarkUserMemoryDatabase db, DeckCharacter? slot)
|
||||
{
|
||||
if (slot is null || string.IsNullOrEmpty(slot.UserCostumeUuid))
|
||||
{
|
||||
@@ -51,7 +51,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
string newUuid = Guid.NewGuid().ToString();
|
||||
db.EntityIUserDeckCharacter.Add(new EntityIUserDeckCharacter
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
UserCostumeUuid = slot.UserCostumeUuid,
|
||||
MainUserWeaponUuid = slot.MainUserWeaponUuid,
|
||||
@@ -64,7 +64,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
{
|
||||
db.EntityIUserDeckCharacterDressupCostume.Add(new EntityIUserDeckCharacterDressupCostume
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
DressupCostumeId = slot.DressupCostumeId
|
||||
});
|
||||
@@ -75,7 +75,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
if (string.IsNullOrEmpty(slot.UserPartsUuid[i])) { continue; }
|
||||
db.EntityIUserDeckPartsGroup.Add(new EntityIUserDeckPartsGroup
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
UserPartsUuid = slot.UserPartsUuid[i],
|
||||
SortOrder = i + 1
|
||||
@@ -87,7 +87,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
if (string.IsNullOrEmpty(slot.SubUserWeaponUuid[i])) { continue; }
|
||||
db.EntityIUserDeckSubWeaponGroup.Add(new EntityIUserDeckSubWeaponGroup
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
UserWeaponUuid = slot.SubUserWeaponUuid[i],
|
||||
SortOrder = i + 1
|
||||
@@ -123,7 +123,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
|
||||
if (request.DeckPower != null)
|
||||
{
|
||||
ApplyDeckPowerRefresh(userDb, userId, (DeckType)request.DeckType, request.UserDeckNumber, request.DeckPower);
|
||||
ApplyDeckPowerRefresh(userDb, (DeckType)request.DeckType, request.UserDeckNumber, request.DeckPower);
|
||||
}
|
||||
|
||||
return Task.FromResult(new RefreshDeckPowerResponse());
|
||||
@@ -148,7 +148,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
continue;
|
||||
}
|
||||
|
||||
ApplyDeckReplacement(userDb, userId, (DeckType)detail.DeckType, detail.UserDeckNumber, detail.Deck);
|
||||
ApplyDeckReplacement(userDb, (DeckType)detail.DeckType, detail.UserDeckNumber, detail.Deck);
|
||||
}
|
||||
|
||||
return Task.FromResult(new ReplaceTripleDeckResponse());
|
||||
@@ -167,7 +167,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
continue;
|
||||
}
|
||||
|
||||
ApplyDeckReplacement(userDb, userId, (DeckType)detail.DeckType, detail.UserDeckNumber, detail.Deck);
|
||||
ApplyDeckReplacement(userDb, (DeckType)detail.DeckType, detail.UserDeckNumber, detail.Deck);
|
||||
}
|
||||
|
||||
return Task.FromResult(new ReplaceMultiDeckResponse());
|
||||
@@ -186,14 +186,14 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
continue;
|
||||
}
|
||||
|
||||
ApplyDeckPowerRefresh(userDb, userId, (DeckType)info.DeckType, info.UserDeckNumber, info.DeckPower);
|
||||
ApplyDeckPowerRefresh(userDb, (DeckType)info.DeckType, info.UserDeckNumber, info.DeckPower);
|
||||
}
|
||||
|
||||
return Task.FromResult(new RefreshMultiDeckPowerResponse());
|
||||
}
|
||||
|
||||
/// <summary>Removes old deck characters and creates new ones from the provided deck proto.</summary>
|
||||
private static void ApplyDeckReplacement(DarkUserMemoryDatabase userDb, long userId, DeckType deckType, int deckNumber, Deck deck)
|
||||
private static void ApplyDeckReplacement(DarkUserMemoryDatabase userDb, DeckType deckType, int deckNumber, Deck deck)
|
||||
{
|
||||
EntityIUserDeck? existing = userDb.EntityIUserDeck
|
||||
.FirstOrDefault(d => d.DeckType == deckType && d.UserDeckNumber == deckNumber);
|
||||
@@ -210,15 +210,15 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
userDb.EntityIUserDeckSubWeaponGroup.RemoveAll(swg => oldUuids.Contains(swg.UserDeckCharacterUuid));
|
||||
}
|
||||
|
||||
string uuid01 = CreateDeckCharacter(userDb, userId, deck.Character01);
|
||||
string uuid02 = CreateDeckCharacter(userDb, userId, deck.Character02);
|
||||
string uuid03 = CreateDeckCharacter(userDb, userId, deck.Character03);
|
||||
string uuid01 = CreateDeckCharacter(userDb, deck.Character01);
|
||||
string uuid02 = CreateDeckCharacter(userDb, deck.Character02);
|
||||
string uuid03 = CreateDeckCharacter(userDb, deck.Character03);
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
existing = new EntityIUserDeck
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
DeckType = deckType,
|
||||
UserDeckNumber = deckNumber,
|
||||
Name = $"Loadout {deckNumber}",
|
||||
@@ -233,7 +233,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
}
|
||||
|
||||
/// <summary>Updates deck and character power values and tracks max deck power per type.</summary>
|
||||
private static void ApplyDeckPowerRefresh(DarkUserMemoryDatabase userDb, long userId, DeckType deckType, int deckNumber, DeckPower deckPower)
|
||||
private static void ApplyDeckPowerRefresh(DarkUserMemoryDatabase userDb, DeckType deckType, int deckNumber, DeckPower deckPower)
|
||||
{
|
||||
EntityIUserDeck? deck = userDb.EntityIUserDeck.FirstOrDefault(d =>
|
||||
d.DeckType == deckType && d.UserDeckNumber == deckNumber);
|
||||
@@ -271,7 +271,7 @@ public class DeckService(UserDataStore store) : MariesWonderland.Proto.Deck.Deck
|
||||
|
||||
if (note == null)
|
||||
{
|
||||
note = new EntityIUserDeckTypeNote { UserId = userId, DeckType = deckType };
|
||||
note = new EntityIUserDeckTypeNote { UserId = userDb.UserId, DeckType = deckType };
|
||||
userDb.EntityIUserDeckTypeNote.Add(note);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
int conversionRate = entry.Medal.ConversionRate > 0 ? entry.Medal.ConversionRate : 1;
|
||||
int bookmarkCount = bs.MedalCount * conversionRate;
|
||||
|
||||
PossessionHelper.Apply(userDb, userId, PossessionType.CONSUMABLE_ITEM, entry.Medal.ConsumableItemId, bookmarkCount, _masterDb);
|
||||
PossessionHelper.Apply(userDb, PossessionType.CONSUMABLE_ITEM, entry.Medal.ConsumableItemId, bookmarkCount, _masterDb);
|
||||
|
||||
convertedMedal.ConvertedMedalPossession.Add(new ConsumableItemPossession
|
||||
{
|
||||
@@ -162,7 +162,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
}
|
||||
|
||||
// Find or create banner state
|
||||
EntitySGachaBannerState bannerState = GetOrCreateBannerState(userDb, userId, entry.GachaId);
|
||||
EntitySGachaBannerState bannerState = GetOrCreateBannerState(userDb, entry.GachaId);
|
||||
|
||||
// Draw items based on label type
|
||||
List<DrawnItem> drawnItems;
|
||||
@@ -221,7 +221,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
if (isMaterialDraw)
|
||||
{
|
||||
// Material draws: grant material and build simple result
|
||||
PossessionHelper.Apply(userDb, userId, (PossessionType)item.PossessionType, item.PossessionId, 1, _masterDb);
|
||||
PossessionHelper.Apply(userDb, (PossessionType)item.PossessionType, item.PossessionId, 1, _masterDb);
|
||||
bool isNew = !IsOwnedByType(item.PossessionType, item.PossessionId, ownedCostumeIds, ownedWeaponIds, userDb);
|
||||
|
||||
gachaResults.Add(new DrawGachaOddsItem
|
||||
@@ -259,14 +259,14 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
}
|
||||
else
|
||||
{
|
||||
PossessionHelper.GrantCostume(userDb, userId, item.PossessionId, _masterDb);
|
||||
PossessionHelper.GrantCostume(userDb, item.PossessionId, _masterDb);
|
||||
ownedCostumeIds.Add(item.PossessionId);
|
||||
|
||||
// Bonus weapon via costume->weapon pairing map
|
||||
GachaItem bonusGachaItem = new();
|
||||
if (costumeWeaponMap.TryGetValue(item.PossessionId, out int pairedWeaponId) && pairedWeaponId > 0)
|
||||
{
|
||||
WeaponHelper.GrantWeapon(userDb, userId, pairedWeaponId, _masterDb);
|
||||
WeaponHelper.GrantWeapon(userDb, pairedWeaponId, _masterDb);
|
||||
bonusGachaItem = new GachaItem
|
||||
{
|
||||
PossessionType = (int)PossessionType.WEAPON,
|
||||
@@ -294,7 +294,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
{
|
||||
// Weapon
|
||||
bool isNew = !ownedWeaponIds.Contains(item.PossessionId);
|
||||
WeaponHelper.GrantWeapon(userDb, userId, item.PossessionId, _masterDb);
|
||||
WeaponHelper.GrantWeapon(userDb, item.PossessionId, _masterDb);
|
||||
ownedWeaponIds.Add(item.PossessionId);
|
||||
|
||||
gachaResults.Add(new DrawGachaOddsItem
|
||||
@@ -325,7 +325,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
// Grant medal consumable items (1 per draw)
|
||||
if (entry.Medal != null && medalBonus > 0)
|
||||
{
|
||||
PossessionHelper.Apply(userDb, userId, PossessionType.CONSUMABLE_ITEM, entry.Medal.ConsumableItemId, medalBonus, _masterDb);
|
||||
PossessionHelper.Apply(userDb, PossessionType.CONSUMABLE_ITEM, entry.Medal.ConsumableItemId, medalBonus, _masterDb);
|
||||
}
|
||||
|
||||
DrawResponse response = new()
|
||||
@@ -361,7 +361,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
return Task.FromResult(new ResetBoxGachaResponse());
|
||||
}
|
||||
|
||||
EntitySGachaBannerState bannerState = GetOrCreateBannerState(userDb, userId, request.GachaId);
|
||||
EntitySGachaBannerState bannerState = GetOrCreateBannerState(userDb, request.GachaId);
|
||||
bannerState.BoxDrewCounts = [];
|
||||
bannerState.BoxNumber++;
|
||||
|
||||
@@ -459,7 +459,7 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
{
|
||||
EntityMMaterial mat = materials[Random.Shared.Next(materials.Count)];
|
||||
drawnItems.Add(((int)PossessionType.MATERIAL, mat.MaterialId));
|
||||
PossessionHelper.Apply(userDb, userId, PossessionType.MATERIAL, mat.MaterialId, 1, _masterDb);
|
||||
PossessionHelper.Apply(userDb, PossessionType.MATERIAL, mat.MaterialId, 1, _masterDb);
|
||||
}
|
||||
|
||||
int newCount = currentCount + drawCount;
|
||||
@@ -1248,14 +1248,14 @@ public class GachaService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
return null;
|
||||
}
|
||||
|
||||
private static EntitySGachaBannerState GetOrCreateBannerState(DarkUserMemoryDatabase userDb, long userId, int gachaId)
|
||||
private static EntitySGachaBannerState GetOrCreateBannerState(DarkUserMemoryDatabase userDb, int gachaId)
|
||||
{
|
||||
EntitySGachaBannerState? bs = FindBannerState(userDb, gachaId);
|
||||
if (bs != null) return bs;
|
||||
|
||||
bs = new EntitySGachaBannerState
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
GachaId = gachaId,
|
||||
BoxNumber = 1,
|
||||
StepNumber = 1
|
||||
|
||||
@@ -83,7 +83,7 @@ public class PartsService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
// Award total gold earned from the sale
|
||||
if (totalGold > 0)
|
||||
{
|
||||
AddGold(userDb, userId, totalGold);
|
||||
AddGold(userDb, totalGold);
|
||||
}
|
||||
|
||||
return Task.FromResult(new SellResponse());
|
||||
@@ -452,7 +452,7 @@ public class PartsService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
/// <summary>
|
||||
/// Credits gold to the user's consumable inventory, creating the inventory entry if one does not yet exist.
|
||||
/// </summary>
|
||||
private void AddGold(DarkUserMemoryDatabase userDb, long userId, int amount)
|
||||
private void AddGold(DarkUserMemoryDatabase userDb, int amount)
|
||||
{
|
||||
EntityIUserConsumableItem? gold = null;
|
||||
foreach (EntityIUserConsumableItem ci in userDb.EntityIUserConsumableItem)
|
||||
@@ -472,7 +472,7 @@ public class PartsService(DarkMasterMemoryDatabase masterDb, UserDataStore store
|
||||
{
|
||||
userDb.EntityIUserConsumableItem.Add(new EntityIUserConsumableItem
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
ConsumableItemId = _gameConfig.ConsumableItemIdForGold,
|
||||
Count = amount,
|
||||
FirstAcquisitionDatetime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
|
||||
@@ -66,7 +66,7 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
EntityIUserPortalCageStatus portalCageStatus = userDb.EntityIUserPortalCageStatus.GetOrCreate(userId);
|
||||
portalCageStatus.IsCurrentProgress = false;
|
||||
|
||||
ApplySceneGrants(userDb, questSceneId, userId);
|
||||
ApplySceneGrants(userDb, questSceneId);
|
||||
|
||||
return Task.FromResult(new UpdateMainFlowSceneProgressResponse());
|
||||
}
|
||||
@@ -156,12 +156,12 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
if (IsSceneAhead(questSceneId, progressStatus.HeadQuestSceneId))
|
||||
progressStatus.HeadQuestSceneId = questSceneId;
|
||||
|
||||
ApplySceneGrants(userDb, questSceneId, userId);
|
||||
ApplySceneGrants(userDb, questSceneId);
|
||||
|
||||
EntityMQuestScene? scene = _masterDb.EntityMQuestScene.FirstOrDefault(s => s.QuestSceneId == questSceneId);
|
||||
if (scene != null && scene.QuestResultType == QuestResultType.HALF_RESULT)
|
||||
{
|
||||
ClearQuestMissions(userDb, scene.QuestId, userId, nowMs);
|
||||
ClearQuestMissions(userDb, scene.QuestId, nowMs);
|
||||
}
|
||||
|
||||
return Task.FromResult(new UpdateExtraQuestSceneProgressResponse());
|
||||
@@ -181,12 +181,12 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
if (IsSceneAhead(questSceneId, progressStatus.HeadQuestSceneId))
|
||||
progressStatus.HeadQuestSceneId = questSceneId;
|
||||
|
||||
ApplySceneGrants(userDb, questSceneId, userId);
|
||||
ApplySceneGrants(userDb, questSceneId);
|
||||
|
||||
EntityMQuestScene? scene = _masterDb.EntityMQuestScene.FirstOrDefault(s => s.QuestSceneId == questSceneId);
|
||||
if (scene != null && scene.QuestResultType == QuestResultType.HALF_RESULT)
|
||||
{
|
||||
ClearQuestMissions(userDb, scene.QuestId, userId, nowMs);
|
||||
ClearQuestMissions(userDb, scene.QuestId, nowMs);
|
||||
}
|
||||
|
||||
return Task.FromResult(new UpdateEventQuestSceneProgressResponse());
|
||||
@@ -505,14 +505,14 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
{
|
||||
if (isFirstClear)
|
||||
{
|
||||
ApplyExpRewards(userDb, quest, userId, questId);
|
||||
ApplyGoldReward(userDb, quest, userId, nowMs);
|
||||
ApplyFirstClearPossessions(userDb, firstClearRewardRows, userId, _masterDb);
|
||||
ApplyWeaponStoryUnlocks(userDb, questId, userId);
|
||||
ApplyExpRewards(userDb, quest, questId);
|
||||
ApplyGoldReward(userDb, quest, nowMs);
|
||||
ApplyFirstClearPossessions(userDb, firstClearRewardRows, _masterDb);
|
||||
ApplyWeaponStoryUnlocks(userDb, questId);
|
||||
}
|
||||
|
||||
ApplyDropRewardPossessions(userDb, dropRewards, userId, _masterDb);
|
||||
ApplyDropRewardPossessions(userDb, replayFlowFirstClearRewards, userId, _masterDb);
|
||||
ApplyDropRewardPossessions(userDb, dropRewards, _masterDb);
|
||||
ApplyDropRewardPossessions(userDb, replayFlowFirstClearRewards, _masterDb);
|
||||
|
||||
userQuest.QuestStateType = (int)QuestStateType.CLEARED;
|
||||
userQuest.ClearCount++;
|
||||
@@ -546,10 +546,10 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
}
|
||||
|
||||
// Mark all missions as cleared (always)
|
||||
ClearQuestMissions(userDb, questId, userId, nowMs);
|
||||
ClearQuestMissions(userDb, questId, nowMs);
|
||||
|
||||
// Build response with all reward categories and clean up the server-side quest session
|
||||
FinishMainQuestResponse response = new() { IsBigWin = isBigWin };
|
||||
FinishMainQuestResponse response= new() { IsBigWin = isBigWin };
|
||||
response.DropReward.AddRange(dropRewards);
|
||||
response.FirstClearReward.AddRange(firstClearRewards);
|
||||
response.MissionClearReward.AddRange(missionClearRewards);
|
||||
@@ -566,7 +566,7 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
}
|
||||
|
||||
/// <summary>Applies user, character, and costume EXP from quest completion. Rental quests skip character/costume EXP.</summary>
|
||||
private void ApplyExpRewards(DarkUserMemoryDatabase userDb, EntityMQuest quest, long userId, int questId)
|
||||
private void ApplyExpRewards(DarkUserMemoryDatabase userDb, EntityMQuest quest, int questId)
|
||||
{
|
||||
// User EXP is always applied regardless of deck.
|
||||
EntityIUserStatus? status = userDb.EntityIUserStatus.FirstOrDefault();
|
||||
@@ -675,7 +675,7 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
}
|
||||
|
||||
/// <summary>Clears all quest missions for a given quest, creating any missing records.</summary>
|
||||
private void ClearQuestMissions(DarkUserMemoryDatabase userDb, int questId, long userId, long nowMs)
|
||||
private void ClearQuestMissions(DarkUserMemoryDatabase userDb, int questId, long nowMs)
|
||||
{
|
||||
EntityMQuest? quest = _masterDb.EntityMQuest.FirstOrDefault(q => q.QuestId == questId);
|
||||
if (quest == null || quest.QuestMissionGroupId == 0) return;
|
||||
@@ -685,7 +685,7 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
{
|
||||
EntityIUserQuestMission userMission = userDb.EntityIUserQuestMission.GetOrCreate(
|
||||
m => m.QuestId == questId && m.QuestMissionId == missionGroupRow.QuestMissionId,
|
||||
() => new EntityIUserQuestMission { UserId = userId, QuestId = questId, QuestMissionId = missionGroupRow.QuestMissionId });
|
||||
() => new EntityIUserQuestMission { UserId = userDb.UserId, QuestId = questId, QuestMissionId = missionGroupRow.QuestMissionId });
|
||||
userMission.IsClear = true;
|
||||
userMission.ProgressValue = 1;
|
||||
userMission.LatestClearDatetime = nowMs;
|
||||
@@ -693,44 +693,44 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
}
|
||||
|
||||
/// <summary>Grants gold (consumable item ID 1) from quest completion.</summary>
|
||||
private static void ApplyGoldReward(DarkUserMemoryDatabase userDb, EntityMQuest quest, long userId, long nowMs)
|
||||
private static void ApplyGoldReward(DarkUserMemoryDatabase userDb, EntityMQuest quest, long nowMs)
|
||||
{
|
||||
if (quest.Gold <= 0) return;
|
||||
EntityIUserConsumableItem? gold = userDb.EntityIUserConsumableItem.FirstOrDefault(c => c.ConsumableItemId == 1);
|
||||
if (gold == null)
|
||||
{
|
||||
gold = new EntityIUserConsumableItem { UserId = userId, ConsumableItemId = 1, Count = 0, FirstAcquisitionDatetime = nowMs };
|
||||
gold = new EntityIUserConsumableItem { UserId = userDb.UserId, ConsumableItemId = 1, Count = 0, FirstAcquisitionDatetime = nowMs };
|
||||
userDb.EntityIUserConsumableItem.Add(gold);
|
||||
}
|
||||
gold.Count += quest.Gold;
|
||||
}
|
||||
|
||||
/// <summary>Grants first-clear reward possessions to the user.</summary>
|
||||
private static void ApplyFirstClearPossessions(DarkUserMemoryDatabase userDb, List<EntityMQuestFirstClearRewardGroup> rewardRows, long userId, DarkMasterMemoryDatabase masterDb)
|
||||
private static void ApplyFirstClearPossessions(DarkUserMemoryDatabase userDb, List<EntityMQuestFirstClearRewardGroup> rewardRows, DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
foreach (EntityMQuestFirstClearRewardGroup row in rewardRows)
|
||||
PossessionHelper.Apply(userDb, userId, row.PossessionType, row.PossessionId, row.Count, masterDb);
|
||||
PossessionHelper.Apply(userDb, row.PossessionType, row.PossessionId, row.Count, masterDb);
|
||||
}
|
||||
|
||||
/// <summary>Grants scene-based possessions from master data for the given quest scene.</summary>
|
||||
private void ApplySceneGrants(DarkUserMemoryDatabase userDb, int questSceneId, long userId)
|
||||
private void ApplySceneGrants(DarkUserMemoryDatabase userDb, int questSceneId)
|
||||
{
|
||||
List<EntityMUserQuestSceneGrantPossession> grants = [.. _masterDb.EntityMUserQuestSceneGrantPossession
|
||||
.Where(g => g.QuestSceneId == questSceneId && !g.IsDebug)];
|
||||
|
||||
foreach (EntityMUserQuestSceneGrantPossession grant in grants)
|
||||
PossessionHelper.Apply(userDb, userId, grant.PossessionType, grant.PossessionId, grant.Count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, grant.PossessionType, grant.PossessionId, grant.Count, _masterDb);
|
||||
}
|
||||
|
||||
/// <summary>Grants all drop reward possessions from a reward list.</summary>
|
||||
private static void ApplyDropRewardPossessions(DarkUserMemoryDatabase userDb, List<QuestReward> rewards, long userId, DarkMasterMemoryDatabase masterDb)
|
||||
private static void ApplyDropRewardPossessions(DarkUserMemoryDatabase userDb, List<QuestReward> rewards, DarkMasterMemoryDatabase masterDb)
|
||||
{
|
||||
foreach (QuestReward reward in rewards)
|
||||
PossessionHelper.Apply(userDb, userId, (PossessionType)reward.PossessionType, reward.PossessionId, reward.Count, masterDb);
|
||||
PossessionHelper.Apply(userDb, (PossessionType)reward.PossessionType, reward.PossessionId, reward.Count, masterDb);
|
||||
}
|
||||
|
||||
/// <summary>Unlocks weapon stories triggered by QUEST_CLEAR. ACQUISITION unlocks are handled by WeaponHelper.GrantWeapon.</summary>
|
||||
private void ApplyWeaponStoryUnlocks(DarkUserMemoryDatabase userDb, int questId, long userId)
|
||||
private void ApplyWeaponStoryUnlocks(DarkUserMemoryDatabase userDb, int questId)
|
||||
{
|
||||
IEnumerable<EntityMWeaponStoryReleaseConditionGroup> questClearCondRows = _masterDb.EntityMWeaponStoryReleaseConditionGroup
|
||||
.Where(c => c.WeaponStoryReleaseConditionType == WeaponStoryReleaseConditionType.QUEST_CLEAR
|
||||
@@ -740,7 +740,7 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
EntityMWeapon? masterWeapon = _masterDb.EntityMWeapon
|
||||
.FirstOrDefault(w => w.WeaponStoryReleaseConditionGroupId == condRow.WeaponStoryReleaseConditionGroupId);
|
||||
if (masterWeapon != null)
|
||||
WeaponHelper.GrantWeaponStory(userDb, masterWeapon.WeaponId, condRow.StoryIndex, userId);
|
||||
WeaponHelper.GrantWeaponStory(userDb, masterWeapon.WeaponId, condRow.StoryIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,13 +962,13 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
{
|
||||
if (isFirstClear)
|
||||
{
|
||||
ApplyExpRewards(userDb, quest, userId, questId);
|
||||
ApplyGoldReward(userDb, quest, userId, nowMs);
|
||||
ApplyFirstClearPossessions(userDb, firstClearRewardRows, userId, _masterDb);
|
||||
ApplyWeaponStoryUnlocks(userDb, questId, userId);
|
||||
ApplyExpRewards(userDb, quest, questId);
|
||||
ApplyGoldReward(userDb, quest, nowMs);
|
||||
ApplyFirstClearPossessions(userDb, firstClearRewardRows, _masterDb);
|
||||
ApplyWeaponStoryUnlocks(userDb, questId);
|
||||
}
|
||||
|
||||
ApplyDropRewardPossessions(userDb, dropRewardsExtra, userId, _masterDb);
|
||||
ApplyDropRewardPossessions(userDb, dropRewardsExtra, _masterDb);
|
||||
|
||||
userQuest.QuestStateType = (int)QuestStateType.CLEARED;
|
||||
userQuest.ClearCount++;
|
||||
@@ -987,9 +987,9 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
}
|
||||
|
||||
// Mark all missions as cleared (always)
|
||||
ClearQuestMissions(userDb, questId, userId, nowMs);
|
||||
ClearQuestMissions(userDb, questId, nowMs);
|
||||
|
||||
FinishExtraQuestResponse response = new() { IsBigWin = isBigWin };
|
||||
FinishExtraQuestResponse response= new() { IsBigWin = isBigWin };
|
||||
response.DropReward.AddRange(dropRewardsExtra);
|
||||
response.FirstClearReward.AddRange(firstClearRewards);
|
||||
response.MissionClearReward.AddRange(missionClearRewards);
|
||||
@@ -1218,13 +1218,13 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
{
|
||||
if (isFirstClear)
|
||||
{
|
||||
ApplyExpRewards(userDb, quest, userId, questId);
|
||||
ApplyGoldReward(userDb, quest, userId, nowMs);
|
||||
ApplyFirstClearPossessions(userDb, firstClearRewardRows, userId, _masterDb);
|
||||
ApplyWeaponStoryUnlocks(userDb, questId, userId);
|
||||
ApplyExpRewards(userDb, quest, questId);
|
||||
ApplyGoldReward(userDb, quest, nowMs);
|
||||
ApplyFirstClearPossessions(userDb, firstClearRewardRows, _masterDb);
|
||||
ApplyWeaponStoryUnlocks(userDb, questId);
|
||||
}
|
||||
|
||||
ApplyDropRewardPossessions(userDb, dropRewardsEvent, userId, _masterDb);
|
||||
ApplyDropRewardPossessions(userDb, dropRewardsEvent, _masterDb);
|
||||
|
||||
userQuest.QuestStateType = (int)QuestStateType.CLEARED;
|
||||
userQuest.ClearCount++;
|
||||
@@ -1243,9 +1243,9 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
}
|
||||
|
||||
// Mark all missions as cleared (always)
|
||||
ClearQuestMissions(userDb, questId, userId, nowMs);
|
||||
ClearQuestMissions(userDb, questId, nowMs);
|
||||
|
||||
FinishEventQuestResponse response = new() { IsBigWin = isBigWin };
|
||||
FinishEventQuestResponse response= new() { IsBigWin = isBigWin };
|
||||
response.DropReward.AddRange(dropRewardsEvent);
|
||||
response.FirstClearReward.AddRange(firstClearRewards);
|
||||
response.MissionClearReward.AddRange(missionClearRewards);
|
||||
@@ -1335,11 +1335,11 @@ public class QuestService(UserDataStore store, DarkMasterMemoryDatabase masterDb
|
||||
for (int i = 0; i < request.SkipCount; i++)
|
||||
{
|
||||
List<QuestReward> iterDrops = BuildDropRewards(quest);
|
||||
ApplyDropRewardPossessions(userDb, iterDrops, userId, _masterDb);
|
||||
ApplyDropRewardPossessions(userDb, iterDrops, _masterDb);
|
||||
dropRewards.AddRange(iterDrops);
|
||||
|
||||
ApplyGoldReward(userDb, quest, userId, nowMs);
|
||||
ApplyExpRewards(userDb, quest, userId, questId);
|
||||
ApplyGoldReward(userDb, quest, nowMs);
|
||||
ApplyExpRewards(userDb, quest, questId);
|
||||
}
|
||||
|
||||
userQuest.ClearCount += request.SkipCount;
|
||||
|
||||
@@ -73,7 +73,7 @@ public class RewardService(UserDataStore store, DarkMasterMemoryDatabase masterD
|
||||
List<EntityMBigHuntRewardGroup> items = CollectNewRewards(rewardGroupId, 0, maxScore);
|
||||
foreach (EntityMBigHuntRewardGroup item in items)
|
||||
{
|
||||
PossessionHelper.Apply(userDb, userId, item.PossessionType, item.PossessionId, item.Count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, item.PossessionType, item.PossessionId, item.Count, _masterDb);
|
||||
weeklyRewards.Add(new BigHuntReward
|
||||
{
|
||||
PossessionType = (int)item.PossessionType,
|
||||
|
||||
@@ -37,11 +37,11 @@ public class ShopService(UserDataStore store, DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
foreach (EntityMShopItemContentPossession content in contents)
|
||||
{
|
||||
GrantShopPossession(userDb, userId, content.PossessionType, content.PossessionId, content.Count * qty);
|
||||
GrantShopPossession(userDb, content.PossessionType, content.PossessionId, content.Count * qty);
|
||||
}
|
||||
|
||||
// Apply side effects (e.g., stamina recovery)
|
||||
ApplyContentEffects(userDb, shopItemId, qty, userId, nowMs);
|
||||
ApplyContentEffects(userDb, shopItemId, qty, nowMs);
|
||||
|
||||
// Track purchase count
|
||||
EntityIUserShopItem? shopItem = userDb.EntityIUserShopItem.FirstOrDefault(s => s.ShopItemId == shopItemId);
|
||||
@@ -145,10 +145,10 @@ public class ShopService(UserDataStore store, DarkMasterMemoryDatabase masterDb)
|
||||
|
||||
foreach (EntityMShopItemContentPossession content in contents)
|
||||
{
|
||||
GrantShopPossession(userDb, userId, content.PossessionType, content.PossessionId, content.Count);
|
||||
GrantShopPossession(userDb, content.PossessionType, content.PossessionId, content.Count);
|
||||
}
|
||||
|
||||
ApplyContentEffects(userDb, request.ShopItemId, 1, userId, nowMs);
|
||||
ApplyContentEffects(userDb, request.ShopItemId, 1, nowMs);
|
||||
|
||||
EntityIUserShopItem? shopItem = userDb.EntityIUserShopItem.FirstOrDefault(s => s.ShopItemId == request.ShopItemId);
|
||||
if (shopItem == null)
|
||||
@@ -226,7 +226,7 @@ public class ShopService(UserDataStore store, DarkMasterMemoryDatabase masterDb)
|
||||
/// Grants a shop possession to the user. For costumes already owned, grants duplication
|
||||
/// exchange items instead. All other types delegate to PossessionHelper.Apply.
|
||||
/// </summary>
|
||||
private void GrantShopPossession(DarkUserMemoryDatabase userDb, long userId, PossessionType possessionType, int possessionId, int count)
|
||||
private void GrantShopPossession(DarkUserMemoryDatabase userDb, PossessionType possessionType, int possessionId, int count)
|
||||
{
|
||||
if (possessionType is PossessionType.COSTUME or PossessionType.COSTUME_ENHANCED
|
||||
&& userDb.EntityIUserCostume.Any(c => c.CostumeId == possessionId))
|
||||
@@ -234,21 +234,21 @@ public class ShopService(UserDataStore store, DarkMasterMemoryDatabase masterDb)
|
||||
foreach (EntityMCostumeDuplicationExchangePossessionGroup exchange in _masterDb.EntityMCostumeDuplicationExchangePossessionGroup
|
||||
.Where(e => e.CostumeId == possessionId))
|
||||
{
|
||||
PossessionHelper.Apply(userDb, userId, exchange.PossessionType, exchange.PossessionId, exchange.Count * count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, exchange.PossessionType, exchange.PossessionId, exchange.Count * count, _masterDb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
PossessionHelper.Apply(userDb, userId, possessionType, possessionId, count, _masterDb);
|
||||
PossessionHelper.Apply(userDb, possessionType, possessionId, count, _masterDb);
|
||||
}
|
||||
|
||||
/// <summary>Applies side-effect content (e.g., stamina recovery) from a shop item purchase.</summary>
|
||||
private void ApplyContentEffects(DarkUserMemoryDatabase userDb, int shopItemId, int qty, long userId, long nowMs)
|
||||
/// <summary>Applies side-effect content(e.g., stamina recovery) from a shop item purchase.</summary>
|
||||
private void ApplyContentEffects(DarkUserMemoryDatabase userDb, int shopItemId, int qty, long nowMs)
|
||||
{
|
||||
List<EntityMShopItemContentEffect> effects = [.. _masterDb.EntityMShopItemContentEffect
|
||||
.Where(e => e.ShopItemId == shopItemId)];
|
||||
|
||||
EntityIUserStatus? userStatus = userDb.EntityIUserStatus.FirstOrDefault(s => s.UserId == userId);
|
||||
EntityIUserStatus? userStatus = userDb.EntityIUserStatus.FirstOrDefault(s => s.UserId == userDb.UserId);
|
||||
if (userStatus == null) { return; }
|
||||
|
||||
EntityMUserLevel? levelData = _masterDb.EntityMUserLevel.FirstOrDefault(l => l.UserLevel == userStatus.Level);
|
||||
|
||||
@@ -18,15 +18,15 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
DarkUserMemoryDatabase userDb = store.GetOrCreate(userId);
|
||||
long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
UpsertTutorialProgress(userDb, userId, (TutorialType)request.TutorialType, request.ProgressPhase, request.ChoiceId);
|
||||
UpsertTutorialProgress(userDb, (TutorialType)request.TutorialType, request.ProgressPhase, request.ChoiceId);
|
||||
|
||||
if (request.TutorialType == (int)TutorialType.MENU_FIRST ||
|
||||
request.TutorialType == (int)TutorialType.MENU_SECOND)
|
||||
{
|
||||
CreateStarterDeck(userDb, userId);
|
||||
CreateStarterDeck(userDb);
|
||||
}
|
||||
|
||||
List<TutorialChoiceReward> rewards = ApplyTutorialRewards(userDb, userId, (TutorialType)request.TutorialType);
|
||||
List<TutorialChoiceReward> rewards = ApplyTutorialRewards(userDb, (TutorialType)request.TutorialType);
|
||||
|
||||
SetTutorialProgressResponse response = new();
|
||||
response.TutorialChoiceReward.AddRange(rewards);
|
||||
@@ -39,14 +39,14 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
long userId = context.GetUserId();
|
||||
DarkUserMemoryDatabase userDb = store.GetOrCreate(userId);
|
||||
|
||||
UpsertTutorialProgress(userDb, userId, (TutorialType)request.TutorialType, request.ProgressPhase, choiceId: 0);
|
||||
UpsertDeck(userDb, userId, request);
|
||||
UpsertTutorialProgress(userDb, (TutorialType)request.TutorialType, request.ProgressPhase, choiceId: 0);
|
||||
UpsertDeck(userDb, request);
|
||||
|
||||
return Task.FromResult(new SetTutorialProgressAndReplaceDeckResponse());
|
||||
}
|
||||
|
||||
/// <summary>Creates or updates a tutorial progress record, advancing to the specified phase.</summary>
|
||||
private static void UpsertTutorialProgress(DarkUserMemoryDatabase db, long userId, TutorialType type, int phase, int choiceId)
|
||||
private static void UpsertTutorialProgress(DarkUserMemoryDatabase db, TutorialType type, int phase, int choiceId)
|
||||
{
|
||||
EntityIUserTutorialProgress? existing = db.EntityIUserTutorialProgress
|
||||
.FirstOrDefault(t => t.TutorialType == type);
|
||||
@@ -55,7 +55,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
{
|
||||
db.EntityIUserTutorialProgress.Add(new EntityIUserTutorialProgress
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
TutorialType = type,
|
||||
ProgressPhase = phase,
|
||||
ChoiceId = choiceId
|
||||
@@ -76,7 +76,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
/// owned costume/weapon/companion. Only runs when no deck 1 character slot exists yet.
|
||||
/// Idempotent: safe to call multiple times.
|
||||
/// </summary>
|
||||
private static void CreateStarterDeck(DarkUserMemoryDatabase db, long userId)
|
||||
private static void CreateStarterDeck(DarkUserMemoryDatabase db)
|
||||
{
|
||||
if (db.EntityIUserCostume.Count == 0)
|
||||
{
|
||||
@@ -106,7 +106,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
|
||||
db.EntityIUserDeckCharacter.Add(new EntityIUserDeckCharacter
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = dcUuid,
|
||||
UserCostumeUuid = costumeUuid,
|
||||
MainUserWeaponUuid = weaponUuid,
|
||||
@@ -117,9 +117,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
{
|
||||
db.EntityIUserDeck.Add(new EntityIUserDeck
|
||||
{
|
||||
UserId = userId,
|
||||
DeckType = DeckType.QUEST,
|
||||
UserDeckNumber = 1,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid01 = dcUuid,
|
||||
Name = "Loadout 1",
|
||||
Power = 0
|
||||
@@ -137,7 +135,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
{
|
||||
db.EntityIUserDeckTypeNote.Add(new EntityIUserDeckTypeNote
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
DeckType = DeckType.QUEST,
|
||||
MaxDeckPower = 0
|
||||
});
|
||||
@@ -149,7 +147,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
/// Removes existing EntityIUserDeckCharacter records for the deck, creates fresh ones with new
|
||||
/// UUIDs, and updates EntityIUserDeck to reference the newly generated character UUIDs.
|
||||
/// </summary>
|
||||
private static void UpsertDeck(DarkUserMemoryDatabase db, long userId, SetTutorialProgressAndReplaceDeckRequest request)
|
||||
private static void UpsertDeck(DarkUserMemoryDatabase db, SetTutorialProgressAndReplaceDeckRequest request)
|
||||
{
|
||||
DeckType deckType = (DeckType)request.DeckType;
|
||||
|
||||
@@ -168,15 +166,15 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
db.EntityIUserDeckSubWeaponGroup.RemoveAll(swg => oldUuids.Contains(swg.UserDeckCharacterUuid));
|
||||
}
|
||||
|
||||
string uuid01 = CreateDeckCharacter(db, userId, request.Deck?.Character01);
|
||||
string uuid02 = CreateDeckCharacter(db, userId, request.Deck?.Character02);
|
||||
string uuid03 = CreateDeckCharacter(db, userId, request.Deck?.Character03);
|
||||
string uuid01 = CreateDeckCharacter(db, request.Deck?.Character01);
|
||||
string uuid02 = CreateDeckCharacter(db, request.Deck?.Character02);
|
||||
string uuid03 = CreateDeckCharacter(db, request.Deck?.Character03);
|
||||
|
||||
if (existing is null)
|
||||
{
|
||||
db.EntityIUserDeck.Add(new EntityIUserDeck
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
DeckType = deckType,
|
||||
UserDeckNumber = request.UserDeckNumber,
|
||||
UserDeckCharacterUuid01 = uuid01,
|
||||
@@ -195,7 +193,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
}
|
||||
|
||||
/// <summary>Creates a deck character record from a DeckCharacter slot proto and returns the new UUID.</summary>
|
||||
private static string CreateDeckCharacter(DarkUserMemoryDatabase db, long userId, DeckCharacter? slot)
|
||||
private static string CreateDeckCharacter(DarkUserMemoryDatabase db, DeckCharacter? slot)
|
||||
{
|
||||
if (slot is null || string.IsNullOrEmpty(slot.UserCostumeUuid))
|
||||
{
|
||||
@@ -205,7 +203,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
string newUuid = Guid.NewGuid().ToString();
|
||||
db.EntityIUserDeckCharacter.Add(new EntityIUserDeckCharacter
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
UserCostumeUuid = slot.UserCostumeUuid,
|
||||
MainUserWeaponUuid = slot.MainUserWeaponUuid,
|
||||
@@ -218,7 +216,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
{
|
||||
db.EntityIUserDeckCharacterDressupCostume.Add(new EntityIUserDeckCharacterDressupCostume
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
DressupCostumeId = slot.DressupCostumeId
|
||||
});
|
||||
@@ -229,7 +227,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
if (string.IsNullOrEmpty(slot.UserPartsUuid[i])) { continue; }
|
||||
db.EntityIUserDeckPartsGroup.Add(new EntityIUserDeckPartsGroup
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
UserPartsUuid = slot.UserPartsUuid[i],
|
||||
SortOrder = i + 1
|
||||
@@ -241,7 +239,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
if (string.IsNullOrEmpty(slot.SubUserWeaponUuid[i])) { continue; }
|
||||
db.EntityIUserDeckSubWeaponGroup.Add(new EntityIUserDeckSubWeaponGroup
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = db.UserId,
|
||||
UserDeckCharacterUuid = newUuid,
|
||||
UserWeaponUuid = slot.SubUserWeaponUuid[i],
|
||||
SortOrder = i + 1
|
||||
@@ -255,7 +253,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
/// Grants tutorial rewards from master data keyed by tutorial type and returns the reward list
|
||||
/// for the response. Each tutorial type may grant companions, gems, items, or other possessions.
|
||||
/// </summary>
|
||||
private List<TutorialChoiceReward> ApplyTutorialRewards(DarkUserMemoryDatabase db, long userId, TutorialType tutorialType)
|
||||
private List<TutorialChoiceReward> ApplyTutorialRewards(DarkUserMemoryDatabase db, TutorialType tutorialType)
|
||||
{
|
||||
List<EntityMTutorialConsumePossessionGroup> rewardRows = [.. masterDb.EntityMTutorialConsumePossessionGroup
|
||||
.Where(r => r.TutorialType == tutorialType)];
|
||||
@@ -264,7 +262,7 @@ public class TutorialService(UserDataStore store, DarkMasterMemoryDatabase maste
|
||||
|
||||
foreach (EntityMTutorialConsumePossessionGroup row in rewardRows)
|
||||
{
|
||||
PossessionHelper.Apply(db, userId, row.PossessionType, row.PossessionId, row.Count, masterDb);
|
||||
PossessionHelper.Apply(db, row.PossessionType, row.PossessionId, row.Count, masterDb);
|
||||
|
||||
result.Add(new TutorialChoiceReward
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
{
|
||||
if (exchange.WeaponId == weapon.WeaponId)
|
||||
{
|
||||
AddConsumableItem(userDb, userId, exchange.ConsumableItemId, exchange.Count);
|
||||
AddConsumableItem(userDb, exchange.ConsumableItemId, exchange.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
|
||||
if (totalGold > 0)
|
||||
{
|
||||
AddConsumableItem(userDb, userId, _gameConfig.ConsumableItemIdForGold, totalGold);
|
||||
AddConsumableItem(userDb, _gameConfig.ConsumableItemIdForGold, totalGold);
|
||||
}
|
||||
|
||||
return Task.FromResult(new SellResponse());
|
||||
@@ -186,9 +186,9 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
weapon.Exp += totalExp;
|
||||
ApplyLevelFromExp(weapon, wm);
|
||||
|
||||
CheckWeaponStoryUnlocks(userDb, userId, weapon.WeaponId, weapon.Level);
|
||||
CheckWeaponStoryUnlocks(userDb, weapon.WeaponId, weapon.Level);
|
||||
|
||||
return Task.FromResult(new EnhanceByMaterialResponse { IsGreatSuccess = false });
|
||||
return Task.FromResult(new EnhanceByMaterialResponse{ IsGreatSuccess = false });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -242,7 +242,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
{
|
||||
if (exchange.WeaponId == matWeapon.WeaponId)
|
||||
{
|
||||
AddConsumableItem(userDb, userId, exchange.ConsumableItemId, exchange.Count);
|
||||
AddConsumableItem(userDb, exchange.ConsumableItemId, exchange.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,9 +269,9 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
weapon.Exp += totalExp;
|
||||
ApplyLevelFromExp(weapon, wm);
|
||||
|
||||
CheckWeaponStoryUnlocks(userDb, userId, weapon.WeaponId, weapon.Level);
|
||||
CheckWeaponStoryUnlocks(userDb, weapon.WeaponId, weapon.Level);
|
||||
|
||||
return Task.FromResult(new EnhanceByWeaponResponse { IsGreatSuccess = false });
|
||||
return Task.FromResult(new EnhanceByWeaponResponse{ IsGreatSuccess = false });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -533,7 +533,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
weapon.LimitBreakCount += totalMaterialCount;
|
||||
|
||||
// Track the highest limit break count in the weapon note
|
||||
UpdateWeaponNote(userDb, userId, weapon);
|
||||
UpdateWeaponNote(userDb, weapon);
|
||||
|
||||
return Task.FromResult(new LimitBreakByMaterialResponse());
|
||||
}
|
||||
@@ -583,7 +583,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
{
|
||||
if (exchange.WeaponId == matWeapon.WeaponId)
|
||||
{
|
||||
AddConsumableItem(userDb, userId, exchange.ConsumableItemId, exchange.Count);
|
||||
AddConsumableItem(userDb, exchange.ConsumableItemId, exchange.Count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -609,7 +609,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
weapon.LimitBreakCount += consumedCount;
|
||||
|
||||
// Track the highest limit break count in the weapon note
|
||||
UpdateWeaponNote(userDb, userId, weapon);
|
||||
UpdateWeaponNote(userDb, weapon);
|
||||
|
||||
return Task.FromResult(new LimitBreakByWeaponResponse());
|
||||
}
|
||||
@@ -712,7 +712,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
}
|
||||
|
||||
// Check if the evolution unlocks new weapon story pages
|
||||
CheckWeaponStoryUnlocks(userDb, userId, evolvedId, weapon.Level);
|
||||
CheckWeaponStoryUnlocks(userDb, evolvedId, weapon.Level);
|
||||
|
||||
return Task.FromResult(new EvolveResponse());
|
||||
}
|
||||
@@ -883,7 +883,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
/// <summary>
|
||||
/// Grants a consumable item to the user, creating the inventory entry if it doesn't exist yet.
|
||||
/// </summary>
|
||||
private static void AddConsumableItem(DarkUserMemoryDatabase userDb, long userId, int itemId, int count)
|
||||
private static void AddConsumableItem(DarkUserMemoryDatabase userDb, int itemId, int count)
|
||||
{
|
||||
foreach (EntityIUserConsumableItem ci in userDb.EntityIUserConsumableItem)
|
||||
{
|
||||
@@ -896,7 +896,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
|
||||
userDb.EntityIUserConsumableItem.Add(new EntityIUserConsumableItem
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
ConsumableItemId = itemId,
|
||||
Count = count,
|
||||
FirstAcquisitionDatetime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
@@ -992,7 +992,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
/// <summary>
|
||||
/// Updates the weapon note to track the highest limit break count ever achieved for this weapon.
|
||||
/// </summary>
|
||||
private static void UpdateWeaponNote(DarkUserMemoryDatabase userDb, long userId, EntityIUserWeapon weapon)
|
||||
private static void UpdateWeaponNote(DarkUserMemoryDatabase userDb, EntityIUserWeapon weapon)
|
||||
{
|
||||
EntityIUserWeaponNote? note = null;
|
||||
foreach (EntityIUserWeaponNote n in userDb.EntityIUserWeaponNote)
|
||||
@@ -1016,7 +1016,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
/// <summary>
|
||||
/// Evaluates weapon story release conditions and unlocks story pages when conditions are met (level reached, evolution, acquisition, etc.).
|
||||
/// </summary>
|
||||
private void CheckWeaponStoryUnlocks(DarkUserMemoryDatabase userDb, long userId, int weaponId, int level)
|
||||
private void CheckWeaponStoryUnlocks(DarkUserMemoryDatabase userDb, int weaponId, int level)
|
||||
{
|
||||
EntityMWeapon? wm = FindWeaponMaster(weaponId);
|
||||
if (wm == null || wm.WeaponStoryReleaseConditionGroupId == 0)
|
||||
@@ -1057,7 +1057,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
|
||||
if (shouldUnlock)
|
||||
{
|
||||
GrantWeaponStoryUnlock(userDb, userId, weaponId, cond.StoryIndex);
|
||||
GrantWeaponStoryUnlock(userDb, weaponId, cond.StoryIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1086,7 +1086,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
/// <summary>
|
||||
/// Unlocks a weapon story page, creating the story record if new or advancing the max released story index.
|
||||
/// </summary>
|
||||
private static void GrantWeaponStoryUnlock(DarkUserMemoryDatabase userDb, long userId, int weaponId, int storyIndex)
|
||||
private static void GrantWeaponStoryUnlock(DarkUserMemoryDatabase userDb, int weaponId, int storyIndex)
|
||||
{
|
||||
EntityIUserWeaponStory? existing = null;
|
||||
foreach (EntityIUserWeaponStory ws in userDb.EntityIUserWeaponStory)
|
||||
@@ -1109,7 +1109,7 @@ public class WeaponService(DarkMasterMemoryDatabase masterDb, UserDataStore stor
|
||||
{
|
||||
userDb.EntityIUserWeaponStory.Add(new EntityIUserWeaponStory
|
||||
{
|
||||
UserId = userId,
|
||||
UserId = userDb.UserId,
|
||||
WeaponId = weaponId,
|
||||
ReleasedMaxStoryIndex = storyIndex
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user