Compare commits

...

29 Commits

Author SHA1 Message Date
David Cernat 8aad93b904
Merge pull request #519 from TES3MP/0.7.0-alpha
[General] Update positions for dead players on other clients
5 years ago
David Cernat 3effd5f1ff [General] Update positions for dead players on other clients
Dead players will now show up at the correct cell and position for living players, making server scripts that allow players to revive each other much more functional.
5 years ago
David Cernat 4692f29b9d
Merge pull request #517 from uramer/0.7.0markers
update player map markers when client changes cell
5 years ago
David Cernat 03d377ec54
Merge pull request #518 from TES3MP/0.7.0-alpha
[General] Rename CellReplace packet into CellReset
5 years ago
David Cernat 8ff2d1b829 [General] Rename CellReplace packet into CellReset 5 years ago
David Cernat cb82318c36 [General] Fix problems with Utils::getArchitectureType() 5 years ago
uramer 3b2098382b update player map markers when client changes cell 5 years ago
David Cernat cb5e24e6c5
Merge pull request #516 from TES3MP/0.7.0-alpha
[Server] Add GetMillisecondsSinceServerStart() server function
5 years ago
David Cernat 91f82d845c [Server] Add GetMillisecondsSinceServerStart() server function 5 years ago
David Cernat d35026bbf5
Merge pull request #515 from TES3MP/0.7.0-alpha
0.7.0 alpha
5 years ago
David Cernat bd677726bf [Server] Add StatsFunctions that get/set damage to attributes/skills 5 years ago
David Cernat 9fc4c83858 [Client] Send skill/attribute packets when skills/attributes are damaged 5 years ago
David Cernat ece39748de [Server] Fix typo causing recursion in deprecated actor list function 5 years ago
David Cernat 5c4d3df551 [Server] Deprecate DoesFileExist(), add DoesFilePathExist() 5 years ago
David Cernat 2cdabddc0e [Server] Move most MiscellaneousFunctions to ServerFunctions 5 years ago
David Cernat b46767de6e [Server] Clean up recent additions to ServerFunctions 5 years ago
David Cernat 911079e0bc
Merge pull request #512 from TES3MP/0.7.0-alpha
0.7.0 alpha
5 years ago
David Cernat 331fa86844 [Server] Call OnServerPostInit after OnRequestDataFileList
This allows different actions to be taken in OnServerPostInit based on what the data files being used are.
5 years ago
David Cernat a0ec9dfd2e [Server] Rename OnRequestPluginList into OnRequestDataFileList 5 years ago
David Cernat 986528c67d [Server] Add error message as argument to OnServerScriptCrash 5 years ago
David Cernat 552a94a0ca [Server] Add OnServerScriptCrash script event 5 years ago
David Cernat a508a0faf8 [Server] Turn GetArguments() from ScriptFunctions into Utils function 5 years ago
David Cernat dcbc9d1831 [Client] Print cells for actor deaths 5 years ago
David Cernat 828c52138f [Documentation] Update readme and credits
According to some legal advice I've received, the "TES3MP Team" is too ambiguous of a legal entity, so – with Koncord's agreement – the copyright is now assigned specifically to us, the project's developers.
5 years ago
David Cernat 69e7d3f2a7 [Documentation] Update credits 5 years ago
David Cernat f3b8a5b909 [General] Check integrity of credits only on Windows clients
This avoids the problems that were encountered in Linux and macOS builds regarding this check while also still addressing the scenario where official Windows builds had their credits modified by people unrelated to the project.
5 years ago
David Cernat a0ad0b29bc Merge branch '0.7.0' of https://github.com/TES3MP/openmw-tes3mp into 0.7.0 5 years ago
David Cernat 222837976c [Server] Fix type name warning for Player
The warning in Visual Studio was: "'Player': type name first seen using 'class' now seen using 'struct'"
5 years ago
Koncord 77386525f2 [General] Update Travis CI 5 years ago

