Seregamil
18.12.2015, 20:01
Просьба не закидывать помидорками, я старался.
Подавая заявку в проф.лигу LightCode Cup возникла мысль, что, возможно, будет написание плагинов. Написать годный плагин на крестах за короткий промежуток времени я не способен, поэтому решил восстановить свою старую работу по какой-никакой попытке написания плагинов в среде .NET
И так. Данная разработка позволит вам писать плагины на C# и полноценно использовать их.
Функции на стороне сервера:
Вызывает метод плагина.
Параметры:
methodName - имя вызываемого метода
split[] - ключ для параметров
i - int32
f - float
s - string
c - char
{Float,_}:... - аргументы соответственно
Возвращаемые значения:
int32,
boolean,
float
Из-за неспособности AMX машины вернуть текстовый параметр пришлось создавать аналогичную предыдущей функцию.
Разница только в параметрах. Возвращается всегда 1.
Параметры:
methodName - имя вызываемого метода
split[] - ключ для параметров
i - int32
f - float
s - string
c - char
str[] - массив для записи текста
length - размер массива
{Float,_}:... - аргументы соответственно
Функции на стороне плагина:
Вызывает каллбэк по его названию и передает параметры.
Параметры:
string callback - название каллбэка
params object[] args - аргументы
Выводит текст в консоль
Параметры:
string text - текст =)
#include <a_samp>
native callDotnetMethod(methodName[], split[], {Float,_}:...);
native callDotnetMethodStr(methodName[], str[], len, split[], {Float,_}:...);
main(){
}
public OnGameModeInit() {
callDotnetMethod("onDotnetLoaded", "cf", 'v', 1.0);
new temp_int = callDotnetMethod("kernel.testINT", "ii", 10, 24);
printf("testINT returned: %i", temp_int);
new temp_bool = callDotnetMethod("kernel.testBOOL", "isi", 1, "boolean=)", 0);
printf("testBOOL returned: %i", temp_bool);
new temp_float = callDotnetMethod("kernel.testFLOAT", "ifcf", 10, 1.432, 'c', 242);
printf("testFLOAT returned: %f", temp_float);
new temp_str[ 16 ] ;
callDotnetMethodStr("kernel.testSTRING", temp_str, sizeof temp_str, "sss", "by", "Seregamil", "dotNET v1.0");
printf("testSTRING returned: %s", temp_str);
return true ;
}
forward onDotnetWasLoaded(str[]);
public onDotnetWasLoaded(str[]){
print(str);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace c_sharp
{
public class kernel
{
public static object onDotnetLoaded(params object[] args)
{
cpp.logwrite("dotnet-> onDotnetLoaded was called. ARGS:");
foreach (object arg in args)
{
cpp.logwrite(arg.ToString());
}
cpp.callRemoteCallback("onDotnetWasLoaded", "Hello! =)");
return true;
}
public static object testINT(params object[] args)
{
cpp.logwrite("dotnet-> testINT was called");
int a = Convert.ToInt32(args[0]);
int b = Convert.ToInt32(args[1]);
return a + b ;
}
public static object testBOOL(params object[] args)
{
cpp.logwrite("dotnet-> testBOOL was called.");
return false;
}
public static object testSTRING(params object[] args)
{
cpp.logwrite("dotnet-> testSTRING was called." );
foreach (object arg in args)
{
cpp.logwrite(string.Format("{0}: {1}",arg.GetType(), arg.ToString()));
}
return "blackJack prod.";
}
public static object testFLOAT(params object[] args)
{
cpp.logwrite("dotnet-> testFLOAT was called. ARGS:");
float result = 13.228f;
return result;
}
}
}
http://i.imgur.com/hwxbI32.png
Решение содержит 2 проекта. Первый на C#, второй на C++. Это COM сборка. При компиляции образуется один *.dll файл в нужной директории. В моем случае это S:\gta-o\plugins\.
Я использую VS2012 Express. Путь для вывода меняется в свойствах проекта dotnet
http://i.imgur.com/B6Li3Zn.png
Второй этап - нужно указать местоположение файла c_sharp.tlb.
7 строка проекта dotnet
#import "C:\Users\Seregamil\Documents\GitHub\.NET-plugin\source\c_sharp\bin\Debug\c_sharp.tlb" raw_interfaces_only
ВНИМАНИЕ. КОМПИЛЯЦИЯ ПРОЕКТА ПРОИЗВОДИТСЯ В РЕЖИМЕ АДМИНИСТРАТОРА
Всё. Вы готовы к разработке плагина на C#.
Все примеры я делал в файле kernel.cs, если хотите - меняйте, делайте зависимость и т.д. у вас нет ограничений.
Файл macro.cs содержит значения MAX_PLAYERS, MAX_VEHICLES etc., использовалось для написания и синхронизации плагина с клиентской частью игрока.
* Я не стал прикручивать SAMPGDK, т.к. мне он не нужен. Основная задача - написание плагинов, а не гейммодов. На офф.форуме есть плагин, позволяющий писать мод на C#
* Я умышленно отключил mono. Хотите писать плагин под Linux - пожалуйста, прикручивается это легко, достаточно поставить библиотеки и перекомпилировать проект.
Ссылка на разработку. Примеры прилагаются https://github.com/Seregamil/.NET-plugin
Огромное спасибо пользователям SDraw, Disinterpreter, g3o0or, Fallen A. за помощь.
Подавая заявку в проф.лигу LightCode Cup возникла мысль, что, возможно, будет написание плагинов. Написать годный плагин на крестах за короткий промежуток времени я не способен, поэтому решил восстановить свою старую работу по какой-никакой попытке написания плагинов в среде .NET
И так. Данная разработка позволит вам писать плагины на C# и полноценно использовать их.
Функции на стороне сервера:
Вызывает метод плагина.
Параметры:
methodName - имя вызываемого метода
split[] - ключ для параметров
i - int32
f - float
s - string
c - char
{Float,_}:... - аргументы соответственно
Возвращаемые значения:
int32,
boolean,
float
Из-за неспособности AMX машины вернуть текстовый параметр пришлось создавать аналогичную предыдущей функцию.
Разница только в параметрах. Возвращается всегда 1.
Параметры:
methodName - имя вызываемого метода
split[] - ключ для параметров
i - int32
f - float
s - string
c - char
str[] - массив для записи текста
length - размер массива
{Float,_}:... - аргументы соответственно
Функции на стороне плагина:
Вызывает каллбэк по его названию и передает параметры.
Параметры:
string callback - название каллбэка
params object[] args - аргументы
Выводит текст в консоль
Параметры:
string text - текст =)
#include <a_samp>
native callDotnetMethod(methodName[], split[], {Float,_}:...);
native callDotnetMethodStr(methodName[], str[], len, split[], {Float,_}:...);
main(){
}
public OnGameModeInit() {
callDotnetMethod("onDotnetLoaded", "cf", 'v', 1.0);
new temp_int = callDotnetMethod("kernel.testINT", "ii", 10, 24);
printf("testINT returned: %i", temp_int);
new temp_bool = callDotnetMethod("kernel.testBOOL", "isi", 1, "boolean=)", 0);
printf("testBOOL returned: %i", temp_bool);
new temp_float = callDotnetMethod("kernel.testFLOAT", "ifcf", 10, 1.432, 'c', 242);
printf("testFLOAT returned: %f", temp_float);
new temp_str[ 16 ] ;
callDotnetMethodStr("kernel.testSTRING", temp_str, sizeof temp_str, "sss", "by", "Seregamil", "dotNET v1.0");
printf("testSTRING returned: %s", temp_str);
return true ;
}
forward onDotnetWasLoaded(str[]);
public onDotnetWasLoaded(str[]){
print(str);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace c_sharp
{
public class kernel
{
public static object onDotnetLoaded(params object[] args)
{
cpp.logwrite("dotnet-> onDotnetLoaded was called. ARGS:");
foreach (object arg in args)
{
cpp.logwrite(arg.ToString());
}
cpp.callRemoteCallback("onDotnetWasLoaded", "Hello! =)");
return true;
}
public static object testINT(params object[] args)
{
cpp.logwrite("dotnet-> testINT was called");
int a = Convert.ToInt32(args[0]);
int b = Convert.ToInt32(args[1]);
return a + b ;
}
public static object testBOOL(params object[] args)
{
cpp.logwrite("dotnet-> testBOOL was called.");
return false;
}
public static object testSTRING(params object[] args)
{
cpp.logwrite("dotnet-> testSTRING was called." );
foreach (object arg in args)
{
cpp.logwrite(string.Format("{0}: {1}",arg.GetType(), arg.ToString()));
}
return "blackJack prod.";
}
public static object testFLOAT(params object[] args)
{
cpp.logwrite("dotnet-> testFLOAT was called. ARGS:");
float result = 13.228f;
return result;
}
}
}
http://i.imgur.com/hwxbI32.png
Решение содержит 2 проекта. Первый на C#, второй на C++. Это COM сборка. При компиляции образуется один *.dll файл в нужной директории. В моем случае это S:\gta-o\plugins\.
Я использую VS2012 Express. Путь для вывода меняется в свойствах проекта dotnet
http://i.imgur.com/B6Li3Zn.png
Второй этап - нужно указать местоположение файла c_sharp.tlb.
7 строка проекта dotnet
#import "C:\Users\Seregamil\Documents\GitHub\.NET-plugin\source\c_sharp\bin\Debug\c_sharp.tlb" raw_interfaces_only
ВНИМАНИЕ. КОМПИЛЯЦИЯ ПРОЕКТА ПРОИЗВОДИТСЯ В РЕЖИМЕ АДМИНИСТРАТОРА
Всё. Вы готовы к разработке плагина на C#.
Все примеры я делал в файле kernel.cs, если хотите - меняйте, делайте зависимость и т.д. у вас нет ограничений.
Файл macro.cs содержит значения MAX_PLAYERS, MAX_VEHICLES etc., использовалось для написания и синхронизации плагина с клиентской частью игрока.
* Я не стал прикручивать SAMPGDK, т.к. мне он не нужен. Основная задача - написание плагинов, а не гейммодов. На офф.форуме есть плагин, позволяющий писать мод на C#
* Я умышленно отключил mono. Хотите писать плагин под Linux - пожалуйста, прикручивается это легко, достаточно поставить библиотеки и перекомпилировать проект.
Ссылка на разработку. Примеры прилагаются https://github.com/Seregamil/.NET-plugin
Огромное спасибо пользователям SDraw, Disinterpreter, g3o0or, Fallen A. за помощь.