forked from mirror/openmw-tes3mp
Compare commits
314 Commits
0.7.0
...
sol2-serve
Author | SHA1 | Date |
---|---|---|
David Cernat | 9029533ec1 | 6 years ago |
Testman | 7fadc533c7 | 6 years ago |
David Cernat | cf33695447 | 7 years ago |
David Cernat | dbd6ccaf97 | 7 years ago |
Testman | 702d5b44c9 | 7 years ago |
David Cernat | 8b482e19ec | 7 years ago |
David Cernat | d5b3d08ec9 | 7 years ago |
David Cernat | 524363702c | 7 years ago |
David Cernat | b3c398605f | 7 years ago |
David Cernat | 176aa62b15 | 7 years ago |
David Cernat | 6bb2a7e24a | 7 years ago |
David Cernat | 058d67dbd0 | 7 years ago |
David Cernat | 49bf605e8e | 7 years ago |
David Cernat | 07b781cd32 | 7 years ago |
Stanislav Zhukov | 08915c44a0 | 7 years ago |
Kyle Cooley | e12330b038 | 7 years ago |
David Cernat | 5c41350532 | 7 years ago |
David Cernat | fc4d3fe3fa | 7 years ago |
David Cernat | 569243c987 | 7 years ago |
Koncord | 7180b009bd | 7 years ago |
David Cernat | 3f7e163c92 | 7 years ago |
David Cernat | 7083cb0359 | 7 years ago |
David Cernat | ad4214d3e2 | 7 years ago |
Kyle Cooley | 83fe29d10f | 7 years ago |
Kyle Cooley | 3a68f4bd8f | 7 years ago |
David Cernat | 8a393d2984 | 7 years ago |
David Cernat | b5922d18fd | 7 years ago |
David Cernat | 98eece808b | 7 years ago |
David Cernat | d4dbfdfdb6 | 7 years ago |
David Cernat | 672bb707a7 | 7 years ago |
David Cernat | 7c8dd7380f | 7 years ago |
David Cernat | c5f33e451f | 7 years ago |
David Cernat | 4846497078 | 7 years ago |
David Cernat | 502751cae0 | 7 years ago |
David Cernat | d58efde3f1 | 7 years ago |
David Cernat | e355dca4dd | 7 years ago |
David Cernat | ed15d9ebf5 | 7 years ago |
David Cernat | 2390744b45 | 7 years ago |
David Cernat | c3b44e11fb | 7 years ago |
David Cernat | f50637bdd4 | 7 years ago |
Koncord | 6131ada0ba | 7 years ago |
David Cernat | 5bb09d3bed | 7 years ago |
Koncord | 2aaf9105af | 7 years ago |
David Cernat | 3d5860d6f4 | 7 years ago |
David Cernat | 7ec08e125b | 7 years ago |
David Cernat | b2a3dd9d60 | 7 years ago |
Koncord | 2ac01dc02a | 7 years ago |
Koncord | 4aff1f1833 | 7 years ago |
Koncord | 017956366f | 7 years ago |
Koncord | afbafdf806 | 7 years ago |
Koncord | d0eef7c98e | 7 years ago |
Koncord | 7deff7a42a | 7 years ago |
Koncord | 23da0b16ea | 7 years ago |
Koncord | 6f7771d97e | 7 years ago |
Koncord | 24ba4ae404 | 7 years ago |
Koncord | 73d030b779 | 7 years ago |
Koncord | 4e869a2974 | 7 years ago |
Koncord | e85d0db771 | 7 years ago |
Koncord | 44c549211e | 7 years ago |
Koncord | 2bfd4627ed | 7 years ago |
Koncord | 9dae748a76 | 7 years ago |
Koncord | bb7c5ee34c | 7 years ago |
Koncord | 54945b537d | 7 years ago |
Koncord | 4bde7d80f5 | 7 years ago |
Koncord | f2a88e6a37 | 7 years ago |
Koncord | 410eb353e8 | 7 years ago |
Koncord | a9614ad28e | 7 years ago |
Koncord | 69436714f9 | 7 years ago |
David Cernat | 3b865244d0 | 7 years ago |
David Cernat | 4e9cac96c7 | 7 years ago |
David Cernat | ac374a8ef9 | 7 years ago |
David Cernat | bdafa8e9ab | 7 years ago |
David Cernat | f1ba9253b0 | 7 years ago |
David Cernat | 5858e05362 | 7 years ago |
David Cernat | 1a8a518897 | 7 years ago |
David Cernat | 569911121d | 7 years ago |
David Cernat | 5cf71a4e67 | 7 years ago |
David Cernat | d70b93e095 | 7 years ago |
Koncord | 6197636fac | 7 years ago |
Koncord | edd883853d | 7 years ago |
Koncord | 0e97b769f9 | 7 years ago |
Koncord | 4cfb04aa7f | 7 years ago |
Koncord | 7e5b929ea2 | 7 years ago |
Koncord | 29ba07fe8c | 7 years ago |
Koncord | de0bb3cdab | 7 years ago |
Koncord | cb86557aca | 7 years ago |
Koncord | 0780329a59 | 7 years ago |
Koncord | 1f1cbf53f9 | 7 years ago |
Koncord | b63bf258ff | 7 years ago |
Koncord | c2578918f2 | 7 years ago |
Koncord | e2e197d84a | 7 years ago |
Koncord | f1e2bc01f6 | 7 years ago |
Koncord | 1e25a122c9 | 7 years ago |
David Cernat | a037193e79 | 7 years ago |
Koncord | 05fac2f67d | 7 years ago |
Koncord | 043eb224e2 | 7 years ago |
Koncord | 35b771b19e | 7 years ago |
David Cernat | 92060bd6b6 | 7 years ago |
Koncord | 1de9f30449 | 7 years ago |
David Cernat | 45d3b24c17 | 7 years ago |
Kyle Cooley | 7248a5d037 | 7 years ago |
Kyle Cooley | ba4d2bd5fe | 7 years ago |
David Cernat | b6a7377692 | 7 years ago |
Kyle Cooley | fcd4d8b842 | 7 years ago |
Kyle Cooley | e2103d0bea | 7 years ago |
Koncord | 35922e4898 | 7 years ago |
Koncord | ef0384b296 | 7 years ago |
Koncord | 5b8f4f3e92 | 7 years ago |
Koncord | 647661daf9 | 7 years ago |
David Cernat | 2f6e3b4cda | 7 years ago |
Koncord | c4949ac5d9 | 7 years ago |
Koncord | 8f5d31cb03 | 7 years ago |
Koncord | 4ab338bbb1 | 7 years ago |
Koncord | 5777759aae | 7 years ago |
Koncord | 2019128d92 | 7 years ago |
David Cernat | 51a92bcf8f | 7 years ago |
David Cernat | 09958681cd | 7 years ago |
David Cernat | 8bb764c6d6 | 7 years ago |
David Cernat | dddd2f1cc7 | 7 years ago |
David Cernat | a84c4c7ecc | 7 years ago |
David Cernat | f2eca2566f | 7 years ago |
Koncord | 077a3d06b3 | 7 years ago |
Koncord | f9c4b847aa | 7 years ago |
Koncord | c5388e49f2 | 7 years ago |
Koncord | ba07d7820f | 7 years ago |
Koncord | 77d14211c9 | 7 years ago |
Koncord | ecbe0127b0 | 7 years ago |
Koncord | fd721143e2 | 7 years ago |
Koncord | 25b7095396 | 7 years ago |
Koncord | 44dc153ebe | 7 years ago |
Koncord | 1ef6ad6215 | 7 years ago |
Koncord | aff1859759 | 7 years ago |
Koncord | 122a30c183 | 7 years ago |
Koncord | 2726d94d10 | 7 years ago |
Koncord | d98bb74b80 | 7 years ago |
Koncord | bfdf348a6c | 7 years ago |
Koncord | f11473da87 | 7 years ago |
Koncord | 4d0072a74c | 7 years ago |
Koncord | cd620e17ec | 7 years ago |
Koncord | dd352f0a91 | 7 years ago |
Koncord | f35d35741e | 7 years ago |
Koncord | 585c24cee8 | 7 years ago |
Koncord | ff8b5061b4 | 7 years ago |
Koncord | e97dac7793 | 7 years ago |
Koncord | 7748e582a8 | 7 years ago |
Koncord | 2cb0ea20f0 | 7 years ago |
David Cernat | de77ee3126 | 7 years ago |
David Cernat | ad61d88cb1 | 7 years ago |
Koncord | 051f65a4d5 | 7 years ago |
Koncord | 7eecbfd08e | 7 years ago |
Koncord | 1c7330635b | 7 years ago |
Koncord | 392e645fe5 | 7 years ago |
Koncord | 91398c5dcc | 7 years ago |
Koncord | aa183e6844 | 7 years ago |
Koncord | c55f0f73b8 | 7 years ago |
David Cernat | 85a9181c12 | 7 years ago |
Koncord | 94f3eaa980 | 7 years ago |
David Cernat | 456bcee68a | 7 years ago |
David Cernat | cfb5835e17 | 7 years ago |
Koncord | cd03d59056 | 7 years ago |
David Cernat | 2bc79fcdf4 | 7 years ago |
David Cernat | c2f330d4f1 | 7 years ago |
David Cernat | fc5e883160 | 7 years ago |
David Cernat | 993cc3dfd6 | 7 years ago |
David Cernat | d1ad0c91f8 | 7 years ago |
David Cernat | 7e322f1f8b | 7 years ago |
David Cernat | bd9e8bd10f | 7 years ago |
David Cernat | 711bdf187a | 7 years ago |
David Cernat | 720ef5f6c5 | 7 years ago |
David Cernat | eff3504b05 | 7 years ago |
Koncord | b55bb445dd | 7 years ago |
Koncord | a546d99000 | 7 years ago |
Koncord | 1841562553 | 7 years ago |
Koncord | 744b8cf168 | 7 years ago |
Koncord | e44fcdc0b3 | 7 years ago |
David Cernat | 901fe72471 | 7 years ago |
David Cernat | a796f81444 | 7 years ago |
Koncord | 46d55816b8 | 7 years ago |
Koncord | 4ebfcc4a21 | 7 years ago |
Koncord | 729f6e745e | 7 years ago |
Koncord | fef3764eb1 | 7 years ago |
Koncord | 382f56178c | 7 years ago |
Koncord | e657934cef | 7 years ago |
Koncord | c276ff4bd9 | 7 years ago |
David Cernat | 0a35b897be | 7 years ago |
David Cernat | b0965f094a | 7 years ago |
David Cernat | ef79a98544 | 7 years ago |
David Cernat | 64b57983f0 | 7 years ago |
David Cernat | 606ddff813 | 7 years ago |
David Cernat | cac4684986 | 7 years ago |
David Cernat | 07d75abdf8 | 7 years ago |
David Cernat | 1ee460bba8 | 7 years ago |
David Cernat | d33254f287 | 7 years ago |
David Cernat | 010a80ceca | 7 years ago |
David Cernat | 947b3f76be | 7 years ago |
David Cernat | 6f822f54aa | 7 years ago |
David Cernat | a3e2ab4d4e | 7 years ago |
David Cernat | 4cc0216e0a | 7 years ago |
David Cernat | 80be664139 | 7 years ago |
David Cernat | 57a0415ba3 | 7 years ago |
David Cernat | 494b10b97e | 7 years ago |
David Cernat | ba161ddddd | 7 years ago |
David Cernat | 7788821a69 | 7 years ago |
David Cernat | 068f733d1e | 7 years ago |
David Cernat | 1272b03f25 | 7 years ago |
David Cernat | b4e8560698 | 7 years ago |
David Cernat | 926106cf8c | 7 years ago |
David Cernat | ac7a588632 | 7 years ago |
David Cernat | a21f5d18d6 | 7 years ago |
David Cernat | a8261bb385 | 7 years ago |
David Cernat | 700e4d032e | 7 years ago |
David Cernat | 4dbada69bf | 7 years ago |
Koncord | ca7f3f7450 | 7 years ago |
Koncord | 64b531aa3c | 7 years ago |
Koncord | f377164db9 | 7 years ago |
Koncord | 7ab01b66e4 | 7 years ago |
Koncord | d15c674584 | 7 years ago |
Koncord | 0da44f69ad | 7 years ago |
Koncord | 062d6a1824 | 7 years ago |
David Cernat | 29cb51cdce | 7 years ago |
Koncord | 1d111fdca8 | 7 years ago |
Koncord | bd7082f57e | 7 years ago |
David Cernat | 71c921faa7 | 7 years ago |
David Cernat | 5653d07c7b | 7 years ago |
Koncord | 948090676a | 7 years ago |
David Cernat | 61db22f5ae | 7 years ago |
David Cernat | b7e5e77166 | 7 years ago |
David Cernat | 378d30834b | 7 years ago |
Koncord | 14d47213ef | 7 years ago |
Koncord | 3495fd43f4 | 7 years ago |
Koncord | e7a5919477 | 7 years ago |
Koncord | 1aa630e4a9 | 7 years ago |
Koncord | e8915f8ec5 | 7 years ago |
Koncord | 14fdec2478 | 7 years ago |
David Cernat | b801cf2c9e | 7 years ago |
David Cernat | 878294e4fe | 7 years ago |
Koncord | d44848ecbb | 7 years ago |
Koncord | 05abb8ace3 | 7 years ago |
Koncord | 04a844a9c0 | 7 years ago |
Koncord | dad0b38f25 | 7 years ago |
Koncord | a3d5fbbdcd | 7 years ago |
Koncord | 916ada108f | 7 years ago |
David Cernat | bece095579 | 7 years ago |
David Cernat | d6dc75e94b | 7 years ago |
David Cernat | 76a4abd7c0 | 7 years ago |
David Cernat | 0e73571111 | 7 years ago |
David Cernat | 8a93631e08 | 7 years ago |
Koncord | ba8613a179 | 7 years ago |
David Cernat | fb67180809 | 7 years ago |
Koncord | 4530370e52 | 7 years ago |
Koncord | ce6a4e4032 | 7 years ago |
Koncord | fc3f2483ee | 7 years ago |
Koncord | dffd3bfa7d | 7 years ago |
Koncord | 7a0b45d456 | 7 years ago |
Koncord | 66283943c5 | 7 years ago |
Koncord | d702845026 | 7 years ago |
Koncord | 0a0c9893b1 | 7 years ago |
David Cernat | 6e7c033a5d | 7 years ago |
David Cernat | bbac26294f | 7 years ago |
David Cernat | b20df4b7cd | 7 years ago |
David Cernat | 17a8e32782 | 7 years ago |
Koncord | 1fd16ba69c | 7 years ago |
Koncord | 62588ce088 | 7 years ago |
Koncord | 6cb9c3c713 | 7 years ago |
Koncord | 3839a2dcfd | 7 years ago |
Koncord | ed75563a94 | 7 years ago |
Koncord | 01a5196a92 | 7 years ago |
Koncord | 15723adb9a | 7 years ago |
Koncord | 57353cdfff | 7 years ago |
David Cernat | fe9a3088bd | 7 years ago |
Koncord | 5c79e7106f | 7 years ago |
David Cernat | 4845599bda | 7 years ago |
David Cernat | 7a38a0b223 | 7 years ago |
Koncord | cbabc91b06 | 7 years ago |
Koncord | 846f83e3e4 | 7 years ago |
David Cernat | 841a4f90c1 | 7 years ago |
David Cernat | 3284769fef | 7 years ago |
David Cernat | b5ce3cebbc | 7 years ago |
Koncord | 73aa83aa03 | 7 years ago |
Koncord | 5fcdff843c | 7 years ago |
David Cernat | 76f1a61538 | 7 years ago |
David Cernat | d591180e99 | 7 years ago |
David Cernat | 381a5fabc4 | 7 years ago |
David Cernat | 9838cc680a | 7 years ago |
David Cernat | 98195b5e3c | 7 years ago |
Koncord | 3124e627cf | 7 years ago |
Koncord | c2286482ae | 7 years ago |
Koncord | f814ae795d | 7 years ago |
Koncord | 50ef9677fe | 7 years ago |
Koncord | 838e05521e | 7 years ago |
David Cernat | cccbe753d7 | 7 years ago |
Koncord | 6decd148e5 | 7 years ago |
Koncord | 045dc566ea | 7 years ago |
Koncord | bb183457a6 | 7 years ago |
Koncord | dc18916f46 | 7 years ago |
Koncord | f99dafbf51 | 7 years ago |
Koncord | aee6fb1265 | 7 years ago |
Koncord | d1388cdf84 | 7 years ago |
Koncord | b869fe0b76 | 7 years ago |
Koncord | 0e2817da88 | 7 years ago |
Koncord | fc8232f943 | 7 years ago |
Koncord | 26324c2578 | 7 years ago |
Koncord | 4e93905350 | 7 years ago |
Koncord | 510e657c93 | 7 years ago |
Koncord | 060ebe3d4a | 7 years ago |
Koncord | 1c0adc47ee | 7 years ago |
Koncord | 66fdba957b | 7 years ago |
Koncord | 1d16958910 | 7 years ago |
Koncord | b18c6dec9d | 7 years ago |
Koncord | 991a1fe8d8 | 7 years ago |
Koncord | 60fc0bedb8 | 7 years ago |
Koncord | 7717f9bece | 7 years ago |
Koncord | fe2dd1bad4 | 7 years ago |
Koncord | 2d0840cb3a | 7 years ago |
@ -1,3 +1,6 @@
|
|||||||
[submodule "extern/breakpad"]
|
[submodule "extern/breakpad"]
|
||||||
path = extern/breakpad
|
path = extern/breakpad
|
||||||
url = https://chromium.googlesource.com/breakpad/breakpad
|
url = https://chromium.googlesource.com/breakpad/breakpad
|
||||||
|
[submodule "extern/sol"]
|
||||||
|
path = extern/sol
|
||||||
|
url = https://github.com/ThePhD/sol2
|
||||||
|
@ -0,0 +1,198 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 31.03.18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Settings.hpp"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#include <apps/browser/netutils/QueryClient.hpp>
|
||||||
|
#include "MainWindow.hpp"
|
||||||
|
|
||||||
|
std::string loadSettings (Settings::Manager & settings, const std::string &cfgName)
|
||||||
|
{
|
||||||
|
Files::ConfigurationManager mCfgMgr;
|
||||||
|
// Create the settings manager and load default settings file
|
||||||
|
const std::string localdefault = (mCfgMgr.getLocalPath() / (cfgName + "-default.cfg")).string();
|
||||||
|
const std::string globaldefault = (mCfgMgr.getGlobalPath() / (cfgName + "-default.cfg")).string();
|
||||||
|
|
||||||
|
// prefer local
|
||||||
|
if (boost::filesystem::exists(localdefault))
|
||||||
|
settings.loadDefault(localdefault);
|
||||||
|
else if (boost::filesystem::exists(globaldefault))
|
||||||
|
settings.loadDefault(globaldefault);
|
||||||
|
else
|
||||||
|
throw std::runtime_error ("No default settings file found! Make sure the file \"" + cfgName + "-default.cfg\" was properly installed.");
|
||||||
|
|
||||||
|
// load user settings if they exist
|
||||||
|
const std::string settingspath = (mCfgMgr.getUserConfigPath() / (cfgName + ".cfg")).string();
|
||||||
|
if (boost::filesystem::exists(settingspath))
|
||||||
|
settings.loadUser(settingspath);
|
||||||
|
|
||||||
|
return settingspath;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsMgr::SettingsMgr()
|
||||||
|
{
|
||||||
|
clientCfg = loadSettings(clientMgr, "tes3mp-client");
|
||||||
|
switchMgr();
|
||||||
|
serverCfg = loadSettings(serverMgr, "tes3mp-server");
|
||||||
|
switchMgr();
|
||||||
|
|
||||||
|
std::string addr = clientMgr.getString("address", "Master");
|
||||||
|
int port = clientMgr.getInt("port", "Master");
|
||||||
|
QueryClient::Get().SetServer(addr, port);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::loadBrowserSettings(Ui::MainWindow &mw)
|
||||||
|
{
|
||||||
|
mw.comboLatency->setCurrentIndex(clientMgr.getInt("maxLatency", "Browser"));
|
||||||
|
mw.leGamemode->setText(QString::fromStdString(clientMgr.getString("gameMode", "Browser")));
|
||||||
|
mw.cBoxNotFull->setCheckState(clientMgr.getBool("notFull", "Browser") ? Qt::Checked : Qt::Unchecked);
|
||||||
|
mw.cBoxWithPlayers->setCheckState(clientMgr.getBool("withPlayers", "Browser") ? Qt::Checked : Qt::Unchecked);
|
||||||
|
mw.cBBoxWOPass->setCheckState(clientMgr.getBool("noPassword", "Browser") ? Qt::Checked : Qt::Unchecked);
|
||||||
|
|
||||||
|
mw.tblServerBrowser->sortByColumn(clientMgr.getInt("sortByCol", "Browser"),
|
||||||
|
clientMgr.getBool("sortByColAscending", "Browser") ? Qt::AscendingOrder : Qt::DescendingOrder);
|
||||||
|
|
||||||
|
loadClientSettings(mw);
|
||||||
|
switchMgr();
|
||||||
|
loadServerSettings(mw);
|
||||||
|
switchMgr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::saveBrowserSettings(Ui::MainWindow &mw)
|
||||||
|
{
|
||||||
|
clientMgr.setInt("maxLatency", "Browser", mw.comboLatency->currentIndex());
|
||||||
|
clientMgr.setString("gameMode", "Browser", mw.leGamemode->text().toStdString());
|
||||||
|
clientMgr.setBool("notFull", "Browser", mw.cBoxNotFull->checkState() == Qt::Checked);
|
||||||
|
clientMgr.setBool("withPlayers", "Browser", mw.cBoxWithPlayers->checkState() == Qt::Checked);
|
||||||
|
clientMgr.setBool("noPassword", "Browser", mw.cBBoxWOPass->checkState() == Qt::Checked);
|
||||||
|
|
||||||
|
clientMgr.setInt("sortByCol", "Browser", mw.tblServerBrowser->horizontalHeader()->sortIndicatorSection());
|
||||||
|
clientMgr.setBool("sortByColAscending", "Browser", mw.tblServerBrowser->horizontalHeader()->sortIndicatorOrder() == Qt::AscendingOrder);
|
||||||
|
|
||||||
|
saveClientSettings(mw);
|
||||||
|
|
||||||
|
clientMgr.saveUser(clientCfg);
|
||||||
|
switchMgr();
|
||||||
|
saveServerSettings(mw);
|
||||||
|
switchMgr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::loadClientSettings(Ui::MainWindow &mw)
|
||||||
|
{
|
||||||
|
mw.leClientAddress->setText(QString::fromStdString(clientMgr.getString("destinationAddress", "General")));
|
||||||
|
mw.leClientPort->setText(QString::fromStdString(clientMgr.getString("port", "General")));
|
||||||
|
mw.leClientPassword->setText(QString::fromStdString(clientMgr.getString("password", "General")));
|
||||||
|
mw.combLoglevel->setCurrentIndex(clientMgr.getInt("logLevel", "General"));
|
||||||
|
|
||||||
|
mw.leClientMAddress->setText(QString::fromStdString(clientMgr.getString("address", "Master")));
|
||||||
|
mw.leClientMPort->setText(QString::fromStdString(clientMgr.getString("port", "Master")));
|
||||||
|
|
||||||
|
mw.pbChatKey->setText(QString::fromStdString(clientMgr.getString("keySay", "Chat")));
|
||||||
|
mw.pbModeKey->setText(QString::fromStdString(clientMgr.getString("keyChatMode", "Chat")));
|
||||||
|
|
||||||
|
mw.sbPosX->setValue(clientMgr.getInt("x", "Chat"));
|
||||||
|
mw.sbPosY->setValue(clientMgr.getInt("y", "Chat"));
|
||||||
|
mw.sbPosW->setValue(clientMgr.getInt("w", "Chat"));
|
||||||
|
mw.sbPosH->setValue(clientMgr.getInt("h", "Chat"));
|
||||||
|
|
||||||
|
mw.sbDelay->setValue(clientMgr.getFloat("delay", "Chat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::saveClientSettings(Ui::MainWindow &mw)
|
||||||
|
{
|
||||||
|
clientMgr.setString("destinationAddress", "General", mw.leClientAddress->text().toStdString());
|
||||||
|
clientMgr.setString("port", "General", mw.leClientPort->text().toStdString());
|
||||||
|
clientMgr.setString("password", "General", mw.leClientPassword->text().toStdString());
|
||||||
|
clientMgr.setInt("logLevel", "General", mw.combLoglevel->currentIndex());
|
||||||
|
|
||||||
|
clientMgr.setString("address", "Master", mw.leClientMAddress->text().toStdString());
|
||||||
|
clientMgr.setString("port", "Master", mw.leClientMPort->text().toStdString());
|
||||||
|
|
||||||
|
clientMgr.setString("keySay", "Chat", mw.pbChatKey->text().toStdString());
|
||||||
|
clientMgr.setString("keyChatMode", "Chat", mw.pbModeKey->text().toStdString());
|
||||||
|
|
||||||
|
clientMgr.setInt("x", "Chat", mw.sbPosX->value());
|
||||||
|
clientMgr.setInt("y", "Chat", mw.sbPosY->value());
|
||||||
|
clientMgr.setInt("w", "Chat", mw.sbPosW->value());
|
||||||
|
clientMgr.setInt("h", "Chat", mw.sbPosH->value());
|
||||||
|
|
||||||
|
clientMgr.setFloat("delay", "Chat", mw.sbDelay->value());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::loadServerSettings(Ui::MainWindow &mw)
|
||||||
|
{
|
||||||
|
mw.leServerAddress->setText(QString::fromStdString(serverMgr.getString("localAddress", "General")));
|
||||||
|
mw.leServerPort->setText(QString::fromStdString(serverMgr.getString("port", "General")));
|
||||||
|
mw.sbMaxPlayers->setValue(serverMgr.getInt("maximumPlayers", "General"));
|
||||||
|
mw.leHostname->setText(QString::fromStdString(serverMgr.getString("hostname", "General")));
|
||||||
|
mw.combServerLoglevel->setCurrentIndex(serverMgr.getInt("logLevel", "General"));
|
||||||
|
mw.leServerPassword->setText(QString::fromStdString(serverMgr.getString("password", "General")));
|
||||||
|
|
||||||
|
mw.chbMSenabled->setCheckState(serverMgr.getBool("enabled", "MasterServer") ? Qt::Checked : Qt::Unchecked);
|
||||||
|
mw.leServerMaddress->setText(QString::fromStdString(serverMgr.getString("address", "MasterServer")));
|
||||||
|
mw.leServerMPort->setText(QString::fromStdString(serverMgr.getString("port", "MasterServer")));
|
||||||
|
mw.sbRate->setValue(serverMgr.getInt("rate", "MasterServer"));
|
||||||
|
|
||||||
|
#ifndef TES3MP_PRE07
|
||||||
|
mw.leModulePath->setText(QString::fromStdString(serverMgr.getString("home", "Modules")));
|
||||||
|
mw.chbAutosort->setCheckState(serverMgr.getBool("autoSort", "Modules") ? Qt::Checked : Qt::Unchecked);
|
||||||
|
#else
|
||||||
|
mw.leModulePath->setText(QString::fromStdString(serverMgr.getString("home", "Plugins")));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::saveServerSettings(Ui::MainWindow &mw)
|
||||||
|
{
|
||||||
|
serverMgr.setString("localAddress", "General", mw.leServerAddress->text().toStdString());
|
||||||
|
serverMgr.setString("port", "General", mw.leServerPort->text().toStdString());
|
||||||
|
serverMgr.setInt("maximumPlayers", "General", mw.sbMaxPlayers->value());
|
||||||
|
serverMgr.setString("hostname", "General", mw.leHostname->text().toStdString());
|
||||||
|
serverMgr.setInt("logLevel", "General", mw.combServerLoglevel->currentIndex());
|
||||||
|
serverMgr.setString("password", "General", mw.leServerPassword->text().toStdString());
|
||||||
|
|
||||||
|
serverMgr.setBool("enabled", "MasterServer", mw.chbMSenabled->checkState() == Qt::Checked);
|
||||||
|
serverMgr.setString("address", "MasterServer", mw.leServerMaddress->text().toStdString());
|
||||||
|
serverMgr.setString("port", "MasterServer", mw.leServerMPort->text().toStdString());
|
||||||
|
serverMgr.setInt("rate", "MasterServer", mw.sbRate->value());
|
||||||
|
|
||||||
|
#ifndef TES3MP_PRE07
|
||||||
|
serverMgr.setString("home", "Modules", mw.leModulePath->text().toStdString());
|
||||||
|
serverMgr.setBool("autoSort", "Modules", mw.chbAutosort->checkState() == Qt::Checked);
|
||||||
|
#else
|
||||||
|
serverMgr.setString("home", "Plugins", mw.leModulePath->text().toStdString());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
serverMgr.saveUser(serverCfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsMgr::switchMgr()
|
||||||
|
{
|
||||||
|
static Settings::CategorySettingValueMap saveUserSettings;
|
||||||
|
static Settings::CategorySettingValueMap saveDefaultSettings;
|
||||||
|
static Settings::CategorySettingVector saveChangedSettings;
|
||||||
|
static bool currentMgrIsClient = true;
|
||||||
|
|
||||||
|
if(!currentMgrIsClient)
|
||||||
|
{
|
||||||
|
saveUserSettings.swap(clientMgr.mUserSettings);
|
||||||
|
saveDefaultSettings.swap(clientMgr.mDefaultSettings);
|
||||||
|
saveChangedSettings.swap(clientMgr.mChangedSettings);
|
||||||
|
|
||||||
|
qDebug() << "Manager switched to Client config";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saveUserSettings.swap(serverMgr.mUserSettings);
|
||||||
|
saveDefaultSettings.swap(serverMgr.mDefaultSettings);
|
||||||
|
saveChangedSettings.swap(serverMgr.mChangedSettings);
|
||||||
|
|
||||||
|
qDebug() << "Manager switched to Server config";
|
||||||
|
}
|
||||||
|
currentMgrIsClient = !currentMgrIsClient;
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 31.03.18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SettingsMgr();
|
||||||
|
|
||||||
|
void loadBrowserSettings(Ui::MainWindow &mw);
|
||||||
|
void saveBrowserSettings(Ui::MainWindow &mw);
|
||||||
|
|
||||||
|
void loadClientSettings(Ui::MainWindow &mw);
|
||||||
|
void saveClientSettings(Ui::MainWindow &mw);
|
||||||
|
|
||||||
|
void loadServerSettings(Ui::MainWindow &mw);
|
||||||
|
void saveServerSettings(Ui::MainWindow &mw);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Settings::Manager serverMgr, clientMgr;
|
||||||
|
std::string serverCfg, clientCfg;
|
||||||
|
void switchMgr();
|
||||||
|
};
|
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 04.09.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AdminRest.hpp"
|
||||||
|
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
|
#include "RestUtils.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace chrono;
|
||||||
|
using namespace boost::property_tree;
|
||||||
|
|
||||||
|
|
||||||
|
AdminRest::AdminRest(const std::string &cert, const std::string &key, const std::string &verifyFile,
|
||||||
|
unsigned short port, std::shared_ptr<MasterServer> master) : httpServer(cert, key, verifyFile), master(master)
|
||||||
|
{
|
||||||
|
httpServer.config.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdminRest::start()
|
||||||
|
{
|
||||||
|
static const string AdminArea = "^/api/admin?";
|
||||||
|
|
||||||
|
httpServer.resource[AdminArea]["POST"] = [this](auto response, auto request) {
|
||||||
|
cout << request->method << endl;
|
||||||
|
cout << request->path << endl;
|
||||||
|
cout << request->http_version << endl;
|
||||||
|
|
||||||
|
for (auto &header : request->header)
|
||||||
|
cout << header.first << ": " << header.second << endl;
|
||||||
|
|
||||||
|
string resp;
|
||||||
|
master->luaStuff([&request, &response, &resp](sol::state &state) {
|
||||||
|
sol::protected_function func = state["OnAdminRequest"];
|
||||||
|
|
||||||
|
sol::protected_function_result result = func.call(request->remote_endpoint_address, request->content.string());
|
||||||
|
if (result.valid())
|
||||||
|
*response << result.get<string>();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cerr << "Error: " << result.get<string>() << endl;
|
||||||
|
*response << response500;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*httpServer.on_error = [](auto request, const boost::system::error_code& err)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: " << err.message() << " " << err.category().name() << std::endl;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
httpServer.default_resource["GET"] = [](auto response, auto /*request*/) {
|
||||||
|
cout << "Default request" << endl;
|
||||||
|
*response << response400;
|
||||||
|
};
|
||||||
|
|
||||||
|
thr = thread([this](){httpServer.start();});
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdminRest::stop()
|
||||||
|
{
|
||||||
|
httpServer.stop();
|
||||||
|
if(thr.joinable())
|
||||||
|
thr.join();
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 04.09.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SimpleWeb/https_server.hpp"
|
||||||
|
#include "MasterServer.hpp"
|
||||||
|
|
||||||
|
typedef SimpleWeb::Server<SimpleWeb::HTTPS> HttpsServer;
|
||||||
|
|
||||||
|
class AdminRest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AdminRest(const std::string &cert, const std::string &key, const std::string &verifyFile, unsigned short port, std::shared_ptr<MasterServer> master);
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HttpsServer httpServer;
|
||||||
|
std::shared_ptr<MasterServer> master;
|
||||||
|
std::thread thr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 04.09.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "SimpleWeb/base_server.hpp"
|
||||||
|
|
||||||
|
static std::string response201 = "HTTP/1.1 201 Created\r\nContent-Length: 7\r\n\r\nCreated";
|
||||||
|
static std::string response202 = "HTTP/1.1 202 Accepted\r\nContent-Length: 8\r\n\r\nAccepted";
|
||||||
|
static std::string response400 = "HTTP/1.1 400 Bad Request\r\nContent-Length: 11\r\n\r\nbad request";
|
||||||
|
|
||||||
|
static std::string response403 = "HTTP/1.1 403 Forbidden\r\nContent-Length: 9\r\n\r\nForbidden";
|
||||||
|
static std::string response500 = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 21\r\n\r\nInternal Server Error";
|
||||||
|
|
||||||
|
template <class Protocol>
|
||||||
|
inline void ResponseStr(std::shared_ptr<typename SimpleWeb::ServerBase<Protocol>::Response> response,
|
||||||
|
std::string content, std::string type = "", std::string code = "200 OK")
|
||||||
|
{
|
||||||
|
*response << "HTTP/1.1 " << code << "\r\n";
|
||||||
|
if (!type.empty())
|
||||||
|
*response << "Content-Type: " << type <<"\r\n";
|
||||||
|
*response << "Content-Length: " << content.length() << "\r\n\r\n" << content;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014-2016 Ole Christian Eidheim
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -1,55 +1,42 @@
|
|||||||
/*
|
#pragma once
|
||||||
* https://github.com/eidheim/Simple-Web-Server/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
* Copyright (c) 2014-2016 Ole Christian Eidheim
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERVER_HTTP_HPP
|
|
||||||
#define SERVER_HTTP_HPP
|
|
||||||
|
|
||||||
#include "base_server.hpp"
|
#include "base_server.hpp"
|
||||||
|
|
||||||
namespace SimpleWeb
|
namespace SimpleWeb {
|
||||||
{
|
|
||||||
|
|
||||||
template <class socket_type>
|
template <class socket_type>
|
||||||
class Server : public ServerBase<socket_type> {};
|
class Server : public ServerBase<socket_type> {};
|
||||||
|
|
||||||
typedef boost::asio::ip::tcp::socket HTTP;
|
using HTTP = asio::ip::tcp::socket;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class Server<HTTP> : public ServerBase<HTTP>
|
class Server<HTTP> : public ServerBase<HTTP> {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Server() : ServerBase<HTTP>::ServerBase(80)
|
Server() noexcept : ServerBase<HTTP>::ServerBase(80) {}
|
||||||
{}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void accept()
|
void accept() override {
|
||||||
{
|
auto session = std::make_shared<Session>(create_connection(*io_service));
|
||||||
//Create new socket for this connection
|
|
||||||
//Shared_ptr is used to pass temporary objects to the asynchronous functions
|
acceptor->async_accept(*session->connection->socket, [this, session](const error_code &ec) {
|
||||||
auto socket = std::make_shared<HTTP>(*io_service);
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
|
if(!lock)
|
||||||
acceptor->async_accept(*socket, [this, socket](const boost::system::error_code &ec)
|
return;
|
||||||
{
|
|
||||||
//Immediately start accepting a new connection (if io_service hasn't been stopped)
|
// Immediately start accepting a new connection (unless io_service has been stopped)
|
||||||
if (ec != boost::asio::error::operation_aborted)
|
if(ec != asio::error::operation_aborted)
|
||||||
accept();
|
this->accept();
|
||||||
|
|
||||||
if (!ec)
|
if(!ec) {
|
||||||
{
|
asio::ip::tcp::no_delay option(true);
|
||||||
boost::asio::ip::tcp::no_delay option(true);
|
error_code ec;
|
||||||
socket->set_option(option);
|
session->connection->socket->set_option(option, ec);
|
||||||
|
|
||||||
this->read_request_and_content(socket);
|
this->read_request_and_content(session);
|
||||||
}
|
}
|
||||||
else if (on_error)
|
else if(this->on_error)
|
||||||
on_error(std::shared_ptr<Request>(new Request(*socket)), ec);
|
this->on_error(session->request, ec);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace SimpleWeb
|
||||||
|
|
||||||
#endif //SERVER_HTTP_HPP
|
|
||||||
|
@ -1,91 +1,82 @@
|
|||||||
#ifndef HTTPS_SERVER_HPP
|
#pragma once
|
||||||
#define HTTPS_SERVER_HPP
|
|
||||||
|
|
||||||
#include "base_server.hpp"
|
#include "base_server.hpp"
|
||||||
|
|
||||||
|
#ifdef USE_STANDALONE_ASIO
|
||||||
|
#include <asio/ssl.hpp>
|
||||||
|
#else
|
||||||
#include <boost/asio/ssl.hpp>
|
#include <boost/asio/ssl.hpp>
|
||||||
#include <openssl/ssl.h>
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
namespace SimpleWeb
|
namespace SimpleWeb {
|
||||||
{
|
using HTTPS = asio::ssl::stream<asio::ip::tcp::socket>;
|
||||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> HTTPS;
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class Server<HTTPS> : public ServerBase<HTTPS>
|
class Server<HTTPS> : public ServerBase<HTTPS> {
|
||||||
{
|
|
||||||
std::string session_id_context;
|
std::string session_id_context;
|
||||||
bool set_session_id_context = false;
|
bool set_session_id_context = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Server(const std::string &cert_file, const std::string &private_key_file,
|
Server(const std::string &cert_file, const std::string &private_key_file, const std::string &verify_file = std::string())
|
||||||
const std::string &verify_file = std::string()) : ServerBase<HTTPS>::ServerBase(443),
|
: ServerBase<HTTPS>::ServerBase(443), context(asio::ssl::context::tlsv12) {
|
||||||
context(boost::asio::ssl::context::tlsv12)
|
|
||||||
{
|
|
||||||
context.use_certificate_chain_file(cert_file);
|
context.use_certificate_chain_file(cert_file);
|
||||||
context.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);
|
context.use_private_key_file(private_key_file, asio::ssl::context::pem);
|
||||||
|
|
||||||
if (verify_file.size() > 0)
|
if(verify_file.size() > 0) {
|
||||||
{
|
|
||||||
context.load_verify_file(verify_file);
|
context.load_verify_file(verify_file);
|
||||||
context.set_verify_mode(boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert |
|
context.set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert | asio::ssl::verify_client_once);
|
||||||
boost::asio::ssl::verify_client_once);
|
|
||||||
set_session_id_context = true;
|
set_session_id_context = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void start()
|
void start() override {
|
||||||
{
|
if(set_session_id_context) {
|
||||||
if (set_session_id_context)
|
|
||||||
{
|
|
||||||
// Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH
|
// Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH
|
||||||
session_id_context = std::to_string(config.port) + ':';
|
session_id_context = std::to_string(config.port) + ':';
|
||||||
session_id_context.append(config.address.rbegin(), config.address.rend());
|
session_id_context.append(config.address.rbegin(), config.address.rend());
|
||||||
SSL_CTX_set_session_id_context(context.native_handle(),
|
SSL_CTX_set_session_id_context(context.native_handle(), reinterpret_cast<const unsigned char *>(session_id_context.data()),
|
||||||
reinterpret_cast<const unsigned char *>(session_id_context.data()),
|
std::min<size_t>(session_id_context.size(), SSL_MAX_SSL_SESSION_ID_LENGTH));
|
||||||
std::min<size_t>(session_id_context.size(),
|
|
||||||
SSL_MAX_SSL_SESSION_ID_LENGTH));
|
|
||||||
}
|
}
|
||||||
ServerBase::start();
|
ServerBase::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::asio::ssl::context context;
|
asio::ssl::context context;
|
||||||
|
|
||||||
virtual void accept()
|
void accept() override {
|
||||||
{
|
auto session = std::make_shared<Session>(create_connection(*io_service, context));
|
||||||
//Create new socket for this connection
|
|
||||||
//Shared_ptr is used to pass temporary objects to the asynchronous functions
|
|
||||||
auto socket = std::make_shared<HTTPS>(*io_service, context);
|
|
||||||
|
|
||||||
acceptor->async_accept((*socket).lowest_layer(), [this, socket](const boost::system::error_code &ec)
|
acceptor->async_accept(session->connection->socket->lowest_layer(), [this, session](const error_code &ec) {
|
||||||
{
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
//Immediately start accepting a new connection (if io_service hasn't been stopped)
|
if(!lock)
|
||||||
if (ec != boost::asio::error::operation_aborted)
|
return;
|
||||||
accept();
|
|
||||||
|
|
||||||
|
if(ec != asio::error::operation_aborted)
|
||||||
|
this->accept();
|
||||||
|
|
||||||
if (!ec)
|
if(!ec) {
|
||||||
{
|
asio::ip::tcp::no_delay option(true);
|
||||||
boost::asio::ip::tcp::no_delay option(true);
|
error_code ec;
|
||||||
socket->lowest_layer().set_option(option);
|
session->connection->socket->lowest_layer().set_option(option, ec);
|
||||||
|
|
||||||
//Set timeout on the following boost::asio::ssl::stream::async_handshake
|
session->connection->set_timeout(config.timeout_request);
|
||||||
auto timer = get_timeout_timer(socket, config.timeout_request);
|
session->connection->socket->async_handshake(asio::ssl::stream_base::server, [this, session](const error_code &ec) {
|
||||||
socket->async_handshake(boost::asio::ssl::stream_base::server, [this, socket, timer]
|
session->connection->cancel_timeout();
|
||||||
(const boost::system::error_code &ec)
|
auto lock = session->connection->handler_runner->continue_lock();
|
||||||
{
|
if(!lock)
|
||||||
if (timer)
|
return;
|
||||||
timer->cancel();
|
|
||||||
if(!ec)
|
if(!ec)
|
||||||
read_request_and_content(socket);
|
this->read_request_and_content(session);
|
||||||
else if (on_error)
|
else if(this->on_error)
|
||||||
on_error(std::shared_ptr<Request>(new Request(*socket)), ec);
|
this->on_error(session->request, ec);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (on_error)
|
else if(this->on_error)
|
||||||
on_error(std::shared_ptr<Request>(new Request(*socket)), ec);
|
this->on_error(session->request, ec);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace SimpleWeb
|
||||||
|
|
||||||
#endif //HTTPS_SERVER_HPP
|
|
||||||
|
@ -0,0 +1,154 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace SimpleWeb {
|
||||||
|
enum class StatusCode {
|
||||||
|
unknown = 0,
|
||||||
|
information_continue = 100,
|
||||||
|
information_switching_protocols,
|
||||||
|
information_processing,
|
||||||
|
success_ok = 200,
|
||||||
|
success_created,
|
||||||
|
success_accepted,
|
||||||
|
success_non_authoritative_information,
|
||||||
|
success_no_content,
|
||||||
|
success_reset_content,
|
||||||
|
success_partial_content,
|
||||||
|
success_multi_status,
|
||||||
|
success_already_reported,
|
||||||
|
success_im_used = 226,
|
||||||
|
redirection_multiple_choices = 300,
|
||||||
|
redirection_moved_permanently,
|
||||||
|
redirection_found,
|
||||||
|
redirection_see_other,
|
||||||
|
redirection_not_modified,
|
||||||
|
redirection_use_proxy,
|
||||||
|
redirection_switch_proxy,
|
||||||
|
redirection_temporary_redirect,
|
||||||
|
redirection_permanent_redirect,
|
||||||
|
client_error_bad_request = 400,
|
||||||
|
client_error_unauthorized,
|
||||||
|
client_error_payment_required,
|
||||||
|
client_error_forbidden,
|
||||||
|
client_error_not_found,
|
||||||
|
client_error_method_not_allowed,
|
||||||
|
client_error_not_acceptable,
|
||||||
|
client_error_proxy_authentication_required,
|
||||||
|
client_error_request_timeout,
|
||||||
|
client_error_conflict,
|
||||||
|
client_error_gone,
|
||||||
|
client_error_length_required,
|
||||||
|
client_error_precondition_failed,
|
||||||
|
client_error_payload_too_large,
|
||||||
|
client_error_uri_too_long,
|
||||||
|
client_error_unsupported_media_type,
|
||||||
|
client_error_range_not_satisfiable,
|
||||||
|
client_error_expectation_failed,
|
||||||
|
client_error_im_a_teapot,
|
||||||
|
client_error_misdirection_required = 421,
|
||||||
|
client_error_unprocessable_entity,
|
||||||
|
client_error_locked,
|
||||||
|
client_error_failed_dependency,
|
||||||
|
client_error_upgrade_required = 426,
|
||||||
|
client_error_precondition_required = 428,
|
||||||
|
client_error_too_many_requests,
|
||||||
|
client_error_request_header_fields_too_large = 431,
|
||||||
|
client_error_unavailable_for_legal_reasons = 451,
|
||||||
|
server_error_internal_server_error = 500,
|
||||||
|
server_error_not_implemented,
|
||||||
|
server_error_bad_gateway,
|
||||||
|
server_error_service_unavailable,
|
||||||
|
server_error_gateway_timeout,
|
||||||
|
server_error_http_version_not_supported,
|
||||||
|
server_error_variant_also_negotiates,
|
||||||
|
server_error_insufficient_storage,
|
||||||
|
server_error_loop_detected,
|
||||||
|
server_error_not_extended = 510,
|
||||||
|
server_error_network_authentication_required
|
||||||
|
};
|
||||||
|
|
||||||
|
const static std::vector<std::pair<StatusCode, std::string>> &status_codes() noexcept {
|
||||||
|
const static std::vector<std::pair<StatusCode, std::string>> status_codes = {
|
||||||
|
{StatusCode::unknown, ""},
|
||||||
|
{StatusCode::information_continue, "100 Continue"},
|
||||||
|
{StatusCode::information_switching_protocols, "101 Switching Protocols"},
|
||||||
|
{StatusCode::information_processing, "102 Processing"},
|
||||||
|
{StatusCode::success_ok, "200 OK"},
|
||||||
|
{StatusCode::success_created, "201 Created"},
|
||||||
|
{StatusCode::success_accepted, "202 Accepted"},
|
||||||
|
{StatusCode::success_non_authoritative_information, "203 Non-Authoritative Information"},
|
||||||
|
{StatusCode::success_no_content, "204 No Content"},
|
||||||
|
{StatusCode::success_reset_content, "205 Reset Content"},
|
||||||
|
{StatusCode::success_partial_content, "206 Partial Content"},
|
||||||
|
{StatusCode::success_multi_status, "207 Multi-Status"},
|
||||||
|
{StatusCode::success_already_reported, "208 Already Reported"},
|
||||||
|
{StatusCode::success_im_used, "226 IM Used"},
|
||||||
|
{StatusCode::redirection_multiple_choices, "300 Multiple Choices"},
|
||||||
|
{StatusCode::redirection_moved_permanently, "301 Moved Permanently"},
|
||||||
|
{StatusCode::redirection_found, "302 Found"},
|
||||||
|
{StatusCode::redirection_see_other, "303 See Other"},
|
||||||
|
{StatusCode::redirection_not_modified, "304 Not Modified"},
|
||||||
|
{StatusCode::redirection_use_proxy, "305 Use Proxy"},
|
||||||
|
{StatusCode::redirection_switch_proxy, "306 Switch Proxy"},
|
||||||
|
{StatusCode::redirection_temporary_redirect, "307 Temporary Redirect"},
|
||||||
|
{StatusCode::redirection_permanent_redirect, "308 Permanent Redirect"},
|
||||||
|
{StatusCode::client_error_bad_request, "400 Bad Request"},
|
||||||
|
{StatusCode::client_error_unauthorized, "401 Unauthorized"},
|
||||||
|
{StatusCode::client_error_payment_required, "402 Payment Required"},
|
||||||
|
{StatusCode::client_error_forbidden, "403 Forbidden"},
|
||||||
|
{StatusCode::client_error_not_found, "404 Not Found"},
|
||||||
|
{StatusCode::client_error_method_not_allowed, "405 Method Not Allowed"},
|
||||||
|
{StatusCode::client_error_not_acceptable, "406 Not Acceptable"},
|
||||||
|
{StatusCode::client_error_proxy_authentication_required, "407 Proxy Authentication Required"},
|
||||||
|
{StatusCode::client_error_request_timeout, "408 Request Timeout"},
|
||||||
|
{StatusCode::client_error_conflict, "409 Conflict"},
|
||||||
|
{StatusCode::client_error_gone, "410 Gone"},
|
||||||
|
{StatusCode::client_error_length_required, "411 Length Required"},
|
||||||
|
{StatusCode::client_error_precondition_failed, "412 Precondition Failed"},
|
||||||
|
{StatusCode::client_error_payload_too_large, "413 Payload Too Large"},
|
||||||
|
{StatusCode::client_error_uri_too_long, "414 URI Too Long"},
|
||||||
|
{StatusCode::client_error_unsupported_media_type, "415 Unsupported Media Type"},
|
||||||
|
{StatusCode::client_error_range_not_satisfiable, "416 Range Not Satisfiable"},
|
||||||
|
{StatusCode::client_error_expectation_failed, "417 Expectation Failed"},
|
||||||
|
{StatusCode::client_error_im_a_teapot, "418 I'm a teapot"},
|
||||||
|
{StatusCode::client_error_misdirection_required, "421 Misdirected Request"},
|
||||||
|
{StatusCode::client_error_unprocessable_entity, "422 Unprocessable Entity"},
|
||||||
|
{StatusCode::client_error_locked, "423 Locked"},
|
||||||
|
{StatusCode::client_error_failed_dependency, "424 Failed Dependency"},
|
||||||
|
{StatusCode::client_error_upgrade_required, "426 Upgrade Required"},
|
||||||
|
{StatusCode::client_error_precondition_required, "428 Precondition Required"},
|
||||||
|
{StatusCode::client_error_too_many_requests, "429 Too Many Requests"},
|
||||||
|
{StatusCode::client_error_request_header_fields_too_large, "431 Request Header Fields Too Large"},
|
||||||
|
{StatusCode::client_error_unavailable_for_legal_reasons, "451 Unavailable For Legal Reasons"},
|
||||||
|
{StatusCode::server_error_internal_server_error, "500 Internal Server Error"},
|
||||||
|
{StatusCode::server_error_not_implemented, "501 Not Implemented"},
|
||||||
|
{StatusCode::server_error_bad_gateway, "502 Bad Gateway"},
|
||||||
|
{StatusCode::server_error_service_unavailable, "503 Service Unavailable"},
|
||||||
|
{StatusCode::server_error_gateway_timeout, "504 Gateway Timeout"},
|
||||||
|
{StatusCode::server_error_http_version_not_supported, "505 HTTP Version Not Supported"},
|
||||||
|
{StatusCode::server_error_variant_also_negotiates, "506 Variant Also Negotiates"},
|
||||||
|
{StatusCode::server_error_insufficient_storage, "507 Insufficient Storage"},
|
||||||
|
{StatusCode::server_error_loop_detected, "508 Loop Detected"},
|
||||||
|
{StatusCode::server_error_not_extended, "510 Not Extended"},
|
||||||
|
{StatusCode::server_error_network_authentication_required, "511 Network Authentication Required"}};
|
||||||
|
return status_codes;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline StatusCode status_code(const std::string &status_code_str) noexcept {
|
||||||
|
for(auto &status_code : status_codes()) {
|
||||||
|
if(status_code.second == status_code_str)
|
||||||
|
return status_code.first;
|
||||||
|
}
|
||||||
|
return StatusCode::unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string &status_code(StatusCode status_code_enum) noexcept {
|
||||||
|
for(auto &status_code : status_codes()) {
|
||||||
|
if(status_code.first == status_code_enum)
|
||||||
|
return status_code.second;
|
||||||
|
}
|
||||||
|
return status_codes()[0].second;
|
||||||
|
}
|
||||||
|
} // namespace SimpleWeb
|
@ -0,0 +1,340 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "status_code.hpp"
|
||||||
|
#include <atomic>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace SimpleWeb {
|
||||||
|
inline bool case_insensitive_equal(const std::string &str1, const std::string &str2) noexcept {
|
||||||
|
return str1.size() == str2.size() &&
|
||||||
|
std::equal(str1.begin(), str1.end(), str2.begin(), [](char a, char b) {
|
||||||
|
return tolower(a) == tolower(b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
class CaseInsensitiveEqual {
|
||||||
|
public:
|
||||||
|
bool operator()(const std::string &str1, const std::string &str2) const noexcept {
|
||||||
|
return case_insensitive_equal(str1, str2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Based on https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x/2595226#2595226
|
||||||
|
class CaseInsensitiveHash {
|
||||||
|
public:
|
||||||
|
size_t operator()(const std::string &str) const noexcept {
|
||||||
|
size_t h = 0;
|
||||||
|
std::hash<int> hash;
|
||||||
|
for(auto c : str)
|
||||||
|
h ^= hash(tolower(c)) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using CaseInsensitiveMultimap = std::unordered_multimap<std::string, std::string, CaseInsensitiveHash, CaseInsensitiveEqual>;
|
||||||
|
|
||||||
|
/// Percent encoding and decoding
|
||||||
|
class Percent {
|
||||||
|
public:
|
||||||
|
/// Returns percent-encoded string
|
||||||
|
static std::string encode(const std::string &value) noexcept {
|
||||||
|
static auto hex_chars = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
result.reserve(value.size()); // Minimum size of result
|
||||||
|
|
||||||
|
for(auto &chr : value) {
|
||||||
|
if(chr == ' ')
|
||||||
|
result += '+';
|
||||||
|
else if(chr == '!' || chr == '#' || chr == '$' || (chr >= '&' && chr <= ',') || (chr >= '/' && chr <= ';') || chr == '=' || chr == '?' || chr == '@' || chr == '[' || chr == ']')
|
||||||
|
result += std::string("%") + hex_chars[chr >> 4] + hex_chars[chr & 15];
|
||||||
|
else
|
||||||
|
result += chr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns percent-decoded string
|
||||||
|
static std::string decode(const std::string &value) noexcept {
|
||||||
|
std::string result;
|
||||||
|
result.reserve(value.size() / 3 + (value.size() % 3)); // Minimum size of result
|
||||||
|
|
||||||
|
for(size_t i = 0; i < value.size(); ++i) {
|
||||||
|
auto &chr = value[i];
|
||||||
|
if(chr == '%' && i + 2 < value.size()) {
|
||||||
|
auto hex = value.substr(i + 1, 2);
|
||||||
|
auto decoded_chr = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
|
||||||
|
result += decoded_chr;
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
else if(chr == '+')
|
||||||
|
result += ' ';
|
||||||
|
else
|
||||||
|
result += chr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Query string creation and parsing
|
||||||
|
class QueryString {
|
||||||
|
public:
|
||||||
|
/// Returns query string created from given field names and values
|
||||||
|
static std::string create(const CaseInsensitiveMultimap &fields) noexcept {
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for(auto &field : fields) {
|
||||||
|
result += (!first ? "&" : "") + field.first + '=' + Percent::encode(field.second);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns query keys with percent-decoded values.
|
||||||
|
static CaseInsensitiveMultimap parse(const std::string &query_string) noexcept {
|
||||||
|
CaseInsensitiveMultimap result;
|
||||||
|
|
||||||
|
if(query_string.empty())
|
||||||
|
return result;
|
||||||
|
|
||||||
|
size_t name_pos = 0;
|
||||||
|
auto name_end_pos = std::string::npos;
|
||||||
|
auto value_pos = std::string::npos;
|
||||||
|
for(size_t c = 0; c < query_string.size(); ++c) {
|
||||||
|
if(query_string[c] == '&') {
|
||||||
|
auto name = query_string.substr(name_pos, (name_end_pos == std::string::npos ? c : name_end_pos) - name_pos);
|
||||||
|
if(!name.empty()) {
|
||||||
|
auto value = value_pos == std::string::npos ? std::string() : query_string.substr(value_pos, c - value_pos);
|
||||||
|
result.emplace(std::move(name), Percent::decode(value));
|
||||||
|
}
|
||||||
|
name_pos = c + 1;
|
||||||
|
name_end_pos = std::string::npos;
|
||||||
|
value_pos = std::string::npos;
|
||||||
|
}
|
||||||
|
else if(query_string[c] == '=') {
|
||||||
|
name_end_pos = c;
|
||||||
|
value_pos = c + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(name_pos < query_string.size()) {
|
||||||
|
auto name = query_string.substr(name_pos, name_end_pos - name_pos);
|
||||||
|
if(!name.empty()) {
|
||||||
|
auto value = value_pos >= query_string.size() ? std::string() : query_string.substr(value_pos);
|
||||||
|
result.emplace(std::move(name), Percent::decode(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HttpHeader {
|
||||||
|
public:
|
||||||
|
/// Parse header fields
|
||||||
|
static CaseInsensitiveMultimap parse(std::istream &stream) noexcept {
|
||||||
|
CaseInsensitiveMultimap result;
|
||||||
|
std::string line;
|
||||||
|
getline(stream, line);
|
||||||
|
size_t param_end;
|
||||||
|
while((param_end = line.find(':')) != std::string::npos) {
|
||||||
|
size_t value_start = param_end + 1;
|
||||||
|
if(value_start < line.size()) {
|
||||||
|
if(line[value_start] == ' ')
|
||||||
|
value_start++;
|
||||||
|
if(value_start < line.size())
|
||||||
|
result.emplace(line.substr(0, param_end), line.substr(value_start, line.size() - value_start - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
getline(stream, line);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RequestMessage {
|
||||||
|
public:
|
||||||
|
/// Parse request line and header fields
|
||||||
|
static bool parse(std::istream &stream, std::string &method, std::string &path, std::string &query_string, std::string &version, CaseInsensitiveMultimap &header) noexcept {
|
||||||
|
header.clear();
|
||||||
|
std::string line;
|
||||||
|
getline(stream, line);
|
||||||
|
size_t method_end;
|
||||||
|
if((method_end = line.find(' ')) != std::string::npos) {
|
||||||
|
method = line.substr(0, method_end);
|
||||||
|
|
||||||
|
size_t query_start = std::string::npos;
|
||||||
|
size_t path_and_query_string_end = std::string::npos;
|
||||||
|
for(size_t i = method_end + 1; i < line.size(); ++i) {
|
||||||
|
if(line[i] == '?' && (i + 1) < line.size())
|
||||||
|
query_start = i + 1;
|
||||||
|
else if(line[i] == ' ') {
|
||||||
|
path_and_query_string_end = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(path_and_query_string_end != std::string::npos) {
|
||||||
|
if(query_start != std::string::npos) {
|
||||||
|
path = line.substr(method_end + 1, query_start - method_end - 2);
|
||||||
|
query_string = line.substr(query_start, path_and_query_string_end - query_start);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
path = line.substr(method_end + 1, path_and_query_string_end - method_end - 1);
|
||||||
|
|
||||||
|
size_t protocol_end;
|
||||||
|
if((protocol_end = line.find('/', path_and_query_string_end + 1)) != std::string::npos) {
|
||||||
|
if(line.compare(path_and_query_string_end + 1, protocol_end - path_and_query_string_end - 1, "HTTP") != 0)
|
||||||
|
return false;
|
||||||
|
version = line.substr(protocol_end + 1, line.size() - protocol_end - 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
header = HttpHeader::parse(stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResponseMessage {
|
||||||
|
public:
|
||||||
|
/// Parse status line and header fields
|
||||||
|
static bool parse(std::istream &stream, std::string &version, std::string &status_code, CaseInsensitiveMultimap &header) noexcept {
|
||||||
|
header.clear();
|
||||||
|
std::string line;
|
||||||
|
getline(stream, line);
|
||||||
|
size_t version_end = line.find(' ');
|
||||||
|
if(version_end != std::string::npos) {
|
||||||
|
if(5 < line.size())
|
||||||
|
version = line.substr(5, version_end - 5);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
if((version_end + 1) < line.size())
|
||||||
|
status_code = line.substr(version_end + 1, line.size() - (version_end + 1) - 1);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
header = HttpHeader::parse(stream);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ContentDisposition {
|
||||||
|
public:
|
||||||
|
/// Can be used to parse the Content-Disposition header field value when
|
||||||
|
/// clients are posting requests with enctype="multipart/form-data"
|
||||||
|
static CaseInsensitiveMultimap parse(const std::string &line) {
|
||||||
|
CaseInsensitiveMultimap result;
|
||||||
|
|
||||||
|
size_t para_start_pos = 0;
|
||||||
|
size_t para_end_pos = std::string::npos;
|
||||||
|
size_t value_start_pos = std::string::npos;
|
||||||
|
for(size_t c = 0; c < line.size(); ++c) {
|
||||||
|
if(para_start_pos != std::string::npos) {
|
||||||
|
if(para_end_pos == std::string::npos) {
|
||||||
|
if(line[c] == ';') {
|
||||||
|
result.emplace(line.substr(para_start_pos, c - para_start_pos), std::string());
|
||||||
|
para_start_pos = std::string::npos;
|
||||||
|
}
|
||||||
|
else if(line[c] == '=')
|
||||||
|
para_end_pos = c;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(value_start_pos == std::string::npos) {
|
||||||
|
if(line[c] == '"' && c + 1 < line.size())
|
||||||
|
value_start_pos = c + 1;
|
||||||
|
}
|
||||||
|
else if(line[c] == '"') {
|
||||||
|
result.emplace(line.substr(para_start_pos, para_end_pos - para_start_pos), line.substr(value_start_pos, c - value_start_pos));
|
||||||
|
para_start_pos = std::string::npos;
|
||||||
|
para_end_pos = std::string::npos;
|
||||||
|
value_start_pos = std::string::npos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(line[c] != ' ' && line[c] != ';')
|
||||||
|
para_start_pos = c;
|
||||||
|
}
|
||||||
|
if(para_start_pos != std::string::npos && para_end_pos == std::string::npos)
|
||||||
|
result.emplace(line.substr(para_start_pos), std::string());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
#include <emmintrin.h>
|
||||||
|
namespace SimpleWeb {
|
||||||
|
inline void spin_loop_pause() noexcept { _mm_pause(); }
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
// TODO: need verification that the following checks are correct:
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1800 && (defined(_M_X64) || defined(_M_IX86))
|
||||||
|
#include <intrin.h>
|
||||||
|
namespace SimpleWeb {
|
||||||
|
inline void spin_loop_pause() noexcept { _mm_pause(); }
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
#else
|
||||||
|
namespace SimpleWeb {
|
||||||
|
inline void spin_loop_pause() noexcept {}
|
||||||
|
} // namespace SimpleWeb
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace SimpleWeb {
|
||||||
|
/// Makes it possible to for instance cancel Asio handlers without stopping asio::io_service
|
||||||
|
class ScopeRunner {
|
||||||
|
/// Scope count that is set to -1 if scopes are to be canceled
|
||||||
|
std::atomic<long> count;
|
||||||
|
|
||||||
|
public:
|
||||||
|
class SharedLock {
|
||||||
|
friend class ScopeRunner;
|
||||||
|
std::atomic<long> &count;
|
||||||
|
SharedLock(std::atomic<long> &count) noexcept : count(count) {}
|
||||||
|
SharedLock &operator=(const SharedLock &) = delete;
|
||||||
|
SharedLock(const SharedLock &) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~SharedLock() noexcept {
|
||||||
|
count.fetch_sub(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ScopeRunner() noexcept : count(0) {}
|
||||||
|
|
||||||
|
/// Returns nullptr if scope should be exited, or a shared lock otherwise
|
||||||
|
std::unique_ptr<SharedLock> continue_lock() noexcept {
|
||||||
|
long expected = count;
|
||||||
|
while(expected >= 0 && !count.compare_exchange_weak(expected, expected + 1))
|
||||||
|
spin_loop_pause();
|
||||||
|
|
||||||
|
if(expected < 0)
|
||||||
|
return nullptr;
|
||||||
|
else
|
||||||
|
return std::unique_ptr<SharedLock>(new SharedLock(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blocks until all shared locks are released, then prevents future shared locks
|
||||||
|
void stop() noexcept {
|
||||||
|
long expected = 0;
|
||||||
|
while(!count.compare_exchange_weak(expected, -1)) {
|
||||||
|
if(expected < 0)
|
||||||
|
return;
|
||||||
|
expected = 0;
|
||||||
|
spin_loop_pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace SimpleWeb
|
@ -0,0 +1,323 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 25.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Actors.hpp"
|
||||||
|
#include "Cell.hpp"
|
||||||
|
#include "CellController.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
#include "Players.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,
|
||||||
|
|
||||||
|
"followPlayer", &Actor::followPlayer,
|
||||||
|
"followActor", &Actor::followActor,
|
||||||
|
|
||||||
|
"refId", sol::property(&Actor::getRefId, &Actor::setRefId),
|
||||||
|
"refNumIndex", sol::property(&Actor::getRefNumIndex, &Actor::setRefNumIndex),
|
||||||
|
"mpNum", sol::property(&Actor::getMpNum, &Actor::setMpNum)
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor::Actor() : NetActor()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::followPlayer(int pid)
|
||||||
|
{
|
||||||
|
actor->aiAction = mwmp::BaseActor::AIAction::Follow;
|
||||||
|
|
||||||
|
actor->hasAiTarget = true;
|
||||||
|
actor->aiTarget.isPlayer = true;
|
||||||
|
|
||||||
|
auto player = Players::getPlayerByPID(pid).get();
|
||||||
|
actor->aiTarget.guid = player->guid;
|
||||||
|
|
||||||
|
aiChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::followActor(unsigned int refNumIndex, unsigned int mpNum)
|
||||||
|
{
|
||||||
|
actor->aiAction = mwmp::BaseActor::AIAction::Follow;
|
||||||
|
|
||||||
|
actor->hasAiTarget = true;
|
||||||
|
actor->aiTarget.isPlayer = false;
|
||||||
|
|
||||||
|
actor->aiTarget.refNumIndex = refNumIndex;
|
||||||
|
actor->aiTarget.mpNum = mpNum;
|
||||||
|
|
||||||
|
aiChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Actor::getRefId() const
|
||||||
|
{
|
||||||
|
return actor->refId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setRefId(const std::string &refId)
|
||||||
|
{
|
||||||
|
actor->refId = refId;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Actor::getRefNumIndex() const
|
||||||
|
{
|
||||||
|
return actor->refNumIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setRefNumIndex(unsigned refNumIndex)
|
||||||
|
{
|
||||||
|
actor->refNumIndex = refNumIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Actor::getMpNum() const
|
||||||
|
{
|
||||||
|
return actor->mpNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::setMpNum(unsigned 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 actorsTable = lua.getState()->create_named_table("Actors");
|
||||||
|
|
||||||
|
actorsTable.set_function("createActor", [&lua](){
|
||||||
|
return lua.getActorCtrl().createActor();
|
||||||
|
});
|
||||||
|
|
||||||
|
actorsTable.set_function("sendActors", [&lua](shared_ptr<Player> player, vector<shared_ptr<Actor>> actors,
|
||||||
|
const std::string &cellDescription, bool sendToAll) {
|
||||||
|
lua.getActorCtrl().sendActors(player, actors, Utils::getCellFromDescription(cellDescription), sendToAll);
|
||||||
|
});
|
||||||
|
|
||||||
|
actorsTable.set_function("sendList", [&lua](shared_ptr<Player> player, vector<shared_ptr<Actor>> actors,
|
||||||
|
const std::string &cellDescription, bool sendToAll) {
|
||||||
|
lua.getActorCtrl().sendList(player, actors, Utils::getCellFromDescription(cellDescription), sendToAll);
|
||||||
|
});
|
||||||
|
|
||||||
|
actorsTable.set_function("requestList", [&lua](shared_ptr<Player> player, const std::string &cellDescription){
|
||||||
|
lua.getActorCtrl().requestList(player, Utils::getCellFromDescription(cellDescription));
|
||||||
|
});
|
||||||
|
|
||||||
|
actorsTable.set_function("getActors", [&lua](shared_ptr<Player> player, const std::string &cellDescription){
|
||||||
|
lua.getActorCtrl().getActors(player, Utils::getCellFromDescription(cellDescription));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
const ESM::Cell &cell, bool sendToAll)
|
||||||
|
{
|
||||||
|
actorList.cell = cell;
|
||||||
|
actorList.guid = player->guid;
|
||||||
|
|
||||||
|
bool positionChanged = false;
|
||||||
|
bool statsChanged = false;
|
||||||
|
/*bool attributesChanged = false;
|
||||||
|
bool skillsChanged = false;
|
||||||
|
bool baseInfoChanged = false;*/
|
||||||
|
bool equipmentChanged = false;
|
||||||
|
bool aiChanged = 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->aiChanged)
|
||||||
|
aiChanged = 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 (aiChanged)
|
||||||
|
{
|
||||||
|
auto packet = actorCtrl->GetPacket(ID_ACTOR_AI);
|
||||||
|
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,
|
||||||
|
const ESM::Cell &cell, bool sendToAll)
|
||||||
|
{
|
||||||
|
actorList.cell = player->cell;
|
||||||
|
actorList.guid = player->guid;
|
||||||
|
actorList.action = mwmp::BaseActorList::Action::Set;
|
||||||
|
|
||||||
|
for (auto &actor : actors)
|
||||||
|
{
|
||||||
|
actorList.baseActors.push_back(actor->actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packet = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_LIST);
|
||||||
|
packet->setActorList(&actorList);
|
||||||
|
packet->Send(actorList.guid);
|
||||||
|
if (sendToAll)
|
||||||
|
CellController::get().getCell(actorList.cell)->sendToLoaded(packet, &actorList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActorController::requestList(std::shared_ptr<Player> player, const ESM::Cell &cell)
|
||||||
|
{
|
||||||
|
actorList.cell = player->cell;
|
||||||
|
actorList.guid = player->guid;
|
||||||
|
actorList.action = mwmp::BaseActorList::Action::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, const ESM::Cell &cell)
|
||||||
|
{
|
||||||
|
Cell *serverCell = CellController::get().getCell(player->cell);
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Actor>> actorList;
|
||||||
|
|
||||||
|
for (const auto &actor : serverCell->getActorList()->baseActors)
|
||||||
|
{
|
||||||
|
auto a = new Actor;
|
||||||
|
a->actor = actor;
|
||||||
|
actorList.emplace_back(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return actorList;
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
unsigned getRefNumIndex() const;
|
||||||
|
void setRefNumIndex(unsigned refNumIndex);
|
||||||
|
unsigned getMpNum() const;
|
||||||
|
void setMpNum(unsigned mpNum);
|
||||||
|
|
||||||
|
void followPlayer(int pid);
|
||||||
|
void followActor(unsigned int refNumIndex, unsigned 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, const ESM::Cell &cell, bool sendToAll = false);
|
||||||
|
void sendList(std::shared_ptr<Player> player, std::vector<std::shared_ptr<Actor>> actors, const ESM::Cell &cell, bool sendToAll = false);
|
||||||
|
|
||||||
|
void requestList(std::shared_ptr<Player> player, const ESM::Cell &cell);
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Actor>> getActors(std::shared_ptr<Player> player, const ESM::Cell &cell);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mwmp::BaseActorList actorList;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 02.01.18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "BaseMgr.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
#include "Worldstate.hpp"
|
||||||
|
|
||||||
|
BaseMgr::BaseMgr(Player *player) : player(player), changed(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseMgr::BaseMgr(Worldstate *worldstate) : worldstate(worldstate), changed(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMgr::update()
|
||||||
|
{
|
||||||
|
if (!changed)
|
||||||
|
return;
|
||||||
|
changed = false;
|
||||||
|
|
||||||
|
processUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseMgr::setChanged()
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
if (player != nullptr)
|
||||||
|
player->addToUpdateQueue();
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 02.01.18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
class Worldstate;
|
||||||
|
|
||||||
|
class BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BaseMgr(Player *player);
|
||||||
|
explicit BaseMgr(Worldstate *worldstate);
|
||||||
|
void update();
|
||||||
|
protected:
|
||||||
|
bool isChanged() const { return changed; };
|
||||||
|
void setChanged();
|
||||||
|
virtual void processUpdate() = 0;
|
||||||
|
Player *player;
|
||||||
|
Worldstate *worldstate;
|
||||||
|
private:
|
||||||
|
bool changed;
|
||||||
|
};
|
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 15.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Books.hpp"
|
||||||
|
#include "Player.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) : BaseMgr(player)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Books::addBook(const std::string &bookId)
|
||||||
|
{
|
||||||
|
if (!isChanged())
|
||||||
|
reset();
|
||||||
|
player->bookChanges.books.push_back({bookId});
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Books::getBookId(unsigned i) const
|
||||||
|
{
|
||||||
|
if (i >= player->bookChanges.books.size())
|
||||||
|
return "invalid";
|
||||||
|
|
||||||
|
return player->bookChanges.books.at(i).bookId;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned Books::getChanges() const
|
||||||
|
{
|
||||||
|
return player->bookChanges.books.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Books::reset()
|
||||||
|
{
|
||||||
|
player->bookChanges.books.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Books::processUpdate()
|
||||||
|
{
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_BOOK);
|
||||||
|
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(/*toOthers*/ false);
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 15.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "BaseMgr.hpp"
|
||||||
|
|
||||||
|
class LuaState;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class Books final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit Books(Player *player);
|
||||||
|
void addBook(const std::string &bookId);
|
||||||
|
std::string getBookId(unsigned i) const;
|
||||||
|
unsigned getChanges() const;
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processUpdate() final;
|
||||||
|
};
|
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 25.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
|
||||||
|
#include "CellState.hpp"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
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(std::move(state))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mwmp::CellState::Type 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:
|
||||||
|
mwmp::CellState::Type getStateType() const;
|
||||||
|
std::string getDescription() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mwmp::CellState state;
|
||||||
|
};
|
@ -0,0 +1,108 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 25.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Cells.hpp"
|
||||||
|
#include "NetActor.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void Cells::Init(LuaState &lua)
|
||||||
|
{
|
||||||
|
lua.getState()->new_usertype<Cells>("Cell",
|
||||||
|
"description", sol::property(&Cells::getDescription, &Cells::setDescription),
|
||||||
|
"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::getDescription() const
|
||||||
|
{
|
||||||
|
return netActor->getNetCreature()->cell.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Cells::setChanged()
|
||||||
|
{
|
||||||
|
if (!changedCell && netActor->isPlayer())
|
||||||
|
netActor->toPlayer()->addToUpdateQueue();
|
||||||
|
changedCell = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cells::setDescription(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);
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
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,45 @@
|
|||||||
|
//
|
||||||
|
// 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 getDescription() const;
|
||||||
|
void setDescription(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;
|
||||||
|
void setChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,147 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 12.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "CharClass.hpp"
|
||||||
|
#include "Player.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),
|
||||||
|
"isCustom", &CharClass::isCustom,
|
||||||
|
|
||||||
|
"name", sol::property(&CharClass::getName, &CharClass::setName),
|
||||||
|
"description", sol::property(&CharClass::getDescription, &CharClass::setDescription),
|
||||||
|
"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) : BaseMgr(player)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
string CharClass::getDefault() const
|
||||||
|
{
|
||||||
|
return player->charClass.mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::setDefault(const string &className)
|
||||||
|
{
|
||||||
|
player->charClass.mId = className;
|
||||||
|
setChanged();
|
||||||
|
printf("CharClass::setDefault()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharClass::isCustom() const
|
||||||
|
{
|
||||||
|
return player->charClass.mId.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::setName(const string &className)
|
||||||
|
{
|
||||||
|
player->charClass.mName = className;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
string CharClass::getName() const
|
||||||
|
{
|
||||||
|
return player->charClass.mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CharClass::getDescription() const
|
||||||
|
{
|
||||||
|
return player->charClass.mDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::setDescription(const string &desc)
|
||||||
|
{
|
||||||
|
player->charClass.mDescription = desc;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CharClass::getSpecialization() const
|
||||||
|
{
|
||||||
|
return player->charClass.mData.mSpecialization;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::setSpecialization(int spec)
|
||||||
|
{
|
||||||
|
auto &data = player->charClass.mData;
|
||||||
|
data.mSpecialization = spec;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<int, 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], data.mSkills[4][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::setMinorSkills(int first, int second, int third, int fourth, int fifth)
|
||||||
|
{
|
||||||
|
auto &data = player->charClass.mData;
|
||||||
|
data.mSkills[0][0] = first;
|
||||||
|
data.mSkills[1][0] = second;
|
||||||
|
data.mSkills[2][0] = third;
|
||||||
|
data.mSkills[3][0] = fourth;
|
||||||
|
data.mSkills[4][0] = fifth;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<int, 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], data.mSkills[4][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::setMajorSkills(int first, int second, int third, int fourth, int fifth)
|
||||||
|
{
|
||||||
|
auto &data = player->charClass.mData;
|
||||||
|
data.mSkills[0][1] = first;
|
||||||
|
data.mSkills[1][1] = second;
|
||||||
|
data.mSkills[2][1] = third;
|
||||||
|
data.mSkills[3][1] = fourth;
|
||||||
|
data.mSkills[4][1] = fifth;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CharClass::processUpdate()
|
||||||
|
{
|
||||||
|
printf("CharClass::update()\n");
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_CHARCLASS);
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(false);
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 12.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include "BaseMgr.hpp"
|
||||||
|
|
||||||
|
class LuaState;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class CharClass final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CharClass(Player *player);
|
||||||
|
|
||||||
|
std::string getDefault() const;
|
||||||
|
void setDefault(const std::string &className);
|
||||||
|
bool isCustom() const;
|
||||||
|
|
||||||
|
std::string getName() const;
|
||||||
|
void setName(const std::string &className);
|
||||||
|
|
||||||
|
std::string getDescription() const;
|
||||||
|
void setDescription(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, int> getMinorSkills() const;
|
||||||
|
void setMinorSkills(int fisrt, int second, int third, int fourth, int fifth);
|
||||||
|
|
||||||
|
std::tuple<int, int, int, int, int> getMajorSkills() const;
|
||||||
|
void setMajorSkills(int fisrt, int second, int third, int fourth, int fifth);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processUpdate() final;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 15.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Dialogue.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
|
||||||
|
void Dialogue::Init(LuaState &lua)
|
||||||
|
{
|
||||||
|
lua.getState()->new_usertype<Dialogue>("Dialogue",
|
||||||
|
"addTopic", &Dialogue::addTopic,
|
||||||
|
"getTopicId", &Dialogue::getTopicId,
|
||||||
|
"size", &Dialogue::size,
|
||||||
|
"reset", &Dialogue::reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Dialogue::Dialogue(Player *player) : BaseMgr(player)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Dialogue::reset()
|
||||||
|
{
|
||||||
|
player->topicChanges.topics.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialogue::processUpdate()
|
||||||
|
{
|
||||||
|
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 (!isChanged())
|
||||||
|
reset();
|
||||||
|
setChanged();
|
||||||
|
player->topicChanges.topics.push_back({topicId});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Dialogue::getTopicId(unsigned int i) const
|
||||||
|
{
|
||||||
|
return player->topicChanges.topics.at(i).topicId;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Dialogue::size() const
|
||||||
|
{
|
||||||
|
return player->topicChanges.topics.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialogue::playAnimation(const std::string &groupname, int mode, int count, bool persist)
|
||||||
|
{
|
||||||
|
player->animation.groupname = groupname;
|
||||||
|
player->animation.mode = mode;
|
||||||
|
player->animation.count = count;
|
||||||
|
player->animation.persist = persist;
|
||||||
|
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ANIM_PLAY);
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(false);
|
||||||
|
player->sendToLoaded(*packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialogue::playSpeech(const std::string &sound)
|
||||||
|
{
|
||||||
|
player->sound = sound;
|
||||||
|
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SPEECH);
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(false);
|
||||||
|
player->sendToLoaded(*packet);
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 15.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "BaseMgr.hpp"
|
||||||
|
|
||||||
|
class LuaState;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class Dialogue final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit Dialogue(Player *player);
|
||||||
|
|
||||||
|
void addTopic(const std::string &topicId);
|
||||||
|
std::string getTopicId(unsigned int i) const;
|
||||||
|
size_t size() const;
|
||||||
|
|
||||||
|
void playAnimation(const std::string &groupname, int mode, int count, bool persist);
|
||||||
|
void playSpeech(const std::string &sound);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
private:
|
||||||
|
void processUpdate() final;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 17.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Factions.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
|
||||||
|
void Factions::Init(LuaState &lua)
|
||||||
|
{
|
||||||
|
lua.getState()->new_usertype<Factions>("Factions",
|
||||||
|
"addFaction", &Factions::addFaction,
|
||||||
|
"getFaction", &Factions::getFaction,
|
||||||
|
"setFaction", &Factions::setFaction,
|
||||||
|
"clear", &Factions::clear,
|
||||||
|
"size", &Factions::size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Factions::Factions(Player *player): BaseMgr(player)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Factions::~Factions()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factions::processUpdate()
|
||||||
|
{
|
||||||
|
auto packet =mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_FACTION);
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(/*toOthers*/ false);
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factions::addFaction(const Faction &faction)
|
||||||
|
{
|
||||||
|
player->factionChanges.factions.emplace_back(faction.faction);
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Faction Factions::getFaction(int id) const
|
||||||
|
{
|
||||||
|
return Faction(player->factionChanges.factions.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factions::setFaction(int id, const Faction &faction)
|
||||||
|
{
|
||||||
|
player->factionChanges.factions.at(id) = faction.faction;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factions::clear()
|
||||||
|
{
|
||||||
|
player->factionChanges.factions.clear();
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.rankChanged();
|
||||||
|
faction.rank = rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Faction::getFactionExpulsionState() const
|
||||||
|
{
|
||||||
|
return faction.isExpelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Faction::setFactionExpulsionState(bool expulsionState)
|
||||||
|
{
|
||||||
|
faction.expulsionChanged();
|
||||||
|
faction.isExpelled = expulsionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Faction::getFactionReputation() const
|
||||||
|
{
|
||||||
|
return faction.reputation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Faction::setFactionReputation(int reputation)
|
||||||
|
{
|
||||||
|
faction.reputationChanged();
|
||||||
|
faction.reputation = reputation;
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 17.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <components/openmw-mp/Base/BasePlayer.hpp>
|
||||||
|
#include "BaseMgr.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 final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit Factions(Player *player);
|
||||||
|
~Factions();
|
||||||
|
|
||||||
|
void addFaction(const Faction &faction);
|
||||||
|
Faction getFaction(int id) const;
|
||||||
|
void setFaction(int id, const Faction &faction);
|
||||||
|
size_t size() const;
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processUpdate() final;
|
||||||
|
};
|
@ -0,0 +1,279 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 15.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
#include "GUI.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
#include <RakPeerInterface.h>
|
||||||
|
|
||||||
|
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,
|
||||||
|
"createWindow", &GUI::createWindow,
|
||||||
|
"deleteWindow", &GUI::deleteWindow
|
||||||
|
);
|
||||||
|
Window::Init(lua);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI::GUI(Player *player): BaseMgr(player)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::processUpdate()
|
||||||
|
{
|
||||||
|
player->guiMessageBox = guiQueue.front().first;
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_GUI_MESSAGEBOX);
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GUI::generateGuiId()
|
||||||
|
{
|
||||||
|
return RakNet::RakPeerInterface::Get64BitUniqueRandomNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::messageBox(sol::function fn, const char *label, sol::this_environment te)
|
||||||
|
{
|
||||||
|
mwmp::BasePlayer::GUIMessageBox mbox;
|
||||||
|
|
||||||
|
mbox.id = generateGuiId();
|
||||||
|
mbox.label = label;
|
||||||
|
mbox.type = Player::GUIMessageBox::Type::MessageBox;
|
||||||
|
|
||||||
|
guiQueue.emplace(std::move(mbox), std::move(fn));
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::customMessageBox(sol::function fn, const char *label, const char *buttons, sol::this_environment te)
|
||||||
|
{
|
||||||
|
mwmp::BasePlayer::GUIMessageBox mbox;
|
||||||
|
mbox.id = generateGuiId();
|
||||||
|
mbox.label = label;
|
||||||
|
mbox.buttons = buttons;
|
||||||
|
mbox.type = Player::GUIMessageBox::Type::CustomMessageBox;
|
||||||
|
|
||||||
|
guiQueue.emplace(std::move(mbox), std::move(fn));
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::inputDialog(sol::function fn, const char *label, const char *note, sol::this_environment te)
|
||||||
|
{
|
||||||
|
mwmp::BasePlayer::GUIMessageBox mbox;
|
||||||
|
|
||||||
|
mbox.id = generateGuiId();
|
||||||
|
mbox.label = label;
|
||||||
|
mbox.note = note;
|
||||||
|
mbox.type = Player::GUIMessageBox::Type::InputDialog;
|
||||||
|
|
||||||
|
guiQueue.emplace(std::move(mbox), std::move(fn));
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::passwordDialog(sol::function fn, const char *label, const char *note, sol::this_environment te)
|
||||||
|
{
|
||||||
|
mwmp::BasePlayer::GUIMessageBox mbox;
|
||||||
|
|
||||||
|
mbox.id = generateGuiId();
|
||||||
|
mbox.label = label;
|
||||||
|
mbox.note = note;
|
||||||
|
mbox.type = Player::GUIMessageBox::Type::PasswordDialog;
|
||||||
|
|
||||||
|
guiQueue.emplace(std::move(mbox), std::move(fn));
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::listBox(sol::function fn, const char *label, const char *items, sol::this_environment te)
|
||||||
|
{
|
||||||
|
mwmp::BasePlayer::GUIMessageBox mbox;
|
||||||
|
|
||||||
|
mbox.id = generateGuiId();
|
||||||
|
|
||||||
|
mbox.label = label;
|
||||||
|
mbox.data = items;
|
||||||
|
mbox.type = Player::GUIMessageBox::Type::ListBox;
|
||||||
|
|
||||||
|
guiQueue.emplace(std::move(mbox), std::move(fn));
|
||||||
|
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::onGUIAction()
|
||||||
|
{
|
||||||
|
auto mbox = std::move(guiQueue.front().first);
|
||||||
|
auto callback = std::move(guiQueue.front().second);
|
||||||
|
guiQueue.pop();
|
||||||
|
|
||||||
|
if (!guiQueue.empty())
|
||||||
|
setChanged();
|
||||||
|
|
||||||
|
if (player->guiMessageBox.id != mbox.id)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Wrong MessageBox id from %s(%d).", player->npc.mName, player->getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback.valid())
|
||||||
|
callback.call(player, player->guiMessageBox.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Window> GUI::createWindow(short x, short y, sol::function fn, sol::this_environment te)
|
||||||
|
{
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
for (auto &window : windows)
|
||||||
|
{
|
||||||
|
if (window.second == nullptr)
|
||||||
|
{
|
||||||
|
id = window.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
id = lastWindowId++;
|
||||||
|
|
||||||
|
auto window = std::make_shared<Window>(player, id);
|
||||||
|
window->setSize(x, y);
|
||||||
|
window->setCallback(fn);
|
||||||
|
|
||||||
|
windows[id] = window;
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::deleteWindow(std::shared_ptr<Window> window)
|
||||||
|
{
|
||||||
|
auto it = windows.find(window->getID());
|
||||||
|
if (it != windows.end())
|
||||||
|
{
|
||||||
|
it->second = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::onGUIWindowAction()
|
||||||
|
{
|
||||||
|
auto it = windows.find(player->guiWindow.id);
|
||||||
|
if (it != windows.end() && it->second != nullptr)
|
||||||
|
{
|
||||||
|
it->second->call(player->guiWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeys::Init(LuaState &lua)
|
||||||
|
{
|
||||||
|
lua.getState()->new_usertype<QuickKeys>("QuickKeys",
|
||||||
|
"addQuickKey", &QuickKeys::addQuickKey,
|
||||||
|
"getQuickKey", &QuickKeys::getQuickKey,
|
||||||
|
"setQuickKey", &QuickKeys::setQuickKey,
|
||||||
|
"clear", &QuickKeys::clear,
|
||||||
|
"size", &QuickKeys::size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
QuickKeys::QuickKeys(Player *player) : BaseMgr(player)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeys::processUpdate()
|
||||||
|
{
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_QUICKKEYS);
|
||||||
|
packet->setPlayer(player);
|
||||||
|
packet->Send(false);
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeys::addQuickKey(const QuickKey &quickKey)
|
||||||
|
{
|
||||||
|
player->quickKeyChanges.quickKeys.push_back(quickKey.quickKey);
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QuickKey QuickKeys::getQuickKey(int id) const
|
||||||
|
{
|
||||||
|
return QuickKey(player->quickKeyChanges.quickKeys.at(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeys::setQuickKey(int id, const QuickKey &quickKey)
|
||||||
|
{
|
||||||
|
player->quickKeyChanges.quickKeys.at(id) = quickKey.quickKey;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKeys::clear()
|
||||||
|
{
|
||||||
|
player->quickKeyChanges.quickKeys.clear();
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t QuickKeys::size() const
|
||||||
|
{
|
||||||
|
return player->quickKeyChanges.quickKeys.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKey::Init(LuaState &lua)
|
||||||
|
{
|
||||||
|
lua.getState()->new_usertype<QuickKey>("QuickKey",
|
||||||
|
"slot", sol::property(&QuickKey::getSlot, &QuickKey::setSlot),
|
||||||
|
"type", sol::property(&QuickKey::getType, &QuickKey::setType),
|
||||||
|
"itemId", sol::property(&QuickKey::getItemId, &QuickKey::setItemId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
QuickKey::QuickKey(mwmp::QuickKey &quickKey): quickKey(quickKey)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int QuickKey::getSlot() const
|
||||||
|
{
|
||||||
|
return quickKey.slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKey::setSlot(unsigned short slot)
|
||||||
|
{
|
||||||
|
quickKey.slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
mwmp::QuickKey::Type QuickKey::getType() const
|
||||||
|
{
|
||||||
|
return quickKey.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKey::setType(mwmp::QuickKey::Type type)
|
||||||
|
{
|
||||||
|
quickKey.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string QuickKey::getItemId() const
|
||||||
|
{
|
||||||
|
return quickKey.itemId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickKey::setItemId(const std::string &itemId)
|
||||||
|
{
|
||||||
|
quickKey.itemId = itemId;
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include "Window.hpp"
|
||||||
|
#include "BaseMgr.hpp"
|
||||||
|
|
||||||
|
class LuaState;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class GUI final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit GUI(Player *player);
|
||||||
|
|
||||||
|
void messageBox(sol::function fn, const char *label, sol::this_environment te);
|
||||||
|
|
||||||
|
void customMessageBox(sol::function fn, const char *label, const char *buttons, sol::this_environment te);
|
||||||
|
void inputDialog(sol::function fn, const char *label, const char *note, sol::this_environment te);
|
||||||
|
void passwordDialog(sol::function fn, const char *label, const char *note, sol::this_environment te);
|
||||||
|
|
||||||
|
void listBox(sol::function fn, const char *label, const char *items, sol::this_environment te);
|
||||||
|
|
||||||
|
void onGUIAction();
|
||||||
|
|
||||||
|
//state 0 - disallow, 1 - allow
|
||||||
|
void setMapVisibility(unsigned short targetPID, unsigned short affectedPID, unsigned short state);
|
||||||
|
void setMapVisibilityAll(unsigned short targetPID, unsigned short state);
|
||||||
|
|
||||||
|
std::shared_ptr<Window> createWindow(short x, short y, sol::function fn, sol::this_environment te);
|
||||||
|
void deleteWindow(std::shared_ptr<Window> window);
|
||||||
|
void onGUIWindowAction();
|
||||||
|
|
||||||
|
void addQuickKey(unsigned short slot, int type, const std::string &itemId);
|
||||||
|
std::string getTopicId(unsigned int i) const;
|
||||||
|
unsigned int getChanges() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t generateGuiId();
|
||||||
|
void processUpdate() final;
|
||||||
|
std::unordered_map<int, std::shared_ptr<Window>> windows;
|
||||||
|
std::queue<std::pair<mwmp::BasePlayer::GUIMessageBox, sol::function>> guiQueue;
|
||||||
|
int lastWindowId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuickKey
|
||||||
|
{
|
||||||
|
friend class QuickKeys;
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit QuickKey(mwmp::QuickKey &quickKey);
|
||||||
|
|
||||||
|
int getSlot() const;
|
||||||
|
void setSlot(unsigned short slot);
|
||||||
|
|
||||||
|
mwmp::QuickKey::Type getType() const;
|
||||||
|
void setType(mwmp::QuickKey::Type slot);
|
||||||
|
|
||||||
|
std::string getItemId() const;
|
||||||
|
void setItemId(const std::string &itemId);
|
||||||
|
|
||||||
|
mwmp::QuickKey quickKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuickKeys final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit QuickKeys(Player *player);
|
||||||
|
|
||||||
|
void addQuickKey(const QuickKey &quickKey);
|
||||||
|
QuickKey getQuickKey(int id) const;
|
||||||
|
void setQuickKey(int id, const QuickKey &quickKey);
|
||||||
|
size_t size() const;
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processUpdate() final;
|
||||||
|
};
|
@ -0,0 +1,188 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 12.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include <apps/openmw/mwworld/inventorystore.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Inventory.hpp"
|
||||||
|
#include "NetActor.hpp"
|
||||||
|
#include <Player.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(false)
|
||||||
|
{
|
||||||
|
printf("Inventory::Inventory()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Inventory::~Inventory()
|
||||||
|
{
|
||||||
|
printf("Inventory::~Inventory()\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::update()
|
||||||
|
{
|
||||||
|
printf("Inventory::update()");
|
||||||
|
/*if (isEquipmentChanged())
|
||||||
|
{
|
||||||
|
if (netActor->isPlayer())
|
||||||
|
{
|
||||||
|
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_EQUIPMENT);
|
||||||
|
packet->setPlayer(dynamic_cast<Player *>(netActor));
|
||||||
|
packet->Send(false);
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto packet = mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_EQUIPMENT);
|
||||||
|
packet->setActorList(&actorList);
|
||||||
|
packet->Send(actorList.guid);
|
||||||
|
|
||||||
|
if (sendToAll)
|
||||||
|
serverCell->sendToLoaded(packet, &actorList);
|
||||||
|
}
|
||||||
|
resetEquipmentFlag();
|
||||||
|
}*/
|
||||||
|
/*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;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inventory::getChangesSize() const
|
||||||
|
{
|
||||||
|
return netActor->getNetCreature()->inventoryChanges.items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge, float enchantmentCharge)
|
||||||
|
{
|
||||||
|
netActor->getNetCreature()->equipmentItems[slot].refId = refId;
|
||||||
|
netActor->getNetCreature()->equipmentItems[slot].count = count;
|
||||||
|
netActor->getNetCreature()->equipmentItems[slot].charge = charge;
|
||||||
|
netActor->getNetCreature()->equipmentItems[slot].enchantmentCharge = enchantmentCharge;
|
||||||
|
|
||||||
|
if (!Utils::vectorContains(&netActor->getNetCreature()->equipmentIndexChanges, slot))
|
||||||
|
netActor->getNetCreature()->equipmentIndexChanges.push_back(slot);
|
||||||
|
|
||||||
|
if (!equipmentChanged && netActor->isPlayer())
|
||||||
|
netActor->toPlayer()->addToUpdateQueue();
|
||||||
|
|
||||||
|
equipmentChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::unequipItem( unsigned short slot)
|
||||||
|
{
|
||||||
|
equipItem(slot, "", 0, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Inventory::addItem(const std::string &refId, unsigned int count, int charge, float enchantmentCharge)
|
||||||
|
{
|
||||||
|
if (!inventoryChanged)
|
||||||
|
resetInventoryFlag();
|
||||||
|
|
||||||
|
mwmp::Item item;
|
||||||
|
item.refId = refId;
|
||||||
|
item.count = count;
|
||||||
|
item.charge = charge;
|
||||||
|
item.enchantmentCharge = enchantmentCharge;
|
||||||
|
|
||||||
|
netActor->getNetCreature()->inventoryChanges.items.emplace_back(item, mwmp::InventoryChanges::Action::Add);
|
||||||
|
if (netActor->isPlayer())
|
||||||
|
netActor->toPlayer()->addToUpdateQueue();
|
||||||
|
inventoryChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::removeItem(const std::string &refId, unsigned short count)
|
||||||
|
{
|
||||||
|
if (!inventoryChanged)
|
||||||
|
resetInventoryFlag();
|
||||||
|
mwmp::Item item;
|
||||||
|
item.refId = refId;
|
||||||
|
item.count = count;
|
||||||
|
|
||||||
|
netActor->getNetCreature()->inventoryChanges.items.emplace_back(item, mwmp::InventoryChanges::Action::Remove);
|
||||||
|
if (netActor->isPlayer())
|
||||||
|
netActor->toPlayer()->addToUpdateQueue();
|
||||||
|
inventoryChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Inventory::hasItemEquipped(const std::string &refId) const
|
||||||
|
{
|
||||||
|
for (const auto &equipmentItem : netActor->getNetCreature()->equipmentItems)
|
||||||
|
if (Misc::StringUtils::ciEqual(equipmentItem.refId, refId))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<std::string, int, int, double> Inventory::getEquipmentItem(unsigned short slot) const
|
||||||
|
{
|
||||||
|
const auto &item = netActor->getNetCreature()->equipmentItems[slot];
|
||||||
|
return make_tuple(item.refId, item.count, item.charge, item.enchantmentCharge);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<std::string, int, int, double> Inventory::getInventoryItem(unsigned int slot) const
|
||||||
|
{
|
||||||
|
const auto &item = netActor->getNetCreature()->inventoryChanges.items.at(slot).first;
|
||||||
|
return make_tuple(item.refId, item.count, item.charge, item.enchantmentCharge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::resetEquipmentFlag()
|
||||||
|
{
|
||||||
|
equipmentChanged = false;
|
||||||
|
|
||||||
|
netActor->getNetCreature()->equipmentIndexChanges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Inventory::isEquipmentChanged()
|
||||||
|
{
|
||||||
|
return equipmentChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Inventory::isInventoryChanged()
|
||||||
|
{
|
||||||
|
return inventoryChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory::resetInventoryFlag()
|
||||||
|
{
|
||||||
|
inventoryChanged = false;
|
||||||
|
|
||||||
|
netActor->getNetCreature()->inventoryChanges.items.clear();
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// 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();
|
||||||
|
bool isInventoryChanged();
|
||||||
|
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, float enchantmentCharge);
|
||||||
|
void removeItem(const std::string& refId, unsigned short count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param slot
|
||||||
|
* @return refid, count, charge, enchantmentCharge
|
||||||
|
*/
|
||||||
|
std::tuple<std::string,int, int, double> getInventoryItem(unsigned int slot) const;
|
||||||
|
|
||||||
|
|
||||||
|
// equipment
|
||||||
|
void equipItem(unsigned short slot, const std::string& refId, unsigned int count, int charge, float enchantmentCharge);
|
||||||
|
void unequipItem(unsigned short slot);
|
||||||
|
|
||||||
|
bool hasItemEquipped(const std::string& refId) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param slot
|
||||||
|
* @return refid, count, charge, enchantmentCharge
|
||||||
|
*/
|
||||||
|
std::tuple<std::string,int, int, double> getEquipmentItem(unsigned short slot) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// not controlled pointer
|
||||||
|
NetActor *netActor;
|
||||||
|
bool equipmentChanged;
|
||||||
|
bool inventoryChanged;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,143 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 25.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
#include <components/openmw-mp/Base/BaseNetCreature.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "NetActor.hpp"
|
||||||
|
#include "Player.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
NetActor::NetActor() : inventory(this), cellAPI(this), isActorPlayer(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetActor::resetUpdateFlags()
|
||||||
|
{
|
||||||
|
baseInfoChanged = false;
|
||||||
|
shapeshiftChanged = false;
|
||||||
|
levelChanged = false;
|
||||||
|
statsChanged = false;
|
||||||
|
positionChanged = false;
|
||||||
|
skillsChanged = false;
|
||||||
|
attributesChanged = 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;
|
||||||
|
|
||||||
|
if (!positionChanged && isPlayer())
|
||||||
|
toPlayer()->addToUpdateQueue();
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!positionChanged && isPlayer())
|
||||||
|
toPlayer()->addToUpdateQueue();
|
||||||
|
positionChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetActor::setMomentum(float x, float y, float z)
|
||||||
|
{
|
||||||
|
netCreature->momentum.pos[0] = x;
|
||||||
|
netCreature->momentum.pos[1] = y;
|
||||||
|
netCreature->momentum.pos[2] = z;
|
||||||
|
|
||||||
|
if (!momentumChanged && isPlayer())
|
||||||
|
toPlayer()->addToUpdateQueue();
|
||||||
|
momentumChanged = 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;
|
||||||
|
|
||||||
|
if (!Utils::vectorContains(&netCreature->statsDynamicIndexChanges, 0))
|
||||||
|
netCreature->statsDynamicIndexChanges.push_back(0);
|
||||||
|
|
||||||
|
if (!statsChanged && isPlayer())
|
||||||
|
toPlayer()->addToUpdateQueue();
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!Utils::vectorContains(&netCreature->statsDynamicIndexChanges, 1))
|
||||||
|
netCreature->statsDynamicIndexChanges.push_back(1);
|
||||||
|
|
||||||
|
if (!statsChanged && isPlayer())
|
||||||
|
toPlayer()->addToUpdateQueue();
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!Utils::vectorContains(&netCreature->statsDynamicIndexChanges, 2))
|
||||||
|
netCreature->statsDynamicIndexChanges.push_back(2);
|
||||||
|
|
||||||
|
if (!statsChanged && isPlayer())
|
||||||
|
toPlayer()->addToUpdateQueue();
|
||||||
|
statsChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Inventory &NetActor::getInventory()
|
||||||
|
{
|
||||||
|
return inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cells &NetActor::getCell()
|
||||||
|
{
|
||||||
|
return cellAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player *NetActor::toPlayer()
|
||||||
|
{
|
||||||
|
if (isPlayer())
|
||||||
|
return dynamic_cast<Player*>(this);
|
||||||
|
return nullptr;
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// 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();
|
||||||
|
virtual ~NetActor() = default;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void setMomentum(float x, float y, 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; }
|
||||||
|
|
||||||
|
bool isPlayer() const { return isActorPlayer; }
|
||||||
|
Player *toPlayer();
|
||||||
|
protected:
|
||||||
|
bool baseInfoChanged, shapeshiftChanged, levelChanged, statsChanged, positionChanged, momentumChanged, attributesChanged, skillsChanged, aiChanged;
|
||||||
|
|
||||||
|
mwmp::BasePlayer *basePlayer;
|
||||||
|
mwmp::BaseNetCreature *netCreature;
|
||||||
|
|
||||||
|
Inventory inventory;
|
||||||
|
Cells cellAPI;
|
||||||
|
bool isActorPlayer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -0,0 +1,595 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 26.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Object.hpp"
|
||||||
|
#include "Player.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),
|
||||||
|
"guid", sol::property(&BaseObject::getGuid, &BaseObject::setGuid),
|
||||||
|
"getPosition", &Object::getPosition,
|
||||||
|
"setPosition", &Object::setPosition,
|
||||||
|
"getRotation", &Object::getRotation,
|
||||||
|
"setRotation", &Object::setRotation,
|
||||||
|
"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),
|
||||||
|
"lockLevel", sol::property(&Object::getLockLevel, &Object::setLockLevel),
|
||||||
|
"doorState", sol::property(&Object::getDoorState, &Object::setDoorState),
|
||||||
|
"hasContainer", &Object::hasContainer,
|
||||||
|
"setTeleportState", &Object::setTeleportState,
|
||||||
|
"setDoorDestination", &Object::setDoorDestination,
|
||||||
|
"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;
|
||||||
|
object.droppedByPlayer = false;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned BaseObject::getRefNum() const
|
||||||
|
{
|
||||||
|
return object.refNumIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseObject::setRefNum(unsigned refNum)
|
||||||
|
{
|
||||||
|
changedBase = true;
|
||||||
|
object.refNumIndex = refNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned BaseObject::getMpNum() const
|
||||||
|
{
|
||||||
|
return object.mpNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseObject::setMpNum(unsigned mpNum)
|
||||||
|
{
|
||||||
|
changedBase = true;
|
||||||
|
object.mpNum = mpNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
RakNet::RakNetGUID BaseObject::getGuid() const
|
||||||
|
{
|
||||||
|
return object.guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseObject::setGuid(const RakNet::RakNetGUID &guid)
|
||||||
|
{
|
||||||
|
changedBase = true;
|
||||||
|
object.guid = guid;
|
||||||
|
object.isPlayer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float Object::getEnchantmentCharge() const
|
||||||
|
{
|
||||||
|
return object.enchantmentCharge;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setEnchantmentCharge(float enchantmentCharge)
|
||||||
|
{
|
||||||
|
changedObjectPlace = true;
|
||||||
|
object.enchantmentCharge = enchantmentCharge;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Object::hasContainer() const
|
||||||
|
{
|
||||||
|
return object.hasContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setTeleportState(bool state)
|
||||||
|
{
|
||||||
|
changedDoorDestination = true;
|
||||||
|
object.teleportState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setDoorDestination(const std::string &cellDescription, float posX, float posY, float posZ, float rotX, float rotY, float rotZ)
|
||||||
|
{
|
||||||
|
changedDoorDestination = true;
|
||||||
|
object.destinationCell = Utils::getCellFromDescription(cellDescription);
|
||||||
|
object.destinationPosition.pos[0] = posX;
|
||||||
|
object.destinationPosition.pos[1] = posY;
|
||||||
|
object.destinationPosition.pos[2] = posZ;
|
||||||
|
object.destinationPosition.rot[0] = rotX;
|
||||||
|
object.destinationPosition.rot[1] = rotY;
|
||||||
|
object.destinationPosition.rot[2] = rotZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setDisarmState(bool state)
|
||||||
|
{
|
||||||
|
changedObjectTrap = true;
|
||||||
|
object.isDisarmed = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::setMasterState(bool state)
|
||||||
|
{
|
||||||
|
changedObjectSpawn = true;
|
||||||
|
object.hasMaster = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Make this actually reflect the capabilities offered by containers in 0.6.3
|
||||||
|
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, double> Container::getItem(int i) const
|
||||||
|
{
|
||||||
|
auto &item = object.containerItems.at(i);
|
||||||
|
return make_tuple(item.refId, item.count, item.charge, item.enchantmentCharge);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Container::setItem(int i, const string &refId, int count, int charge, float enchantmentCharge)
|
||||||
|
{
|
||||||
|
auto &item = object.containerItems.at(i);
|
||||||
|
item.refId = refId;
|
||||||
|
item.count = count;
|
||||||
|
item.charge = charge;
|
||||||
|
item.enchantmentCharge = enchantmentCharge;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Container::addItem(const string &refId, int count, int charge, float enchantmentCharge)
|
||||||
|
{
|
||||||
|
mwmp::ContainerItem item;
|
||||||
|
item.refId = refId;
|
||||||
|
item.count = count;
|
||||||
|
item.charge = charge;
|
||||||
|
item.enchantmentCharge = enchantmentCharge;
|
||||||
|
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,
|
||||||
|
const std::string &cellDescription) {
|
||||||
|
return lua.getObjectCtrl().sendObjects(player, objects, Utils::getCellFromDescription(cellDescription));
|
||||||
|
});
|
||||||
|
|
||||||
|
objectCtrl.set_function("sendContainers", [&lua](shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Container>>> objects,
|
||||||
|
const std::string &cellDescription) {
|
||||||
|
return lua.getObjectCtrl().sendContainers(player, objects, Utils::getCellFromDescription(cellDescription));
|
||||||
|
});
|
||||||
|
|
||||||
|
objectCtrl.set_function("sendConsoleCommand", [&lua](shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects,
|
||||||
|
const std::string &cellDescription, const std::string &command,
|
||||||
|
bool broadcast) {
|
||||||
|
return lua.getObjectCtrl().sendConsoleCommand(player, objects, Utils::getCellFromDescription(cellDescription),
|
||||||
|
command, broadcast);
|
||||||
|
});
|
||||||
|
objectCtrl.set_function("requestContainers", [&lua](shared_ptr<Player> player) {
|
||||||
|
lua.getObjectCtrl().requestContainers(player);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<vector<shared_ptr<Object>>> ObjectController::copyObjects(mwmp::BaseObjectList &objectList)
|
||||||
|
{
|
||||||
|
auto objects = make_shared<vector<shared_ptr<Object>>>();
|
||||||
|
|
||||||
|
for (auto &obj : objectList.baseObjects)
|
||||||
|
{
|
||||||
|
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::BaseObjectList &objectList)
|
||||||
|
{
|
||||||
|
auto containers = make_shared<vector<shared_ptr<Container>>>();
|
||||||
|
|
||||||
|
for (auto &obj : objectList.baseObjects)
|
||||||
|
{
|
||||||
|
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, const ESM::Cell &cell, bool broadcast)
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
DOOR_STATE = 0,
|
||||||
|
DOOR_DESTINATION,
|
||||||
|
OBJECT_STATE,
|
||||||
|
OBJECT_SCALE,
|
||||||
|
OBJECT_TRAP,
|
||||||
|
OBJECT_LOCK,
|
||||||
|
OBJECT_DELETE,
|
||||||
|
OBJECT_SPAWN,
|
||||||
|
OBJECT_PLACE,
|
||||||
|
LAST
|
||||||
|
};
|
||||||
|
mwmp::BaseObjectList objectLists[Type::LAST];
|
||||||
|
bool changed[Type::LAST];
|
||||||
|
|
||||||
|
for (auto &objectList : objectLists)
|
||||||
|
{
|
||||||
|
objectList.action = mwmp::BaseObjectList::Action::Set;
|
||||||
|
objectList.guid = player->guid;
|
||||||
|
objectList.cell = 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;
|
||||||
|
objectLists[Type::DOOR_STATE].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedDoorDestination && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::DOOR_DESTINATION] = true;
|
||||||
|
objectLists[Type::DOOR_DESTINATION].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectState && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_STATE] = true;
|
||||||
|
objectLists[Type::OBJECT_STATE].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectScale && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_SCALE] = true;
|
||||||
|
objectLists[Type::OBJECT_SCALE].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectTrap && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_TRAP] = true;
|
||||||
|
objectLists[Type::OBJECT_TRAP].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectLock && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_LOCK] = true;
|
||||||
|
objectLists[Type::OBJECT_LOCK].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectDelete && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_DELETE] = true;
|
||||||
|
objectLists[Type::OBJECT_DELETE].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectSpawn && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_SPAWN] = true;
|
||||||
|
objectLists[Type::OBJECT_SPAWN].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
if (object->changedObjectPlace && validNewObjOrCopy)
|
||||||
|
{
|
||||||
|
changed[Type::OBJECT_PLACE] = true;
|
||||||
|
objectLists[Type::OBJECT_PLACE].baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto worldCtrl = mwmp::Networking::get().getObjectPacketController();
|
||||||
|
|
||||||
|
if (changed[Type::DOOR_STATE])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_DOOR_STATE);
|
||||||
|
auto &objectList = objectLists[Type::DOOR_STATE];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::DOOR_DESTINATION])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_DOOR_DESTINATION);
|
||||||
|
auto &objectList = objectLists[Type::DOOR_DESTINATION];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_STATE])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_STATE);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_STATE];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_SCALE])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_SCALE);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_SCALE];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_TRAP])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_TRAP);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_TRAP];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_LOCK])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_LOCK);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_LOCK];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_DELETE])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_DELETE);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_DELETE];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_SCALE])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_SPAWN);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_SCALE];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
if (changed[Type::OBJECT_PLACE])
|
||||||
|
{
|
||||||
|
auto packet = worldCtrl->GetPacket(ID_OBJECT_PLACE);
|
||||||
|
auto &objectList = objectLists[Type::OBJECT_PLACE];
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectController::sendConsoleCommand(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Object>>> objects,
|
||||||
|
const ESM::Cell &cell, const std::string &consoleCommand, bool broadcast)
|
||||||
|
{
|
||||||
|
|
||||||
|
mwmp::BaseObjectList objectList;
|
||||||
|
objectList.cell = cell;
|
||||||
|
objectList.consoleCommand = consoleCommand;
|
||||||
|
objectList.guid = player->guid;
|
||||||
|
|
||||||
|
for (auto &object : *objects)
|
||||||
|
objectList.baseObjects.push_back(object->object);
|
||||||
|
|
||||||
|
auto packet = mwmp::Networking::get().getObjectPacketController()->GetPacket(ID_CONSOLE_COMMAND);
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectController::sendContainers(shared_ptr<Player> player, shared_ptr<vector<shared_ptr<Container>>> objects,
|
||||||
|
const ESM::Cell &cell, bool broadcast)
|
||||||
|
{
|
||||||
|
|
||||||
|
mwmp::BaseObjectList objectList;
|
||||||
|
objectList.cell = cell;
|
||||||
|
objectList.action = mwmp::BaseObjectList::Action::Set;
|
||||||
|
objectList.guid = player->guid;
|
||||||
|
|
||||||
|
for (auto &object : *objects)
|
||||||
|
{
|
||||||
|
bool validNewObjOrCopy = (!object->copied && object->changedBase) || object->copied;
|
||||||
|
if (object->changed && validNewObjOrCopy)
|
||||||
|
objectList.baseObjects.push_back(object->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto packet = mwmp::Networking::get().getObjectPacketController()->GetPacket(ID_CONTAINER);
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(false);
|
||||||
|
|
||||||
|
if (broadcast)
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectController::requestContainers(shared_ptr<Player> player)
|
||||||
|
{
|
||||||
|
mwmp::BaseObjectList objectList;
|
||||||
|
objectList.action = mwmp::BaseObjectList::Action::Request;
|
||||||
|
objectList.guid = player->guid;
|
||||||
|
objectList.cell = player->cell;
|
||||||
|
|
||||||
|
auto packet = mwmp::Networking::get().getObjectPacketController()->GetPacket(ID_CONTAINER);
|
||||||
|
packet->setObjectList(&objectList);
|
||||||
|
packet->Send(objectList.guid);
|
||||||
|
}
|
@ -0,0 +1,130 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <components/openmw-mp/Base/BaseObject.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class LuaState;
|
||||||
|
class Player;
|
||||||
|
|
||||||
|
class BaseObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BaseObject();
|
||||||
|
std::string getRefId() const;
|
||||||
|
void setRefId(const std::string &refId);
|
||||||
|
|
||||||
|
unsigned getRefNum() const;
|
||||||
|
void setRefNum(unsigned refNum);
|
||||||
|
|
||||||
|
unsigned getMpNum() const;
|
||||||
|
void setMpNum(unsigned mpNum);
|
||||||
|
|
||||||
|
RakNet::RakNetGUID getGuid() const;
|
||||||
|
void setGuid(const RakNet::RakNetGUID &guid);
|
||||||
|
|
||||||
|
//void setEventCell(const std::string &cellDescription);
|
||||||
|
|
||||||
|
|
||||||
|
mwmp::BaseObject 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);
|
||||||
|
|
||||||
|
float getEnchantmentCharge() const;
|
||||||
|
void setEnchantmentCharge(float enchantmentCharge);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
bool hasContainer() const;
|
||||||
|
|
||||||
|
void setTeleportState(bool state);
|
||||||
|
void setDoorDestination(const std::string &cellDescription, float posX, float posY, float posZ, float rotX, float rotY, float rotZ);
|
||||||
|
|
||||||
|
void setDisarmState(bool state);
|
||||||
|
void setMasterState(bool state);
|
||||||
|
|
||||||
|
bool changedDoorState, changedDoorDestination, 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, double> getItem(int i) const;
|
||||||
|
void addItem(const std::string &refId, int count, int charge, float enchantmentCharge);
|
||||||
|
|
||||||
|
void setItem(int i, const std::string &refId, int count, int charge, float enchantmentCharge);
|
||||||
|
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::BaseObjectList &objectList);
|
||||||
|
std::shared_ptr<std::vector<std::shared_ptr<Container>>> copyContainers(mwmp::BaseObjectList &objectList);
|
||||||
|
|
||||||
|
void sendObjects(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Object>>> objects,
|
||||||
|
const ESM::Cell &cell, bool broadcast = false);
|
||||||
|
void sendConsoleCommand(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Object>>> objects,
|
||||||
|
const ESM::Cell &cell, const std::string &consoleCommand, bool broadcast = false);
|
||||||
|
void sendContainers(std::shared_ptr<Player> player, std::shared_ptr<std::vector<std::shared_ptr<Container>>> objects,
|
||||||
|
const ESM::Cell &cell, bool broadcast = false);
|
||||||
|
|
||||||
|
void requestContainers(std::shared_ptr<Player> player);
|
||||||
|
};
|
@ -0,0 +1,148 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 12.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Players.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
Players::Store Players::store;
|
||||||
|
std::queue<Player*> Players::updateQueue;
|
||||||
|
|
||||||
|
void Players::Init(LuaState &lua)
|
||||||
|
{
|
||||||
|
sol::table playersTable = lua.getState()->create_named_table("Players");
|
||||||
|
playersTable.set_function("getByPID", [](int pid) { return Players::getPlayerByPID(pid).get(); });
|
||||||
|
playersTable.set_function("getByGUID", [](RakNet::RakNetGUID guid) { return Players::getPlayerByGUID(guid).get(); });
|
||||||
|
playersTable.set_function("for_each", [](sol::function func)
|
||||||
|
{
|
||||||
|
for (shared_ptr<Player> player : store)
|
||||||
|
func(player);
|
||||||
|
});
|
||||||
|
|
||||||
|
playersTable.set_function("size", &Players::size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_TRACE, "%d references: %d", guid.g, it->use_count());
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleter(Player *pl)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Player %lu deleted", pl->guid.g);
|
||||||
|
delete pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Player> Players::addPlayer(RakNet::RakNetGUID guid)
|
||||||
|
{
|
||||||
|
const int maxConnections = 65535;
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Creating new player with guid %lu", guid.g);
|
||||||
|
|
||||||
|
auto player = shared_ptr<Player>(new Player(guid), deleter);
|
||||||
|
|
||||||
|
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_VERBOSE, "Marking player (pid %i) for deletion", pid);
|
||||||
|
auto &ls = store.get<ByID>();
|
||||||
|
auto it = ls.find(pid);
|
||||||
|
if (it != ls.end())
|
||||||
|
{
|
||||||
|
(*it)->markedForDeletion = true;
|
||||||
|
mwmp::Networking::get().getState().getState()->collect_garbage();
|
||||||
|
size_t useCount = it->use_count();
|
||||||
|
ls.erase(it);
|
||||||
|
LOG_APPEND(Log::LOG_TRACE, "- references: %d", useCount - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Players::deletePlayerByGUID(RakNet::RakNetGUID guid)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Marking player (guid %lu) for deletion", guid.g);
|
||||||
|
auto &ls = store.get<ByGUID>();
|
||||||
|
auto it = ls.find(guid.g);
|
||||||
|
if (it != ls.end())
|
||||||
|
{
|
||||||
|
(*it)->markedForDeletion = true;
|
||||||
|
mwmp::Networking::get().getState().getState()->collect_garbage();
|
||||||
|
size_t useCount = it->use_count();
|
||||||
|
ls.erase(it);
|
||||||
|
LOG_APPEND(Log::LOG_TRACE, "- references: %d", useCount - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Players::for_each(std::function<void (Player *)> func)
|
||||||
|
{
|
||||||
|
for (auto &player : store)
|
||||||
|
func(player.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Players::processUpdated()
|
||||||
|
{
|
||||||
|
while (!updateQueue.empty())
|
||||||
|
{
|
||||||
|
Player *player = updateQueue.front();
|
||||||
|
updateQueue.pop();
|
||||||
|
player->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Players::addToQueue(Player *player)
|
||||||
|
{
|
||||||
|
updateQueue.push(player);
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// 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 <queue>
|
||||||
|
#include "Player.hpp"
|
||||||
|
|
||||||
|
class LuaState;
|
||||||
|
|
||||||
|
|
||||||
|
class Players
|
||||||
|
{
|
||||||
|
friend class Player;
|
||||||
|
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(Player *)> func);
|
||||||
|
|
||||||
|
static void processUpdated();
|
||||||
|
private:
|
||||||
|
static void addToQueue(Player *player);
|
||||||
|
|
||||||
|
static Store store;
|
||||||
|
static std::queue<Player*> updateQueue;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,154 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 25.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
|
#include "Script/LuaState.hpp"
|
||||||
|
#include "Networking.hpp"
|
||||||
|
|
||||||
|
#include "Quests.hpp"
|
||||||
|
#include "Player.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
mwmp::JournalItem::Type JournalItem::getType() const
|
||||||
|
{
|
||||||
|
return item.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JournalItem::setType(mwmp::JournalItem::Type 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,
|
||||||
|
"getKill", &Quests::getKill
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quests::Quests(Player *player) : BaseMgr(player), changedKills(false), changedJournal(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Quests::processUpdate()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Quests::setJournalItem(unsigned int id, JournalItem item)
|
||||||
|
{
|
||||||
|
player->journalChanges.journalItems.at(id) = item.item;
|
||||||
|
changedJournal = true;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<std::string, int> Quests::getKill(unsigned int i) const
|
||||||
|
{
|
||||||
|
auto & kill = player->killChanges.kills.at(i);
|
||||||
|
return std::make_tuple(kill.refId, kill.number);
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 25.08.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <components/openmw-mp/Base/BasePlayer.hpp>
|
||||||
|
#include "BaseMgr.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);
|
||||||
|
|
||||||
|
mwmp::JournalItem::Type getType() const;
|
||||||
|
void setType(mwmp::JournalItem::Type type);
|
||||||
|
|
||||||
|
std::string getActorRefId() const;
|
||||||
|
void setActorRefId(const std::string &refid);
|
||||||
|
|
||||||
|
|
||||||
|
mwmp::JournalItem item;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Quests final: public BaseMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init(LuaState &lua);
|
||||||
|
public:
|
||||||
|
explicit Quests(Player *player);
|
||||||
|
|
||||||
|
|
||||||
|
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::tuple<std::string, int> getKill(unsigned int i) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processUpdate() final;
|
||||||
|
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,103 @@
|
|||||||
|
//
|
||||||
|
// Created by koncord on 08.08.17.
|
||||||
|
//
|
||||||
|
#include "CommandController.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/spirit/home/x3.hpp>
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#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(Misc::StringUtils::lowerCase(command), func, helpMessage);
|
||||||
|
};
|
||||||
|
|
||||||
|
cmdCtrlTable["unregisterCommand"] = [&lua](const std::string &command) {
|
||||||
|
lua.getCmdCtrl().unregisterCommand(Misc::StringUtils::lowerCase(command));
|
||||||
|
};
|
||||||
|
|
||||||
|
cmdCtrlTable["hasCommand"] = [&lua](const std::string &command) {
|
||||||
|
return lua.getCmdCtrl().hasCommand(Misc::StringUtils::lowerCase(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(const std::shared_ptr<Player> &player,
|
||||||
|
const std::string &message, unsigned channel)
|
||||||
|
{
|
||||||
|
char cmdChar = message[0];
|
||||||
|
if (message.size() < 2 || (cmdChar != '/' && cmdChar != '!'))
|
||||||
|
return make_pair(ExecResult::NOT_CMD, "");
|
||||||
|
|
||||||
|
auto tokens = cmdParser(message);
|
||||||
|
|
||||||
|
auto cmd = commands.find(Misc::StringUtils::lowerCase(&tokens[0][1]));
|
||||||
|
if (cmd != commands.end())
|
||||||
|
{
|
||||||
|
tokens.pop_front();
|
||||||
|
bool result = cmd->second.func(player, sol::as_table(move(tokens)), channel);
|
||||||
|
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))
|
||||||
|
Utils::throwError("failed to parse message: "+ message);*/
|
||||||
|
|
||||||
|
if (!x3::parse(message.cbegin(), message.cend(), arguments, ret))
|
||||||
|
Utils::throwError("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(const std::shared_ptr<Player> &player, const std::string &message, unsigned channel);
|
||||||
|
private:
|
||||||
|
std::deque<std::string> cmdParser(const std::string &message);
|
||||||
|
Container commands;
|
||||||
|
};
|
@ -0,0 +1,158 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
lua.getEventCtrl().registerEvent(event, env, func, false);
|
||||||
|
};
|
||||||
|
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 &moduleName, sol::table data) {
|
||||||
|
lua.getEventCtrl().raiseEvent(event, data, moduleName);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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_REPUTATION),
|
||||||
|
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_QUICKKEYS),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_TOPIC),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_DISPOSITION),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_BOOK),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_MISCELLANEOUS),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_INTERACTION),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_REST),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_SENDMESSAGE),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_ENDCHARGEN),
|
||||||
|
ADD_CORE_EVENT(ON_PLAYER_WEATHER),
|
||||||
|
ADD_CORE_EVENT(ON_RECORD_DYNAMIC),
|
||||||
|
ADD_CORE_EVENT(ON_CHANNEL_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),
|
||||||
|
ADD_CORE_EVENT(ON_WORLD_MAP)
|
||||||
|
);
|
||||||
|
|
||||||
|
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)
|
||||||
|
Utils::throwError("Event " + to_string(i) + " is not registered");
|
||||||
|
#endif
|
||||||
|
events[i]; // create core event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventController::registerEvent(int event, sol::environment &env, sol::function& func, bool needsOldState)
|
||||||
|
{
|
||||||
|
auto iter = events.find(event);
|
||||||
|
if (iter != events.end())
|
||||||
|
iter->second.push(env, func, needsOldState);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 &moduleName)
|
||||||
|
{
|
||||||
|
auto iter = events.find(id);
|
||||||
|
if (iter != events.end())
|
||||||
|
{
|
||||||
|
if (!moduleName.empty())
|
||||||
|
{
|
||||||
|
auto f = std::find_if(iter->second.begin(), iter->second.end(), [&moduleName](const auto &item){
|
||||||
|
return item.env["ModuleName"]["name"] == moduleName;
|
||||||
|
});
|
||||||
|
if (f != iter->second.end())
|
||||||
|
f->fn.call(data); // call only specified mod
|
||||||
|
}
|
||||||
|
iter->second.call(CallbackCollection::type_tag<void>(), false, data); // call all registered events with this id
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cerr << "Event with id: " << id << " is not registered" << endl;
|
||||||
|
}
|
@ -0,0 +1,204 @@
|
|||||||
|
//
|
||||||
|
// 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_REPUTATION,
|
||||||
|
ON_PLAYER_EQUIPMENT,
|
||||||
|
ON_PLAYER_INVENTORY,
|
||||||
|
ON_PLAYER_JOURNAL,
|
||||||
|
ON_PLAYER_FACTION,
|
||||||
|
ON_PLAYER_SHAPESHIFT,
|
||||||
|
ON_PLAYER_SPELLBOOK,
|
||||||
|
ON_PLAYER_QUICKKEYS,
|
||||||
|
ON_PLAYER_TOPIC,
|
||||||
|
ON_PLAYER_DISPOSITION,
|
||||||
|
ON_PLAYER_BOOK,
|
||||||
|
ON_PLAYER_MISCELLANEOUS,
|
||||||
|
ON_PLAYER_INTERACTION,
|
||||||
|
ON_PLAYER_REST,
|
||||||
|
ON_PLAYER_SENDMESSAGE,
|
||||||
|
ON_PLAYER_ENDCHARGEN,
|
||||||
|
ON_PLAYER_WEATHER,
|
||||||
|
|
||||||
|
ON_RECORD_DYNAMIC,
|
||||||
|
|
||||||
|
ON_CHANNEL_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,
|
||||||
|
|
||||||
|
ON_WORLD_MAP,
|
||||||
|
|
||||||
|
LAST,
|
||||||
|
};
|
||||||
|
const int FIRST = ON_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallbackCollection // todo: add sort by dependencies
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct CBType
|
||||||
|
{
|
||||||
|
sol::environment env;
|
||||||
|
sol::function fn;
|
||||||
|
bool needsOldState;
|
||||||
|
CBType(sol::environment _env, sol::function _fn, bool _needsOldState): env(_env), fn(_fn), needsOldState(_needsOldState) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<CBType> Container;
|
||||||
|
typedef Container::iterator Iterator;
|
||||||
|
typedef Container::const_iterator CIterator;
|
||||||
|
|
||||||
|
template<typename> struct type_tag {};
|
||||||
|
|
||||||
|
void push(sol::environment &env, sol::function &func, bool needsOldState) { functions.emplace_back(env, func, needsOldState); }
|
||||||
|
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; }
|
||||||
|
|
||||||
|
template<typename... Args, typename OldData>
|
||||||
|
void callWOld(const OldData &oldData, Args&&... args)
|
||||||
|
{
|
||||||
|
lastCalled = functions.end();
|
||||||
|
_stop = false;
|
||||||
|
for (CIterator iter = functions.begin(); iter != functions.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (!_stop)
|
||||||
|
{
|
||||||
|
if (!iter->needsOldState)
|
||||||
|
{
|
||||||
|
iter->fn.call(std::forward<Args>(args)...);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
iter->fn.call(std::forward<Args>(args)..., oldData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastCalled = iter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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->fn.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->fn.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, bool needsOldState);
|
||||||
|
CallbackCollection& GetEvents(Event event);
|
||||||
|
Event createEvent();
|
||||||
|
void raiseEvent(Event id, sol::table data, const std::string &moduleName = "");
|
||||||
|
void stop(int event);
|
||||||
|
|
||||||
|
template<Event event, bool canProvideOldState = false, typename R = void, typename... Args>
|
||||||
|
R Call(Args&&... args)
|
||||||
|
{
|
||||||
|
if (canProvideOldState)
|
||||||
|
events.at(event).callWOld(std::forward<Args>(args)...);
|
||||||
|
else
|
||||||
|
return events.at(event).call(CallbackCollection::type_tag<R>{}, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<Event event, bool canProvideOldState = false, typename R = void>
|
||||||
|
R Call()
|
||||||
|
{
|
||||||
|
return events.at(event).call(CallbackCollection::type_tag<R>{});
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Container events;
|
||||||
|
Event lastEvent = CoreEvent::LAST;
|
||||||
|
LuaState *luaCtrl;
|
||||||
|
};
|
@ -1,367 +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).equipmentItems[slot].refId.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ActorFunctions::GetActorEquipmentItemCount(unsigned int i, unsigned short slot) noexcept
|
|
||||||
{
|
|
||||||
return readActorList->baseActors.at(i).equipmentItems[slot].count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ActorFunctions::GetActorEquipmentItemCharge(unsigned int i, unsigned short slot) noexcept
|
|
||||||
{
|
|
||||||
return readActorList->baseActors.at(i).equipmentItems[slot].charge;
|
|
||||||
}
|
|
||||||
|
|
||||||
double ActorFunctions::GetActorEquipmentItemEnchantmentCharge(unsigned int i, unsigned short slot) noexcept
|
|
||||||
{
|
|
||||||
return readActorList->baseActors.at(i).equipmentItems[slot].enchantmentCharge;
|
|
||||||
}
|
|
||||||
|
|
||||||
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::SetActorAIAction(unsigned int action) noexcept
|
|
||||||
{
|
|
||||||
tempActor.aiAction = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActorFunctions::SetActorAITargetToPlayer(unsigned short pid) noexcept
|
|
||||||
{
|
|
||||||
Player *player;
|
|
||||||
GET_PLAYER(pid, player, );
|
|
||||||
|
|
||||||
tempActor.hasAiTarget = true;
|
|
||||||
tempActor.aiTarget.isPlayer = true;
|
|
||||||
|
|
||||||
tempActor.aiTarget.guid = player->guid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActorFunctions::SetActorAITargetToActor(int refNumIndex, int mpNum) noexcept
|
|
||||||
{
|
|
||||||
tempActor.hasAiTarget = true;
|
|
||||||
tempActor.aiTarget.isPlayer = false;
|
|
||||||
|
|
||||||
tempActor.aiTarget.refNumIndex = refNumIndex;
|
|
||||||
tempActor.aiTarget.mpNum = mpNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActorFunctions::EquipActorItem(unsigned short slot, const char *refId, unsigned int count, int charge, double enchantmentCharge) noexcept
|
|
||||||
{
|
|
||||||
tempActor.equipmentItems[slot].refId = refId;
|
|
||||||
tempActor.equipmentItems[slot].count = count;
|
|
||||||
tempActor.equipmentItems[slot].charge = charge;
|
|
||||||
tempActor.equipmentItems[slot].enchantmentCharge = enchantmentCharge;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ActorFunctions::UnequipActorItem(unsigned short slot) noexcept
|
|
||||||
{
|
|
||||||
ActorFunctions::EquipActorItem(slot, "", 0, -1, -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::SendActorAI() noexcept
|
|
||||||
{
|
|
||||||
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_AI)->setActorList(&writeActorList);
|
|
||||||
mwmp::Networking::get().getActorPacketController()->GetPacket(ID_ACTOR_AI)->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,614 +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},\
|
|
||||||
{"GetActorEquipmentItemEnchantmentCharge", ActorFunctions::GetActorEquipmentItemEnchantmentCharge},\
|
|
||||||
\
|
|
||||||
{"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},\
|
|
||||||
\
|
|
||||||
{"SetActorAIAction", ActorFunctions::SetActorAIAction},\
|
|
||||||
{"SetActorAITargetToPlayer", ActorFunctions::SetActorAITargetToPlayer},\
|
|
||||||
{"SetActorAITargetToActor", ActorFunctions::SetActorAITargetToActor},\
|
|
||||||
\
|
|
||||||
{"EquipActorItem", ActorFunctions::EquipActorItem},\
|
|
||||||
{"UnequipActorItem", ActorFunctions::UnequipActorItem},\
|
|
||||||
\
|
|
||||||
{"AddActor", ActorFunctions::AddActor},\
|
|
||||||
\
|
|
||||||
{"SendActorList", ActorFunctions::SendActorList},\
|
|
||||||
{"SendActorAuthority", ActorFunctions::SendActorAuthority},\
|
|
||||||
{"SendActorPosition", ActorFunctions::SendActorPosition},\
|
|
||||||
{"SendActorStatsDynamic", ActorFunctions::SendActorStatsDynamic},\
|
|
||||||
{"SendActorEquipment", ActorFunctions::SendActorEquipment},\
|
|
||||||
{"SendActorAI", ActorFunctions::SendActorAI},\
|
|
||||||
{"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 Get the enchantment 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 enchantment charge.
|
|
||||||
*/
|
|
||||||
static double GetActorEquipmentItemEnchantmentCharge(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 Set the AI action of the temporary actor stored on the server.
|
|
||||||
*
|
|
||||||
* \param action The new action.
|
|
||||||
* \return void
|
|
||||||
*/
|
|
||||||
static void SetActorAIAction(unsigned int action) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set a player as the AI target of the temporary actor stored on the server.
|
|
||||||
*
|
|
||||||
* \param pid The player ID.
|
|
||||||
* \return void
|
|
||||||
*/
|
|
||||||
static void SetActorAITargetToPlayer(unsigned short pid) noexcept;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Set another actor as the AI target of the temporary actor stored on the server.
|
|
||||||
*
|
|
||||||
* \param refNumIndex The refNumIndex of the target actor.
|
|
||||||
* \param mpNum The mpNum of the target actor.
|
|
||||||
* \return void
|
|
||||||
*/
|
|
||||||
static void SetActorAITargetToActor(int refNumIndex, int mpNum) 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.
|
|
||||||
* \param enchantmentCharge The enchantment charge of the item.
|
|
||||||
* \return void
|
|
||||||
*/
|
|
||||||
static void EquipActorItem(unsigned short slot, const char* refId, unsigned int count, int charge, double enchantmentCharge = -1) 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 ActorAI packet.
|
|
||||||
*
|
|
||||||
* It is sent only to the player for whom the current actor list was initialized.
|
|
||||||
*
|
|
||||||
* \return void
|
|
||||||
*/
|
|
||||||
static void SendActorAI() 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,55 +0,0 @@
|
|||||||
#include "Books.hpp"
|
|
||||||
|
|
||||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
|
||||||
|
|
||||||
#include <apps/openmw-mp/Script/ScriptFunctions.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,125 +0,0 @@
|
|||||||
#include "Cells.hpp"
|
|
||||||
|
|
||||||
#include <components/openmw-mp/Log.hpp>
|
|
||||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
|
||||||
|
|
||||||
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
|
|
||||||
#include <apps/openmw-mp/Player.hpp>
|
|
||||||
#include <apps/openmw-mp/Networking.hpp>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
static std::string tempCellDescription;
|
|
||||||
|
|
||||||
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::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);
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
#ifndef OPENMW_CELLAPI_HPP
|
|
||||||
#define OPENMW_CELLAPI_HPP
|
|
||||||
|
|
||||||
#include "../Types.hpp"
|
|
||||||
|
|
||||||
#define CELLAPI \
|
|
||||||
{"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},\
|
|
||||||
\
|
|
||||||
{"SendCell", CellFunctions::SendCell}
|
|
||||||
|
|
||||||
|
|
||||||
class CellFunctions
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \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 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;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //OPENMW_CELLAPI_HPP
|
|
@ -1,137 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by koncord on 29.08.16.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "CharClass.hpp"
|
|
||||||
|
|
||||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
|
||||||
|
|
||||||
#include <apps/openmw-mp/Networking.hpp>
|
|
||||||
#include <apps/openmw-mp/Script/ScriptFunctions.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,47 +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::CleanChatForPid(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,84 +0,0 @@
|
|||||||
#include "Dialogue.hpp"
|
|
||||||
|
|
||||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
|
||||||
|
|
||||||
#include <apps/openmw-mp/Script/ScriptFunctions.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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogueFunctions::PlayAnimation(unsigned short pid, const char* groupname, int mode, int count, bool persist) noexcept
|
|
||||||
{
|
|
||||||
Player *player;
|
|
||||||
GET_PLAYER(pid, player, );
|
|
||||||
|
|
||||||
player->animation.groupname = groupname;
|
|
||||||
player->animation.mode = mode;
|
|
||||||
player->animation.count = count;
|
|
||||||
player->animation.persist = persist;
|
|
||||||
|
|
||||||
mwmp::PlayerPacket *packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_ANIM_PLAY);
|
|
||||||
packet->setPlayer(player);
|
|
||||||
packet->Send(false);
|
|
||||||
player->sendToLoaded(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DialogueFunctions::PlaySpeech(unsigned short pid, const char* sound) noexcept
|
|
||||||
{
|
|
||||||
Player *player;
|
|
||||||
GET_PLAYER(pid, player, );
|
|
||||||
|
|
||||||
player->sound = sound;
|
|
||||||
|
|
||||||
mwmp::PlayerPacket *packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SPEECH);
|
|
||||||
packet->setPlayer(player);
|
|
||||||
packet->Send(false);
|
|
||||||
player->sendToLoaded(packet);
|
|
||||||
}
|
|
@ -1,75 +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},\
|
|
||||||
\
|
|
||||||
{"PlayAnimation", DialogueFunctions::PlayAnimation},\
|
|
||||||
{"PlaySpeech", DialogueFunctions::PlaySpeech}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
static void PlayAnimation(unsigned short pid, const char* groupname, int mode = 0, int count = 1, bool persist = false) noexcept;
|
|
||||||
static void PlaySpeech(unsigned short pid, const char* sound) noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //OPENMW_DIALOGUEAPI_HPP
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue