Мануал Corsair - Pearls every 30 min via mail

orohimaru2

Выдающийся
Местный
Сообщения
57
Розыгрыши
0
Репутация
114
Реакции
199
Баллы
1 388
Автор не я взял с Англ сайта
Приветствую. Недавно я сделал забавную штуку: игра выводит список игроков онлайн, сортирует его и отправляет жемчужины только тем, кто находится онлайн.

1. Для этого используется планировщик заданий.
a. Действие — «Запустить программу».
b. Программа/скрипт: "C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\SQLCMD.EXE"
c. Аргументы: -S . -d SA_BETA_WORLDDB_0002 -i "D:\SQL\Mail_Pearls_Online.sql"
d. Запустить в: D:\SQL\
ПРИМЕЧАНИЯ: Расположение моего файла: D:\SQL\. Вы можете разместить свой SQL-файл где угодно. Просто отредактируйте C и D выше.

Вот файл Mail_Pearls_Online.sql, который я создал.
Код:
USE [SA_BETA_WORLDDB_0002];
GO

DECLARE @OutputSymNo NVARCHAR(50);
DECLARE @ReturnCode INT;

-- Mail details - REPLACE these with your actual item and mail information
DECLARE @ItemKeyToSend BIGINT = 6;      -- Example: 54321 (replace with the actual item ID)
DECLARE @ItemCountToSend BIGINT = 150;        -- Example: 1 (number of items to send)
DECLARE @EnchantLevelToSend INT = 0;        -- Example: 0 (enchant level of the item)
DECLARE @MailTitleToSend NVARCHAR(100) = N'Free Pearls!'; -- The mail subject for online players
DECLARE @MailContentsToSend NVARCHAR(300) = N'Thanks for playing! Have some pearls!'; -- The mail body

PRINT N'Attempting to send mail to all currently online users...';

EXEC @ReturnCode = dbo.sendMailToOnlineUsers
    @itemKey = @ItemKeyToSend,
    @itemCount = @ItemCountToSend,
    @enchant = @EnchantLevelToSend,
    @title = @MailTitleToSend,
    @contents = @MailContentsToSend,
    @symNo = @OutputSymNo OUTPUT;

IF @ReturnCode = 0
BEGIN
    PRINT N'Mail sending process to online users finished successfully.';
END
ELSE
BEGIN
    PRINT N'Mail sending process to online users encountered an error.';
    PRINT N'Final Error Code: ' + CAST(@ReturnCode AS NVARCHAR(10));
    PRINT N'Final Error Message: ' + ISNULL(@OutputSymNo, N'No specific error message provided.');
END
GO
Вы заметите, что выполняется dbo.sendMailToOnlineUsers.
Это хранимая процедура базы данных. Создать её легко. Разверните/откройте базу данных SA_BETA_WORLDDB_0002, разверните раздел «Программируемость» и разверните раздел «Хранимые процедуры». Проверьте, есть ли у вас процедура dbo.sendMailToOnlineUsers. Если да — отлично. Если нет, давайте создадим её.
Щёлкните правой кнопкой мыши по разделу «Хранимые процедуры» и выберите «Создать и сохранить процедуру». Удалите всё и вставьте в процедуру ниже, затем нажмите «Выполнить» (или F5), чтобы запустить её. Обновите страницу, и она должна появиться.
Код:
USE [SA_BETA_WORLDDB_0002]
GO
/****** Object:  StoredProcedure [dbo].[sendMailToOnlineUsers]    Script Date: 8/28/2025 3:34:19 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[sendMailToOnlineUsers]
    @itemKey BIGINT,
    @itemCount BIGINT = 1,
    @enchant INT = 0,
    @title NVARCHAR(100) = N'Online Player Reward!',
    @contents NVARCHAR(300) = N'Thank you for being online! Here is a special gift.',
    @symNo NVARCHAR(50) OUTPUT -- Meaningful only in case of failure
AS
BEGIN
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    SET LOCK_TIMEOUT 3000;
    SET XACT_ABORT ON;

    DECLARE @returnValue INT = 0;  -- Return code from dbo.sendMail
    DECLARE @toFamilyName NVARCHAR(50); -- Variable for current online user's family name

    BEGIN TRANSACTION;

    -- Cursor to iterate through online users
    -- We are now explicitly filtering where _lastServerNo is positive (indicating online status)
    DECLARE OnlineUserCursor CURSOR FOR
    SELECT _userNickname
    FROM PaGamePrivate.TblUserInformation
    WHERE
        _lastServerNo > 0 -- This is the key condition for online users
        -- The _lastLoginTime > _lastLogoutTime check is often redundant if _lastServerNo is reliably managed,
        -- but can be kept as an extra safeguard if you wish.
        -- AND _lastLoginTime > _lastLogoutTime
        -- The time threshold check is also less critical if _lastServerNo is accurate,
        -- but could be used to filter for very recently active players if needed.
        -- AND _lastLoginTime >= DATEADD(minute, -10, GETDATE())
    ORDER BY
        _userNickname;

    OPEN OnlineUserCursor;
    FETCH NEXT FROM OnlineUserCursor INTO @toFamilyName;

    IF @@FETCH_STATUS <> 0
    BEGIN
        SET @symNo = N'NoOnlineUsersFound';
        PRINT N'No online users found to send mail to.';
        COMMIT TRANSACTION;
        RETURN 0;
    END

    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT N'Attempting to send mail to online user: ' + @toFamilyName;

        -- Call the fixed dbo.sendMail procedure for the current online user
        EXEC @returnValue = [dbo].[sendMail]
            @toFamilyName = @toFamilyName,
            @itemKey = @itemKey,
            @itemCount = @itemCount,
            @enchant = @enchant,
            @title = @title,
            @contents = @contents,
            @symNo = @symNo OUTPUT; -- Capture output error message

        IF @returnValue <> 0
        BEGIN
            PRINT N'  FAILED: Mail to online user ' + @toFamilyName + ' failed.';
            PRINT N'  Error Code: ' + CAST(@returnValue AS NVARCHAR(10));
            PRINT N'  Error Message: ' + ISNULL(@symNo, N'No specific error message provided.');
            -- Decide whether to rollback the whole transaction or just log and continue
            -- For online mail, you might want to continue to other users even if one fails.
            -- If you want to stop on first error, uncomment:
            -- ROLLBACK TRANSACTION;
            -- RETURN @returnValue;
        END
        ELSE
        BEGIN
            PRINT N'  SUCCESS: Mail sent to online user ' + @toFamilyName + '.';
        END

        FETCH NEXT FROM OnlineUserCursor INTO @toFamilyName;
    END;

    CLOSE OnlineUserCursor;
    DEALLOCATE OnlineUserCursor;

    COMMIT TRANSACTION;
    PRINT N'Mail sending process to online users completed.';
    RETURN 0;
END;
 

Назад
Сверху