@ -4,7 +4,7 @@ os:
osx_image: xcode9.4
language: cpp
sudo: required
dist: trusty
dist: xenial
branches:
only:
- master
@ -15,18 +15,18 @@ env:
global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg=
- secure: 1QK0yVyoOB+gf2I7XzvhXu9w/5lq4stBXIwJbVCTjz4Q4XVHCosURaW1MAgKzMrPnbFEwjyn5uQ8BwsvvfkuN1AZD0YXITgc7gyI+J1wQ/p/ljxRxglakU6WEgsTs2J5z9UmGac4YTXg+quK7YP3rv+zuGim2I2rhzImejyzp0Ym3kRCnNcy+SGBsiRaevRJMe00Ch8zGAbEhduQGeSoS6W0rcu02DNlQKiq5NktWsXR+TWWWVfIeIlQR/lbPsCd0pdxMaMv2QCY0rVbwrYxWJwr/Qe45dAdWp+8/C3PbXpeMSGxlLa33nJNX4Lf/djxbjm8KWk6edaXPajrjR/0iwcpwq0jg2Jt6XfEdnJt35F1gpXlc04sxStjG45uloOKCFYT0wdhIO1Lq+hDP54wypQl+JInd5qC001O7pwhVxO36EgKWqo8HD+BqGDBwsNj2engy9Qcp3wO6G0rLBPB3CrZsk9wrHVv5cSiQSLMhId3Xviu3ZI2qEDA+kgTvxrKrsnMj4bILVCyG5Ka2Mj22wIDW9e8oIab9oTdujax3DTN1GkD6QuOAGzwDsNwGASsgfoeZ+FUhgM75RlBWGMilgkmnF7EJ0oAXLEpjtABnEr2d4qHv+y08kOuTDBLB9ExzCIj024dYYYNLZrqPKx0ncHuCMG2QNj2aJAJEZtj1rQ=
addons:
apt:
sources:
- sourceline: 'ppa:openmw/openmw'
- sourceline: 'ppa:rakhimov/boost'
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages: [
# Dev
cmake, clang-3.8, libunshield-dev, libtinyxml-dev,
g++-6,
cmake, clang-6.0, libunshield-dev, libtinyxml-dev,
g++-8,
# Tests
libgtest-dev, google-mock,
# Boost
@ -45,7 +45,7 @@ addons:
project:
name: "TES3MP/openmw-tes3mp"
description: "<Your project description here>"
notification_email: stas5978@gmail.com
notification_email: koncord@tes3mp.com
build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE"
build_command: "make -j3"
branch_pattern: coverity_scan
@ -53,21 +53,21 @@ matrix:
include:
- os: linux
env:
- ANALYZE="scan-build-3.8 --use-cc clang-3.8 --use-c++ clang++-3.8 "
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8"
- ANALYZE="scan-build-6.0 --use-cc clang-6.0 --use-c++ clang++-6.0 "
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
compiler: clang
- os: linux
env:
- MATRIX_CC="CC=gcc-6 && CXX=g++-6"
- MATRIX_CC="CC=gcc-8 && CXX=g++-8"
- os: linux
env:
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8"
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
allow_failures:
- env:
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8"
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
- env:
- ANALYZE="scan-build-3.8 --use-cc clang-3.8 --use-c++ clang++-3.8 "
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8"
- ANALYZE="scan-build-6.0 --use-cc clang-6.0 --use-c++ clang++-6.0 "
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
before_install:
- ./CI/before_install.${TRAVIS_OS_NAME}.sh

@ -15,19 +15,8 @@ sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
cd ~/
git clone https://github.com/TES3MP/RakNet
cd RakNet
cmake . -DRAKNET_ENABLE_DLL=OFF -DRAKNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
git clone https://github.com/TES3MP/CrabNet
cd CrabNet
cmake . -DCRABNET_ENABLE_DLL=OFF -DCRABNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
make -j3
cd ~/
git clone https://github.com/Koncord/CallFF
cd CallFF
mkdir build
cd build
cmake ../
make -j3
cd ~/
wget https://github.com/zdevito/terra/releases/download/release-2016-03-25/terra-Linux-x86_64-332a506.zip
unzip terra-Linux-x86_64-332a506.zip

@ -9,8 +9,7 @@ if [ ! -z "${MATRIX_CC}" ]; then
eval "${MATRIX_CC}"
fi
export RAKNET_ROOT=~/RakNet
export Terra_ROOT=~/terra-Linux-x86_64-332a506
export RAKNET_ROOT=~/CrabNet
export CODE_COVERAGE=0
if [ ! -z "${ANALYZE}" ]; then
@ -36,7 +35,5 @@ ${ANALYZE}cmake .. \
-DBINDIR=/usr/games \
-DCMAKE_BUILD_TYPE="None" \
-DUSE_SYSTEM_TINYXML=TRUE \
-DRakNet_LIBRARY_RELEASE=~/RakNet/lib/libRakNetLibStatic.a \
-DRakNet_LIBRARY_DEBUG=~/RakNet/lib/libRakNetLibStatic.a \
-DCallFF_INCLUDES=~/CallFF/include \
-DCallFF_LIBRARY=~/CallFF/build/src/libcallff.a
-DRakNet_LIBRARY_RELEASE=~/CrabNet/lib/libRakNetLibStatic.a \
-DRakNet_LIBRARY_DEBUG=~/CrabNet/lib/libRakNetLibStatic.a

@ -2,7 +2,7 @@ TES3MP
======
Copyright (c) 2008-2015, OpenMW Team
Copyright (c) 2016-2018, TES3MP Team
Copyright (c) 2016-2019, Stanislav Zhukov & David Cernat
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=0.7.0)](https://travis-ci.org/TES3MP/openmw-tes3mp)
@ -15,7 +15,7 @@ TES3MP is a project adding multiplayer functionality to [OpenMW](https://github.
Font Licenses:
* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVu Font License.txt](https://github.com/TES3MP/openmw-tes3mp/blob/master/files/mygui/DejaVu%20Font%20License.txt) for more information)
Project Status
Project status
--------------
[Version changelog](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-changelog.md)
@ -24,25 +24,26 @@ As of version 0.7.0, TES3MP is fully playable, providing very extensive player,
Remaining gameplay problems mostly relate to AI and the synchronization of clientside script variables.
Donations
---------------
You can benefit the project by donating on Patreon to our two developers, [David Cernat](https://www.patreon.com/davidcernat) and [Koncord](https://www.patreon.com/Koncord), as well as by supporting [OpenMW](https://openmw.org).
Contributing
--------------
---------------
Development has been relatively fast, but any contribution regarding [code](https://github.com/TES3MP/openmw-tes3mp/blob/master/CONTRIBUTING.md), documentation, bug hunting or video showcases is greatly appreciated.
Helping us with documentation, bug hunting and video showcases is always greatly appreciated.
Test sessions are often advertised on [our Discord server](https://discord.gg/ECJk293) or in [our Steam group](https://steamcommunity.com/groups/mwmulti).
For code contributions, it's best to start out with modestly sized fixes and features and work your way up. There are so many different possible implementations of more major features many of which would cause undesirable code or vision conflicts with OpenMW that those should be talked over in advance with the existing developers before effort is spent on them.
Feel free to contact the [team members](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-credits.md) for any questions you might have.
Getting Started
Getting started
---------------
* [Quickstart guide](https://github.com/TES3MP/openmw-tes3mp/wiki/Quickstart-guide)
* [Steam group](https://steamcommunity.com/groups/mwmulti) and its [detailed FAQ](https://steamcommunity.com/groups/mwmulti/discussions/1/353916184342480541/)
* [TES3MP section on OpenMW forums](https://forum.openmw.org/viewforum.php?f=45)
* [Discord server](https://discord.gg/ECJk293)
* [Subreddit](https://www.reddit.com/r/tes3mp)
* [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues)
Donations
---------------
You can benefit the project by contributing to the Patreon pages of our two developers, [David Cernat](https://www.patreon.com/davidcernat) and [Koncord](https://www.patreon.com/Koncord), as well as by supporting [OpenMW](https://openmw.org).

@ -585,8 +585,8 @@ void Networking::InitQuery(std::string queryAddr, unsigned short queryPort)
void Networking::postInit()
{
Script::Call<Script::CallbackIdentity("OnRequestDataFileList")>();
Script::Call<Script::CallbackIdentity("OnServerPostInit")>();
Script::Call<Script::CallbackIdentity("OnRequestPluginList")>();
}
PacketPreInit::PluginContainer &Networking::getSamples()

@ -21,7 +21,6 @@
#include "Cell.hpp"
#include "CellController.hpp"
struct Player;
typedef std::map<RakNet::RakNetGUID, Player*> TPlayers;
typedef std::map<unsigned short, Player*> TSlots;

@ -537,7 +537,7 @@ void ActorFunctions::InitializeActorList(unsigned short pid) noexcept
void ActorFunctions::CopyLastActorListToStore() noexcept
{
CopyLastActorListToStore();
CopyReceivedActorListToStore();
}
unsigned int ActorFunctions::GetActorRefNumIndex(unsigned int index) noexcept

@ -1,38 +1,12 @@
#include "Miscellaneous.hpp"
#include <components/misc/stringops.hpp>
#include <components/openmw-mp/Log.hpp>
#include <apps/openmw-mp/Script/ScriptFunctions.hpp>
#include <apps/openmw-mp/Networking.hpp>
#include <iostream>
using namespace std;
static std::string tempFilename;
bool MiscellaneousFunctions::DoesFileExist(const char *filePath) noexcept
{
return boost::filesystem::exists(filePath);
}
const char *MiscellaneousFunctions::GetCaseInsensitiveFilename(const char *folderPath, const char *filename) noexcept
{
if (!boost::filesystem::exists(folderPath)) return "invalid";
boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
for (boost::filesystem::directory_iterator itr(folderPath); itr != end_itr; ++itr)
{
if (Misc::StringUtils::ciEqual(itr->path().filename().string(), filename))
{
tempFilename = itr->path().filename().string();
return tempFilename.c_str();
}
}
return "invalid";
}
unsigned int MiscellaneousFunctions::GetLastPlayerId() noexcept
{
return Players::getLastPlayerId();
@ -47,13 +21,3 @@ void MiscellaneousFunctions::SetCurrentMpNum(int mpNum) noexcept
{
mwmp::Networking::getPtr()->setCurrentMpNum(mpNum);
}
void MiscellaneousFunctions::LogMessage(unsigned short level, const char *message) noexcept
{
LOG_MESSAGE_SIMPLE(level, "[Script]: %s", message);
}
void MiscellaneousFunctions::LogAppend(unsigned short level, const char *message) noexcept
{
LOG_APPEND(level, "[Script]: %s", message);
}

@ -4,42 +4,15 @@
#include "../Types.hpp"
#define MISCELLANEOUSAPI \
{"DoesFileExist", MiscellaneousFunctions::DoesFileExist},\
{"GetCaseInsensitiveFilename", MiscellaneousFunctions::GetCaseInsensitiveFilename},\
\
{"GetLastPlayerId", MiscellaneousFunctions::GetLastPlayerId},\
\
{"GetCurrentMpNum", MiscellaneousFunctions::GetCurrentMpNum},\
{"SetCurrentMpNum", MiscellaneousFunctions::SetCurrentMpNum},\
\
{"LogMessage", MiscellaneousFunctions::LogMessage},\
{"LogAppend", MiscellaneousFunctions::LogAppend}
{"SetCurrentMpNum", MiscellaneousFunctions::SetCurrentMpNum}
class MiscellaneousFunctions
{
public:
/**
* \brief Check whether a certain file exists.
*
* This will be a case sensitive check on case sensitive filesystems.
*
* Whenever you want to enforce case insensitivity, use GetCaseInsensitiveFilename() instead.
*
* \return Whether the file exists or not.
*/
static bool DoesFileExist(const char *filePath) noexcept;
/**
* \brief Get the first filename in a folder that has a case insensitive match with the filename
* argument.
*
* This is used to retain case insensitivity when opening data files on Linux.
*
* \return The filename that matches.
*/
static const char *GetCaseInsensitiveFilename(const char *folderPath, const char *filename) noexcept;
/**
* \brief Get the last player ID currently connected to the server.
*
@ -75,30 +48,6 @@ public:
* \return void
*/
static void SetCurrentMpNum(int mpNum) noexcept;
/**
* \brief Write a log message with its own timestamp.
*
* It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
*
* \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
* 3 for LOG_ERROR, 4 for LOG_FATAL).
* \param message The message logged.
* \return void
*/
static void LogMessage(unsigned short level, const char *message) noexcept;
/**
* \brief Write a log message without its own timestamp.
*
* It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
*
* \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
* 3 for LOG_ERROR, 4 for LOG_FATAL).
* \param message The message logged.
* \return void
*/
static void LogAppend(unsigned short level, const char *message) noexcept;
};
#endif //OPENMW_MISCELLANEOUSAPI_HPP

@ -1,5 +1,6 @@
#include "Server.hpp"
#include <components/misc/stringops.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <components/openmw-mp/Log.hpp>
#include <components/openmw-mp/Version.hpp>
@ -9,6 +10,18 @@
#include <apps/openmw-mp/MasterClient.hpp>
#include <Script/Script.hpp>
static std::string tempFilename;
static std::chrono::high_resolution_clock::time_point startupTime = std::chrono::high_resolution_clock::now();
void ServerFunctions::LogMessage(unsigned short level, const char *message) noexcept
{
LOG_MESSAGE_SIMPLE(level, "[Script]: %s", message);
}
void ServerFunctions::LogAppend(unsigned short level, const char *message) noexcept
{
LOG_APPEND(level, "[Script]: %s", message);
}
void ServerFunctions::StopServer(int code) noexcept
{
@ -35,6 +48,40 @@ void ServerFunctions::UnbanAddress(const char *ipAddress) noexcept
mwmp::Networking::getPtr()->unbanAddress(ipAddress);
}
bool ServerFunctions::DoesFilePathExist(const char *filePath) noexcept
{
return boost::filesystem::exists(filePath);
}
const char *ServerFunctions::GetCaseInsensitiveFilename(const char *folderPath, const char *filename) noexcept
{
if (!boost::filesystem::exists(folderPath)) return "invalid";
boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
for (boost::filesystem::directory_iterator itr(folderPath); itr != end_itr; ++itr)
{
if (Misc::StringUtils::ciEqual(itr->path().filename().string(), filename))
{
tempFilename = itr->path().filename().string();
return tempFilename.c_str();
}
}
return "invalid";
}
const char* ServerFunctions::GetDataPath() noexcept
{
return Script::GetModDir();
}
unsigned int ServerFunctions::GetMillisecondsSinceServerStart() noexcept
{
std::chrono::high_resolution_clock::time_point currentTime = std::chrono::high_resolution_clock::now();
std::chrono::milliseconds milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startupTime);
return milliseconds.count();
}
const char *ServerFunctions::GetOperatingSystemType() noexcept
{
return Utils::getOperatingSystemType().c_str();
@ -137,34 +184,46 @@ void ServerFunctions::SetRuleValue(const char *key, double value) noexcept
mc->SetRuleValue(key, value);
}
void ServerFunctions::AddPluginHash(const char *pluginName, const char *hashStr) noexcept
void ServerFunctions::AddDataFileRequirement(const char *dataFilename, const char *checksumString) noexcept
{
auto &samples = mwmp::Networking::getPtr()->getSamples();
auto it = std::find_if(samples.begin(), samples.end(), [&pluginName](mwmp::PacketPreInit::PluginPair &item) {
return item.first == pluginName;
auto it = std::find_if(samples.begin(), samples.end(), [&dataFilename](mwmp::PacketPreInit::PluginPair &item) {
return item.first == dataFilename;
});
if (it != samples.end())
it->second.push_back((unsigned) std::stoul(hashStr));
it->second.push_back((unsigned) std::stoul(checksumString));
else
{
mwmp::PacketPreInit::HashList hashList;
mwmp::PacketPreInit::HashList checksumList;
unsigned hash = 0;
unsigned checksum = 0;
if (strlen(hashStr) != 0)
if (strlen(checksumString) != 0)
{
hash = (unsigned) std::stoul(hashStr);
hashList.push_back(hash);
checksum = (unsigned) std::stoul(checksumString);
checksumList.push_back(checksum);
}
samples.emplace_back(pluginName, hashList);
samples.emplace_back(dataFilename, checksumList);
auto mclient = mwmp::Networking::getPtr()->getMasterClient();
if (mclient)
mclient->PushPlugin({pluginName, hash});
mclient->PushPlugin({dataFilename, checksum});
}
}
// All methods below are deprecated versions of methods from above
bool ServerFunctions::DoesFileExist(const char *filePath) noexcept
{
return DoesFilePathExist(filePath);
}
const char* ServerFunctions::GetModDir() noexcept
{
return Script::GetModDir();
return GetDataPath();
}
void ServerFunctions::AddPluginHash(const char *pluginName, const char *checksumString) noexcept
{
AddDataFileRequirement(pluginName, checksumString);
}

@ -4,38 +4,73 @@
#include "../Types.hpp"
#define SERVERAPI \
{"StopServer", ServerFunctions::StopServer},\
{"LogMessage", ServerFunctions::LogMessage},\
{"LogAppend", ServerFunctions::LogAppend},\
\
{"Kick", ServerFunctions::Kick},\
{"BanAddress", ServerFunctions::BanAddress},\
{"UnbanAddress", ServerFunctions::UnbanAddress},\
{"StopServer", ServerFunctions::StopServer},\
\
{"GetOperatingSystemType", ServerFunctions::GetOperatingSystemType},\
{"GetArchitectureType", ServerFunctions::GetArchitectureType},\
{"GetServerVersion", ServerFunctions::GetServerVersion},\
{"GetProtocolVersion", ServerFunctions::GetProtocolVersion},\
{"GetAvgPing", ServerFunctions::GetAvgPing},\
{"GetIP", ServerFunctions::GetIP},\
{"GetMaxPlayers", ServerFunctions::GetMaxPlayers},\
{"GetPort", ServerFunctions::GetPort},\
{"HasPassword", ServerFunctions::HasPassword},\
{"GetPluginEnforcementState", ServerFunctions::GetPluginEnforcementState},\
{"GetScriptErrorIgnoringState", ServerFunctions::GetScriptErrorIgnoringState},\
{"Kick", ServerFunctions::Kick},\
{"BanAddress", ServerFunctions::BanAddress},\
{"UnbanAddress", ServerFunctions::UnbanAddress},\
\
{"SetGameMode", ServerFunctions::SetGameMode},\
{"SetHostname", ServerFunctions::SetHostname},\
{"SetServerPassword", ServerFunctions::SetServerPassword},\
{"SetPluginEnforcementState", ServerFunctions::SetPluginEnforcementState},\
{"SetScriptErrorIgnoringState", ServerFunctions::SetScriptErrorIgnoringState},\
{"SetRuleString", ServerFunctions::SetRuleString},\
{"SetRuleValue", ServerFunctions::SetRuleValue},\
{"AddPluginHash", ServerFunctions::AddPluginHash},\
{"GetModDir", ServerFunctions::GetModDir}
{"DoesFilePathExist", ServerFunctions::DoesFilePathExist},\
{"GetCaseInsensitiveFilename", ServerFunctions::GetCaseInsensitiveFilename},\
{"GetDataPath", ServerFunctions::GetDataPath},\
{"GetMillisecondsSinceServerStart", ServerFunctions::GetMillisecondsSinceServerStart},\
{"GetOperatingSystemType", ServerFunctions::GetOperatingSystemType},\
{"GetArchitectureType", ServerFunctions::GetArchitectureType},\
{"GetServerVersion", ServerFunctions::GetServerVersion},\
{"GetProtocolVersion", ServerFunctions::GetProtocolVersion},\
{"GetAvgPing", ServerFunctions::GetAvgPing},\
{"GetIP", ServerFunctions::GetIP},\
{"GetMaxPlayers", ServerFunctions::GetMaxPlayers},\
{"GetPort", ServerFunctions::GetPort},\
{"HasPassword", ServerFunctions::HasPassword},\
{"GetPluginEnforcementState", ServerFunctions::GetPluginEnforcementState},\
{"GetScriptErrorIgnoringState", ServerFunctions::GetScriptErrorIgnoringState},\
\
{"SetGameMode", ServerFunctions::SetGameMode},\
{"SetHostname", ServerFunctions::SetHostname},\
{"SetServerPassword", ServerFunctions::SetServerPassword},\
{"SetPluginEnforcementState", ServerFunctions::SetPluginEnforcementState},\
{"SetScriptErrorIgnoringState", ServerFunctions::SetScriptErrorIgnoringState},\
{"SetRuleString", ServerFunctions::SetRuleString},\
{"SetRuleValue", ServerFunctions::SetRuleValue},\
\
{"AddDataFileRequirement", ServerFunctions::AddDataFileRequirement},\
\
{"DoesFileExist", ServerFunctions::DoesFileExist},\
{"GetModDir", ServerFunctions::GetModDir},\
{"AddPluginHash", ServerFunctions::AddPluginHash}
class ServerFunctions
{
public:
/**
* \brief Write a log message with its own timestamp.
*
* It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
*
* \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
* 3 for LOG_ERROR, 4 for LOG_FATAL).
* \param message The message logged.
* \return void
*/
static void LogMessage(unsigned short level, const char *message) noexcept;
/**
* \brief Write a log message without its own timestamp.
*
* It will have "[Script]:" prepended to it so as to mark it as a script-generated log message.
*
* \param level The logging level used (0 for LOG_VERBOSE, 1 for LOG_INFO, 2 for LOG_WARN,
* 3 for LOG_ERROR, 4 for LOG_FATAL).
* \param message The message logged.
* \return void
*/
static void LogAppend(unsigned short level, const char *message) noexcept;
/**
* \brief Shut down the server.
*
@ -68,6 +103,41 @@ public:
*/
static void UnbanAddress(const char *ipAddress) noexcept;
/**
* \brief Check whether a certain file path exists.
*
* This will be a case sensitive check on case sensitive filesystems.
*
* Whenever you want to enforce case insensitivity, use GetCaseInsensitiveFilename() instead.
*
* \return Whether the file exists or not.
*/
static bool DoesFilePathExist(const char *filePath) noexcept;
/**
* \brief Get the first filename in a folder that has a case insensitive match with the filename
* argument.
*
* This is used to retain case insensitivity when opening data files on Linux.
*
* \return The filename that matches.
*/
static const char *GetCaseInsensitiveFilename(const char *folderPath, const char *filename) noexcept;
/**
* \brief Get the path of the server's data folder.
*
* \return The data path.
*/
static const char *GetDataPath() noexcept;
/**
* \brief Get the milliseconds elapsed since the server was started.
*
* \return The time since the server's startup in milliseconds.
*/
static unsigned int GetMillisecondsSinceServerStart() noexcept;
/**
* \brief Get the type of the operating system used by the server.
*
@ -119,7 +189,7 @@ public:
/**
* \brief Get the port used by the server.
*
* \return Port
* \return The port.
*/
static unsigned short GetPort() noexcept;
@ -220,13 +290,24 @@ public:
static void SetRuleValue(const char *key, double value) noexcept;
/**
* \brief Adds plugins to the internal server structure to validate players.
* @param pluginName Name with extension of the plugin or master file.
* @param hash Hash string
* \brief Add a data file and a corresponding CRC32 checksum to the data file loadout
* that connecting clients need to match.
*
* It can be used multiple times to set multiple checksums for the same data file.
*
* Note: If an empty string is provided for the checksum, a checksum will not be
* required for that data file.
*
* @param dataFilename The filename of the data file.
* @param checksumString A string with the CRC32 checksum required.
*/
static void AddPluginHash(const char *pluginName, const char *hash) noexcept;
static void AddDataFileRequirement(const char *dataFilename, const char *checksumString) noexcept;
// All methods below are deprecated versions of methods from above
static bool DoesFileExist(const char *filePath) noexcept;
static const char *GetModDir() noexcept;
static void AddPluginHash(const char *pluginName, const char *checksumString) noexcept;
};
#endif //OPENMW_SERVERAPI_HPP

@ -201,6 +201,17 @@ int StatsFunctions::GetAttributeModifier(unsigned short pid, unsigned short attr
return player->creatureStats.mAttributes[attributeId].mMod;
}
double StatsFunctions::GetAttributeDamage(unsigned short pid, unsigned short attributeId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (attributeId >= Attribute::Length)
return 0;
return player->creatureStats.mAttributes[attributeId].mDamage;
}
int StatsFunctions::GetSkillBase(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
@ -223,6 +234,17 @@ int StatsFunctions::GetSkillModifier(unsigned short pid, unsigned short skillId)
return player->npcStats.mSkills[skillId].mMod;
}
double StatsFunctions::GetSkillDamage(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
GET_PLAYER(pid, player, 0);
if (skillId >= Skill::Length)
return 0;
return player->npcStats.mSkills[skillId].mDamage;
}
double StatsFunctions::GetSkillProgress(unsigned short pid, unsigned short skillId) noexcept
{
Player *player;
@ -437,6 +459,20 @@ void StatsFunctions::ClearAttributeModifier(unsigned short pid, unsigned short a
player->attributeIndexChanges.push_back(attributeId);
}
void StatsFunctions::SetAttributeDamage(unsigned short pid, unsigned short attributeId, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
if (attributeId >= Attribute::Length)
return;
player->creatureStats.mAttributes[attributeId].mDamage = value;
if (!Utils::vectorContains(player->attributeIndexChanges, attributeId))
player->attributeIndexChanges.push_back(attributeId);
}
void StatsFunctions::SetSkillBase(unsigned short pid, unsigned short skillId, int value) noexcept
{
Player *player;
@ -465,6 +501,20 @@ void StatsFunctions::ClearSkillModifier(unsigned short pid, unsigned short skill
player->skillIndexChanges.push_back(skillId);
}
void StatsFunctions::SetSkillDamage(unsigned short pid, unsigned short skillId, double value) noexcept
{
Player *player;
GET_PLAYER(pid, player, );
if (skillId >= Skill::Length)
return;
player->npcStats.mSkills[skillId].mDamage = value;
if (!Utils::vectorContains(player->skillIndexChanges, skillId))
player->skillIndexChanges.push_back(skillId);
}
void StatsFunctions::SetSkillProgress(unsigned short pid, unsigned short skillId, double value) noexcept
{
Player *player;

@ -30,9 +30,11 @@
\
{"GetAttributeBase", StatsFunctions::GetAttributeBase},\
{"GetAttributeModifier", StatsFunctions::GetAttributeModifier},\
{"GetAttributeDamage", StatsFunctions::GetAttributeDamage},\
\
{"GetSkillBase", StatsFunctions::GetSkillBase},\
{"GetSkillModifier", StatsFunctions::GetSkillModifier},\
{"GetSkillDamage", StatsFunctions::GetSkillDamage},\
{"GetSkillProgress", StatsFunctions::GetSkillProgress},\
{"GetSkillIncrease", StatsFunctions::GetSkillIncrease},\
\
@ -58,9 +60,11 @@
\
{"SetAttributeBase", StatsFunctions::SetAttributeBase},\
{"ClearAttributeModifier", StatsFunctions::ClearAttributeModifier},\
{"SetAttributeDamage", StatsFunctions::SetAttributeDamage},\
\
{"SetSkillBase", StatsFunctions::SetSkillBase},\
{"ClearSkillModifier", StatsFunctions::ClearSkillModifier},\
{"SetSkillDamage", StatsFunctions::SetSkillDamage},\
{"SetSkillProgress", StatsFunctions::SetSkillProgress},\
{"SetSkillIncrease", StatsFunctions::SetSkillIncrease},\
\
@ -267,6 +271,16 @@ public:
*/
static int GetAttributeModifier(unsigned short pid, unsigned short attributeId) noexcept;
/**
* \brief Get the amount of damage (as caused through the Damage Attribute effect)
* to a player's attribute.
*
* \param pid The player ID.
* \param attributeId The attribute ID.
* \return The amount of damage to the attribute.
*/
static double GetAttributeDamage(unsigned short pid, unsigned short attributeId) noexcept;
/**
* \brief Get the base value of a player's skill.
*
@ -285,6 +299,16 @@ public:
*/
static int GetSkillModifier(unsigned short pid, unsigned short skillId) noexcept;
/**
* \brief Get the amount of damage (as caused through the Damage Skill effect)
* to a player's skill.
*
* \param pid The player ID.
* \param skillId The skill ID.
* \return The amount of damage to the skill.
*/
static double GetSkillDamage(unsigned short pid, unsigned short skillId) noexcept;
/**
* \brief Get the progress the player has made towards increasing a certain skill by 1.
*
@ -477,6 +501,17 @@ public:
*/
static void ClearAttributeModifier(unsigned short pid, unsigned short attributeId) noexcept;
/**
* \brief Set the amount of damage (as caused through the Damage Attribute effect) to
* a player's attribute.
*
* \param pid The player ID.
* \param attributeId The attribute ID.
* \param value The amount of damage to the player's attribute.
* \return void
*/
static void SetAttributeDamage(unsigned short pid, unsigned short attributeId, double value) noexcept;
/**
* \brief Set the base value of a player's skill.
*
@ -501,6 +536,17 @@ public:
*/
static void ClearSkillModifier(unsigned short pid, unsigned short skillId) noexcept;
/**
* \brief Set the amount of damage (as caused through the Damage Skill effect) to
* a player's skill.
*
* \param pid The player ID.
* \param skillId The skill ID.
* \param value The amount of damage to the player's skill.
* \return void
*/
static void SetSkillDamage(unsigned short pid, unsigned short skillId, double value) noexcept;
/**
* \brief Set the progress the player has made towards increasing a certain skill by 1.
*

@ -21,7 +21,7 @@ int ScriptFunctions::CreateTimerEx(ScriptFunc callback, int msec, const char *ty
try
{
vector<boost::any> params;
GetArguments(params, args, types);
Utils::getArguments(params, args, types);
return mwmp::TimerAPI::CreateTimer(callback, msec, types, params);
}

@ -105,6 +105,7 @@ public:
catch (std::exception &e)
{
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, e.what());
Script::Call<Script::CallbackIdentity("OnServerScriptCrash")>(e.what());
if (!mwmp::Networking::getPtr()->getScriptErrorIgnoringState())
throw;

@ -13,62 +13,6 @@ constexpr ScriptCallbackData ScriptFunctions::callbacks[];
using namespace std;
void ScriptFunctions::GetArguments(std::vector<boost::any> &params, va_list args, const std::string &def)
{
params.reserve(def.length());
try
{
for (char c : def)
{
switch (c)
{
case 'i':
params.emplace_back(va_arg(args, unsigned int));
break;
case 'q':
params.emplace_back(va_arg(args, signed int));
break;
case 'l':
params.emplace_back(va_arg(args, unsigned long long));
break;
case 'w':
params.emplace_back(va_arg(args, signed long long));
break;
case 'f':
params.emplace_back(va_arg(args, double));
break;
case 'p':
params.emplace_back(va_arg(args, void*));
break;
case 's':
params.emplace_back(va_arg(args, const char*));
break;
case 'b':
params.emplace_back(va_arg(args, int));
break;
default:
throw runtime_error("C++ call: Unknown argument identifier " + c);
}
}
}
catch (...)
{
va_end(args);
throw;
}
va_end(args);
}
void ScriptFunctions::MakePublic(ScriptFunc _public, const char *name, char ret_type, const char *def) noexcept
{
Public::MakePublic(_public, name, ret_type, def);
@ -81,7 +25,7 @@ boost::any ScriptFunctions::CallPublic(const char *name, va_list args) noexcept
try
{
string def = Public::GetDefinition(name);
GetArguments(params, args, def);
Utils::getArguments(params, args, def);
return Public::Call(name, params);
}

@ -47,7 +47,6 @@ class ScriptFunctions
{
public:
static void GetArguments(std::vector<boost::any> &params, va_list args, const std::string &def);
static void MakePublic(ScriptFunc _public, const char *name, char ret_type, const char *def) noexcept;
static boost::any CallPublic(const char *name, va_list args) noexcept;
@ -157,6 +156,7 @@ public:
{"OnServerInit", Callback<>()},
{"OnServerPostInit", Callback<>()},
{"OnServerExit", Callback<bool>()},
{"OnServerScriptCrash", Callback<const char*>()},
{"OnPlayerConnect", Callback<unsigned short>()},
{"OnPlayerDisconnect", Callback<unsigned short>()},
{"OnPlayerDeath", Callback<unsigned short>()},
@ -209,7 +209,7 @@ public:
{"OnWorldMap", Callback<unsigned short>()},
{"OnWorldWeather", Callback<unsigned short>() },
{"OnMpNumIncrement", Callback<int>()},
{"OnRequestPluginList", Callback<>()}
{"OnRequestDataFileList", Callback<>()}
};
};

@ -1,9 +1,7 @@
//
// Created by koncord on 04.03.17.
//
#include "Utils.hpp"
#include <cstdarg>
using namespace std;
const vector<string> Utils::split(const string &str, int delimiter)
@ -52,3 +50,59 @@ ESM::Cell Utils::getCellFromDescription(std::string cellDescription)
return cell;
}
void Utils::getArguments(std::vector<boost::any> &params, va_list args, const std::string &def)
{
params.reserve(def.length());
try
{
for (char c : def)
{
switch (c)
{
case 'i':
params.emplace_back(va_arg(args, unsigned int));
break;
case 'q':
params.emplace_back(va_arg(args, signed int));
break;
case 'l':
params.emplace_back(va_arg(args, unsigned long long));
break;
case 'w':
params.emplace_back(va_arg(args, signed long long));
break;
case 'f':
params.emplace_back(va_arg(args, double));
break;
case 'p':
params.emplace_back(va_arg(args, void*));
break;
case 's':
params.emplace_back(va_arg(args, const char*));
break;
case 'b':
params.emplace_back(va_arg(args, int));
break;
default:
throw runtime_error("C++ call: Unknown argument identifier " + c);
}
}
}
catch (...)
{
va_end(args);
throw;
}
va_end(args);
}

@ -1,7 +1,3 @@
//
// Created by koncord on 04.03.17.
//
#ifndef OPENMW_UTILS_HPP
#define OPENMW_UTILS_HPP
@ -9,6 +5,8 @@
#include <regex>
#include <vector>
#include <boost/any.hpp>
#include <components/esm/loadcell.hpp>
#include <components/openmw-mp/Utils.hpp>
@ -27,6 +25,8 @@ namespace Utils
ESM::Cell getCellFromDescription(std::string cellDescription);
void getArguments(std::vector<boost::any> &params, va_list args, const std::string &def);
template<size_t N>
constexpr unsigned int hash(const char(&str)[N], size_t I = N)
{

@ -201,26 +201,6 @@ int main(int argc, char *argv[])
vector<string> plugins(Utils::split(mgr.getString("plugins", "Plugins"), ','));
Utils::printVersion("TES3MP dedicated server", TES3MP_VERSION, version.mCommitHash, TES3MP_PROTO_VERSION);
// Check for unmodified tes3mp-credits file; this makes it so people can't repackage official releases with
// their own made-up credits, though it obviously has no bearing on unofficial releases that change
// the checksum below
boost::filesystem::path folderPath(boost::filesystem::initial_path<boost::filesystem::path>());
folderPath = boost::filesystem::system_complete(boost::filesystem::path(argv[0])).remove_filename();
std::string creditsPath = folderPath.string() + "/tes3mp-credits";
unsigned int expectedChecksumInt = Utils::hexStrToInt(TES3MP_CREDITS_CHECKSUM);
bool hasValidCredits = Utils::doesFileHaveChecksum(creditsPath + ".md", expectedChecksumInt);
if (!hasValidCredits)
hasValidCredits = Utils::doesFileHaveChecksum(creditsPath + ".txt", expectedChecksumInt);
if (!hasValidCredits)
{
LOG_MESSAGE_SIMPLE(Log::LOG_FATAL, "The server is shutting down");
LOG_APPEND(Log::LOG_FATAL, "- %s", TES3MP_CREDITS_ERROR);
return 1;
}
Script::SetModDir(dataDirectory);
@ -327,6 +307,7 @@ int main(int argc, char *argv[])
catch (std::exception &e)
{
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, e.what());
Script::Call<Script::CallbackIdentity("OnServerScriptCrash")>(e.what());
throw; //fall through
}

@ -1,7 +1,3 @@
//
// Created by koncord on 31.03.17.
//
#ifndef OPENMW_PROCESSORPLAYERPOSITION_HPP
#define OPENMW_PROCESSORPLAYERPOSITION_HPP
@ -19,11 +15,7 @@ namespace mwmp
void Do(PlayerPacket &packet, Player &player) override
{
//DEBUG_PRINTF(strPacketID);
if (!player.creatureStats.mDead)
{
player.sendToLoaded(&packet);
}
player.sendToLoaded(&packet);
}
};
}

@ -134,7 +134,7 @@ add_openmw_dir (mwmp/processors/object BaseObjectProcessor
ProcessorScriptGlobalFloat
)
add_openmw_dir (mwmp/processors/worldstate ProcessorCellCreate ProcessorCellReplace ProcessorRecordDynamic
add_openmw_dir (mwmp/processors/worldstate ProcessorCellCreate ProcessorCellReset ProcessorRecordDynamic
ProcessorWorldCollisionOverride ProcessorWorldMap ProcessorWorldRegionAuthority ProcessorWorldTime
ProcessorWorldWeather
)

@ -221,10 +221,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
/*
Start of tes3mp addition
Check for unmodified tes3mp-credits file; this makes it so people can't repackage official releases with
their own made-up credits, though it obviously has no bearing on unofficial releases that change
the checksum below
Check for unmodified tes3mp-credits file on Windows; this makes it so people can't repackage official
releases with their own made-up credits, though it obviously has no bearing on unofficial releases that
change the checksum below
*/
#ifdef _WIN32
boost::filesystem::path folderPath(boost::filesystem::initial_path<boost::filesystem::path>());
folderPath = boost::filesystem::system_complete(boost::filesystem::path(argv[0])).remove_filename();
std::string creditsPath = folderPath.string() + "/tes3mp-credits";
@ -242,6 +243,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "tes3mp", TES3MP_CREDITS_ERROR, 0);
return false;
}
#endif
/*
End of tes3mp addition
*/

@ -458,6 +458,15 @@ namespace MWGui
updateMagicMarkers();
updateCustomMarkers();
/*
Start of tes3mp addition
Update player markers when cell changes to fix their locations
*/
updatePlayerMarkers();
/*
End of tes3mp addition
*/
}
void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell)

@ -71,6 +71,13 @@ DedicatedPlayer::~DedicatedPlayer()
void DedicatedPlayer::update(float dt)
{
// Only move and set anim flags if the framerate isn't too low
if (dt < 0.1)
{
move(dt);
setAnimFlags();
}
MWMechanics::CreatureStats *ptrCreatureStats = &ptr.getClass().getCreatureStats(ptr);
MWMechanics::DynamicStat<float> value;
@ -100,13 +107,6 @@ void DedicatedPlayer::update(float dt)
ptrCreatureStats->setAiSetting(MWMechanics::CreatureStats::AI_Fight, 0);
ptrCreatureStats->setAiSetting(MWMechanics::CreatureStats::AI_Flee, 0);
ptrCreatureStats->setAiSetting(MWMechanics::CreatureStats::AI_Hello, 0);
// Only move and set anim flags if the framerate isn't too low
if (dt < 0.1)
{
move(dt);
setAnimFlags();
}
}
void DedicatedPlayer::move(float dt)

@ -68,10 +68,10 @@ void LocalActor::update(bool forceUpdate)
void LocalActor::updateCell()
{
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Sending ID_ACTOR_CELL_CHANGE about %s %i-%i to server",
refId.c_str(), refNum, mpNum);
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Sending ID_ACTOR_CELL_CHANGE about %s %i-%i in cell %s to server",
refId.c_str(), refNum, mpNum, cell.getDescription().c_str());
LOG_APPEND(Log::LOG_VERBOSE, "- Moved from %s to %s", cell.getDescription().c_str(), ptr.getCell()->getCell()->getDescription().c_str());
LOG_APPEND(Log::LOG_VERBOSE, "- Moved to cell %s", ptr.getCell()->getCell()->getDescription().c_str());
cell = *ptr.getCell()->getCell();
position = ptr.getRefData().getPosition();
@ -194,8 +194,8 @@ void LocalActor::updateStatsDynamic(bool forceUpdate)
if (MechanicsHelper::isEmptyTarget(killer))
killer = MechanicsHelper::getTarget(ptr);
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_ACTOR_DEATH about %s %i-%i to server",
refId.c_str(), refNum, mpNum);
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Sending ID_ACTOR_DEATH about %s %i-%i in cell %s to server",
refId.c_str(), refNum, mpNum, cell.getDescription().c_str());
mwmp::Main::get().getNetworking()->getActorList()->addDeathActor(*this);

@ -284,6 +284,7 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
{
if (ptrNpcStats.getAttribute(i).getBase() != creatureStats.mAttributes[i].mBase ||
ptrNpcStats.getAttribute(i).getModifier() != creatureStats.mAttributes[i].mMod ||
ptrNpcStats.getAttribute(i).getDamage() != creatureStats.mAttributes[i].mDamage ||
ptrNpcStats.getSkillIncrease(i) != npcStats.mSkillIncrease[i] ||
forceUpdate)
{
@ -318,6 +319,7 @@ void LocalPlayer::updateSkills(bool forceUpdate)
// Update a skill if its base value has changed at all or its progress has changed enough
if (ptrNpcStats.getSkill(i).getBase() != npcStats.mSkills[i].mBase ||
ptrNpcStats.getSkill(i).getModifier() != npcStats.mSkills[i].mMod ||
ptrNpcStats.getSkill(i).getDamage() != npcStats.mSkills[i].mDamage ||
abs(ptrNpcStats.getSkill(i).getProgress() - npcStats.mSkills[i].mProgress) > 0.75 ||
forceUpdate)
{

@ -89,7 +89,7 @@
#include "WorldstateProcessor.hpp"
#include "worldstate/ProcessorCellCreate.hpp"
#include "worldstate/ProcessorCellReplace.hpp"
#include "worldstate/ProcessorCellReset.hpp"
#include "worldstate/ProcessorRecordDynamic.hpp"
#include "worldstate/ProcessorWorldCollisionOverride.hpp"
#include "worldstate/ProcessorWorldMap.hpp"
@ -186,7 +186,7 @@ void ProcessorInitializer()
ActorProcessor::AddProcessor(new ProcessorActorTest());
WorldstateProcessor::AddProcessor(new ProcessorCellCreate());
WorldstateProcessor::AddProcessor(new ProcessorCellReplace());
WorldstateProcessor::AddProcessor(new ProcessorCellReset());
WorldstateProcessor::AddProcessor(new ProcessorRecordDynamic());
WorldstateProcessor::AddProcessor(new ProcessorWorldCollisionOverride());
WorldstateProcessor::AddProcessor(new ProcessorWorldMap());

@ -1,23 +0,0 @@
#ifndef OPENMW_PROCESSORCELLREPLACE_HPP
#define OPENMW_PROCESSORCELLREPLACE_HPP
#include "../WorldstateProcessor.hpp"
namespace mwmp
{
class ProcessorCellReplace : public WorldstateProcessor
{
public:
ProcessorCellReplace()
{
BPP_INIT(ID_CELL_REPLACE)
}
virtual void Do(WorldstatePacket &packet, Worldstate &worldstate)
{
// Placeholder
}
};
}
#endif //OPENMW_PROCESSORCELLREPLACE_HPP

@ -0,0 +1,23 @@
#ifndef OPENMW_PROCESSORCELLRESET_HPP
#define OPENMW_PROCESSORCELLRESET_HPP
#include "../WorldstateProcessor.hpp"
namespace mwmp
{
class ProcessorCellReset : public WorldstateProcessor
{
public:
ProcessorCellReset()
{
BPP_INIT(ID_CELL_RESET)
}
virtual void Do(WorldstatePacket &packet, Worldstate &worldstate)
{
// Placeholder
}
};
}
#endif //OPENMW_PROCESSORCELLRESET_HPP

@ -202,7 +202,7 @@ add_component_dir (openmw-mp/Packets/Object
add_component_dir (openmw-mp/Packets/Worldstate
WorldstatePacket
PacketCellCreate PacketCellReplace PacketRecordDynamic PacketWorldCollisionOverride PacketWorldMap
PacketCellCreate PacketCellReset PacketRecordDynamic PacketWorldCollisionOverride PacketWorldMap
PacketWorldRegionAuthority PacketWorldTime PacketWorldWeather
)

@ -1,5 +1,5 @@
#include "../Packets/Worldstate/PacketCellCreate.hpp"
#include "../Packets/Worldstate/PacketCellReplace.hpp"
#include "../Packets/Worldstate/PacketCellReset.hpp"
#include "../Packets/Worldstate/PacketRecordDynamic.hpp"
#include "../Packets/Worldstate/PacketWorldCollisionOverride.hpp"
#include "../Packets/Worldstate/PacketWorldMap.hpp"
@ -20,7 +20,7 @@ inline void AddPacket(mwmp::WorldstatePacketController::packets_t *packets, RakN
mwmp::WorldstatePacketController::WorldstatePacketController(RakNet::RakPeerInterface *peer)
{
AddPacket<PacketCellCreate>(&packets, peer);
AddPacket<PacketCellReplace>(&packets, peer);
AddPacket<PacketCellReset>(&packets, peer);
AddPacket<PacketRecordDynamic>(&packets, peer);
AddPacket<PacketWorldCollisionOverride>(&packets, peer);
AddPacket<PacketWorldMap>(&packets, peer);

@ -104,7 +104,7 @@ enum GameMessages
ID_GAME_PREINIT,
ID_CELL_CREATE,
ID_CELL_REPLACE,
ID_CELL_RESET,
ID_RECORD_DYNAMIC,
ID_WORLD_COLLISION_OVERRIDE,
ID_WORLD_MAP,

@ -1,17 +0,0 @@
#include "PacketCellReplace.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
using namespace mwmp;
PacketCellReplace::PacketCellReplace(RakNet::RakPeerInterface *peer) : WorldstatePacket(peer)
{
packetID = ID_CELL_REPLACE;
orderChannel = CHANNEL_SYSTEM;
}
void PacketCellReplace::Packet(RakNet::BitStream *bs, bool send)
{
WorldstatePacket::Packet(bs, send);
// Placeholder
}

@ -0,0 +1,17 @@
#include "PacketCellReset.hpp"
#include <components/openmw-mp/NetworkMessages.hpp>
using namespace mwmp;
PacketCellReset::PacketCellReset(RakNet::RakPeerInterface *peer) : WorldstatePacket(peer)
{
packetID = ID_CELL_RESET;
orderChannel = CHANNEL_SYSTEM;
}
void PacketCellReset::Packet(RakNet::BitStream *bs, bool send)
{
WorldstatePacket::Packet(bs, send);
// Placeholder
}

@ -1,18 +1,18 @@
#ifndef OPENMW_PACKETCELLREPLACE_HPP
#define OPENMW_PACKETCELLREPLACE_HPP
#ifndef OPENMW_PACKETCELLRESET_HPP
#define OPENMW_PACKETCELLRESET_HPP
#include <components/openmw-mp/Packets/Worldstate/WorldstatePacket.hpp>
#include <components/openmw-mp/NetworkMessages.hpp>
namespace mwmp
{
class PacketCellReplace: public WorldstatePacket
class PacketCellReset: public WorldstatePacket
{
public:
PacketCellReplace(RakNet::RakPeerInterface *peer);
PacketCellReset(RakNet::RakPeerInterface *peer);
virtual void Packet(RakNet::BitStream *bs, bool send);
};
}
#endif //OPENMW_PACKETCELLREPLACE_HPP
#endif //OPENMW_PACKETCELLRESET_HPP

@ -192,15 +192,16 @@ std::string Utils::getArchitectureType()
{
#if defined(__x86_64__) || defined(_M_X64)
return "64-bit";
#elif defined(__i386__) || defined(_M_I86)
#elif defined(__i386__) || defined(_M_I86) || defined(_M_IX86)
return "32-bit";
#elif defined(__ARM_ARCH)
return "ARMv" + __ARM_ARCH;
std::string architectureType = "ARMv" + __ARM_ARCH;
#ifdef __aarch64__
return "64-bit";
architectureType = architectureType + " 64-bit";
#else
return "32-bit";
architectureType = architectureType + " 32-bit";
#endif
return architectureType;
#else
return "Unknown architecture";
#endif

@ -7,6 +7,7 @@
#define TES3MP_DEFAULT_PASSW "SuperPassword"
#define TES3MP_MASTERSERVER_PASSW "12345"
#define TES3MP_CREDITS_CHECKSUM "BC39D2E9"
#define TES3MP_CREDITS_CHECKSUM "BAEFF920"
#endif //OPENMW_VERSION_HPP

@ -4,14 +4,14 @@ tes3mp Credits
Programmers
----------------
Stanislav Zhukov (Koncord) - Overall architecture, networking & scripting systems, player sync, server browser & master server
Stanislav Zhukov (Koncord) - Architecture, networking & scripting systems, player sync, server browser & master server
David Cernat - World, NPC & quest sync, player sync improvements, state saving & loading, extensive bug fixes
Additional programming
----------------------
Grim Kriegor - Lua teleportation commands, early script fixes
Grim Kriegor - Linux deployment scripts, Lua teleportation commands, early script fixes
Battlerax - Various small fixes
@ -26,6 +26,7 @@ Community administrators
Community moderators
--------------------
Lysol
Michael Fitzmayer (mupf)
Nac
NicholasAH
@ -53,6 +54,7 @@ Translation
Super special thanks
--------------------
Alexander Ovsyannikov
Bret Curtis (psi29a)
Gabriel Pascu (iGrebla)
greetasdf
@ -73,8 +75,9 @@ Special thanks
Gluka
Goodevil
Ignatious
James Wards of Gore Corps LAN Club (www.gorecorps.co.nz)
James Wards of Gore Corps LAN Club (gorecorps.co.nz)
Jeremiah
Kyle Willey of Loreshaper Games (steempeak.com/@loreshapergames)
Lewis Sadlier
Luc Keating
Michael Zagar (Zoops)
@ -84,6 +87,7 @@ Special thanks
Scorcio
Simon Nemes
Texafornian
Thrud
Zaphida
All the developers of OpenMW for creating an amazing open source project

Loading…
Cancel
Save