Unity DarkRift2
Скачать
https://assetstore.unity.com/packages/tools/network/darkrift-networking-2-95309
Создать БД
CREATE DATABASE darkrift
WITH
OWNER = andedali
ENCODING = 'UTF8'
CONNECTION LIMIT = -1;
Запуск
Разархивировать DarkRift Server (.NET Framework 4.0) Запускать DarkRift.Server.Console.exe В конфиге Server.config можно поменять порт (4296 по умолчанию)
<listeners>
<listener name="DefaultNetworkListener" type="BichannelListener" address="0.0.0.0" port="4296
<settings noDelay="true" />
</listener>
</listeners>
В юнити создаём в сцене пустой объект DarkRiftClient и вешаем на него скрипт UnityClient
Билд на .NET 8.0
1. Качаем себе репозиторий с гитхаба https://github.com/DarkRiftNetworking/DarkRift (cmd в адресной строке окна куда ставить)
git clone https://github.com/DarkRiftNetworking/DarkRift
2. Скорректировать сборку, убрать не работающий плагин BadWordFilter из сборки. D:\Projects\DarkRift\DarkRift Server\DarkRift.Server\DarkRift.Server.csproj Добавить
<ItemGroup>
<Compile Remove="Plugins\Chat\BadWordFilter.cs" />
<Compile Remove="Plugins\Chat\IBadWordFilter.cs" />
</ItemGroup>
D:\Projects\DarkRift\DarkRift Server\DarkRift.Server\DarkRiftServer.cs Убрать
public IBadWordFilter BadWordFilter => PluginManager.GetPluginByType<BadWordFilter>();
...
typeof(Plugins.Chat.BadWordFilter),
D:\Projects\DarkRift\DarkRift Server\DarkRift.Server\Plugin.cs Убрать
public IBadWordFilter BadWordFilter => PluginManager.GetPluginByType<BadWordFilter>();
3. Обновим версию для сборки D:\Projects\DarkRift\DarkRift Server\DarkRift.Server.Console\DarkRift.Server.Console.csproj Заменить
<TargetFrameworks Condition=" '$(DRBuildMode)' != 'coreonly' ">net4.0;netcoreapp2.0;netcoreapp3.1;net5.0;net6.0;net8.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(DRBuildMode)' == 'coreonly' ">netcoreapp2.0;netcoreapp3.1;net5.0;net6.0;net8.0</TargetFrameworks>
4. Сам билд
dotnet build DarkRift2.sln -c Release -f net8.0 -p:NoWarn=NU1903 -p:TreatWarningsAsErrors=false -p:SkipCopyToBuild=true
Создается D:\Projects\DarkRift\unordinal\dr-build
5. Настройка
mkdir "D:\Projects\DarkRift\unordinal\dr-build\Release\net8.0" && echo Created net8.0 directory
cd "D:\Projects\DarkRift\unordinal\dr-build\Release\net8.0"
Создаём папки
mkdir Lib
mkdir Data
mkdir Logs
mkdir Plugins
Копирование основных библиотек
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\DarkRift.Server.Console.dll" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\DarkRift.Server.Console.deps.json" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\DarkRift.Server.Console.runtimeconfig.json" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\DarkRift.dll" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\DarkRift.Server.dll" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\DarkRift.Client.dll" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\*.xml" "Lib\"
copy "D:\Projects\DarkRift\unordinal\dr-build\DarkRift.Server.Console\bin\Release\net8.0\Server.config" "."
Создание bat файла
echo @echo off > start_server_net8.bat
echo cd /d "%%~dp0" >> start_server_net8.bat
echo echo Starting DarkRift Server (.NET 8.0)... >> start_server_net8.bat
echo echo. >> start_server_net8.bat
echo dotnet Lib/DarkRift.Server.Console.dll >> start_server_net8.bat
echo pause >> start_server_net8.bat
6. В самом юнити обновить dll D:\Projects\Unity\MMOProject\Assets\DarkRift\DarkRift\Plugins DarkRift.dll DarkRift.xml D:\Projects\Unity\MMOProject\Assets\DarkRift\DarkRift\Plugins\Server DarkRift.Server.dll DarkRift.Server.xml D:\Projects\Unity\MMOProject\Assets\DarkRift\DarkRift\Plugins\Client DarkRift.Client.dll DarkRift.Client.xml
Плагины
1. Соединение с БД postgres В Visual Studio 2022 Создать проект - Библиотека классов PostgresConnector .NET 8.0 Nullable ПКМ - PostgresConnector - Свойства Сборка - Общее - Допускающий значение NULL - Отключить ЛКМ - PostgresConnector
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>disable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>latest</LangVersion>
</PropertyGroup>
ПКМ - Зависимости - Управление пакетами NuGet... Ставим npgsql (последняя на момент 9.0.3) + зависимости (Microsoft.Extensions.Logging.Abstractions так же установить) ПКМ - Зависимости - Добавить ссылку на проект Выбрать через обзор DarkRift.dll и DarkRift.Server.dll Удалить Class1.cs ПКМ - PostgresConnector - Добавить - Создать элемент - Connector.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using Npgsql;
namespace PostgresConnector
{
public static class Connector
{
private static string connectionString = "Host=127.0.0.1;Port=5432;Database=darkrift;Username=andedali;Password=pass;";
public static void SetConnectionString(string value)
{
connectionString = value ?? throw new ArgumentNullException("value");
}
public static void ExecuteNonQuery(string query, params KeyValuePair<string, object>[] parameters)
{
try
{
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
{
using (NpgsqlCommand command = new NpgsqlCommand(query, connection))
{
foreach (KeyValuePair<string, object> pair in parameters)
{
command.Parameters.AddWithValue(pair.Key, pair.Value ?? DBNull.Value);
}
connection.Open();
command.ExecuteNonQuery();
}
}
}
catch (NpgsqlException e)
{
throw new Exception(e.Message, e);
}
}
public static object ExecuteScalar(string query, params KeyValuePair<string, object>[] parameters)
{
try
{
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
{
using (NpgsqlCommand command = new NpgsqlCommand(query, connection))
{
foreach (KeyValuePair<string, object> pair in parameters)
{
command.Parameters.AddWithValue(pair.Key, pair.Value ?? DBNull.Value);
}
connection.Open();
return command.ExecuteScalar();
}
}
}
catch (NpgsqlException e)
{
throw new Exception(e.Message, e);
}
}
public static Dictionary<string, object>[] ExecuteQuery(string query, params KeyValuePair<string, object>[] parameters)
{
try
{
using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
{
using (NpgsqlCommand command = new NpgsqlCommand(query, connection))
{
foreach (KeyValuePair<string, object> pair in parameters)
{
command.Parameters.AddWithValue(pair.Key, pair.Value ?? DBNull.Value);
}
connection.Open();
using (NpgsqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
{
int fieldCount = reader.FieldCount;
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
while (reader.Read())
{
Dictionary<string, object> row = new Dictionary<string, object>(fieldCount);
for (int i = 0; i < fieldCount; i++)
{
object value = reader.IsDBNull(i) ? null : reader.GetValue(i);
row.Add(reader.GetName(i), value);
}
rows.Add(row);
}
return rows.ToArray();
}
}
}
}
catch (NpgsqlException e)
{
throw new Exception(e.Message, e);
}
}
public static string EscapeString(string s)
{
if (s == null) return string.Empty;
return s.Replace("'", "''");
}
// Async методы для .NET 8.0
public static async Task ExecuteNonQueryAsync(string query, params KeyValuePair<string, object>[] parameters)
{
try
{
await using var connection = new NpgsqlConnection(connectionString);
await using var command = new NpgsqlCommand(query, connection);
foreach (var pair in parameters)
{
command.Parameters.AddWithValue(pair.Key, pair.Value ?? DBNull.Value);
}
await connection.OpenAsync();
await command.ExecuteNonQueryAsync();
}
catch (NpgsqlException e)
{
throw new Exception($"Database error: {e.Message}", e);
}
}
public static async Task<object> ExecuteScalarAsync(string query, params KeyValuePair<string, object>[] parameters)
{
try
{
await using var connection = new NpgsqlConnection(connectionString);
await using var command = new NpgsqlCommand(query, connection);
foreach (var pair in parameters)
{
command.Parameters.AddWithValue(pair.Key, pair.Value ?? DBNull.Value);
}
await connection.OpenAsync();
return await command.ExecuteScalarAsync();
}
catch (NpgsqlException e)
{
throw new Exception($"Database error: {e.Message}", e);
}
}
// Проверка подключения к БД с детальной диагностикой
public static async Task<(bool success, string error)> TestConnectionAsync()
{
try
{
await using var connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
bool isOpen = connection.State == ConnectionState.Open;
if (isOpen)
{
// Дополнительно проверим, что можем выполнить запрос
await using var cmd = new NpgsqlCommand("SELECT 1", connection);
await cmd.ExecuteScalarAsync();
return (true, "Connection successful");
}
return (false, $"Connection state: {connection.State}");
}
catch (Exception ex)
{
return (false, $"Connection failed: {ex.Message}");
}
}
}
}
Для проверке создать логин плагин (библиотека LoginPlugin) Добавить в зависимости PostgresConnector.dll Создать Login.cs
using System;
using System.Threading.Tasks;
using DarkRift;
using DarkRift.Server;
using PostgresConnector;
namespace LoginPlugin
{
public class Login : Plugin
{
public override bool ThreadSafe => true;
public override Version Version => new Version(1, 0, 0);
public Login(PluginLoadData pluginLoadData) : base(pluginLoadData)
{
// Читаем настройки из конфигурации, если есть
if (pluginLoadData.Settings != null)
{
string connectionString = pluginLoadData.Settings["ConnectionString"];
if (!string.IsNullOrEmpty(connectionString))
{
Connector.SetConnectionString(connectionString);
Logger.Info($"Using custom connection string from config");
}
}
// Инициализация плагина
_ = InitializeAsync();
}
private async Task InitializeAsync()
{
try
{
Logger.Info("Initializing PostgreSQL plugin...");
// Тестируем подключение к БД
var (connectionSuccessful, errorMessage) = await Connector.TestConnectionAsync();
if (!connectionSuccessful)
{
Logger.Error($"Failed to connect to PostgreSQL database: {errorMessage}");
Logger.Info("Please check:");
Logger.Info("1. PostgreSQL server is running");
Logger.Info("2. Database 'darkrift' exists");
Logger.Info("3. Username/password are correct");
Logger.Info("4. Connection string in Connector.cs or ConnectionString in Server.config");
return;
}
Logger.Info("Successfully connected to PostgreSQL database");
// Создаем таблицу users
await CreateUsersTableAsync();
Logger.Info("Users table created/verified successfully");
// Тестовая вставка данных
await TestDatabaseOperations();
Logger.Info("PostgreSQL plugin initialized successfully");
}
catch (Exception ex)
{
Logger.Error($"Failed to initialize PostgreSQL plugin: {ex.Message}");
}
}
// Создание таблицы users
private static async Task CreateUsersTableAsync()
{
const string createTableQuery = @"
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE
);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);";
await Connector.ExecuteNonQueryAsync(createTableQuery);
}
private async Task TestDatabaseOperations()
{
try
{
// Проверяем, есть ли уже тестовые данные
var userCount = await Connector.ExecuteScalarAsync("SELECT COUNT(*) FROM users");
Logger.Info($"Current users count: {userCount}");
// Если таблица пустая, добавляем тестового пользователя
if (Convert.ToInt32(userCount) == 0)
{
await Connector.ExecuteNonQueryAsync(
"INSERT INTO users (username, email, password_hash) VALUES (@username, @email, @password)",
new System.Collections.Generic.KeyValuePair<string, object>("@username", "test_user"),
new System.Collections.Generic.KeyValuePair<string, object>("@email", "test@darkrift.com"),
new System.Collections.Generic.KeyValuePair<string, object>("@password", "hashed_password_123")
);
Logger.Info("Test user created successfully");
}
}
catch (Exception ex)
{
Logger.Error($"Database test operations failed: {ex.Message}");
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Logger.Info("PostgreSQL plugin disposed");
}
base.Dispose(disposing);
}
}
}
Добавить dll в D:\Projects\DarkRift\unordinal\dr-build\Release\net8.0\Plugins PostgresConnector.dll Npgsql.dll Microsoft.Extensions.Logging.Abstractions.dll LoginPlugin.dll (Пакеты - пакет - Открыть папку в проводнике, чтобы получить dll для связки)
Комментарии
Комментариев пока нет.