forked from teamnwah/openmw-tes3coop
[Server] Rework Plugin API, move Lua system to external library
Use LibFFI for Public & Timer APIs Use "PlayerId" type instead "unsigned short" Add GetPluginDir() function0.8.0-dev
parent
a9701028a2
commit
4ca5da5666
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by koncord on 09.01.19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
typedef std::variant<uint8_t,
|
||||
int8_t,
|
||||
uint16_t,
|
||||
int16_t,
|
||||
uint32_t,
|
||||
int32_t,
|
||||
uint64_t,
|
||||
int64_t,
|
||||
const char *,
|
||||
void *,
|
||||
float,
|
||||
double,
|
||||
bool> TArgVariant;
|
||||
typedef std::vector<TArgVariant> TArgsStore;
|
||||
|
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by koncord on 15.01.19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef X86_WIN64
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 RetType;
|
||||
#else
|
||||
typedef unsigned long long RetType;
|
||||
#endif
|
||||
#elif defined __x86_64__ && defined __ILP32__
|
||||
typedef unsigned long long RetType;
|
||||
#else
|
||||
typedef unsigned long RetType;
|
||||
#endif
|
||||
|
||||
typedef unsigned long long(*ScriptFunc)();
|
||||
typedef unsigned int PlayerId;
|
||||
|
||||
#define InvalidPID ((unsigned int) -1)
|
||||
|
||||
#if !defined __cplusplus
|
||||
#define bool uint8_t
|
||||
#endif
|
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by koncord on 12.01.19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Types.hpp"
|
||||
|
||||
template<typename... Types>
|
||||
using Callback = void (*)(Types...);
|
||||
|
||||
template<typename R>
|
||||
using FunctionEllipsis = R(*)(...);
|
||||
|
||||
template<size_t N>
|
||||
static constexpr unsigned int CallbackIndex(const char(&str)[N])
|
||||
{
|
||||
return Utils::hash(str);
|
||||
}
|
||||
|
||||
struct CallbackIdentity
|
||||
{
|
||||
const char* types;
|
||||
const unsigned int numargs;
|
||||
|
||||
constexpr bool matches(const char* types, const unsigned int N = 0) const
|
||||
{
|
||||
return N < numargs ? this->types[N] == types[N] && matches(types, N + 1) : this->types[N] == types[N];
|
||||
}
|
||||
|
||||
template<typename... Types>
|
||||
constexpr CallbackIdentity(Callback<Types...>) : types(TypeString<Types...>::value), numargs(sizeof(TypeString<Types...>::value) - 1) {}
|
||||
};
|
||||
|
||||
struct ScriptCallbackData
|
||||
{
|
||||
const char* name;
|
||||
const unsigned long long index;
|
||||
const CallbackIdentity callback;
|
||||
|
||||
template<size_t N>
|
||||
constexpr ScriptCallbackData(const char(&name)[N], CallbackIdentity _callback) : name(name), index(CallbackIndex(name)), callback(_callback) {}
|
||||
};
|
@ -0,0 +1,13 @@
|
||||
#include "Callbacks.hpp"
|
||||
#include "API/PublicFnAPI.hpp"
|
||||
#include <cstdarg>
|
||||
#include <iostream>
|
||||
#include <apps/openmw-mp/Player.hpp>
|
||||
#include <apps/openmw-mp/Networking.hpp>
|
||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||
|
||||
template<typename... Types>
|
||||
constexpr char TypeString<Types...>::value[];
|
||||
constexpr ScriptCallbackData Callbacks::callbacks[];
|
||||
|
||||
using namespace std;
|
@ -0,0 +1,105 @@
|
||||
#ifndef SCRIPTFUNCTIONS_HPP
|
||||
#define SCRIPTFUNCTIONS_HPP
|
||||
|
||||
#include <Script/Functions/Actors.h>
|
||||
#include <Script/Functions/Books.h>
|
||||
#include <Script/Functions/Cells.h>
|
||||
#include <Script/Functions/CharClass.h>
|
||||
#include <Script/Functions/Chat.h>
|
||||
#include <Script/Functions/Dialogue.h>
|
||||
#include <Script/Functions/Factions.h>
|
||||
#include <Script/Functions/GUI.h>
|
||||
#include <Script/Functions/Items.h>
|
||||
#include <Script/Functions/Mechanics.h>
|
||||
#include <Script/Functions/Miscellaneous.h>
|
||||
#include <Script/Functions/Objects.h>
|
||||
#include <Script/Functions/Positions.h>
|
||||
#include <Script/Functions/Public.h>
|
||||
#include <Script/Functions/Quests.h>
|
||||
#include <Script/Functions/RecordsDynamic.h>
|
||||
#include <Script/Functions/Shapeshift.h>
|
||||
#include <Script/Functions/Server.h>
|
||||
#include <Script/Functions/Settings.h>
|
||||
#include <Script/Functions/Spells.h>
|
||||
#include <Script/Functions/Stats.h>
|
||||
#include <Script/Functions/Timer.h>
|
||||
#include <Script/Functions/Worldstate.h>
|
||||
#include "Callback.hpp"
|
||||
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
|
||||
#ifndef __PRETTY_FUNCTION__
|
||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#define GET_PLAYER(pid, pl, retvalue) \
|
||||
pl = Players::getPlayer(pid); \
|
||||
if (player == 0) {\
|
||||
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "%s: Player with pid \'%d\' not found\n", __PRETTY_FUNCTION__, pid);\
|
||||
/*ScriptFunctions::StopServer(1);*/ \
|
||||
return retvalue;\
|
||||
}
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
static constexpr ScriptCallbackData callbacks[]{
|
||||
{"OnServerInit", Callback<>()},
|
||||
{"OnServerPostInit", Callback<>()},
|
||||
{"OnServerExit", Callback<bool>()},
|
||||
{"OnPlayerConnect", Callback<PlayerId>()},
|
||||
{"OnPlayerDisconnect", Callback<PlayerId>()},
|
||||
{"OnPlayerDeath", Callback<PlayerId>()},
|
||||
{"OnPlayerResurrect", Callback<PlayerId>()},
|
||||
{"OnPlayerCellChange", Callback<PlayerId>()},
|
||||
{"OnPlayerAttribute", Callback<PlayerId>()},
|
||||
{"OnPlayerSkill", Callback<PlayerId>()},
|
||||
{"OnPlayerLevel", Callback<PlayerId>()},
|
||||
{"OnPlayerBounty", Callback<PlayerId>()},
|
||||
{"OnPlayerReputation", Callback<PlayerId>()},
|
||||
{"OnPlayerEquipment", Callback<PlayerId>()},
|
||||
{"OnPlayerInventory", Callback<PlayerId>()},
|
||||
{"OnPlayerJournal", Callback<PlayerId>()},
|
||||
{"OnPlayerFaction", Callback<PlayerId>()},
|
||||
{"OnPlayerShapeshift", Callback<PlayerId>()},
|
||||
{"OnPlayerSpellbook", Callback<PlayerId>()},
|
||||
{"OnPlayerQuickKeys", Callback<PlayerId>()},
|
||||
{"OnPlayerTopic", Callback<PlayerId>()},
|
||||
{"OnPlayerDisposition", Callback<PlayerId>()},
|
||||
{"OnPlayerBook", Callback<PlayerId>()},
|
||||
{"OnPlayerItemUse", Callback<PlayerId>()},
|
||||
{"OnPlayerMiscellaneous", Callback<PlayerId>()},
|
||||
{"OnPlayerInput", Callback<PlayerId>()},
|
||||
{"OnPlayerRest", Callback<PlayerId>()},
|
||||
{"OnRecordDynamic", Callback<PlayerId>()},
|
||||
{"OnCellLoad", Callback<PlayerId, const char*>()},
|
||||
{"OnCellUnload", Callback<PlayerId, const char*>()},
|
||||
{"OnCellDeletion", Callback<const char*>()},
|
||||
{"OnContainer", Callback<PlayerId, const char*>()},
|
||||
{"OnDoorState", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectActivate", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectPlace", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectState", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectSpawn", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectDelete", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectLock", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectScale", Callback<PlayerId, const char*>()},
|
||||
{"OnObjectTrap", Callback<PlayerId, const char*>()},
|
||||
{"OnVideoPlay", Callback<PlayerId, const char*>()},
|
||||
{"OnActorList", Callback<PlayerId, const char*>()},
|
||||
{"OnActorEquipment", Callback<PlayerId, const char*>()},
|
||||
{"OnActorAI", Callback<PlayerId, const char*>()},
|
||||
{"OnActorDeath", Callback<PlayerId, const char*>()},
|
||||
{"OnActorCellChange", Callback<PlayerId, const char*>()},
|
||||
{"OnActorTest", Callback<PlayerId, const char*>()},
|
||||
{"OnPlayerSendMessage", Callback<PlayerId, const char*>()},
|
||||
{"OnPlayerEndCharGen", Callback<PlayerId>()},
|
||||
{"OnGUIAction", Callback<PlayerId, int, const char*>()},
|
||||
{"OnWorldKillCount", Callback<PlayerId>()},
|
||||
{"OnWorldMap", Callback<PlayerId>()},
|
||||
{"OnWorldWeather", Callback<PlayerId>() },
|
||||
{"OnMpNumIncrement", Callback<int>()},
|
||||
{"OnRequestPluginList", Callback<>()}
|
||||
};
|
||||
};
|
||||
|
||||
#endif //SCRIPTFUNCTIONS_HPP
|
@ -0,0 +1,149 @@
|
||||
//
|
||||
// Created by koncord on 09.01.19.
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include "FFI.hpp"
|
||||
|
||||
FFI::FFI(ScriptFunc func, char retFormat, const char *argFormat, ...)
|
||||
{
|
||||
std::va_list argList;
|
||||
va_start(argList, argFormat);
|
||||
|
||||
fnPtr = func;
|
||||
|
||||
setArguments(argFormat, argList);
|
||||
setRetType(retFormat);
|
||||
|
||||
va_end(argList);
|
||||
}
|
||||
|
||||
void FFI::setArguments(const std::string &format, va_list argList)
|
||||
{
|
||||
cifInitialized = false;
|
||||
va_list vaList;
|
||||
va_copy(vaList, argList);
|
||||
|
||||
resize(format.size());
|
||||
|
||||
for (size_t i = 0; i < format.size(); ++i)
|
||||
{
|
||||
switch (format[i])
|
||||
{
|
||||
case 'v':
|
||||
break;
|
||||
case 's': // const char*
|
||||
setArgument(i, (const char*) va_arg(vaList, const char*));
|
||||
break;
|
||||
case 'c':
|
||||
setArgument(i, (int8_t) va_arg(vaList, int));
|
||||
break;
|
||||
case 'C':
|
||||
setArgument(i, (uint8_t) va_arg(vaList, int));
|
||||
break;
|
||||
case 'h':
|
||||
setArgument(i, (int16_t) va_arg(vaList, int));
|
||||
break;
|
||||
case 'H':
|
||||
setArgument(i, (uint16_t) va_arg(vaList, int));
|
||||
break;
|
||||
case 'i':
|
||||
setArgument(i, va_arg(vaList, int32_t));
|
||||
break;
|
||||
case 'I':
|
||||
setArgument(i, va_arg(vaList, uint32_t));
|
||||
break;
|
||||
case 'l':
|
||||
setArgument(i, va_arg(vaList, int64_t));
|
||||
break;
|
||||
case 'L':
|
||||
setArgument(i, va_arg(vaList, uint64_t));
|
||||
break;
|
||||
case 'd':
|
||||
case 'f':
|
||||
setArgument(i, va_arg(vaList, double));
|
||||
break;
|
||||
case 'p':
|
||||
setArgument(i, va_arg(vaList, void*));
|
||||
break;
|
||||
case 'b': // bool
|
||||
setArgument(i, (bool) (va_arg(vaList, int) == 1));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(vaList);
|
||||
}
|
||||
|
||||
void FFI::setRetType(char type)
|
||||
{
|
||||
cifInitialized = false;
|
||||
retType = formatToFFIType(type);
|
||||
}
|
||||
|
||||
void FFI::setFunctionPtr(ScriptFunc func)
|
||||
{
|
||||
cifInitialized = false;
|
||||
fnPtr = func;
|
||||
}
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
ffi_type *FFI::formatToFFIType(char type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 'v':
|
||||
return CToFFIType<void>();
|
||||
case 's':
|
||||
return CToFFIType<const char *>();
|
||||
case 'c':
|
||||
return CToFFIType<int8_t>();
|
||||
case 'C':
|
||||
return CToFFIType<uint8_t>();
|
||||
case 'h':
|
||||
return CToFFIType<int16_t>();
|
||||
case 'H':
|
||||
return CToFFIType<uint16_t>();
|
||||
case 'i':
|
||||
return CToFFIType<int32_t>();
|
||||
case 'I':
|
||||
return CToFFIType<uint32_t>();
|
||||
case 'l':
|
||||
return CToFFIType<int64_t>();
|
||||
case 'L':
|
||||
return CToFFIType<uint64_t>();
|
||||
case 'f':
|
||||
case 'd':
|
||||
return CToFFIType<double>();
|
||||
case 'p':
|
||||
return CToFFIType<void *>();
|
||||
case 'b': // bool
|
||||
return CToFFIType<bool>();
|
||||
default:
|
||||
throw std::invalid_argument(std::string("unknown argument type \'") + type + '\'');
|
||||
}
|
||||
}
|
||||
|
||||
void FFI::resize(size_t size)
|
||||
{
|
||||
types.resize(size);
|
||||
ptrs.resize(size);
|
||||
argsStore.resize(size);
|
||||
}
|
||||
|
||||
RetType FFI::call()
|
||||
{
|
||||
if (!cifInitialized)
|
||||
{
|
||||
cifInitialized = true;
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, (unsigned int) types.size(), retType, types.data()) != FFI_OK)
|
||||
throw std::runtime_error("Whoops! Cannot prepare CIF!");
|
||||
}
|
||||
ffi_arg retVal;
|
||||
ffi_call(&cif, FFI_FN(fnPtr), &retVal, ptrs.data());
|
||||
return retVal;
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
//
|
||||
// Created by koncord on 09.01.19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <ffi.h>
|
||||
}
|
||||
#include <stdexcept>
|
||||
#include "ArgsStore.hpp"
|
||||
#include <Script/CTypes.h>
|
||||
class FFI
|
||||
{
|
||||
private:
|
||||
std::vector<ffi_type *> types;
|
||||
std::vector<void *> ptrs;
|
||||
TArgsStore argsStore;
|
||||
ffi_type *retType;
|
||||
bool cifInitialized;
|
||||
ffi_cif cif;
|
||||
ScriptFunc fnPtr;
|
||||
|
||||
void resize(size_t size);
|
||||
|
||||
template<typename T>
|
||||
constexpr ffi_type *CToFFIType()
|
||||
{
|
||||
if (std::is_same<T, bool>::value)
|
||||
return &ffi_type_sint8;
|
||||
if (std::is_same<T, void>::value)
|
||||
return &ffi_type_void;
|
||||
if (std::is_same<T, uint8_t>::value)
|
||||
return &ffi_type_uint8;
|
||||
if (std::is_same<T, int8_t>::value)
|
||||
return &ffi_type_sint8;
|
||||
if (std::is_same<T, uint16_t>::value)
|
||||
return &ffi_type_uint16;
|
||||
if (std::is_same<T, int16_t>::value)
|
||||
return &ffi_type_sint16;
|
||||
if (std::is_same<T, uint32_t>::value)
|
||||
return &ffi_type_uint32;
|
||||
if (std::is_same<T, int32_t>::value)
|
||||
return &ffi_type_sint32;
|
||||
if (std::is_same<T, uint64_t>::value)
|
||||
return &ffi_type_uint64;
|
||||
if (std::is_same<T, int64_t>::value)
|
||||
return &ffi_type_sint64;
|
||||
if (std::is_same<T, float>::value)
|
||||
return &ffi_type_float;
|
||||
if (std::is_same<T, double>::value)
|
||||
return &ffi_type_double;
|
||||
if (std::is_pointer<T>::value)
|
||||
return &ffi_type_pointer;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void setArgument(size_t index, const T &v)
|
||||
{
|
||||
types[index] = CToFFIType<T>();
|
||||
argsStore[index] = v;
|
||||
ptrs[index] = (void *) &std::get<T>(argsStore[index]);
|
||||
}
|
||||
ffi_type *formatToFFIType(char type);
|
||||
|
||||
protected:
|
||||
FFI() = default;
|
||||
public:
|
||||
explicit FFI(ScriptFunc func, char retFormat, const char *argFormat, ...);
|
||||
|
||||
void setArguments(const std::string &format, va_list argList);
|
||||
void setRetType(char type);
|
||||
void setFunctionPtr(ScriptFunc func);
|
||||
|
||||
RetType call();
|
||||
};
|
@ -1,323 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 08.05.16.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "LangLua.hpp"
|
||||
#include <Script/Script.hpp>
|
||||
#include <Script/Types.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
std::set<std::string> LangLua::packagePath;
|
||||
std::set<std::string> LangLua::packageCPath;
|
||||
|
||||
void setLuaPath(lua_State* L, const char* path, bool cpath = false)
|
||||
{
|
||||
string field = cpath ? "cpath" : "path";
|
||||
lua_getglobal(L, "package");
|
||||
|
||||
lua_getfield(L, -1, field.c_str());
|
||||
std::string cur_path = lua_tostring(L, -1);
|
||||
cur_path.append(";");
|
||||
cur_path.append(path);
|
||||
lua_pop(L, 1);
|
||||
lua_pushstring(L, cur_path.c_str());
|
||||
lua_setfield(L, -2, field.c_str());
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lib_t LangLua::GetInterface()
|
||||
{
|
||||
return reinterpret_cast<lib_t>(lua);
|
||||
}
|
||||
|
||||
LangLua::LangLua(lua_State *lua)
|
||||
{
|
||||
this->lua = lua;
|
||||
}
|
||||
|
||||
LangLua::LangLua()
|
||||
{
|
||||
lua = luaL_newstate();
|
||||
luaL_openlibs(lua); // load all lua std libs
|
||||
|
||||
std::string p, cp;
|
||||
for (auto& path : packagePath)
|
||||
p += path + ';';
|
||||
|
||||
for (auto& path : packageCPath)
|
||||
cp += path + ';';
|
||||
|
||||
setLuaPath(lua, p.c_str());
|
||||
setLuaPath(lua, cp.c_str(), true);
|
||||
|
||||
}
|
||||
|
||||
LangLua::~LangLua()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<unsigned int I, unsigned int F>
|
||||
struct Lua_dispatch_ {
|
||||
template<typename R, typename... Args>
|
||||
inline static R Lua_dispatch(lua_State*&& lua, Args&&... args) noexcept {
|
||||
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
|
||||
auto arg = luabridge::Stack<typename CharType<F_.func.types[I - 1]>::type>::get(lua, I);
|
||||
return Lua_dispatch_<I - 1, F>::template Lua_dispatch<R>(
|
||||
forward<lua_State*>(lua),
|
||||
arg,
|
||||
forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int F>
|
||||
struct Lua_dispatch_<0, F> {
|
||||
template<typename R, typename... Args>
|
||||
inline static R Lua_dispatch(lua_State*&&, Args&&... args) noexcept {
|
||||
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
|
||||
return reinterpret_cast<FunctionEllipsis<R>>(F_.func.addr)(forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<unsigned int I>
|
||||
static typename enable_if<ScriptFunctions::functions[I].func.ret == 'v', int>::type wrapper(lua_State* lua) noexcept {
|
||||
Lua_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template Lua_dispatch<void>(forward<lua_State*>(lua));
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<unsigned int I>
|
||||
static typename enable_if<ScriptFunctions::functions[I].func.ret != 'v', int>::type wrapper(lua_State* lua) noexcept {
|
||||
auto ret = Lua_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template Lua_dispatch<
|
||||
typename CharType<ScriptFunctions::functions[I].func.ret>::type>(forward<lua_State*>(lua));
|
||||
luabridge::Stack <typename CharType<ScriptFunctions::functions[I].func.ret>::type>::push (lua, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<unsigned int I>
|
||||
struct F_
|
||||
{
|
||||
static constexpr LuaFuctionData F{ScriptFunctions::functions[I].name, wrapper<I>};
|
||||
};
|
||||
|
||||
|
||||
template<> struct F_<0> { static constexpr LuaFuctionData F{"CreateTimer", LangLua::CreateTimer}; };
|
||||
template<> struct F_<1> { static constexpr LuaFuctionData F{"CreateTimerEx", LangLua::CreateTimerEx}; };
|
||||
template<> struct F_<2> { static constexpr LuaFuctionData F{"MakePublic", LangLua::MakePublic}; };
|
||||
template<> struct F_<3> { static constexpr LuaFuctionData F{"CallPublic", LangLua::CallPublic}; };
|
||||
|
||||
#ifdef __arm__
|
||||
template<std::size_t... Is>
|
||||
struct indices {};
|
||||
template<std::size_t N, std::size_t... Is>
|
||||
struct build_indices : build_indices<N-1, N-1, Is...> {};
|
||||
template<std::size_t... Is>
|
||||
struct build_indices<0, Is...> : indices<Is...> {};
|
||||
template<std::size_t N>
|
||||
using IndicesFor = build_indices<N>;
|
||||
|
||||
template<size_t... Indices>
|
||||
LuaFuctionData *functions(indices<Indices...>)
|
||||
{
|
||||
|
||||
static LuaFuctionData functions_[sizeof...(Indices)]{
|
||||
F_<Indices>::F...
|
||||
};
|
||||
|
||||
static_assert(
|
||||
sizeof(functions_) / sizeof(functions_[0]) ==
|
||||
sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]),
|
||||
"Not all functions have been mapped to Lua");
|
||||
|
||||
return functions_;
|
||||
}
|
||||
#else
|
||||
template<unsigned int I>
|
||||
struct C
|
||||
{
|
||||
constexpr static void Fn(LuaFuctionData *functions_)
|
||||
{
|
||||
functions_[I] = F_<I>::F;
|
||||
C<I - 1>::Fn(functions_);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct C<0>
|
||||
{
|
||||
constexpr static void Fn(LuaFuctionData *functions_)
|
||||
{
|
||||
functions_[0] = F_<0>::F;
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t LastI>
|
||||
LuaFuctionData *functions()
|
||||
{
|
||||
|
||||
static LuaFuctionData functions_[LastI];
|
||||
C<LastI - 1>::Fn(functions_);
|
||||
|
||||
static_assert(
|
||||
sizeof(functions_) / sizeof(functions_[0]) ==
|
||||
sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]),
|
||||
"Not all functions have been mapped to Lua");
|
||||
|
||||
return functions_;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LangLua::LoadProgram(const char *filename)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if ((err =luaL_loadfile(lua, filename)) != 0)
|
||||
throw runtime_error("Lua script " + string(filename) + " error (" + to_string(err) + "): \"" +
|
||||
string(lua_tostring(lua, -1)) + "\"");
|
||||
|
||||
constexpr auto functions_n = sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]);
|
||||
|
||||
#if __arm__
|
||||
LuaFuctionData *functions_ = functions(IndicesFor<functions_n>{});
|
||||
#else
|
||||
LuaFuctionData *functions_ = functions<sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0])>();
|
||||
#endif
|
||||
luabridge::Namespace tes3mp = luabridge::getGlobalNamespace(lua).beginNamespace("tes3mp");
|
||||
|
||||
for (unsigned i = 0; i < functions_n; i++)
|
||||
tes3mp.addCFunction(functions_[i].name, functions_[i].func);
|
||||
|
||||
tes3mp.endNamespace();
|
||||
|
||||
if ((err = lua_pcall(lua, 0, 0, 0)) != 0) // Run once script for load in memory.
|
||||
throw runtime_error("Lua script " + string(filename) + " error (" + to_string(err) + "): \"" +
|
||||
string(lua_tostring(lua, -1)) + "\"");
|
||||
}
|
||||
|
||||
int LangLua::FreeProgram()
|
||||
{
|
||||
lua_close(lua);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LangLua::IsCallbackPresent(const char *name)
|
||||
{
|
||||
return luabridge::getGlobal(lua, name).isFunction();
|
||||
}
|
||||
|
||||
boost::any LangLua::Call(const char *name, const char *argl, int buf, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
va_start(vargs, buf);
|
||||
|
||||
int n_args = (int)(strlen(argl));
|
||||
|
||||
lua_getglobal(lua, name);
|
||||
|
||||
for (int index = 0; index < n_args; index++)
|
||||
{
|
||||
switch (argl[index])
|
||||
{
|
||||
case 'i':
|
||||
luabridge::Stack<unsigned int>::push(lua,va_arg(vargs, unsigned int));
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
luabridge::Stack<signed int>::push(lua,va_arg(vargs, signed int));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
luabridge::Stack<unsigned long long>::push(lua, va_arg(vargs, unsigned long long));
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
luabridge::Stack<signed long long>::push(lua, va_arg(vargs, signed long long));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
luabridge::Stack<double>::push(lua, va_arg(vargs, double));
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
luabridge::Stack<void*>::push(lua, va_arg(vargs, void*));
|
||||
break;
|
||||
|
||||
case 's':
|
||||
luabridge::Stack<const char*>::push(lua, va_arg(vargs, const char*));
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
luabridge::Stack<bool>::push(lua, (bool) va_arg(vargs, int));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error(std::string("C++ call: Unknown argument identifier ") + argl[index]);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(vargs);
|
||||
|
||||
luabridge::LuaException::pcall(lua, n_args, 1);
|
||||
return boost::any(luabridge::LuaRef::fromStack(lua, -1));
|
||||
}
|
||||
|
||||
boost::any LangLua::Call(const char *name, const char *argl, const std::vector<boost::any> &args)
|
||||
{
|
||||
int n_args = (int)(strlen(argl));
|
||||
|
||||
lua_getglobal(lua, name);
|
||||
|
||||
for (int index = 0; index < n_args; index++)
|
||||
{
|
||||
switch (argl[index])
|
||||
{
|
||||
case 'i':
|
||||
luabridge::Stack<unsigned int>::push(lua, boost::any_cast<unsigned int>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
luabridge::Stack<signed int>::push(lua, boost::any_cast<signed int>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
luabridge::Stack<unsigned long long>::push(lua, boost::any_cast<unsigned long long>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
luabridge::Stack<signed long long>::push(lua, boost::any_cast<signed long long>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
luabridge::Stack<double>::push(lua, boost::any_cast<double>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
luabridge::Stack<void *>::push(lua, boost::any_cast<void *>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 's':
|
||||
luabridge::Stack<const char *>::push(lua, boost::any_cast<const char *>(args.at(index)));
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
luabridge::Stack<bool>::push(lua, boost::any_cast<int>(args.at(index)));
|
||||
break;
|
||||
default:
|
||||
throw runtime_error(std::string("Lua call: Unknown argument identifier ") + argl[index]);
|
||||
}
|
||||
}
|
||||
|
||||
luabridge::LuaException::pcall(lua, n_args, 1);
|
||||
return boost::any(luabridge::LuaRef::fromStack(lua, -1));
|
||||
}
|
||||
|
||||
void LangLua::AddPackagePath(const std::string& path)
|
||||
{
|
||||
packagePath.emplace(path);
|
||||
}
|
||||
|
||||
void LangLua::AddPackageCPath(const std::string& path)
|
||||
{
|
||||
packageCPath.emplace(path);
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 08.05.16.
|
||||
//
|
||||
|
||||
#ifndef PLUGINSYSTEM3_LANGLUA_HPP
|
||||
#define PLUGINSYSTEM3_LANGLUA_HPP
|
||||
|
||||
#include "lua.hpp"
|
||||
|
||||
#include <extern/LuaBridge/LuaBridge.h>
|
||||
#include <LuaBridge.h>
|
||||
#include <set>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include "../ScriptFunction.hpp"
|
||||
#include "../Language.hpp"
|
||||
|
||||
struct LuaFuctionData
|
||||
{
|
||||
const char* name;
|
||||
lua_CFunction func;
|
||||
};
|
||||
|
||||
class LangLua: public Language
|
||||
{
|
||||
public:
|
||||
virtual lib_t GetInterface() override;
|
||||
lua_State *lua;
|
||||
public:
|
||||
LangLua();
|
||||
LangLua(lua_State *lua);
|
||||
~LangLua();
|
||||
|
||||
static void AddPackagePath(const std::string &path);
|
||||
static void AddPackageCPath(const std::string &path);
|
||||
|
||||
static int MakePublic(lua_State *lua) noexcept;
|
||||
static int CallPublic(lua_State *lua);
|
||||
|
||||
static int CreateTimer(lua_State *lua) noexcept;
|
||||
static int CreateTimerEx(lua_State *lua);
|
||||
|
||||
virtual void LoadProgram(const char *filename) override;
|
||||
virtual int FreeProgram() override;
|
||||
virtual bool IsCallbackPresent(const char *name) override;
|
||||
virtual boost::any Call(const char *name, const char *argl, int buf, ...) override;
|
||||
virtual boost::any Call(const char *name, const char *argl, const std::vector<boost::any> &args) override;
|
||||
private:
|
||||
static std::set<std::string> packageCPath;
|
||||
static std::set<std::string> packagePath;
|
||||
};
|
||||
|
||||
|
||||
#endif //PLUGINSYSTEM3_LANGLUA_HPP
|
@ -1,184 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 09.05.16.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "LangLua.hpp"
|
||||
#include <Script/API/TimerAPI.hpp>
|
||||
#include <Script/API/PublicFnAPI.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
inline vector<boost::any> DefToVec(lua_State *lua, const string &types, int args_begin, int args_n)
|
||||
{
|
||||
vector<boost::any> args;
|
||||
|
||||
for (int i = args_begin; i < args_n + args_begin; i++)
|
||||
{
|
||||
switch (types[i - args_begin])
|
||||
{
|
||||
case 'i':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<unsigned int>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<signed int>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
/*case 'l':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<unsigned long long>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<signed long long>::get(lua, i));
|
||||
break;
|
||||
}*/
|
||||
|
||||
case 'f':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<double>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<const char*>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
stringstream ssErr;
|
||||
ssErr << "Lua: Unknown argument identifier" << "\"" << types[i] << "\"" << endl;
|
||||
throw std::runtime_error(ssErr.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
int LangLua::MakePublic(lua_State *lua) noexcept
|
||||
{
|
||||
const char * callback = luabridge::Stack<const char*>::get(lua, 1);
|
||||
const char * name = luabridge::Stack<const char*>::get(lua, 2);
|
||||
char ret_type = luabridge::Stack<char>::get(lua, 3);
|
||||
const char * def = luabridge::Stack<const char*>::get(lua, 4);
|
||||
|
||||
Public::MakePublic(callback, lua, name, ret_type, def);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int LangLua::CallPublic(lua_State *lua)
|
||||
{
|
||||
const char * name = luabridge::Stack<const char*>::get(lua, 1);
|
||||
|
||||
int args_n = lua_gettop(lua) - 1;
|
||||
|
||||
string types = Public::GetDefinition(name);
|
||||
|
||||
if (args_n != (long)types.size())
|
||||
throw invalid_argument("Script call: Number of arguments does not match definition");
|
||||
|
||||
vector<boost::any> args = DefToVec(lua, types, 2, args_n);
|
||||
|
||||
boost::any result = Public::Call(&name[0], args);
|
||||
if (result.empty())
|
||||
return 0;
|
||||
|
||||
auto retTypeHash = result.type().hash_code();
|
||||
|
||||
if (retTypeHash == typeid(signed int).hash_code())
|
||||
luabridge::Stack<signed int>::push(lua, boost::any_cast<signed int>(result));
|
||||
else if (retTypeHash == typeid(unsigned int).hash_code())
|
||||
luabridge::Stack<unsigned int>::push(lua, boost::any_cast<unsigned int>(result));
|
||||
else if (retTypeHash == typeid(double).hash_code())
|
||||
luabridge::Stack<double>::push(lua, boost::any_cast<double>(result));
|
||||
else if (retTypeHash == typeid(const char*).hash_code())
|
||||
luabridge::Stack<const char*>::push(lua, boost::any_cast<const char*>(result));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LangLua::CreateTimer(lua_State *lua) noexcept
|
||||
{
|
||||
|
||||
const char * callback= luabridge::Stack<const char*>::get(lua, 1);
|
||||
int msec = luabridge::Stack<int>::get(lua, 2);
|
||||
|
||||
int id = mwmp::TimerAPI::CreateTimerLua(lua, callback, msec, "", vector<boost::any>());
|
||||
luabridge::push(lua, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LangLua::CreateTimerEx(lua_State *lua)
|
||||
{
|
||||
const char * callback = luabridge::Stack<const char*>::get(lua, 1);
|
||||
int msec = luabridge::Stack<int>::get(lua, 2);
|
||||
|
||||
const char * types = luabridge::Stack<const char*>::get(lua, 3);
|
||||
|
||||
int args_n = (int)lua_strlen(lua, 3);
|
||||
|
||||
vector<boost::any> args;
|
||||
|
||||
for (int i = 4; i < args_n + 4; i++)
|
||||
{
|
||||
switch (types[i - 4])
|
||||
{
|
||||
case 'i':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<unsigned int>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<signed int>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
/*case 'l':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<unsigned long long>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<signed long long>::get(lua, i));
|
||||
break;
|
||||
}*/
|
||||
|
||||
case 'f':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<double>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
args.emplace_back(luabridge::Stack<const char*>::get(lua, i));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
stringstream ssErr;
|
||||
ssErr << "Lua: Unknown argument identifier" << "\"" << types[i] << "\"" << endl;
|
||||
throw std::runtime_error(ssErr.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int id = mwmp::TimerAPI::CreateTimerLua(lua, callback, msec, types, args);
|
||||
luabridge::push(lua, id);
|
||||
return 1;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 09.05.16.
|
||||
//
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
#include "LangNative.hpp"
|
||||
#include <Script/SystemInterface.hpp>
|
||||
#include <Script/Script.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template<typename R>
|
||||
bool SetScript(lib_t lib, const char *name, R value)
|
||||
{
|
||||
SystemInterface<R *> result(lib, name);
|
||||
|
||||
if (result)
|
||||
*result.result = value;
|
||||
|
||||
return result.operator bool();
|
||||
}
|
||||
|
||||
void LangNative::LoadProgram(const char *filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "rb");
|
||||
|
||||
if (!file)
|
||||
throw runtime_error("Script not found: " + string(filename));
|
||||
|
||||
fclose(file);
|
||||
|
||||
#ifdef _WIN32
|
||||
lib = LoadLibrary(filename);
|
||||
#else
|
||||
lib = dlopen(filename, RTLD_LAZY);
|
||||
#endif
|
||||
|
||||
if (!lib)
|
||||
throw runtime_error("Was not able to load C++ script: " + string(filename));
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
const char *prefix = SystemInterface<const char *>(lib, "prefix").result;
|
||||
string pf(prefix);
|
||||
|
||||
for (const auto &function : ScriptFunctions::functions)
|
||||
if (!SetScript(lib, string(pf + function.name).c_str(), function.func.addr))
|
||||
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Script function pointer not found: %s", function.name);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FreeProgram();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
int LangNative::FreeProgram()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(lib);
|
||||
#else
|
||||
dlclose(lib);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool LangNative::IsCallbackPresent(const char *name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::any LangNative::Call(const char *name, const char *argl, int buf, ...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
boost::any LangNative::Call(const char *name, const char *argl, const std::vector<boost::any> &args)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
lib_t LangNative::GetInterface()
|
||||
{
|
||||
return lib;
|
||||
}
|
||||
|
||||
|
||||
LangNative::LangNative(): lib(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LangNative::~LangNative()
|
||||
{
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 09.05.16.
|
||||
//
|
||||
|
||||
#ifndef PLUGINSYSTEM3_LANGNATIVE_HPP
|
||||
#define PLUGINSYSTEM3_LANGNATIVE_HPP
|
||||
|
||||
|
||||
#include <Script/Language.hpp>
|
||||
#include <Script/SystemInterface.hpp>
|
||||
|
||||
class LangNative : public Language
|
||||
{
|
||||
lib_t lib;
|
||||
public:
|
||||
virtual lib_t GetInterface() override;
|
||||
LangNative();
|
||||
~LangNative();
|
||||
virtual void LoadProgram(const char *filename) override;
|
||||
virtual int FreeProgram() override;
|
||||
virtual bool IsCallbackPresent(const char *name) override;
|
||||
virtual boost::any Call(const char *name, const char *argl, int buf, ...) override;
|
||||
virtual boost::any Call(const char *name, const char *argl, const std::vector<boost::any> &args) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //PLUGINSYSTEM3_LANGNATIVE_HPP
|
@ -1,28 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 19.03.16.
|
||||
//
|
||||
|
||||
#ifndef PLUGINSYSTEM3_LANGUAGE_HPP
|
||||
#define PLUGINSYSTEM3_LANGUAGE_HPP
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <vector>
|
||||
|
||||
class Language
|
||||
{
|
||||
public:
|
||||
virtual ~Language(){}
|
||||
virtual void LoadProgram(const char* filename) = 0;
|
||||
virtual int FreeProgram() = 0;
|
||||
virtual bool IsCallbackPresent(const char* name) = 0;
|
||||
virtual boost::any Call(const char* name, const char* argl, int buf, ...) = 0;
|
||||
virtual boost::any Call(const char* name, const char* argl, const std::vector<boost::any>& args) = 0;
|
||||
|
||||
virtual lib_t GetInterface() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //PLUGINSYSTEM3_LANGUAGE_HPP
|
@ -0,0 +1,85 @@
|
||||
//
|
||||
// Created by koncord on 12.01.19.
|
||||
//
|
||||
|
||||
#include "Plugin.hpp"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
Plugin::PluginList Plugin::plugins;
|
||||
//constexpr ScriptCallbackData Plugin::callbacks[];
|
||||
|
||||
static Plugin* scriptTmpPtr; // hack for RegisterEvent
|
||||
|
||||
Plugin::Plugin(const std::string &pluginName)
|
||||
{
|
||||
lib = OpenLibrary(pluginName.c_str());
|
||||
|
||||
if (!lib)
|
||||
throw std::invalid_argument(std::string("Plugin ") + pluginName + " not found.");
|
||||
|
||||
PluginInit = SystemInterface<decltype(PluginInit)>(lib, "PluginInit").result;
|
||||
if (!PluginInit)
|
||||
throw std::runtime_error("\"void PluginInit(int pluginId)\" not implemented by plugin");
|
||||
|
||||
PluginFree = SystemInterface<decltype(PluginFree)>(lib, "PluginFree").result;
|
||||
if (!PluginFree)
|
||||
throw std::runtime_error("\"void PluginFree()\" not implemented");
|
||||
}
|
||||
|
||||
Plugin::~Plugin()
|
||||
{
|
||||
PluginFree();
|
||||
CloseLibrary(lib);
|
||||
}
|
||||
|
||||
bool Plugin::LoadPlugin(const std::string &plugin)
|
||||
{
|
||||
auto script = std::make_unique<Plugin>(plugin);
|
||||
scriptTmpPtr = script.get(); // needs for RegisterEvent
|
||||
|
||||
bool result = script->PluginInit() == 1;
|
||||
|
||||
scriptTmpPtr = nullptr; // reset value for safety
|
||||
|
||||
if (result)
|
||||
{
|
||||
plugins.push_back(std::move(script));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Plugin::LoadPlugins(const std::vector<std::string> &pluginsList)
|
||||
{
|
||||
for(const auto &plugin : pluginsList)
|
||||
LoadPlugin(plugin);
|
||||
}
|
||||
|
||||
static std::string moddir;
|
||||
|
||||
void Plugin::SetModDir(const std::string &_moddir)
|
||||
{
|
||||
if (moddir.empty()) // do not allow to change in runtime
|
||||
moddir = _moddir;
|
||||
}
|
||||
|
||||
const char* Plugin::GetModDir()
|
||||
{
|
||||
return moddir.c_str();
|
||||
}
|
||||
|
||||
static std::string plugindir;
|
||||
|
||||
void Plugin::SetPluginDir(const std::string &pluginDir)
|
||||
{
|
||||
if (plugindir.empty()) // do not allow to change in runtime
|
||||
plugindir = pluginDir;
|
||||
}
|
||||
|
||||
const char *Plugin::GetPluginDir()
|
||||
{
|
||||
return plugindir.c_str();
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
//
|
||||
// Created by koncord on 12.01.19.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SystemInterface.hpp"
|
||||
#include "Callbacks.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class Plugin: Callbacks
|
||||
{
|
||||
private:
|
||||
lib_t lib;
|
||||
void (*PluginFree)();
|
||||
int (*PluginInit)();
|
||||
|
||||
typedef std::vector<std::unique_ptr<Plugin>> PluginList;
|
||||
std::unordered_map<unsigned int, FunctionEllipsis<void>> callbacks_;
|
||||
|
||||
static PluginList plugins;
|
||||
|
||||
public:
|
||||
explicit Plugin(const std::string &pluginName);
|
||||
~Plugin();
|
||||
Plugin(const Plugin&) = delete;
|
||||
Plugin& operator=(const Plugin&) = delete;
|
||||
|
||||
static bool LoadPlugin(const std::string &plugin);
|
||||
static void LoadPlugins(const std::vector<std::string> &pluginsList);
|
||||
static void SetModDir(const std::string &moddir);
|
||||
static const char* GetModDir();
|
||||
static void SetPluginDir(const std::string &pluginDir);
|
||||
static const char* GetPluginDir();
|
||||
|
||||
static constexpr ScriptCallbackData const& CallBackData(const unsigned int I, const unsigned int N = 0)
|
||||
{
|
||||
return callbacks[N].index == I ? callbacks[N] : CallBackData(I, N + 1);
|
||||
}
|
||||
|
||||
template<unsigned int I, bool B = false, typename... Args>
|
||||
static unsigned int Call(Args&&... args)
|
||||
{
|
||||
constexpr ScriptCallbackData const& data = CallBackData(I);
|
||||
static_assert(data.callback.matches(TypeString<typename std::remove_reference<Args>::type...>::value),
|
||||
"Wrong number or types of arguments");
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
for (auto& plugin : plugins)
|
||||
{
|
||||
if (!plugin->callbacks_.count(I))
|
||||
plugin->callbacks_.emplace(I, SystemInterface<FunctionEllipsis<void>>(plugin->lib, data.name).result);
|
||||
|
||||
auto callback = plugin->callbacks_[I];
|
||||
|
||||
if (!callback)
|
||||
continue;
|
||||
|
||||
(callback)(std::forward<Args>(args)...);
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
};
|
@ -1,108 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 19.03.16.
|
||||
//
|
||||
|
||||
#include "Script.hpp"
|
||||
#include "LangNative/LangNative.hpp"
|
||||
|
||||
#if defined (ENABLE_LUA)
|
||||
#include "LangLua/LangLua.hpp"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
Script::ScriptList Script::scripts;
|
||||
std::string Script::moddir;
|
||||
|
||||
Script::Script(const char *path)
|
||||
{
|
||||
FILE *file = fopen(path, "rb");
|
||||
|
||||
if (!file)
|
||||
throw runtime_error("Script not found: " + string(path));
|
||||
|
||||
fclose(file);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (strstr(path, ".dll"))
|
||||
#else
|
||||
if (strstr(path, ".so"))
|
||||
#endif
|
||||
{
|
||||
script_type = SCRIPT_CPP;
|
||||
lang = new LangNative();
|
||||
}
|
||||
#if defined (ENABLE_LUA)
|
||||
else if (strstr(path, ".lua") || strstr(path, ".t"))
|
||||
{
|
||||
lang = new LangLua();
|
||||
script_type = SCRIPT_LUA;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw runtime_error("Script type not recognized: " + string(path));
|
||||
|
||||
try
|
||||
{
|
||||
lang->LoadProgram(path);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
lang->FreeProgram();
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Script::~Script()
|
||||
{
|
||||
lang->FreeProgram();
|
||||
|
||||
delete lang;
|
||||
}
|
||||
|
||||
void Script::LoadScripts(char *scripts, const char *base)
|
||||
{
|
||||
char *token = strtok(scripts, ",");
|
||||
|
||||
try
|
||||
{
|
||||
while (token)
|
||||
{
|
||||
char path[4096];
|
||||
snprintf(path, sizeof(path), Utils::convertPath("%s/%s/%s").c_str(), base, "scripts", token);
|
||||
Script::scripts.emplace_back(new Script(path));
|
||||
token = strtok(nullptr, ",");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
UnloadScripts();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void Script::UnloadScripts()
|
||||
{
|
||||
//Public::DeleteAll();
|
||||
scripts.clear();
|
||||
}
|
||||
|
||||
void Script::LoadScript(const char *script, const char *base)
|
||||
{
|
||||
char path[4096];
|
||||
snprintf(path, sizeof(path), Utils::convertPath("%s/%s/%s").c_str(), base, "scripts", script);
|
||||
Script::scripts.emplace_back(new Script(path));
|
||||
}
|
||||
|
||||
void Script::SetModDir(const std::string &moddir)
|
||||
{
|
||||
if (Script::moddir.empty()) // do not allow to change in runtime
|
||||
Script::moddir = moddir;
|
||||
}
|
||||
|
||||
const char* Script::GetModDir()
|
||||
{
|
||||
return moddir.c_str();
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 19.03.16.
|
||||
//
|
||||
|
||||
#ifndef PLUGINSYSTEM3_SCRIPT_HPP
|
||||
#define PLUGINSYSTEM3_SCRIPT_HPP
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
#include "Types.hpp"
|
||||
#include "SystemInterface.hpp"
|
||||
#include "ScriptFunction.hpp"
|
||||
#include "ScriptFunctions.hpp"
|
||||
#include "Language.hpp"
|
||||
|
||||
#include "Networking.hpp"
|
||||
|
||||
class Script : private ScriptFunctions
|
||||
{
|
||||
// http://imgur.com/hU0N4EH
|
||||
private:
|
||||
|
||||
Language *lang;
|
||||
|
||||
enum
|
||||
{
|
||||
SCRIPT_CPP,
|
||||
SCRIPT_LUA
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
R GetScript(const char *name)
|
||||
{
|
||||
if (script_type == SCRIPT_CPP)
|
||||
{
|
||||
return SystemInterface<R>(lang->GetInterface(), name).result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return reinterpret_cast<R>(lang->IsCallbackPresent(name));
|
||||
}
|
||||
}
|
||||
|
||||
int script_type;
|
||||
std::unordered_map<unsigned int, FunctionEllipsis<void>> callbacks_;
|
||||
|
||||
typedef std::vector<std::unique_ptr<Script>> ScriptList;
|
||||
static ScriptList scripts;
|
||||
|
||||
Script(const char *path);
|
||||
|
||||
Script(const Script&) = delete;
|
||||
Script& operator=(const Script&) = delete;
|
||||
|
||||
protected:
|
||||
static std::string moddir;
|
||||
public:
|
||||
~Script();
|
||||
|
||||
static void LoadScript(const char *script, const char* base);
|
||||
static void LoadScripts(char* scripts, const char* base);
|
||||
static void UnloadScripts();
|
||||
static void SetModDir(const std::string &moddir);
|
||||
static const char* GetModDir();
|
||||
|
||||
static constexpr ScriptCallbackData const& CallBackData(const unsigned int I, const unsigned int N = 0) {
|
||||
return callbacks[N].index == I ? callbacks[N] : CallBackData(I, N + 1);
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static constexpr unsigned int CallbackIdentity(const char(&str)[N])
|
||||
{
|
||||
return Utils::hash(str);
|
||||
}
|
||||
|
||||
template<unsigned int I, bool B = false, typename... Args>
|
||||
static unsigned int Call(Args&&... args) {
|
||||
constexpr ScriptCallbackData const& data = CallBackData(I);
|
||||
static_assert(data.callback.matches(TypeString<typename std::remove_reference<Args>::type...>::value),
|
||||
"Wrong number or types of arguments");
|
||||
|
||||
unsigned int count = 0;
|
||||
|
||||
for (auto& script : scripts)
|
||||
{
|
||||
if (!script->callbacks_.count(I))
|
||||
script->callbacks_.emplace(I, script->GetScript<FunctionEllipsis<void>>(data.name));
|
||||
|
||||
auto callback = script->callbacks_[I];
|
||||
|
||||
if (!callback)
|
||||
continue;
|
||||
|
||||
if (script->script_type == SCRIPT_CPP)
|
||||
(callback)(std::forward<Args>(args)...);
|
||||
#if defined (ENABLE_LUA)
|
||||
else if (script->script_type == SCRIPT_LUA)
|
||||
{
|
||||
try
|
||||
{
|
||||
script->lang->Call(data.name, data.callback.types, B, std::forward<Args>(args)...);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, e.what());
|
||||
|
||||
if (!mwmp::Networking::getPtr()->getScriptErrorIgnoringState())
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //PLUGINSYSTEM3_SCRIPT_HPP
|
@ -1,73 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 23.01.16.
|
||||
//
|
||||
|
||||
#include<iostream>
|
||||
#include <stdexcept>
|
||||
#include "ScriptFunction.hpp"
|
||||
|
||||
#if defined (ENABLE_LUA)
|
||||
#include "LangLua/LangLua.hpp"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
ScriptFunction::ScriptFunction(ScriptFunc fCpp,char ret_type, const string &def) :
|
||||
fCpp(fCpp), ret_type(ret_type), def(def), script_type(SCRIPT_CPP)
|
||||
{
|
||||
|
||||
}
|
||||
#if defined (ENABLE_LUA)
|
||||
ScriptFunction::ScriptFunction(const ScriptFuncLua &fLua, lua_State *lua, char ret_type, const std::string &def) :
|
||||
fLua({lua, fLua}), ret_type(ret_type), def(def), script_type(SCRIPT_LUA)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ScriptFunction::~ScriptFunction()
|
||||
{
|
||||
#if defined (ENABLE_LUA)
|
||||
if (script_type == SCRIPT_LUA)
|
||||
fLua.name.~ScriptFuncLua();
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::any ScriptFunction::Call(const vector<boost::any> &args)
|
||||
{
|
||||
boost::any result;
|
||||
|
||||
if (def.length() != args.size())
|
||||
throw runtime_error("Script call: Number of arguments does not match definition");
|
||||
#if defined (ENABLE_LUA)
|
||||
else if (script_type == SCRIPT_LUA)
|
||||
{
|
||||
LangLua langLua(fLua.lua);
|
||||
boost::any any = langLua.Call(fLua.name.c_str(), def.c_str(), args);
|
||||
|
||||
switch (ret_type)
|
||||
{
|
||||
case 'i':
|
||||
result = boost::any_cast<luabridge::LuaRef>(any).cast<unsigned int>();
|
||||
break;
|
||||
case 'q':
|
||||
result = boost::any_cast<luabridge::LuaRef>(any).cast<signed int>();
|
||||
break;
|
||||
case 'f':
|
||||
result = boost::any_cast<luabridge::LuaRef>(any).cast<double>();
|
||||
break;
|
||||
case 's':
|
||||
result = boost::any_cast<luabridge::LuaRef>(any).cast<const char*>();
|
||||
break;
|
||||
case 'v':
|
||||
result = boost::any();
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("Lua call: Unknown return type" + ret_type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
//
|
||||
// Created by koncord on 23.01.16.
|
||||
//
|
||||
|
||||
#ifndef SCRIPTFUNCTION_HPP
|
||||
#define SCRIPTFUNCTION_HPP
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#if defined (ENABLE_LUA)
|
||||
#include "LangLua/LangLua.hpp"
|
||||
#endif
|
||||
|
||||
typedef unsigned long long(*ScriptFunc)();
|
||||
#if defined (ENABLE_LUA)
|
||||
typedef std::string ScriptFuncLua;
|
||||
#endif
|
||||
|
||||
class ScriptFunction
|
||||
{
|
||||
protected:
|
||||
union
|
||||
{
|
||||
ScriptFunc fCpp;
|
||||
#if defined (ENABLE_LUA)
|
||||
struct
|
||||
{
|
||||
lua_State *lua;
|
||||
ScriptFuncLua name;
|
||||
} fLua;
|
||||
#endif
|
||||
};
|
||||
|
||||
protected:
|
||||
char ret_type;
|
||||
std::string def;
|
||||
int script_type;
|
||||
enum
|
||||
{
|
||||
SCRIPT_CPP,
|
||||
SCRIPT_LUA
|
||||
};
|
||||
|
||||
ScriptFunction(ScriptFunc fCpp, char ret_type, const std::string &def);
|
||||
#if defined (ENABLE_LUA)
|
||||
ScriptFunction(const ScriptFuncLua &fPawn, lua_State *lua, char ret_type, const std::string &def);
|
||||
#endif
|
||||
virtual ~ScriptFunction();
|
||||
|
||||
boost::any Call(const std::vector<boost::any> &args);
|
||||
};
|
||||
|
||||
#endif //SCRIPTFUNCTION_HPP
|
@ -1,70 +0,0 @@
|
||||
#include "ScriptFunctions.hpp"
|
||||
#include "API/PublicFnAPI.hpp"
|
||||
#include <cstdarg>
|
||||
#include <iostream>
|
||||
#include <apps/openmw-mp/Player.hpp>
|
||||
#include <apps/openmw-mp/Networking.hpp>
|
||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||
|
||||
template<typename... Types>
|
||||
constexpr char TypeString<Types...>::value[];
|
||||
constexpr ScriptFunctionData ScriptFunctions::functions[];
|
||||
constexpr ScriptCallbackData ScriptFunctions::callbacks[];
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ScriptFunctions::GetArguments(std::vector<boost::any> ¶ms, va_list args, const std::string &def)
|
||||
{
|
||||
params.reserve(def.length());
|
||||
|
||||
try
|
||||
{
|
||||
for (char c : def)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'i':
|
||||
params.emplace_back(va_arg(args, unsigned int));
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
params.emplace_back(va_arg(args, signed int));
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
params.emplace_back(va_arg(args, unsigned long long));
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
params.emplace_back(va_arg(args, signed long long));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
params.emplace_back(va_arg(args, double));
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
params.emplace_back(va_arg(args, void*));
|
||||
break;
|
||||
|
||||
case 's':
|
||||
params.emplace_back(va_arg(args, const char*));
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
params.emplace_back(va_arg(args, int));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw runtime_error(std::string("C++ call: Unknown argument identifier ") + c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
va_end(args);
|
||||
throw;
|
||||
}
|
||||
va_end(args);
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
#ifndef SCRIPTFUNCTIONS_HPP
|
||||
#define SCRIPTFUNCTIONS_HPP
|
||||
|
||||
#include <Script/Functions/Actors.h>
|
||||
#include <Script/Functions/Books.h>
|
||||
#include <Script/Functions/Cells.h>
|
||||
#include <Script/Functions/CharClass.h>
|
||||
#include <Script/Functions/Chat.h>
|
||||
#include <Script/Functions/Dialogue.h>
|
||||
#include <Script/Functions/Factions.h>
|
||||
#include <Script/Functions/GUI.h>
|
||||
#include <Script/Functions/Items.h>
|
||||
#include <Script/Functions/Mechanics.h>
|
||||
#include <Script/Functions/Miscellaneous.h>
|
||||
#include <Script/Functions/Objects.h>
|
||||
#include <Script/Functions/Positions.h>
|
||||
#include <Script/Functions/Public.h>
|
||||
#include <Script/Functions/Quests.h>
|
||||
#include <Script/Functions/RecordsDynamic.h>
|
||||
#include <Script/Functions/Shapeshift.h>
|
||||
#include <Script/Functions/Server.h>
|
||||
#include <Script/Functions/Settings.h>
|
||||
#include <Script/Functions/Spells.h>
|
||||
#include <Script/Functions/Stats.h>
|
||||
#include <Script/Functions/Timer.h>
|
||||
#include <Script/Functions/Worldstate.h>
|
||||
#include <RakNetTypes.h>
|
||||
#include <tuple>
|
||||
#include <apps/openmw-mp/Player.hpp>
|
||||
#include "ScriptFunction.hpp"
|
||||
#include "Types.hpp"
|
||||
|
||||
#include <components/openmw-mp/Log.hpp>
|
||||
|
||||
#ifndef __PRETTY_FUNCTION__
|
||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#define GET_PLAYER(pid, pl, retvalue) \
|
||||
pl = Players::getPlayer(pid); \
|
||||
if (player == 0) {\
|
||||
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "%s: Player with pid \'%d\' not found\n", __PRETTY_FUNCTION__, pid);\
|
||||
/*ScriptFunctions::StopServer(1);*/ \
|
||||
return retvalue;\
|
||||
}
|
||||
|
||||
|
||||
class ScriptFunctions
|
||||
{
|
||||
public:
|
||||
static void GetArguments(std::vector<boost::any> ¶ms, va_list args, const std::string &def);
|
||||
|
||||
static constexpr ScriptFunctionData functions[]{
|
||||
{"CreateTimer", TimerFunctions::CreateTimer},
|
||||
{"CreateTimerEx", TimerFunctions::CreateTimerEx},
|
||||
{"MakePublic", PublicFunctions::MakePublic},
|
||||
{"CallPublic", PublicFunctions::CallPublic},
|
||||
|
||||
{"StartTimer", TimerFunctions::StartTimer},
|
||||
{"StopTimer", TimerFunctions::StopTimer},
|
||||
{"RestartTimer", TimerFunctions::RestartTimer},
|
||||
{"FreeTimer", TimerFunctions::FreeTimer},
|
||||
{"IsTimerElapsed", TimerFunctions::IsTimerElapsed},
|
||||
|
||||
ACTORAPI,
|
||||
BOOKAPI,
|
||||
CELLAPI,
|
||||
CHARCLASSAPI,
|
||||
CHATAPI,
|
||||
DIALOGUEAPI,
|
||||
FACTIONAPI,
|
||||
GUIAPI,
|
||||
ITEMAPI,
|
||||
MECHANICSAPI,
|
||||
MISCELLANEOUSAPI,
|
||||
POSITIONAPI,
|
||||
QUESTAPI,
|
||||
RECORDSDYNAMICAPI,
|
||||
SHAPESHIFTAPI,
|
||||
SERVERAPI,
|
||||
SETTINGSAPI,
|
||||
SPELLAPI,
|
||||
STATAPI,
|
||||
OBJECTAPI,
|
||||
WORLDSTATEAPI
|
||||
};
|
||||
|
||||
static constexpr ScriptCallbackData callbacks[]{
|
||||
{"OnServerInit", Callback<>()},
|
||||
{"OnServerPostInit", Callback<>()},
|
||||
{"OnServerExit", Callback<bool>()},
|
||||
{"OnPlayerConnect", Callback<unsigned short>()},
|
||||
{"OnPlayerDisconnect", Callback<unsigned short>()},
|
||||
{"OnPlayerDeath", Callback<unsigned short>()},
|
||||
{"OnPlayerResurrect", Callback<unsigned short>()},
|
||||
{"OnPlayerCellChange", Callback<unsigned short>()},
|
||||
{"OnPlayerAttribute", Callback<unsigned short>()},
|
||||
{"OnPlayerSkill", Callback<unsigned short>()},
|
||||
{"OnPlayerLevel", Callback<unsigned short>()},
|
||||
{"OnPlayerBounty", Callback<unsigned short>()},
|
||||
{"OnPlayerReputation", Callback<unsigned short>()},
|
||||
{"OnPlayerEquipment", Callback<unsigned short>()},
|
||||
{"OnPlayerInventory", Callback<unsigned short>()},
|
||||
{"OnPlayerJournal", Callback<unsigned short>()},
|
||||
{"OnPlayerFaction", Callback<unsigned short>()},
|
||||
{"OnPlayerShapeshift", Callback<unsigned short>()},
|
||||
{"OnPlayerSpellbook", Callback<unsigned short>()},
|
||||
{"OnPlayerQuickKeys", Callback<unsigned short>()},
|
||||
{"OnPlayerTopic", Callback<unsigned short>()},
|
||||
{"OnPlayerDisposition", Callback<unsigned short>()},
|
||||
{"OnPlayerBook", Callback<unsigned short>()},
|
||||
{"OnPlayerItemUse", Callback<unsigned short>()},
|
||||
{"OnPlayerMiscellaneous", Callback<unsigned short>()},
|
||||
{"OnPlayerInput", Callback<unsigned short>()},
|
||||
{"OnPlayerRest", Callback<unsigned short>()},
|
||||
{"OnRecordDynamic", Callback<unsigned short>()},
|
||||
{"OnCellLoad", Callback<unsigned short, const char*>()},
|
||||
{"OnCellUnload", Callback<unsigned short, const char*>()},
|
||||
{"OnCellDeletion", Callback<const char*>()},
|
||||
{"OnContainer", Callback<unsigned short, const char*>()},
|
||||
{"OnDoorState", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectActivate", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectPlace", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectState", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectSpawn", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectDelete", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectLock", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectScale", Callback<unsigned short, const char*>()},
|
||||
{"OnObjectTrap", Callback<unsigned short, const char*>()},
|
||||
{"OnVideoPlay", Callback<unsigned short, const char*>()},
|
||||
{"OnActorList", Callback<unsigned short, const char*>()},
|
||||
{"OnActorEquipment", Callback<unsigned short, const char*>()},
|
||||
{"OnActorAI", Callback<unsigned short, const char*>()},
|
||||
{"OnActorDeath", Callback<unsigned short, const char*>()},
|
||||
{"OnActorCellChange", Callback<unsigned short, const char*>()},
|
||||
{"OnActorTest", Callback<unsigned short, const char*>()},
|
||||
{"OnPlayerSendMessage", Callback<unsigned short, const char*>()},
|
||||
{"OnPlayerEndCharGen", Callback<unsigned short>()},
|
||||
{"OnGUIAction", Callback<unsigned short, int, const char*>()},
|
||||
{"OnWorldKillCount", Callback<unsigned short>()},
|
||||
{"OnWorldMap", Callback<unsigned short>()},
|
||||
{"OnWorldWeather", Callback<unsigned short>() },
|
||||
{"OnMpNumIncrement", Callback<int>()},
|
||||
{"OnRequestPluginList", Callback<>()}
|
||||
};
|
||||
};
|
||||
|
||||
#endif //SCRIPTFUNCTIONS_HPP
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue