Автор не я взял с Англ сайта
Приветствую. Недавно я сделал забавную штуку: игра выводит список игроков онлайн, сортирует его и отправляет жемчужины только тем, кто находится онлайн.
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, который я создал.
Вы заметите, что выполняется dbo.sendMailToOnlineUsers.
Это хранимая процедура базы данных. Создать её легко. Разверните/откройте базу данных SA_BETA_WORLDDB_0002, разверните раздел «Программируемость» и разверните раздел «Хранимые процедуры». Проверьте, есть ли у вас процедура dbo.sendMailToOnlineUsers. Если да — отлично. Если нет, давайте создадим её.
Щёлкните правой кнопкой мыши по разделу «Хранимые процедуры» и выберите «Создать и сохранить процедуру». Удалите всё и вставьте в процедуру ниже, затем нажмите «Выполнить» (или F5), чтобы запустить её. Обновите страницу, и она должна появиться.
Приветствую. Недавно я сделал забавную штуку: игра выводит список игроков онлайн, сортирует его и отправляет жемчужины только тем, кто находится онлайн.
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
Это хранимая процедура базы данных. Создать её легко. Разверните/откройте базу данных 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;