[General] Modernize Script API

This commit changes the style of tes3mp serverside scripting mods. Short list of changes:
* Break compatibility with old server mods
* OOP style lua API
* Basic dependency checker, allowing the installation of multiple server mods without changing configs
* Remove support for C++ plugins
* Change outdated LuaBridge to [sol2](https://github.com/ThePhD/sol2);
* Support GCC, Clang and MSVC compilers
* New environment variables: "TES3MP_SERVER_DIR" and "TES3MP_SERVER_USERDIR";
* New entity "Command controller" for registering new chat commands;
* New Event system
* Simplified Timer API
* All Lua mods now run in their own environments
* Add global namespace - Data that can be used for communicating between mods
* Player and Actor inherit base class NetActor
new-script-api
Koncord 7 years ago
parent 77ce05b7d6
commit 2d0840cb3a

3
.gitmodules vendored

@ -1,3 +1,6 @@
[submodule "extern/breakpad"]
path = extern/breakpad
url = https://chromium.googlesource.com/breakpad/breakpad
[submodule "extern/sol"]
path = extern/sol
url = https://github.com/ThePhD/sol2

@ -0,0 +1,270 @@
//
// Created by koncord on 25.08.17.
//
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Actors.hpp"
#include "Script/LuaState.hpp"
#include "Networking.hpp"
#include "Cell.hpp"
#include "CellController.hpp"
#include "Player.hpp"
using namespace std;
void Actor::Init(LuaState &lua)
{
lua.getState()->new_usertype<Actor>("Actor",
"getPosition", &NetActor::getPosition,
"setPosition", &NetActor::setPosition,
"getRotation", &NetActor::getRotation,
"setRotation", &NetActor::setRotation,
"getHealth", &NetActor::getHealth,
"setHealth", &NetActor::setHealth,
"getMagicka", &NetActor::getMagicka,
"setMagicka", &NetActor::setMagicka,
"getFatigue", &NetActor::getFatigue,
"setFatigue", &NetActor::setFatigue,
"getCell", &NetActor::getCell,
"getInventory", &NetActor::getInventory,
"refId", sol::property(&Actor::getRefId, &Actor::setRefId),
"refNumIndex", sol::property(&Actor::getRefNumIndex, &Actor::setRefNumIndex),
"mpNum", sol::property(&Actor::getMpNum, &Actor::setMpNum)
);
}
Actor::Actor() : NetActor()
{
}
std::string Actor::getRefId() const
{
return actor->refId;
}
void Actor::setRefId(const std::string &refId)
{
actor->refId = refId;
}
int Actor::getRefNumIndex() const
{
return actor->refNumIndex;
}
void Actor::setRefNumIndex(int refNumIndex)
{
actor->refNumIndex = refNumIndex;
}
int Actor::getMpNum() const
{
return actor->mpNum;
}
void Actor::setMpNum(int mpNum)
{
actor->mpNum = mpNum;
}
bool Actor::doesHavePosition() const
{
return actor->hasPositionData;
}
bool Actor::doesHaveStatsDynamic() const
{
return actor->hasStatsDynamicData;
}
void ActorController::Init(LuaState &lua)
{
sol::table playersTable = lua.getState()->create_named_table("Actors");
playersTable.set_function("createActor", [&lua](){
lua.getActorCtrl().createActor();
});
playersTable.set_function("sendActors", [&lua](shared_ptr<Player> player, vector<shared_ptr<Actor>> actors,
bool sendToAll) {
lua.getActorCtrl().sendActors(player, actors, sendToAll);
});
playersTable.set_function("sendList", [&lua](shared_ptr<Player> player, vector<shared_ptr<Actor>> actors,
bool sendToAll) {
lua.getActorCtrl().sendList(player, actors, sendToAll);
});
playersTable.set_function("requestList", [&lua](shared_ptr<Player> player){
lua.getActorCtrl().requestList(player);
});
playersTable.set_function("getActors", [&lua](shared_ptr<Player> player){
lua.getActorCtrl().getActors(player);
});
}
ActorController::ActorController()
{
}
ActorController::~ActorController()
{
}
std::shared_ptr<Actor> ActorController::createActor()
{
Actor *actor = new Actor();
actor->actor.reset(new mwmp::BaseActor);
return shared_ptr<Actor>(actor);
}
void ActorController::sendActors(std::shared_ptr<Player> player, std::vector<std::shared_ptr<Actor>> actors, bool sendToAll)
{
actorList.cell = player->cell;
actorList.guid = player->guid;
bool positionChanged = false;
bool statsChanged = false;
bool attributesChanged = false;
bool skillsChanged = false;
bool baseInfoChanged = false;
bool equipmentChanged = false;
bool changedCell = false;
actorList.baseActors.clear();
for (auto &actor : actors)
{
actorList.baseActors.push_back(actor->actor);
if (actor->positionChanged)
positionChanged = true;
if (actor->statsChanged)
statsChanged = true;
if (actor->attributesChanged)
attributesChanged = true;
if (actor->skillsChanged)
skillsChanged = true;
if (actor->baseInfoChanged)
baseInfoChanged = true;
if (actor->inventory.isEquipmentChanged())
{
equipmentChanged = true;
actor->inventory.resetEquipmentFlag();
}
if (actor->cellAPI.isChangedCell())
{
changedCell = true;
actor->cellAPI.resetChangedCell();
}
actor->resetUpdateFlags();
}
auto actorCtrl = mwmp::Networking::get().getActorPacketController();
Cell *serverCell = nullptr;
if (sendToAll)
serverCell = CellController::get()->getCell(&actorList.cell);
if (positionChanged)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_POSITION);
packet->setActorList(&actorList);
packet->Send(actorList.guid);
if (sendToAll)
serverCell->sendToLoaded(packet, &actorList);
}
if (statsChanged)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_STATS_DYNAMIC);
packet->setActorList(&actorList);
packet->Send(actorList.guid);
if (sendToAll)
serverCell->sendToLoaded(packet, &actorList);
}
/*if (attributesChanged)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_POSITION);
}
if (skillsChanged)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_POSITION);
}
if (baseInfoChanged)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_POSITION);
}*/
if (equipmentChanged)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_EQUIPMENT);
packet->setActorList(&actorList);
packet->Send(actorList.guid);
if (sendToAll)
serverCell->sendToLoaded(packet, &actorList);
}
if (changedCell)
{
auto packet = actorCtrl->GetPacket(ID_ACTOR_CELL_CHANGE);
packet->setActorList(&actorList);
packet->Send(actorList.guid);
if (sendToAll)
serverCell->sendToLoaded(packet, &actorList);
}
}
void ActorController::sendList(std::shared_ptr<Player> player, std::vector<std::shared_ptr<Actor>> actors, bool sendToAll)
{
actorList.cell = player->cell;
actorList.guid = player->guid;
actorList.action = mwmp::BaseActorList::SET;
auto packet = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_LIST);
packet->setActorList(&actorList);
packet->Send(actorList.guid);
}
void ActorController::requestList(std::shared_ptr<Player> player)
{
actorList.cell = player->cell;
actorList.guid = player->guid;
actorList.action = mwmp::BaseActorList::REQUEST;
auto packet = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_LIST);
packet->setActorList(&actorList);
packet->Send(actorList.guid);
}
std::vector<std::shared_ptr<Actor>> ActorController::getActors(std::shared_ptr<Player> player)
{
Cell *serverCell = CellController::get()->getCell(&player->cell);
std::vector<std::shared_ptr<Actor>> actorList;
for (auto actor : serverCell->getActorList()->baseActors)
{
Actor *a = new Actor;
a->actor = actor;
actorList.emplace_back(a);
}
return actorList;
}

@ -0,0 +1,55 @@
//
// Created by koncord on 25.08.17.
//
#pragma once
#include <string>
#include <components/openmw-mp/Base/BaseActor.hpp>
#include "NetActor.hpp"
class LuaState;
class Player;
class Actor: public NetActor
{
friend class ActorController;
public:
static void Init(LuaState &lua);
public:
Actor();
std::string getRefId() const;
void setRefId(const std::string &refId);
int getRefNumIndex() const;
void setRefNumIndex(int refNumIndex);
int getMpNum() const;
void setMpNum(int mpNum);
bool doesHavePosition() const; // ????
bool doesHaveStatsDynamic() const; // ????
std::shared_ptr<mwmp::BaseActor> actor;
};
class ActorController
{
public:
static void Init(LuaState &lua);
public:
ActorController();
~ActorController();
std::shared_ptr<Actor> createActor();
void sendActors(std::shared_ptr<Player> player, std::vector<std::shared_ptr<Actor>> actors, bool sendToAll = false);
void sendList(std::shared_ptr<Player> player, std::vector<std::shared_ptr<Actor>> actors, bool sendToAll = false);
void requestList(std::shared_ptr<Player> player);
std::vector<std::shared_ptr<Actor>> getActors(std::shared_ptr<Player> player);
private:
mwmp::BaseActorList actorList;
};

@ -0,0 +1,68 @@
//
// Created by koncord on 15.08.17.
//
#include "Books.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Script/LuaState.hpp"
#include "Player.hpp"
#include "Networking.hpp"
void Books::Init(LuaState &lua)
{
lua.getState()->new_usertype<Books>("Books",
"addBook", &Books::addBook,
"getBookId", &Books::getBookId,
"getChanges", &Books::getChanges,
"reset", &Books::reset
);
}
Books::Books(Player *player) : player(player), changed(false)
{
}
Books::~Books()
{
}
void Books::addBook(const std::string &bookId)
{
if (!changed)
reset();
player->bookChanges.books.push_back({bookId});
changed = true;
}
std::string Books::getBookId(unsigned i) const
{
if (i >= player->bookChanges.count)
return "invalid";
return player->bookChanges.books.at(i).bookId;
}
unsigned Books::getChanges() const
{
return player->bookChanges.count;
}
void Books::reset()
{
player->bookChanges.books.clear();
}
void Books::update()
{
if (!changed)
return;
changed = false;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOOK);
packet->setPlayer(player);
packet->Send(/*toOthers*/ false);
}

@ -0,0 +1,32 @@
//
// Created by koncord on 15.08.17.
//
#pragma once
#include <string>
class LuaState;
class Player;
class Books
{
public:
static void Init(LuaState &lua);
public:
explicit Books(Player *player);
~Books();
void addBook(const std::string &bookId);
std::string getBookId(unsigned i) const;
unsigned getChanges() const;
void reset();
void update();
private:
Player *player;
bool changed;
};

@ -1,12 +1,5 @@
project(tes3mp-server)
if(UNIX) #temporarily disabled for non-unix
if(NOT (${CMAKE_CXX_COMPILER} MATCHES "aarch64" OR ${CMAKE_CXX_COMPILER} MATCHES "arm")) #temporarily disabled for arm
find_package(CallFF REQUIRED)
include_directories(${CallFF_INCLUDES})
endif(NOT (${CMAKE_CXX_COMPILER} MATCHES "aarch64" OR ${CMAKE_CXX_COMPILER} MATCHES "arm"))
endif(UNIX)
option(BUILD_WITH_PAWN "Enable Pawn language" OFF)
option(ENABLE_BREAKPAD "Enable Google Breakpad for Crash reporting" OFF)
@ -22,89 +15,52 @@ if(ENABLE_BREAKPAD)
include_directories(${CMAKE_SOURCE_DIR}/extern/breakpad/src ${Breakpad_Headers})
endif(ENABLE_BREAKPAD)
if(BUILD_WITH_PAWN)
option(BUILD_WITH_LUA "Enable Terra/Lua language" ON)
option(FORCE_LUA "Use Lua instead Terra" OFF)
add_subdirectory(amx)
#set(Pawn_ROOT ${CMAKE_SOURCE_DIR}/external/pawn/)
set(Pawn_INCLUDES ${Pawn_ROOT}/include)
set(Pawn_LIBRARY ${Pawn_ROOT}/lib/libamx.a)
set(PawnScript_Sources
Script/LangPawn/LangPAWN.cpp
Script/LangPawn/PawnFunc.cpp)
set(PawnScript_Headers ${Pawn_INCLUDES}
Script/LangPawn/LangPAWN.hpp
)
#set(Terra_ROOT ${CMAKE_SOURCE_DIR}/external/terra/)
#if(WIN32 OR FORCE_LUA)
find_package(LuaJit REQUIRED)
#[[else()
find_package(Terra REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_TERRA")]]
#endif()
set(LuaScript_Headers ${Terra_INCLUDES} ${LUA_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/extern/sol/sol.hpp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_PAWN -DPAWN_CELL_SIZE=64")
#include_directories(${Pawn_INCLUDES})
include_directories("./amx/linux")
endif(BUILD_WITH_PAWN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_LUA")
include_directories(${Terra_INCLUDES} ${LUA_INCLUDE_DIR} ${LUAJIT_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/extern/sol)
option(BUILD_WITH_LUA "Enable Terra/Lua language" ON)
option(FORCE_LUA "Use Lua instead Terra" OFF)
if(BUILD_WITH_LUA)
#set(Terra_ROOT ${CMAKE_SOURCE_DIR}/external/terra/)
if(WIN32 OR FORCE_LUA)
find_package(Lua51 REQUIRED)
MESSAGE(STATUS "Found LUA_LIBRARY: ${LUA_LIBRARY}")
MESSAGE(STATUS "Found LUA_INCLUDE_DIR: ${LUA_INCLUDE_DIR}")
else()
find_package(Terra REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_TERRA")
endif()
set(LuaScript_Sources
Script/LangLua/LangLua.cpp
Script/LangLua/LuaFunc.cpp)
set(LuaScript_Headers ${Terra_INCLUDES} ${LUA_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/extern/LuaBridge ${CMAKE_SOURCE_DIR}/extern/LuaBridge/detail
Script/LangLua/LangLua.hpp)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_LUA")
include_directories(${Terra_INCLUDES} ${LUA_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/extern/LuaBridge)
endif(BUILD_WITH_LUA)
set(NativeScript_Sources
Script/LangNative/LangNative.cpp
)
set(NativeScript_Headers
Script/LangNative/LangNative.hpp
)
# local files
set(SERVER
main.cpp
Player.cpp
Player.cpp Players.cpp
Networking.cpp
MasterClient.cpp
Cell.cpp
CellController.cpp
Utils.cpp
Script/Script.cpp Script/ScriptFunction.cpp
Script/ScriptFunctions.cpp
Script/Functions/Actors.cpp Script/Functions/World.cpp Script/Functions/Miscellaneous.cpp
Script/Functions/Books.cpp Script/Functions/Cells.cpp Script/Functions/CharClass.cpp
Script/Functions/Chat.cpp Script/Functions/Dialogue.cpp Script/Functions/Factions.cpp
Script/Functions/GUI.cpp Script/Functions/Items.cpp Script/Functions/Mechanics.cpp
Script/Functions/Positions.cpp Script/Functions/Quests.cpp Script/Functions/Settings.cpp
Script/Functions/Spells.cpp Script/Functions/Stats.cpp Script/Functions/Timer.cpp
Script/API/TimerAPI.cpp Script/API/PublicFnAPI.cpp
${PawnScript_Sources}
${LuaScript_Sources}
${NativeScript_Sources}
CharClass.cpp
Inventory.cpp
Settings.cpp
Timer.cpp
Books.cpp
GUI.cpp
Dialogue.cpp
Factions.cpp
Cells.cpp
Quests.cpp
Spells.cpp
Actors.cpp
NetActor.cpp
CellState.cpp
Object.cpp
Script/CommandController.cpp Script/EventController.cpp Script/LuaState.cpp Script/luaUtils.cpp
)
set(SERVER_HEADER
Script/Types.hpp Script/Script.hpp Script/SystemInterface.hpp
Script/ScriptFunction.hpp Script/Platform.hpp Script/Language.hpp
Script/ScriptFunctions.hpp Script/API/TimerAPI.hpp Script/API/PublicFnAPI.hpp
${PawnScript_Headers}
${LuaScript_Headers}
${NativeScript_Headers}
${CallFF_INCLUDES}
)
source_group(tes3mp-server FILES ${SERVER} ${SERVER_HEADER})
@ -171,7 +127,13 @@ add_executable(tes3mp-server
${PROCESSORS_ACTOR} ${PROCESSORS_PLAYER} ${PROCESSORS_WORLD} ${PROCESSORS}
${APPLE_BUNDLE_RESOURCES}
)
add_definitions(-std=gnu++14 -Wno-ignored-qualifiers)
target_compile_definitions(tes3mp-server PRIVATE $<$<CONFIG:Debug>:SOL_SAFE_FUNCTIONS>) # for lua debuging
target_compile_definitions(tes3mp-server PRIVATE $<$<CONFIG:Debug>:SERVER_DEBUG>) # for lua debuging
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(tes3mp-server PRIVATE -std=gnu++14 -Wno-ignored-qualifiers -ftemplate-depth=2048)
endif()
target_link_libraries(tes3mp-server
#${Boost_SYSTEM_LIBRARY}
@ -182,9 +144,8 @@ target_link_libraries(tes3mp-server
components
${Terra_LIBRARY}
${LUA_LIBRARIES}
${Pawn_LIBRARY}
${LUAJIT_LIBRARY}
${Breakpad_Library}
${CallFF_LIBRARY}
)
if (UNIX)

@ -7,8 +7,9 @@
#include <components/openmw-mp/NetworkMessages.hpp>
#include <iostream>
#include "Script/EventController.hpp"
#include "Player.hpp"
#include "Script/Script.hpp"
#include "Networking.hpp"
using namespace std;
@ -39,7 +40,8 @@ void Cell::addPlayer(Player *player)
LOG_APPEND(Log::LOG_INFO, "- Adding %s to Cell %s", player->npc.mName.c_str(), getDescription().c_str());
Script::Call<Script::CallbackIdentity("OnCellLoad")>(player->getId(), getDescription().c_str());
mwmp::Networking::get().getState().getEventCtrl().Call<CoreEvent::ON_CELL_LOAD>(player, getDescription());
players.push_back(player);
}
@ -60,7 +62,8 @@ void Cell::removePlayer(Player *player)
LOG_APPEND(Log::LOG_INFO, "- Removing %s from Cell %s", player->npc.mName.c_str(), getDescription().c_str());
Script::Call<Script::CallbackIdentity("OnCellUnload")>(player->getId(), getDescription().c_str());
mwmp::Networking::get().getState().getEventCtrl().Call<CoreEvent::ON_CELL_UNLOAD>(player, getDescription());
players.erase(it);
return;
@ -72,27 +75,27 @@ void Cell::readActorList(unsigned char packetID, const mwmp::BaseActorList *newA
{
for (unsigned int i = 0; i < newActorList->count; i++)
{
mwmp::BaseActor newActor = newActorList->baseActors.at(i);
auto &newActor = newActorList->baseActors.at(i);
mwmp::BaseActor *cellActor;
if (containsActor(newActor.refNumIndex, newActor.mpNum))
if (containsActor(newActor->refNumIndex, newActor->mpNum))
{
cellActor = getActor(newActor.refNumIndex, newActor.mpNum);
cellActor = getActor(newActor->refNumIndex, newActor->mpNum);
switch (packetID)
{
case ID_ACTOR_POSITION:
cellActor->hasPositionData = true;
cellActor->position = newActor.position;
cellActor->position = newActor->position;
break;
case ID_ACTOR_STATS_DYNAMIC:
cellActor->hasStatsDynamicData = true;
cellActor->creatureStats.mDynamic[0] = newActor.creatureStats.mDynamic[0];
cellActor->creatureStats.mDynamic[1] = newActor.creatureStats.mDynamic[1];
cellActor->creatureStats.mDynamic[2] = newActor.creatureStats.mDynamic[2];
cellActor->creatureStats.mDynamic[0] = newActor->creatureStats.mDynamic[0];
cellActor->creatureStats.mDynamic[1] = newActor->creatureStats.mDynamic[1];
cellActor->creatureStats.mDynamic[2] = newActor->creatureStats.mDynamic[2];
break;
}
}
@ -107,9 +110,9 @@ bool Cell::containsActor(int refNumIndex, int mpNum)
{
for (unsigned int i = 0; i < cellActorList.baseActors.size(); i++)
{
mwmp::BaseActor actor = cellActorList.baseActors.at(i);
auto &actor = cellActorList.baseActors.at(i);
if (actor.refNumIndex == refNumIndex && actor.mpNum == mpNum)
if (actor->refNumIndex == refNumIndex && actor->mpNum == mpNum)
return true;
}
return false;
@ -119,28 +122,28 @@ mwmp::BaseActor *Cell::getActor(int refNumIndex, int mpNum)
{
for (unsigned int i = 0; i < cellActorList.baseActors.size(); i++)
{
mwmp::BaseActor *actor = &cellActorList.baseActors.at(i);
auto &actor = cellActorList.baseActors.at(i);
if (actor->refNumIndex == refNumIndex && actor->mpNum == mpNum)
return actor;
return actor.get();
}
return 0;
}
void Cell::removeActors(const mwmp::BaseActorList *newActorList)
{
for (std::vector<mwmp::BaseActor>::iterator it = cellActorList.baseActors.begin(); it != cellActorList.baseActors.end();)
for (auto it = cellActorList.baseActors.begin(); it != cellActorList.baseActors.end();)
{
int refNumIndex = (*it).refNumIndex;
int mpNum = (*it).mpNum;
int refNumIndex = (*it)->refNumIndex;
int mpNum = (*it)->mpNum;
bool foundActor = false;
for (unsigned int i = 0; i < newActorList->count; i++)
{
mwmp::BaseActor newActor = newActorList->baseActors.at(i);
auto &newActor = newActorList->baseActors.at(i);
if (newActor.refNumIndex == refNumIndex && newActor.mpNum == mpNum)
if (newActor->refNumIndex == refNumIndex && newActor->mpNum == mpNum)
{
it = cellActorList.baseActors.erase(it);
foundActor = true;

@ -1,9 +1,10 @@
#include "CellController.hpp"
#include <iostream>
#include <apps/openmw-mp/Script/EventController.hpp>
#include "Cell.hpp"
#include "Player.hpp"
#include "Script/Script.hpp"
#include "Networking.hpp"
using namespace std;
@ -50,7 +51,7 @@ Cell *CellController::getCell(ESM::Cell *esmCell)
Cell *CellController::getCellByXY(int x, int y)
{
auto it = find_if(cells.begin(), cells.end(), [x, y](const Cell *c)
auto it = find_if (cells.begin(), cells.end(), [x, y](const Cell *c)
{
return c->cell.mData.mX == x && c->cell.mData.mY == y;
});
@ -66,7 +67,7 @@ Cell *CellController::getCellByXY(int x, int y)
Cell *CellController::getCellByName(std::string cellName)
{
auto it = find_if(cells.begin(), cells.end(), [cellName](const Cell *c)
auto it = find_if (cells.begin(), cells.end(), [cellName](const Cell *c)
{
return c->cell.mName == cellName;
});
@ -83,7 +84,7 @@ Cell *CellController::getCellByName(std::string cellName)
Cell *CellController::addCell(ESM::Cell cellData)
{
LOG_APPEND(Log::LOG_INFO, "- Loaded cells: %d", cells.size());
auto it = find_if(cells.begin(), cells.end(), [cellData](const Cell *c) {
auto it = find_if (cells.begin(), cells.end(), [cellData](const Cell *c) {
// Currently we cannot compare because plugin lists can be loaded in different order
//return c->cell.sRecordId == cellData.sRecordId;
return c->cell.isExterior() ? (c->cell.mData.mX == cellData.mData.mX && c->cell.mData.mY == cellData.mData.mY) :
@ -116,7 +117,8 @@ void CellController::removeCell(Cell *cell)
{
if (*it != nullptr && *it == cell)
{
Script::Call<Script::CallbackIdentity("OnCellDeletion")>(cell->getDescription().c_str());
mwmp::Networking::get().getState().getEventCtrl().Call<CoreEvent::ON_CELL_DELETION>(cell->getDescription());
LOG_APPEND(Log::LOG_INFO, "- Removing %s from CellController", cell->getDescription().c_str());
delete *it;

@ -0,0 +1,30 @@
//
// Created by koncord on 25.08.17.
//
#include "CellState.hpp"
#include "Script/LuaState.hpp"
void CellState::Init(LuaState &lua)
{
lua.getState()->new_usertype<CellState>("CellState",
"type", sol::property(&CellState::getStateType),
"description", sol::property(&CellState::getDescription)
);
}
CellState::CellState(mwmp::CellState state) : state(state)
{
}
int CellState::getStateType() const
{
return state.type;
}
std::string CellState::getDescription() const
{
return state.cell.getDescription();
}

@ -0,0 +1,24 @@
//
// Created by koncord on 25.08.17.
//
#pragma once
#include <string>
#include <components/openmw-mp/Base/BasePlayer.hpp>
class LuaState;
class CellState
{
public:
static void Init(LuaState &lua);
explicit CellState(mwmp::CellState state);
public:
int getStateType() const;
std::string getDescription() const;
private:
mwmp::CellState state;
};

@ -0,0 +1,99 @@
//
// Created by koncord on 25.08.17.
//
#include "Cells.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Script/LuaState.hpp"
#include "NetActor.hpp"
#include "Networking.hpp"
using namespace std;
void Cells::Init(LuaState &lua)
{
lua.getState()->new_usertype<Cells>("Cells",
"cell", sol::property(&Cells::getCell, &Cells::setCell),
"getExterior", &Cells::getExterior,
"setExterior", &Cells::setExterior,
"getRegion", &Cells::getRegion,
"isExterior", &Cells::isExterior,
"isChangingRegion", &Cells::isChangingRegion
);
}
Cells::Cells(NetActor *netActor) : netActor(netActor), changedCell(false)
{
}
Cells::~Cells()
{
}
void Cells::update()
{
}
std::string Cells::getCell() const
{
return netActor->getNetCreature()->cell.getDescription();
}
void Cells::setCell(const std::string &cellDescription)
{
/*LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Script is moving %s from %s to %s", netActor->getNetCreature()->npc.mName.c_str(),
netActor->getNetCreature()->cell.getDescription().c_str(), cellDescription.c_str());*/
netActor->getNetCreature()->cell = Utils::getCellFromDescription(cellDescription);
changedCell = true;
}
std::tuple<int, int> Cells::getExterior() const
{
return make_tuple(netActor->getNetCreature()->cell.mData.mX, netActor->getNetCreature()->cell.mData.mY);
}
void Cells::setExterior(int x, int y)
{
/*LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Script is moving %s from %s to %i,%i", netActor->getNetCreature()->npc.mName.c_str(),
netActor->getNetCreature()->cell.getDescription().c_str(), x, y);*/
// If the player is currently in an interior, turn off the interior flag from the cell
if (!netActor->getNetCreature()->cell.isExterior())
netActor->getNetCreature()->cell.mData.mFlags &= ~ESM::Cell::Interior;
netActor->getNetCreature()->cell.mData.mX = x;
netActor->getNetCreature()->cell.mData.mY = y;
changedCell = true;
}
bool Cells::isExterior() const
{
return netActor->getNetCreature()->cell.isExterior();
}
bool Cells::isChangingRegion() const
{
return netActor->getNetCreature()->isChangingRegion;
}
std::string Cells::getRegion() const
{
return netActor->getNetCreature()->cell.mRegion;
}
bool Cells::isChangedCell() const
{
return changedCell;
}
void Cells::resetChangedCell()
{
changedCell = false;
}

@ -0,0 +1,43 @@
//
// Created by koncord on 25.08.17.
//
#pragma once
#include <cstddef>
#include <string>
#include <components/openmw-mp/Base/BasePlayer.hpp>
class LuaState;
class NetActor;
class Cells
{
public:
static void Init(LuaState &lua);
public:
explicit Cells(NetActor *netActor);
~Cells();
void update();
std::string getCell() const;
void setCell(const std::string &cellDescription);
std::tuple<int, int> getExterior() const;
void setExterior(int x, int y);
bool isExterior() const;
bool isChangingRegion() const;
std::string getRegion() const;
bool isChangedCell() const;
void resetChangedCell();
private:
NetActor *netActor;
bool changedCell;
};

@ -0,0 +1,153 @@
//
// Created by koncord on 12.08.17.
//
#include "CharClass.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Script/LuaState.hpp>
#include "Player.hpp"
#include "Networking.hpp"
using namespace std;
void CharClass::Init(LuaState &lua)
{
lua.getState()->new_usertype<CharClass>("Class",
//"__gc", sol::destructor(deleter),
"default", sol::property(&CharClass::getDefault, &CharClass::setDefault),
"isDefault", &CharClass::isDefault,
"name", sol::property(&CharClass::getName, &CharClass::setName),
"description", sol::property(&CharClass::getDesc, &CharClass::setDesc),
"specialization",
sol::property(&CharClass::getSpecialization, &CharClass::setSpecialization),
"getMajorAttributes", &CharClass::getMajorAttributes,
"setMajorAttributes", &CharClass::setMajorAttributes,
"getMinorSkills", &CharClass::getMinorSkills,
"setMinorSkills", &CharClass::setMinorSkills,
"getMajorSkills", &CharClass::getMajorSkills,
"setMajorSkills", &CharClass::setMajorSkills
);
}
CharClass::CharClass(Player *player) : player(player), changed(false)
{
printf("CharClass::CharClass()\n");
}
CharClass::~CharClass()
{
printf("CharClass::~CharClass()\n");
}
string CharClass::getDefault() const
{
return player->charClass.mId;
}
void CharClass::setDefault(const string &className)
{
player->charClass.mId = className;
changed = true;
printf("CharClass::setDefault()\n");
}
bool CharClass::isDefault() const
{
return player->charClass.mId.empty();
}
void CharClass::setName(const string &className)
{
player->charClass.mName = className;
changed = true;
}
string CharClass::getName() const
{
return player->charClass.mName;
}
std::string CharClass::getDesc() const
{
return player->charClass.mDescription;
}
void CharClass::setDesc(const string &desc)
{
player->charClass.mDescription = desc;
changed = true;
}
std::tuple<int, int> CharClass::getMajorAttributes() const
{
const auto &data = player->charClass.mData;
return make_tuple(data.mAttribute[0], data.mAttribute[1]);
}
void CharClass::setMajorAttributes(int first, int second)
{
auto &data = player->charClass.mData;
data.mAttribute[0] = first;
data.mAttribute[1] = second;
changed = true;
}
int CharClass::getSpecialization() const
{
return player->charClass.mData.mSpecialization;
}
void CharClass::setSpecialization(int spec)
{
auto &data = player->charClass.mData;
data.mSpecialization = spec;
changed = true;
}
std::tuple<int, int, int, int> CharClass::getMinorSkills() const
{
const auto &data = player->charClass.mData;
return make_tuple( data.mSkills[0][0], data.mSkills[1][0], data.mSkills[2][0], data.mSkills[3][0]);
}
void CharClass::setMinorSkills(int fisrt, int second, int third, int fourth)
{
auto &data = player->charClass.mData;
data.mSkills[0][0] = fisrt;
data.mSkills[1][0] = second;
data.mSkills[2][0] = third;
data.mSkills[3][0] = fourth;
changed = true;
}
std::tuple<int, int, int, int> CharClass::getMajorSkills() const
{
const auto &data = player->charClass.mData;
return make_tuple( data.mSkills[0][1], data.mSkills[1][1], data.mSkills[2][1], data.mSkills[3][1]);
}
void CharClass::setMajorSkills(int fisrt, int second, int third, int fourth)
{
auto &data = player->charClass.mData;
data.mSkills[0][1] = fisrt;
data.mSkills[1][1] = second;
data.mSkills[2][1] = third;
data.mSkills[3][1] = fourth;
changed = true;
}
void CharClass::update()
{
if (!changed)
return;
changed = false;
printf("CharClass::update()\n");
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARCLASS);
packet->setPlayer(player);
packet->Send(false);
}

@ -0,0 +1,50 @@
//
// Created by koncord on 12.08.17.
//
#pragma once
#include <string>
#include <tuple>
class LuaState;
class Player;
class CharClass
{
public:
static void Init(LuaState &lua);
public:
explicit CharClass(Player *player);
~CharClass();
void update();
std::string getDefault() const;
void setDefault(const std::string &className);
bool isDefault() const;
std::string getName() const;
void setName(const std::string &className);
std::string getDesc() const;
void setDesc(const std::string &desc);
std::tuple<int, int> getMajorAttributes() const;
void setMajorAttributes(int first, int second);
int getSpecialization() const;
void setSpecialization(int spec);
std::tuple<int, int, int, int> getMinorSkills() const;
void setMinorSkills(int fisrt, int second, int third, int fourth);
std::tuple<int, int, int, int> getMajorSkills() const;
void setMajorSkills(int fisrt, int second, int third, int fourth);
private:
// not controlled pointer
Player *player;
bool changed;
};

@ -0,0 +1,62 @@
//
// Created by koncord on 15.08.17.
//
#include "Dialogue.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Script/LuaState.hpp"
#include "Player.hpp"
#include "Networking.hpp"
void Dialogue::Init(LuaState &lua)
{
lua.getState()->new_usertype<Dialogue>("Dialogue",
"addTopic", &Dialogue::addTopic,
"getTopicId", &Dialogue::getTopicId,
"getChanges", &Dialogue::getChanges,
"reset", &Dialogue::reset);
}
Dialogue::Dialogue(Player *player) : player(player), changed(false)
{
}
void Dialogue::reset()
{
player->topicChanges.topics.clear();
}
void Dialogue::update()
{
if (!changed)
return;
changed = false;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_TOPIC);
packet->setPlayer(player);
packet->Send(/*toOthers*/ false);
}
void Dialogue::addTopic(const std::string &topicId)
{
if (!changed)
reset();
changed = true;
player->topicChanges.topics.push_back({topicId});
}
std::string Dialogue::getTopicId(unsigned int i) const
{
return player->topicChanges.topics.at(i).topicId;
}
unsigned int Dialogue::getChanges() const
{
return player->topicChanges.count;
}

@ -0,0 +1,30 @@
//
// Created by koncord on 15.08.17.
//
#pragma once
#include <string>
class LuaState;
class Player;
class Dialogue
{
public:
static void Init(LuaState &lua);
public:
explicit Dialogue(Player *player);
void addTopic(const std::string &topicId);
std::string getTopicId(unsigned int i) const;
unsigned int getChanges() const;
void reset();
void update();
private:
Player *player;
bool changed;
};

@ -0,0 +1,154 @@
//
// Created by koncord on 17.08.17.
//
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Factions.hpp"
#include "Player.hpp"
#include "Script/LuaState.hpp"
#include "Networking.hpp"
void Factions::Init(LuaState &lua)
{
lua.getState()->new_usertype<Factions>("Factions",
"addFaction", &Factions::addFaction,
"changesAction", sol::property(&Factions::getFactionChangesAction, &Factions::setFactionChangesAction),
"getFaction", &Factions::getFaction,
"setFaction", &Factions::setFaction,
"clear", &Factions::clear,
"size", &Factions::size
);
/*"InitializeFactionChanges", FactionFunctions::InitializeFactionChanges,
"GetFactionChangesSize", FactionFunctions::GetFactionChangesSize,
"GetFactionChangesAction", FactionFunctions::GetFactionChangesAction,
"GetFactionId", FactionFunctions::GetFactionId,
"GetFactionRank", FactionFunctions::GetFactionRank,
"GetFactionExpulsionState", FactionFunctions::GetFactionExpulsionState,
"GetFactionReputation", FactionFunctions::GetFactionReputation,
"SetFactionChangesAction", FactionFunctions::SetFactionChangesAction,
"SetFactionId", FactionFunctions::SetFactionId,
"SetFactionRank", FactionFunctions::SetFactionRank,
"SetFactionExpulsionState", FactionFunctions::SetFactionExpulsionState,
"SetFactionReputation", FactionFunctions::SetFactionReputation,
"AddFaction", FactionFunctions::AddFaction,
"SendFactionChanges", FactionFunctions::SendFactionChanges*/
}
Factions::Factions(Player *player): player(player), changed(false)
{
}
Factions::~Factions()
{
}
void Factions::update()
{
if (!changed)
return;
changed = false;
auto packet =mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_FACTION);
packet->setPlayer(player);
packet->Send(/*toOthers*/ false);
clear();
}
int Factions::getFactionChangesAction() const
{
return player->factionChanges.action;
}
void Factions::setFactionChangesAction(int action)
{
player->factionChanges.action = action;
changed = true;
}
void Factions::addFaction(Faction faction)
{
player->factionChanges.factions.push_back(faction.faction);
changed = true;
}
Faction Factions::getFaction(int id) const
{
return Faction(player->factionChanges.factions.at(id));
}
void Factions::setFaction(int id, Faction faction)
{
player->factionChanges.factions.at(id) = faction.faction;
changed = true;
}
void Factions::clear()
{
player->factionChanges.factions.clear();
changed = true;
}
size_t Factions::size() const
{
return player->factionChanges.factions.size();
}
void Faction::Init(LuaState &lua)
{
lua.getState()->new_usertype<Faction>("Faction",
"factionId", sol::property(&Faction::getFactionId, &Faction::setFactionId),
"rank", sol::property(&Faction::getFactionRank, &Faction::setFactionRank),
"isExpelled", sol::property(&Faction::getFactionExpulsionState, &Faction::setFactionExpulsionState),
"reputation", sol::property(&Faction::getFactionReputation, &Faction::setFactionReputation)
);
}
Faction::Faction(mwmp::Faction &faction): faction(faction)
{
}
std::string Faction::getFactionId() const
{
return faction.factionId;
}
void Faction::setFactionId(const std::string &factionId)
{
faction.factionId = factionId;
}
int Faction::getFactionRank() const
{
return faction.rank;
}
void Faction::setFactionRank(unsigned int rank)
{
faction.rank = rank;
}
bool Faction::getFactionExpulsionState() const
{
return faction.isExpelled;
}
void Faction::setFactionExpulsionState(bool expulsionState)
{
faction.isExpelled = expulsionState;
}
int Faction::getFactionReputation() const
{
return faction.reputation;
}
void Faction::setFactionReputation(int reputation)
{
faction.reputation = reputation;
}

@ -0,0 +1,59 @@
//
// Created by koncord on 17.08.17.
//
#pragma once
#include <string>
#include <components/openmw-mp/Base/BasePlayer.hpp>
class LuaState;
class Player;
class Faction
{
friend class Factions;
public:
static void Init(LuaState &lua);
public:
explicit Faction(mwmp::Faction &faction);
std::string getFactionId() const;
void setFactionId(const std::string &factionId);
int getFactionRank() const;
void setFactionRank(unsigned int rank);
bool getFactionExpulsionState() const;
void setFactionExpulsionState(bool expulsionState);
int getFactionReputation() const;
void setFactionReputation(int reputation);
mwmp::Faction faction;
};
class Factions
{
public:
static void Init(LuaState &lua);
public:
explicit Factions(Player *player);
~Factions();
void update();
int getFactionChangesAction() const;
void setFactionChangesAction(int action);
void addFaction(Faction faction);
Faction getFaction(int id) const;
void setFaction(int id, Faction faction);
size_t size() const;
void clear();
private:
mwmp::Faction tempFaction;
Player *player;
bool changed;
};

@ -0,0 +1,100 @@
//
// Created by koncord on 15.08.17.
//
#include <components/openmw-mp/NetworkMessages.hpp>
#include "GUI.hpp"
#include "Player.hpp"
#include "Networking.hpp"
void GUI::Init(LuaState &lua)
{
lua.getState()->new_usertype<GUI>("GUI",
"messageBox", &GUI::messageBox,
"customMessageBox", &GUI::customMessageBox,
"inputDialog", &GUI::inputDialog,
"passwordDialog", &GUI::passwordDialog,
"listBox", &GUI::listBox,
"setMapVisibility", &GUI::setMapVisibility,
"setMapVisibilityAll", &GUI::setMapVisibilityAll
);
}
GUI::GUI(Player *player): player(player), changed(false)
{
}
GUI::~GUI()
{
}
void GUI::update()
{
if (!changed)
return;
changed = false;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX);
packet->setPlayer(player);
packet->Send(false);
}
void GUI::messageBox(int id, const char *label)
{
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.type = Player::GUIMessageBox::MessageBox;
changed = true;
}
void GUI::customMessageBox(int id, const char *label, const char *buttons)
{
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.buttons = buttons;
player->guiMessageBox.type = Player::GUIMessageBox::CustomMessageBox;
changed = true;
}
void GUI::inputDialog(int id, const char *label)
{
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.type = Player::GUIMessageBox::InputDialog;
changed = true;
}
void GUI::passwordDialog(int id, const char *label, const char *note)
{
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.note = note;
player->guiMessageBox.type = Player::GUIMessageBox::PasswordDialog;
changed = true;
}
void GUI::listBox(int id, const char *label, const char *items)
{
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.data = items;
player->guiMessageBox.type = Player::GUIMessageBox::ListBox;
changed = true;
}
void GUI::setMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state)
{
LOG_MESSAGE(Log::LOG_WARN, "stub");
}
void GUI::setMapVisibilityAll(unsigned short targetPID, unsigned short state)
{
LOG_MESSAGE(Log::LOG_WARN, "stub");
}

@ -0,0 +1,36 @@
//
// Created by koncord on 15.08.17.
//
#pragma once
class LuaState;
class Player;
class GUI
{
public:
static void Init(LuaState &lua);
public:
explicit GUI(Player *player);
~GUI();
void update();
void messageBox(int id, const char *label);
void customMessageBox(int id, const char *label, const char *buttons);
void inputDialog(int id, const char *label);
void passwordDialog(int id, const char *label, const char *note);
void listBox(int id, const char *label, const char *items);
//state 0 - disallow, 1 - allow
void setMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state);
void setMapVisibilityAll(unsigned short targetPID, unsigned short state);
private:
Player *player;
bool changed;
};

@ -0,0 +1,164 @@
//
// Created by koncord on 12.08.17.
//
#include "Inventory.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Script/LuaState.hpp>
#include <apps/openmw/mwworld/inventorystore.hpp>
#include <components/misc/stringops.hpp>
#include "NetActor.hpp"
#include "Networking.hpp"
using namespace std;
void Inventory::Init(LuaState &lua)
{
lua.getState()->new_usertype<Inventory>("Inventory",
"getInventoryChangesSize", &Inventory::getChangesSize,
"addItem", &Inventory::addItem,
"removeItem", &Inventory::removeItem,
"getInventoryItem", &Inventory::getInventoryItem,
"equipItem", &Inventory::equipItem,
"unequipItem", &Inventory::unequipItem,
"hasItemEquipped", &Inventory::hasItemEquipped,
"getEquipmentItem", &Inventory::getEquipmentItem
);
}
Inventory::Inventory(NetActor *actor) : netActor(actor), equipmentChanged(false), inventoryChanged(0)
{
printf("Inventory::Inventory()\n");
}
Inventory::~Inventory()
{
printf("Inventory::~Inventory()\n");
}
void Inventory::update()
{
printf("Inventory::update()");
/*if (equipmentChanged)
{
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_EQUIPMENT);
packet->setPlayer(netActor->getNetCreature());
packet->Send(false);
packet->Send(true);
}
if (inventoryChanged != 0)
{
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_EQUIPMENT);
packet->setPlayer(netActor->getNetCreature());
packet->Send(false);
}
equipmentChanged = false;
inventoryChanged = 0;*/
}
void Inventory::InitializeInventoryChanges()
{
netActor->getNetCreature()->inventoryChanges.items.clear();
netActor->getNetCreature()->inventoryChanges.action = mwmp::InventoryChanges::SET;
}
int Inventory::getChangesSize() const
{
return netActor->getNetCreature()->inventoryChanges.count;
}
void Inventory::equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge)
{
netActor->getNetCreature()->equipedItems[slot].refId = refId;
netActor->getNetCreature()->equipedItems[slot].count = count;
netActor->getNetCreature()->equipedItems[slot].charge = charge;
equipmentChanged = true;
}
void Inventory::unequipItem( unsigned short slot)
{
equipItem(slot, "", 0, -1);
}
void Inventory::addItem(const std::string &refId, unsigned int count, int charge)
{
if (inventoryChanged == mwmp::InventoryChanges::REMOVE)
return;
if (inventoryChanged == 0)
InitializeInventoryChanges();
mwmp::Item item;
item.refId = refId;
item.count = count;
item.charge = charge;
netActor->getNetCreature()->inventoryChanges.items.push_back(item);
netActor->getNetCreature()->inventoryChanges.action = mwmp::InventoryChanges::ADD;
inventoryChanged = netActor->getNetCreature()->inventoryChanges.action;
}
void Inventory::removeItem(const std::string &refId, unsigned short count)
{
if (inventoryChanged == mwmp::InventoryChanges::ADD)
return;
if (inventoryChanged == 0)
InitializeInventoryChanges();
mwmp::Item item;
item.refId = refId;
item.count = count;
netActor->getNetCreature()->inventoryChanges.items.push_back(item);
netActor->getNetCreature()->inventoryChanges.action = mwmp::InventoryChanges::REMOVE;
inventoryChanged = netActor->getNetCreature()->inventoryChanges.action;
}
bool Inventory::hasItemEquipped(const std::string &refId) const
{
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++)
if (Misc::StringUtils::ciEqual(netActor->getNetCreature()->equipedItems[slot].refId, refId))
return true;
return false;
}
std::tuple<std::string, int, int> Inventory::getEquipmentItem(unsigned short slot) const
{
const auto &item = netActor->getNetCreature()->equipedItems[slot];
return make_tuple(item.refId, item.count, item.charge);
}
std::tuple<std::string, int, int> Inventory::getInventoryItem(unsigned int slot) const
{
const auto &item = netActor->getNetCreature()->inventoryChanges.items.at(slot);
return make_tuple(item.refId, item.count, item.charge);
}
void Inventory::resetEquipmentFlag()
{
equipmentChanged = false;
}
bool Inventory::isEquipmentChanged()
{
return equipmentChanged;
}
void Inventory::resetInventoryFlag()
{
inventoryChanged = 0;
}
int Inventory::inventoryChangeType()
{
return inventoryChanged;
}

@ -0,0 +1,63 @@
//
// Created by koncord on 12.08.17.
//
#pragma once
#include <string>
#include <tuple>
class LuaState;
class NetActor;
class Inventory
{
public:
static void Init(LuaState &lua);
bool isEquipmentChanged();
void resetEquipmentFlag();
int inventoryChangeType();
void resetInventoryFlag();
public:
explicit Inventory(NetActor *netActor);
~Inventory();
void update();
//inventory
int getChangesSize() const;
void addItem(const std::string& refId, unsigned int count, int charge);
void removeItem(const std::string& refId, unsigned short count);
/**
*
* @param slot
* @return refid, count, charge
*/
std::tuple<std::string,int, int> getInventoryItem(unsigned int slot) const;
// equipment
void equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge);
void unequipItem(unsigned short slot);
bool hasItemEquipped(const std::string& refId) const;
/**
*
* @param slot
* @return refid, count, charge
*/
std::tuple<std::string,int, int> getEquipmentItem(unsigned short slot) const;
private:
void InitializeInventoryChanges();
private:
// not controlled pointer
NetActor *netActor;
bool equipmentChanged;
int inventoryChanged;
};

@ -13,6 +13,7 @@
#include <components/openmw-mp/Version.hpp>
#include <components/openmw-mp/Master/PacketMasterAnnounce.hpp>
#include "Networking.hpp"
#include "Players.hpp"
using namespace std;
using namespace mwmp;
@ -32,7 +33,7 @@ MasterClient::MasterClient(RakNet::RakPeerInterface *peer, std::string queryAddr
void MasterClient::SetPlayers(unsigned pl)
{
mutexData.lock();
if (queryData.GetPlayers() != pl)
if ((unsigned) queryData.GetPlayers() != pl)
{
queryData.SetPlayers(pl);
updated = true;
@ -43,7 +44,7 @@ void MasterClient::SetPlayers(unsigned pl)
void MasterClient::SetMaxPlayers(unsigned pl)
{
mutexData.lock();
if (queryData.GetMaxPlayers() != pl)
if ((unsigned) queryData.GetMaxPlayers() != pl)
{
queryData.SetMaxPlayers(pl);
updated = true;
@ -194,22 +195,22 @@ void MasterClient::Thread()
queryData.SetPassword((int) Networking::get().isPassworded());
queryData.SetVersion(TES3MP_VERSION);
auto *players = Players::getPlayers();
//auto *players = Players::getPlayers();
while (sRun)
{
SetPlayers((int) players->size());
SetPlayers((unsigned) Players::size());
auto pIt = players->begin();
if (queryData.players.size() != players->size())
auto pIt = Players::begin();
if (queryData.players.size() != Players::size())
{
queryData.players.clear();
updated = true;
}
else
{
for (int i = 0; pIt != players->end(); i++, pIt++)
for (int i = 0; pIt != Players::end(); i++, pIt++)
{
if (queryData.players[i] != pIt->second->npc.mName)
if (queryData.players[i] != (*pIt)->npc.mName)
{
queryData.players.clear();
updated = true;
@ -221,13 +222,12 @@ void MasterClient::Thread()
if (updated)
{
updated = false;
if (pIt != players->end())
if (pIt != Players::end())
{
for (auto player : *players)
{
if (!player.second->npc.mName.empty())
queryData.players.push_back(player.second->npc.mName);
}
Players::for_each([this](auto player) {
if (!player->npc.mName.empty())
queryData.players.push_back(player->npc.mName);
});
}
Send(PacketMasterAnnounce::FUNCTION_ANNOUNCE);
}

@ -46,7 +46,7 @@ private:
std::thread thrQuery;
mwmp::PacketMasterAnnounce pma;
RakNet::BitStream writeStream;
bool updated;
std::atomic<bool> updated;
};

@ -0,0 +1,98 @@
//
// Created by koncord on 25.08.17.
//
#include "NetActor.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Script/LuaState.hpp"
//#include "Player.hpp"
#include "Networking.hpp"
#include <components/openmw-mp/Base/BaseNetCreature.hpp>
using namespace std;
NetActor::NetActor() : inventory(this), cellAPI(this)
{
}
void NetActor::resetUpdateFlags()
{
statsChanged = false;
skillsChanged = false;
attributesChanged = false;
baseInfoChanged = false;
positionChanged = false;
}
std::tuple<float, float, float> NetActor::getPosition() const
{
return make_tuple(netCreature->position.pos[0], netCreature->position.pos[1], netCreature->position.pos[2]);
}
void NetActor::setPosition(float x, float y, float z)
{
netCreature->position.pos[0] = x;
netCreature->position.pos[1] = y;
netCreature->position.pos[2] = z;
positionChanged = true;
}
std::tuple<float, float> NetActor::getRotation() const
{
return make_tuple(netCreature->position.rot[0], netCreature->position.rot[2]);
}
void NetActor::setRotation(float x, float z)
{
netCreature->position.rot[0] = x;
netCreature->position.rot[2] = z;
positionChanged = true;
}
std::tuple<float, float> NetActor::getHealth() const
{
return make_tuple(netCreature->creatureStats.mDynamic[0].mBase, netCreature->creatureStats.mDynamic[0].mCurrent);
}
void NetActor::setHealth(float base, float current)
{
netCreature->creatureStats.mDynamic[0].mBase = base;
netCreature->creatureStats.mDynamic[0].mCurrent = current;
statsChanged = true;
}
std::tuple<float, float> NetActor::getMagicka() const
{
return make_tuple(netCreature->creatureStats.mDynamic[1].mBase, netCreature->creatureStats.mDynamic[1].mCurrent);
}
void NetActor::setMagicka(float base, float current)
{
netCreature->creatureStats.mDynamic[1].mBase = base;
netCreature->creatureStats.mDynamic[1].mCurrent = current;
statsChanged = true;
}
std::tuple<float, float> NetActor::getFatigue() const
{
return make_tuple(netCreature->creatureStats.mDynamic[2].mBase, netCreature->creatureStats.mDynamic[2].mCurrent);
}
void NetActor::setFatigue(float base, float current)
{
netCreature->creatureStats.mDynamic[2].mBase = base;
netCreature->creatureStats.mDynamic[2].mCurrent = current;
statsChanged = true;
}
Inventory &NetActor::getInventory()
{
return inventory;
}
Cells &NetActor::getCell()
{
return cellAPI;
}

@ -0,0 +1,75 @@
//
// Created by koncord on 25.08.17.
//
#pragma once
#include <RakNetTypes.h>
#include <tuple>
#include "Inventory.hpp"
#include "Cells.hpp"
namespace mwmp
{
class BasePlayer;
class BaseNetCreature;
class BaseActor;
}
class NetActor
{
public:
NetActor();
void resetUpdateFlags();
/**
*
* @return x, y, z
*/
std::tuple<float, float, float> getPosition() const;
void setPosition(float x, float y, float z);
/**
*
* @return x, y
*/
std::tuple<float, float> getRotation() const;
void setRotation(float x, float z);
/**
*
* @return base, current
*/
std::tuple<float, float> getHealth() const;
void setHealth(float base, float current);
/**
*
* @return base, current
*/
std::tuple<float, float> getMagicka() const;
void setMagicka(float base, float current);
/**
*
* @return base, current
*/
std::tuple<float, float> getFatigue() const;
void setFatigue(float base, float current);
Inventory &getInventory();
Cells &getCell();
mwmp::BaseNetCreature *getNetCreature() { return netCreature; }
protected:
bool statsChanged, attributesChanged, skillsChanged, baseInfoChanged, positionChanged;
mwmp::BasePlayer *basePlayer;
mwmp::BaseNetCreature *netCreature;
Inventory inventory;
Cells cellAPI;
};

@ -2,7 +2,8 @@
// Created by koncord on 12.01.16.
//
#include "Player.hpp"
#include "Players.hpp"
#include <Script/EventController.hpp>
#include "processors/ProcessorInitializer.hpp"
#include <RakPeer.h>
#include <Kbhit.h>
@ -14,8 +15,7 @@
#include <components/openmw-mp/Packets/PacketPreInit.hpp>
#include <iostream>
#include <Script/Script.hpp>
#include <Script/API/TimerAPI.hpp>
//#include <Script/API/TimerAPI.hpp>
#include <chrono>
#include <thread>
@ -34,11 +34,12 @@ Networking *Networking::sThis = 0;
static int currentMpNum = 0;
Networking::Networking(RakNet::RakPeerInterface *peer) : mclient(nullptr)
{
sThis = this;
this->peer = peer;
players = Players::getPlayers();
CellController::create();
@ -53,21 +54,22 @@ Networking::Networking(RakNet::RakPeerInterface *peer) : mclient(nullptr)
running = true;
exitCode = 0;
Script::Call<Script::CallbackIdentity("OnServerInit")>();
luaState.loadMods();
serverPassword = TES3MP_DEFAULT_PASSW;
ProcessorInitializer();
luaState.getEventCtrl().Call<CoreEvent::ON_POST_INIT>();
}
Networking::~Networking()
{
Script::Call<Script::CallbackIdentity("OnServerExit")>(false);
luaState.getEventCtrl().Call<CoreEvent::ON_EXIT>(false);
CellController::destroy();
sThis = 0;
sThis = nullptr;
delete playerPacketController;
delete actorPacketController;
delete worldPacketController;
@ -86,13 +88,13 @@ bool Networking::isPassworded() const
void Networking::processPlayerPacket(RakNet::Packet *packet)
{
Player *player = Players::getPlayer(packet->guid);
auto player = Players::getPlayerByGUID(packet->guid);
PlayerPacket *myPacket = playerPacketController->GetPacket(packet->data[0]);
if (packet->data[0] == ID_HANDSHAKE)
{
myPacket->setPlayer(player);
myPacket->setPlayer(player.get());
myPacket->Read();
if (player->isHandshaked())
@ -125,15 +127,13 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
{
player->setLoadState(Player::LOADED);
static constexpr unsigned int ident = Script::CallbackIdentity("OnPlayerConnect");
Script::CallBackReturn<ident> result = true;
Script::Call<ident>(result, Players::getPlayer(packet->guid)->getId());
bool result = luaState.getEventCtrl().Call<CoreEvent::ON_PLAYER_CONNECT, bool>(player);
if (!result)
{
playerPacketController->GetPacket(ID_USER_DISCONNECTED)->setPlayer(Players::getPlayer(packet->guid));
playerPacketController->GetPacket(ID_USER_DISCONNECTED)->setPlayer(player.get());
playerPacketController->GetPacket(ID_USER_DISCONNECTED)->Send(false);
Players::deletePlayer(packet->guid);
Players::deletePlayerByGUID(packet->guid);
return;
}
}
@ -141,7 +141,7 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Received ID_PLAYER_BASEINFO about %s", player->npc.mName.c_str());
myPacket->setPlayer(player);
myPacket->setPlayer(player.get());
myPacket->Read();
myPacket->Send(true);
}
@ -163,7 +163,7 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
void Networking::processActorPacket(RakNet::Packet *packet)
{
Player *player = Players::getPlayer(packet->guid);
auto player = Players::getPlayerByGUID(packet->guid);
if (!player->isHandshaked() || player->getLoadState() != Player::POSTLOADED)
return;
@ -175,7 +175,7 @@ void Networking::processActorPacket(RakNet::Packet *packet)
void Networking::processWorldPacket(RakNet::Packet *packet)
{
Player *player = Players::getPlayer(packet->guid);
auto player = Players::getPlayerByGUID(packet->guid);
if (!player->isHandshaked() || player->getLoadState() != Player::POSTLOADED)
return;
@ -185,15 +185,15 @@ void Networking::processWorldPacket(RakNet::Packet *packet)
}
void Networking::update(RakNet::Packet *packet)
bool Networking::update(RakNet::Packet *packet)
{
Player *player = Players::getPlayer(packet->guid);
auto player = Players::getPlayerByGUID(packet->guid);
RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
bsIn.IgnoreBytes((unsigned int) RakNet::RakNetGUID::size()); // Ignore GUID from received packet
if (player == 0)
if (player == nullptr)
{
if (packet->data[0] == ID_GAME_PREINIT)
{
@ -223,7 +223,6 @@ void Networking::update(RakNet::Packet *packet)
// the server
if (it == hashList.end())
break;
}
else // name is incorrect
break;
@ -245,33 +244,39 @@ void Networking::update(RakNet::Packet *packet)
packetPreInit.setChecksums(&tmp);
packetPreInit.Send(packet->systemAddress);
}
return;
return false;
}
playerPacketController->SetStream(&bsIn, 0);
playerPacketController->GetPacket(ID_HANDSHAKE)->RequestData(packet->guid);
Players::newPlayer(packet->guid);
player = Players::getPlayer(packet->guid);
return;
player = Players::addPlayer(packet->guid);
return false;
}
else if (playerPacketController->ContainsPacket(packet->data[0]))
if (playerPacketController->ContainsPacket(packet->data[0]))
{
playerPacketController->SetStream(&bsIn, 0);
processPlayerPacket(packet);
return true;
}
else if (actorPacketController->ContainsPacket(packet->data[0]))
if (actorPacketController->ContainsPacket(packet->data[0]))
{
actorPacketController->SetStream(&bsIn, 0);
processActorPacket(packet);
return true;
}
else if (worldPacketController->ContainsPacket(packet->data[0]))
if (worldPacketController->ContainsPacket(packet->data[0]))
{
worldPacketController->SetStream(&bsIn, 0);
processWorldPacket(packet);
return true;
}
else
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled RakNet packet with identifier %i has arrived", packet->data[0]);
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Unhandled RakNet packet with identifier %i has arrived", packet->data[0]);
return false;
}
void Networking::newPlayer(RakNet::RakNetGUID guid)
@ -284,27 +289,24 @@ void Networking::newPlayer(RakNet::RakNetGUID guid)
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Sending info about other players to %lu", guid.g);
for (TPlayers::iterator pl = players->begin(); pl != players->end(); pl++) //sending other players to new player
Players::for_each([this, &guid](auto pl) //sending other players to new player
{
// If we are iterating over the new player, don't send the packets below
if (pl->first == guid) continue;
if (pl->guid == guid) return;
// If an invalid key makes it into the Players map, ignore it
else if (pl->first == RakNet::UNASSIGNED_RAKNET_GUID) continue;
// if player not fully connected
else if (pl->second == nullptr) continue;
else if (pl->guid == RakNet::UNASSIGNED_RAKNET_GUID) return;
// If we are iterating over a player who has inputted their name, proceed
else if (pl->second->getLoadState() == Player::POSTLOADED)
else if (pl->getLoadState() == Player::POSTLOADED)
{
playerPacketController->GetPacket(ID_PLAYER_BASEINFO)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_SKILL)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_POSITION)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_CELL_CHANGE)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_EQUIPMENT)->setPlayer(pl->second);
playerPacketController->GetPacket(ID_PLAYER_BASEINFO)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_SKILL)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_POSITION)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_CELL_CHANGE)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_EQUIPMENT)->setPlayer(pl.get());
playerPacketController->GetPacket(ID_PLAYER_BASEINFO)->Send(guid);
playerPacketController->GetPacket(ID_PLAYER_STATS_DYNAMIC)->Send(guid);
@ -314,7 +316,7 @@ void Networking::newPlayer(RakNet::RakNetGUID guid)
playerPacketController->GetPacket(ID_PLAYER_CELL_CHANGE)->Send(guid);
playerPacketController->GetPacket(ID_PLAYER_EQUIPMENT)->Send(guid);
}
}
});
LOG_APPEND(Log::LOG_WARN, "- Done");
@ -322,14 +324,15 @@ void Networking::newPlayer(RakNet::RakNetGUID guid)
void Networking::disconnectPlayer(RakNet::RakNetGUID guid)
{
Player *player = Players::getPlayer(guid);
if (!player)
auto player = Players::getPlayerByGUID(guid);
if (player == nullptr)
return;
Script::Call<Script::CallbackIdentity("OnPlayerDisconnect")>(player->getId());
playerPacketController->GetPacket(ID_USER_DISCONNECTED)->setPlayer(player);
luaState.getEventCtrl().Call<CoreEvent::ON_PLAYER_DISCONNECT>(player);
playerPacketController->GetPacket(ID_USER_DISCONNECTED)->setPlayer(player.get());
playerPacketController->GetPacket(ID_USER_DISCONNECTED)->Send(true);
Players::deletePlayer(guid);
Players::deletePlayerByGUID(guid);
}
PlayerPacketController *Networking::getPlayerPacketController() const
@ -370,11 +373,11 @@ void Networking::setCurrentMpNum(int value)
int Networking::incrementMpNum()
{
currentMpNum++;
Script::Call<Script::CallbackIdentity("OnMpNumIncrement")>(currentMpNum);
luaState.getEventCtrl().Call<CoreEvent::ON_MP_REFNUM>(currentMpNum);
return currentMpNum;
}
const Networking &Networking::get()
Networking &Networking::get()
{
return *sThis;
}
@ -397,16 +400,14 @@ PacketPreInit::PluginContainer Networking::getPluginListSample()
while (true)
{
unsigned field = 0;
auto name = "";
Script::Call<Script::CallbackIdentity("OnRequestPluginList")>(name, id, field++);
if (strlen(name) == 0)
auto name = luaState.getEventCtrl().Call<CoreEvent::ON_REQUEST_PLUGIN_LIST, string>(id, field++);
if (name.size() == 0)
break;
PacketPreInit::HashList hashList;
while (true)
{
auto hash = "";
Script::Call<Script::CallbackIdentity("OnRequestPluginList")>(hash, id, field++);
if (strlen(hash) == 0)
auto hash = luaState.getEventCtrl().Call<CoreEvent::ON_REQUEST_PLUGIN_LIST, string>(id, field++);
if (hash.size() == 0)
break;
hashList.push_back((unsigned)stoul(hash));
}
@ -426,8 +427,11 @@ int Networking::mainLoop()
{
RakNet::Packet *packet;
auto &timerCtrl = luaState.getTimerCtrl();
while (running)
{
bool updated = false;
if (kbhit() && getch() == '\n')
break;
for (packet=peer->Receive(); packet; peer->DeallocatePacket(packet), packet=peer->Receive())
@ -469,15 +473,22 @@ int Networking::mainLoop()
case ID_UNCONNECTED_PING:
break;
default:
update(packet);
updated = update(packet);
break;
}
}
TimerAPI::Tick();
this_thread::sleep_for(chrono::milliseconds(1));
timerCtrl.tick();
if (updated)
{
// fixme: not good to call for_each every frame. Maybe for_each_Updated will be better
Players::for_each([](shared_ptr<Player> pl) {
pl->update();
});
}
this_thread::sleep_for (chrono::milliseconds(1));
}
TimerAPI::Terminate();
timerCtrl.terminate();
return exitCode;
}
@ -523,7 +534,7 @@ void Networking::InitQuery(std::string queryAddr, unsigned short queryPort)
void Networking::postInit()
{
Script::Call<Script::CallbackIdentity("OnServerPostInit")>();
luaState.getEventCtrl().Call<CoreEvent::ON_POST_INIT>();
samples = getPluginListSample();
if (mclient)
{

@ -9,7 +9,7 @@
#include <components/openmw-mp/Controllers/ActorPacketController.hpp>
#include <components/openmw-mp/Controllers/WorldPacketController.hpp>
#include <components/openmw-mp/Packets/PacketPreInit.hpp>
#include "Player.hpp"
#include <apps/openmw-mp/Script/LuaState.hpp>
class MasterClient;
namespace mwmp
@ -31,7 +31,7 @@ namespace mwmp
void processPlayerPacket(RakNet::Packet *packet);
void processActorPacket(RakNet::Packet *packet);
void processWorldPacket(RakNet::Packet *packet);
void update(RakNet::Packet *packet);
bool update(RakNet::Packet *packet);
unsigned short numberOfConnections() const;
unsigned int maxConnections() const;
@ -45,6 +45,8 @@ namespace mwmp
ActorPacketController *getActorPacketController() const;
WorldPacketController *getWorldPacketController() const;
LuaState &getState() {return luaState;}
BaseActorList *getLastActorList();
BaseEvent *getLastEvent();
@ -57,18 +59,18 @@ namespace mwmp
void setServerPassword(std::string passw) noexcept;
bool isPassworded() const;
static const Networking &get();
static Networking &get();
static Networking *getPtr();
void postInit();
private:
LuaState luaState;
PacketPreInit::PluginContainer getPluginListSample();
std::string serverPassword;
static Networking *sThis;
RakNet::RakPeerInterface *peer;
RakNet::BitStream bsOut;
TPlayers *players;
MasterClient *mclient;
BaseActorList baseActorList;

@ -0,0 +1,466 @@
//
// Created by koncord on 26.08.17.
//
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Object.hpp"
#include "Player.hpp"
#include "Networking.hpp"
using namespace std;
void Object::Init(LuaState &lua)
{
lua.getState()->new_usertype<Object>("Object",
"refId", sol::property(&BaseObject::getRefId, &BaseObject::setRefId),
"refNum", sol::property(&BaseObject::getRefNum, &BaseObject::setRefNum),
"mpNum", sol::property(&BaseObject::getMpNum, &BaseObject::setMpNum),
"setPosition", &Object::setPosition,
"getPosition", &Object::getPosition,
"setRotation", &Object::setRotation,
"getRotation", &Object::getRotation,
"count", sol::property(&Object::getCount, &Object::setCount),
"goldValue", sol::property(&Object::getGoldValue, &Object::setGoldValue),
"scale", sol::property(&Object::getScale, &Object::setScale),
"state", sol::property(&Object::getState, &Object::setState),
"doorState", sol::property(&Object::getDoorState, &Object::setDoorState),
"lockLevel", sol::property(&Object::getLockLevel, &Object::setLockLevel),
"setDisarmState", &Object::setDisarmState,
"setMasterState", &Object::setMasterState
);
}
Object::Object()
{
}
Object::~Object()
{
}
void Object::update()
{
}
tuple<float, float, float> Object::getPosition() const
{
return make_tuple(object.position.pos[0], object.position.pos[1], object.position.pos[2]);
}
void Object::setPosition(float x, float y, float z)
{
object.position.pos[0] = x;
object.position.pos[1] = y;
object.position.pos[2] = z;
changedObjectPlace = true;
}
tuple<float, float, float> Object::getRotation() const
{
return make_tuple(object.position.rot[0], object.position.rot[1], object.position.rot[2]);
}
void Object::setRotation(float x, float y, float z)
{
object.position.rot[0] = x;
object.position.rot[1] = y;
object.position.rot[2] = z;
changedObjectPlace = true;
}
BaseObject::BaseObject(): changedBase(false), copied(false)
{
}
string BaseObject::getRefId() const
{
return object.refId;
}
void BaseObject::setRefId(const string &refId)
{
changedBase = true;
object.refId = refId;
}
int BaseObject::getRefNum() const
{
return object.refNumIndex;
}
void BaseObject::setRefNum(int refNum)
{
changedBase = true;
object.refNumIndex = refNum;
}
int BaseObject::getMpNum() const
{
return object.mpNum;
}
void BaseObject::setMpNum(int mpNum)
{
changedBase = true;
object.mpNum = mpNum;
}
int Object::getCount() const
{
return object.count;
}
void Object::setCount(int count)
{
changedObjectPlace = true;
object.count = count;
}
int Object::getCharge() const
{
return object.charge;
}
void Object::setCharge(int charge)
{
changedObjectPlace = true;
object.charge = charge;
}
int Object::getGoldValue() const
{
return object.goldValue;
}
void Object::setGoldValue(int gold)
{
changedObjectPlace = true;
object.goldValue = gold;
}
float Object::getScale() const
{
return object.scale;
}
void Object::setScale(float scale)
{
changedObjectScale = true;
object.scale = scale;
}
bool Object::getState() const
{
return object.objectState;
}
void Object::setState(bool state)
{
changedObjectState = true;
object.objectState = state;
}
int Object::getDoorState() const
{
return object.doorState;
}
void Object::setDoorState(int state)
{
changedDoorState = true;
object.doorState = state;
}
int Object::getLockLevel() const
{
return object.lockLevel;
}
void Object::setLockLevel(int locklevel)
{
changedObjectLock = true;
object.lockLevel = locklevel;
}
void Object::setDisarmState(bool state)
{
changedObjectTrap = true;
object.isDisarmed = state;
}
void Object::setMasterState(bool state)
{
changedObjectSpawn = true;
object.hasMaster = state;
}
void Container::Init(LuaState &lua)
{
lua.getState()->new_usertype<Container>("Container",
"refId", sol::property(&BaseObject::getRefId, &BaseObject::setRefId),
"refNum", sol::property(&BaseObject::getRefNum, &BaseObject::setRefNum),
"mpNum", sol::property(&BaseObject::getMpNum, &BaseObject::setMpNum),
"getItem", &Container::getItem,
"addItem", &Container::addItem,
"setItem", &Container::setItem,
"getActionCount", &Container::getActionCount
);
}
Container::Container()
{
}
tuple<string, int, int> Container::getItem(int i) const
{
auto &item = object.containerItems.at(i);
return make_tuple(item.refId, item.count, item.charge);
}
void Container::setItem(int i, const string &refId, int count, int charge)
{
auto &item = object.containerItems.at(i);
item.refId = refId;
item.count = count;
item.charge = charge;
changed = true;
}
void Container::addItem(const string &refId, int count, int charge)
{
mwmp::ContainerItem item;
item.refId = refId;
item.count = count;
item.charge = charge;
object.containerItems.push_back(item);
changed = true;
}
int Container::getActionCount(int i) const
{
return object.containerItems.at(i).actionCount;
}
size_t Container::size() const
{
return object.containerItems.size();
}
void ObjectController::Init(LuaState &lua)
{
sol::table objectCtrl = lua.getState()->create_table("ObjectCtrl");
objectCtrl.set_function("sendObjects", [&lua](shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects) {
return lua.getObjectCtrl().sendObjects(player, objects);
});
objectCtrl.set_function("sendContainers", [&lua](shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Container>>> objects) {
return lua.getObjectCtrl().sendContainers(player, objects);
});
objectCtrl.set_function("requestContainers", [&lua](shared_ptr<Player> player) {
return lua.getObjectCtrl().requestContainers(player);
});
}
shared_ptr<vector<shared_ptr<Object>>> ObjectController::copyObjects(mwmp::BaseEvent &event)
{
auto objects = make_shared<vector<shared_ptr<Object>>>();
for(auto &obj : event.worldObjects)
{
auto object = new Object;
object->copied = true;
object->object = obj;
objects->emplace_back(object);
}
return objects;
}
shared_ptr<vector<shared_ptr<Container>>> ObjectController::copyContainers(mwmp::BaseEvent &event)
{
auto containers = make_shared<vector<shared_ptr<Container>>>();
for(auto &obj : event.worldObjects)
{
auto container = new Container;
container->copied = true;
container->object = obj;
containers->emplace_back(container);
}
return containers;
}
void ObjectController::sendObjects(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects)
{
enum Type
{
DOOR_STATE = 0,
OBJECT_STATE,
OBJECT_SCALE,
OBJECT_TRAP,
OBJECT_LOCK,
OBJECT_DELETE,
OBJECT_SPAWN,
OBJECT_PLACE,
LAST
};
mwmp::BaseEvent events[Type::LAST];
bool changed[Type::LAST];
for(auto &e : events)
{
e.action = mwmp::BaseEvent::SET;
e.guid = player->guid;
e.cell = player->cell;
}
for(auto &object : *objects)
{
//sendObject(player.get(), object.get());
bool validNewObjOrCopy = (!object->copied && object->changedBase) || object->copied;
if(object->changedDoorState && validNewObjOrCopy)
{
changed[Type::DOOR_STATE] = true;
events[Type::DOOR_STATE].worldObjects.push_back(object->object);
}
if(object->changedObjectState && validNewObjOrCopy)
{
changed[Type::OBJECT_STATE] = true;
events[Type::OBJECT_STATE].worldObjects.push_back(object->object);
}
if(object->changedObjectScale && validNewObjOrCopy)
{
changed[Type::OBJECT_SCALE] = true;
events[Type::OBJECT_SCALE].worldObjects.push_back(object->object);
}
if(object->changedObjectTrap && validNewObjOrCopy)
{
changed[Type::OBJECT_TRAP] = true;
events[Type::OBJECT_TRAP].worldObjects.push_back(object->object);
}
if(object->changedObjectLock && validNewObjOrCopy)
{
changed[Type::OBJECT_LOCK] = true;
events[Type::OBJECT_LOCK].worldObjects.push_back(object->object);
}
if(object->changedObjectDelete && validNewObjOrCopy)
{
changed[Type::OBJECT_DELETE] = true;
events[Type::OBJECT_DELETE].worldObjects.push_back(object->object);
}
if(object->changedObjectSpawn && validNewObjOrCopy)
{
changed[Type::OBJECT_SPAWN] = true;
events[Type::OBJECT_SPAWN].worldObjects.push_back(object->object);
}
if(object->changedObjectPlace && validNewObjOrCopy)
{
changed[Type::OBJECT_PLACE] = true;
events[Type::OBJECT_PLACE].worldObjects.push_back(object->object);
}
}
auto worldCtrl = mwmp::Networking::get().getWorldPacketController();
if(changed[Type::DOOR_STATE])
{
auto packet = worldCtrl->GetPacket(ID_DOOR_STATE);
auto &event = events[Type::DOOR_STATE];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_STATE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_STATE);
auto &event = events[Type::OBJECT_STATE];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_SCALE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_SCALE);
auto &event = events[Type::OBJECT_SCALE];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_TRAP])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_TRAP);
auto &event = events[Type::OBJECT_TRAP];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_LOCK])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_LOCK);
auto &event = events[Type::OBJECT_LOCK];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_DELETE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_DELETE);
auto &event = events[Type::OBJECT_DELETE];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_SCALE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_SPAWN);
auto &event = events[Type::OBJECT_SCALE];
packet->setEvent(&event);
packet->Send(event.guid);
}
if(changed[Type::OBJECT_PLACE])
{
auto packet = worldCtrl->GetPacket(ID_OBJECT_PLACE);
auto &event = events[Type::OBJECT_PLACE];
packet->setEvent(&event);
packet->Send(event.guid);
}
}
void ObjectController::sendContainers(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Container>>> objects)
{
mwmp::BaseEvent event;
event.cell = player->cell;
event.action = mwmp::BaseEvent::SET;
event.guid = player->guid;
for(auto &object : *objects)
{
bool validNewObjOrCopy = (!object->copied && object->changedBase) || object->copied;
if(object->changed && validNewObjOrCopy)
event.worldObjects.push_back(object->object);
}
auto packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER);
packet->setEvent(&event);
packet->Send(event.guid);
}
void ObjectController::requestContainers(shared_ptr<Player> player)
{
mwmp::BaseEvent event;
event.action = mwmp::BaseEvent::REQUEST;
event.guid = player->guid;
event.cell = player->cell;
auto packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER);
packet->setEvent(&event);
packet->Send(event.guid);
}

@ -0,0 +1,119 @@
//
// Created by koncord on 26.08.17.
//
#pragma once
#include <tuple>
#include <components/openmw-mp/Base/BaseEvent.hpp>
#include <memory>
class LuaState;
class Player;
class BaseObject
{
public:
BaseObject();
std::string getRefId() const;
void setRefId(const std::string &refId);
int getRefNum() const;
void setRefNum(int refNum);
int getMpNum() const;
void setMpNum(int mpNum);
//void setEventCell(const std::string &cellDescription);
mwmp::WorldObject object;
bool changedBase;
bool copied;
};
class Object : public BaseObject
{
public:
static void Init(LuaState &lua);
public:
Object();
~Object();
void update();
/**
*
* @return x, y, z
*/
std::tuple<float, float, float> getPosition() const;
void setPosition(float x, float y, float z);
/**
*
* @return x, y, z
*/
std::tuple<float, float, float> getRotation() const;
void setRotation(float x, float y, float z);
int getCount() const;
void setCount(int count);
int getCharge() const;
void setCharge(int charge);
int getGoldValue() const;
void setGoldValue(int gold);
float getScale() const;
void setScale(float scale);
bool getState() const;
void setState(bool state);
int getDoorState() const;
void setDoorState(int state);
int getLockLevel() const;
void setLockLevel(int locklevel);
void setDisarmState(bool state);
void setMasterState(bool state);
bool changedDoorState, changedObjectState, changedObjectScale, changedObjectTrap, changedObjectLock,
changedObjectDelete, changedObjectSpawn, changedObjectPlace;
};
class Container : public BaseObject
{
public:
static void Init(LuaState &lua);
public:
Container();
std::tuple<std::string, int, int> getItem(int i) const;
void addItem(const std::string &refId, int count, int charge);
void setItem(int i, const std::string &refId, int count, int charge);
int getActionCount(int i) const;
size_t size() const;
bool changed;
};
class ObjectController
{
public:
static void Init(LuaState &lua);
public:
std::shared_ptr<std::vector<std::shared_ptr<Object>>> copyObjects(mwmp::BaseEvent &event);
std::shared_ptr<std::vector<std::shared_ptr<Container>>> copyContainers(mwmp::BaseEvent &event);
void sendObjects(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Object>>> objects);
void sendContainers(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Container>>> objects);
void requestContainers(std::shared_ptr<Player> player);
};

@ -2,79 +2,194 @@
// Created by koncord on 05.01.16.
//
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Player.hpp"
#include "Networking.hpp"
#include "Inventory.hpp"
#include "Settings.hpp"
TPlayers Players::players;
TSlots Players::slots;
using namespace std;
void Players::deletePlayer(RakNet::RakNetGUID guid)
void Player::Init(LuaState &lua)
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Deleting player with guid %lu", guid.g);
if (players[guid] != 0)
{
CellController::get()->deletePlayer(players[guid]);
LOG_APPEND(Log::LOG_INFO, "- Emptying slot %i", players[guid]->getId());
lua.getState()->new_usertype<Player>("Player",
"getPosition", &NetActor::getPosition,
"setPosition", &NetActor::setPosition,
"getRotation", &NetActor::getRotation,
"setRotation", &NetActor::setRotation,
"getHealth", &NetActor::getHealth,
"setHealth", &NetActor::setHealth,
"getMagicka", &NetActor::getMagicka,
"setMagicka", &NetActor::setMagicka,
"getFatigue", &NetActor::getFatigue,
"setFatigue", &NetActor::setFatigue,
"getCell", &NetActor::getCell,
"getInventory", &NetActor::getInventory,
"getPreviousCellPos", &Player::getPreviousCellPos,
"kick", &Player::kick,
"ban", &Player::ban,
"address", sol::property(&Player::getIP),
"getAvgPing", &Player::getAvgPing,
"message", &Player::message,
"cleanChat", &Player::cleanChat,
"pid", sol::readonly_property(&Player::id),
"guid", sol::readonly_property(&Player::getGUID),
"name", sol::property(&Player::getName, &Player::setName),
"setCharGenStage", &Player::setCharGenStage,
"isMale", &Player::isMale,
"setIsMake", &Player::setIsMale,
"level", sol::property(&Player::getLevel, &Player::setLevel),
"race", sol::property(&Player::getRace, &Player::setRace),
"head", sol::property(&Player::getHead, &Player::setHead),
"hair", sol::property(&Player::getHair, &Player::setHair),
"birthsign", sol::property(&Player::getBirthsign, &Player::setBirthsign),
"bounty", sol::property(&Player::getBounty, &Player::setBounty),
"levelProgress", sol::property(&Player::getLevelProgress, &Player::setLevelProgress),
"creatureModel", sol::property(&Player::getCreatureModel, &Player::setCreatureModel),
"isCreatureName", sol::property(&Player::isCreatureName, &Player::creatureName),
"resurrect", &Player::resurrect,
"jail", &Player::jail,
"werewolf", sol::property(&Player::getWerewolfState, &Player::setWerewolfState),
"getAttribute", &Player::getAttribute,
"setAttribute", &Player::setAttribute,
"getSkill", &Player::getSkill,
"setSkill", &Player::setSkill,
"getClass", &Player::getCharClass,
"getSettings", &Player::getSettings,
"getBooks", &Player::getBooks,
"getGUI", &Player::getGUI,
"getDialogue", &Player::getDialogue,
"getFactions", &Player::getFactions,
"getQuests", &Player::getQuests,
"getSpells", &Player::getSpells,
"getCellState", &Player::getCellState,
"cellStateSize", &Player::cellStateSize,
"addCellExplored", &Player::addCellExplored,
"setAuthority", &Player::setAuthority
);
}
slots[players[guid]->getId()] = 0;
delete players[guid];
players.erase(guid);
}
Player::Player(RakNet::RakNetGUID guid) : BasePlayer(guid), NetActor(), changedMap(false), cClass(this),
settings(this), books(this), gui(this), dialogue(this), factions(this),
quests(this), spells(this)
{
basePlayer = this;
netCreature = this;
printf("Player::Player()\n");
handshakeState = false;
loadState = NOTLOADED;
resetUpdateFlags();
cell.blank();
npc.blank();
npcStats.blank();
creatureStats.blank();
charClass.blank();
}
void Players::newPlayer(RakNet::RakNetGUID guid)
Player::~Player()
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Creating new player with guid %lu", guid.g);
printf("Player::~Player()\n");
CellController::get()->deletePlayer(this);
}
players[guid] = new Player(guid);
players[guid]->cell.blank();
players[guid]->npc.blank();
players[guid]->npcStats.blank();
players[guid]->creatureStats.blank();
players[guid]->charClass.blank();
players[guid]->isWerewolf = false;
void Player::update()
{
auto plPCtrl = mwmp::Networking::get().getPlayerPacketController();
for (unsigned int i = 0; i < mwmp::Networking::get().maxConnections(); i++)
if (inventory.isEquipmentChanged())
{
if (slots[i] == 0)
{
LOG_APPEND(Log::LOG_INFO, "- Storing in slot %i", i);
slots[i] = players[guid];
slots[i]->setId(i);
break;
}
auto packet = plPCtrl->GetPacket(ID_PLAYER_EQUIPMENT);
packet->setPlayer(this);
packet->Send(false);
packet->Send(true);
inventory.resetEquipmentFlag();
}
}
Player *Players::getPlayer(RakNet::RakNetGUID guid)
{
if (players.count(guid) == 0)
return nullptr;
return players[guid];
}
if (inventory.inventoryChangeType() != 0)
{
auto packet = plPCtrl->GetPacket(ID_PLAYER_EQUIPMENT);
packet->setPlayer(this);
packet->Send(/*toOthers*/ false);
inventory.resetInventoryFlag();
}
TPlayers *Players::getPlayers()
{
return &players;
}
if (attributesChanged)
{
auto packet = plPCtrl->GetPacket(ID_PLAYER_ATTRIBUTE);
packet->setPlayer(basePlayer);
packet->Send(false);
packet->Send(true);
}
if (statsChanged)
{
auto packet = plPCtrl->GetPacket(ID_PLAYER_STATS_DYNAMIC);
packet->setPlayer(basePlayer);
packet->Send(false);
packet->Send(true);
}
if (skillsChanged)
{
auto packet = plPCtrl->GetPacket(ID_PLAYER_SKILL);
packet->setPlayer(basePlayer);
packet->Send(false);
packet->Send(true);
}
if (baseInfoChanged)
{
auto packet = plPCtrl->GetPacket(ID_PLAYER_BASEINFO);
packet->setPlayer(basePlayer);
packet->Send(false);
packet->Send(true);
}
unsigned short Players::getLastPlayerId()
{
return slots.rbegin()->first;
}
if (positionChanged)
{
auto packet = plPCtrl->GetPacket(ID_PLAYER_POSITION);
packet->setPlayer(basePlayer);
packet->Send(false);
}
Player::Player(RakNet::RakNetGUID guid) : BasePlayer(guid)
{
handshakeState = false;
loadState = NOTLOADED;
}
if (changedMap)
{
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MAP);
packet->setPlayer(this);
packet->Send(/*toOthers*/ false);
changedMap = false;
}
Player::~Player()
{
if (cellAPI.isChangedCell())
{
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CELL_CHANGE);
packet->setPlayer(this);
packet->Send(/*toOthers*/ false);
cellAPI.resetChangedCell();
}
cClass.update();
settings.update();
books.update();
gui.update();
dialogue.update();
factions.update();
cellAPI.update();
quests.update();
spells.update();
resetUpdateFlags();
}
unsigned short Player::getId()
@ -107,13 +222,6 @@ int Player::getLoadState()
return loadState;
}
Player *Players::getPlayer(unsigned short id)
{
if (slots.find(id) == slots.end())
return nullptr;
return slots[id];
}
CellController::TContainer *Player::getCells()
{
return &cells;
@ -160,3 +268,348 @@ void Player::forEachLoaded(std::function<void(Player *pl, Player *other)> func)
func(this, pl);
}
}
void Player::kick() const
{
mwmp::Networking::getPtr()->kickPlayer(guid);
}
void Player::ban() const
{
auto netCtrl = mwmp::Networking::getPtr();
RakNet::SystemAddress addr = netCtrl->getSystemAddress(guid);
netCtrl->banAddress(addr.ToString(false));
}
void Player::cleanChat()
{
chatMessage.clear();
auto packet = mwmp::Networking::get().getPlayerPacketController();
packet->GetPacket(ID_CHAT_MESSAGE)->setPlayer(this);
packet->GetPacket(ID_CHAT_MESSAGE)->Send(false);
}
std::string Player::getIP() const
{
RakNet::SystemAddress addr = mwmp::Networking::getPtr()->getSystemAddress(guid);
return addr.ToString(false);
}
int Player::getAvgPing()
{
return mwmp::Networking::get().getAvgPing(guid);
}
void Player::setName(const std::string &name)
{
npc.mName = name;
baseInfoChanged = true;
}
std::string Player::getName()
{
return npc.mName;
}
void Player::setCharGenStage(int start, int end)
{
charGenStage.current = start;
charGenStage.end = end;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARGEN);
packet->setPlayer(this);
packet->Send(false);
}
void Player::message(const std::string &message, bool toAll)
{
chatMessage = message;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE);
packet->setPlayer(this);
packet->Send(false);
if (toAll)
packet->Send(true);
}
bool Player::isMale() const
{
return npc.isMale();
}
void Player::setIsMale(bool male)
{
npc.setIsMale(male);
baseInfoChanged = true;
}
void Player::setLevel(int level)
{
creatureStats.mLevel = level;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL);
packet->setPlayer(this);
packet->Send(false);
packet->Send(true);
}
int Player::getLevel() const
{
return creatureStats.mLevel;
}
void Player::setRace(const std::string &race)
{
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Setting race for %s: %s -> %s", npc.mName.c_str(), npc.mRace.c_str(), race.c_str());
npc.mRace = race;
baseInfoChanged = true;
}
std::string Player::getRace() const
{
return npc.mRace;
}
void Player::setHead(const std::string &head)
{
npc.mHead = head;
baseInfoChanged = true;
}
std::string Player::getHead() const
{
return npc.mHead;
}
void Player::setHair(const std::string &hair)
{
npc.mHair = hair;
baseInfoChanged = true;
}
std::string Player::getHair() const
{
return npc.mHair;
}
std::string Player::getBirthsign() const
{
return birthsign;
}
void Player::setBirthsign(const std::string &sign)
{
birthsign = sign;
baseInfoChanged = true;
}
int Player::getBounty() const
{
return npcStats.mBounty;
}
void Player::setBounty(int bounty)
{
npcStats.mBounty = bounty;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY);
packet->setPlayer(this);
packet->Send(false);
packet->Send(true);
}
void Player::setLevelProgress(int progress)
{
npcStats.mLevelProgress = progress;
skillsChanged = true;
}
int Player::getLevelProgress() const
{
return npcStats.mLevelProgress;
}
void Player::setCreatureModel(const std::string &model)
{
creatureModel = model;
baseInfoChanged = true;
}
std::string Player::getCreatureModel() const
{
return creatureModel;
}
void Player::creatureName(bool useName)
{
useCreatureName = useName;
baseInfoChanged = true;
}
bool Player::isCreatureName() const
{
return useCreatureName;
}
std::tuple<int, int> Player::getAttribute(unsigned short id) const
{
if (id >= ESM::Attribute::Length)
return make_tuple(0, 0);
return make_tuple(creatureStats.mAttributes[id].mBase, creatureStats.mAttributes[id].mCurrent);
}
void Player::setAttribute(unsigned short id, int base, int current)
{
if (id >= ESM::Attribute::Length)
return;
creatureStats.mAttributes[id].mBase = base;
creatureStats.mAttributes[id].mCurrent = current;
attributesChanged = true;
}
std::tuple<int, int, float, int> Player::getSkill(unsigned short id) const
{
if (id >= ESM::Skill::Length)
return make_tuple(0, 0, 0.0f, 0);
const auto &skill = npcStats.mSkills[id];
return make_tuple(skill.mBase, skill.mCurrent, skill.mProgress, npcStats.mSkillIncrease[id]);
}
void Player::setSkill(unsigned short id, int base, int current, float progress, int increase)
{
if (id >= ESM::Skill::Length)
return;
auto &skill = npcStats.mSkills[id];
skill.mBase = base;
skill.mCurrent = current;
skill.mProgress = progress;
npcStats.mSkillIncrease[id] = increase;
skillsChanged = true;
}
CharClass &Player::getCharClass(sol::this_state thisState)
{
return cClass;
}
GameSettings &Player::getSettings()
{
return settings;
}
Books &Player::getBooks()
{
return books;
}
GUI &Player::getGUI()
{
return gui;
}
Dialogue &Player::getDialogue()
{
return dialogue;
}
Factions &Player::getFactions()
{
return factions;
}
Quests &Player::getQuests()
{
return quests;
}
Spells &Player::getSpells()
{
return spells;
}
std::tuple<float, float, float> Player::getPreviousCellPos() const
{
return make_tuple(previousCellPosition.pos[0], previousCellPosition.pos[1], previousCellPosition.pos[2]);
}
void Player::resurrect(unsigned int type)
{
resurrectType = type;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_RESURRECT);
packet->setPlayer(this);
packet->Send(false);
packet->Send(true);
}
void Player::jail(int jailDays, bool ignoreJailTeleportation, bool ignoreJailSkillIncreases,
const std::string &jailProgressText, const std::string &jailEndText)
{
this->jailDays = jailDays;
this->ignoreJailTeleportation = ignoreJailTeleportation;
this->ignoreJailSkillIncreases = ignoreJailSkillIncreases;
this->jailProgressText = jailProgressText;
this->jailEndText = jailEndText;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_JAIL);
packet->setPlayer(this);
packet->Send(false);
}
void Player::setWerewolfState(bool state)
{
isWerewolf = state;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SHAPESHIFT);
packet->setPlayer(this);
packet->Send(false);
packet->Send(true);
}
bool Player::getWerewolfState() const
{
return isWerewolf;
}
size_t Player::cellStateSize() const
{
return cellStateChanges.cellStates.size();
}
void Player::addCellExplored(const std::string &cellDescription)
{
auto cellExplored = Utils::getCellFromDescription(cellDescription);
mapChanges.cellsExplored.push_back(cellExplored);
changedMap = true;
}
CellState Player::getCellState(int i)
{
return CellState(cellStateChanges.cellStates.at(i));
}
void Player::setAuthority()
{
mwmp::BaseActorList writeActorList;
writeActorList.cell = cell;
writeActorList.guid = guid;
Cell *serverCell = CellController::get()->getCell(&cell);
if (serverCell != nullptr)
{
serverCell->setAuthority(guid);
mwmp::ActorPacket *authorityPacket = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_AUTHORITY);
authorityPacket->setActorList(&writeActorList);
authorityPacket->Send(writeActorList.guid);
// Also send this to everyone else who has the cell loaded
serverCell->sendToLoaded(authorityPacket, &writeActorList);
}
}

@ -8,6 +8,7 @@
#include <map>
#include <string>
#include <chrono>
#include <memory>
#include <RakNetTypes.h>
#include <components/esm/npcstats.hpp>
@ -18,32 +19,30 @@
#include <components/openmw-mp/Log.hpp>
#include <components/openmw-mp/Base/BasePlayer.hpp>
#include <components/openmw-mp/Packets/Player/PlayerPacket.hpp>
#include <apps/openmw-mp/Script/LuaState.hpp>
#include "Cell.hpp"
#include "CellController.hpp"
struct Player;
typedef std::map<RakNet::RakNetGUID, Player*> TPlayers;
typedef std::map<unsigned short, Player*> TSlots;
class Players
{
public:
static void newPlayer(RakNet::RakNetGUID guid);
static void deletePlayer(RakNet::RakNetGUID guid);
static Player *getPlayer(RakNet::RakNetGUID guid);
static Player *getPlayer(unsigned short id);
static TPlayers *getPlayers();
static unsigned short getLastPlayerId();
private:
static TPlayers players;
static TSlots slots;
};
class Player : public mwmp::BasePlayer
#include "CharClass.hpp"
#include "Inventory.hpp"
#include "Settings.hpp"
#include "Books.hpp"
#include "GUI.hpp"
#include "Dialogue.hpp"
#include "Factions.hpp"
#include "Cells.hpp"
#include "Quests.hpp"
#include "Spells.hpp"
#include "NetActor.hpp"
#include "CellState.hpp"
class Player : public mwmp::BasePlayer, public NetActor
{
friend class Cell;
friend class Players;
unsigned short id;
uint64_t getGUID() const {return guid.g;}
public:
static void Init(LuaState &lua);
public:
enum
@ -52,7 +51,7 @@ public:
LOADED,
POSTLOADED
};
Player(RakNet::RakNetGUID guid);
explicit Player(RakNet::RakNetGUID guid);
unsigned short getId();
void setId(unsigned short id);
@ -70,11 +69,126 @@ public:
void forEachLoaded(std::function<void(Player *pl, Player *other)> func);
void update();
public:
void kick() const;
void ban() const;
void cleanChat();
int getAvgPing();
void setName(const std::string &name);
std::string getName();
void setCharGenStage(int start, int end);
void message(const std::string &message, bool toAll = false);
bool isMale() const;
void setIsMale(bool male);
void setRace(const std::string &race);
std::string getRace() const;
void setHead(const std::string &head);
std::string getHead() const;
void setHair(const std::string &hair);
std::string getHair() const;
std::string getBirthsign() const;
void setBirthsign(const std::string &sign);
int getBounty() const;
void setBounty(int bounty);
void setLevel(int level);
int getLevel() const;
void setLevelProgress(int progress);
int getLevelProgress() const;
/**
* \brief Send a PlayerResurrect packet about a player.
*
* This sends the packet to all players connected to the server.
*
* \param type The type of resurrection (0 for REGULAR, 1 for IMPERIAL_SHRINE, 2 for TRIBUNAL_TEMPLE).
*/
void resurrect(unsigned int type);
/**
* \brief Send a PlayerJail packet about a player.
*
* This is similar to the player being jailed by a guard, but provides extra parameters for
* increased flexibility.
*
* It is only sent to the player being jailed, as the other players will be informed of the
* jailing's actual consequences via other packets sent by the affected client.
*
* \param jailDays The number of days to spend jailed, where each day affects one skill point.
* \param ignoreJailTeleportation Whether the player being teleported to the nearest jail
* marker should be overridden.
* \param ignoreJailSkillIncrease Whether the player's Sneak and Security skills should be
* prevented from increasing as a result of the jailing,
* overriding default behavior.
* \param jailProgressText The text that should be displayed while jailed.
* \param jailEndText The text that should be displayed once the jailing period is over.
*/
void jail(int jailDays, bool ignoreJailTeleportation, bool ignoreJailSkillIncreases,
const std::string &jailProgressText, const std::string &jailEndText);
void setWerewolfState(bool state);
bool getWerewolfState() const;
void setCreatureModel(const std::string &model);
std::string getCreatureModel() const;
void creatureName(bool useName);
bool isCreatureName() const;
std::string getIP() const;
/**
*
* @return x, y, z
*/
std::tuple<float, float, float> getPreviousCellPos() const;
/**
*
* @return base, current
*/
std::tuple<int, int> getAttribute(unsigned short id) const;
void setAttribute(unsigned short id, int base, int current);
/**
*
* @return base, current, progress, increase
*/
std::tuple<int, int, float, int> getSkill(unsigned short id) const;
void setSkill(unsigned short id, int base, int current, float progress, int increase);
CellState getCellState(int i);
size_t cellStateSize() const;
void addCellExplored(const std::string &cellDescription);
CharClass &getCharClass(sol::this_state thisState);
GameSettings &getSettings();
Books &getBooks();
GUI &getGUI();
Dialogue &getDialogue();
Factions &getFactions();
Quests &getQuests();
Spells &getSpells();
void setAuthority();
private:
CellController::TContainer cells;
bool handshakeState;
int loadState;
bool /*statsChanged, attributesChanged, skillsChanged, baseInfoChanged, positionChanged,*/ changedMap;
CharClass cClass;
GameSettings settings;
Books books;
GUI gui;
Dialogue dialogue;
Factions factions;
Quests quests;
Spells spells;
};
#endif //OPENMW_PLAYER_HPP

@ -0,0 +1,113 @@
//
// Created by koncord on 12.08.17.
//
#include "Players.hpp"
using namespace std;
Players::Store Players::store;
void Players::Init(LuaState &lua)
{
sol::table playersTable = lua.getState()->create_named_table("Players");
playersTable.set_function("getByPID", &Players::getPlayerByPID);
playersTable.set_function("getByGUID", &Players::getPlayerByGUID);
playersTable.set_function("for_each", [](sol::function func)
{
for (shared_ptr<Player> player : store)
func(player);
});
}
std::shared_ptr<Player> Players::getPlayerByPID(int pid)
{
const auto &ls = store.get<ByID>();
auto it = ls.find(pid);
if (it != ls.end())
return *it;
return nullptr;
}
std::shared_ptr<Player> Players::getPlayerByGUID(RakNet::RakNetGUID guid)
{
const auto &ls = store.get<ByGUID>();
auto it = ls.find(guid.g);
if (it != ls.end())
return *it;
return nullptr;
}
std::shared_ptr<Player> Players::addPlayer(RakNet::RakNetGUID guid)
{
const int maxConnections = 65535;
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Creating new player with guid %lu", guid.g);
auto player = make_shared<Player>(guid);
unsigned short findPid = 0;
const auto &ls = store.get<ByID>();
for (; findPid < maxConnections; ++findPid) // find empty slot
{
auto it = ls.find(findPid);
if (it == ls.end())
break;
}
if (findPid >= maxConnections)
return nullptr;
LOG_APPEND(Log::LOG_INFO, "- Storing in slot %i", findPid);
player->id = findPid;
player->guid = guid;
store.push_back(player);
return player;
}
void Players::deletePlayerByPID(int pid)
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Marking player (pid %lu) to deleting", pid);
auto &ls = store.get<ByID>();
auto it = ls.find(pid);
if (it != ls.end())
{
ls.erase(it);
}
}
void Players::deletePlayerByGUID(RakNet::RakNetGUID guid)
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Marking player (guid %lu) to deleting", guid.g);
auto &ls = store.get<ByGUID>();
auto it = ls.find(guid.g);
if (it != ls.end())
{
LOG_APPEND(Log::LOG_INFO, "- references: %d", it->use_count());
ls.erase(it);
LOG_APPEND(Log::LOG_INFO, "- references: %d", it->use_count());
}
}
void Players::for_each(std::function<void (std::shared_ptr<Player>)> func)
{
for (auto &player : store)
func(player);
}
Players::Store::const_iterator Players::begin()
{
return store.cbegin();
}
Players::Store::const_iterator Players::end()
{
return store.cend();
}
size_t Players::size()
{
return store.size();
}

@ -0,0 +1,53 @@
//
// Created by koncord on 12.08.17.
//
#pragma once
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include "Player.hpp"
class LuaState;
class Players
{
public:
static void Init(LuaState &lua);
public:
Players() = delete; // static class
protected:
struct ByID {};
struct ByGUID {};
public:
typedef boost::multi_index_container<std::shared_ptr<Player>,
boost::multi_index::indexed_by<
boost::multi_index::random_access<>,
boost::multi_index::ordered_unique<boost::multi_index::tag<ByGUID>, BOOST_MULTI_INDEX_CONST_MEM_FUN(Player, uint64_t, getGUID)>,
boost::multi_index::ordered_unique<boost::multi_index::tag<ByID>, boost::multi_index::member<Player, unsigned short, &Player::id> >
> > Store;
static std::shared_ptr<Player> getPlayerByPID(int pid);
static std::shared_ptr<Player> getPlayerByGUID(RakNet::RakNetGUID guid);
static std::shared_ptr<Player> addPlayer(RakNet::RakNetGUID guid);
static void deletePlayerByPID(int pid);
static void deletePlayerByGUID(RakNet::RakNetGUID guid);
static Store::const_iterator begin();
static Store::const_iterator end();
static size_t size();
static void for_each(std::function<void(std::shared_ptr<Player>)> func);
private:
static Store store;
};

@ -0,0 +1,161 @@
//
// Created by koncord on 25.08.17.
//
#include "Quests.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
#include "Script/LuaState.hpp"
#include "Player.hpp"
#include "Networking.hpp"
void JournalItem::Init(LuaState &lua)
{
lua.getState()->new_usertype<JournalItem>("JournalItem",
"quest", sol::property(&JournalItem::getQuest, &JournalItem::setQuest),
"index", sol::property(&JournalItem::getIndex, &JournalItem::setIndex),
"actorRefId", sol::property(&JournalItem::getActorRefId, &JournalItem::setActorRefId),
"type", sol::property(&JournalItem::getType, &JournalItem::setType)
);
}
JournalItem::JournalItem(mwmp::JournalItem item) : item(item)
{
}
JournalItem::~JournalItem()
{
}
std::string JournalItem::getQuest() const
{
return item.quest;
}
void JournalItem::setQuest(const std::string &quest)
{
item.quest = quest;
}
int JournalItem::getIndex() const
{
return item.index;
}
void JournalItem::setIndex(int index)
{
item.index = index;
}
int JournalItem::getType() const
{
return item.type;
}
void JournalItem::setType(int type)
{
item.type = type;
}
std::string JournalItem::getActorRefId() const
{
return item.actorRefId;
}
void JournalItem::setActorRefId(const std::string &refid)
{
item.actorRefId = refid;
}
void Quests::Init(LuaState &lua)
{
lua.getState()->new_usertype<Quests>("Quests",
"getJournalChangesSize", &Quests::getJournalChangesSize,
"getKillChangesSize", &Quests::getKillChangesSize,
"addJournalItem", &Quests::addJournalItem,
"setJournalItem", &Quests::setJournalItem,
"getJournalItem", &Quests::getJournalItem,
"addKill", &Quests::addKill,
"getKillRefId", &Quests::getKillRefId,
"getKillNumber", &Quests::getKillNumber
);
}
Quests::Quests(Player *player) : player(player), changedKills(false), changedJournal(false)
{
}
Quests::~Quests()
{
}
void Quests::update()
{
if (changedJournal)
{
changedJournal = false;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_JOURNAL);
packet->setPlayer(player);
packet->Send(/*toOthers*/ false);
}
if (changedKills)
{
changedKills = false;
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT);
packet->setPlayer(player);
packet->Send(/*toOthers*/ false);
}
}
size_t Quests::getJournalChangesSize() const
{
return player->journalChanges.journalItems.size();
}
size_t Quests::getKillChangesSize() const
{
return player->killChanges.kills.size();
}
void Quests::addJournalItem(JournalItem item)
{
player->journalChanges.journalItems.push_back(item.item);
changedJournal = true;
}
void Quests::setJournalItem(unsigned int id, JournalItem item)
{
player->journalChanges.journalItems.at(id) = item.item;
changedJournal = true;
}
JournalItem Quests::getJournalItem(unsigned int id)
{
return JournalItem(player->journalChanges.journalItems.at(id));
}
void Quests::addKill(const std::string &refId, int number)
{
player->killChanges.kills.push_back({refId, number});
changedKills = true;
}
std::string Quests::getKillRefId(unsigned int i) const
{
return player->killChanges.kills.at(i).refId;
}
int Quests::getKillNumber(unsigned int i) const
{
return player->killChanges.kills.at(i).number;
}

@ -0,0 +1,63 @@
//
// Created by koncord on 25.08.17.
//
#pragma once
#include <cstddef>
#include <components/openmw-mp/Base/BasePlayer.hpp>
class LuaState;
class Player;
class JournalItem
{
public:
static void Init(LuaState &lua);
public:
explicit JournalItem(mwmp::JournalItem item);
~JournalItem();
std::string getQuest() const;
void setQuest(const std::string &quest);
int getIndex() const;
void setIndex(int index);
int getType() const;
void setType(int type);
std::string getActorRefId() const;
void setActorRefId(const std::string &refid);
mwmp::JournalItem item;
};
class Quests
{
public:
static void Init(LuaState &lua);
public:
explicit Quests(Player *player);
~Quests();
void update();
size_t getJournalChangesSize() const;
size_t getKillChangesSize() const;
void addJournalItem(JournalItem item);
void setJournalItem(unsigned int id, JournalItem item);
JournalItem getJournalItem(unsigned int id);
void addKill(const std::string &refId, int number);
std::string getKillRefId(unsigned int i) const;
int getKillNumber(unsigned int i) const;
private:
Player *player;
bool changedKills, changedJournal;
};

@ -1,93 +0,0 @@
//
// Created by koncord on 14.05.16.
//
#include <Script/ScriptFunction.hpp>
#include "PublicFnAPI.hpp"
using namespace std;
unordered_map<string, Public *> Public::publics;
Public::~Public()
{
}
Public::Public(ScriptFunc _public, const std::string &name, char ret_type, const std::string &def) : ScriptFunction(_public, ret_type, def)
{
publics.emplace(name, this);
}
Public::Public(ScriptFuncLua _public, lua_State *lua, const std::string &name, char ret_type, const std::string &def) : ScriptFunction(
_public, lua, ret_type, def)
{
publics.emplace(name, this);
}
#if defined(ENABLE_PAWN)
Public::Public(ScriptFuncPAWN _public, AMX* amx, const std::string& name, char ret_type, const std::string& def): ScriptFunction(_public, amx, ret_type, def)
{
publics.emplace(name, this);
}
#endif
boost::any Public::Call(const std::string &name, const std::vector<boost::any> &args)
{
auto it = publics.find(name);
if (it == publics.end())
throw runtime_error("Public with name \"" + name + "\" does not exist");
return it->second->ScriptFunction::Call(args);
}
const std::string &Public::GetDefinition(const std::string &name)
{
auto it = publics.find(name);
if (it == publics.end())
throw runtime_error("Public with name \"" + name + "\" does not exist");
return it->second->def;
}
bool Public::IsLua(const std::string &name)
{
#if !defined(ENABLE_LUA)
return false;
#else
auto it = publics.find(name);
if (it == publics.end())
throw runtime_error("Public with name \"" + name + "\" does not exist");
return it->second->script_type == SCRIPT_LUA;
#endif
}
bool Public::IsPAWN(const std::string &name)
{
#if !defined(ENABLE_PAWN)
return false;
#else
auto it = publics.find(name);
if (it == publics.end())
throw runtime_error("Public with name \"" + name + "\" does not exist");
return it->second->script_type == SCRIPT_PAWN;
#endif
}
void Public::DeleteAll()
{
for (auto it = publics.begin(); it != publics.end(); it++)
{
Public *_public = it->second;
delete _public;
publics.erase(it);
}
}

@ -1,42 +0,0 @@
//
// Created by koncord on 14.05.16.
//
#ifndef PLUGINSYSTEM3_PUBLICFNAPI_HPP
#define PLUGINSYSTEM3_PUBLICFNAPI_HPP
#include <unordered_map>
#include <Script/ScriptFunction.hpp>
class Public : public ScriptFunction
{
private:
~Public();
static std::unordered_map<std::string, Public *> publics;
Public(ScriptFunc _public, const std::string &name, char ret_type, const std::string &def);
#if defined(ENABLE_PAWN)
Public(ScriptFuncPAWN _public, AMX* amx, const std::string& name, char ret_type, const std::string& def);
#endif
#if defined(ENABLE_LUA)
Public(ScriptFuncLua _public, lua_State *lua, const std::string &name, char ret_type, const std::string &def);
#endif
public:
template<typename... Args>
static void MakePublic(Args &&... args)
{ new Public(std::forward<Args>(args)...); }
static boost::any Call(const std::string &name, const std::vector<boost::any> &args);
static const std::string& GetDefinition(const std::string& name);
static bool IsPAWN(const std::string &name);
static bool IsLua(const std::string &name);
static void DeleteAll();
};
#endif //PLUGINSYSTEM3_PUBLICFNAPI_HPP

@ -1,238 +0,0 @@
//
// Created by koncord on 15.03.16.
//
#include "TimerAPI.hpp"
#include <chrono>
#include <iostream>
using namespace mwmp;
using namespace std;
Timer::Timer(ScriptFunc callback, long msec, const std::string& def, std::vector<boost::any> args) : ScriptFunction(callback, 'v', def)
{
targetMsec = msec;
this->args = args;
end = true;
}
#if defined(ENABLE_PAWN)
Timer::Timer(AMX *amx, ScriptFuncPAWN callback, long msec, const std::string &def, std::vector<boost::any> args): ScriptFunction(callback, amx, 'v', def)
{
targetMsec = msec;
this->args = args;
end = true;
}
#endif
#if defined(ENABLE_LUA)
Timer::Timer(lua_State *lua, ScriptFuncLua callback, long msec, const std::string& def, std::vector<boost::any> args): ScriptFunction(callback, lua, 'v', def)
{
targetMsec = msec;
this->args = args;
end = true;
}
#endif
void Timer::Tick()
{
if (end)
return;
const auto duration = chrono::system_clock::now().time_since_epoch();
const auto time = chrono::duration_cast<chrono::milliseconds>(duration).count();
if (time - startTime >= targetMsec)
{
end = true;
Call(args);
}
}
bool Timer::IsEnd()
{
return end;
}
void Timer::Stop()
{
end = true;
}
void Timer::Restart(int msec)
{
targetMsec = msec;
Start();
}
void Timer::Start()
{
end = false;
const auto duration = chrono::system_clock::now().time_since_epoch();
const auto msec = chrono::duration_cast<chrono::milliseconds>(duration).count();
startTime = msec;
}
int TimerAPI::pointer = 0;
std::unordered_map<int, Timer* > TimerAPI::timers;
#if defined(ENABLE_PAWN)
int TimerAPI::CreateTimerPAWN(AMX *amx, ScriptFuncPAWN callback, long msec, const string& def, std::vector<boost::any> args)
{
int id = -1;
for (auto timer : timers)
{
if (timer.second != nullptr)
continue;
timer.second = new Timer(amx, callback, msec, def, args);
id = timer.first;
}
if (id == -1)
{
timers[pointer] = new Timer(amx, callback, msec, def, args);
id = pointer;
pointer++;
}
return id;
}
#endif
#if defined(ENABLE_LUA)
int TimerAPI::CreateTimerLua(lua_State *lua, ScriptFuncLua callback, long msec, const std::string& def, std::vector<boost::any> args)
{
int id = -1;
for (auto timer : timers)
{
if (timer.second != nullptr)
continue;
timer.second = new Timer(lua, callback, msec, def, args);
id = timer.first;
}
if (id == -1)
{
timers[pointer] = new Timer(lua, callback, msec, def, args);
id = pointer;
pointer++;
}
return id;
}
#endif
int TimerAPI::CreateTimer(ScriptFunc callback, long msec, const std::string &def, std::vector<boost::any> args)
{
int id = -1;
for (auto timer : timers)
{
if (timer.second != nullptr)
continue;
timer.second = new Timer(callback, msec, def, args);
id = timer.first;
}
if (id == -1)
{
timers[pointer] = new Timer(callback, msec, def, args);
id = pointer;
pointer++;
}
return id;
}
void TimerAPI::FreeTimer(int timerid)
{
try
{
if (timers.at(timerid) != nullptr)
{
delete timers[timerid];
timers[timerid] = nullptr;
}
}
catch(...)
{
std::cerr << "Timer " << timerid << " not found!" << endl;
}
}
void TimerAPI::ResetTimer(int timerid, long msec)
{
try
{
timers.at(timerid)->Restart(msec);
}
catch(...)
{
std::cerr << "Timer " << timerid << " not found!" << endl;
}
}
void TimerAPI::StartTimer(int timerid)
{
try
{
Timer *timer = timers.at(timerid);
if (timer == nullptr)
throw 1;
timer->Start();
}
catch(...)
{
std::cerr << "Timer " << timerid << " not found!" << endl;
}
}
void TimerAPI::StopTimer(int timerid)
{
try
{
timers.at(timerid)->Stop();
}
catch(...)
{
std::cerr << "Timer " << timerid << " not found!" << endl;
}
}
bool TimerAPI::IsEndTimer(int timerid)
{
bool ret = false;
try
{
ret = timers.at(timerid)->IsEnd();
}
catch(...)
{
std::cerr << "Timer " << timerid << " not found!" << endl;
}
return ret;
}
void TimerAPI::Terminate()
{
for (auto timer : timers)
{
if (timer.second != nullptr)
delete timer.second;
timer.second = nullptr;
}
}
void TimerAPI::Tick()
{
for (auto timer : timers)
{
if (timer.second != nullptr)
timer.second->Tick();
}
}

@ -1,70 +0,0 @@
//
// Created by koncord on 15.03.16.
//
#ifndef OPENMW_TIMERAPI_HPP
#define OPENMW_TIMERAPI_HPP
#include <string>
#include <Script/Script.hpp>
#include <Script/ScriptFunction.hpp>
namespace mwmp
{
class TimerAPI;
class Timer: public ScriptFunction
{
friend class TimerAPI;
public:
Timer(ScriptFunc callback, long msec, const std::string& def, std::vector<boost::any> args);
#if defined(ENABLE_PAWN)
Timer(AMX *amx, ScriptFuncPAWN callback, long msec, const std::string& def, std::vector<boost::any> args);
#endif
#if defined(ENABLE_LUA)
Timer(lua_State *lua, ScriptFuncLua callback, long msec, const std::string& def, std::vector<boost::any> args);
#endif
void Tick();
bool IsEnd();
void Stop();
void Start();
void Restart(int msec);
private:
double startTime, targetMsec;
std::string publ, arg_types;
std::vector<boost::any> args;
Script *scr;
bool end;
};
class TimerAPI
{
public:
#if defined(ENABLE_PAWN)
static int CreateTimerPAWN(AMX *amx, ScriptFuncPAWN callback, long msec, const std::string& def, std::vector<boost::any> args);
#endif
#if defined(ENABLE_LUA)
static int CreateTimerLua(lua_State *lua, ScriptFuncLua callback, long msec, const std::string& def, std::vector<boost::any> args);
#endif
static int CreateTimer(ScriptFunc callback, long msec, const std::string& def, std::vector<boost::any> args);
static void FreeTimer(int timerid);
static void ResetTimer(int timerid, long msec);
static void StartTimer(int timerid);
static void StopTimer(int timerid);
static bool IsEndTimer(int timerid);
static void Terminate();
static void Tick();
private:
static std::unordered_map<int, Timer* > timers;
static int pointer;
};
}
#endif //OPENMW_TIMERAPI_HPP

@ -0,0 +1,100 @@
//
// Created by koncord on 08.08.17.
//
#include "CommandController.hpp"
#include <boost/spirit/home/x3.hpp>
#include <iostream>
#include "Player.hpp"
#include "LuaState.hpp"
using namespace std;
void CommandController::Init(LuaState &lua)
{
sol::table cmdCtrlTable = lua.getState()->create_named_table("CommandController");
cmdCtrlTable["registerCommand"] = [&lua](const std::string &command, sol::function func, const std::string &helpMessage) {
return lua.getCmdCtrl().registerCommand(command, func, helpMessage);
};
cmdCtrlTable["unregisterCommand"] = [&lua](const std::string &command) {
lua.getCmdCtrl().unregisterCommand(command);
};
cmdCtrlTable["hasCommand"] = [&lua](const std::string &command) {
return lua.getCmdCtrl().hasCommand(command);
};
cmdCtrlTable["getHelpStrings"] = [&lua]() {
auto &commands = lua.getCmdCtrl().commands;
sol::table helpTable = lua.getState()->create_table(commands.size(), 0);
for (const auto &cmd : commands)
helpTable.add(cmd.first, cmd.second.helpMessage);
return helpTable;
};
}
bool CommandController::registerCommand(const std::string &command, sol::function func, const std::string &helpMessage)
{
auto iter = commands.find(command);
if (iter == commands.end())
{
commands.emplace(command, Command {std::move(func), helpMessage});
return true;
}
return false;
}
void CommandController::unregisterCommand(const std::string &command)
{
commands.erase(command);
}
bool CommandController::hasCommand(const std::string &command)
{
return commands.find(command) != commands.end();
}
std::pair<CommandController::ExecResult, std::string> CommandController::exec(std::shared_ptr<Player> player, const std::string &message)
{
char cmdChar = message[0];
if (message.size() < 2 || (cmdChar != '/' && cmdChar != '!'))
return make_pair(ExecResult::NOT_CMD, "");
auto tokens = cmdParser(message);
auto cmd = commands.find(&tokens[0][1]);
if (cmd != commands.end())
{
tokens.pop_front();
bool result = cmd->second.func(player, sol::as_table(tokens));
if (result)
return make_pair(ExecResult::SUCCESS, "");
return make_pair(ExecResult::FAIL, cmd->second.helpMessage);
}
return make_pair(ExecResult::NOT_FOUND, "");
}
std::deque<std::string> CommandController::cmdParser(const std::string &message)
{
deque<string> ret;
namespace x3 = boost::spirit::x3;
auto const sep = ' ';
auto const quoted = '"' >> *~x3::char_('"') >> '"';
auto const unquoted = *~x3::char_(sep);
auto const arguments = (quoted | unquoted) % sep;
/*auto const command = '/' >> *~x3::char_(sep) >> sep;
if (!x3::phrase_parse(message.cbegin(), message.cend(), arguments, command, ret))
throw runtime_error("failed to parse message: "+ message);*/
if (!x3::parse(message.cbegin(), message.cend(), arguments, ret))
throw runtime_error("failed to parse message: " + message);
return ret;
}

@ -0,0 +1,63 @@
//
// Created by koncord on 08.08.17.
//
#pragma once
#include "sol.hpp"
#include "Utils.hpp"
#include <string>
#include <deque>
class Player;
class LuaState;
struct Command
{
sol::function func;
std::string helpMessage;
};
class CommandController
{
typedef std::unordered_map<std::string, Command> Container;
typedef Container::iterator Iter;
typedef Container::const_iterator CIter;
public:
static void Init(LuaState &lua);
public:
enum class ExecResult : int
{
NOT_FOUND,
SUCCESS,
FAIL,
NOT_CMD
};
/**
* Register new command. Only unique commands are allowed.
* @param command name of command. Case sensitive. No need in command prefix ('/' or '!').
* @param helpMessage help message. Shows in the '/help' command also appears if exec() fails.
* @param callback Will be called when command is called.
* @return false if the command already registered.
*/
bool registerCommand(const std::string &command, sol::function callback, const std::string &helpMessage);
/**
* Removes a registered command
* @param command name of command.
*/
void unregisterCommand(const std::string &command);
/**
* Check a command is exist.
* @param command name of command
* @return false if the command did not exist.
*/
bool hasCommand(const std::string &command);
std::pair<ExecResult, std::string> exec(std::shared_ptr<Player> player, const std::string &message);
private:
std::deque<std::string> cmdParser(const std::string &message);
Container commands;
};

@ -0,0 +1,153 @@
//
// Created by koncord on 30.07.17.
//
#include <iostream>
#include "EventController.hpp"
using namespace std;
#define ADD_CORE_EVENT(event) #event, CoreEvent::event
void EventController::Init(LuaState &lua)
{
sol::table eventsTable = lua.getState()->create_named_table("Event");
eventsTable["register"] = [&lua](int event, sol::function func, sol::this_environment te) {
sol::environment& env = te;
string modname = env["ModInfo"]["name"];
lua.getEventCtrl().registerEvent(event, env, func);
};
eventsTable["stop"] = [&lua](int event) {
lua.getEventCtrl().stop(event);
};
eventsTable["create"] = [&lua]() {
return lua.getEventCtrl().createEvent();
};
eventsTable["raise"] = [&lua](unsigned event, sol::table data) {
lua.getEventCtrl().raiseEvent(event, data);
};
eventsTable["raiseSpecified"] = [&lua](unsigned event, const std::string &modname, sol::table data) {
lua.getEventCtrl().raiseEvent(event, data, modname);
};
}
EventController::EventController(LuaState *luaCtrl)
{
this->luaCtrl = luaCtrl;
#ifdef SERVER_DEBUG
luaCtrl->getState()->new_enum<false>
#else
luaCtrl->getState()->new_enum
#endif
("Events",
ADD_CORE_EVENT(ON_POST_INIT),
ADD_CORE_EVENT(ON_EXIT),
ADD_CORE_EVENT(ON_PLAYER_CONNECT),
ADD_CORE_EVENT(ON_PLAYER_DISCONNECT),
ADD_CORE_EVENT(ON_PLAYER_DEATH),
ADD_CORE_EVENT(ON_PLAYER_RESURRECT),
ADD_CORE_EVENT(ON_PLAYER_CELLCHANGE),
ADD_CORE_EVENT(ON_PLAYER_KILLCOUNT),
ADD_CORE_EVENT(ON_PLAYER_ATTRIBUTE),
ADD_CORE_EVENT(ON_PLAYER_SKILL),
ADD_CORE_EVENT(ON_PLAYER_LEVEL),
ADD_CORE_EVENT(ON_PLAYER_BOUNTY),
ADD_CORE_EVENT(ON_PLAYER_EQUIPMENT),
ADD_CORE_EVENT(ON_PLAYER_INVENTORY),
ADD_CORE_EVENT(ON_PLAYER_JOURNAL),
ADD_CORE_EVENT(ON_PLAYER_FACTION),
ADD_CORE_EVENT(ON_PLAYER_SHAPESHIFT),
ADD_CORE_EVENT(ON_PLAYER_SPELLBOOK),
ADD_CORE_EVENT(ON_PLAYER_TOPIC),
ADD_CORE_EVENT(ON_PLAYER_DISPOSITION),
ADD_CORE_EVENT(ON_PLAYER_BOOK),
ADD_CORE_EVENT(ON_PLAYER_MAP),
ADD_CORE_EVENT(ON_PLAYER_REST),
ADD_CORE_EVENT(ON_PLAYER_SENDMESSAGE),
ADD_CORE_EVENT(ON_PLAYER_ENDCHARGEN),
ADD_CORE_EVENT(ON_GUI_ACTION),
ADD_CORE_EVENT(ON_REQUEST_PLUGIN_LIST),
ADD_CORE_EVENT(ON_MP_REFNUM),
ADD_CORE_EVENT(ON_ACTOR_EQUIPMENT),
ADD_CORE_EVENT(ON_ACTOR_CELL_CHANGE),
ADD_CORE_EVENT(ON_ACTOR_LIST),
ADD_CORE_EVENT(ON_ACTOR_TEST),
ADD_CORE_EVENT(ON_CELL_LOAD),
ADD_CORE_EVENT(ON_CELL_UNLOAD),
ADD_CORE_EVENT(ON_CELL_DELETION),
ADD_CORE_EVENT(ON_CONTAINER),
ADD_CORE_EVENT(ON_DOOR_STATE),
ADD_CORE_EVENT(ON_OBJECT_PLACE),
ADD_CORE_EVENT(ON_OBJECT_STATE),
ADD_CORE_EVENT(ON_OBJECT_SPAWN),
ADD_CORE_EVENT(ON_OBJECT_DELETE),
ADD_CORE_EVENT(ON_OBJECT_LOCK),
ADD_CORE_EVENT(ON_OBJECT_SCALE),
ADD_CORE_EVENT(ON_OBJECT_TRAP)
);
sol::state &state = *luaCtrl->getState();
sol::table eventsEnum = state["Events"];
for (int i = CoreEvent::FIRST; i < CoreEvent::LAST; ++i)
{
#ifdef SERVER_DEBUG
bool found = false;
eventsEnum.for_each([&found, &i](sol::object key, sol::object value){
if (value.as<int>() == i)
{
found = true;
return;
}
});
if (!found)
throw runtime_error("Event " + to_string(i) + " is not registered. Dear developer, please fix me :D");
#endif
events[i]; // create core event
}
}
void EventController::registerEvent(int event, sol::environment &env, sol::function& func)
{
auto iter = events.find(event);
if (iter != events.end())
iter->second.push(env, func);
}
void EventController::stop(int event)
{
printf("EventController::stop\n");
auto iter = events.find(event);
if (iter != events.end())
iter->second.stop();
}
CallbackCollection &EventController::GetEvents(Event event)
{
return events.at(event);
}
Event EventController::createEvent()
{
events[lastEvent];
return lastEvent++;
}
void EventController::raiseEvent(Event id, sol::table data, const string &modname)
{
auto iter = events.find(id);
if (iter != events.end())
{
if (!modname.empty())
{
auto f = std::find_if (iter->second.begin(), iter->second.end(), [&modname](const auto &item){
return item.first["ModName"]["name"] == modname;
});
if (f != iter->second.end())
f->second.call(data); // call only specified mod
}
iter->second.call(CallbackCollection::type_tag<void>(), data); // call all registered events with this id
}
else
cerr << "Event with id: " << id << " is not registered" << endl;
}

@ -0,0 +1,166 @@
//
// Created by koncord on 30.07.17.
//
#pragma once
#include "sol.hpp"
#include "Utils.hpp"
#include "LuaState.hpp"
typedef unsigned Event;
namespace CoreEvent
{
enum
{
ON_EXIT = 0,
ON_POST_INIT,
ON_REQUEST_PLUGIN_LIST,
ON_PLAYER_CONNECT,
ON_PLAYER_DISCONNECT,
ON_PLAYER_DEATH,
ON_PLAYER_RESURRECT,
ON_PLAYER_CELLCHANGE,
ON_PLAYER_KILLCOUNT,
ON_PLAYER_ATTRIBUTE,
ON_PLAYER_SKILL,
ON_PLAYER_LEVEL,
ON_PLAYER_BOUNTY,
ON_PLAYER_EQUIPMENT,
ON_PLAYER_INVENTORY,
ON_PLAYER_JOURNAL,
ON_PLAYER_FACTION,
ON_PLAYER_SHAPESHIFT,
ON_PLAYER_SPELLBOOK,
ON_PLAYER_TOPIC,
ON_PLAYER_DISPOSITION,
ON_PLAYER_BOOK,
ON_PLAYER_MAP,
ON_PLAYER_REST,
ON_PLAYER_SENDMESSAGE,
ON_PLAYER_ENDCHARGEN,
ON_GUI_ACTION,
ON_MP_REFNUM,
ON_ACTOR_EQUIPMENT,
ON_ACTOR_CELL_CHANGE,
ON_ACTOR_LIST,
ON_ACTOR_TEST,
ON_CELL_LOAD,
ON_CELL_UNLOAD,
ON_CELL_DELETION,
ON_CONTAINER,
ON_DOOR_STATE,
ON_OBJECT_PLACE,
ON_OBJECT_STATE,
ON_OBJECT_SPAWN,
ON_OBJECT_DELETE,
ON_OBJECT_LOCK,
ON_OBJECT_SCALE,
ON_OBJECT_TRAP,
LAST,
};
const int FIRST = ON_EXIT;
}
class CallbackCollection // todo: add sort by dependencies
{
public:
typedef std::vector<std::pair<sol::environment, sol::function>> Container;
typedef Container::iterator Iterator;
typedef Container::const_iterator CIterator;
template<typename> struct type_tag {};
void push(sol::environment &env, sol::function &func) { functions.emplace_back(env, func); }
CIterator begin() const { return functions.begin(); }
CIterator end() const { return functions.end(); }
void stop() {_stop = true;}
bool isStoped() const {return _stop;}
CIterator stopedAt() const { return lastCalled; }
auto get(const std::string &modname)
{
for(auto iter = functions.cbegin(); iter != functions.cend(); ++iter)
{
if(iter->first["ModName"]["name"] == modname)
return iter;
}
return functions.cend();
}
template<typename... Args>
void call(type_tag<void>, Args&&... args)
{
lastCalled = functions.end();
_stop = false;
for(CIterator iter = functions.begin(); iter != functions.end(); ++iter)
{
if(!_stop)
iter->second.call(std::forward<Args>(args)...);
else
{
lastCalled = iter;
break;
}
}
}
template<typename R, typename... Args>
decltype(auto) call(type_tag<R>, Args&&... args)
{
R ret;
lastCalled = functions.end();
_stop = false;
for(CIterator iter = functions.begin(); iter != functions.end(); ++iter)
{
if (!_stop)
ret = iter->second.call(std::forward<Args>(args)...);
else
{
lastCalled = iter;
break;
}
}
return ret;
}
private:
Container functions;
CIterator lastCalled;
bool _stop = false;
};
class EventController
{
public:
static void Init(LuaState &lua);
public:
explicit EventController(LuaState *luaCtrl);
typedef std::unordered_map<int, CallbackCollection> Container;
void registerEvent(int event, sol::environment &env, sol::function& func);
CallbackCollection& GetEvents(Event event);
Event createEvent();
void raiseEvent(Event id, sol::table data, const std::string &modname = "");
void stop(int event);
template<Event event, typename R = void, typename... Args>
R Call(Args&&... args)
{
return events.at(event).call(CallbackCollection::type_tag<R>{}, std::forward<Args>(args)...);
}
private:
Container events;
Event lastEvent = CoreEvent::LAST;
LuaState *luaCtrl;
};

@ -1,330 +0,0 @@
#include <components/openmw-mp/NetworkMessages.hpp>
#include <components/openmw-mp/Base/BaseActor.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <apps/openmw-mp/Player.hpp>
#include <apps/openmw-mp/Utils.hpp>
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/esm/creaturestats.hpp>
#include "Actors.hpp"
using namespace mwmp;
BaseActorList *readActorList;
BaseActorList writeActorList;
BaseActor tempActor;
const BaseActor emptyActor = {};
static std::string tempCellDescription;
void ActorFunctions::ReadLastActorList() noexcept
{
readActorList = mwmp::Networking::getPtr()->getLastActorList();
}
void ActorFunctions::ReadCellActorList(const char* cellDescription) noexcept
{
ESM::Cell esmCell = Utils::getCellFromDescription(cellDescription);
Cell *serverCell = CellController::get()->getCell(&esmCell);
readActorList = serverCell->getActorList();
}
void ActorFunctions::InitializeActorList(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
writeActorList.cell.blank();
writeActorList.baseActors.clear();
writeActorList.guid = player->guid;
}
unsigned int ActorFunctions::GetActorListSize() noexcept
{
return readActorList->count;
}
unsigned char ActorFunctions::GetActorListAction() noexcept
{
return readActorList->action;
}
const char *ActorFunctions::GetActorCell(unsigned int i) noexcept
{
tempCellDescription = readActorList->baseActors.at(i).cell.getDescription();
return tempCellDescription.c_str();
}
const char *ActorFunctions::GetActorRefId(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).refId.c_str();
}
int ActorFunctions::GetActorRefNumIndex(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).refNumIndex;
}
int ActorFunctions::GetActorMpNum(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).mpNum;
}
double ActorFunctions::GetActorPosX(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).position.pos[0];
}
double ActorFunctions::GetActorPosY(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).position.pos[1];
}
double ActorFunctions::GetActorPosZ(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).position.pos[2];
}
double ActorFunctions::GetActorRotX(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).position.rot[0];
}
double ActorFunctions::GetActorRotY(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).position.rot[1];
}
double ActorFunctions::GetActorRotZ(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).position.rot[2];
}
double ActorFunctions::GetActorHealthBase(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[0].mBase;
}
double ActorFunctions::GetActorHealthCurrent(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[0].mCurrent;
}
double ActorFunctions::GetActorHealthModified(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[0].mMod;
}
double ActorFunctions::GetActorMagickaBase(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[1].mBase;
}
double ActorFunctions::GetActorMagickaCurrent(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[1].mCurrent;
}
double ActorFunctions::GetActorMagickaModified(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[1].mMod;
}
double ActorFunctions::GetActorFatigueBase(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[2].mBase;
}
double ActorFunctions::GetActorFatigueCurrent(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[2].mCurrent;
}
double ActorFunctions::GetActorFatigueModified(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).creatureStats.mDynamic[2].mMod;
}
const char *ActorFunctions::GetActorEquipmentItemRefId(unsigned int i, unsigned short slot) noexcept
{
return readActorList->baseActors.at(i).equipedItems[slot].refId.c_str();
}
int ActorFunctions::GetActorEquipmentItemCount(unsigned int i, unsigned short slot) noexcept
{
return readActorList->baseActors.at(i).equipedItems[slot].count;
}
int ActorFunctions::GetActorEquipmentItemCharge(unsigned int i, unsigned short slot) noexcept
{
return readActorList->baseActors.at(i).equipedItems[slot].charge;
}
bool ActorFunctions::DoesActorHavePosition(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).hasPositionData;
}
bool ActorFunctions::DoesActorHaveStatsDynamic(unsigned int i) noexcept
{
return readActorList->baseActors.at(i).hasStatsDynamicData;
}
void ActorFunctions::SetActorListCell(const char* cellDescription) noexcept
{
writeActorList.cell = Utils::getCellFromDescription(cellDescription);
}
void ActorFunctions::SetActorListAction(unsigned char action) noexcept
{
writeActorList.action = action;
}
void ActorFunctions::SetActorCell(const char* cellDescription) noexcept
{
tempActor.cell = Utils::getCellFromDescription(cellDescription);
}
void ActorFunctions::SetActorRefId(const char* refId) noexcept
{
tempActor.refId = refId;
}
void ActorFunctions::SetActorRefNumIndex(int refNumIndex) noexcept
{
tempActor.refNumIndex = refNumIndex;
}
void ActorFunctions::SetActorMpNum(int mpNum) noexcept
{
tempActor.mpNum = mpNum;
}
void ActorFunctions::SetActorPosition(double x, double y, double z) noexcept
{
tempActor.position.pos[0] = x;
tempActor.position.pos[1] = y;
tempActor.position.pos[2] = z;
}
void ActorFunctions::SetActorRotation(double x, double y, double z) noexcept
{
tempActor.position.rot[0] = x;
tempActor.position.rot[1] = y;
tempActor.position.rot[2] = z;
}
void ActorFunctions::SetActorHealthBase(double value) noexcept
{
tempActor.creatureStats.mDynamic[0].mBase = value;
}
void ActorFunctions::SetActorHealthCurrent(double value) noexcept
{
tempActor.creatureStats.mDynamic[0].mCurrent = value;
}
void ActorFunctions::SetActorHealthModified(double value) noexcept
{
tempActor.creatureStats.mDynamic[0].mMod = value;
}
void ActorFunctions::SetActorMagickaBase(double value) noexcept
{
tempActor.creatureStats.mDynamic[1].mBase = value;
}
void ActorFunctions::SetActorMagickaCurrent(double value) noexcept
{
tempActor.creatureStats.mDynamic[1].mCurrent = value;
}
void ActorFunctions::SetActorMagickaModified(double value) noexcept
{
tempActor.creatureStats.mDynamic[1].mMod = value;
}
void ActorFunctions::SetActorFatigueBase(double value) noexcept
{
tempActor.creatureStats.mDynamic[2].mBase = value;
}
void ActorFunctions::SetActorFatigueCurrent(double value) noexcept
{
tempActor.creatureStats.mDynamic[2].mCurrent = value;
}
void ActorFunctions::SetActorFatigueModified(double value) noexcept
{
tempActor.creatureStats.mDynamic[2].mMod = value;
}
void ActorFunctions::EquipActorItem(unsigned short slot, const char *refId, unsigned int count, int charge) noexcept
{
tempActor.equipedItems[slot].refId = refId;
tempActor.equipedItems[slot].count = count;
tempActor.equipedItems[slot].charge = charge;
}
void ActorFunctions::UnequipActorItem(unsigned short slot) noexcept
{
ActorFunctions::EquipActorItem(slot, "", 0, -1);
}
void ActorFunctions::AddActor() noexcept
{
writeActorList.baseActors.push_back(tempActor);
tempActor = emptyActor;
}
void ActorFunctions::SendActorList() noexcept
{
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_LIST)->setActorList(&writeActorList);
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_LIST)->Send(writeActorList.guid);
}
void ActorFunctions::SendActorAuthority() noexcept
{
Cell *serverCell = CellController::get()->getCell(&writeActorList.cell);
if (serverCell != nullptr)
{
serverCell->setAuthority(writeActorList.guid);
mwmp::ActorPacket *authorityPacket = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_AUTHORITY);
authorityPacket->setActorList(&writeActorList);
authorityPacket->Send(writeActorList.guid);
// Also send this to everyone else who has the cell loaded
serverCell->sendToLoaded(authorityPacket, &writeActorList);
}
}
void ActorFunctions::SendActorPosition() noexcept
{
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_POSITION)->setActorList(&writeActorList);
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_POSITION)->Send(writeActorList.guid);
}
void ActorFunctions::SendActorStatsDynamic() noexcept
{
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_STATS_DYNAMIC)->setActorList(&writeActorList);
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_STATS_DYNAMIC)->Send(writeActorList.guid);
}
void ActorFunctions::SendActorEquipment() noexcept
{
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_EQUIPMENT)->setActorList(&writeActorList);
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_EQUIPMENT)->Send(writeActorList.guid);
}
void ActorFunctions::SendActorCellChange() noexcept
{
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_CELL_CHANGE)->setActorList(&writeActorList);
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_CELL_CHANGE)->Send(writeActorList.guid);
}

@ -1,563 +0,0 @@
#ifndef OPENMW_ACTORAPI_HPP
#define OPENMW_ACTORAPI_HPP
#define ACTORAPI \
{"ReadLastActorList", ActorFunctions::ReadLastActorList},\
{"ReadCellActorList", ActorFunctions::ReadCellActorList},\
{"InitializeActorList", ActorFunctions::InitializeActorList},\
\
{"GetActorListSize", ActorFunctions::GetActorListSize},\
{"GetActorListAction", ActorFunctions::GetActorListAction},\
\
{"GetActorCell", ActorFunctions::GetActorCell},\
{"GetActorRefId", ActorFunctions::GetActorRefId},\
{"GetActorRefNumIndex", ActorFunctions::GetActorRefNumIndex},\
{"GetActorMpNum", ActorFunctions::GetActorMpNum},\
\
{"GetActorPosX", ActorFunctions::GetActorPosX},\
{"GetActorPosY", ActorFunctions::GetActorPosY},\
{"GetActorPosZ", ActorFunctions::GetActorPosZ},\
{"GetActorRotX", ActorFunctions::GetActorRotX},\
{"GetActorRotY", ActorFunctions::GetActorRotY},\
{"GetActorRotZ", ActorFunctions::GetActorRotZ},\
\
{"GetActorHealthBase", ActorFunctions::GetActorHealthBase},\
{"GetActorHealthCurrent", ActorFunctions::GetActorHealthCurrent},\
{"GetActorHealthModified", ActorFunctions::GetActorHealthModified},\
{"GetActorMagickaBase", ActorFunctions::GetActorMagickaBase},\
{"GetActorMagickaCurrent", ActorFunctions::GetActorMagickaCurrent},\
{"GetActorMagickaModified", ActorFunctions::GetActorMagickaModified},\
{"GetActorFatigueBase", ActorFunctions::GetActorFatigueBase},\
{"GetActorFatigueCurrent", ActorFunctions::GetActorFatigueCurrent},\
{"GetActorFatigueModified", ActorFunctions::GetActorFatigueModified},\
\
{"GetActorEquipmentItemRefId", ActorFunctions::GetActorEquipmentItemRefId},\
{"GetActorEquipmentItemCount", ActorFunctions::GetActorEquipmentItemCount},\
{"GetActorEquipmentItemCharge", ActorFunctions::GetActorEquipmentItemCharge},\
\
{"DoesActorHavePosition", ActorFunctions::DoesActorHavePosition},\
{"DoesActorHaveStatsDynamic", ActorFunctions::DoesActorHaveStatsDynamic},\
\
{"SetActorListCell", ActorFunctions::SetActorListCell},\
{"SetActorListAction", ActorFunctions::SetActorListAction},\
\
{"SetActorCell", ActorFunctions::SetActorCell},\
{"SetActorRefId", ActorFunctions::SetActorRefId},\
{"SetActorRefNumIndex", ActorFunctions::SetActorRefNumIndex},\
{"SetActorMpNum", ActorFunctions::SetActorMpNum},\
\
{"SetActorPosition", ActorFunctions::SetActorPosition},\
{"SetActorRotation", ActorFunctions::SetActorRotation},\
\
{"SetActorHealthBase", ActorFunctions::SetActorHealthBase},\
{"SetActorHealthCurrent", ActorFunctions::SetActorHealthCurrent},\
{"SetActorHealthModified", ActorFunctions::SetActorHealthModified},\
{"SetActorMagickaBase", ActorFunctions::SetActorMagickaBase},\
{"SetActorMagickaCurrent", ActorFunctions::SetActorMagickaCurrent},\
{"SetActorMagickaModified", ActorFunctions::SetActorMagickaModified},\
{"SetActorFatigueBase", ActorFunctions::SetActorFatigueBase},\
{"SetActorFatigueCurrent", ActorFunctions::SetActorFatigueCurrent},\
{"SetActorFatigueModified", ActorFunctions::SetActorFatigueModified},\
\
{"EquipActorItem", ActorFunctions::EquipActorItem},\
{"UnequipActorItem", ActorFunctions::UnequipActorItem},\
\
{"AddActor", ActorFunctions::AddActor},\
\
{"SendActorList", ActorFunctions::SendActorList},\
{"SendActorAuthority", ActorFunctions::SendActorAuthority},\
{"SendActorPosition", ActorFunctions::SendActorPosition},\
{"SendActorStatsDynamic", ActorFunctions::SendActorStatsDynamic},\
{"SendActorEquipment", ActorFunctions::SendActorEquipment},\
{"SendActorCellChange", ActorFunctions::SendActorCellChange}
class ActorFunctions
{
public:
/**
* \brief Use the last actor list received by the server as the one being read.
*
* \return void
*/
static void ReadLastActorList() noexcept;
/**
* \brief Use the temporary actor list stored for a cell as the one being read.
*
* This type of actor list is used to store actor positions and dynamic stats and is deleted
* when the cell is unloaded.
*
* \param cellDescription The description of the cell whose actor list should be read.
* \return void
*/
static void ReadCellActorList(const char* cellDescription) noexcept;
/**
* \brief Clear the data from the last actor list sent by the server.
*
* This is used to initialize the sending of new Actor packets.
*
* \param pid The player ID to whom the actor list should be attached.
* \return void
*/
static void InitializeActorList(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in the read actor list.
*
* \return The number of indexes.
*/
static unsigned int GetActorListSize() noexcept;
/**
* \brief Get the action type used in the read actor list.
*
* \return The action type (0 for SET, 1 for ADD, 2 for REMOVE, 3 for REQUEST).
*/
static unsigned char GetActorListAction() noexcept;
/**
* \brief Get the cell description of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The cell description.
*/
static const char *GetActorCell(unsigned int i) noexcept;
/**
* \brief Get the refId of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The refId.
*/
static const char *GetActorRefId(unsigned int i) noexcept;
/**
* \brief Get the refNumIndex of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The refNumIndex.
*/
static int GetActorRefNumIndex(unsigned int i) noexcept;
/**
* \brief Get the mpNum of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The mpNum.
*/
static int GetActorMpNum(unsigned int i) noexcept;
/**
* \brief Get the X position of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The X position.
*/
static double GetActorPosX(unsigned int i) noexcept;
/**
* \brief Get the Y position of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The Y position.
*/
static double GetActorPosY(unsigned int i) noexcept;
/**
* \brief Get the Z position of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The Z position.
*/
static double GetActorPosZ(unsigned int i) noexcept;
/**
* \brief Get the X rotation of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The X rotation.
*/
static double GetActorRotX(unsigned int i) noexcept;
/**
* \brief Get the Y rotation of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The Y rotation.
*/
static double GetActorRotY(unsigned int i) noexcept;
/**
* \brief Get the Z rotation of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The Z rotation.
*/
static double GetActorRotZ(unsigned int i) noexcept;
/**
* \brief Get the base health of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The base health.
*/
static double GetActorHealthBase(unsigned int i) noexcept;
/**
* \brief Get the current health of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The current health.
*/
static double GetActorHealthCurrent(unsigned int i) noexcept;
/**
* \brief Get the modified health of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The modified health.
*/
static double GetActorHealthModified(unsigned int i) noexcept;
/**
* \brief Get the base magicka of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The base magicka.
*/
static double GetActorMagickaBase(unsigned int i) noexcept;
/**
* \brief Get the current magicka of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The current magicka.
*/
static double GetActorMagickaCurrent(unsigned int i) noexcept;
/**
* \brief Get the modified magicka of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The modified magicka.
*/
static double GetActorMagickaModified(unsigned int i) noexcept;
/**
* \brief Get the base fatigue of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The base fatigue.
*/
static double GetActorFatigueBase(unsigned int i) noexcept;
/**
* \brief Get the current fatigue of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The current fatigue.
*/
static double GetActorFatigueCurrent(unsigned int i) noexcept;
/**
* \brief Get the modified fatigue of the actor at a certain index in the read actor list.
*
* \param i The index of the actor.
* \return The modified fatigue.
*/
static double GetActorFatigueModified(unsigned int i) noexcept;
/**
* \brief Get the refId of the item in a certain slot of the equipment of the actor at a
* certain index in the read actor list.
*
* \param i The index of the actor.
* \param slot The slot of the equipment item.
* \return The refId.
*/
static const char *GetActorEquipmentItemRefId(unsigned int i, unsigned short slot) noexcept;
/**
* \brief Get the count of the item in a certain slot of the equipment of the actor at a
* certain index in the read actor list.
*
* \param i The index of the actor.
* \param slot The slot of the equipment item.
* \return The item count.
*/
static int GetActorEquipmentItemCount(unsigned int i, unsigned short slot) noexcept;
/**
* \brief Get the charge of the item in a certain slot of the equipment of the actor at a
* certain index in the read actor list.
*
* \param i The index of the actor.
* \param slot The slot of the equipment item.
* \return The charge.
*/
static int GetActorEquipmentItemCharge(unsigned int i, unsigned short slot) noexcept;
/**
* \brief Check whether there is any positional data for the actor at a certain index in
* the read actor list.
*
* This is only useful when reading the actor list data recorded for a particular cell.
*
* \param i The index of the actor.
* \return Whether the read actor list contains positional data.
*/
static bool DoesActorHavePosition(unsigned int i) noexcept;
/**
* \brief Check whether there is any dynamic stats data for the actor at a certain index in
* the read actor list.
*
* This is only useful when reading the actor list data recorded for a particular cell.
*
* \param i The index of the actor.
* \return Whether the read actor list contains dynamic stats data.
*/
static bool DoesActorHaveStatsDynamic(unsigned int i) noexcept;
/**
* \brief Set the cell of the temporary actor list stored on the server.
*
* The cell is determined to be an exterior cell if it fits the pattern of a number followed
* by a comma followed by another number.
*
* \param cellDescription The description of the cell.
* \return void
*/
static void SetActorListCell(const char* cellDescription) noexcept;
/**
* \brief Set the action type of the temporary actor list stored on the server.
*
* \param action The action type (0 for SET, 1 for ADD, 2 for REMOVE, 3 for REQUEST).
* \return void
*/
static void SetActorListAction(unsigned char action) noexcept;
/**
* \brief Set the cell of the temporary actor stored on the server.
*
* Used for ActorCellChange packets, where a specific actor's cell now differs from that of the
* actor list.
*
* The cell is determined to be an exterior cell if it fits the pattern of a number followed
* by a comma followed by another number.
*
* \param cellDescription The description of the cell.
* \return void
*/
static void SetActorCell(const char* cellDescription) noexcept;
/**
* \brief Set the refId of the temporary actor stored on the server.
*
* \param refId The refId.
* \return void
*/
static void SetActorRefId(const char* refId) noexcept;
/**
* \brief Set the refNumIndex of the temporary actor stored on the server.
*
* \param refNumIndex The refNumIndex.
* \return void
*/
static void SetActorRefNumIndex(int refNumIndex) noexcept;
/**
* \brief Set the mpNum of the temporary actor stored on the server.
*
* \param mpNum The mpNum.
* \return void
*/
static void SetActorMpNum(int mpNum) noexcept;
/**
* \brief Set the position of the temporary actor stored on the server.
*
* \param x The X position.
* \param y The Y position.
* \param z The Z position.
* \return void
*/
static void SetActorPosition(double x, double y, double z) noexcept;
/**
* \brief Set the rotation of the temporary actor stored on the server.
*
* \param x The X rotation.
* \param y The Y rotation.
* \param z The Z rotation.
* \return void
*/
static void SetActorRotation(double x, double y, double z) noexcept;
/**
* \brief Set the base health of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorHealthBase(double value) noexcept;
/**
* \brief Set the current health of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorHealthCurrent(double value) noexcept;
/**
* \brief Set the modified health of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorHealthModified(double value) noexcept;
/**
* \brief Set the base magicka of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorMagickaBase(double value) noexcept;
/**
* \brief Set the current magicka of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorMagickaCurrent(double value) noexcept;
/**
* \brief Set the modified magicka of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorMagickaModified(double value) noexcept;
/**
* \brief Set the base fatigue of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorFatigueBase(double value) noexcept;
/**
* \brief Set the current fatigue of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorFatigueCurrent(double value) noexcept;
/**
* \brief Set the modified fatigue of the temporary actor stored on the server.
*
* \param value The new value.
* \return void
*/
static void SetActorFatigueModified(double value) noexcept;
/**
* \brief Equip an item in a certain slot of the equipment of the temporary actor stored
* on the server.
*
* \param slot The equipment slot.
* \param refId The refId of the item.
* \param count The count of the item.
* \param charge The charge of the item.
* \return void
*/
static void EquipActorItem(unsigned short slot, const char* refId, unsigned int count, int charge) noexcept;
/**
* \brief Unequip the item in a certain slot of the equipment of the temporary actor stored
* on the server.
*
* \param slot The equipment slot.
* \return void
*/
static void UnequipActorItem(unsigned short slot) noexcept;
/**
* \brief Add a copy of the server's temporary actor to the server's temporary actor list.
*
* In the process, the server's temporary actor will automatically be cleared so a new
* one can be set up.
*
* \return void
*/
static void AddActor() noexcept;
/**
* \brief Send an ActorList packet.
*
* It is sent only to the player for whom the current actor list was initialized.
*
* \return void
*/
static void SendActorList() noexcept;
/**
* \brief Send an ActorAuthority packet.
*
* The player for whom the current actor list was initialized is recorded in the server memory
* as the new actor authority for the actor list's cell.
*
* The packet is sent to that player as well as all other players who have the cell loaded.
*
* \return void
*/
static void SendActorAuthority() noexcept;
/**
* \brief Send an ActorPosition packet.
*
* It is sent only to the player for whom the current actor list was initialized.
*
* \return void
*/
static void SendActorPosition() noexcept;
/**
* \brief Send an ActorStatsDynamic packet.
*
* It is sent only to the player for whom the current actor list was initialized.
*
* \return void
*/
static void SendActorStatsDynamic() noexcept;
/**
* \brief Send an ActorEquipment packet.
*
* It is sent only to the player for whom the current actor list was initialized.
*
* \return void
*/
static void SendActorEquipment() noexcept;
/**
* \brief Send an ActorCellChange packet.
*
* It is sent only to the player for whom the current actor list was initialized.
*
* \return void
*/
static void SendActorCellChange() noexcept;
};
#endif //OPENMW_ACTORAPI_HPP

@ -1,53 +0,0 @@
#include "Books.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
using namespace mwmp;
void BookFunctions::InitializeBookChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
return player->bookChanges.books.clear();
}
unsigned int BookFunctions::GetBookChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->bookChanges.count;
}
void BookFunctions::AddBook(unsigned short pid, const char* bookId) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Book book;
book.bookId = bookId;
player->bookChanges.books.push_back(book);
}
const char *BookFunctions::GetBookId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->bookChanges.count)
return "invalid";
return player->bookChanges.books.at(i).bookId.c_str();
}
void BookFunctions::SendBookChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOOK)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOOK)->Send(toOthers);
}

@ -1,69 +0,0 @@
#ifndef OPENMW_BOOKAPI_HPP
#define OPENMW_BOOKAPI_HPP
#define BOOKAPI \
{"InitializeBookChanges", BookFunctions::InitializeBookChanges},\
\
{"GetBookChangesSize", BookFunctions::GetBookChangesSize},\
\
{"AddBook", BookFunctions::AddBook},\
\
{"GetBookId", BookFunctions::GetBookId},\
\
{"SendBookChanges", BookFunctions::SendBookChanges}
class BookFunctions
{
public:
/**
* \brief Clear the last recorded book changes for a player.
*
* This is used to initialize the sending of new PlayerBook packets.
*
* \param pid The player ID whose book changes should be used.
* \return void
*/
static void InitializeBookChanges(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest book changes.
*
* \param pid The player ID whose book changes should be used.
* \return The number of indexes.
*/
static unsigned int GetBookChangesSize(unsigned short pid) noexcept;
/**
* \brief Add a new book to the book changes for a player.
*
* \param pid The player ID whose book changes should be used.
* \param bookId The bookId of the book.
* \return void
*/
static void AddBook(unsigned short pid, const char* bookId) noexcept;
/**
* \brief Get the bookId at a certain index in a player's latest book changes.
*
* \param pid The player ID whose book changes should be used.
* \param i The index of the book.
* \return The bookId.
*/
static const char *GetBookId(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Send a PlayerBook packet with a player's recorded book changes.
*
* \param pid The player ID whose book changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendBookChanges(unsigned short pid, bool toOthers = false) noexcept;
private:
};
#endif //OPENMW_BOOKAPI_HPP

@ -1,149 +0,0 @@
#include "Cells.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Player.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/Log.hpp>
#include <iostream>
using namespace std;
static std::string tempCellDescription;
void CellFunctions::InitializeMapChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->mapChanges.cellsExplored.clear();
}
unsigned int CellFunctions::GetCellStateChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->cellStateChanges.count;
}
unsigned int CellFunctions::GetCellStateType(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->cellStateChanges.cellStates.at(i).type;
}
const char *CellFunctions::GetCellStateDescription(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->cellStateChanges.count)
return "invalid";
tempCellDescription = player->cellStateChanges.cellStates.at(i).cell.getDescription();
return tempCellDescription.c_str();
}
const char *CellFunctions::GetCell(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
tempCellDescription = player->cell.getDescription().c_str();
return tempCellDescription.c_str();
}
int CellFunctions::GetExteriorX(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->cell.mData.mX;
}
int CellFunctions::GetExteriorY(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->cell.mData.mY;
}
bool CellFunctions::IsInExterior(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, false);
return player->cell.isExterior();
}
const char *CellFunctions::GetRegion(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->cell.mRegion.c_str();
}
bool CellFunctions::IsChangingRegion(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, false);
return player->isChangingRegion;
}
void CellFunctions::SetCell(unsigned short pid, const char *cellDescription) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Script is moving %s from %s to %s", player->npc.mName.c_str(),
player->cell.getDescription().c_str(), cellDescription);
player->cell = Utils::getCellFromDescription(cellDescription);
}
void CellFunctions::SetExteriorCell(unsigned short pid, int x, int y) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Script is moving %s from %s to %i,%i", player->npc.mName.c_str(),
player->cell.getDescription().c_str(), x, y);
// If the player is currently in an interior, turn off the interior flag
// from the cell
if (!player->cell.isExterior())
player->cell.mData.mFlags &= ~ESM::Cell::Interior;
player->cell.mData.mX = x;
player->cell.mData.mY = y;
}
void CellFunctions::AddCellExplored(unsigned short pid, const char* cellDescription) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
ESM::Cell cellExplored = Utils::getCellFromDescription(cellDescription);
player->mapChanges.cellsExplored.push_back(cellExplored);
}
void CellFunctions::SendCell(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CELL_CHANGE)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CELL_CHANGE)->Send(false);
}
void CellFunctions::SendMapChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MAP)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MAP)->Send(toOthers);
}

@ -1,179 +0,0 @@
#ifndef OPENMW_CELLAPI_HPP
#define OPENMW_CELLAPI_HPP
#include "../Types.hpp"
#define CELLAPI \
{"InitializeMapChanges", CellFunctions::InitializeMapChanges},\
\
{"GetCellStateChangesSize", CellFunctions::GetCellStateChangesSize},\
\
{"GetCellStateType", CellFunctions::GetCellStateType},\
{"GetCellStateDescription", CellFunctions::GetCellStateDescription},\
\
{"GetCell", CellFunctions::GetCell},\
{"GetExteriorX", CellFunctions::GetExteriorX},\
{"GetExteriorY", CellFunctions::GetExteriorY},\
{"IsInExterior", CellFunctions::IsInExterior},\
\
{"GetRegion", CellFunctions::GetRegion},\
{"IsChangingRegion", CellFunctions::IsChangingRegion},\
\
{"SetCell", CellFunctions::SetCell},\
{"SetExteriorCell", CellFunctions::SetExteriorCell},\
\
{"AddCellExplored", CellFunctions::AddCellExplored},\
\
{"SendCell", CellFunctions::SendCell},\
{"SendMapChanges", CellFunctions::SendMapChanges}
class CellFunctions
{
public:
/**
* \brief Clear the last recorded map changes for a player.
*
* This is used to initialize the sending of new PlayerMap packets.
*
* \param pid The player ID whose map changes should be used.
* \return void
*/
static void InitializeMapChanges(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest cell state changes.
*
* \param pid The player ID whose cell state changes should be used.
* \return The number of indexes.
*/
static unsigned int GetCellStateChangesSize(unsigned short pid) noexcept;
/**
* \brief Get the cell state type at a certain index in a player's latest cell state changes.
*
* \param pid The player ID whose cell state changes should be used.
* \param i The index of the cell state.
* \return The cell state type (0 for LOAD, 1 for UNLOAD).
*/
static unsigned int GetCellStateType(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the cell description at a certain index in a player's latest cell state changes.
*
* \param pid The player ID whose cell state changes should be used.
* \param i The index of the cell state.
* \return The cell description.
*/
static const char *GetCellStateDescription(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the cell description of a player's cell.
*
* \param pid The player ID.
* \return The cell description.
*/
static const char *GetCell(unsigned short pid) noexcept;
/**
* \brief Get the X coordinate of the player's exterior cell.
*
* \param pid The player ID.
* \return The X coordinate of the cell.
*/
static int GetExteriorX(unsigned short pid) noexcept;
/**
* \brief Get the Y coordinate of the player's exterior cell.
*
* \param pid The player ID.
* \return The Y coordinate of the cell.
*/
static int GetExteriorY(unsigned short pid) noexcept;
/**
* \brief Check whether the player is in an exterior cell or not.
*
* \param pid The player ID.
* \return Whether the player is in an exterior cell.
*/
static bool IsInExterior(unsigned short pid) noexcept;
/**
* \brief Get the region of the player's exterior cell.
*
* A blank value will be returned if the player is in an interior.
*
* \param pid The player ID.
* \return The region.
*/
static const char *GetRegion(unsigned short pid) noexcept;
/**
* \brief Check whether the player's last cell change has involved a region change.
*
* \param pid The player ID.
* \return Whether the player has changed their region.
*/
static bool IsChangingRegion(unsigned short pid) noexcept;
/**
* \brief Set the cell of a player.
*
* This changes the cell recorded for that player in the server memory, but does not by itself
* send a packet.
*
* The cell is determined to be an exterior cell if it fits the pattern of a number followed
* by a comma followed by another number.
*
* \param pid The player ID.
* \param cellDescription The cell description.
* \return void
*/
static void SetCell(unsigned short pid, const char *cellDescription) noexcept;
/**
* \brief Set the cell of a player to an exterior cell.
*
* This changes the cell recorded for that player in the server memory, but does not by itself
* send a packet.
*
* \param pid The player ID.
* \param x The X coordinate of the cell.
* \param y The Y coordinate of the cell.
* \return void
*/
static void SetExteriorCell(unsigned short pid, int x, int y) noexcept;
/**
* \brief Add a new explored cell to the map changes for a player.
*
* \param pid The player ID whose map changes should be used.
* \param cellDescription The cell description of the explored cell.
* \return void
*/
static void AddCellExplored(unsigned short pid, const char* cellDescription) noexcept;
/**
* \brief Send a PlayerCellChange packet about a player.
*
* It is only sent to the affected player.
*
* \param pid The player ID.
* \return void
*/
static void SendCell(unsigned short pid) noexcept;
/**
* \brief Send a PlayerMap packet with a player's recorded map changes.
*
* \param pid The player ID whose map changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendMapChanges(unsigned short pid, bool toOthers = false) noexcept;
};
#endif //OPENMW_CELLAPI_HPP

@ -1,135 +0,0 @@
//
// Created by koncord on 29.08.16.
//
#include "CharClass.hpp"
#include <apps/openmw-mp/Networking.hpp>
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
using namespace std;
using namespace ESM;
const char *CharClassFunctions::GetDefaultClass(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
return player->charClass.mId.c_str();
}
const char *CharClassFunctions::GetClassName(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
return player->charClass.mName.c_str();
}
const char *CharClassFunctions::GetClassDesc(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
return player->charClass.mDescription.c_str();
}
int CharClassFunctions::GetClassMajorAttribute(unsigned short pid, unsigned char slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (slot > 1)
throw invalid_argument("Incorrect attribute slot id");
return player->charClass.mData.mAttribute[slot];
}
int CharClassFunctions::GetClassSpecialization(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->charClass.mData.mSpecialization;
}
int CharClassFunctions::GetClassMajorSkill(unsigned short pid, unsigned char slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (slot > 4)
throw invalid_argument("Incorrect skill slot id");
return player->charClass.mData.mSkills[slot][1];
}
int CharClassFunctions::GetClassMinorSkill(unsigned short pid, unsigned char slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (slot > 4)
throw invalid_argument("Incorrect skill slot id");
return player->charClass.mData.mSkills[slot][0];
}
int CharClassFunctions::IsClassDefault(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return !player->charClass.mId.empty(); // true if default
}
void CharClassFunctions::SetDefaultClass(unsigned short pid, const char *id) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->charClass.mId = id;
}
void CharClassFunctions::SetClassName(unsigned short pid, const char *name) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->charClass.mName = name;
player->charClass.mId = "";
}
void CharClassFunctions::SetClassDesc(unsigned short pid, const char *desc) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->charClass.mDescription = desc;
}
void CharClassFunctions::SetClassMajorAttribute(unsigned short pid, unsigned char slot, int attrId) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (slot > 1)
throw invalid_argument("Incorrect attribute slot id");
player->charClass.mData.mAttribute[slot] = attrId;
}
void CharClassFunctions::SetClassSpecialization(unsigned short pid, int spec) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->charClass.mData.mSpecialization = spec;
}
void CharClassFunctions::SetClassMajorSkill(unsigned short pid, unsigned char slot, int skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (slot > 4)
throw invalid_argument("Incorrect skill slot id");
player->charClass.mData.mSkills[slot][1] = skillId;
}
void CharClassFunctions::SetClassMinorSkill(unsigned short pid, unsigned char slot, int skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (slot > 4)
throw invalid_argument("Incorrect skill slot id");
player->charClass.mData.mSkills[slot][0] = skillId;
}
void CharClassFunctions::SendClass(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARCLASS)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARCLASS)->Send(false);
}

@ -1,181 +0,0 @@
//
// Created by koncord on 29.08.16.
//
#ifndef OPENMW_CHARCLASSAPI_HPP
#define OPENMW_CHARCLASSAPI_HPP
#include "../Types.hpp"
#define CHARCLASSAPI \
{"GetDefaultClass", CharClassFunctions::GetDefaultClass},\
{"GetClassName", CharClassFunctions::GetClassName},\
{"GetClassDesc", CharClassFunctions::GetClassDesc},\
{"GetClassMajorAttribute", CharClassFunctions::GetClassMajorAttribute},\
{"GetClassSpecialization", CharClassFunctions::GetClassSpecialization},\
{"GetClassMajorSkill", CharClassFunctions::GetClassMajorSkill},\
{"GetClassMinorSkill", CharClassFunctions::GetClassMinorSkill},\
{"IsClassDefault", CharClassFunctions::IsClassDefault},\
\
{"SetDefaultClass", CharClassFunctions::SetDefaultClass},\
{"SetClassName", CharClassFunctions::SetClassName},\
{"SetClassDesc", CharClassFunctions::SetClassDesc},\
{"SetClassMajorAttribute", CharClassFunctions::SetClassMajorAttribute},\
{"SetClassSpecialization", CharClassFunctions::SetClassSpecialization},\
{"SetClassMajorSkill", CharClassFunctions::SetClassMajorSkill},\
{"SetClassMinorSkill", CharClassFunctions::SetClassMinorSkill},\
\
{"SendClass", CharClassFunctions::SendClass}
class CharClassFunctions
{
public:
/**
* \brief Get the default class used by a player.
*
* \param pid The player ID.
* \return The ID of the default class.
*/
static const char *GetDefaultClass(unsigned short pid) noexcept;
/**
* \brief Get the name of the custom class used by a player.
*
* \param pid The player ID.
* \return The name of the custom class.
*/
static const char *GetClassName(unsigned short pid) noexcept;
/**
* \brief Get the description of the custom class used by a player.
*
* \param pid The player ID.
* \return The description of the custom class.
*/
static const char *GetClassDesc(unsigned short pid) noexcept;
/**
* \brief Get the ID of one of the two major attributes of a custom class used by a player.
*
* \param pid The player ID.
* \param slot The slot of the major attribute (0 or 1).
* \return The ID of the major attribute.
*/
static int GetClassMajorAttribute(unsigned short pid, unsigned char slot) noexcept;
/**
* \brief Get the specialization ID of the custom class used by a player.
*
* \param pid The player ID.
* \return The specialization ID of the custom class (0 for Combat, 1 for Magic, 2 for Stealth).
*/
static int GetClassSpecialization(unsigned short pid) noexcept;
/**
* \brief Get the ID of one of the five major skills of a custom class used by a player.
*
* \param pid The player ID.
* \param slot The slot of the major skill (0 to 4).
* \return The ID of the major skill.
*/
static int GetClassMajorSkill(unsigned short pid, unsigned char slot) noexcept;
/**
* \brief Get the ID of one of the five minor skills of a custom class used by a player.
*
* \param pid The player ID.
* \param slot The slot of the minor skill (0 to 4).
* \return The ID of the minor skill.
*/
static int GetClassMinorSkill(unsigned short pid, unsigned char slot) noexcept;
/**
* \brief Check whether the player is using a default class instead of a custom one.
*
* \param pid The player ID.
* \return Whether the player is using a default class.
*/
static int IsClassDefault(unsigned short pid) noexcept;
/**
* \brief Set the default class used by a player.
*
* If this is left blank, the custom class data set for the player will be used instead.
*
* \param pid The player ID.
* \param id The ID of the default class.
* \return void
*/
static void SetDefaultClass(unsigned short pid, const char *id) noexcept;
/**
* \brief Set the name of the custom class used by a player.
*
* \param pid The player ID.
* \param name The name of the custom class.
* \return void
*/
static void SetClassName(unsigned short pid, const char *name) noexcept;
/**
* \brief Set the description of the custom class used by a player.
*
* \param pid The player ID.
* \param desc The description of the custom class.
* \return void
*/
static void SetClassDesc(unsigned short pid, const char *desc) noexcept;
/**
* \brief Set the ID of one of the two major attributes of the custom class used by a player.
*
* \param pid The player ID.
* \param slot The slot of the major attribute (0 or 1).
* \param attrId The ID to use for the attribute.
* \return void
*/
static void SetClassMajorAttribute(unsigned short pid, unsigned char slot, int attrId) noexcept;
/**
* \brief Set the specialization of the custom class used by a player.
*
* \param pid The player ID.
* \param spec The specialization ID to use (0 for Combat, 1 for Magic, 2 for Stealth).
* \return void
*/
static void SetClassSpecialization(unsigned short pid, int spec) noexcept;
/**
* \brief Set the ID of one of the five major skills of the custom class used by a player.
*
* \param pid The player ID.
* \param slot The slot of the major skill (0 to 4).
* \param skillId The ID to use for the skill.
* \return void
*/
static void SetClassMajorSkill(unsigned short pid, unsigned char slot, int skillId) noexcept;
/**
* \brief Set the ID of one of the five minor skills of the custom class used by a player.
*
* \param pid The player ID.
* \param slot The slot of the minor skill (0 to 4).
* \param skillId The ID to use for the skill.
* \return void
*/
static void SetClassMinorSkill(unsigned short pid, unsigned char slot, int skillId) noexcept;
/**
* \brief Send a PlayerCharClass packet about a player.
*
* It is only sent to the affected player.
*
* \param pid The player ID.
* \return void
*/
static void SendClass(unsigned short pid) noexcept;
};
#endif //OPENMW_CHARCLASSAPI_HPP

@ -1,46 +0,0 @@
//
// Created by koncord on 29.04.16.
//
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
void ScriptFunctions::SendMessage(unsigned short pid, const char *message, bool broadcast) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->chatMessage = message;
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "System: %s", message);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->Send(false);
if (broadcast)
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->Send(true);
}
void ScriptFunctions::CleanChatByPid(unsigned short pid)
{
Player *player;
GET_PLAYER(pid, player,);
player->chatMessage.clear();
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->Send(false);
}
void ScriptFunctions::CleanChat()
{
for (auto player : *Players::getPlayers())
{
player.second->chatMessage.clear();
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->setPlayer(player.second);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_CHAT_MESSAGE)->Send(false);
}
}

@ -1,53 +0,0 @@
#include "Dialogue.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
using namespace mwmp;
void DialogueFunctions::InitializeTopicChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->topicChanges.topics.clear();
}
unsigned int DialogueFunctions::GetTopicChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->topicChanges.count;
}
void DialogueFunctions::AddTopic(unsigned short pid, const char* topicId) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Topic topic;
topic.topicId = topicId;
player->topicChanges.topics.push_back(topic);
}
const char *DialogueFunctions::GetTopicId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->topicChanges.count)
return "invalid";
return player->topicChanges.topics.at(i).topicId.c_str();
}
void DialogueFunctions::SendTopicChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_TOPIC)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_TOPIC)->Send(toOthers);
}

@ -1,68 +0,0 @@
#ifndef OPENMW_DIALOGUEAPI_HPP
#define OPENMW_DIALOGUEAPI_HPP
#define DIALOGUEAPI \
{"InitializeTopicChanges", DialogueFunctions::InitializeTopicChanges},\
\
{"GetTopicChangesSize", DialogueFunctions::GetTopicChangesSize},\
\
{"AddTopic", DialogueFunctions::AddTopic},\
\
{"GetTopicId", DialogueFunctions::GetTopicId},\
\
{"SendTopicChanges", DialogueFunctions::SendTopicChanges}
class DialogueFunctions
{
public:
/**
* \brief Clear the last recorded topic changes for a player.
*
* This is used to initialize the sending of new PlayerTopic packets.
*
* \param pid The player ID whose topic changes should be used.
* \return void
*/
static void InitializeTopicChanges(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest topic changes.
*
* \param pid The player ID whose topic changes should be used.
* \return The number of indexes.
*/
static unsigned int GetTopicChangesSize(unsigned short pid) noexcept;
/**
* \brief Add a new topic to the topic changes for a player.
*
* \param pid The player ID whose topic changes should be used.
* \param topicId The topicId of the topic.
* \return void
*/
static void AddTopic(unsigned short pid, const char* topicId) noexcept;
/**
* \brief Get the topicId at a certain index in a player's latest topic changes.
*
* \param pid The player ID whose topic changes should be used.
* \param i The index of the topic.
* \return The topicId.
*/
static const char *GetTopicId(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Send a PlayerTopic packet with a player's recorded topic changes.
*
* \param pid The player ID whose topic changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendTopicChanges(unsigned short pid, bool toOthers = false) noexcept;
private:
};
#endif //OPENMW_DIALOGUEAPI_HPP

@ -1,116 +0,0 @@
#include "Factions.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/misc/stringops.hpp>
using namespace mwmp;
Faction tempFaction;
const Faction emptyFaction = {};
void FactionFunctions::InitializeFactionChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->factionChanges.factions.clear();
}
unsigned int FactionFunctions::GetFactionChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->factionChanges.count;
}
unsigned char FactionFunctions::GetFactionChangesAction(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->factionChanges.action;
}
const char *FactionFunctions::GetFactionId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->factionChanges.count)
return "invalid";
return player->factionChanges.factions.at(i).factionId.c_str();
}
int FactionFunctions::GetFactionRank(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->factionChanges.factions.at(i).rank;
}
bool FactionFunctions::GetFactionExpulsionState(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, false);
return player->factionChanges.factions.at(i).isExpelled;
}
int FactionFunctions::GetFactionReputation(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->factionChanges.factions.at(i).reputation;
}
void FactionFunctions::SetFactionChangesAction(unsigned short pid, unsigned char action) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->factionChanges.action = action;
}
void FactionFunctions::SetFactionId(const char* factionId) noexcept
{
tempFaction.factionId = factionId;
}
void FactionFunctions::SetFactionRank(unsigned int rank) noexcept
{
tempFaction.rank = rank;
}
void FactionFunctions::SetFactionExpulsionState(bool expulsionState) noexcept
{
tempFaction.isExpelled = expulsionState;
}
void FactionFunctions::SetFactionReputation(int reputation) noexcept
{
tempFaction.reputation = reputation;
}
void FactionFunctions::AddFaction(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->factionChanges.factions.push_back(tempFaction);
tempFaction = emptyFaction;
}
void FactionFunctions::SendFactionChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_FACTION)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_FACTION)->Send(toOthers);
}

@ -1,156 +0,0 @@
#ifndef OPENMW_FACTIONAPI_HPP
#define OPENMW_FACTIONAPI_HPP
#define FACTIONAPI \
{"InitializeFactionChanges", FactionFunctions::InitializeFactionChanges},\
\
{"GetFactionChangesSize", FactionFunctions::GetFactionChangesSize},\
{"GetFactionChangesAction", FactionFunctions::GetFactionChangesAction},\
\
{"GetFactionId", FactionFunctions::GetFactionId},\
{"GetFactionRank", FactionFunctions::GetFactionRank},\
{"GetFactionExpulsionState", FactionFunctions::GetFactionExpulsionState},\
{"GetFactionReputation", FactionFunctions::GetFactionReputation},\
\
{"SetFactionChangesAction", FactionFunctions::SetFactionChangesAction},\
{"SetFactionId", FactionFunctions::SetFactionId},\
{"SetFactionRank", FactionFunctions::SetFactionRank},\
{"SetFactionExpulsionState", FactionFunctions::SetFactionExpulsionState},\
{"SetFactionReputation", FactionFunctions::SetFactionReputation},\
\
{"AddFaction", FactionFunctions::AddFaction},\
\
{"SendFactionChanges", FactionFunctions::SendFactionChanges}
class FactionFunctions
{
public:
/**
* \brief Clear the last recorded faction changes for a player.
*
* This is used to initialize the sending of new PlayerFaction packets.
*
* \param pid The player ID whose faction changes should be used.
* \return void
*/
static void InitializeFactionChanges(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \return The number of indexes.
*/
static unsigned int GetFactionChangesSize(unsigned short pid) noexcept;
/**
* \brief Get the action type used in a player's latest faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \return The action type (0 for RANK, 1 for EXPULSION, 2 for REPUTATION).
*/
static unsigned char GetFactionChangesAction(unsigned short pid) noexcept;
/**
* \brief Get the factionId at a certain index in a player's latest faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \param i The index of the faction.
* \return The factionId.
*/
static const char *GetFactionId(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the rank at a certain index in a player's latest faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \param i The index of the faction.
* \return The rank.
*/
static int GetFactionRank(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the expulsion state at a certain index in a player's latest faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \param i The index of the faction.
* \return The expulsion state.
*/
static bool GetFactionExpulsionState(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the reputation at a certain index in a player's latest faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \param i The index of the faction.
* \return The reputation.
*/
static int GetFactionReputation(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Set the action type in a player's faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \param action The action (0 for RANK, 1 for EXPULSION, 2 for REPUTATION).
* \return void
*/
static void SetFactionChangesAction(unsigned short pid, unsigned char action) noexcept;
/**
* \brief Set the factionId of the temporary faction stored on the server.
*
* \param factionId The factionId.
* \return void
*/
static void SetFactionId(const char* factionId) noexcept;
/**
* \brief Set the rank of the temporary faction stored on the server.
*
* \param rank The rank.
* \return void
*/
static void SetFactionRank(unsigned int rank) noexcept;
/**
* \brief Set the expulsion state of the temporary faction stored on the server.
*
* \param expulsionState The expulsion state.
* \return void
*/
static void SetFactionExpulsionState(bool expulsionState) noexcept;
/**
* \brief Set the reputation of the temporary faction stored on the server.
*
* \param reputation The reputation.
* \return void
*/
static void SetFactionReputation(int reputation) noexcept;
/**
* \brief Add the server's temporary faction to the faction changes for a player.
*
* In the process, the server's temporary faction will automatically be cleared so a new one
* can be set up.
*
* \param pid The player ID whose faction changes should be used.
* \return void
*/
static void AddFaction(unsigned short pid) noexcept;
/**
* \brief Send a PlayerFaction packet with a player's recorded faction changes.
*
* \param pid The player ID whose faction changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendFactionChanges(unsigned short pid, bool toOthers = false) noexcept;
private:
};
#endif //OPENMW_FACTIONAPI_HPP

@ -1,86 +0,0 @@
//
// Created by koncord on 23.07.16.
//
#include "GUI.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
void GUIFunctions::_MessageBox(unsigned short pid, int id, const char *label) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.type = Player::GUIMessageBox::MessageBox;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->Send(false);
}
void GUIFunctions::CustomMessageBox(unsigned short pid, int id, const char *label, const char *buttons) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.buttons = buttons;
player->guiMessageBox.type = Player::GUIMessageBox::CustomMessageBox;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->Send(false);
}
void GUIFunctions::InputDialog(unsigned short pid, int id, const char *label) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.type = Player::GUIMessageBox::InputDialog;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->Send(false);
}
void GUIFunctions::PasswordDialog(unsigned short pid, int id, const char *label, const char *note) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.note = note;
player->guiMessageBox.type = Player::GUIMessageBox::PasswordDialog;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->Send(false);
}
void GUIFunctions::ListBox(unsigned short pid, int id, const char *label, const char *items)
{
Player *player;
GET_PLAYER(pid, player,);
player->guiMessageBox.id = id;
player->guiMessageBox.label = label;
player->guiMessageBox.data = items;
player->guiMessageBox.type = Player::GUIMessageBox::ListBox;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX)->Send(false);
}
void GUIFunctions::SetMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state) noexcept
{
LOG_MESSAGE(Log::LOG_WARN, "stub");
}
void GUIFunctions::SetMapVisibilityAll(unsigned short targetPID, unsigned short state) noexcept
{
LOG_MESSAGE(Log::LOG_WARN, "stub");
}

@ -1,34 +0,0 @@
//
// Created by koncord on 30.08.16.
//
#ifndef OPENMW_GUIAPI_HPP
#define OPENMW_GUIAPI_HPP
#define GUIAPI \
{"MessageBox", GUIFunctions::_MessageBox},\
{"CustomMessageBox", GUIFunctions::CustomMessageBox},\
{"InputDialog", GUIFunctions::InputDialog},\
{"PasswordDialog", GUIFunctions::PasswordDialog},\
{"ListBox", GUIFunctions::ListBox},\
{"SetMapVisibility", GUIFunctions::SetMapVisibility},\
{"SetMapVisibilityAll", GUIFunctions::SetMapVisibilityAll}
class GUIFunctions
{
public:
/* Do not rename into MessageBox to not conflict with WINAPI's MessageBox */
static void _MessageBox(unsigned short pid, int id, const char *label) noexcept;
static void CustomMessageBox(unsigned short pid, int id, const char *label, const char *buttons) noexcept;
static void InputDialog(unsigned short pid, int id, const char *label) noexcept;
static void PasswordDialog(unsigned short pid, int id, const char *label, const char *note) noexcept;
static void ListBox(unsigned short pid, int id, const char *label, const char *items);
//state 0 - disallow, 1 - allow
static void SetMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state) noexcept;
static void SetMapVisibilityAll(unsigned short targetPID, unsigned short state) noexcept;
};
#endif //OPENMW_GUIAPI_HPP

@ -1,160 +0,0 @@
//
// Created by koncord on 02.03.16.
//
#include "Items.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <apps/openmw/mwworld/inventorystore.hpp>
#include <components/misc/stringops.hpp>
using namespace mwmp;
void ItemFunctions::InitializeInventoryChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->inventoryChanges.items.clear();
player->inventoryChanges.action = InventoryChanges::SET;
}
int ItemFunctions::GetEquipmentSize() noexcept
{
return MWWorld::InventoryStore::Slots;
}
unsigned int ItemFunctions::GetInventoryChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->inventoryChanges.count;
}
void ItemFunctions::EquipItem(unsigned short pid, unsigned short slot, const char *refId, unsigned int count, int charge) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->equipedItems[slot].refId = refId;
player->equipedItems[slot].count = count;
player->equipedItems[slot].charge = charge;
}
void ItemFunctions::UnequipItem(unsigned short pid, unsigned short slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
ItemFunctions::EquipItem(pid, slot, "", 0, -1);
}
void ItemFunctions::AddItem(unsigned short pid, const char* refId, unsigned int count, int charge) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
Item item;
item.refId = refId;
item.count = count;
item.charge = charge;
player->inventoryChanges.items.push_back(item);
player->inventoryChanges.action = InventoryChanges::ADD;
}
void ItemFunctions::RemoveItem(unsigned short pid, const char* refId, unsigned short count) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
Item item;
item.refId = refId;
item.count = count;
player->inventoryChanges.items.push_back(item);
player->inventoryChanges.action = InventoryChanges::REMOVE;
}
bool ItemFunctions::HasItemEquipped(unsigned short pid, const char* refId)
{
Player *player;
GET_PLAYER(pid, player, false);
for (int slot = 0; slot < MWWorld::InventoryStore::Slots; slot++)
if (Misc::StringUtils::ciEqual(player->equipedItems[slot].refId, refId))
return true;
return false;
}
const char *ItemFunctions::GetEquipmentItemRefId(unsigned short pid, unsigned short slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->equipedItems[slot].refId.c_str();
}
int ItemFunctions::GetEquipmentItemCount(unsigned short pid, unsigned short slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->equipedItems[slot].count;
}
int ItemFunctions::GetEquipmentItemCharge(unsigned short pid, unsigned short slot) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->equipedItems[slot].charge;
}
const char *ItemFunctions::GetInventoryItemRefId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->inventoryChanges.count)
return "invalid";
return player->inventoryChanges.items.at(i).refId.c_str();
}
int ItemFunctions::GetInventoryItemCount(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->inventoryChanges.items.at(i).count;
}
int ItemFunctions::GetInventoryItemCharge(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->inventoryChanges.items.at(i).charge;
}
void ItemFunctions::SendEquipment(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_EQUIPMENT)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_EQUIPMENT)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_EQUIPMENT)->Send(true);
}
void ItemFunctions::SendInventoryChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_INVENTORY)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_INVENTORY)->Send(toOthers);
}

@ -1,64 +0,0 @@
//
// Created by koncord on 30.08.16.
//
#ifndef OPENMW_ITEMAPI_HPP
#define OPENMW_ITEMAPI_HPP
#define ITEMAPI \
{"InitializeInventoryChanges", ItemFunctions::InitializeInventoryChanges},\
\
{"GetEquipmentSize", ItemFunctions::GetEquipmentSize},\
{"GetInventoryChangesSize", ItemFunctions::GetInventoryChangesSize},\
\
{"EquipItem", ItemFunctions::EquipItem},\
{"UnequipItem", ItemFunctions::UnequipItem},\
\
{"AddItem", ItemFunctions::AddItem},\
{"RemoveItem", ItemFunctions::RemoveItem},\
\
{"HasItemEquipped", ItemFunctions::HasItemEquipped},\
\
{"GetEquipmentItemRefId", ItemFunctions::GetEquipmentItemRefId},\
{"GetEquipmentItemCount", ItemFunctions::GetEquipmentItemCount},\
{"GetEquipmentItemCharge", ItemFunctions::GetEquipmentItemCharge},\
\
{"GetInventoryItemRefId", ItemFunctions::GetInventoryItemRefId},\
{"GetInventoryItemCount", ItemFunctions::GetInventoryItemCount},\
{"GetInventoryItemCharge", ItemFunctions::GetInventoryItemCharge},\
\
{"SendEquipment", ItemFunctions::SendEquipment},\
{"SendInventoryChanges", ItemFunctions::SendInventoryChanges}
class ItemFunctions
{
public:
static void InitializeInventoryChanges(unsigned short pid) noexcept;
static int GetEquipmentSize() noexcept;
static unsigned int GetInventoryChangesSize(unsigned short pid) noexcept;
static void EquipItem(unsigned short pid, unsigned short slot, const char* refId, unsigned int count, int charge) noexcept;
static void UnequipItem(unsigned short pid, unsigned short slot) noexcept;
static void AddItem(unsigned short pid, const char* refId, unsigned int count, int charge) noexcept;
static void RemoveItem(unsigned short pid, const char* refId, unsigned short count) noexcept;
static bool HasItemEquipped(unsigned short pid, const char* refId);
static const char *GetEquipmentItemRefId(unsigned short pid, unsigned short slot) noexcept;
static int GetEquipmentItemCount(unsigned short pid, unsigned short slot) noexcept;
static int GetEquipmentItemCharge(unsigned short pid, unsigned short slot) noexcept;
static const char *GetInventoryItemRefId(unsigned short pid, unsigned int i) noexcept;
static int GetInventoryItemCount(unsigned short pid, unsigned int i) noexcept;
static int GetInventoryItemCharge(unsigned short pid, unsigned int i) noexcept;
static void SendEquipment(unsigned short pid) noexcept;
static void SendInventoryChanges(unsigned short pid, bool toOthers = false) noexcept;
private:
};
#endif //OPENMW_ITEMAPI_HPP

@ -1,62 +0,0 @@
#include "Mechanics.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/Log.hpp>
#include <iostream>
using namespace std;
bool MechanicsFunctions::IsWerewolf(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->isWerewolf;
}
void MechanicsFunctions::SetWerewolfState(unsigned short pid, bool isWerewolf)
{
Player *player;
GET_PLAYER(pid, player, );
player->isWerewolf = isWerewolf;
}
void MechanicsFunctions::SendShapeshift(unsigned short pid)
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SHAPESHIFT)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SHAPESHIFT)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SHAPESHIFT)->Send(true);
}
void MechanicsFunctions::Jail(unsigned short pid, int jailDays, bool ignoreJailTeleportation, bool ignoreJailSkillIncreases,
const char* jailProgressText, const char* jailEndText) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->jailDays = jailDays;
player->ignoreJailTeleportation = ignoreJailTeleportation;
player->ignoreJailSkillIncreases = ignoreJailSkillIncreases;
player->jailProgressText = jailProgressText;
player->jailEndText = jailEndText;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_JAIL)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_JAIL)->Send(false);
}
void MechanicsFunctions::Resurrect(unsigned short pid, unsigned int type) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->resurrectType = type;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_RESURRECT)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_RESURRECT)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_RESURRECT)->Send(true);
}

@ -1,89 +0,0 @@
#ifndef OPENMW_MECHANICSAPI_HPP
#define OPENMW_MECHANICSAPI_HPP
#include "../Types.hpp"
#define MECHANICSAPI \
{"IsWerewolf", MechanicsFunctions::IsWerewolf},\
\
{"SetWerewolfState", MechanicsFunctions::SetWerewolfState},\
\
{"SendShapeshift", MechanicsFunctions::SendShapeshift},\
\
{"Jail", MechanicsFunctions::Jail},\
{"Resurrect", MechanicsFunctions::Resurrect}
class MechanicsFunctions
{
public:
/**
* \brief Check whether a player is a werewolf.
*
* This is based on the last PlayerShapeshift packet received or sent for that player.
*
* \param pid The player ID.
* \return The werewolf state.
*/
static bool IsWerewolf(unsigned short pid) noexcept;
/**
* \brief Set the werewolf state of a player.
*
* This changes the werewolf state recorded for that player in the server memory, but
* does not by itself send a packet.
*
* \param pid The player ID.
* \param bool The new werewolf state.
* \return void
*/
static void SetWerewolfState(unsigned short pid, bool isWerewolf);
/**
* \brief Send a PlayerShapeshift packet about a player.
*
* This sends the packet to all players connected to the server. It is currently used
* only to communicate werewolf states.
*
* \param pid The player ID.
* \return void
*/
static void SendShapeshift(unsigned short pid);
/**
* \brief Send a PlayerJail packet about a player.
*
* This is similar to the player being jailed by a guard, but provides extra parameters for
* increased flexibility.
*
* It is only sent to the player being jailed, as the other players will be informed of the
* jailing's actual consequences via other packets sent by the affected client.
*
* \param pid The player ID.
* \param jailDays The number of days to spend jailed, where each day affects one skill point.
* \param ignoreJailTeleportation Whether the player being teleported to the nearest jail
* marker should be overridden.
* \param ignoreJailSkillIncrease Whether the player's Sneak and Security skills should be
* prevented from increasing as a result of the jailing,
* overriding default behavior.
* \param jailProgressText The text that should be displayed while jailed.
* \param jailEndText The text that should be displayed once the jailing period is over.
* \return void
*/
static void Jail(unsigned short pid, int jailDays, bool ignoreJailTeleportation = false, bool ignoreJailSkillIncreases = false,
const char* jailProgressText = "", const char* jailEndText = "") noexcept;
/**
* \brief Send a PlayerResurrect packet about a player.
*
* This sends the packet to all players connected to the server.
*
* \param pid The player ID.
* \param type The type of resurrection (0 for REGULAR, 1 for IMPERIAL_SHRINE,
* 2 for TRIBUNAL_TEMPLE).
* \return void
*/
static void Resurrect(unsigned short pid, unsigned int type) noexcept;
};
#endif //OPENMW_MECHANICSAPI_HPP

@ -1,32 +0,0 @@
#include "Miscellaneous.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/Log.hpp>
#include <iostream>
using namespace std;
unsigned int MiscellaneousFunctions::GetLastPlayerId() noexcept
{
return Players::getLastPlayerId();
}
int MiscellaneousFunctions::GetCurrentMpNum() noexcept
{
return mwmp::Networking::getPtr()->getCurrentMpNum();
}
void MiscellaneousFunctions::SetCurrentMpNum(int mpNum) noexcept
{
mwmp::Networking::getPtr()->setCurrentMpNum(mpNum);
}
void MiscellaneousFunctions::LogMessage(unsigned short level, const char *message) noexcept
{
LOG_MESSAGE_SIMPLE(level, "[Script]: %s", message);
}
void MiscellaneousFunctions::LogAppend(unsigned short level, const char *message) noexcept
{
LOG_APPEND(level, "[Script]: %s", message);
}

@ -1,79 +0,0 @@
#ifndef OPENMW_MISCELLANEOUSAPI_HPP
#define OPENMW_MISCELLANEOUSAPI_HPP
#include "../Types.hpp"
#define MISCELLANEOUSAPI \
{"GetLastPlayerId", MiscellaneousFunctions::GetLastPlayerId},\
\
{"GetCurrentMpNum", MiscellaneousFunctions::GetCurrentMpNum},\
{"SetCurrentMpNum", MiscellaneousFunctions::SetCurrentMpNum},\
\
{"LogMessage", MiscellaneousFunctions::LogMessage},\
{"LogAppend", MiscellaneousFunctions::LogAppend}
class MiscellaneousFunctions
{
public:
/**
* \brief Get the last player ID currently connected to the server.
*
* Every player receives a unique numerical index known as their player ID upon joining the
* server.
*
* \return The player ID.
*/
static unsigned int GetLastPlayerId() noexcept;
/**
* \brief Get the current (latest) mpNum generated by the server.
*
* Every object that did not exist in an .ESM or .ESP data file and has instead been placed or
* spawned through a server-sent packet has a numerical index known as its mpNum.
*
* When ObjectPlace and ObjectSpawn packets are received from players, their objects lack mpNums,
* so the server assigns them some based on incrementing the server's current mpNum, with the
* operation's final mpNum becoming the server's new current mpNum.
*
* \return The mpNum.
*/
static int GetCurrentMpNum() noexcept;
/**
* \brief Set the current (latest) mpNum generated by the server.
*
* When restarting a server, it is important to revert to the previous current (latest) mpNum
* as stored in the server's data, so as to avoid starting over from 0 and ending up assigning
* duplicate mpNums to objects.
*
* \param mpNum The number that should be used as the new current mpNum.
* \return void
*/
static void SetCurrentMpNum(int mpNum) noexcept;
/**
* \brief Write a log message with its own timestamp.
*
* It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
*
* \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
* 3 for LOG_ERROR, 4 for LOG_FATAL).
* \param message The message logged.
* \return void
*/
static void LogMessage(unsigned short level, const char *message) noexcept;
/**
* \brief Write a log message without its own timestamp.
*
* It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
*
* \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
* 3 for LOG_ERROR, 4 for LOG_FATAL).
* \param message The message logged.
* \return void
*/
static void LogAppend(unsigned short level, const char *message) noexcept;
};
#endif //OPENMW_MISCELLANEOUSAPI_HPP

@ -1,128 +0,0 @@
#include "Positions.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Player.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <iostream>
using namespace std;
void PositionFunctions::GetPos(unsigned short pid, float *x, float *y, float *z) noexcept
{
*x = 0.00;
*y = 0.00;
*z = 0.00;
Player *player;
GET_PLAYER(pid, player,);
*x = player->position.pos[0];
*y = player->position.pos[1];
*z = player->position.pos[2];
}
double PositionFunctions::GetPosX(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->position.pos[0];
}
double PositionFunctions::GetPosY(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->position.pos[1];
}
double PositionFunctions::GetPosZ(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->position.pos[2];
}
double PositionFunctions::GetPreviousCellPosX(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->previousCellPosition.pos[0];
}
double PositionFunctions::GetPreviousCellPosY(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->previousCellPosition.pos[1];
}
double PositionFunctions::GetPreviousCellPosZ(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->previousCellPosition.pos[2];
}
void PositionFunctions::GetRot(unsigned short pid, float *x, float *y, float *z) noexcept
{
*x = 0.00;
*y = 0.00;
*z = 0.00;
Player *player;
GET_PLAYER(pid, player, );
*x = player->position.rot[0];
*y = player->position.rot[1];
*z = player->position.rot[2];
}
double PositionFunctions::GetRotX(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->position.rot[0];
}
double PositionFunctions::GetRotZ(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->position.rot[2];
}
void PositionFunctions::SetPos(unsigned short pid, double x, double y, double z) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->position.pos[0] = x;
player->position.pos[1] = y;
player->position.pos[2] = z;
}
void PositionFunctions::SetRot(unsigned short pid, double x, double z) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->position.rot[0] = x;
player->position.rot[2] = z;
}
void PositionFunctions::SendPos(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_POSITION)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_POSITION)->Send(false);
}

@ -1,158 +0,0 @@
#ifndef OPENMW_POSITIONAPI_HPP
#define OPENMW_POSITIONAPI_HPP
#include "../Types.hpp"
#define POSITIONAPI \
{"GetPos", PositionFunctions::GetPos},\
{"GetPosX", PositionFunctions::GetPosX},\
{"GetPosY", PositionFunctions::GetPosY},\
{"GetPosZ", PositionFunctions::GetPosZ},\
\
{"GetPreviousCellPosX", PositionFunctions::GetPreviousCellPosX},\
{"GetPreviousCellPosY", PositionFunctions::GetPreviousCellPosY},\
{"GetPreviousCellPosZ", PositionFunctions::GetPreviousCellPosZ},\
\
{"GetRot", PositionFunctions::GetRot},\
{"GetRotX", PositionFunctions::GetRotX},\
{"GetRotZ", PositionFunctions::GetRotZ},\
\
{"SetPos", PositionFunctions::SetPos},\
{"SetRot", PositionFunctions::SetRot},\
\
{"SendPos", PositionFunctions::SendPos}
class PositionFunctions
{
public:
/**
* \brief Assign the player's positional coordinate values to the variables passed as
* parameters.
*
* \param pid The player ID.
* \param x The variable for the X position.
* \param y The variable for the Y position.
* \param z The variable for the Z position.
* \return void
*/
static void GetPos(unsigned short pid, float *x, float *y, float *z) noexcept;
/**
* \brief Get the X position of a player.
*
* \param pid The player ID.
* \return The X position.
*/
static double GetPosX(unsigned short pid) noexcept;
/**
* \brief Get the Y position of a player.
*
* \param pid The player ID.
* \return The Y position.
*/
static double GetPosY(unsigned short pid) noexcept;
/**
* \brief Get the Z position of a player.
*
* \param pid The player ID.
* \return The Z position.
*/
static double GetPosZ(unsigned short pid) noexcept;
/**
* \brief Get the X position of a player from before their latest cell change.
*
* \param pid The player ID.
* \return The X position.
*/
static double GetPreviousCellPosX(unsigned short pid) noexcept;
/**
* \brief Get the Y position of a player from before their latest cell change.
*
* \param pid The player ID.
* \return The Y position.
*/
static double GetPreviousCellPosY(unsigned short pid) noexcept;
/**
* \brief Get the Z position of a player from before their latest cell change.
*
* \param pid The player ID.
* \return The Z position.
*/
static double GetPreviousCellPosZ(unsigned short pid) noexcept;
/**
* \brief Assign the player's rotational coordinate values to the variables passed as
* parameters.
*
* \param pid The player ID.
* \param x The variable for the X rotation.
* \param y The variable for the Y rotation.
* \param z The variable for the Z rotation.
* \return void
*/
static void GetRot(unsigned short pid, float *x, float *y, float *z) noexcept;
/**
* \brief Get the X rotation of a player.
*
* \param pid The player ID.
* \return The X rotation.
*/
static double GetRotX(unsigned short pid) noexcept;
/**
* \brief Get the Z rotation of a player.
*
* \param pid The player ID.
* \return The Z rotation.
*/
static double GetRotZ(unsigned short pid) noexcept;
/**
* \brief Set the position of a player.
*
* This changes the positional coordinates recorded for that player in the server memory, but
* does not by itself send a packet.
*
* \param pid The player ID.
* \param x The X position.
* \param y The Y position.
* \param z The Z position.
* \return void
*/
static void SetPos(unsigned short pid, double x, double y, double z) noexcept;
/**
* \brief Set the rotation of a player.
*
* This changes the rotational coordinates recorded for that player in the server memory, but
* does not by itself send a packet.
*
* A player's Y rotation is always 0, which is why there is no Y rotation parameter.
*
* \param pid The player ID.
* \param x The X position.
* \param z The Z position.
* \return void
*/
static void SetRot(unsigned short pid, double x, double z) noexcept;
/**
* \brief Send a PlayerPosition packet about a player.
*
* It is only sent to the affected player.
*
* \param pid The player ID.
* \return void
*/
static void SendPos(unsigned short pid) noexcept;
};
#endif //OPENMW_POSITIONAPI_HPP

@ -1,150 +0,0 @@
#include "Quests.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/misc/stringops.hpp>
using namespace mwmp;
void QuestFunctions::InitializeJournalChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->journalChanges.journalItems.clear();
}
void QuestFunctions::InitializeKillChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->killChanges.kills.clear();
}
unsigned int QuestFunctions::GetJournalChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->journalChanges.count;
}
unsigned int QuestFunctions::GetKillChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->killChanges.count;
}
void QuestFunctions::AddJournalEntry(unsigned short pid, const char* quest, unsigned int index, const char* actorRefId) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::JournalItem journalItem;
journalItem.type = JournalItem::ENTRY;
journalItem.quest = quest;
journalItem.index = index;
journalItem.actorRefId = actorRefId;
player->journalChanges.journalItems.push_back(journalItem);
}
void QuestFunctions::AddJournalIndex(unsigned short pid, const char* quest, unsigned int index) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::JournalItem journalItem;
journalItem.type = JournalItem::INDEX;
journalItem.quest = quest;
journalItem.index = index;
player->journalChanges.journalItems.push_back(journalItem);
}
void QuestFunctions::AddKill(unsigned short pid, const char* refId, int number) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Kill kill;
kill.refId = refId;
kill.number = number;
player->killChanges.kills.push_back(kill);
}
const char *QuestFunctions::GetJournalItemQuest(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->journalChanges.count)
return "invalid";
return player->journalChanges.journalItems.at(i).quest.c_str();
}
int QuestFunctions::GetJournalItemIndex(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->journalChanges.journalItems.at(i).index;
}
int QuestFunctions::GetJournalItemType(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->journalChanges.journalItems.at(i).type;
}
const char *QuestFunctions::GetJournalItemActorRefId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->journalChanges.journalItems.at(i).actorRefId.c_str();
}
const char *QuestFunctions::GetKillRefId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->killChanges.count)
return "invalid";
return player->killChanges.kills.at(i).refId.c_str();
}
int QuestFunctions::GetKillNumber(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->killChanges.kills.at(i).number;
}
void QuestFunctions::SendJournalChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_JOURNAL)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_JOURNAL)->Send(toOthers);
}
void QuestFunctions::SendKillChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_KILL_COUNT)->Send(toOthers);
}

@ -1,176 +0,0 @@
#ifndef OPENMW_QUESTAPI_HPP
#define OPENMW_QUESTAPI_HPP
#define QUESTAPI \
{"InitializeJournalChanges", QuestFunctions::InitializeJournalChanges},\
{"InitializeKillChanges", QuestFunctions::InitializeKillChanges},\
\
{"GetJournalChangesSize", QuestFunctions::GetJournalChangesSize},\
{"GetKillChangesSize", QuestFunctions::GetKillChangesSize},\
\
{"AddJournalEntry", QuestFunctions::AddJournalEntry},\
{"AddJournalIndex", QuestFunctions::AddJournalIndex},\
{"AddKill", QuestFunctions::AddKill},\
\
{"GetJournalItemQuest", QuestFunctions::GetJournalItemQuest},\
{"GetJournalItemIndex", QuestFunctions::GetJournalItemIndex},\
{"GetJournalItemType", QuestFunctions::GetJournalItemType},\
{"GetJournalItemActorRefId", QuestFunctions::GetJournalItemActorRefId},\
{"GetKillRefId", QuestFunctions::GetKillRefId},\
{"GetKillNumber", QuestFunctions::GetKillNumber},\
\
{"SendJournalChanges", QuestFunctions::SendJournalChanges},\
{"SendKillChanges", QuestFunctions::SendKillChanges}
class QuestFunctions
{
public:
/**
* \brief Clear the last recorded journal changes for a player.
*
* This is used to initialize the sending of new PlayerJournal packets.
*
* \param pid The player ID whose journal changes should be used.
* \return void
*/
static void InitializeJournalChanges(unsigned short pid) noexcept;
/**
* \brief Clear the last recorded kill count changes for a player.
*
* This is used to initialize the sending of new PlayerKillCount packets.
*
* \param pid The player ID whose kill count changes should be used.
* \return void
*/
static void InitializeKillChanges(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest journal changes.
*
* \param pid The player ID whose journal changes should be used.
* \return The number of indexes.
*/
static unsigned int GetJournalChangesSize(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest kill count changes.
*
* \param pid The player ID whose kill count changes should be used.
* \return The number of indexes.
*/
static unsigned int GetKillChangesSize(unsigned short pid) noexcept;
/**
* \brief Add a new journal item of type ENTRY to the journal changes for a player.
*
* \param pid The player ID whose journal changes should be used.
* \param quest The quest of the journal item.
* \param index The quest index of the journal item.
* \param actorRefId The actor refId of the journal item.
* \return void
*/
static void AddJournalEntry(unsigned short pid, const char* quest, unsigned int index, const char* actorRefId) noexcept;
/**
* \brief Add a new journal item of type INDEX to the journal changes for a player.
*
* \param pid The player ID whose journal changes should be used.
* \param quest The quest of the journal item.
* \param index The quest index of the journal item.
* \return void
*/
static void AddJournalIndex(unsigned short pid, const char* quest, unsigned int index) noexcept;
/**
* \brief Add a new kill count to the kill count changes for a player.
*
* \param pid The player ID whose kill count changes should be used.
* \param refId The refId of the kill count.
* \param number The number of kills in the kill count.
* \return void
*/
static void AddKill(unsigned short pid, const char* refId, int number) noexcept;
/**
* \brief Get the quest at a certain index in a player's latest journal changes.
*
* \param pid The player ID whose journal changes should be used.
* \param i The index of the journalItem.
* \return The quest.
*/
static const char *GetJournalItemQuest(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the quest index at a certain index in a player's latest journal changes.
*
* \param pid The player ID whose journal changes should be used.
* \param i The index of the journalItem.
* \return The quest index.
*/
static int GetJournalItemIndex(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the journal item type at a certain index in a player's latest journal changes.
*
* \param pid The player ID whose journal changes should be used.
* \param i The index of the journalItem.
* \return The type (0 for ENTRY, 1 for INDEX).
*/
static int GetJournalItemType(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the actor refId at a certain index in a player's latest journal changes.
*
* Every journal change has an associated actor, which is usually the quest giver.
*
* \param pid The player ID whose journal changes should be used.
* \param i The index of the journalItem.
* \return The actor refId.
*/
static const char *GetJournalItemActorRefId(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the refId at a certain index in a player's latest kill count changes.
*
* \param pid The player ID whose kill count changes should be used.
* \param i The index of the kill count.
* \return The refId.
*/
static const char *GetKillRefId(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the number of kills at a certain index in a player's latest kill count changes.
*
* \param pid The player ID whose kill count changes should be used.
* \param i The index of the kill count.
* \return The number of kills.
*/
static int GetKillNumber(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Send a PlayerJournal packet with a player's recorded journal changes.
*
* \param pid The player ID whose journal changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendJournalChanges(unsigned short pid, bool toOthers = false) noexcept;
/**
* \brief Send a PlayerKillCount packet with a player's recorded kill count changes.
*
* \param pid The player ID whose kill count changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendKillChanges(unsigned short pid, bool toOthers = false) noexcept;
private:
};
#endif //OPENMW_QUESTAPI_HPP

@ -1,33 +0,0 @@
#include "Settings.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/Log.hpp>
#include <iostream>
using namespace std;
void SettingFunctions::SetConsoleAllow(unsigned short pid, bool state)
{
Player *player;
GET_PLAYER(pid, player,);
player->consoleAllowed = state;
}
void SettingFunctions::SetDifficulty(unsigned short pid, int difficulty)
{
Player *player;
GET_PLAYER(pid, player,);
player->difficulty = difficulty;
}
void SettingFunctions::SendSettings(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_SETTINGS)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_SETTINGS)->Send(false);
}

@ -1,49 +0,0 @@
#ifndef OPENMW_SETTINGSAPI_HPP
#define OPENMW_SETTINGSAPI_HPP
#include "../Types.hpp"
#define SETTINGSAPI \
{"SetConsoleAllow", SettingFunctions::SetConsoleAllow},\
{"SetDifficulty", SettingFunctions::SetDifficulty},\
\
{"SendSettings", SettingFunctions::SendSettings}
class SettingFunctions
{
public:
/**
* \brief Set whether the console is allowed for a player.
*
* This changes the console permission for that player in the server memory, but does not
* by itself send a packet.
*
* \param pid The player ID.
* \param bool The console permission state.
* \return void
*/
static void SetConsoleAllow(unsigned short pid, bool state);
/**
* \brief Set the difficulty for a player.
*
* This changes the difficulty for that player in the server memory, but does not by itself
* send a packet.
*
* \param pid The player ID.
* \param bool The difficulty.
* \return void
*/
static void SetDifficulty(unsigned short pid, int difficulty);
/**
* \brief Send a PlayerSettings packet to the player affected by it.
*
* \param pid The player ID to send it to.
* \return void
*/
static void SendSettings(unsigned short pid) noexcept;
};
#endif //OPENMW_SETTINGSAPI_HPP

@ -1,277 +0,0 @@
#include "Spells.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/misc/stringops.hpp>
using namespace mwmp;
void SpellFunctions::InitializeSpellbookChanges(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->spellbookChanges.spells.clear();
}
unsigned int SpellFunctions::GetSpellbookChangesSize(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->spellbookChanges.count;
}
unsigned int SpellFunctions::GetSpellbookChangesAction(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->spellbookChanges.action;
}
void SpellFunctions::SetSpellbookChangesAction(unsigned short pid, unsigned char action) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->spellbookChanges.action = action;
}
void SpellFunctions::AddSpell(unsigned short pid, const char* spellId) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
ESM::Spell spell;
spell.mId = spellId;
player->spellbookChanges.spells.push_back(spell);
}
void SpellFunctions::AddCustomSpell(unsigned short pid, const char* spellId, const char* spellName) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
ESM::Spell spell;
spell.mName = spellName;
spell.mId = spellId;
player->spellbookChanges.spells.push_back(spell);
}
void SpellFunctions::AddCustomSpellData(unsigned short pid, const char* spellId, int type, int cost, int flags) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
int index = -1;
for(int i = 0; i < player->spellbookChanges.spells.size(); i++)
{
if( strcmp(player->spellbookChanges.spells.at(i).mId.c_str(), spellId) == 0)
{
index = i;
}
}
if(index == -1)
return;
player->spellbookChanges.spells.at(index).mData.mType = type;
player->spellbookChanges.spells.at(index).mData.mCost = cost;
player->spellbookChanges.spells.at(index).mData.mFlags = flags;
}
void SpellFunctions::AddCustomSpellEffect(unsigned short pid, const char* spellId, short effectId, signed char mSkill, signed char mAttribute, int mRange, int mArea, int mDuration, int mMagnMin, int mMagnMax) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
int index = -1;
for(int i = 0; i < player->spellbookChanges.spells.size(); i++)
{
if( strcmp(player->spellbookChanges.spells.at(i).mId.c_str(), spellId) == 0)
{
index = i;
}
}
if(index == -1)
return;
ESM::ENAMstruct effect;
effect.mEffectID = effectId;
effect.mSkill = mSkill;
effect.mAttribute = mAttribute;
effect.mRange = mRange;
effect.mArea = mArea;
effect.mDuration = mDuration;
effect.mMagnMin = mMagnMin;
effect.mMagnMax = mMagnMax;
player->spellbookChanges.spells.at(index).mEffects.mList.push_back(effect);
}
const char *SpellFunctions::GetSpellId(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->spellbookChanges.count)
return "invalid";
return player->spellbookChanges.spells.at(i).mId.c_str();
}
const char *SpellFunctions::GetSpellName(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
if (i >= player->spellbookChanges.count)
return "invalid";
return player->spellbookChanges.spells.at(i).mName.c_str();
}
int SpellFunctions::GetSpellType(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mData.mType;
}
int SpellFunctions::GetSpellCost(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mData.mCost;
}
int SpellFunctions::GetSpellFlags(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mData.mFlags;
}
unsigned int SpellFunctions::GetSpellEffectCount(unsigned short pid, unsigned int i) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.size();
}
short SpellFunctions::GetSpellEffectId(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mEffectID;
}
signed char SpellFunctions::GetSpellEffectSkill(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mSkill;
}
signed char SpellFunctions::GetSpellEffectAttribute(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mAttribute;
}
int SpellFunctions::GetSpellEffectRange(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mRange;
}
int SpellFunctions::GetSpellEffectArea(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mArea;
}
int SpellFunctions::GetSpellEffectDuration(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mDuration;
}
int SpellFunctions::GetSpellEffectMagnMin(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mMagnMin;
}
int SpellFunctions::GetSpellEffectMagnMax(unsigned short pid, unsigned int i, unsigned int j) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (i >= player->spellbookChanges.count)
return 0;
return player->spellbookChanges.spells.at(i).mEffects.mList.at(j).mMagnMax;
}
void SpellFunctions::SendSpellbookChanges(unsigned short pid, bool toOthers) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SPELLBOOK)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SPELLBOOK)->Send(toOthers);
}

@ -1,268 +0,0 @@
#ifndef OPENMW_SPELLAPI_HPP
#define OPENMW_SPELLAPI_HPP
#define SPELLAPI \
{"InitializeSpellbookChanges", SpellFunctions::InitializeSpellbookChanges},\
\
{"GetSpellbookChangesSize", SpellFunctions::GetSpellbookChangesSize},\
{"GetSpellbookChangesAction", SpellFunctions::GetSpellbookChangesAction},\
\
{"SetSpellbookChangesAction", SpellFunctions::SetSpellbookChangesAction},\
{"AddSpell", SpellFunctions::AddSpell},\
{"AddCustomSpell", SpellFunctions::AddCustomSpell},\
{"AddCustomSpellData", SpellFunctions::AddCustomSpellData},\
{"AddCustomSpellEffect", SpellFunctions::AddCustomSpellEffect},\
\
{"GetSpellId", SpellFunctions::GetSpellId},\
{"GetSpellName", SpellFunctions::GetSpellName},\
{"GetSpellType", SpellFunctions::GetSpellType},\
{"GetSpellCost", SpellFunctions::GetSpellCost},\
{"GetSpellFlags", SpellFunctions::GetSpellFlags},\
{"GetSpellEffectCount", SpellFunctions::GetSpellEffectCount},\
{"GetSpellEffectId", SpellFunctions::GetSpellEffectId},\
{"GetSpellEffectSkill", SpellFunctions::GetSpellEffectSkill},\
{"GetSpellEffectAttribute", SpellFunctions::GetSpellEffectAttribute},\
{"GetSpellEffectRange", SpellFunctions::GetSpellEffectRange},\
{"GetSpellEffectArea", SpellFunctions::GetSpellEffectArea},\
{"GetSpellEffectDuration", SpellFunctions::GetSpellEffectDuration},\
{"GetSpellEffectMagnMin", SpellFunctions::GetSpellEffectMagnMin},\
{"GetSpellEffectMagnMax", SpellFunctions::GetSpellEffectMagnMax},\
\
{"SendSpellbookChanges", SpellFunctions::SendSpellbookChanges}
class SpellFunctions
{
public:
/**
* \brief Clear the last recorded spellbook changes for a player.
*
* This is used to initialize the sending of new PlayerSpellbook packets.
*
* \param pid The player ID whose spellbook changes should be used.
* \return void
*/
static void InitializeSpellbookChanges(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \return The number of indexes.
*/
static unsigned int GetSpellbookChangesSize(unsigned short pid) noexcept;
/**
* \brief Get the action type used in a player's latest spellbook changes.
*
* \param pid The player ID whose faction changes should be used.
* \return The action type (0 for SET, 1 for ADD, 2 for REMOVE).
*/
static unsigned int GetSpellbookChangesAction(unsigned short pid) noexcept;
/**
* \brief Set the action type in a player's spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param action The action (0 for SET, 1 for ADD, 2 for REMOVE).
* \return void
*/
static void SetSpellbookChangesAction(unsigned short pid, unsigned char action) noexcept;
/**
* \brief Add a new spell to the spellbook changes for a player.
*
* \param pid The player ID whose spellbook changes should be used.
* \param spellId The spellId of the spell.
* \return void
*/
static void AddSpell(unsigned short pid, const char* spellId) noexcept;
/**
* \brief Add a new custom spell to the spellbook changes for a player.
*
* \param pid The player ID whose spellbook changes should be used.
* \param spellId The spellId of the spell.
* \param spellName The name of the spell.
* \return void
*/
static void AddCustomSpell(unsigned short pid, const char* spellId, const char* spellName) noexcept;
/**
* \brief Add custom spell data to the spellbook changes for a player.
*
* \param pid The player ID whose spellbook changes should be used.
* \param spellId The spellId of the spell.
* \param type The type of the spell.
* \param cost The cost of the spell.
* \param flags The flags of the spell.
* \return void
*/
static void AddCustomSpellData(unsigned short pid, const char* spellId, int type, int cost, int flags) noexcept;
/**
* \brief Add custom spell effect to the spellbook changes for a player.
*
* \param pid The player ID whose spellbook changes should be used.
* \param spellId The spellId of the spell.
* \param effectId The effectId of the spell effect.
* \param mSkill The skill affected by the spell effect.
* \param mAttribute The attribute affected by the spell effect.
* \param mRange The range of the spell effect.
* \param mArea The area of the spell effect.
* \param mDuration The duration of the spell effect.
* \param mMagnMin The minimum magnitude of the spell effect.
* \param mMagnMax The maximum magnitude of the spell effect.
* \return void
*/
static void AddCustomSpellEffect(unsigned short pid, const char* spellId, short effectId, signed char mSkill, signed char mAttribute, int mRange, int mArea, int mDuration, int mMagnMin, int mMagnMax) noexcept;
/**
* \brief Get the spellId at a certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \return The spellId.
*/
static const char *GetSpellId(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the name of the spell at a certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \return The spell name.
*/
static const char *GetSpellName(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the type of the spell at a certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \return The spell type.
*/
static int GetSpellType(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the cost of the spell at a certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \return The spell cost.
*/
static int GetSpellCost(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the flags of the spell at a certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \return The spell flags.
*/
static int GetSpellFlags(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the number of effects on the spell at a certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \return The spell effect count.
*/
static unsigned int GetSpellEffectCount(unsigned short pid, unsigned int i) noexcept;
/**
* \brief Get the effectId of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The effectId.
*/
static short GetSpellEffectId(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the affected skill of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The affected skill.
*/
static signed char GetSpellEffectSkill(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the affected attribute of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The affected attribute.
*/
static signed char GetSpellEffectAttribute(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the range of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The range.
*/
static int GetSpellEffectRange(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the area of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The area.
*/
static int GetSpellEffectArea(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the duration of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The duration.
*/
static int GetSpellEffectDuration(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the minimum magnitude of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The minimum magnitude.
*/
static int GetSpellEffectMagnMin(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Get the maximum magnitude of the effect at a certain index in the spell at another certain index in a player's latest spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param i The index of the spell.
* \param j The index of the effect.
* \return The maximum magnitude.
*/
static int GetSpellEffectMagnMax(unsigned short pid, unsigned int i, unsigned int j) noexcept;
/**
* \brief Send a PlayerSpellbook packet with a player's recorded spellbook changes.
*
* \param pid The player ID whose spellbook changes should be used.
* \param toOthers Whether this packet should be sent only to other players or
* only to the player it is about.
* \return void
*/
static void SendSpellbookChanges(unsigned short pid, bool toOthers = false) noexcept;
private:
};
#endif //OPENMW_SPELLAPI_HPP

@ -1,565 +0,0 @@
//
// Created by koncord on 29.02.16.
//
#include "Stats.hpp"
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/esm/attr.hpp>
#include <components/esm/loadskil.hpp>
#include <components/misc/stringops.hpp>
#include <components/openmw-mp/Log.hpp>
#include <iostream>
using namespace std;
using namespace ESM;
int StatsFunctions::GetAttributeCount() noexcept
{
return Attribute::Length;
}
int StatsFunctions::GetSkillCount() noexcept
{
return Skill::Length;
}
int StatsFunctions::GetAttributeId(const char *name) noexcept
{
for (int x = 0; x < Attribute::Length; x++)
{
if (Misc::StringUtils::ciEqual(name, Attribute::sAttributeNames[x]))
{
return x;
}
}
return -1;
}
int StatsFunctions::GetSkillId(const char *name) noexcept
{
for (int x = 0; x < Skill::Length; x++)
{
if (Misc::StringUtils::ciEqual(name, Skill::sSkillNames[x]))
{
return x;
}
}
return -1;
}
const char *StatsFunctions::GetAttributeName(unsigned short attribute) noexcept
{
if (attribute >= Attribute::Length)
return "invalid";
return Attribute::sAttributeNames[attribute].c_str();
}
const char *StatsFunctions::GetSkillName(unsigned short skill) noexcept
{
if (skill >= Skill::Length)
return "invalid";
return Skill::sSkillNames[skill].c_str();
}
const char *StatsFunctions::GetName(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mName.c_str();
}
const char *StatsFunctions::GetRace(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mRace.c_str();
}
const char *StatsFunctions::GetHead(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mHead.c_str();
}
const char *StatsFunctions::GetHairstyle(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npc.mHair.c_str();
}
int StatsFunctions::GetIsMale(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, false);
return player->npc.isMale();
}
const char *StatsFunctions::GetBirthsign(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->birthsign.c_str();
}
const char *StatsFunctions::GetCreatureModel(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->creatureModel.c_str();
}
bool StatsFunctions::IsCreatureName(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->useCreatureName;
}
const char *StatsFunctions::GetDeathReason(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->deathReason.c_str();
}
int StatsFunctions::GetLevel(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->creatureStats.mLevel;
}
int StatsFunctions::GetLevelProgress(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npcStats.mLevelProgress;
}
double StatsFunctions::GetHealthBase(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[0].mBase;
}
double StatsFunctions::GetHealthCurrent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[0].mCurrent;
}
double StatsFunctions::GetMagickaBase(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[1].mBase;
}
double StatsFunctions::GetMagickaCurrent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[1].mCurrent;
}
double StatsFunctions::GetFatigueBase(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[2].mBase;
}
double StatsFunctions::GetFatigueCurrent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
return player->creatureStats.mDynamic[2].mCurrent;
}
int StatsFunctions::GetAttributeBase(unsigned short pid, unsigned short attribute) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attribute >= Attribute::Length)
return 0;
return player->creatureStats.mAttributes[attribute].mBase;
}
int StatsFunctions::GetAttributeCurrent(unsigned short pid, unsigned short attribute) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attribute >= Attribute::Length)
return 0;
return player->creatureStats.mAttributes[attribute].mCurrent;
}
int StatsFunctions::GetSkillBase(unsigned short pid, unsigned short skill) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (skill >= Skill::Length)
return 0;
return player->npcStats.mSkills[skill].mBase;
}
int StatsFunctions::GetSkillCurrent(unsigned short pid, unsigned short skill) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (skill >= Skill::Length)
return 0;
return player->npcStats.mSkills[skill].mCurrent;
}
double StatsFunctions::GetSkillProgress(unsigned short pid, unsigned short skill) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0.0f);
if (skill >= Skill::Length)
return 0;
return player->npcStats.mSkills[skill].mProgress;
}
int StatsFunctions::GetSkillIncrease(unsigned short pid, unsigned int attribute) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attribute > Attribute::Length)
return 0;
return player->npcStats.mSkillIncrease[attribute];
}
int StatsFunctions::GetBounty(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
return player->npcStats.mBounty;
}
void StatsFunctions::SetName(unsigned short pid, const char *name) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mName == name)
return;
player->npc.mName = name;
}
void StatsFunctions::SetRace(unsigned short pid, const char *race) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mRace == race)
return;
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Setting race for %s: %s -> %s", player->npc.mName.c_str(),
player->npc.mRace.c_str(), race);
player->npc.mRace = race;
}
void StatsFunctions::SetHead(unsigned short pid, const char *head) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mHead == head)
return;
player->npc.mHead = head;
}
void StatsFunctions::SetHairstyle(unsigned short pid, const char *style) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (player->npc.mHair == style)
return;
player->npc.mHair = style;
}
void StatsFunctions::SetIsMale(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->npc.setIsMale(value == true);
}
void StatsFunctions::SetBirthsign(unsigned short pid, const char *sign) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
if (player->birthsign == sign)
return;
player->birthsign = sign;
}
void StatsFunctions::SetCreatureModel(unsigned short pid, const char *name, bool useCreatureName) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->creatureModel = name;
player->useCreatureName = useCreatureName;
}
void StatsFunctions::SetLevel(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->creatureStats.mLevel = value;
}
void StatsFunctions::SetLevelProgress(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->npcStats.mLevelProgress = value;
}
void StatsFunctions::SetHealthBase(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[0].mBase = value;
}
void StatsFunctions::SetHealthCurrent(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[0].mCurrent = value;
}
void StatsFunctions::SetMagickaBase(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[1].mBase = value;
}
void StatsFunctions::SetMagickaCurrent(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[1].mCurrent = value;
}
void StatsFunctions::SetFatigueBase(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[2].mBase = value;
}
void StatsFunctions::SetFatigueCurrent(unsigned short pid, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->creatureStats.mDynamic[2].mCurrent = value;
}
void StatsFunctions::SetAttributeBase(unsigned short pid, unsigned short attribute, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (attribute >= Attribute::Length)
return;
player->creatureStats.mAttributes[attribute].mBase = value;
}
void StatsFunctions::SetAttributeCurrent(unsigned short pid, unsigned short attribute, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (attribute >= Attribute::Length)
return;
player->creatureStats.mAttributes[attribute].mCurrent = value;
}
void StatsFunctions::SetSkillBase(unsigned short pid, unsigned short skill, int value) noexcept //TODO: need packet for one value
{
Player *player;
GET_PLAYER(pid, player,);
if (skill >= Skill::Length)
return;
player->npcStats.mSkills[skill].mBase = value;
}
void StatsFunctions::SetSkillCurrent(unsigned short pid, unsigned short skill, int value) noexcept //TODO: need packet for one value
{
Player *player;
GET_PLAYER(pid, player,);
if (skill >= Skill::Length)
return;
player->npcStats.mSkills[skill].mCurrent = value;
}
void StatsFunctions::SetSkillProgress(unsigned short pid, unsigned short skill, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
if (skill >= Skill::Length)
return;
player->npcStats.mSkills[skill].mProgress = value;
}
void StatsFunctions::SetSkillIncrease(unsigned short pid, unsigned int attribute, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
if (attribute > Attribute::Length)
return;
player->npcStats.mSkillIncrease[attribute] = value;
}
void StatsFunctions::SetBounty(unsigned short pid, int value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
player->npcStats.mBounty = value;
}
void StatsFunctions::SetCharGenStage(unsigned short pid, int start, int end) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->charGenStage.current = start;
player->charGenStage.end = end;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARGEN)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARGEN)->Send(false);
}
void StatsFunctions::SendBaseInfo(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BASEINFO)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BASEINFO)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BASEINFO)->Send(true);
}
void StatsFunctions::SendStatsDynamic(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_STATS_DYNAMIC)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_STATS_DYNAMIC)->Send(true);
}
void StatsFunctions::SendAttributes(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ATTRIBUTE)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ATTRIBUTE)->Send(true);
}
void StatsFunctions::SendSkills(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SKILL)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SKILL)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SKILL)->Send(true);
}
void StatsFunctions::SendLevel(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_LEVEL)->Send(true);
}
void StatsFunctions::SendBounty(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY)->Send(false);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOUNTY)->Send(true);
}

@ -1,163 +0,0 @@
//
// Created by koncord on 30.08.16.
//
#ifndef OPENMW_STATAPI_HPP
#define OPENMW_STATAPI_HPP
#define STATAPI \
{"GetAttributeCount", StatsFunctions::GetAttributeCount},\
{"GetSkillCount", StatsFunctions::GetSkillCount},\
{"GetAttributeId", StatsFunctions::GetAttributeId},\
{"GetSkillId", StatsFunctions::GetSkillId},\
{"GetAttributeName", StatsFunctions::GetAttributeName},\
{"GetSkillName", StatsFunctions::GetSkillName},\
\
{"GetName", StatsFunctions::GetName},\
{"GetRace", StatsFunctions::GetRace},\
{"GetHead", StatsFunctions::GetHead},\
{"GetHair", StatsFunctions::GetHairstyle},\
{"GetIsMale", StatsFunctions::GetIsMale},\
{"GetBirthsign", StatsFunctions::GetBirthsign},\
{"GetCreatureModel", StatsFunctions::GetCreatureModel},\
{"IsCreatureName", StatsFunctions::IsCreatureName},\
{"GetDeathReason", StatsFunctions::GetDeathReason},\
\
{"GetLevel", StatsFunctions::GetLevel},\
{"GetLevelProgress", StatsFunctions::GetLevelProgress},\
\
{"GetHealthBase", StatsFunctions::GetHealthBase},\
{"GetHealthCurrent", StatsFunctions::GetHealthCurrent},\
\
{"GetMagickaBase", StatsFunctions::GetMagickaBase},\
{"GetMagickaCurrent", StatsFunctions::GetMagickaCurrent},\
\
{"GetFatigueBase", StatsFunctions::GetFatigueBase},\
{"GetFatigueCurrent", StatsFunctions::GetFatigueCurrent},\
\
{"GetAttributeBase", StatsFunctions::GetAttributeBase},\
{"GetAttributeCurrent", StatsFunctions::GetAttributeCurrent},\
\
{"GetSkillBase", StatsFunctions::GetSkillBase},\
{"GetSkillCurrent", StatsFunctions::GetSkillCurrent},\
{"GetSkillProgress", StatsFunctions::GetSkillProgress},\
{"GetSkillIncrease", StatsFunctions::GetSkillIncrease},\
\
{"GetBounty", StatsFunctions::GetBounty},\
\
{"SetName", StatsFunctions::SetName},\
{"SetRace", StatsFunctions::SetRace},\
{"SetHead", StatsFunctions::SetHead},\
{"SetHair", StatsFunctions::SetHairstyle},\
{"SetIsMale", StatsFunctions::SetIsMale},\
{"SetBirthsign", StatsFunctions::SetBirthsign},\
{"SetCreatureModel", StatsFunctions::SetCreatureModel},\
\
{"SetLevel", StatsFunctions::SetLevel},\
{"SetLevelProgress", StatsFunctions::SetLevelProgress},\
\
{"SetHealthBase", StatsFunctions::SetHealthBase},\
{"SetHealthCurrent", StatsFunctions::SetHealthCurrent},\
{"SetMagickaBase", StatsFunctions::SetMagickaBase},\
{"SetMagickaCurrent", StatsFunctions::SetMagickaCurrent},\
{"SetFatigueBase", StatsFunctions::SetFatigueBase},\
{"SetFatigueCurrent", StatsFunctions::SetFatigueCurrent},\
\
{"SetAttributeBase", StatsFunctions::SetAttributeBase},\
{"SetAttributeCurrent", StatsFunctions::SetAttributeCurrent},\
\
{"SetSkillBase", StatsFunctions::SetSkillBase},\
{"SetSkillCurrent", StatsFunctions::SetSkillCurrent},\
{"SetSkillProgress", StatsFunctions::SetSkillProgress},\
{"SetSkillIncrease", StatsFunctions::SetSkillIncrease},\
\
{"SetBounty", StatsFunctions::SetBounty},\
{"SetCharGenStage", StatsFunctions::SetCharGenStage},\
\
{"SendBaseInfo", StatsFunctions::SendBaseInfo},\
\
{"SendStatsDynamic", StatsFunctions::SendStatsDynamic},\
{"SendAttributes", StatsFunctions::SendAttributes},\
{"SendSkills", StatsFunctions::SendSkills},\
{"SendLevel", StatsFunctions::SendLevel},\
{"SendBounty", StatsFunctions::SendBounty}
class StatsFunctions
{
public:
static int GetAttributeCount() noexcept;
static int GetSkillCount() noexcept;
static int GetAttributeId(const char *name) noexcept;
static int GetSkillId(const char *name) noexcept;
static const char *GetAttributeName(unsigned short attribute) noexcept;
static const char *GetSkillName(unsigned short skill) noexcept;
static const char *GetName(unsigned short pid) noexcept;
static const char *GetRace(unsigned short pid) noexcept;
static const char *GetHead(unsigned short pid) noexcept;
static const char *GetHairstyle(unsigned short pid) noexcept;
static int GetIsMale(unsigned short pid) noexcept;
static const char *GetBirthsign(unsigned short pid) noexcept;
static const char *GetCreatureModel(unsigned short pid) noexcept;
static bool IsCreatureName(unsigned short pid) noexcept;
static const char *GetDeathReason(unsigned short pid) noexcept;
static int GetLevel(unsigned short pid) noexcept;
static int GetLevelProgress(unsigned short pid) noexcept;
static double GetHealthBase(unsigned short pid) noexcept;
static double GetHealthCurrent(unsigned short pid) noexcept;
static double GetMagickaBase(unsigned short pid) noexcept;
static double GetMagickaCurrent(unsigned short pid) noexcept;
static double GetFatigueBase(unsigned short pid) noexcept;
static double GetFatigueCurrent(unsigned short pid) noexcept;
static int GetAttributeBase(unsigned short pid, unsigned short attribute) noexcept;
static int GetAttributeCurrent(unsigned short pid, unsigned short attribute) noexcept;
static int GetSkillBase(unsigned short pid, unsigned short skill) noexcept;
static int GetSkillCurrent(unsigned short pid, unsigned short skill) noexcept;
static double GetSkillProgress(unsigned short pid, unsigned short skill) noexcept;
static int GetSkillIncrease(unsigned short pid, unsigned int pos) noexcept;
static int GetBounty(unsigned short pid) noexcept;
static void SetName(unsigned short pid, const char *name) noexcept;
static void SetRace(unsigned short pid, const char *race) noexcept;
static void SetHead(unsigned short pid, const char *head) noexcept;
static void SetHairstyle(unsigned short pid, const char *style) noexcept;
static void SetIsMale(unsigned short pid, int male) noexcept;
static void SetBirthsign(unsigned short pid, const char *name) noexcept;
static void SetCreatureModel(unsigned short pid, const char *name, bool useCreatureName) noexcept;
static void SetLevel(unsigned short pid, int value) noexcept;
static void SetLevelProgress(unsigned short pid, int value) noexcept;
static void SetHealthBase(unsigned short pid, double value) noexcept;
static void SetHealthCurrent(unsigned short pid, double value) noexcept;
static void SetMagickaBase(unsigned short pid, double value) noexcept;
static void SetMagickaCurrent(unsigned short pid, double value) noexcept;
static void SetFatigueBase(unsigned short pid, double value) noexcept;
static void SetFatigueCurrent(unsigned short pid, double value) noexcept;
static void SetAttributeBase(unsigned short pid, unsigned short attribute, int value) noexcept;
static void SetAttributeCurrent(unsigned short pid, unsigned short attribute, int value) noexcept;
static void SetSkillBase(unsigned short pid, unsigned short skill, int value) noexcept;
static void SetSkillCurrent(unsigned short pid, unsigned short skill, int value) noexcept;
static void SetSkillProgress(unsigned short pid, unsigned short skill, double value) noexcept;
static void SetSkillIncrease(unsigned short pid, unsigned int pos, int value) noexcept;
static void SetBounty(unsigned short pid, int value) noexcept;
static void SetCharGenStage(unsigned short pid, int start, int end) noexcept;
static void SendBaseInfo(unsigned short pid) noexcept;
static void SendStatsDynamic(unsigned short pid) noexcept;
static void SendAttributes(unsigned short pid) noexcept;
static void SendSkills(unsigned short pid) noexcept;
static void SendLevel(unsigned short pid) noexcept;
static void SendBounty(unsigned short pid) noexcept;
};
#endif //OPENMW_STATAPI_HPP

@ -1,58 +0,0 @@
//
// Created by koncord on 15.03.16.
//
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <Player.hpp>
#include <Networking.hpp>
#include <Script/API/TimerAPI.hpp>
using namespace std;
using namespace mwmp;
int ScriptFunctions::CreateTimer(ScriptFunc callback, int msec) noexcept
{
return mwmp::TimerAPI::CreateTimer(callback, msec, "", vector<boost::any>());
}
int ScriptFunctions::CreateTimerEx(ScriptFunc callback, int msec, const char *types, va_list args) noexcept
{
try
{
vector<boost::any> params;
GetArguments(params, args, types);
return mwmp::TimerAPI::CreateTimer(callback, msec, types, params);
}
catch (...)
{
return -1;
}
}
void ScriptFunctions::StartTimer(int timerId) noexcept
{
TimerAPI::StartTimer(timerId);
}
void ScriptFunctions::StopTimer(int timerId) noexcept
{
TimerAPI::StopTimer(timerId);
}
void ScriptFunctions::RestartTimer(int timerId, int msec) noexcept
{
TimerAPI::ResetTimer(timerId, msec);
}
void ScriptFunctions::FreeTimer(int timerId) noexcept
{
TimerAPI::FreeTimer(timerId);
}
bool ScriptFunctions::IsTimerElapsed(int timerId) noexcept
{
return TimerAPI::IsEndTimer(timerId);
}

@ -1,361 +0,0 @@
#include <components/openmw-mp/NetworkMessages.hpp>
#include <components/openmw-mp/Base/BaseEvent.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <apps/openmw-mp/Player.hpp>
#include <apps/openmw-mp/Utils.hpp>
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include "World.hpp"
using namespace mwmp;
BaseEvent *readEvent;
BaseEvent writeEvent;
WorldObject tempWorldObject;
const WorldObject emptyWorldObject = {};
ContainerItem tempContainerItem;
const ContainerItem emptyContainerItem = {};
void WorldFunctions::ReadLastEvent() noexcept
{
readEvent = mwmp::Networking::getPtr()->getLastEvent();
}
void WorldFunctions::InitializeEvent(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
writeEvent.cell.blank();
writeEvent.worldObjects.clear();
writeEvent.guid = player->guid;
}
unsigned int WorldFunctions::GetObjectChangesSize() noexcept
{
return readEvent->worldObjectCount;
}
unsigned char WorldFunctions::GetEventAction() noexcept
{
return readEvent->action;
}
const char *WorldFunctions::GetObjectRefId(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).refId.c_str();
}
int WorldFunctions::GetObjectRefNumIndex(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).refNumIndex;
}
int WorldFunctions::GetObjectMpNum(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).mpNum;
}
int WorldFunctions::GetObjectCount(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).count;
}
int WorldFunctions::GetObjectCharge(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).charge;
}
int WorldFunctions::GetObjectGoldValue(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).goldValue;
}
double WorldFunctions::GetObjectScale(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).scale;
}
bool WorldFunctions::GetObjectState(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).objectState;
}
int WorldFunctions::GetObjectDoorState(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).doorState;
}
int WorldFunctions::GetObjectLockLevel(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).lockLevel;
}
double WorldFunctions::GetObjectPosX(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).position.pos[0];
}
double WorldFunctions::GetObjectPosY(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).position.pos[1];
}
double WorldFunctions::GetObjectPosZ(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).position.pos[2];
}
double WorldFunctions::GetObjectRotX(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).position.rot[0];
}
double WorldFunctions::GetObjectRotY(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).position.rot[1];
}
double WorldFunctions::GetObjectRotZ(unsigned int i) noexcept
{
return readEvent->worldObjects.at(i).position.rot[2];
}
unsigned int WorldFunctions::GetContainerChangesSize(unsigned int objectIndex) noexcept
{
return readEvent->worldObjects.at(objectIndex).containerItemCount;
}
const char *WorldFunctions::GetContainerItemRefId(unsigned int objectIndex, unsigned int itemIndex) noexcept
{
return readEvent->worldObjects.at(objectIndex)
.containerItems.at(itemIndex).refId.c_str();
}
int WorldFunctions::GetContainerItemCount(unsigned int objectIndex, unsigned int itemIndex) noexcept
{
return readEvent->worldObjects.at(objectIndex)
.containerItems.at(itemIndex).count;
}
int WorldFunctions::GetContainerItemCharge(unsigned int objectIndex, unsigned int itemIndex) noexcept
{
return readEvent->worldObjects.at(objectIndex)
.containerItems.at(itemIndex).charge;
}
int WorldFunctions::GetContainerItemActionCount(unsigned int objectIndex, unsigned int itemIndex) noexcept
{
return readEvent->worldObjects.at(objectIndex)
.containerItems.at(itemIndex).actionCount;
}
void WorldFunctions::SetEventCell(const char* cellDescription) noexcept
{
writeEvent.cell = Utils::getCellFromDescription(cellDescription);
}
void WorldFunctions::SetEventAction(unsigned char action) noexcept
{
writeEvent.action = action;
}
void WorldFunctions::SetObjectRefId(const char* refId) noexcept
{
tempWorldObject.refId = refId;
}
void WorldFunctions::SetObjectRefNumIndex(int refNumIndex) noexcept
{
tempWorldObject.refNumIndex = refNumIndex;
}
void WorldFunctions::SetObjectMpNum(int mpNum) noexcept
{
tempWorldObject.mpNum = mpNum;
}
void WorldFunctions::SetObjectCount(int count) noexcept
{
tempWorldObject.count = count;
}
void WorldFunctions::SetObjectCharge(int charge) noexcept
{
tempWorldObject.charge = charge;
}
void WorldFunctions::SetObjectGoldValue(int goldValue) noexcept
{
tempWorldObject.goldValue = goldValue;
}
void WorldFunctions::SetObjectScale(double scale) noexcept
{
tempWorldObject.scale = scale;
}
void WorldFunctions::SetObjectState(bool objectState) noexcept
{
tempWorldObject.objectState = objectState;
}
void WorldFunctions::SetObjectDoorState(int doorState) noexcept
{
tempWorldObject.doorState = doorState;
}
void WorldFunctions::SetObjectLockLevel(int lockLevel) noexcept
{
tempWorldObject.lockLevel = lockLevel;
}
void WorldFunctions::SetObjectDisarmState(bool disarmState) noexcept
{
tempWorldObject.isDisarmed = disarmState;
}
void WorldFunctions::SetObjectMasterState(bool masterState) noexcept
{
tempWorldObject.hasMaster = masterState;
}
void WorldFunctions::SetObjectPosition(double x, double y, double z) noexcept
{
tempWorldObject.position.pos[0] = x;
tempWorldObject.position.pos[1] = y;
tempWorldObject.position.pos[2] = z;
}
void WorldFunctions::SetObjectRotation(double x, double y, double z) noexcept
{
tempWorldObject.position.rot[0] = x;
tempWorldObject.position.rot[1] = y;
tempWorldObject.position.rot[2] = z;
}
void WorldFunctions::SetContainerItemRefId(const char* refId) noexcept
{
tempContainerItem.refId = refId;
}
void WorldFunctions::SetContainerItemCount(int count) noexcept
{
tempContainerItem.count = count;
}
void WorldFunctions::SetContainerItemCharge(int charge) noexcept
{
tempContainerItem.charge = charge;
}
void WorldFunctions::AddWorldObject() noexcept
{
writeEvent.worldObjects.push_back(tempWorldObject);
tempWorldObject = emptyWorldObject;
}
void WorldFunctions::AddContainerItem() noexcept
{
tempWorldObject.containerItems.push_back(tempContainerItem);
tempContainerItem = emptyContainerItem;
}
void WorldFunctions::SendObjectPlace() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_PLACE)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_PLACE)->Send(writeEvent.guid);
}
void WorldFunctions::SendObjectSpawn() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_SPAWN)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_SPAWN)->Send(writeEvent.guid);
}
void WorldFunctions::SendObjectDelete() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_DELETE)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_DELETE)->Send(writeEvent.guid);
}
void WorldFunctions::SendObjectLock() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_LOCK)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_LOCK)->Send(writeEvent.guid);
}
void WorldFunctions::SendObjectTrap() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_TRAP)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_TRAP)->Send(writeEvent.guid);
}
void WorldFunctions::SendObjectScale() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_SCALE)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_SCALE)->Send(writeEvent.guid);
}
void WorldFunctions::SendObjectState() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_STATE)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_OBJECT_STATE)->Send(writeEvent.guid);
}
void WorldFunctions::SendDoorState() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_DOOR_STATE)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_DOOR_STATE)->Send(writeEvent.guid);
}
void WorldFunctions::SendContainer() noexcept
{
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER)->setEvent(&writeEvent);
mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER)->Send(writeEvent.guid);
}
void WorldFunctions::SetHour(unsigned short pid, double hour) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->hour = hour;
player->month = -1;
player->day = -1;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME)->Send(false);
}
void WorldFunctions::SetMonth(unsigned short pid, int month) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->hour = -1;
player->month = month;
player->day = -1;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME)->Send(false);
}
void WorldFunctions::SetDay(unsigned short pid, int day) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
player->hour = -1;
player->month = -1;
player->day = day;
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME)->setPlayer(player);
mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME)->Send(false);
}

@ -1,615 +0,0 @@
#ifndef OPENMW_WORLDAPI_HPP
#define OPENMW_WORLDAPI_HPP
#define WORLDAPI \
{"ReadLastEvent", WorldFunctions::ReadLastEvent},\
{"InitializeEvent", WorldFunctions::InitializeEvent},\
\
{"GetObjectChangesSize", WorldFunctions::GetObjectChangesSize},\
{"GetEventAction", WorldFunctions::GetEventAction},\
\
{"GetObjectRefId", WorldFunctions::GetObjectRefId},\
{"GetObjectRefNumIndex", WorldFunctions::GetObjectRefNumIndex},\
{"GetObjectMpNum", WorldFunctions::GetObjectMpNum},\
{"GetObjectCount", WorldFunctions::GetObjectCount},\
{"GetObjectCharge", WorldFunctions::GetObjectCharge},\
{"GetObjectGoldValue", WorldFunctions::GetObjectGoldValue},\
{"GetObjectScale", WorldFunctions::GetObjectScale},\
{"GetObjectState", WorldFunctions::GetObjectState},\
{"GetObjectDoorState", WorldFunctions::GetObjectDoorState},\
{"GetObjectLockLevel", WorldFunctions::GetObjectLockLevel},\
{"GetObjectPosX", WorldFunctions::GetObjectPosX},\
{"GetObjectPosY", WorldFunctions::GetObjectPosY},\
{"GetObjectPosZ", WorldFunctions::GetObjectPosZ},\
{"GetObjectRotX", WorldFunctions::GetObjectRotX},\
{"GetObjectRotY", WorldFunctions::GetObjectRotY},\
{"GetObjectRotZ", WorldFunctions::GetObjectRotZ},\
\
{"GetContainerChangesSize", WorldFunctions::GetContainerChangesSize},\
{"GetContainerItemRefId", WorldFunctions::GetContainerItemRefId},\
{"GetContainerItemCount", WorldFunctions::GetContainerItemCount},\
{"GetContainerItemCharge", WorldFunctions::GetContainerItemCharge},\
{"GetContainerItemActionCount", WorldFunctions::GetContainerItemActionCount},\
\
{"SetEventCell", WorldFunctions::SetEventCell},\
{"SetEventAction", WorldFunctions::SetEventAction},\
\
{"SetObjectRefId", WorldFunctions::SetObjectRefId},\
{"SetObjectRefNumIndex", WorldFunctions::SetObjectRefNumIndex},\
{"SetObjectMpNum", WorldFunctions::SetObjectMpNum},\
{"SetObjectCount", WorldFunctions::SetObjectCount},\
{"SetObjectCharge", WorldFunctions::SetObjectCharge},\
{"SetObjectGoldValue", WorldFunctions::SetObjectGoldValue},\
{"SetObjectScale", WorldFunctions::SetObjectScale},\
{"SetObjectState", WorldFunctions::SetObjectState},\
{"SetObjectDoorState", WorldFunctions::SetObjectDoorState},\
{"SetObjectLockLevel", WorldFunctions::SetObjectLockLevel},\
{"SetObjectDisarmState", WorldFunctions::SetObjectDisarmState},\
{"SetObjectMasterState", WorldFunctions::SetObjectMasterState},\
{"SetObjectPosition", WorldFunctions::SetObjectPosition},\
{"SetObjectRotation", WorldFunctions::SetObjectRotation},\
\
{"SetContainerItemRefId", WorldFunctions::SetContainerItemRefId},\
{"SetContainerItemCount", WorldFunctions::SetContainerItemCount},\
{"SetContainerItemCharge", WorldFunctions::SetContainerItemCharge},\
\
{"AddWorldObject", WorldFunctions::AddWorldObject},\
{"AddContainerItem", WorldFunctions::AddContainerItem},\
\
{"SendObjectPlace", WorldFunctions::SendObjectPlace},\
{"SendObjectSpawn", WorldFunctions::SendObjectSpawn},\
{"SendObjectDelete", WorldFunctions::SendObjectDelete},\
{"SendObjectLock", WorldFunctions::SendObjectLock},\
{"SendObjectTrap", WorldFunctions::SendObjectTrap},\
{"SendObjectScale", WorldFunctions::SendObjectScale},\
{"SendObjectState", WorldFunctions::SendObjectState},\
{"SendDoorState", WorldFunctions::SendDoorState},\
{"SendContainer", WorldFunctions::SendContainer},\
\
{"SetHour", WorldFunctions::SetHour},\
{"SetMonth", WorldFunctions::SetMonth},\
{"SetDay", WorldFunctions::SetDay}
class WorldFunctions
{
public:
/**
* \brief Use the last event received by the server as the one being read.
*
* \return void
*/
static void ReadLastEvent() noexcept;
/**
* \brief Clear the data from the last event sent by the server.
*
* This is used to initialize the sending of new Object packets.
*
* \param pid The player ID to whom the event should be attached.
* \return void
*/
static void InitializeEvent(unsigned short pid) noexcept;
/**
* \brief Get the number of indexes in the read event's object changes.
*
* \return The number of indexes.
*/
static unsigned int GetObjectChangesSize() noexcept;
/**
* \brief Get the action type used in the read event.
*
* \return The action type (0 for SET, 1 for ADD, 2 for REMOVE, 3 for REQUEST).
*/
static unsigned char GetEventAction() noexcept;
/**
* \brief Get the refId of the object at a certain index in the read event's object changes.
*
* \return The refId.
*/
static const char *GetObjectRefId(unsigned int i) noexcept;
/**
* \brief Get the refNumIndex of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The refNumIndex.
*/
static int GetObjectRefNumIndex(unsigned int i) noexcept;
/**
* \brief Get the mpNum of the object at a certain index in the read event's object changes.
*
* \param i The index of the object.
* \return The mpNum.
*/
static int GetObjectMpNum(unsigned int i) noexcept;
/**
* \brief Get the count of the object at a certain index in the read event's object changes.
*
* \param i The index of the object.
* \return The object count.
*/
static int GetObjectCount(unsigned int i) noexcept;
/**
* \brief Get the charge of the object at a certain index in the read event's object changes.
*
* \param i The index of the object.
* \return The charge.
*/
static int GetObjectCharge(unsigned int i) noexcept;
/**
* \brief Get the gold value of the object at a certain index in the read event's object
* changes.
*
* This is used solely to get the gold value of gold. It is not used for other objects.
*
* \param i The index of the object.
* \return The gold value.
*/
static int GetObjectGoldValue(unsigned int i) noexcept;
/**
* \brief Get the object scale of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The object scale.
*/
static double GetObjectScale(unsigned int i) noexcept;
/**
* \brief Get the object state of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The object state.
*/
static bool GetObjectState(unsigned int i) noexcept;
/**
* \brief Get the door state of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The door state.
*/
static int GetObjectDoorState(unsigned int i) noexcept;
/**
* \brief Get the lock level of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The lock level.
*/
static int GetObjectLockLevel(unsigned int i) noexcept;
/**
* \brief Get the X position of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The X position.
*/
static double GetObjectPosX(unsigned int i) noexcept;
/**
* \brief Get the Y position of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The Y position.
*/
static double GetObjectPosY(unsigned int i) noexcept;
/**
* \brief Get the Z position at a certain index in the read event's object changes.
*
* \param i The index of the object.
* \return The Z position.
*/
static double GetObjectPosZ(unsigned int i) noexcept;
/**
* \brief Get the X rotation of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The X rotation.
*/
static double GetObjectRotX(unsigned int i) noexcept;
/**
* \brief Get the Y rotation of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The Y rotation.
*/
static double GetObjectRotY(unsigned int i) noexcept;
/**
* \brief Get the Z rotation of the object at a certain index in the read event's object
* changes.
*
* \param i The index of the object.
* \return The Z rotation.
*/
static double GetObjectRotZ(unsigned int i) noexcept;
/**
* \brief Get the number of container item indexes of the object at a certain index in the
* read event's object changes.
*
* \param i The index of the object.
* \return The number of container item indexes.
*/
static unsigned int GetContainerChangesSize(unsigned int objectIndex) noexcept;
/**
* \brief Get the refId of the container item at a certain itemIndex in the container changes
* of the object at a certain objectIndex in the read event's object changes.
*
* \param objectIndex The index of the object.
* \param itemIndex The index of the container item.
* \return The refId.
*/
static const char *GetContainerItemRefId(unsigned int objectIndex, unsigned int itemIndex) noexcept;
/**
* \brief Get the item count of the container item at a certain itemIndex in the container
* changes of the object at a certain objectIndex in the read event's object changes.
*
* \param objectIndex The index of the object.
* \param itemIndex The index of the container item.
* \return The item count.
*/
static int GetContainerItemCount(unsigned int objectIndex, unsigned int itemIndex) noexcept;
/**
* \brief Get the charge of the container item at a certain itemIndex in the container changes
* of the object at a certain objectIndex in the read event's object changes.
*
* \param objectIndex The index of the object.
* \param itemIndex The index of the container item.
* \return The charge.
*/
static int GetContainerItemCharge(unsigned int objectIndex, unsigned int itemIndex) noexcept;
/**
* \brief Get the action count of the container item at a certain itemIndex in the container
* changes of the object at a certain objectIndex in the read event's object changes.
*
* \param objectIndex The index of the object.
* \param itemIndex The index of the container item.
* \return The action count.
*/
static int GetContainerItemActionCount(unsigned int objectIndex, unsigned int itemIndex) noexcept;
/**
* \brief Set the cell of the temporary event stored on the server.
*
* The cell is determined to be an exterior cell if it fits the pattern of a number followed
* by a comma followed by another number.
*
* \param cellDescription The description of the cell.
* \return void
*/
static void SetEventCell(const char* cellDescription) noexcept;
/**
* \brief Set the action type of the temporary event stored on the server.
*
* \param action The action type (0 for SET, 1 for ADD, 2 for REMOVE, 3 for REQUEST).
* \return void
*/
static void SetEventAction(unsigned char action) noexcept;
/**
* \brief Set the refId of the temporary world object stored on the server.
*
* \param refId The refId.
* \return void
*/
static void SetObjectRefId(const char* refId) noexcept;
/**
* \brief Set the refNumIndex of the temporary world object stored on the server.
*
* Every object loaded from .ESM and .ESP data files has a unique refNumIndex which needs to be
* retained to refer to it in packets.
*
* On the other hand, objects placed or spawned via the server should always have a refNumIndex
* of 0.
*
* \param refNumIndex The refNumIndex.
* \return void
*/
static void SetObjectRefNumIndex(int refNumIndex) noexcept;
/**
* \brief Set the mpNum of the temporary world object stored on the server.
*
* Every object placed or spawned via the server is assigned an mpNum by incrementing the last
* mpNum stored on the server. Scripts should take care to ensure that mpNums are kept unique
* for these objects.
*
* Objects loaded from .ESM and .ESP data files should always have an mpNum of 0, because they
* have unique refNumIndexes instead.
*
* \param mpNum The mpNum.
* \return void
*/
static void SetObjectMpNum(int mpNum) noexcept;
/**
* \brief Set the object count of the temporary world object stored on the server.
*
* This determines the quantity of an object, with the exception of gold.
*
* \param count The object count.
* \return void
*/
static void SetObjectCount(int count) noexcept;
/**
* \brief Set the charge of the temporary world object stored on the server.
*
* Object durabilities are set through this value.
*
* \param charge The charge.
* \return void
*/
static void SetObjectCharge(int charge) noexcept;
/**
* \brief Set the gold value of the temporary world object stored on the server.
*
* This is used solely to set the gold value for gold. It has no effect on other objects.
*
* \param goldValue The gold value.
* \return void
*/
static void SetObjectGoldValue(int goldValue) noexcept;
/**
* \brief Set the scale of the temporary world object stored on the server.
*
* Objects are smaller or larger than their default size based on their scale.
*
* \param scale The scale.
* \return void
*/
static void SetObjectScale(double scale) noexcept;
/**
* \brief Set the object state of the temporary world object stored on the server.
*
* Objects are enabled or disabled based on their object state.
*
* \param objectState The object state.
* \return void
*/
static void SetObjectState(bool objectState) noexcept;
/**
* \brief Set the door state of the temporary world object stored on the server.
*
* Doors are open or closed based on their door state.
*
* \param doorState The door state.
* \return void
*/
static void SetObjectDoorState(int doorState) noexcept;
/**
* \brief Set the lock level of the temporary world object stored on the server.
*
* \param lockLevel The lock level.
* \return void
*/
static void SetObjectLockLevel(int lockLevel) noexcept;
/**
* \brief Set the disarm state of the temporary world object stored on the server.
*
* \param disarmState The disarmState.
* \return void
*/
static void SetObjectDisarmState(bool disarmState) noexcept;
/**
* \brief Set the master state of the temporary world object stored on the server.
*
* This only affects living actors and determines whether they are followers of another
* living actor.
*
* \param masterState The master state.
* \return void
*/
static void SetObjectMasterState(bool masterState) noexcept;
/**
* \brief Set the position of the temporary world object stored on the server.
*
* \param x The X position.
* \param y The Y position.
* \param z The Z position.
* \return void
*/
static void SetObjectPosition(double x, double y, double z) noexcept;
/**
* \brief Set the rotation of the temporary world object stored on the server.
*
* \param x The X rotation.
* \param y The Y rotation.
* \param z The Z rotation.
* \return void
*/
static void SetObjectRotation(double x, double y, double z) noexcept;
/**
* \brief Set the refId of the temporary container item stored on the server.
*
* \param refId The refId.
* \return void
*/
static void SetContainerItemRefId(const char* refId) noexcept;
/**
* \brief Set the item count of the temporary container item stored on the server.
*
* \param count The item count.
* \return void
*/
static void SetContainerItemCount(int count) noexcept;
/**
* \brief Set the charge of the temporary container item stored on the server.
*
* \param charge The charge.
* \return void
*/
static void SetContainerItemCharge(int charge) noexcept;
/**
* \brief Add a copy of the server's temporary world object to the server's temporary event.
*
* In the process, the server's temporary world object will automatically be cleared so a new
* one can be set up.
*
* \return void
*/
static void AddWorldObject() noexcept;
/**
* \brief Add a copy of the server's temporary container item to the container changes of the
* server's temporary world object.
*
* In the process, the server's temporary container item will automatically be cleared so a new
* one can be set up.
*
* \return void
*/
static void AddContainerItem() noexcept;
/**
* \brief Send an ObjectPlace packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectPlace() noexcept;
/**
* \brief Send an ObjectSpawn packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectSpawn() noexcept;
/**
* \brief Send an ObjectDelete packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectDelete() noexcept;
/**
* \brief Send an ObjectLock packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectLock() noexcept;
/**
* \brief Send an ObjectTrap packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectTrap() noexcept;
/**
* \brief Send an ObjectScale packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectScale() noexcept;
/**
* \brief Send an ObjectState packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendObjectState() noexcept;
/**
* \brief Send a DoorState packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendDoorState() noexcept;
/**
* \brief Send a Container packet.
*
* It is sent only to the player for whom the current event was initialized.
*
* \return void
*/
static void SendContainer() noexcept;
/**
* \brief Set the game hour for a player and send a GameTime packet to that player.
*
* \param pid The player ID.
* \param hour The hour.
* \return void
*/
static void SetHour(unsigned short pid, double hour) noexcept;
/**
* \brief Set the game month for a player and send a GameTime packet to that player.
*
* \param pid The player ID.
* \param month The month.
* \return void
*/
static void SetMonth(unsigned short pid, int month) noexcept;
/**
* \brief Set the game day for a player and send a GameTime packet to that player.
*
* \param pid The player ID.
* \param day The day.
* \return void
*/
static void SetDay(unsigned short pid, int day) noexcept;
};
#endif //OPENMW_WORLDAPI_HPP

@ -1,198 +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;
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
#if defined(ENABLE_TERRA)
terra_init(lua);
#endif
}
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}; };
template<size_t... Indices>
inline LuaFuctionData *LangLua::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_;
}
void LangLua::LoadProgram(const char *filename)
{
int err = 0;
#if defined(ENABLE_TERRA)
if ((err = terra_loadfile(lua, filename)) != 0)
#else
if ((err =luaL_loadfile(lua, filename)) != 0)
#endif
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]);
LuaFuctionData *functions_ = functions(IndicesFor<functions_n>{});
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);
std::vector<boost::any> args;
ScriptFunctions::GetArguments(args, vargs, argl);
return Call(name, argl, args);
}
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 (intptr_t i = 0; i < n_args; i++)
{
switch (argl[i])
{
case 'i':
luabridge::Stack<unsigned int>::push(lua, boost::any_cast<unsigned int>(args.at(i)));
break;
case 'q':
luabridge::Stack<signed int>::push(lua, boost::any_cast<signed int>(args.at(i)));
break;
case 'l':
luabridge::Stack<unsigned long long>::push(lua, boost::any_cast<unsigned long long>(args.at(i)));
break;
case 'w':
luabridge::Stack<signed long long>::push(lua, boost::any_cast<signed long long>(args.at(i)));
break;
case 'f':
luabridge::Stack<double>::push(lua, boost::any_cast<double>(args.at(i)));
break;
case 'p':
luabridge::Stack<void *>::push(lua, boost::any_cast<void *>(args.at(i)));
break;
case 's':
luabridge::Stack<const char *>::push(lua, boost::any_cast<const char *>(args.at(i)));
break;
case 'b':
luabridge::Stack<bool>::push(lua, boost::any_cast<int>(args.at(i)));
break;
default:
throw runtime_error("Lua call: Unknown argument identifier " + argl[i]);
}
}
luabridge::LuaException::pcall (lua, n_args, 1);
return boost::any(luabridge::LuaRef::fromStack(lua, -1));
}

@ -1,62 +0,0 @@
//
// Created by koncord on 08.05.16.
//
#ifndef PLUGINSYSTEM3_LANGLUA_HPP
#define PLUGINSYSTEM3_LANGLUA_HPP
#ifdef ENABLE_TERRA
#include <terra/terra.h>
#else
#include "lua.hpp"
#endif
#include <extern/LuaBridge/LuaBridge.h>
#include <LuaBridge.h>
#include <boost/any.hpp>
#include "../ScriptFunction.hpp"
#include "../Language.hpp"
struct LuaFuctionData
{
const char* name;
lua_CFunction func;
};
class LangLua: public Language
{
private:
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>;
public:
virtual lib_t GetInterface() override;
template<std::size_t... Indices>
static LuaFuctionData* functions(indices<Indices...>);
lua_State *lua;
public:
LangLua();
LangLua(lua_State *lua);
~LangLua();
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;
};
#endif //PLUGINSYSTEM3_LANGLUA_HPP

@ -1,182 +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, 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;
if (result.type().hash_code() == typeid(signed int).hash_code())
luabridge::Stack<signed int>::push(lua, boost::any_cast<signed int>(result));
else if (result.type().hash_code() == typeid(unsigned int).hash_code())
luabridge::Stack<unsigned int>::push(lua, boost::any_cast<unsigned int>(result));
else if (result.type().hash_code() == typeid(double).hash_code())
luabridge::Stack<double>::push(lua, boost::any_cast<double>(result));
else if (result.type().hash_code() == 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()
{
}
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,458 +0,0 @@
//
// Created by koncord on 08.05.16.
//
#include "LangPAWN.hpp"
#include <amxmodules.h>
#include <amxaux.h>
#include "Script.hpp"
using namespace std;
typedef long NetworkID;
static vector<vector<char>> strings;
static vector<pair<cell*, double>> floats;
static pair<cell*, NetworkID*> data = {nullptr, nullptr};
void free_strings() noexcept {
strings.clear();
}
void free_floats() noexcept {
for (const auto& value : floats)
*value.first = amx_ftoc(value.second);
floats.clear();
}
void free_data(unsigned int size) noexcept {
if (data.first && data.second)
for (unsigned int i = 0; i < size; ++i)
data.first[i] = data.second[i];
data.first = nullptr;
data.second = nullptr;
}
void after_call() noexcept {
free_strings();
free_floats();
}
template<typename R>
void after_call(const R&) noexcept {
free_strings();
free_floats();
}
template<>
void after_call(const unsigned int& result) noexcept {
free_strings();
free_floats();
free_data(result);
}
template<typename R, unsigned int I, unsigned int F>
struct PAWN_extract_ {
inline static R PAWN_extract(AMX*&&, const cell*&& params) noexcept {
return static_cast<R>(forward<const cell*>(params)[I]);
}
};
template<unsigned int I, unsigned int F>
struct PAWN_extract_<void*, I, F>
{
inline static void* PAWN_extract(AMX *&&amx, const cell *&&params) noexcept
{
return amx_Address(amx, forward<const cell *>(params)[I]); // fixme: I'm not sure in this fix
}
};
template<unsigned int I, unsigned int F>
struct PAWN_extract_<double, I, F> {
inline static double PAWN_extract(AMX*&&, const cell*&& params) noexcept {
return amx_ctof(forward<const cell*>(params)[I]);
}
};
template<unsigned int I, unsigned int F>
struct PAWN_extract_<const char*, I, F> {
inline static const char* PAWN_extract(AMX*&& amx, const cell*&& params) noexcept {
int len;
cell* source;
source = amx_Address(amx, params[I]);
amx_StrLen(source, &len);
strings.emplace_back(len + 1);
char* value = &strings.back()[0];
amx_GetString(value, source, 0, UNLIMITED);
return value;
}
};
template<unsigned int I, unsigned int F>
struct PAWN_extract_<double*, I, F> {
inline static double* PAWN_extract(AMX*&& amx, const cell*&& params) noexcept {
floats.emplace_back(amx_Address(amx, params[I]), 0.00);
return &floats.back().second;
}
};
template<unsigned int I, unsigned int F>
struct PAWN_extract_<NetworkID**, I, F> {
inline static NetworkID** PAWN_extract(AMX*&& amx, const cell*&& params) noexcept {
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
static_assert(F_.func.numargs == I, "NetworkID** must be the last parameter");
data.first = amx_Address(amx, params[I]);
return &data.second;
}
};
template<unsigned int I, unsigned int F>
struct PAWN_dispatch_ {
template<typename R, typename... Args>
inline static R PAWN_dispatch(AMX*&& amx, const cell*&& params, Args&&... args) noexcept {
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F];
auto arg = PAWN_extract_<typename CharType<F_.func.types[I - 1]>::type, I, F>::PAWN_extract(forward<AMX*>(amx), forward<const cell*>(params));
return PAWN_dispatch_<I - 1, F>::template PAWN_dispatch<R>(
forward<AMX*>(amx),
forward<const cell*>(params),
arg,
forward<Args>(args)...);
}
};
template<unsigned int F>
struct PAWN_dispatch_<0, F> {
template<typename R, typename... Args>
inline static R PAWN_dispatch(AMX*&&, const cell*&&, 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', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<void>(forward<AMX*>(amx), forward<const cell*>(params));
after_call();
return 1;
}
template<unsigned int I>
static typename enable_if<ScriptFunctions::functions[I].func.ret == 'f', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
double value = PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<double>(forward<AMX*>(amx), forward<const cell*>(params));
after_call();
return amx_ftoc(value);
}
template<unsigned int I>
static typename enable_if<ScriptFunctions::functions[I].func.ret == 's', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
const char* value = PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<const char*>(forward<AMX*>(amx), forward<const cell*>(params));
after_call();
if (value) {
cell* dest = amx_Address(amx, params[ScriptFunctions::functions[I].func.numargs + 1]);
amx_SetString(dest, value, 1, 0, strlen(value) + 1);
return 1;
}
return 0;
}
template<unsigned int I>
static typename enable_if<ScriptFunctions::functions[I].func.ret != 'v' && ScriptFunctions::functions[I].func.ret != 'f' && ScriptFunctions::functions[I].func.ret != 's', cell>::type wrapper(AMX* amx, const cell* params) noexcept {
auto result = PAWN_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template PAWN_dispatch<typename CharType<ScriptFunctions::functions[I].func.ret>::type>(forward<AMX*>(amx), forward<const cell*>(params));
after_call(result);
return result;
}
template<unsigned int I> struct F_ { static constexpr AMX_NATIVE_INFO F{ScriptFunctions::functions[I].name, wrapper<I>}; };
template<> struct F_<0> { static constexpr AMX_NATIVE_INFO F{"CreateTimer", LangPAWN::CreateTimer}; };
template<> struct F_<1> { static constexpr AMX_NATIVE_INFO F{"CreateTimerEx", LangPAWN::CreateTimerEx}; };
template<> struct F_<2> { static constexpr AMX_NATIVE_INFO F{"MakePublic", LangPAWN::MakePublic}; };
template<> struct F_<3> { static constexpr AMX_NATIVE_INFO F{"CallPublic", LangPAWN::CallPublic}; };
void LangPAWN::LoadProgram(const char *filename)
{
int err = aux_LoadProgram(amx, filename, 0);
if (err != AMX_ERR_NONE)
throw runtime_error("PAWN script " + string(filename) + " error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\"");
amx_CoreInit(amx);
amx_ConsoleInit(amx);
amx_FloatInit(amx);
amx_TimeInit(amx);
amx_StringInit(amx);
amx_FileInit(amx);
constexpr auto functions_n = sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]);
amx_Register(amx, functions(IndicesFor<functions_n>{}), functions_n); // TODO: throw if error
}
int LangPAWN::FreeProgram()
{
int err = aux_FreeProgram(amx);
delete amx;
return err;
}
bool LangPAWN::IsCallbackPresent(const char *name)
{
int idx;
return (amx_FindPublic(amx, name, &idx) == AMX_ERR_NONE);
}
boost::any LangPAWN::Call(const char *name, const char *argl, int buf, ...)
{
va_list args;
va_start(args, buf);
cell ret = 0;
vector<pair<cell *, char *>> strings;
try
{
int idx = 0;
int err = 0;
err = amx_FindPublic(amx, name, &idx);
if (err != AMX_ERR_NONE)
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
unsigned int len = strlen(argl);
vector<cell> args_amx;
for (unsigned int i = 0; i < len; ++i)
{
switch (argl[i])
{
case 'i':
args_amx.emplace_back(va_arg(args, unsigned
int));
break;
case 'q':
args_amx.emplace_back(va_arg(args, signed
int));
break;
case 'l':
args_amx.emplace_back(va_arg(args, unsigned
long
long));
break;
case 'w':
args_amx.emplace_back(va_arg(args, signed
long
long));
break;
case 'f':
{
double value = va_arg(args, double);
args_amx.emplace_back(amx_ftoc(value));
break;
}
case 'p':
args_amx.emplace_back(reinterpret_cast<uintptr_t>(va_arg(args, void*)));
break;
case 's':
args_amx.emplace_back(reinterpret_cast<uintptr_t>(va_arg(args, char*)));
break;
default:
throw runtime_error("PAWN call: Unknown argument identifier " + argl[i]);
}
}
for (unsigned int i = len; i; --i)
{
switch (argl[i - 1])
{
case 's':
{
char *string = reinterpret_cast<char *>(static_cast<unsigned int>(args_amx[i - 1]));
cell *store;
amx_PushString(amx, &store, string, 1, 0);
strings.emplace_back(store, string);
break;
}
default:
amx_Push(amx, args_amx[i - 1]);
break;
}
}
err = amx_Exec(amx, &ret, idx);
if (err != AMX_ERR_NONE)
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
if (buf != 0)
for (const auto &str : strings)
amx_GetString(str.second, str.first, 0, strlen(str.second) + 1);
if (!strings.empty())
amx_Release(amx, strings[0].first);
}
catch (...)
{
va_end(args);
if (!strings.empty())
amx_Release(amx, strings[0].first);
throw;
}
return boost::any(ret);
}
boost::any LangPAWN::Call(const char *name, const char *argl, const std::vector<boost::any> &args)
{
cell ret = 0;
cell *str = nullptr;
try
{
int idx = 0;
int err = 0;
err = amx_FindPublic(amx, name, &idx);
if (err != AMX_ERR_NONE)
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
for (intptr_t i = strlen(argl) - 1; i >= 0; i--)
{
switch (argl[i])
{
case 'i':
{
cell value = (cell) boost::any_cast<unsigned int>(args.at(i));
amx_Push(amx, value);
break;
}
case 'q':
{
cell value = (cell) boost::any_cast<signed int>(args.at(i));
amx_Push(amx, value);
break;
}
case 'l':
{
cell value = (cell) boost::any_cast<unsigned long long>(args.at(i));
amx_Push(amx, value);
break;
}
case 'w':
{
cell value = (cell) boost::any_cast<signed long long>(args.at(i));
amx_Push(amx, value);
break;
}
case 'f':
{
double value = boost::any_cast<double>(args.at(i));
amx_Push(amx, amx_ftoc(value));
break;
}
case 'p':
{
cell value = (cell) boost::any_cast<void *>(args.at(i));
amx_Push(amx, value);
break;
}
case 's':
{
string string_ = boost::any_cast<string>(args.at(i));
cell *store;
amx_PushString(amx, &store, string_.c_str(), 1, 0);
if (!str)
str = store;
break;
}
default:
throw runtime_error("PAWN call: Unknown argument identifier " + argl[i]);
}
}
err = amx_Exec(amx, &ret, idx);
if (err != AMX_ERR_NONE)
throw runtime_error("PAWN runtime error (" + to_string(err) + "): \"" + string(aux_StrError(err)) + "\".");
if (str)
amx_Release(amx, str);
}
catch (...)
{
if (str)
amx_Release(amx, str);
throw;
}
return ret;
}
template<size_t... Indices>
inline AMX_NATIVE_INFO *LangPAWN::functions(indices<Indices...>)
{
static AMX_NATIVE_INFO 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 PAWN");
return functions_;
}
lib_t LangPAWN::GetInterface()
{
return reinterpret_cast<lib_t>(amx);
}
LangPAWN::LangPAWN()
{
//throw std::runtime_error("Pawn is no longer supported, use Terra/Lua!");
amx = new AMX();
}
LangPAWN::LangPAWN(AMX *amx)
{
this->amx = amx;
}
LangPAWN::~LangPAWN()
{
}

@ -1,46 +0,0 @@
//
// Created by koncord on 08.05.16.
//
#ifndef PLUGINSYSTEM3_LANGPAWN_HPP
#define PLUGINSYSTEM3_LANGPAWN_HPP
#include "Language.hpp"
#include <amx.h>
class LangPAWN: public Language
{
private:
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>;
public:
virtual lib_t GetInterface() override;
template<std::size_t... Indices>
static AMX_NATIVE_INFO* functions(indices<Indices...>);
AMX *amx;
public:
LangPAWN();
LangPAWN(AMX *amx);
~LangPAWN();
static cell MakePublic(AMX *amx, const cell *params) noexcept;
static cell CallPublic(AMX *amx, const cell *params) noexcept;
static cell CreateTimer(AMX *amx, const cell *params) noexcept;
static cell CreateTimerEx(AMX *amx, const cell *params) noexcept;
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_LANGPAWN_HPP

@ -1,154 +0,0 @@
//
// Created by koncord on 09.05.16.
//
#include <API/PublicFnAPI.hpp>
#include "LangPAWN.hpp"
#include "API/TimerAPI.hpp"
using namespace std;
cell LangPAWN::MakePublic(AMX *amx, const cell *params) noexcept
{
int len;
cell* source;
source = amx_Address(amx, params[1]);
amx_StrLen(source, &len);
vector<char> real;
real.reserve(len + 1);
amx_GetString(&real[0], source, 0, UNLIMITED);
source = amx_Address(amx, params[2]);
amx_StrLen(source, &len);
vector<char> name;
name.reserve(len + 1);
amx_GetString(&name[0], source, 0, UNLIMITED);
cell *ret_addr = amx_Address(amx, params[3]);
char ret_type = static_cast<char>(*reinterpret_cast<cell*>(&ret_addr));
source = amx_Address(amx, params[4]);
amx_StrLen(source, &len);
vector<char> def;
def.reserve(len + 1);
amx_GetString(&def[0], source, 0, UNLIMITED);
Public::MakePublic(&real[0], amx, &name[0], ret_type, &def[0]);
return 1;
}
cell LangPAWN::CallPublic(AMX *amx, const cell *params) noexcept
{
int len;
cell* source;
source = amx_Address(amx, params[1]);
amx_StrLen(source, &len);
vector<char> name;
name.reserve(len + 1);
amx_GetString(&name[0], source, 0, UNLIMITED);
string def;
try
{
def = Public::GetDefinition(&name[0]);
}
catch (...) { return 0; }
vector<boost::any> args;
unsigned int count = (params[0] / sizeof(cell)) - 1;
if (count != def.length())
throw runtime_error("Script call: Number of arguments does not match definition");
for (unsigned int i = 0; i < count; ++i)
{
cell* data = amx_Address(amx, params[i + 2]);
switch (def[i])
{
case 'i':
{
args.emplace_back((unsigned int) *data);
break;
}
case 'q':
{
args.emplace_back((signed int) *data);
break;
}
case 'l':
{
args.emplace_back((unsigned long long) *data);
break;
}
case 'w':
{
args.emplace_back((signed long long) *data);
break;
}
case 'f':
{
args.emplace_back((double) amx_ctof(*data));
break;
}
case 'p':
{
args.emplace_back((void*) data);
break;
}
case 's':
{
amx_StrLen(data, &len);
vector<char> str;
str.reserve(len + 1);
amx_GetString(&str[0], data, 0, UNLIMITED);
args.emplace_back(string(&str[0]).c_str());
break;
}
default:
throw runtime_error("PAWN call: Unknown argument identifier " + def[i]);
}
}
boost::any result = Public::Call(&name[0], args);
if (result.empty())
return 0;
cell ret = 0;
if (result.type().hash_code() == typeid(signed int).hash_code())
ret = boost::any_cast<signed int>(result);
else if (result.type().hash_code() == typeid(unsigned int).hash_code())
ret = boost::any_cast<unsigned int>(result);
else if (result.type().hash_code() == typeid(double).hash_code())
ret = amx_ftoc(result);
return ret;
}
cell LangPAWN::CreateTimer(AMX *amx, const cell *params) noexcept
{
}
cell LangPAWN::CreateTimerEx(AMX *amx, const cell *params) noexcept
{
}

@ -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,429 @@
//
// Created by koncord on 01.08.17.
//
#include <iostream>
#include <cstdlib>
#include <boost/filesystem.hpp>
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include <components/misc/stringops.hpp>
#include <apps/openmw/mwworld/inventorystore.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <components/openmw-mp/Version.hpp>
#include <apps/openmw-mp/GUI.hpp>
#include <apps/openmw-mp/Dialogue.hpp>
#include <apps/openmw-mp/Factions.hpp>
#include <apps/openmw-mp/Quests.hpp>
#include <apps/openmw-mp/Spells.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include "LuaState.hpp"
#include "EventController.hpp"
#include "luaUtils.hpp"
#include "CommandController.hpp"
#include "../Inventory.hpp"
#include "../Settings.hpp"
#include "../Players.hpp"
#include "../Networking.hpp"
#include "../MasterClient.hpp"
using namespace std;
LuaState::LuaState()
{
lua = make_shared<sol::state>();
lua->open_libraries();
LuaUtils::Init(*this);
actorCtrl = make_unique<ActorController>();
ActorController::Init(*this);
eventCtrl = make_unique<EventController>(this);
EventController::Init(*this);
objectCtrl = make_unique<ObjectController>();
ObjectController::Init(*this);
cmdCtrl = make_unique<CommandController>();
Player::Init(*this);
CharClass::Init(*this);
Inventory::Init(*this);
GameSettings::Init(*this);
Books::Init(*this);
GUI::Init(*this);
Dialogue::Init(*this);
Factions::Init(*this);
Faction::Init(*this);
JournalItem::Init(*this);
Quests::Init(*this);
Effect::Init(*this);
Spell::Init(*this);
Spells::Init(*this);
Players::Init(*this);
timerCtrl = make_unique<TimerController>();
TimerController::Init(*this);
Timer::Init(*this);
CommandController::Init(*this);
dataEnv = sol::environment(*lua, sol::create, lua->globals());
lua->set("Data", dataEnv); // plain global environment for communicating between mods
auto coreTable = dataEnv.create("Core");
coreTable["VERSION"] = TES3MP_VERSION;
coreTable["PROTOCOL"] = TES3MP_PROTO_VERSION;
coreTable["loadedMods"] = coreTable.create();
// errors in sol::functions catches only in debug build for better performance
#ifdef SOL_SAFE_FUNCTIONS
lua->set_function("ErrorHandler", [](sol::object error_msg) {
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, ("Lua: " + error_msg.as<string>()).c_str());
});
sol::reference errHandler = (*lua)["ErrorHandler"];
sol::protected_function::set_default_handler(errHandler);
#endif
sol::table Constants = lua->create_named_table("Constants");
Constants.set_function("GetAttributeCount", []() {
return ESM::Attribute::Length;
});
Constants.set_function("GetSkillCount", []() {
return ESM::Skill::Length;
});
Constants.set_function("GetAttributeId", [](const string &name) {
for (int x = 0; x < ESM::Attribute::Length; x++)
if (Misc::StringUtils::ciEqual(name, ESM::Attribute::sAttributeNames[x]))
return x;
return -1;
});
Constants.set_function("GetSkillId", [](const string &name) {
for (int x = 0; x < ESM::Skill::Length; x++)
if (Misc::StringUtils::ciEqual(name, ESM::Skill::sSkillNames[x]))
return x;
return -1;
});
Constants.set_function("GetAttributeName", [](unsigned short attribute) -> const string {
if (attribute >= ESM::Attribute::Length)
return "invalid";
return ESM::Attribute::sAttributeNames[attribute];
});
Constants.set_function("GetSkillName", [](unsigned short skill) -> const string {
if (skill >= ESM::Skill::Length)
return "invalid";
return ESM::Skill::sSkillNames[skill];
});
Constants.set_function("GetEquipmentSize", []() {
return MWWorld::InventoryStore::Slots;
});
lua->set_function("getCurrentMpNum", []() {
return mwmp::Networking::getPtr()->getCurrentMpNum();
});
lua->set_function("setCurrentMpNum", [](int num) {
mwmp::Networking::getPtr()->setCurrentMpNum(num);
});
lua->set_function("logMessage", [](unsigned short level, const char *message) {
LOG_MESSAGE_SIMPLE(level, "[Script]: %s", message);
});
lua->set_function("logAppend", [](unsigned short level, const char *message) {
LOG_APPEND(level, "[Script]: %s", message);
});
lua->set_function("stopServer", [](int code) {
mwmp::Networking::getPtr()->stopServer(code);
});
lua->set_function("banAddress", [](const char *ipAddress) {
mwmp::Networking::getPtr()->banAddress(ipAddress);
});
lua->set_function("unbanAddress", [](const char *ipAddress) {
mwmp::Networking::getPtr()->unbanAddress(ipAddress);
});
lua->set_function("setRuleValue", [](const std::string &key, sol::object value) {
if (!value.valid())
return;
auto mc = mwmp::Networking::getPtr()->getMasterClient();
if (mc)
{
sol::type type = value.get_type();
if (type == sol::type::string)
mc->SetRuleString(key, value.as<string>());
if (type == sol::type::number)
mc->SetRuleValue(key, value.as<double>());
}
});
lua->set_function("setModname", [](const std::string &modname) {
auto mc = mwmp::Networking::getPtr()->getMasterClient();
if (mc)
mc->SetModname(modname);
});
lua->set_function("setHostname", [](const std::string &hostname) {
auto mc = mwmp::Networking::getPtr()->getMasterClient();
if (mc)
mc->SetHostname(hostname);
});
lua->set_function("setServerPassword", [](const std::string &passw) {
mwmp::Networking::getPtr()->setServerPassword(passw);
});
lua->set_function("setHour", [](double hour) {
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME);
Players::for_each([&hour, &packet](std::shared_ptr<Player> player){
player->hour = hour;
player->month = -1;
player->day = -1;
packet->setPlayer(player.get());
packet->Send(false);
});
});
lua->set_function("setMonth", [](int month) {
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME);
Players::for_each([&month, &packet](std::shared_ptr<Player> player){
player->hour = -1;
player->month = month;
player->day = -1;
packet->setPlayer(player.get());
packet->Send(false);
});
});
lua->set_function("setDay", [](int day) {
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GAME_TIME);
Players::for_each([&day, &packet](std::shared_ptr<Player> player){
player->hour = -1;
player->month = -1;
player->day = day;
packet->setPlayer(player.get());
packet->Send(false);
});
});
}
sol::environment LuaState::openScript(std::string path, std::string modname)
{
cout << "Loading file: " << path + "/" + modname + "/main.lua" << endl;
sol::environment env(*lua, sol::create, lua->globals());
std::string package_path = env["package"]["path"];
env["package"]["path"] = Utils::convertPath(path + "/" + modname + "/?.lua") + ";" + package_path;
package_path = env["package"]["path"];
//env["ModInfo"] = sol::create;
lua->script_file(path + "/" + modname + "/main.lua", env);
sol::table modinfo = env["ModInfo"];
if (!modinfo.valid())
throw runtime_error("ModInfo table for \"" + modname + "\" not found");
if (modinfo["name"].get_type() != sol::type::string)
throw runtime_error(modname + R"(: ModInfo["name"] undefined or not string")");
if (modinfo["version"].get_type() != sol::type::string)
throw runtime_error(modname + R"(: ModInfo["version"] undefined or not string")");
sol::table dependencies = modinfo["dependencies"];
if (dependencies.get_type() != sol::type::table)
throw runtime_error(modname + R"(: ModInfo["dependencies"] undefined or not table")");
string name = env["ModInfo"]["name"];
mods.emplace(name, env);
sol::table loaded = dataEnv["Core"]["loadedMods"];
loaded.add(name);
cout << "modname: " << name << endl;
return env;
}
void LuaState::addGlobalPackagePath(const std::string &path)
{
std::string package_path = (*lua)["package"]["path"];
(*lua)["package"]["path"] = Utils::convertPath(path) + ";" + package_path;
}
void LuaState::addGlobalCPath(const std::string &path)
{
std::string cpath = (*lua)["package"]["cpath"];
(*lua)["package"]["cpath"] = Utils::convertPath(path) + ";" + cpath;
}
CommandController &LuaState::getCmdCtrl()
{
return *cmdCtrl;
}
EventController &LuaState::getEventCtrl()
{
return *eventCtrl;
}
TimerController &LuaState::getTimerCtrl()
{
return *timerCtrl;
}
ActorController &LuaState::getActorCtrl()
{
return *actorCtrl;
}
ObjectController &LuaState::getObjectCtrl()
{
return *objectCtrl;
}
int CompVersion(const string &wishVersion, const string &depVersionFound)
{
unsigned startVer = 0;
if (wishVersion[0] == '>')
{
startVer = 1;
if (wishVersion[1] == '=')
startVer = 2;
}
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(".");
tokenizer tokensWish(wishVersion.begin() + startVer, wishVersion.end(), sep), tokensFound(depVersionFound, sep);
auto wishIter = tokensWish.begin();
auto founditer = tokensFound.begin();
int bellowExpected = 0;
for (int i = 0; i < 3; ++i)
{
auto v1 = boost::lexical_cast<int>(*(wishIter++));
auto v2 = boost::lexical_cast<int>(*(founditer++));
if (v2 > v1 && startVer > 0)
return 0; // found applicable version
if (v2 <= v1)
{
if (v2 == v1 && startVer == 1)
bellowExpected++;
else if (v2 < v1)
return -1; // found version below expected
continue;
}
return 1; // version higher than expected
}
if (bellowExpected == 3)
return -1; // found version below expected
return 0;
}
void LuaState::loadMods()
{
using namespace boost::filesystem;
auto funcLoadMods = [this](path path) {
path /= "mods";
const auto mainScript = "main.lua";
if (!is_directory(path))
throw runtime_error(path.string() + ": No such directory.");
for (const auto &modDir : directory_iterator(path))
{
if (is_directory(modDir.status()) && exists(modDir.path() / mainScript))
openScript(path.string(), modDir.path().filename().string());
}
};
#ifdef _WIN32
const char* libExt = ".dll";
#else
const char* libExt = ".so";
#endif
path envServerDir = std::getenv("TES3MP_SERVER_DIR");
const char *envServerUserDir = std::getenv("TES3MP_SERVER_USERDIR");
if (envServerDir.empty())
{
envServerDir = current_path();
setenv("TES3MP_SERVER_DIR", envServerDir.c_str(), 1);
}
addGlobalPackagePath(envServerDir.string() + "/lib/lua/?/init.lua;" + envServerDir.string() + "/lib/lua/?.lua");
addGlobalCPath(envServerDir.string() + "lib/?" + libExt);
funcLoadMods(envServerDir);
if (envServerUserDir != nullptr)
{
funcLoadMods(envServerUserDir);
addGlobalPackagePath(string(envServerUserDir) + "/lib/lua/?/init.lua;" + string(envServerUserDir) + "/lib/lua/?.lua");
}
for (auto &mod : mods)
{
const string &modName = mod.first;
sol::environment &modEnv = mod.second;
sol::table dependencies = modEnv["ModInfo"]["dependencies"];
for (auto &dependency : dependencies)
{
int idx = dependency.first.as<int>();
sol::table dep = dependency.second;
const std::string depNameRequest = dep[1];
const std::string depVersionRequest = dep[2];
cout << "\"" << idx << "\": \"" << depNameRequest << "\" \"" << depVersionRequest << "\"" << endl;
const auto &depEnvIt = mods.find(depNameRequest);
if (depEnvIt != mods.end())
{
string depVersionFound = depEnvIt->second["ModInfo"]["version"];
if (CompVersion(depVersionRequest, depVersionFound) != 0)
{
stringstream sstr;
sstr << depNameRequest << ": version \"" << depVersionFound
<< "\" is not applicable for \"" << modName << "\" expected \""
<< depVersionRequest + "\"";
throw runtime_error(sstr.str());
}
}
else
{
stringstream sstr;
sstr << depNameRequest + " \"" << depVersionRequest << "\" not found.";
throw runtime_error(sstr.str());
}
}
}
dataEnv["Core"]["LOADED_MODS"] = mods.size();
eventCtrl->Call<CoreEvent::ON_POST_INIT>();
}

@ -0,0 +1,49 @@
//
// Created by koncord on 01.08.17.
//
#pragma once
#include "sol.hpp"
#include "CommandController.hpp"
#include "Timer.hpp"
#include <unordered_map>
#include <memory>
#include <apps/openmw-mp/Actors.hpp>
#include <apps/openmw-mp/Object.hpp>
//class CommandController;
class EventController;
//class TimerController;
class LuaState
{
public:
LuaState();
~LuaState() = default;
std::shared_ptr<sol::state> getState() { return lua; }
void addGlobalPackagePath(const std::string &path);
void addGlobalCPath(const std::string &path);
sol::table getCoreTable() { return dataEnv["Core"]; }
sol::environment &getDataEnv(){ return dataEnv; }
void loadMods();
CommandController &getCmdCtrl();
EventController &getEventCtrl();
TimerController &getTimerCtrl();
ObjectController &getObjectCtrl();
ActorController &getActorCtrl();
private:
sol::environment openScript(std::string path, std::string modname);
private:
std::shared_ptr<sol::state> lua;
sol::environment dataEnv;
std::unique_ptr<CommandController> cmdCtrl;
std::unique_ptr<EventController> eventCtrl;
std::unique_ptr<TimerController> timerCtrl;
std::unique_ptr<ActorController> actorCtrl;
std::unique_ptr<ObjectController> objectCtrl;
std::unordered_map<std::string, sol::environment> mods;
};

@ -1,20 +0,0 @@
//
// Created by koncord on 23.01.16.
//
#ifndef PLATFORM_HPP
#define PLATFORM_HPP
#if _MSC_VER
#ifdef _M_X86
#define ARCH_X86
#endif
#endif
#if __GNUC__
#ifdef __i386__
#define ARCH_X86
#endif
#endif
#endif //PLATFORM_HPP

@ -1,109 +0,0 @@
//
// Created by koncord on 19.03.16.
//
#include "Script.hpp"
#include "LangNative/LangNative.hpp"
#if defined (ENABLE_PAWN)
#include "LangPawn/LangPAWN.hpp"
#endif
#if defined (ENABLE_LUA)
#include "LangLua/LangLua.hpp"
#endif
using namespace std;
Script::ScriptList Script::scripts;
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_PAWN)
else if (strstr(path, ".amx"))
{
lang = new LangPAWN();
script_type = SCRIPT_PAWN;
}
#endif
#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();
#if defined (ENABLE_TERRA)
terra_llvmshutdown();
#endif
}
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));
}

@ -1,156 +0,0 @@
//
// Created by koncord on 19.03.16.
//
#ifndef PLUGINSYSTEM3_SCRIPT_HPP
#define PLUGINSYSTEM3_SCRIPT_HPP
#include "Types.hpp"
#include "SystemInterface.hpp"
#include "ScriptFunction.hpp"
#include "ScriptFunctions.hpp"
#include "Language.hpp"
#include <boost/any.hpp>
#include <unordered_map>
#include <memory>
class Script : private ScriptFunctions
{
// http://imgur.com/hU0N4EH
private:
Language *lang;
enum
{
SCRIPT_CPP,
SCRIPT_PAWN,
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;
public:
~Script();
static void LoadScript(const char *script, const char* base);
static void LoadScripts(char* scripts, const char* base);
static void UnloadScripts();
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>
using CallBackReturn = typename CharType<CallBackData(I).callback.ret>::type;
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(CallBackReturn<I>& result, 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;
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Called function \"%s\"", data.name);
if (script->script_type == SCRIPT_CPP)
result = reinterpret_cast<FunctionEllipsis<CallBackReturn<I>>>(callback)(std::forward<Args>(args)...);
#if defined (ENABLE_PAWN)
else if (script->script_type == SCRIPT_PAWN)
{
boost::any any = script->lang->Call(data.name, data.callback.types, B, std::forward<Args>(args)...);
result = reinterpret_cast<CallBackReturn<I>> ((int)boost::any_cast<int64_t>(any)); // TODO: WTF?! int?!
}
#endif
#if defined (ENABLE_LUA)
else if (script->script_type == SCRIPT_LUA)
{
boost::any any = script->lang->Call(data.name, data.callback.types, B, std::forward<Args>(args)...);
result = static_cast<CallBackReturn<I>>(boost::any_cast<luabridge::LuaRef>(any).cast<CallBackReturn<I>>());
}
#endif
++count;
}
return count;
}
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;
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Called function \"%s\"", data.name);
if (script->script_type == SCRIPT_CPP)
reinterpret_cast<FunctionEllipsis<CallBackReturn<I>>>(callback)(std::forward<Args>(args)...);
#if defined (ENABLE_PAWN)
else if (script->script_type == SCRIPT_PAWN)
script->lang->Call(data.name, data.callback.types, B, std::forward<Args>(args)...);
#endif
#if defined (ENABLE_LUA)
else if (script->script_type == SCRIPT_LUA)
script->lang->Call(data.name, data.callback.types, B, std::forward<Args>(args)...);
#endif
++count;
}
return count;
}
};
#endif //PLUGINSYSTEM3_SCRIPT_HPP

@ -1,167 +0,0 @@
//
// Created by koncord on 23.01.16.
//
#include<iostream>
#include <stdexcept>
#include "ScriptFunction.hpp"
#if !defined(_WIN32) && !defined(__ARM_ARCH) // temporarily disabled
#include <call.hpp>
#endif
#if defined (ENABLE_LUA)
#include "LangLua/LangLua.hpp"
#endif
#if defined (ENABLE_PAWN)
#include "LangPawn/LangPAWN.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
#if defined (ENABLE_PAWN)
ScriptFunction::ScriptFunction(const ScriptFuncPAWN &fPawn, AMX *amx, char ret_type, const string &def) :
fPawn({amx, fPawn}), def(def), ret_type(ret_type), script_type(SCRIPT_PAWN)
{
}
#endif
ScriptFunction::~ScriptFunction()
{
#if defined (ENABLE_PAWN)
if (script_type == SCRIPT_PAWN)
fPawn.name.~ScriptFuncPAWN();
#if defined (ENABLE_LUA)
else
#endif
#endif
#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_PAWN)
if (script_type == SCRIPT_PAWN)
{
LangPAWN langPawn(fPawn.amx);
boost::any any = langPawn.Call(fPawn.name.c_str(), def.c_str(), args);
result = boost::any();
cell ret = boost::any_cast<cell>(any);
switch (ret_type)
{
case 'i':
result = static_cast<unsigned int>(ret);
break;
case 'q':
result = static_cast<signed int>(ret);
break;
case 's':
throw runtime_error("Pawn call: the Pawn does not supported strings in public functions");
case 'f':
result = static_cast<double>(amx_ctof(ret));
break;
case 'v':
result = boost::any();
break;
default:
throw runtime_error("Pawn call: Unknown return type" + ret_type);
}
}
#endif
#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
else
{
#if !defined(_WIN32) && !defined(__ARM_ARCH) // temporarily disabled
string::iterator it;
vector<boost::any>::const_iterator it2;
vector<intptr_t> data;
CallArgs callArgs;
for (it = def.begin(), it2 = args.begin(); it != def.end(); ++it, ++it2)
{
switch (*it)
{
case 'i':
callArgs.push_integer(boost::any_cast<unsigned int>(*it2));
break;
case 'q':
callArgs.push_integer(boost::any_cast<signed int>(*it2));
break;
case 'f':
callArgs.push_double(boost::any_cast<double>(*it2));
break;
case 'd':
callArgs.push_double(boost::any_cast<double*>(*it2));
break;
case 's':
callArgs.push_stringPtr(boost::any_cast<const char *>(*it2));
break;
case 'v':
result = boost::any();
break;
default:
throw runtime_error("C++ call: Unknown argument identifier " + *it);
}
}
Func f = reinterpret_cast<Func>(fCpp);
result = ::Call(f, callArgs);
#else
throw runtime_error("C++ call: Windows and ARM not supported yet.");
#endif
}
return result;
}

@ -1,72 +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
#if defined (ENABLE_PAWN)
#include <amx.h>
#endif
typedef unsigned long long(*ScriptFunc)();
#if defined (ENABLE_PAWN)
typedef std::string ScriptFuncPAWN;
#endif
#if defined (ENABLE_LUA)
typedef std::string ScriptFuncLua;
#endif
class ScriptFunction
{
protected:
union
{
ScriptFunc fCpp;
#if defined (ENABLE_PAWN)
struct
{
AMX *amx;
ScriptFuncPAWN name;
} fPawn;
#endif
#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_PAWN,
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
#if defined (ENABLE_PAWN)
ScriptFunction(const ScriptFuncPAWN &fPawn, AMX *amx, char ret_type, const std::string &def);
#endif
virtual ~ScriptFunction();
boost::any Call(const std::vector<boost::any> &args);
};
#endif //SCRIPTFUNCTION_HPP

@ -1,174 +0,0 @@
//
// Created by koncord on 24.01.16.
//
#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>
#include <components/openmw-mp/Version.hpp>
#include "MasterClient.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> &params, 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("C++ call: Unknown argument identifier " + c);
}
}
}
catch (...)
{
va_end(args);
throw;
}
va_end(args);
}
void ScriptFunctions::MakePublic(ScriptFunc _public, const char *name, char ret_type, const char *def) noexcept
{
Public::MakePublic(_public, name, ret_type, def);
}
boost::any ScriptFunctions::CallPublic(const char *name, va_list args) noexcept
{
vector<boost::any> params;
try
{
string def = Public::GetDefinition(name);
GetArguments(params, args, def);
return Public::Call(name, params);
}
catch (...) {}
return 0;
}
void ScriptFunctions::StopServer(int code) noexcept
{
mwmp::Networking::getPtr()->stopServer(code);
}
void ScriptFunctions::Kick(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,);
mwmp::Networking::getPtr()->kickPlayer(player->guid);
}
void ScriptFunctions::BanAddress(const char *ipAddress) noexcept
{
mwmp::Networking::getPtr()->banAddress(ipAddress);
}
void ScriptFunctions::UnbanAddress(const char *ipAddress) noexcept
{
mwmp::Networking::getPtr()->unbanAddress(ipAddress);
}
const char *ScriptFunctions::GetServerVersion() noexcept
{
return TES3MP_VERSION;
}
const char *ScriptFunctions::GetProtocolVersion() noexcept
{
static string version = to_string(TES3MP_PROTO_VERSION);
return version.c_str();
}
int ScriptFunctions::GetAvgPing(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player,-1);
return mwmp::Networking::get().getAvgPing(player->guid);
}
const char *ScriptFunctions::GetIP(unsigned short pid) noexcept
{
Player *player;
GET_PLAYER(pid, player, "");
RakNet::SystemAddress addr = mwmp::Networking::getPtr()->getSystemAddress(player->guid);
return addr.ToString(false);
}
void ScriptFunctions::SetModname(const char *name) noexcept
{
mwmp::Networking::getPtr()->getMasterClient()->SetModname(name);
}
void ScriptFunctions::SetHostname(const char *name) noexcept
{
mwmp::Networking::getPtr()->getMasterClient()->SetHostname(name);
}
void ScriptFunctions::SetServerPassword(const char *passw) noexcept
{
mwmp::Networking::getPtr()->setServerPassword(passw);
}
void ScriptFunctions::SetRuleString(const char *key, const char *value) noexcept
{
auto mc = mwmp::Networking::getPtr()->getMasterClient();
if (mc)
mc->SetRuleString(key, value);
}
void ScriptFunctions::SetRuleValue(const char *key, double value) noexcept
{
auto mc = mwmp::Networking::getPtr()->getMasterClient();
if (mc)
mc->SetRuleValue(key, value);
}

@ -1,186 +0,0 @@
//
// Created by koncord on 24.01.16.
//
#ifndef SCRIPTFUNCTIONS_HPP
#define SCRIPTFUNCTIONS_HPP
#include <Script/Functions/Actors.hpp>
#include <Script/Functions/Books.hpp>
#include <Script/Functions/Cells.hpp>
#include <Script/Functions/CharClass.hpp>
#include <Script/Functions/Dialogue.hpp>
#include <Script/Functions/Factions.hpp>
#include <Script/Functions/GUI.hpp>
#include <Script/Functions/Items.hpp>
#include <Script/Functions/Mechanics.hpp>
#include <Script/Functions/Miscellaneous.hpp>
#include <Script/Functions/Positions.hpp>
#include <Script/Functions/Quests.hpp>
#include <Script/Functions/Settings.hpp>
#include <Script/Functions/Spells.hpp>
#include <Script/Functions/Stats.hpp>
#include <Script/Functions/World.hpp>
#include <RakNetTypes.h>
//#include <amx/amx.h>
#include <tuple>
#include <apps/openmw-mp/Player.hpp>
#include "ScriptFunction.hpp"
#include "Types.hpp"
#include <components/openmw-mp/Log.hpp>
#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> &params, va_list args, const std::string &def);
static void StopServer(int code) noexcept;
static void MakePublic(ScriptFunc _public, const char *name, char ret_type, const char *def) noexcept;
static boost::any CallPublic(const char *name, va_list args) noexcept;
static void SendMessage(unsigned short pid, const char *message, bool broadcast) noexcept;
static void CleanChatByPid(unsigned short pid);
static void CleanChat();
/**
* \brief Create timer
* \param callback
* \param msec
* \return return timer id
*/
static int CreateTimer(ScriptFunc callback, int msec) noexcept;
static int CreateTimerEx(ScriptFunc callback, int msec, const char *types, va_list args) noexcept;
static void StartTimer(int timerId) noexcept;
static void StopTimer(int timerId) noexcept;
static void RestartTimer(int timerId, int msec) noexcept;
static void FreeTimer(int timerId) noexcept;
static bool IsTimerElapsed(int timerId) noexcept;
static void Kick(unsigned short pid) noexcept;
static void BanAddress(const char *ipAddress) noexcept;
static void UnbanAddress(const char *ipAddress) noexcept;
static const char *GetServerVersion() noexcept;
static const char *GetProtocolVersion() noexcept;
static int GetAvgPing(unsigned short pid) noexcept;
static const char* GetIP(unsigned short pid) noexcept;
static void SetModname(const char* name) noexcept;
static void SetHostname(const char* name) noexcept;
static void SetServerPassword(const char *passw) noexcept;
static void SetRuleString(const char *key, const char *value) noexcept;
static void SetRuleValue(const char *key, double value) noexcept;
static constexpr ScriptFunctionData functions[]{
{"CreateTimer", ScriptFunctions::CreateTimer},
{"CreateTimerEx", reinterpret_cast<Function<void>>(ScriptFunctions::CreateTimerEx)},
{"MakePublic", ScriptFunctions::MakePublic},
{"CallPublic", reinterpret_cast<Function<void>>(ScriptFunctions::CallPublic)},
{"StartTimer", ScriptFunctions::StartTimer},
{"StopTimer", ScriptFunctions::StopTimer},
{"RestartTimer", ScriptFunctions::RestartTimer},
{"FreeTimer", ScriptFunctions::FreeTimer},
{"IsTimerElapsed", ScriptFunctions::IsTimerElapsed},
{"StopServer", ScriptFunctions::StopServer},
{"SendMessage", ScriptFunctions::SendMessage},
{"Kick", ScriptFunctions::Kick},
{"BanAddress", ScriptFunctions::BanAddress},
{"UnbanAddress", ScriptFunctions::UnbanAddress},
{"GetServerVersion", ScriptFunctions::GetServerVersion},
{"GetProtocolVersion", ScriptFunctions::GetProtocolVersion},
{"GetAvgPing", ScriptFunctions::GetAvgPing},
{"SetModname", ScriptFunctions::SetModname},
{"SetHostname", ScriptFunctions::SetHostname},
{"SetServerPassword", ScriptFunctions::SetServerPassword},
{"SetRuleString", ScriptFunctions::SetRuleString},
{"SetRuleValue", ScriptFunctions::SetRuleValue},
{"CleanChatByPid", ScriptFunctions::CleanChatByPid},
{"CleanChat", ScriptFunctions::CleanChat},
{"GetIP", ScriptFunctions::GetIP},
ACTORAPI,
BOOKAPI,
CELLAPI,
CHARCLASSAPI,
DIALOGUEAPI,
FACTIONAPI,
GUIAPI,
ITEMAPI,
MECHANICSAPI,
MISCELLANEOUSAPI,
POSITIONAPI,
QUESTAPI,
SETTINGSAPI,
SPELLAPI,
STATAPI,
WORLDAPI
};
static constexpr ScriptCallbackData callbacks[]{
{"Main", Function<int, int, int>()},
{"OnServerInit", Function<void>()},
{"OnServerPostInit", Function<void>()},
{"OnServerExit", Function<void, bool>()},
{"OnPlayerConnect", Function<bool, unsigned short>()},
{"OnPlayerDisconnect", Function<void, unsigned short>()},
{"OnPlayerDeath", Function<void, unsigned short>()},
{"OnPlayerResurrect", Function<void, unsigned short>()},
{"OnPlayerCellChange", Function<void, unsigned short>()},
{"OnPlayerKillCount", Function<void, unsigned short>()},
{"OnPlayerAttribute", Function<void, unsigned short>()},
{"OnPlayerSkill", Function<void, unsigned short>()},
{"OnPlayerLevel", Function<void, unsigned short>()},
{"OnPlayerBounty", Function<void, unsigned short>()},
{"OnPlayerEquipment", Function<void, unsigned short>()},
{"OnPlayerInventory", Function<void, unsigned short>()},
{"OnPlayerJournal", Function<void, unsigned short>()},
{"OnPlayerFaction", Function<void, unsigned short>()},
{"OnPlayerShapeshift", Function<void, unsigned short>()},
{"OnPlayerSpellbook", Function<void, unsigned short>()},
{"OnPlayerTopic", Function<void, unsigned short>()},
{"OnPlayerDisposition", Function<void, unsigned short>()},
{"OnPlayerBook", Function<void, unsigned short>()},
{"OnPlayerMap", Function<void, unsigned short>()},
{"OnPlayerRest", Function<void, unsigned short>()},
{"OnCellLoad", Function<void, unsigned short, const char*>()},
{"OnCellUnload", Function<void, unsigned short, const char*>()},
{"OnCellDeletion", Function<void, const char*>()},
{"OnContainer", Function<void, unsigned short, const char*>()},
{"OnDoorState", Function<void, unsigned short, const char*>()},
{"OnObjectPlace", Function<void, unsigned short, const char*>()},
{"OnObjectState", Function<void, unsigned short, const char*>()},
{"OnObjectSpawn", Function<void, unsigned short, const char*>()},
{"OnObjectDelete", Function<void, unsigned short, const char*>()},
{"OnObjectLock", Function<void, unsigned short, const char*>()},
{"OnObjectScale", Function<void, unsigned short, const char*>()},
{"OnObjectTrap", Function<void, unsigned short, const char*>()},
{"OnActorList", Function<void, unsigned short, const char*>()},
{"OnActorEquipment", Function<void, unsigned short, const char*>()},
{"OnActorCellChange", Function<void, unsigned short, const char*>()},
{"OnActorTest", Function<void, unsigned short, const char*>()},
{"OnPlayerSendMessage", Function<bool, unsigned short, const char*>()},
{"OnPlayerEndCharGen", Function<void, unsigned short>()},
{"OnGUIAction", Function<void, unsigned short, int, const char*>()},
{"OnMpNumIncrement", Function<void, int>()},
{"OnRequestPluginList", Function<const char *, unsigned int, unsigned int>()}
};
};
#endif //SCRIPTFUNCTIONS_HPP

@ -1,43 +0,0 @@
//
// Created by koncord on 19.03.16.
//
#ifndef PLUGINSYSTEM3_SYSTEMINTERFACE_HPP
#define PLUGINSYSTEM3_SYSTEMINTERFACE_HPP
#ifdef _WIN32
#include <winsock2.h>
#else
#include <dlfcn.h>
#endif
#include "Types.hpp"
template<typename R = void*>
struct SystemInterface
{
union
{
R result;
#ifdef _WIN32
decltype(GetProcAddress(lib_t(), nullptr)) data;
#else
decltype(dlsym(lib_t(), nullptr)) data;
#endif
};
#ifndef _WIN32
static_assert(sizeof(result) == sizeof(data), "R should have the same size");
#endif
SystemInterface() : data(nullptr) {}
explicit operator bool() { return data; }
#ifdef _WIN32
SystemInterface(lib_t handle, const char* name) : data(GetProcAddress(handle, name)) {}
#else
SystemInterface(lib_t handle, const char* name) : data(dlsym(handle, name)) {}
#endif
};
#endif //PLUGINSYSTEM3_SYSTEMINTERFACE_HPP

@ -1,113 +0,0 @@
//
// Created by koncord on 23.01.16.
//
#ifndef TMPTYPES_HPP
#define TMPTYPES_HPP
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <RakNetTypes.h>
#include "Utils.hpp"
#ifdef _WIN32
#include <winsock2.h>
#endif
#ifdef _WIN32
typedef HMODULE lib_t;
#else
typedef void* lib_t;
#endif
template<typename T> struct sizeof_void { enum { value = sizeof(T) }; };
template<> struct sizeof_void<void> { enum { value = 0 }; };
template<typename T, size_t t> struct TypeChar { static_assert(!t, "Unsupported type in variadic type list"); };
template<> struct TypeChar<bool, sizeof(bool)> { enum { value = 'b' }; };
template<typename T> struct TypeChar<T*, sizeof(void*)> { enum { value = 'p' }; };
template<> struct TypeChar<double*, sizeof(double*)> { enum { value = 'd' }; };
template<> struct TypeChar<RakNet::NetworkID**, sizeof(RakNet::NetworkID**)> { enum { value = 'n' }; };
template<typename T> struct TypeChar<T, sizeof(uint8_t)> { enum { value = std::is_signed<T>::value ? 'q' : 'i' }; };
template<typename T> struct TypeChar<T, sizeof(uint16_t)> { enum { value = std::is_signed<T>::value ? 'q' : 'i' }; };
template<typename T> struct TypeChar<T, sizeof(uint32_t)> { enum { value = std::is_signed<T>::value ? 'q' : 'i' }; };
template<typename T> struct TypeChar<T, sizeof(uint64_t)> { enum { value = std::is_signed<T>::value ? 'w' : 'l' }; };
template<> struct TypeChar<double, sizeof(double)> { enum { value = 'f' }; };
template<> struct TypeChar<char*, sizeof(char*)> { enum { value = 's' }; };
template<> struct TypeChar<const char*, sizeof(const char*)> { enum { value = 's' }; };
template<> struct TypeChar<void, sizeof_void<void>::value> { enum { value = 'v' }; };
template<const char t> struct CharType { static_assert(!t, "Unsupported type in variadic type list"); };
template<> struct CharType<'b'> { typedef bool type; };
template<> struct CharType<'p'> { typedef void* type; };
template<> struct CharType<'d'> { typedef double* type; };
template<> struct CharType<'n'> { typedef RakNet::NetworkID** type; };
template<> struct CharType<'q'> { typedef signed int type; };
template<> struct CharType<'i'> { typedef unsigned int type; };
template<> struct CharType<'w'> { typedef signed long long type; };
template<> struct CharType<'l'> { typedef unsigned long long type; };
template<> struct CharType<'f'> { typedef double type; };
template<> struct CharType<'s'> { typedef const char* type; };
template<> struct CharType<'v'> { typedef void type; };
template<typename... Types>
struct TypeString {
static constexpr char value[sizeof...(Types) + 1] = {
TypeChar<Types, sizeof(Types)>::value...
};
};
template<typename R, typename... Types>
using Function = R(*)(Types...);
template<typename R>
using FunctionEllipsis = R(*)(...);
struct ScriptIdentity
{
const char* types;
const char ret;
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 R, typename... Types>
constexpr ScriptIdentity(Function<R, Types...>) : types(TypeString<Types...>::value), ret(TypeChar<R, sizeof_void<R>::value>::value), numargs(sizeof(TypeString<Types...>::value) - 1) {}
};
struct ScriptFunctionPointer : public ScriptIdentity
{
Function<void> addr;
template<typename R, typename... Types>
constexpr ScriptFunctionPointer(Function<R, Types...> addr) : ScriptIdentity(addr), addr(reinterpret_cast<Function<void>>(addr)) {}
};
struct ScriptFunctionData
{
const char* name;
const ScriptFunctionPointer func;
constexpr ScriptFunctionData(const char* name, ScriptFunctionPointer func) : name(name), func(func) {}
};
struct ScriptCallbackData
{
const char* name;
const unsigned int index;
const ScriptIdentity callback;
template<size_t N>
constexpr ScriptCallbackData(const char(&name)[N], ScriptIdentity _callback) : name(name), index(Utils::hash(name)), callback(_callback) {}
};
#endif //TMPTYPES_HPP

@ -0,0 +1,31 @@
//
// Created by koncord on 03.08.17.
//
#include <boost/tokenizer.hpp>
#include "luaUtils.hpp"
#include "LuaState.hpp"
sol::table str_split(const std::string &str, const sol::object &sepObj, sol::this_state state)
{
sol::state_view lua(state);
sol::table tbl = lua.create_table();
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(sepObj.valid() ? sepObj.as<const char *>() : ":");
tokenizer tokens(str, sep);
for (const auto &token : tokens)
tbl.add(token);
return tbl;
}
void LuaUtils::Init(LuaState &lua)
{
sol::table strTable = (*lua.getState())["string"];
if (!strTable.valid())
throw std::runtime_error("string library not initialized");
strTable.set_function("split", &str_split);
}

@ -0,0 +1,18 @@
//
// Created by koncord on 03.08.17.
//
#pragma once
#include "Utils.hpp"
#include "sol.hpp"
class LuaState;
class LuaUtils
{
//Singleton(LuaUtils)
public:
static void Init(LuaState &lua);
};

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save