Add authentication server, dev CLI, Docker multi-service setup, and cross-platform improvements

This commit is contained in:
Ilya Groshev
2026-04-21 16:49:44 +03:00
parent 43d6527b42
commit a3fbb1aeba
121 changed files with 4523 additions and 2888 deletions
+21 -89
View File
@@ -14,15 +14,8 @@ import (
"lunar-tear/server/internal/masterdata"
"lunar-tear/server/internal/model"
"lunar-tear/server/internal/store"
"lunar-tear/server/internal/userdata"
)
var costumeDiffTables = []string{
"IUserCostume",
"IUserMaterial",
"IUserConsumableItem",
}
type CostumeServiceServer struct {
pb.UnimplementedCostumeServiceServer
users store.UserRepository
@@ -38,10 +31,10 @@ func NewCostumeServiceServer(users store.UserRepository, sessions store.SessionR
func (s *CostumeServiceServer) Enhance(ctx context.Context, req *pb.EnhanceRequest) (*pb.EnhanceResponse, error) {
log.Printf("[CostumeService] Enhance: uuid=%s materials=%v", req.UserCostumeUuid, req.Materials)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
costume, ok := user.Costumes[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] Enhance: costume uuid=%s not found", req.UserCostumeUuid)
@@ -98,30 +91,19 @@ func (s *CostumeServiceServer) Enhance(ctx context.Context, req *pb.EnhanceReque
return nil, fmt.Errorf("costume enhance: %w", err)
}
diff := userdata.BuildDiffFromTables(userdata.ProjectTables(snapshot, costumeDiffTables))
return &pb.EnhanceResponse{
IsGreatSuccess: false,
SurplusEnhanceMaterial: map[int32]int32{},
DiffUserData: diff,
}, nil
}
var awakenDiffTables = []string{
"IUserCostume",
"IUserMaterial",
"IUserConsumableItem",
"IUserCostumeAwakenStatusUp",
"IUserThought",
}
func (s *CostumeServiceServer) Awaken(ctx context.Context, req *pb.AwakenRequest) (*pb.AwakenResponse, error) {
log.Printf("[CostumeService] Awaken: uuid=%s materials=%v", req.UserCostumeUuid, req.Materials)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
costume, ok := user.Costumes[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] Awaken: costume uuid=%s not found", req.UserCostumeUuid)
@@ -179,11 +161,7 @@ func (s *CostumeServiceServer) Awaken(ctx context.Context, req *pb.AwakenRequest
return nil, fmt.Errorf("costume awaken: %w", err)
}
diff := userdata.BuildDiffFromTables(userdata.ProjectTables(snapshot, awakenDiffTables))
return &pb.AwakenResponse{
DiffUserData: diff,
}, nil
return &pb.AwakenResponse{}, nil
}
func (s *CostumeServiceServer) applyAwakenStatusUp(user *store.UserState, costumeUuid string, statusUpGroupId int32, nowMillis int64) {
@@ -245,19 +223,13 @@ func (s *CostumeServiceServer) applyAwakenItemAcquire(user *store.UserState, ite
log.Printf("[CostumeService] Awaken: granted thought id=%d", acq.PossessionId)
}
var activeSkillDiffTables = []string{
"IUserCostumeActiveSkill",
"IUserMaterial",
"IUserConsumableItem",
}
func (s *CostumeServiceServer) EnhanceActiveSkill(ctx context.Context, req *pb.EnhanceActiveSkillRequest) (*pb.EnhanceActiveSkillResponse, error) {
log.Printf("[CostumeService] EnhanceActiveSkill: uuid=%s addLevel=%d", req.UserCostumeUuid, req.AddLevelCount)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
costume, ok := user.Costumes[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] EnhanceActiveSkill: costume uuid=%s not found", req.UserCostumeUuid)
@@ -332,20 +304,16 @@ func (s *CostumeServiceServer) EnhanceActiveSkill(ctx context.Context, req *pb.E
return nil, fmt.Errorf("costume enhance active skill: %w", err)
}
diff := userdata.BuildDiffFromTables(userdata.ProjectTables(snapshot, activeSkillDiffTables))
return &pb.EnhanceActiveSkillResponse{
DiffUserData: diff,
}, nil
return &pb.EnhanceActiveSkillResponse{}, nil
}
func (s *CostumeServiceServer) LimitBreak(ctx context.Context, req *pb.LimitBreakRequest) (*pb.LimitBreakResponse, error) {
log.Printf("[CostumeService] LimitBreak: uuid=%s materials=%v", req.UserCostumeUuid, req.Materials)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
costume, ok := user.Costumes[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] LimitBreak: costume uuid=%s not found", req.UserCostumeUuid)
@@ -389,30 +357,16 @@ func (s *CostumeServiceServer) LimitBreak(ctx context.Context, req *pb.LimitBrea
return nil, fmt.Errorf("costume limit break: %w", err)
}
diff := userdata.BuildDiffFromTables(userdata.ProjectTables(snapshot, costumeDiffTables))
return &pb.LimitBreakResponse{
DiffUserData: diff,
}, nil
}
var lotteryEffectDiffTables = []string{
"IUserCostume",
"IUserCostumeLotteryEffect",
"IUserCostumeLotteryEffectAbility",
"IUserCostumeLotteryEffectStatusUp",
"IUserCostumeLotteryEffectPending",
"IUserConsumableItem",
"IUserMaterial",
return &pb.LimitBreakResponse{}, nil
}
func (s *CostumeServiceServer) UnlockLotteryEffectSlot(ctx context.Context, req *pb.UnlockLotteryEffectSlotRequest) (*pb.UnlockLotteryEffectSlotResponse, error) {
log.Printf("[CostumeService] UnlockLotteryEffectSlot: uuid=%s slot=%d", req.UserCostumeUuid, req.SlotNumber)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
costume, ok := user.Costumes[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] UnlockLotteryEffectSlot: costume uuid=%s not found", req.UserCostumeUuid)
@@ -458,26 +412,16 @@ func (s *CostumeServiceServer) UnlockLotteryEffectSlot(ctx context.Context, req
return nil, fmt.Errorf("costume unlock lottery effect slot: %w", err)
}
diff := userdata.BuildDiffFromTables(userdata.ProjectTables(snapshot, lotteryEffectDiffTables))
return &pb.UnlockLotteryEffectSlotResponse{
DiffUserData: diff,
}, nil
return &pb.UnlockLotteryEffectSlotResponse{}, nil
}
func (s *CostumeServiceServer) DrawLotteryEffect(ctx context.Context, req *pb.DrawLotteryEffectRequest) (*pb.DrawLotteryEffectResponse, error) {
log.Printf("[CostumeService] DrawLotteryEffect: uuid=%s slot=%d", req.UserCostumeUuid, req.SlotNumber)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
oldUser, _ := s.users.LoadUser(userId)
tracker := userdata.NewDeleteTracker().
Track("IUserMaterial", oldUser, userdata.SortedMaterialRecords, []string{"userId", "materialId"}).
Track("IUserConsumableItem", oldUser, userdata.SortedConsumableItemRecords, []string{"userId", "consumableItemId"}).
Track("IUserCostumeLotteryEffectPending", oldUser, userdata.SortedCostumeLotteryEffectPendingRecords, []string{"userId", "userCostumeUuid"})
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
costume, ok := user.Costumes[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] DrawLotteryEffect: costume uuid=%s not found", req.UserCostumeUuid)
@@ -514,7 +458,7 @@ func (s *CostumeServiceServer) DrawLotteryEffect(ctx context.Context, req *pb.Dr
totalWeight += row.Weight
}
roll := rand.Int31n(totalWeight)
var picked masterdata.CostumeLotteryEffectOddsRow
var picked masterdata.EntityMCostumeLotteryEffectOddsGroup
for _, row := range oddsPool {
roll -= row.Weight
if roll < 0 {
@@ -550,24 +494,16 @@ func (s *CostumeServiceServer) DrawLotteryEffect(ctx context.Context, req *pb.Dr
return nil, fmt.Errorf("costume draw lottery effect: %w", err)
}
diff := tracker.Apply(snapshot, userdata.ProjectTables(snapshot, lotteryEffectDiffTables))
return &pb.DrawLotteryEffectResponse{
DiffUserData: diff,
}, nil
return &pb.DrawLotteryEffectResponse{}, nil
}
func (s *CostumeServiceServer) ConfirmLotteryEffect(ctx context.Context, req *pb.ConfirmLotteryEffectRequest) (*pb.ConfirmLotteryEffectResponse, error) {
log.Printf("[CostumeService] ConfirmLotteryEffect: uuid=%s accept=%v", req.UserCostumeUuid, req.IsAccept)
userId := currentUserId(ctx, s.users, s.sessions)
userId := CurrentUserId(ctx, s.users, s.sessions)
nowMillis := gametime.NowMillis()
oldUser, _ := s.users.LoadUser(userId)
tracker := userdata.NewDeleteTracker().
Track("IUserCostumeLotteryEffectPending", oldUser, userdata.SortedCostumeLotteryEffectPendingRecords, []string{"userId", "userCostumeUuid"})
snapshot, err := s.users.UpdateUser(userId, func(user *store.UserState) {
_, err := s.users.UpdateUser(userId, func(user *store.UserState) {
pending, ok := user.CostumeLotteryEffectPending[req.UserCostumeUuid]
if !ok {
log.Printf("[CostumeService] ConfirmLotteryEffect: no pending for uuid=%s", req.UserCostumeUuid)
@@ -596,9 +532,5 @@ func (s *CostumeServiceServer) ConfirmLotteryEffect(ctx context.Context, req *pb
return nil, fmt.Errorf("costume confirm lottery effect: %w", err)
}
diff := tracker.Apply(snapshot, userdata.ProjectTables(snapshot, lotteryEffectDiffTables))
return &pb.ConfirmLotteryEffectResponse{
DiffUserData: diff,
}, nil
return &pb.ConfirmLotteryEffectResponse{}, nil
}