feat: add exceptions
This commit is contained in:
parent
a2428bb0d1
commit
521af7c00e
62
L2BotCore/Domain/Exceptions.h
Normal file
62
L2BotCore/Domain/Exceptions.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace L2Bot::Domain
|
||||||
|
{
|
||||||
|
class RuntimeException : public std::runtime_error
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using _Mybase = std::runtime_error;
|
||||||
|
|
||||||
|
explicit RuntimeException(const std::wstring& _Message) : _Mybase(convert(_Message)), m_Message(_Message) {}
|
||||||
|
|
||||||
|
explicit RuntimeException(const wchar_t* _Message) : RuntimeException(std::wstring(_Message)) {}
|
||||||
|
|
||||||
|
/// returns the explanatory string
|
||||||
|
const char* what() const noexcept override
|
||||||
|
{
|
||||||
|
return std::runtime_error::what();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::wstring& Message() const noexcept
|
||||||
|
{
|
||||||
|
return m_Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !_HAS_EXCEPTIONS
|
||||||
|
protected:
|
||||||
|
virtual void _Doraise() const override { // perform class-specific exception handling
|
||||||
|
_RAISE(*this);
|
||||||
|
}
|
||||||
|
#endif // !_HAS_EXCEPTIONS
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string convert(const std::wstring& wmsg) const
|
||||||
|
{
|
||||||
|
const auto size = wmsg.size() + 1;
|
||||||
|
char* msg = new char[size];
|
||||||
|
size_t charsConverted = 0;
|
||||||
|
wcstombs_s(&charsConverted, msg, size, wmsg.c_str(), wmsg.length());
|
||||||
|
|
||||||
|
const std::string result(msg);
|
||||||
|
delete[] msg;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::wstring m_Message;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CriticalRuntimeException : public RuntimeException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CriticalRuntimeException(const std::wstring& _Message) : RuntimeException(_Message) {}
|
||||||
|
|
||||||
|
explicit CriticalRuntimeException(const wchar_t* _Message) : RuntimeException(_Message) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -33,7 +33,7 @@ namespace L2Bot::Domain::Logger
|
|||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
localtime_s(&timeinfo, &rawTime);
|
localtime_s(&timeinfo, &rawTime);
|
||||||
std::wstringstream oss;
|
std::wstringstream oss;
|
||||||
oss << "[" << std::put_time(&timeinfo, L"%Y-%m-%d %H.%M.%S") << "]";
|
oss << "[" << std::put_time(&timeinfo, L"%Y-%m-%d %H:%M:%S") << "]";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,9 +35,30 @@ namespace L2Bot::Domain::Logger
|
|||||||
Log(LogLevel::app, format, args...);
|
Log(LogLevel::app, format, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Error(const std::wstring& message) const
|
||||||
|
{
|
||||||
|
Log(LogLevel::error, message);
|
||||||
|
}
|
||||||
|
void Warning(const std::wstring& message) const
|
||||||
|
{
|
||||||
|
Log(LogLevel::warning, message);
|
||||||
|
}
|
||||||
|
void Info(const std::wstring& message) const
|
||||||
|
{
|
||||||
|
Log(LogLevel::info, message);
|
||||||
|
}
|
||||||
|
void App(const std::wstring& message) const
|
||||||
|
{
|
||||||
|
Log(LogLevel::app, message);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class ... Args>
|
template <class ... Args>
|
||||||
void Log(LogLevel level, const std::wformat_string<Args...> format, Args... args) const
|
void Log(LogLevel level, const std::wformat_string<Args...> format, Args... args) const
|
||||||
|
{
|
||||||
|
Log(level, std::vformat(format.get(), std::make_wformat_args(args...)));
|
||||||
|
}
|
||||||
|
void Log(LogLevel level, const std::wstring& message) const
|
||||||
{
|
{
|
||||||
std::wstring prefix = L"";
|
std::wstring prefix = L"";
|
||||||
if (level == LogLevel::error) {
|
if (level == LogLevel::error) {
|
||||||
@ -55,7 +76,7 @@ namespace L2Bot::Domain::Logger
|
|||||||
|
|
||||||
for (const auto& channel : m_Channels) {
|
for (const auto& channel : m_Channels) {
|
||||||
if (channel->IsAppropriateLevel(level)) {
|
if (channel->IsAppropriateLevel(level)) {
|
||||||
channel->SendToChannel(prefix + std::vformat(format.get(), std::make_wformat_args(args...)));
|
channel->SendToChannel(prefix + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "../DTO/Message.h"
|
#include "../DTO/Message.h"
|
||||||
#include "../Services/IncomingMessageProcessor.h"
|
#include "../Services/IncomingMessageProcessor.h"
|
||||||
#include "../Services/OutgoingMessageBuilder.h"
|
#include "../Services/OutgoingMessageBuilder.h"
|
||||||
|
#include "../Exceptions.h"
|
||||||
|
#include "../Services/ServiceLocator.h"
|
||||||
|
|
||||||
namespace L2Bot::Domain::Services
|
namespace L2Bot::Domain::Services
|
||||||
{
|
{
|
||||||
@ -69,19 +71,30 @@ namespace L2Bot::Domain::Services
|
|||||||
{
|
{
|
||||||
while (!m_Stopped)
|
while (!m_Stopped)
|
||||||
{
|
{
|
||||||
const auto& messages = GetOutgoingMessages();
|
try {
|
||||||
|
const auto& messages = GetOutgoingMessages();
|
||||||
|
|
||||||
if (m_Transport.IsConnected())
|
if (m_Transport.IsConnected())
|
||||||
{
|
|
||||||
for (const auto& message : messages)
|
|
||||||
{
|
{
|
||||||
m_Transport.Send(
|
for (const auto& message : messages)
|
||||||
m_Serializer.Serialize(message)
|
{
|
||||||
);
|
m_Transport.Send(
|
||||||
|
m_Serializer.Serialize(message)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
}
|
||||||
|
catch (const CriticalRuntimeException& e)
|
||||||
|
{
|
||||||
|
m_Stopped = true;
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Error(e.Message());
|
||||||
|
}
|
||||||
|
catch (const RuntimeException& e)
|
||||||
|
{
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Warning(e.Message());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,15 +102,28 @@ namespace L2Bot::Domain::Services
|
|||||||
{
|
{
|
||||||
while (!m_Stopped)
|
while (!m_Stopped)
|
||||||
{
|
{
|
||||||
if (m_Transport.IsConnected())
|
try {
|
||||||
{
|
if (m_Transport.IsConnected())
|
||||||
const auto messageType = m_IncomingMessageProcessor.Process(m_Transport.Receive());
|
{
|
||||||
|
const auto& message = m_Transport.Receive();
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Info(L"received message from client: {}", message);
|
||||||
|
const auto messageType = m_IncomingMessageProcessor.Process(message);
|
||||||
|
|
||||||
if (messageType == Serializers::IncomingMessage::Type::invalidate) {
|
if (messageType == Serializers::IncomingMessage::Type::invalidate) {
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
}
|
||||||
|
catch (const CriticalRuntimeException& e)
|
||||||
|
{
|
||||||
|
m_Stopped = true;
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Error(e.Message());
|
||||||
|
}
|
||||||
|
catch (const RuntimeException& e)
|
||||||
|
{
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Warning(e.Message());
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,11 +131,22 @@ namespace L2Bot::Domain::Services
|
|||||||
{
|
{
|
||||||
while (!m_Stopped)
|
while (!m_Stopped)
|
||||||
{
|
{
|
||||||
if (!m_Transport.IsConnected())
|
try {
|
||||||
{
|
if (!m_Transport.IsConnected())
|
||||||
m_Transport.Connect();
|
{
|
||||||
|
m_Transport.Connect();
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
|
}
|
||||||
|
catch (const CriticalRuntimeException& e)
|
||||||
|
{
|
||||||
|
m_Stopped = true;
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Error(e.Message());
|
||||||
|
}
|
||||||
|
catch (const RuntimeException& e)
|
||||||
|
{
|
||||||
|
ServiceLocator::GetInstance().GetLogger()->Warning(e.Message());
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +229,7 @@
|
|||||||
<ClInclude Include="Domain\ValueObjects\Transform.h" />
|
<ClInclude Include="Domain\ValueObjects\Transform.h" />
|
||||||
<ClInclude Include="Domain\ValueObjects\VariableStats.h" />
|
<ClInclude Include="Domain\ValueObjects\VariableStats.h" />
|
||||||
<ClInclude Include="Domain\ValueObjects\VitalStats.h" />
|
<ClInclude Include="Domain\ValueObjects\VitalStats.h" />
|
||||||
|
<ClInclude Include="Domain\Exceptions.h" />
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
<ClInclude Include="Domain\Helpers\HashCombiner.h" />
|
<ClInclude Include="Domain\Helpers\HashCombiner.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
|
@ -234,6 +234,9 @@
|
|||||||
<ClInclude Include="Domain\Logger\Logger.h">
|
<ClInclude Include="Domain\Logger\Logger.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Domain\Exceptions.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="pch.cpp">
|
<ClCompile Include="pch.cpp">
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <format>
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
#include "Domain/Services/ServiceLocator.h"
|
#include "Domain/Services/ServiceLocator.h"
|
||||||
|
|
||||||
#define BUFFER_SIZE 16384
|
#define BUFFER_SIZE 16384
|
||||||
@ -38,8 +40,7 @@ public:
|
|||||||
|
|
||||||
if (m_Pipe == INVALID_HANDLE_VALUE)
|
if (m_Pipe == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot connect to the pipe ""{}""", m_PipeName);
|
throw RuntimeException(std::format(L"cannot create the pipe {}: {}", m_PipeName, GetLastError()));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -81,14 +82,14 @@ public:
|
|||||||
const auto overlappedResult = GetOverlappedResult(m_Pipe, &m_WritingOverlapped, &ret, false);
|
const auto overlappedResult = GetOverlappedResult(m_Pipe, &m_WritingOverlapped, &ret, false);
|
||||||
if (!overlappedResult)
|
if (!overlappedResult)
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot get overlapped result for the pipe ""{}"" when writing", m_PipeName);
|
|
||||||
m_Connected = false;
|
m_Connected = false;
|
||||||
|
throw RuntimeException(std::format(L"cannot get overlapped result for the pipe {} when writing", m_PipeName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot write to the pipe ""{}"": {}", m_PipeName, lastError);
|
|
||||||
m_Connected = false;
|
m_Connected = false;
|
||||||
|
throw RuntimeException(std::format(L"cannot write to the pipe {}: {}", m_PipeName, lastError));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,16 +115,14 @@ public:
|
|||||||
const auto overlappedResult = GetOverlappedResult(m_Pipe, &m_ReadingOverlapped, &ret, false);
|
const auto overlappedResult = GetOverlappedResult(m_Pipe, &m_ReadingOverlapped, &ret, false);
|
||||||
if (!overlappedResult)
|
if (!overlappedResult)
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot get overlapped result for the pipe ""{}"" when reading", m_PipeName);
|
|
||||||
m_Connected = false;
|
m_Connected = false;
|
||||||
return L"";
|
throw RuntimeException(std::format(L"cannot get overlapped result for the pipe {} when reading", m_PipeName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot read from the pipe ""{}"": {}", m_PipeName, lastError);
|
|
||||||
m_Connected = false;
|
m_Connected = false;
|
||||||
return L"";
|
throw RuntimeException(std::format(L"cannot read from the pipe {}: {}", m_PipeName, lastError));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +151,7 @@ private:
|
|||||||
const bool connected = ConnectNamedPipe(m_Pipe, &m_ConntectingOverlapped) == 0;
|
const bool connected = ConnectNamedPipe(m_Pipe, &m_ConntectingOverlapped) == 0;
|
||||||
if (!connected)
|
if (!connected)
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot connect to the pipe ""{}"": {}", m_PipeName, GetLastError());
|
throw RuntimeException(std::format(L"cannot connect the pipe {}: {}", m_PipeName, GetLastError()));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (GetLastError())
|
switch (GetLastError())
|
||||||
@ -165,7 +164,7 @@ private:
|
|||||||
if (SetEvent(m_ConntectingOverlapped.hEvent))
|
if (SetEvent(m_ConntectingOverlapped.hEvent))
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"an error has occurred when connecting to the pipe ""{}"": {}", m_PipeName, GetLastError());
|
throw RuntimeException(std::format(L"an error has occurred when connecting to the pipe ""{}"": {}", m_PipeName, GetLastError()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,8 +175,7 @@ private:
|
|||||||
overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
overlapped.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||||
if (overlapped.hEvent == NULL)
|
if (overlapped.hEvent == NULL)
|
||||||
{
|
{
|
||||||
Services::ServiceLocator::GetInstance().GetLogger()->Error(L"cannot create overlapped for the pipe ""{}"": {}", m_PipeName, GetLastError());
|
throw RuntimeException(std::format(L"cannot create overlapped for the pipe {}: {}", m_PipeName, GetLastError()));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
overlapped.Offset = 0;
|
overlapped.Offset = 0;
|
||||||
overlapped.OffsetHigh = 0;
|
overlapped.OffsetHigh = 0;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "../GameStructs/FName.h"
|
#include "../GameStructs/FName.h"
|
||||||
#include "../../../Common/Common.h"
|
#include "../../../Common/Common.h"
|
||||||
#include "Domain/Entities/AbnormalEffect.h"
|
#include "Domain/Entities/AbnormalEffect.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
using namespace L2Bot::Domain;
|
using namespace L2Bot::Domain;
|
||||||
|
|
||||||
@ -28,15 +29,17 @@ namespace Interlude
|
|||||||
{
|
{
|
||||||
const auto data = m_L2GameData.GetMSData(skillId, level);
|
const auto data = m_L2GameData.GetMSData(skillId, level);
|
||||||
|
|
||||||
const auto name = data && data->name ? data->name : L"";
|
if (!data) {
|
||||||
const auto description = data && data->description ? data->description : L"";
|
throw RuntimeException(std::format(L"cannot load MSData for abnormal effect {}", skillId));
|
||||||
const auto iconEntry = data ? m_FName.GetEntry(data->iconNameIndex) : nullptr;
|
}
|
||||||
|
|
||||||
|
const auto iconEntry = m_FName.GetEntry(data->iconNameIndex);
|
||||||
|
|
||||||
return std::make_shared<Entities::AbnormalEffect>(
|
return std::make_shared<Entities::AbnormalEffect>(
|
||||||
skillId,
|
skillId,
|
||||||
static_cast<uint8_t>(level),
|
static_cast<uint8_t>(level),
|
||||||
std::wstring(name),
|
data->name ? std::wstring(data->name) : L"",
|
||||||
std::wstring(description),
|
data->description ? std::wstring(data->description) : L"",
|
||||||
iconEntry ? std::wstring(iconEntry->value) : L""
|
iconEntry ? std::wstring(iconEntry->value) : L""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <format>
|
||||||
#include "../GameStructs/L2GameDataWrapper.h"
|
#include "../GameStructs/L2GameDataWrapper.h"
|
||||||
#include "../GameStructs/FName.h"
|
#include "../GameStructs/FName.h"
|
||||||
#include "../GameStructs/GameStructs.h"
|
#include "../GameStructs/GameStructs.h"
|
||||||
#include "../../../Common/Common.h"
|
#include "../../../Common/Common.h"
|
||||||
#include "Domain/Entities/Drop.h"
|
#include "Domain/Entities/Drop.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
namespace Interlude
|
namespace Interlude
|
||||||
{
|
{
|
||||||
@ -63,8 +65,15 @@ namespace Interlude
|
|||||||
const Data GetData(const Item* item) const
|
const Data GetData(const Item* item) const
|
||||||
{
|
{
|
||||||
const auto itemData = m_L2GameData.GetItemData(item->itemId);
|
const auto itemData = m_L2GameData.GetItemData(item->itemId);
|
||||||
const auto nameEntry = itemData ? m_FName.GetEntry(itemData->nameIndex) : nullptr;
|
if (!itemData) {
|
||||||
const auto iconEntry = itemData ? m_FName.GetEntry(itemData->iconNameIndex) : nullptr;
|
throw RuntimeException(std::format(L"cannot load ItemData for drop {}", item->itemId));
|
||||||
|
}
|
||||||
|
const auto nameEntry = m_FName.GetEntry(itemData->nameIndex);
|
||||||
|
const auto iconEntry = m_FName.GetEntry(itemData->iconNameIndex);
|
||||||
|
|
||||||
|
if (!item->pawn) {
|
||||||
|
throw RuntimeException(std::format(L"pawn is empty for drop {}", std::wstring(nameEntry->value)));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
item->objectId,
|
item->objectId,
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <format>
|
||||||
#include "../GameStructs/GameStructs.h"
|
#include "../GameStructs/GameStructs.h"
|
||||||
#include "../../../Common/Common.h"
|
#include "../../../Common/Common.h"
|
||||||
#include "Domain/Entities/Hero.h"
|
#include "Domain/Entities/Hero.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
namespace Interlude
|
namespace Interlude
|
||||||
{
|
{
|
||||||
@ -72,73 +74,79 @@ namespace Interlude
|
|||||||
private:
|
private:
|
||||||
const Data GetData(const User* item) const
|
const Data GetData(const User* item) const
|
||||||
{
|
{
|
||||||
const auto playerController = item->pawn ? item->pawn->lineagePlayerController : nullptr;
|
if (!item->pawn) {
|
||||||
|
throw RuntimeException(std::format(L"pawn is empty for hero {}", item->nickname));
|
||||||
|
}
|
||||||
|
const auto playerController = item->pawn->lineagePlayerController;
|
||||||
|
if (!playerController) {
|
||||||
|
throw RuntimeException(std::format(L"player controller is empty for hero {}", item->nickname));
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
item->objectId,
|
item->objectId,
|
||||||
ValueObjects::Transform(
|
ValueObjects::Transform(
|
||||||
ValueObjects::Vector3(item->pawn->Location.x, item->pawn->Location.y, item->pawn->Location.z),
|
ValueObjects::Vector3(item->pawn->Location.x, item->pawn->Location.y, item->pawn->Location.z),
|
||||||
ValueObjects::Vector3(
|
ValueObjects::Vector3(
|
||||||
static_cast<float_t>(item->pawn->Rotation.Pitch),
|
static_cast<float_t>(item->pawn->Rotation.Pitch),
|
||||||
static_cast<float_t>(item->pawn->Rotation.Yaw),
|
static_cast<float_t>(item->pawn->Rotation.Yaw),
|
||||||
static_cast<float_t>(item->pawn->Rotation.Roll)
|
static_cast<float_t>(item->pawn->Rotation.Roll)
|
||||||
),
|
|
||||||
ValueObjects::Vector3(item->pawn->Velocity.x, item->pawn->Velocity.y, item->pawn->Velocity.z),
|
|
||||||
ValueObjects::Vector3(item->pawn->Acceleration.x, item->pawn->Acceleration.y, item->pawn->Acceleration.z)
|
|
||||||
),
|
),
|
||||||
ValueObjects::FullName(
|
ValueObjects::Vector3(item->pawn->Velocity.x, item->pawn->Velocity.y, item->pawn->Velocity.z),
|
||||||
std::wstring(item->nickname),
|
ValueObjects::Vector3(item->pawn->Acceleration.x, item->pawn->Acceleration.y, item->pawn->Acceleration.z)
|
||||||
std::wstring(item->title)
|
),
|
||||||
),
|
ValueObjects::FullName(
|
||||||
ValueObjects::VitalStats(
|
std::wstring(item->nickname),
|
||||||
item->maxHp, item->hp,
|
std::wstring(item->title)
|
||||||
item->maxMp, item->mp,
|
),
|
||||||
item->maxCp, item->cp
|
ValueObjects::VitalStats(
|
||||||
),
|
item->maxHp, item->hp,
|
||||||
ValueObjects::Phenotype(
|
item->maxMp, item->mp,
|
||||||
(Enums::RaceEnum)item->raceId,
|
item->maxCp, item->cp
|
||||||
item->gender == L2::Gender::MALE,
|
),
|
||||||
(Enums::ClassEnum)item->classId,
|
ValueObjects::Phenotype(
|
||||||
(Enums::ClassEnum)item->activeClassId
|
(Enums::RaceEnum)item->raceId,
|
||||||
),
|
item->gender == L2::Gender::MALE,
|
||||||
ValueObjects::ExperienceInfo(
|
(Enums::ClassEnum)item->classId,
|
||||||
item->lvl,
|
(Enums::ClassEnum)item->activeClassId
|
||||||
item->exp,
|
),
|
||||||
item->sp
|
ValueObjects::ExperienceInfo(
|
||||||
),
|
item->lvl,
|
||||||
ValueObjects::PermanentStats(
|
item->exp,
|
||||||
item->str,
|
item->sp
|
||||||
item->dex,
|
),
|
||||||
item->con,
|
ValueObjects::PermanentStats(
|
||||||
item->int_,
|
item->str,
|
||||||
item->men,
|
item->dex,
|
||||||
item->wit
|
item->con,
|
||||||
),
|
item->int_,
|
||||||
ValueObjects::VariableStats(
|
item->men,
|
||||||
item->accuracy,
|
item->wit
|
||||||
item->critRate,
|
),
|
||||||
item->pAttack,
|
ValueObjects::VariableStats(
|
||||||
item->attackSpeed,
|
item->accuracy,
|
||||||
item->pDefense,
|
item->critRate,
|
||||||
item->evasion,
|
item->pAttack,
|
||||||
item->mAttack,
|
item->attackSpeed,
|
||||||
item->mDefense,
|
item->pDefense,
|
||||||
item->castingSpeed
|
item->evasion,
|
||||||
),
|
item->mAttack,
|
||||||
ValueObjects::Reputation(
|
item->mDefense,
|
||||||
item->karma,
|
item->castingSpeed
|
||||||
item->pkKills,
|
),
|
||||||
item->pvpKills,
|
ValueObjects::Reputation(
|
||||||
static_cast<uint8_t>(item->recRemaining),
|
item->karma,
|
||||||
static_cast<uint8_t>(item->evalScore)
|
item->pkKills,
|
||||||
),
|
item->pvpKills,
|
||||||
ValueObjects::InventoryInfo(
|
static_cast<uint8_t>(item->recRemaining),
|
||||||
item->maxWeight,
|
static_cast<uint8_t>(item->evalScore)
|
||||||
item->weight,
|
),
|
||||||
item->invSlotCount
|
ValueObjects::InventoryInfo(
|
||||||
),
|
item->maxWeight,
|
||||||
playerController ? playerController->targetObjectId : 0,
|
item->weight,
|
||||||
playerController ? playerController->isStanding == 1 : true
|
item->invSlotCount
|
||||||
|
),
|
||||||
|
playerController->targetObjectId,
|
||||||
|
playerController->isStanding == 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "Domain/Entities/ShieldItem.h"
|
#include "Domain/Entities/ShieldItem.h"
|
||||||
#include "Domain/DTO/ItemData.h"
|
#include "Domain/DTO/ItemData.h"
|
||||||
#include "../Helpers/EnchantHelper.h"
|
#include "../Helpers/EnchantHelper.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
using namespace L2Bot::Domain;
|
using namespace L2Bot::Domain;
|
||||||
|
|
||||||
@ -92,39 +93,37 @@ namespace Interlude
|
|||||||
{
|
{
|
||||||
//FIXME during first start data may be undefined
|
//FIXME during first start data may be undefined
|
||||||
const auto data = GetItemData(itemInfo.itemId);
|
const auto data = GetItemData(itemInfo.itemId);
|
||||||
|
if (!data) {
|
||||||
if (data)
|
throw RuntimeException(std::format(L"cannot load ItemData for item {}", itemInfo.itemId));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (data->dataType)
|
||||||
{
|
{
|
||||||
switch (data->dataType)
|
case L2::ItemDataType::ARMOR:
|
||||||
{
|
return CreateArmor(itemInfo);
|
||||||
case L2::ItemDataType::ARMOR:
|
case L2::ItemDataType::WEAPON:
|
||||||
return CreateArmor(itemInfo);
|
return CreateWeaponOrShield(itemInfo, static_cast<const FL2WeaponItemData*>(data));
|
||||||
case L2::ItemDataType::WEAPON:
|
|
||||||
return CreateWeaponOrShield(itemInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateEtc(itemInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return CreateEtc(itemInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(std::shared_ptr<Entities::BaseItem>& item, const DTO::ItemData& itemInfo) const
|
void Update(std::shared_ptr<Entities::BaseItem>& item, const DTO::ItemData& itemInfo) const
|
||||||
{
|
{
|
||||||
//FIXME during first start data may be undefined
|
//FIXME during first start data may be undefined
|
||||||
const auto data = GetItemData(itemInfo.itemId);
|
const auto data = GetItemData(itemInfo.itemId);
|
||||||
|
if (!data) {
|
||||||
if (data)
|
throw RuntimeException(std::format(L"cannot load ItemData for item {}", itemInfo.itemId));
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (data->dataType)
|
||||||
{
|
{
|
||||||
switch (data->dataType)
|
case L2::ItemDataType::ARMOR:
|
||||||
{
|
UpdateArmor(item, itemInfo);
|
||||||
case L2::ItemDataType::ARMOR:
|
return;
|
||||||
UpdateArmor(item, itemInfo);
|
case L2::ItemDataType::WEAPON:
|
||||||
return;
|
UpdateWeaponOrShield(item, itemInfo, static_cast<const FL2WeaponItemData*>(data));
|
||||||
case L2::ItemDataType::WEAPON:
|
return;
|
||||||
UpdateWeaponOrShield(item, itemInfo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateEtc(item, itemInfo);
|
UpdateEtc(item, itemInfo);
|
||||||
@ -215,10 +214,8 @@ namespace Interlude
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Entities::BaseItem> CreateWeaponOrShield(const DTO::ItemData& itemInfo) const
|
std::shared_ptr<Entities::BaseItem> CreateWeaponOrShield(const DTO::ItemData& itemInfo, const FL2WeaponItemData* itemData) const
|
||||||
{
|
{
|
||||||
const auto itemData = static_cast<const FL2WeaponItemData*>(GetItemData(itemInfo.itemId));
|
|
||||||
|
|
||||||
if (itemData->weaponType != L2::WeaponType::SHIELD)
|
if (itemData->weaponType != L2::WeaponType::SHIELD)
|
||||||
{
|
{
|
||||||
const auto& data = GetWeaponData(itemInfo, itemData);
|
const auto& data = GetWeaponData(itemInfo, itemData);
|
||||||
@ -266,10 +263,8 @@ namespace Interlude
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateWeaponOrShield(std::shared_ptr<Entities::BaseItem>& item, const DTO::ItemData& itemInfo) const
|
void UpdateWeaponOrShield(std::shared_ptr<Entities::BaseItem>& item, const DTO::ItemData& itemInfo, const FL2WeaponItemData* itemData) const
|
||||||
{
|
{
|
||||||
const auto itemData = static_cast<const FL2WeaponItemData*>(GetItemData(itemInfo.itemId));
|
|
||||||
|
|
||||||
if (itemData->weaponType != L2::WeaponType::SHIELD)
|
if (itemData->weaponType != L2::WeaponType::SHIELD)
|
||||||
{
|
{
|
||||||
auto weaponItem = std::dynamic_pointer_cast<Entities::WeaponItem>(item);
|
auto weaponItem = std::dynamic_pointer_cast<Entities::WeaponItem>(item);
|
||||||
@ -322,21 +317,20 @@ namespace Interlude
|
|||||||
const BaseData GetBaseData(const DTO::ItemData& itemInfo) const
|
const BaseData GetBaseData(const DTO::ItemData& itemInfo) const
|
||||||
{
|
{
|
||||||
const auto data = GetItemData(itemInfo.itemId);
|
const auto data = GetItemData(itemInfo.itemId);
|
||||||
|
if (!data) {
|
||||||
const auto nameEntry = data ? m_FName.GetEntry(data->nameIndex) : nullptr;
|
throw RuntimeException(std::format(L"cannot load ItemData for item {}", itemInfo.itemId));
|
||||||
const auto name = nameEntry ? std::wstring(nameEntry->value) : L"";
|
}
|
||||||
const auto iconEntry = data ? m_FName.GetEntry(data->iconNameIndex) : nullptr;
|
const auto nameEntry = m_FName.GetEntry(data->nameIndex);
|
||||||
const auto icon = iconEntry ? std::wstring(iconEntry->value) : L"";
|
const auto iconEntry = m_FName.GetEntry(data->iconNameIndex);
|
||||||
const auto description = data && data->description ? std::wstring(data->description) : L"";
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
itemInfo.objectId,
|
itemInfo.objectId,
|
||||||
itemInfo.itemId,
|
itemInfo.itemId,
|
||||||
itemInfo.mana,
|
itemInfo.mana,
|
||||||
name,
|
nameEntry ? std::wstring(nameEntry->value) : L"",
|
||||||
icon,
|
iconEntry ? std::wstring(iconEntry->value) : L"",
|
||||||
description,
|
data->description ? std::wstring(data->description) : L"",
|
||||||
(uint16_t)(data ? data->weight : 0)
|
static_cast<uint16_t>(data->weight)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <format>
|
||||||
#include "../../../Common/Common.h"
|
#include "../../../Common/Common.h"
|
||||||
#include "Domain/Entities/NPC.h"
|
#include "Domain/Entities/NPC.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
namespace Interlude
|
namespace Interlude
|
||||||
{
|
{
|
||||||
@ -53,6 +55,9 @@ namespace Interlude
|
|||||||
private:
|
private:
|
||||||
const Data GetData(const User* item) const
|
const Data GetData(const User* item) const
|
||||||
{
|
{
|
||||||
|
if (!item->pawn) {
|
||||||
|
throw RuntimeException(std::format(L"pawn is empty for npc {}", item->nickname));
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
item->objectId,
|
item->objectId,
|
||||||
ValueObjects::Transform(
|
ValueObjects::Transform(
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <format>
|
||||||
#include "../../../Common/Common.h"
|
#include "../../../Common/Common.h"
|
||||||
#include "Domain/Entities/Player.h"
|
#include "Domain/Entities/Player.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
namespace Interlude
|
namespace Interlude
|
||||||
{
|
{
|
||||||
@ -50,6 +52,9 @@ namespace Interlude
|
|||||||
private:
|
private:
|
||||||
const Data GetData(const User* item) const
|
const Data GetData(const User* item) const
|
||||||
{
|
{
|
||||||
|
if (!item->pawn) {
|
||||||
|
throw RuntimeException(std::format(L"pawn is empty for player {}", item->nickname));
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
item->objectId,
|
item->objectId,
|
||||||
ValueObjects::Transform(
|
ValueObjects::Transform(
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "../GameStructs/FName.h"
|
#include "../GameStructs/FName.h"
|
||||||
#include "../../../Common/Common.h"
|
#include "../../../Common/Common.h"
|
||||||
#include "Domain/Entities/Skill.h"
|
#include "Domain/Entities/Skill.h"
|
||||||
|
#include "Domain/Exceptions.h"
|
||||||
|
|
||||||
using namespace L2Bot::Domain;
|
using namespace L2Bot::Domain;
|
||||||
|
|
||||||
@ -72,21 +73,20 @@ namespace Interlude
|
|||||||
const Data GetData(const uint32_t skillId, const uint32_t level, const uint32_t isActive) const
|
const Data GetData(const uint32_t skillId, const uint32_t level, const uint32_t isActive) const
|
||||||
{
|
{
|
||||||
const auto data = m_L2GameData.GetMSData(skillId, level);
|
const auto data = m_L2GameData.GetMSData(skillId, level);
|
||||||
|
if (!data) {
|
||||||
|
throw RuntimeException(std::format(L"cannot load MSData for skill {}", skillId));
|
||||||
|
}
|
||||||
|
|
||||||
const auto cost = data ? data->mpCost : 0;
|
const auto iconEntry = m_FName.GetEntry(data->iconNameIndex);
|
||||||
const auto range = data ? data->range : 0;
|
|
||||||
const auto name = data && data->name ? data->name : L"";
|
|
||||||
const auto description = data && data->description ? data->description : L"";
|
|
||||||
const auto iconEntry = data ? m_FName.GetEntry(data->iconNameIndex) : nullptr;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
skillId,
|
skillId,
|
||||||
static_cast<uint8_t>(level),
|
static_cast<uint8_t>(level),
|
||||||
isActive != 1,
|
isActive != 1,
|
||||||
static_cast<uint8_t>(cost),
|
static_cast<uint8_t>(data->mpCost),
|
||||||
static_cast<int16_t>(range),
|
static_cast<int16_t>(data->range),
|
||||||
std::wstring(name),
|
data->name ? std::wstring(data->name) : L"",
|
||||||
std::wstring(description),
|
data->description ? std::wstring(data->description) : L"",
|
||||||
iconEntry ? std::wstring(iconEntry->value) : L"",
|
iconEntry ? std::wstring(iconEntry->value) : L"",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "../Factories/HeroFactory.h"
|
#include "../Factories/HeroFactory.h"
|
||||||
#include "Domain/Events/HeroCreatedEvent.h"
|
#include "Domain/Events/HeroCreatedEvent.h"
|
||||||
#include "Domain/Events/HeroDeletedEvent.h"
|
#include "Domain/Events/HeroDeletedEvent.h"
|
||||||
|
#include "Domain/Events/CreatureDiedEvent.h"
|
||||||
#include "../GameStructs/NetworkHandlerWrapper.h"
|
#include "../GameStructs/NetworkHandlerWrapper.h"
|
||||||
#include "Domain/Services/ServiceLocator.h"
|
#include "Domain/Services/ServiceLocator.h"
|
||||||
|
|
||||||
@ -49,6 +50,21 @@ namespace Interlude
|
|||||||
m_Hero = nullptr;
|
m_Hero = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Init() override
|
||||||
|
{
|
||||||
|
Services::ServiceLocator::GetInstance().GetEventDispatcher()->Subscribe(Events::CreatureDiedEvent::name, [this](const Events::Event& evt) {
|
||||||
|
std::unique_lock<std::shared_timed_mutex>(m_Mutex);
|
||||||
|
if (evt.GetName() == Events::CreatureDiedEvent::name)
|
||||||
|
{
|
||||||
|
const auto casted = static_cast<const Events::CreatureDiedEvent&>(evt);
|
||||||
|
if (m_Hero && m_Hero->GetId() == casted.GetCreatureId())
|
||||||
|
{
|
||||||
|
Services::ServiceLocator::GetInstance().GetLogger()->App(L"{} died", m_Hero->GetFullName().GetNickname());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
HeroRepository(const NetworkHandlerWrapper& networkHandler, const HeroFactory& factory) :
|
HeroRepository(const NetworkHandlerWrapper& networkHandler, const HeroFactory& factory) :
|
||||||
m_NetworkHandler(networkHandler),
|
m_NetworkHandler(networkHandler),
|
||||||
m_Factory(factory)
|
m_Factory(factory)
|
||||||
|
Loading…
Reference in New Issue
Block a user