mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-31 00:49:35 -06:00
Compare commits
9 Commits
fix-window
...
issue-960
| Author | SHA1 | Date | |
|---|---|---|---|
| bf58cf85cc | |||
| f6f3cdc3c0 | |||
| 66cf96af1a | |||
| 0e6cb8ab19 | |||
| 42cf2b6377 | |||
| 3cfbc9d3df | |||
| 5ba37ff7d6 | |||
| 8f00f1601c | |||
| 5e3c869141 |
9
.github/workflows/build-and-test.yml
vendored
9
.github/workflows/build-and-test.yml
vendored
@@ -8,13 +8,12 @@ on:
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: Build & Test (${{ matrix.os }} - ${{ matrix.cfg }})
|
||||
name: Build & Test (${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||
cfg: [ debug, release ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
@@ -34,9 +33,9 @@ jobs:
|
||||
- name: cmake
|
||||
uses: lukka/run-cmake@v10
|
||||
with:
|
||||
configurePreset: "ci-${{matrix.os}}-${{matrix.cfg}}"
|
||||
buildPreset: "ci-${{matrix.os}}-${{matrix.cfg}}"
|
||||
testPreset: "ci-${{matrix.os}}-${{matrix.cfg}}"
|
||||
configurePreset: "ci-${{matrix.os}}"
|
||||
buildPreset: "ci-${{matrix.os}}"
|
||||
testPreset: "ci-${{matrix.os}}"
|
||||
- name: artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
@@ -1,242 +1,128 @@
|
||||
{
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 14,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default configure step",
|
||||
"description": "Use 'build' dir and Unix makefiles",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"generator": "Unix Makefiles"
|
||||
},
|
||||
{
|
||||
"name": "ci-debug",
|
||||
"displayName": "CI configure step for Debug",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-release",
|
||||
"displayName": "CI configure step for Release",
|
||||
"inherits": "default",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04-release",
|
||||
"displayName": "CI configure step for Ubuntu",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "ci-release"
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04-debug",
|
||||
"displayName": "CI configure step for Ubuntu",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "ci-debug"
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13-release",
|
||||
"displayName": "CI configure step for MacOS",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "ci-release"
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13-debug",
|
||||
"displayName": "CI configure step for MacOS",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "ci-debug"
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022-release",
|
||||
"displayName": "CI configure step for Windows",
|
||||
"description": "Set architecture to 64-bit (b/c RakNet)",
|
||||
"inherits": "ci-release",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"architecture": {
|
||||
"value": "x64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022-debug",
|
||||
"displayName": "CI configure step for Windows",
|
||||
"description": "Set architecture to 64-bit (b/c RakNet)",
|
||||
"inherits": "ci-debug",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"architecture": {
|
||||
"value": "x64"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-default-release",
|
||||
"inherits": "ci-windows-2022-release",
|
||||
"displayName": "Windows only Configure Settings (Release)",
|
||||
"description": "Sets build and install directories",
|
||||
"generator": "Ninja",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-default-debug",
|
||||
"inherits": "ci-windows-2022-debug",
|
||||
"displayName": "Windows only Configure Settings (Debug)",
|
||||
"description": "Sets build and install directories",
|
||||
"generator": "Ninja",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"configurePreset": "default",
|
||||
"displayName": "Default Build",
|
||||
"description": "Default Build",
|
||||
"version": 3,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 14,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"displayName": "Default configure step",
|
||||
"description": "Use 'build' dir and Unix makefiles",
|
||||
"binaryDir": "${sourceDir}/build",
|
||||
"generator": "Unix Makefiles"
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"displayName": "CI configure step for Ubuntu",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "default"
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13",
|
||||
"displayName": "CI configure step for MacOS",
|
||||
"description": "Same as default, Used in GitHub actions workflow",
|
||||
"inherits": "default"
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022",
|
||||
"displayName": "CI configure step for Windows",
|
||||
"description": "Set architecture to 64-bit (b/c RakNet)",
|
||||
"inherits": "default",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"architecture": {
|
||||
"value": "x64"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "windows-default",
|
||||
"inherits": "ci-windows-2022",
|
||||
"displayName": "Windows only Configure Settings",
|
||||
"description": "Sets build and install directories",
|
||||
"generator": "Ninja",
|
||||
"architecture": {
|
||||
"value": "x64",
|
||||
"strategy": "external"
|
||||
}
|
||||
}
|
||||
],
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "default",
|
||||
"configurePreset": "default",
|
||||
"displayName": "Default Build",
|
||||
"description": "Default Build",
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022",
|
||||
"configurePreset": "ci-windows-2022",
|
||||
"displayName": "Windows CI Build",
|
||||
"description": "This preset is used by the CI build on windows",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"configurePreset": "ci-ubuntu-22.04",
|
||||
"displayName": "Linux CI Build",
|
||||
"description": "This preset is used by the CI build on linux",
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13",
|
||||
"configurePreset": "ci-macos-13",
|
||||
"displayName": "MacOS CI Build",
|
||||
"description": "This preset is used by the CI build on MacOS",
|
||||
"jobs": 2
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "ci-ubuntu-22.04",
|
||||
"configurePreset": "ci-ubuntu-22.04",
|
||||
"displayName": "CI Tests on Linux",
|
||||
"description": "Runs all tests on a linux configuration",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022-debug",
|
||||
"configurePreset": "ci-windows-2022-debug",
|
||||
"displayName": "Windows CI Build",
|
||||
"description": "This preset is used by the CI build on windows",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"inherits": "default"
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13",
|
||||
"configurePreset": "ci-macos-13",
|
||||
"displayName": "CI Tests on MacOS",
|
||||
"description": "Runs all tests on a Mac configuration",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022-release",
|
||||
"configurePreset": "ci-windows-2022-release",
|
||||
"displayName": "Windows CI Build",
|
||||
"description": "This preset is used by the CI build on windows",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"inherits": "default"
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022",
|
||||
"configurePreset": "ci-windows-2022",
|
||||
"displayName": "CI Tests on windows",
|
||||
"description": "Runs all tests on a windows configuration",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04-debug",
|
||||
"configurePreset": "ci-ubuntu-22.04-debug",
|
||||
"displayName": "Linux CI Build",
|
||||
"description": "This preset is used by the CI build on linux",
|
||||
"inherits": "default"
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04-release",
|
||||
"configurePreset": "ci-ubuntu-22.04-release",
|
||||
"displayName": "Linux CI Build",
|
||||
"description": "This preset is used by the CI build on linux",
|
||||
"inherits": "default"
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13-debug",
|
||||
"configurePreset": "ci-macos-13-debug",
|
||||
"displayName": "MacOS CI Build",
|
||||
"description": "This preset is used by the CI build on MacOS",
|
||||
"inherits": "default"
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13-release",
|
||||
"configurePreset": "ci-macos-13-release",
|
||||
"displayName": "MacOS CI Build",
|
||||
"description": "This preset is used by the CI build on MacOS",
|
||||
"inherits": "default"
|
||||
}
|
||||
],
|
||||
"testPresets": [
|
||||
{
|
||||
"name": "ci-ubuntu-22.04-debug",
|
||||
"configurePreset": "ci-ubuntu-22.04-debug",
|
||||
"displayName": "CI Tests on Linux",
|
||||
"description": "Runs all tests on a linux configuration",
|
||||
"configuration": "Debug",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-ubuntu-22.04-release",
|
||||
"configurePreset": "ci-ubuntu-22.04-release",
|
||||
"displayName": "CI Tests on Linux",
|
||||
"description": "Runs all tests on a linux configuration",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13-debug",
|
||||
"configurePreset": "ci-macos-13-debug",
|
||||
"displayName": "CI Tests on MacOS",
|
||||
"description": "Runs all tests on a Mac configuration",
|
||||
"configuration": "Debug",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-macos-13-release",
|
||||
"configurePreset": "ci-macos-13-release",
|
||||
"displayName": "CI Tests on MacOS",
|
||||
"description": "Runs all tests on a Mac configuration",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022-release",
|
||||
"configurePreset": "ci-windows-2022-release",
|
||||
"displayName": "CI Tests on windows",
|
||||
"description": "Runs all tests on a windows configuration",
|
||||
"configuration": "RelWithDebInfo",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
},
|
||||
"filter": {
|
||||
"exclude": {
|
||||
"name": "((example)|(minigzip))+"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ci-windows-2022-debug",
|
||||
"configurePreset": "ci-windows-2022-debug",
|
||||
"displayName": "CI Tests on windows",
|
||||
"description": "Runs all tests on a windows configuration for debug",
|
||||
"configuration": "Debug",
|
||||
"execution": {
|
||||
"jobs": 2
|
||||
},
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
},
|
||||
"filter": {
|
||||
"exclude": {
|
||||
"name": "((example)|(minigzip))+"
|
||||
}
|
||||
"output": {
|
||||
"outputOnFailure": true
|
||||
},
|
||||
"filter": {
|
||||
"exclude": {
|
||||
"name": "((example)|(minigzip))+"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -49,12 +49,3 @@ function(UpdateConfigOption file_name old_option_name new_option_name)
|
||||
file(APPEND ${file_name} "\n" ${current_value})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(DoAppleMariaDBCopy target location)
|
||||
if(APPLE)
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${MARIADBCPP_SHARED_LIBRARY_LOCATION}
|
||||
${location})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -36,19 +36,16 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||
data.playerID = playerId;
|
||||
|
||||
uint32_t len;
|
||||
if (!inStream.Read<uint32_t>(len)) return;
|
||||
inStream.Read<uint32_t>(len);
|
||||
|
||||
if (len > 33) {
|
||||
LOG("Received a really long player name, probably a fake packet %i.", len);
|
||||
return;
|
||||
for (int i = 0; i < len; i++) {
|
||||
char character; inStream.Read<char>(character);
|
||||
data.playerName += character;
|
||||
}
|
||||
|
||||
data.playerName.resize(len);
|
||||
inStream.ReadAlignedBytes(reinterpret_cast<unsigned char*>(data.playerName.data()), len);
|
||||
|
||||
if (!inStream.Read(data.zoneID)) return;
|
||||
if (!inStream.Read(data.muteExpire)) return;
|
||||
if (!inStream.Read(data.gmLevel)) return;
|
||||
inStream.Read(data.zoneID);
|
||||
inStream.Read(data.muteExpire);
|
||||
inStream.Read(data.gmLevel);
|
||||
data.sysAddr = packet->systemAddress;
|
||||
|
||||
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
||||
@@ -125,11 +122,6 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
||||
size_t membersSize = 0;
|
||||
inStream.Read(membersSize);
|
||||
|
||||
if (membersSize >= 4) {
|
||||
LOG("Tried to create a team with more than 4 players");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<LWOOBJID> members;
|
||||
|
||||
members.reserve(membersSize);
|
||||
|
||||
55
dCommon/dEnums/eCSRCommand.h
Normal file
55
dCommon/dEnums/eCSRCommand.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef __ECSRCOMMAND__H__
|
||||
#define __ECSRCOMMAND__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eCSRCommand : uint32_t {
|
||||
QUERY_SERVER_STATUS = 0,
|
||||
QUERY_CHARACTER_LOCATION,
|
||||
QUERY_CHARACTER_ONLINE_STATUS,
|
||||
INVENTORY_ADD_ITEM,
|
||||
INVENTORY_DELETE_ITEM,
|
||||
MODERATE_MUTE_ACCOUNT,
|
||||
MODERATE_BAN_ACCOUNT,
|
||||
MODERATE_EDUCATE_CHARACTER,
|
||||
MODERATE_KICK_CHARACTER,
|
||||
MODERATE_WARN_CHARACTER,
|
||||
MODERATE_RENAME_CHARACTER,
|
||||
MODERATE_DELETE_CHARACTER_FRIEND,
|
||||
MODERATE_KILL_CHARACTER,
|
||||
UPDATE_CHARACTER_HEALTH,
|
||||
UPDATE_CHARACTER_ARMOR,
|
||||
UPDATE_CHARACTER_IMAGINATION,
|
||||
UPDATE_CHARACTER_MAX_HEALTH,
|
||||
UPDATE_CHARACTER_MAX_ARMOR,
|
||||
UPDATE_CHARACTER_MAX_IMAGINATION,
|
||||
UPDATE_CHARACTER_CURRENCY,
|
||||
UPDATE_CHARACTER_REPUTATION,
|
||||
UPDATE_CHARACTER_LEGO_SCORE,
|
||||
UPDATE_CHARACTER_EMOTES,
|
||||
UPDATE_CHARACTER_ADD_ACHIEVEMENT,
|
||||
UPDATE_CHARACTER_COMPLETE_ACHIEVEMENT,
|
||||
UPDATE_CHARACTER_REMOVE_ACHIEVEMENT,
|
||||
UPDATE_CHARACTER_POSITION_OFFLINE,
|
||||
UPDATE_CHARACTER_INV_SLOT_AMOUNT,
|
||||
UTILITY_SAVE_CHARACTER,
|
||||
UTILITY_SEND_MAIL,
|
||||
UTILITY_GIVE_ITEM_TO_ALL_PLAYERS_ONLINE,
|
||||
METRICS_CONFIGURE,
|
||||
DISABLE_ZONE,
|
||||
INIT_DONATION_AMOUNT,
|
||||
KILL_SERVERS_COUNTDOWN,
|
||||
DISABLE_FAQ,
|
||||
THROTTLEQUEUE,
|
||||
GATEGM_ACCESS,
|
||||
RECONNECT_CRISP,
|
||||
MODERATE_KICK_ACCOUNT,
|
||||
TOGGLE_CRISP_SERVER,
|
||||
QUICK_DRAIN_SERVER,
|
||||
QUICK_DRAIN_SERVER_RENEW,
|
||||
REPLICATE_CHARACTER,
|
||||
GET_SERVER_STATUS,
|
||||
RELOAD_SERVER_INIS
|
||||
};
|
||||
|
||||
#endif //!__ECSRCOMMAND__H__
|
||||
16
dCommon/dEnums/eDeletionRestrictionsCheckType.h
Normal file
16
dCommon/dEnums/eDeletionRestrictionsCheckType.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __EDELETIONRESTRICTIONSCHECKTYPE__H__
|
||||
#define __EDELETIONRESTRICTIONSCHECKTYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eDeletionRestrictionsCheckType : uint32_t {
|
||||
INCLUDE_LOTS,
|
||||
EXCLUDE_LOTS,
|
||||
ANY_OF_THESE,
|
||||
ALL_OF_THESE,
|
||||
WHILE_IN_ZONE,
|
||||
ALWAYS_RESTRICTED,
|
||||
MAX
|
||||
};
|
||||
|
||||
#endif //!__EDELETIONRESTRICTIONSCHECKTYPE__H__
|
||||
@@ -4,9 +4,6 @@
|
||||
#define __EINVENTORYTYPE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "magic_enum.hpp"
|
||||
|
||||
static const uint8_t NUMBER_OF_INVENTORIES = 17;
|
||||
/**
|
||||
* Represents the different types of inventories an entity may have
|
||||
@@ -59,10 +56,4 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<eInventoryType> {
|
||||
static constexpr int min = 0;
|
||||
static constexpr int max = 16;
|
||||
};
|
||||
|
||||
#endif //!__EINVENTORYTYPE__H__
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef __EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
||||
#define __EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class eReponseMoveItemBetweenInventoryTypeCode : int32_t {
|
||||
SUCCESS,
|
||||
FAIL_GENERIC,
|
||||
FAIL_INV_FULL,
|
||||
FAIL_ITEM_NOT_FOUND,
|
||||
FAIL_CANT_MOVE_TO_THAT_INV_TYPE,
|
||||
FAIL_NOT_NEAR_BANK,
|
||||
FAIL_CANT_SWAP_ITEMS,
|
||||
FAIL_SOURCE_TYPE,
|
||||
FAIL_WRONG_DEST_TYPE,
|
||||
FAIL_SWAP_DEST_TYPE,
|
||||
FAIL_CANT_MOVE_THINKING_HAT,
|
||||
FAIL_DISMOUNT_BEFORE_MOVING
|
||||
};
|
||||
|
||||
#endif //!__EREPONSEMOVEITEMBETWEENINVENTORYTYPECODE__H__
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "CDRailActivatorComponent.h"
|
||||
#include "CDRewardCodesTable.h"
|
||||
#include "CDPetComponentTable.h"
|
||||
#include "CDDeletionRestrictionsTable.h"
|
||||
|
||||
#ifndef CDCLIENT_CACHE_ALL
|
||||
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
||||
@@ -103,6 +104,7 @@ DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
|
||||
DEFINE_TABLE_STORAGE(CDTamingBuildPuzzleTable);
|
||||
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
|
||||
DEFINE_TABLE_STORAGE(CDZoneTableTable);
|
||||
DEFINE_TABLE_STORAGE(CDDeletionRestrictionsTable)
|
||||
|
||||
void CDClientManager::LoadValuesFromDatabase() {
|
||||
if (!CDClientDatabase::isConnected) {
|
||||
@@ -150,6 +152,7 @@ void CDClientManager::LoadValuesFromDatabase() {
|
||||
CDTamingBuildPuzzleTable::Instance().LoadValuesFromDatabase();
|
||||
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
||||
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
||||
CDDeletionRestrictionsTable::Instance().LoadValuesFromDatabase();
|
||||
}
|
||||
|
||||
void CDClientManager::LoadValuesFromDefaults() {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "CDDeletionRestrictionsTable.h"
|
||||
#include "GeneralUtils.h"
|
||||
#include "eDeletionRestrictionsCheckType.h"
|
||||
|
||||
CDDeletionRestriction CDDeletionRestrictionsTable::Default = {
|
||||
.id = 0,
|
||||
.restricted = false,
|
||||
.ids = {},
|
||||
.checkType = eDeletionRestrictionsCheckType::MAX
|
||||
};
|
||||
|
||||
void CDDeletionRestrictionsTable::LoadValuesFromDatabase() {
|
||||
auto& entries = GetEntriesMutable();
|
||||
|
||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM DeletionRestrictions");
|
||||
while (!tableData.eof()) {
|
||||
CDDeletionRestriction entry;
|
||||
entry.id = tableData.getIntField("id", -1);
|
||||
if (entry.id == -1) continue;
|
||||
entry.restricted = tableData.getIntField("restricted", -1);
|
||||
const std::string raw_ids = tableData.getStringField("ids", "");
|
||||
if (!raw_ids.empty()) {
|
||||
for (const auto& idstr : GeneralUtils::SplitString(raw_ids, ',')) {
|
||||
if (!idstr.empty()) {
|
||||
const auto id = GeneralUtils::TryParse<int32_t>(idstr);
|
||||
if (id) entry.ids.push_back(id.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.checkType = static_cast<eDeletionRestrictionsCheckType>(tableData.getIntField("checkType", static_cast<int>(eDeletionRestrictionsCheckType::MAX)));
|
||||
|
||||
entries.insert(std::make_pair(entry.id, entry));
|
||||
tableData.nextRow();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const CDDeletionRestriction& CDDeletionRestrictionsTable::GetByID(uint32_t id) {
|
||||
auto& entries = GetEntries();
|
||||
const auto& it = entries.find(id);
|
||||
if (it != entries.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return Default;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "CDTable.h"
|
||||
|
||||
enum class eDeletionRestrictionsCheckType : uint32_t;
|
||||
|
||||
struct CDDeletionRestriction {
|
||||
uint32_t id;
|
||||
bool restricted;
|
||||
std::vector<uint32_t> ids;
|
||||
eDeletionRestrictionsCheckType checkType;
|
||||
};
|
||||
|
||||
class CDDeletionRestrictionsTable : public CDTable<CDDeletionRestrictionsTable, std::map<uint32_t, CDDeletionRestriction>> {
|
||||
public:
|
||||
void LoadValuesFromDatabase();
|
||||
const CDDeletionRestriction& GetByID(uint32_t id);
|
||||
|
||||
static CDDeletionRestriction Default;
|
||||
};
|
||||
@@ -33,7 +33,7 @@ struct CDItemComponent {
|
||||
uint32_t itemRating; //!< ???
|
||||
bool isTwoHanded; //!< Whether or not the item is double handed
|
||||
uint32_t minNumRequired; //!< Maybe the minimum number required for a mission, or to own this object?
|
||||
uint32_t delResIndex; //!< ???
|
||||
uint32_t delResIndex; //!< Relates to DeletionRestrictions Table
|
||||
uint32_t currencyLOT; //!< ???
|
||||
uint32_t altCurrencyCost; //!< ???
|
||||
std::string subItems; //!< A comma seperate string of sub items (maybe for multi-itemed things like faction test gear set)
|
||||
|
||||
@@ -38,4 +38,6 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
||||
"CDSkillBehaviorTable.cpp"
|
||||
"CDTamingBuildPuzzleTable.cpp"
|
||||
"CDVendorComponentTable.cpp"
|
||||
"CDZoneTableTable.cpp" PARENT_SCOPE)
|
||||
"CDZoneTableTable.cpp"
|
||||
"CDDeletionRestrictionsTable.cpp"
|
||||
PARENT_SCOPE)
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "IActivityLog.h"
|
||||
#include "IIgnoreList.h"
|
||||
#include "IAccountsRewardCodes.h"
|
||||
#include "IBehaviors.h"
|
||||
|
||||
namespace sql {
|
||||
class Statement;
|
||||
@@ -41,8 +40,7 @@ class GameDatabase :
|
||||
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList,
|
||||
public IBehaviors {
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList {
|
||||
public:
|
||||
virtual ~GameDatabase() = default;
|
||||
// TODO: These should be made private.
|
||||
|
||||
@@ -33,9 +33,6 @@ public:
|
||||
|
||||
// Add a new account to the database.
|
||||
virtual void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) = 0;
|
||||
|
||||
// Update the GameMaster level of an account.
|
||||
virtual void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IACCOUNTS__H__
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef IBEHAVIORS_H
|
||||
#define IBEHAVIORS_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
|
||||
class IBehaviors {
|
||||
public:
|
||||
struct Info {
|
||||
int32_t behaviorId{};
|
||||
uint32_t characterId{};
|
||||
std::string behaviorInfo;
|
||||
};
|
||||
|
||||
// This Add also takes care of updating if it exists.
|
||||
virtual void AddBehavior(const Info& info) = 0;
|
||||
virtual std::string GetBehavior(const int32_t behaviorId) = 0;
|
||||
virtual void RemoveBehavior(const int32_t behaviorId) = 0;
|
||||
};
|
||||
|
||||
#endif //!IBEHAVIORS_H
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef __IPROPERTIESCONTENTS__H__
|
||||
#define __IPROPERTIESCONTENTS__H__
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
@@ -17,7 +16,6 @@ public:
|
||||
LWOOBJID id{};
|
||||
LOT lot{};
|
||||
uint32_t ugcId{};
|
||||
std::array<int32_t, 5> behaviors{};
|
||||
};
|
||||
|
||||
// Inserts a new UGC model into the database.
|
||||
@@ -34,7 +32,7 @@ public:
|
||||
virtual void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) = 0;
|
||||
|
||||
// Update the model position and rotation for the given property id.
|
||||
virtual void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) = 0;
|
||||
virtual void UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) = 0;
|
||||
|
||||
// Remove the model for the given property id.
|
||||
virtual void RemoveModel(const LWOOBJID& modelId) = 0;
|
||||
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
std::vector<IPropertyContents::Model> GetPropertyModels(const LWOOBJID& propertyId) override;
|
||||
void RemoveUnreferencedUgcModels() override;
|
||||
void InsertNewPropertyModel(const LWOOBJID& propertyId, const IPropertyContents::Model& model, const std::string_view name) override;
|
||||
void UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) override;
|
||||
void UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) override;
|
||||
void RemoveModel(const LWOOBJID& modelId) override;
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
@@ -108,10 +108,6 @@ public:
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||
void AddBehavior(const IBehaviors::Info& info) override;
|
||||
std::string GetBehavior(const int32_t behaviorId) override;
|
||||
void RemoveBehavior(const int32_t characterId) override;
|
||||
void UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) override;
|
||||
private:
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
|
||||
@@ -35,7 +35,3 @@ void MySQLDatabase::UpdateAccountPassword(const uint32_t accountId, const std::s
|
||||
void MySQLDatabase::InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) {
|
||||
ExecuteInsert("INSERT INTO accounts (name, password, gm_level) VALUES (?, ?, ?);", username, bcryptpassword, static_cast<int32_t>(eGameMasterLevel::OPERATOR));
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdateAccountGmLevel(const uint32_t accountId, const eGameMasterLevel gmLevel) {
|
||||
ExecuteUpdate("UPDATE accounts SET gm_level = ? WHERE id = ?;", static_cast<int32_t>(gmLevel), accountId);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "IBehaviors.h"
|
||||
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::AddBehavior(const IBehaviors::Info& info) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO behaviors (behavior_info, character_id, behavior_id) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE behavior_info = ?",
|
||||
info.behaviorInfo, info.characterId, info.behaviorId, info.behaviorInfo
|
||||
);
|
||||
}
|
||||
|
||||
void MySQLDatabase::RemoveBehavior(const int32_t behaviorId) {
|
||||
ExecuteDelete("DELETE FROM behaviors WHERE behavior_id = ?", behaviorId);
|
||||
}
|
||||
|
||||
std::string MySQLDatabase::GetBehavior(const int32_t behaviorId) {
|
||||
auto result = ExecuteSelect("SELECT behavior_info FROM behaviors WHERE behavior_id = ?", behaviorId);
|
||||
return result->next() ? result->getString("behavior_info").c_str() : "";
|
||||
}
|
||||
@@ -2,7 +2,6 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
||||
"Accounts.cpp"
|
||||
"AccountsRewardCodes.cpp"
|
||||
"ActivityLog.cpp"
|
||||
"Behaviors.cpp"
|
||||
"BugReports.cpp"
|
||||
"CharInfo.cpp"
|
||||
"CharXml.cpp"
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::vector<IPropertyContents::Model> MySQLDatabase::GetPropertyModels(const LWOOBJID& propertyId) {
|
||||
auto result = ExecuteSelect(
|
||||
"SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id, "
|
||||
"behavior_1, behavior_2, behavior_3, behavior_4, behavior_5 "
|
||||
"FROM properties_contents WHERE property_id = ?;", propertyId);
|
||||
auto result = ExecuteSelect("SELECT id, lot, x, y, z, rx, ry, rz, rw, ugc_id FROM properties_contents WHERE property_id = ?;", propertyId);
|
||||
|
||||
std::vector<IPropertyContents::Model> toReturn;
|
||||
toReturn.reserve(result->rowsCount());
|
||||
@@ -20,12 +17,6 @@ std::vector<IPropertyContents::Model> MySQLDatabase::GetPropertyModels(const LWO
|
||||
model.rotation.y = result->getFloat("ry");
|
||||
model.rotation.z = result->getFloat("rz");
|
||||
model.ugcId = result->getUInt64("ugc_id");
|
||||
model.behaviors[0] = result->getInt("behavior_1");
|
||||
model.behaviors[1] = result->getInt("behavior_2");
|
||||
model.behaviors[2] = result->getInt("behavior_3");
|
||||
model.behaviors[3] = result->getInt("behavior_4");
|
||||
model.behaviors[4] = result->getInt("behavior_5");
|
||||
|
||||
toReturn.push_back(std::move(model));
|
||||
}
|
||||
return toReturn;
|
||||
@@ -41,23 +32,21 @@ void MySQLDatabase::InsertNewPropertyModel(const LWOOBJID& propertyId, const IPr
|
||||
model.id, propertyId, model.ugcId == 0 ? std::nullopt : std::optional(model.ugcId), static_cast<uint32_t>(model.lot),
|
||||
model.position.x, model.position.y, model.position.z, model.rotation.x, model.rotation.y, model.rotation.z, model.rotation.w,
|
||||
name, "", // Model description. TODO implement this.
|
||||
model.behaviors[0], // behavior 1
|
||||
model.behaviors[1], // behavior 2
|
||||
model.behaviors[2], // behavior 3
|
||||
model.behaviors[3], // behavior 4
|
||||
model.behaviors[4] // behavior 5
|
||||
0, // behavior 1. TODO implement this.
|
||||
0, // behavior 2. TODO implement this.
|
||||
0, // behavior 3. TODO implement this.
|
||||
0, // behavior 4. TODO implement this.
|
||||
0 // behavior 5. TODO implement this.
|
||||
);
|
||||
} catch (sql::SQLException& e) {
|
||||
LOG("Error inserting new property model: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void MySQLDatabase::UpdateModel(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation, const std::array<std::pair<int32_t, std::string>, 5>& behaviors) {
|
||||
void MySQLDatabase::UpdateModelPositionRotation(const LWOOBJID& propertyId, const NiPoint3& position, const NiQuaternion& rotation) {
|
||||
ExecuteUpdate(
|
||||
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ?, "
|
||||
"behavior_1 = ?, behavior_2 = ?, behavior_3 = ?, behavior_4 = ?, behavior_5 = ? WHERE id = ?;",
|
||||
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w,
|
||||
behaviors[0].first, behaviors[1].first, behaviors[2].first, behaviors[3].first, behaviors[4].first, propertyId);
|
||||
"UPDATE properties_contents SET x = ?, y = ?, z = ?, rx = ?, ry = ?, rz = ?, rw = ? WHERE id = ?;",
|
||||
position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, propertyId);
|
||||
}
|
||||
|
||||
void MySQLDatabase::RemoveModel(const LWOOBJID& modelId) {
|
||||
|
||||
@@ -225,7 +225,7 @@ void Entity::Initialize() {
|
||||
|
||||
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
|
||||
|
||||
AddComponent<ModelComponent>()->LoadBehaviors();
|
||||
AddComponent<ModelComponent>();
|
||||
|
||||
AddComponent<RenderComponent>();
|
||||
|
||||
@@ -649,7 +649,7 @@ void Entity::Initialize() {
|
||||
}
|
||||
|
||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent<PetComponent>()) {
|
||||
AddComponent<ModelComponent>()->LoadBehaviors();
|
||||
AddComponent<ModelComponent>();
|
||||
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
|
||||
auto* destroyableComponent = AddComponent<DestroyableComponent>();
|
||||
destroyableComponent->SetHealth(1);
|
||||
|
||||
@@ -199,26 +199,6 @@ void BehaviorContext::UpdatePlayerSyncs(float deltaTime) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this->skillUId != 0 && !clientInitalized) {
|
||||
EchoSyncSkill echo;
|
||||
echo.bDone = true;
|
||||
echo.uiSkillHandle = this->skillUId;
|
||||
echo.uiBehaviorHandle = entry.handle;
|
||||
|
||||
RakNet::BitStream bitStream{};
|
||||
entry.behavior->SyncCalculation(this, bitStream, entry.branchContext);
|
||||
|
||||
echo.sBitStream.assign(reinterpret_cast<char*>(bitStream.GetData()), bitStream.GetNumberOfBytesUsed());
|
||||
|
||||
RakNet::BitStream message;
|
||||
BitStreamUtils::WriteHeader(message, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||
message.Write(this->originator);
|
||||
echo.Serialize(message);
|
||||
|
||||
Game::server->Send(message, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||
}
|
||||
|
||||
this->syncEntries.erase(this->syncEntries.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
||||
destroyable->SetIsShielded(true);
|
||||
|
||||
context->RegisterTimerBehavior(this, branch, target->GetObjectID());
|
||||
|
||||
Game::entityManager->SerializeEntity(target);
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||
@@ -54,13 +52,7 @@ void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchCon
|
||||
|
||||
const auto toRemove = std::min(present, this->m_absorbAmount);
|
||||
|
||||
const auto remaining = present - toRemove;
|
||||
|
||||
destroyable->SetDamageToAbsorb(remaining);
|
||||
|
||||
destroyable->SetIsShielded(remaining > 0);
|
||||
|
||||
Game::entityManager->SerializeEntity(target);
|
||||
destroyable->SetDamageToAbsorb(present - toRemove);
|
||||
}
|
||||
|
||||
void DamageAbsorptionBehavior::Load() {
|
||||
|
||||
@@ -37,9 +37,6 @@
|
||||
#include "CDScriptComponentTable.h"
|
||||
#include "CDObjectSkillsTable.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
|
||||
this->m_Dirty = true;
|
||||
@@ -495,11 +492,6 @@ void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* const groups = inventoryElement->FirstChildElement("grps");
|
||||
if (groups) {
|
||||
LoadGroupXml(*groups);
|
||||
}
|
||||
|
||||
m_Consumable = inventoryElement->IntAttribute("csl", LOT_NULL);
|
||||
|
||||
auto* bag = bags->FirstChildElement();
|
||||
@@ -638,15 +630,6 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
|
||||
bags->LinkEndChild(bag);
|
||||
}
|
||||
|
||||
auto* groups = inventoryElement->FirstChildElement("grps");
|
||||
if (groups) {
|
||||
groups->DeleteChildren();
|
||||
} else {
|
||||
groups = inventoryElement->InsertNewChildElement("grps");
|
||||
}
|
||||
|
||||
UpdateGroupXml(*groups);
|
||||
|
||||
auto* items = inventoryElement->FirstChildElement("items");
|
||||
|
||||
if (items == nullptr) {
|
||||
@@ -1620,110 +1603,3 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) {
|
||||
m_Skills.insert_or_assign(slot, skillId);
|
||||
return true;
|
||||
}
|
||||
|
||||
void InventoryComponent::UpdateGroup(const GroupUpdate& groupUpdate) {
|
||||
if (groupUpdate.groupId.empty()) return;
|
||||
|
||||
if (groupUpdate.inventory != eInventoryType::BRICKS && groupUpdate.inventory != eInventoryType::MODELS) {
|
||||
LOG("Invalid inventory type for grouping %s", StringifiedEnum::ToString(groupUpdate.inventory).data());
|
||||
return;
|
||||
}
|
||||
|
||||
auto& groups = m_Groups[groupUpdate.inventory];
|
||||
auto groupItr = std::ranges::find_if(groups, [&groupUpdate](const Group& group) {
|
||||
return group.groupId == groupUpdate.groupId;
|
||||
});
|
||||
|
||||
if (groupUpdate.command != GroupUpdateCommand::ADD && groupItr == groups.end()) {
|
||||
LOG("Group %s not found in inventory %s. Cannot process command.", groupUpdate.groupId.c_str(), StringifiedEnum::ToString(groupUpdate.inventory).data());
|
||||
return;
|
||||
}
|
||||
|
||||
if (groupUpdate.command == GroupUpdateCommand::ADD && groups.size() >= MaximumGroupCount) {
|
||||
LOG("Cannot add group to inventory %s. Maximum group count reached.", StringifiedEnum::ToString(groupUpdate.inventory).data());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (groupUpdate.command) {
|
||||
case GroupUpdateCommand::ADD: {
|
||||
auto& group = groups.emplace_back();
|
||||
group.groupId = groupUpdate.groupId;
|
||||
group.groupName = groupUpdate.groupName;
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::ADD_LOT: {
|
||||
groupItr->lots.insert(groupUpdate.lot);
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::REMOVE: {
|
||||
groups.erase(groupItr);
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::REMOVE_LOT: {
|
||||
groupItr->lots.erase(groupUpdate.lot);
|
||||
break;
|
||||
}
|
||||
case GroupUpdateCommand::MODIFY: {
|
||||
groupItr->groupName = groupUpdate.groupName;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG("Invalid group update command %i", groupUpdate.command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::UpdateGroupXml(tinyxml2::XMLElement& groups) const {
|
||||
for (const auto& [inventory, groupsData] : m_Groups) {
|
||||
for (const auto& group : groupsData) {
|
||||
auto* const groupElement = groups.InsertNewChildElement("grp");
|
||||
|
||||
groupElement->SetAttribute("id", group.groupId.c_str());
|
||||
groupElement->SetAttribute("n", group.groupName.c_str());
|
||||
groupElement->SetAttribute("t", static_cast<uint32_t>(inventory));
|
||||
groupElement->SetAttribute("u", 0);
|
||||
std::ostringstream lots;
|
||||
bool first = true;
|
||||
for (const auto lot : group.lots) {
|
||||
if (!first) lots << ' ';
|
||||
first = false;
|
||||
|
||||
lots << lot;
|
||||
}
|
||||
groupElement->SetAttribute("l", lots.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::LoadGroupXml(const tinyxml2::XMLElement& groups) {
|
||||
auto* groupElement = groups.FirstChildElement("grp");
|
||||
|
||||
while (groupElement) {
|
||||
const char* groupId = nullptr;
|
||||
const char* groupName = nullptr;
|
||||
const char* lots = nullptr;
|
||||
uint32_t inventory = eInventoryType::INVALID;
|
||||
|
||||
groupElement->QueryStringAttribute("id", &groupId);
|
||||
groupElement->QueryStringAttribute("n", &groupName);
|
||||
groupElement->QueryStringAttribute("l", &lots);
|
||||
groupElement->QueryAttribute("t", &inventory);
|
||||
|
||||
if (!groupId || !groupName || !lots) {
|
||||
LOG("Failed to load group from xml id %i name %i lots %i",
|
||||
groupId == nullptr, groupName == nullptr, lots == nullptr);
|
||||
} else {
|
||||
auto& group = m_Groups[static_cast<eInventoryType>(inventory)].emplace_back();
|
||||
group.groupId = groupId;
|
||||
group.groupName = groupName;
|
||||
|
||||
for (const auto& lotStr : GeneralUtils::SplitString(lots, ' ')) {
|
||||
auto lot = GeneralUtils::TryParse<LOT>(lotStr);
|
||||
if (lot) group.lots.insert(*lot);
|
||||
}
|
||||
}
|
||||
|
||||
groupElement = groupElement->NextSiblingElement("grp");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,35 +37,6 @@ enum class eItemType : int32_t;
|
||||
*/
|
||||
class InventoryComponent final : public Component {
|
||||
public:
|
||||
struct Group {
|
||||
// Generated ID for the group. The ID is sent by the client and has the format user_group + Math.random() * UINT_MAX.
|
||||
std::string groupId;
|
||||
// Custom name assigned by the user.
|
||||
std::string groupName;
|
||||
// All the lots the user has in the group.
|
||||
std::set<LOT> lots;
|
||||
};
|
||||
|
||||
enum class GroupUpdateCommand {
|
||||
ADD,
|
||||
ADD_LOT,
|
||||
MODIFY,
|
||||
REMOVE,
|
||||
REMOVE_LOT,
|
||||
};
|
||||
|
||||
// Based on the command, certain fields will be used or not used.
|
||||
// for example, ADD_LOT wont use groupName, MODIFY wont use lots, etc.
|
||||
struct GroupUpdate {
|
||||
std::string groupId;
|
||||
std::string groupName;
|
||||
LOT lot;
|
||||
eInventoryType inventory;
|
||||
GroupUpdateCommand command;
|
||||
};
|
||||
|
||||
static constexpr uint32_t MaximumGroupCount = 50;
|
||||
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||
InventoryComponent(Entity* parent);
|
||||
|
||||
@@ -396,23 +367,14 @@ public:
|
||||
*/
|
||||
void UnequipScripts(Item* unequippedItem);
|
||||
|
||||
std::map<BehaviorSlot, uint32_t> GetSkills() { return m_Skills; };
|
||||
std::map<BehaviorSlot, uint32_t> GetSkills(){ return m_Skills; };
|
||||
|
||||
bool SetSkill(int slot, uint32_t skillId);
|
||||
bool SetSkill(BehaviorSlot slot, uint32_t skillId);
|
||||
|
||||
void UpdateGroup(const GroupUpdate& groupUpdate);
|
||||
void RemoveGroup(const std::string& groupId);
|
||||
|
||||
~InventoryComponent() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The key is the inventory the group belongs to, the value maps' key is the id for the group.
|
||||
* This is only used for bricks and model inventories.
|
||||
*/
|
||||
std::map<eInventoryType, std::vector<Group>> m_Groups{ { eInventoryType::BRICKS, {} }, { eInventoryType::MODELS, {} } };
|
||||
|
||||
/**
|
||||
* All the inventory this entity possesses
|
||||
*/
|
||||
@@ -515,9 +477,6 @@ private:
|
||||
* @param document the xml doc to load from
|
||||
*/
|
||||
void UpdatePetXml(tinyxml2::XMLDocument& document);
|
||||
|
||||
void LoadGroupXml(const tinyxml2::XMLElement& groups);
|
||||
void UpdateGroupXml(tinyxml2::XMLElement& groups) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
|
||||
#include "BehaviorStates.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
#include "Database.h"
|
||||
|
||||
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
m_OriginalPosition = m_Parent->GetDefaultPosition();
|
||||
@@ -17,33 +14,6 @@ ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
||||
}
|
||||
|
||||
void ModelComponent::LoadBehaviors() {
|
||||
auto behaviors = GeneralUtils::SplitString(m_Parent->GetVar<std::string>(u"userModelBehaviors"), ',');
|
||||
for (const auto& behavior : behaviors) {
|
||||
if (behavior.empty()) continue;
|
||||
|
||||
const auto behaviorId = GeneralUtils::TryParse<int32_t>(behavior);
|
||||
if (!behaviorId.has_value() || behaviorId.value() == 0) continue;
|
||||
|
||||
LOG_DEBUG("Loading behavior %d", behaviorId.value());
|
||||
auto& inserted = m_Behaviors.emplace_back();
|
||||
inserted.SetBehaviorId(*behaviorId);
|
||||
|
||||
const auto behaviorStr = Database::Get()->GetBehavior(behaviorId.value());
|
||||
|
||||
tinyxml2::XMLDocument behaviorXml;
|
||||
auto res = behaviorXml.Parse(behaviorStr.c_str(), behaviorStr.size());
|
||||
LOG_DEBUG("Behavior %i %d: %s", res, behaviorId.value(), behaviorStr.c_str());
|
||||
|
||||
const auto* const behaviorRoot = behaviorXml.FirstChildElement("Behavior");
|
||||
if (!behaviorRoot) {
|
||||
LOG("Failed to load behavior %d due to missing behavior root", behaviorId.value());
|
||||
continue;
|
||||
}
|
||||
inserted.Deserialize(*behaviorRoot);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
// ItemComponent Serialization. Pets do not get this serialization.
|
||||
if (!m_Parent->HasComponent(eReplicaComponentType::PET)) {
|
||||
@@ -102,23 +72,3 @@ void ModelComponent::MoveToInventory(MoveToInventoryMessage& msg) {
|
||||
m_Behaviors.erase(m_Behaviors.begin() + msg.GetBehaviorIndex());
|
||||
// TODO move to the inventory
|
||||
}
|
||||
|
||||
std::array<std::pair<int32_t, std::string>, 5> ModelComponent::GetBehaviorsForSave() const {
|
||||
std::array<std::pair<int32_t, std::string>, 5> toReturn{};
|
||||
for (auto i = 0; i < m_Behaviors.size(); i++) {
|
||||
const auto& behavior = m_Behaviors.at(i);
|
||||
if (behavior.GetBehaviorId() == -1) continue;
|
||||
auto& [id, behaviorData] = toReturn[i];
|
||||
id = behavior.GetBehaviorId();
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
auto* root = doc.NewElement("Behavior");
|
||||
behavior.Serialize(*root);
|
||||
doc.InsertFirstChild(root);
|
||||
|
||||
tinyxml2::XMLPrinter printer(0, true, 0);
|
||||
doc.Print(&printer);
|
||||
behaviorData = printer.CStr();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include "dCommonVars.h"
|
||||
@@ -29,8 +28,6 @@ public:
|
||||
|
||||
ModelComponent(Entity* parent);
|
||||
|
||||
void LoadBehaviors();
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
/**
|
||||
@@ -112,8 +109,6 @@ public:
|
||||
|
||||
void VerifyBehaviors();
|
||||
|
||||
std::array<std::pair<int32_t, std::string>, 5> GetBehaviorsForSave() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The behaviors of the model
|
||||
|
||||
@@ -21,11 +21,9 @@
|
||||
#include "eObjectBits.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "ModelComponent.h"
|
||||
|
||||
#include <vector>
|
||||
#include "CppScripts.h"
|
||||
#include <ranges>
|
||||
|
||||
PropertyManagementComponent* PropertyManagementComponent::instance = nullptr;
|
||||
|
||||
@@ -595,20 +593,6 @@ void PropertyManagementComponent::Load() {
|
||||
settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
}
|
||||
|
||||
std::ostringstream userModelBehavior;
|
||||
bool firstAdded = false;
|
||||
for (auto behavior : databaseModel.behaviors) {
|
||||
if (behavior < 0) {
|
||||
LOG("Invalid behavior ID: %d, removing behavior reference from model", behavior);
|
||||
behavior = 0;
|
||||
}
|
||||
if (firstAdded) userModelBehavior << ",";
|
||||
userModelBehavior << behavior;
|
||||
firstAdded = true;
|
||||
}
|
||||
|
||||
settings.push_back(new LDFData<std::string>(u"userModelBehaviors", userModelBehavior.str()));
|
||||
|
||||
node->config = settings;
|
||||
|
||||
const auto spawnerId = Game::zoneManager->MakeSpawner(info);
|
||||
@@ -626,12 +610,6 @@ void PropertyManagementComponent::Save() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* const owner = GetOwner();
|
||||
if (!owner) return;
|
||||
|
||||
const auto* const character = owner->GetCharacter();
|
||||
if (!character) return;
|
||||
|
||||
auto present = Database::Get()->GetPropertyModels(propertyId);
|
||||
|
||||
std::vector<LWOOBJID> modelIds;
|
||||
@@ -646,20 +624,6 @@ void PropertyManagementComponent::Save() {
|
||||
if (entity == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto* modelComponent = entity->GetComponent<ModelComponent>();
|
||||
if (!modelComponent) continue;
|
||||
const auto modelBehaviors = modelComponent->GetBehaviorsForSave();
|
||||
|
||||
// save the behaviors of the model
|
||||
for (const auto& [behaviorId, behaviorStr] : modelBehaviors) {
|
||||
if (behaviorStr.empty() || behaviorId == -1 || behaviorId == 0) continue;
|
||||
IBehaviors::Info info {
|
||||
.behaviorId = behaviorId,
|
||||
.characterId = character->GetID(),
|
||||
.behaviorInfo = behaviorStr
|
||||
};
|
||||
Database::Get()->AddBehavior(info);
|
||||
}
|
||||
|
||||
const auto position = entity->GetPosition();
|
||||
const auto rotation = entity->GetRotation();
|
||||
@@ -671,13 +635,10 @@ void PropertyManagementComponent::Save() {
|
||||
model.position = position;
|
||||
model.rotation = rotation;
|
||||
model.ugcId = 0;
|
||||
for (auto i = 0; i < model.behaviors.size(); i++) {
|
||||
model.behaviors[i] = modelBehaviors[i].first;
|
||||
}
|
||||
|
||||
Database::Get()->InsertNewPropertyModel(propertyId, model, "Objects_" + std::to_string(model.lot) + "_name");
|
||||
} else {
|
||||
Database::Get()->UpdateModel(id, position, rotation, modelBehaviors);
|
||||
Database::Get()->UpdateModelPositionRotation(id, position, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ RacingControlComponent::RacingControlComponent(Entity* parent)
|
||||
m_LoadedPlayers = 0;
|
||||
m_LoadTimer = 0;
|
||||
m_Finished = 0;
|
||||
m_StartTime = 0;
|
||||
m_EmptyTimer = 0;
|
||||
m_SoloRacing = Game::config->GetValue("solo_racing") == "1";
|
||||
|
||||
@@ -397,6 +398,25 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu
|
||||
GameMessages::SendNotifyRacingClient(
|
||||
m_Parent->GetObjectID(), 2, 0, LWOOBJID_EMPTY, u"",
|
||||
player->GetObjectID(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionComponent == nullptr) return;
|
||||
|
||||
missionComponent->Progress(eMissionTaskType::RACING, 0, static_cast<LWOOBJID>(eRacingTaskParam::COMPETED_IN_RACE)); // Progress task for competing in a race
|
||||
missionComponent->Progress(eMissionTaskType::RACING, data->smashedTimes, static_cast<LWOOBJID>(eRacingTaskParam::SAFE_DRIVER)); // Finish a race without being smashed.
|
||||
|
||||
// If solo racing is enabled OR if there are 3 players in the race, progress placement tasks.
|
||||
if (m_SoloRacing || m_LoadedPlayers > 2) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, data->finished, static_cast<LWOOBJID>(eRacingTaskParam::FINISH_WITH_PLACEMENT)); // Finish in 1st place on a race
|
||||
if (data->finished == 1) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS)); // Finish in 1st place on multiple tracks.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::WIN_RACE_IN_WORLD)); // Finished first place in specific world.
|
||||
}
|
||||
if (data->finished == m_LoadedPlayers) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::LAST_PLACE_FINISH)); // Finished first place in specific world.
|
||||
}
|
||||
}
|
||||
} else if ((id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") && button == m_ActivityExitConfirm) {
|
||||
auto* vehicle = Game::entityManager->GetEntity(data->vehicleID);
|
||||
|
||||
@@ -426,9 +446,9 @@ void RacingControlComponent::Serialize(RakNet::BitStream& outBitStream, bool bIs
|
||||
outBitStream.Write(player.playerID);
|
||||
|
||||
outBitStream.Write(player.data[0]);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.raceTime.count() / 1000.0f);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.raceTime);
|
||||
else outBitStream.Write(player.data[1]);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.bestLapTime.count() / 1000.0f);
|
||||
if (player.finished != 0) outBitStream.Write<float>(player.bestLapTime);
|
||||
else outBitStream.Write(player.data[2]);
|
||||
if (player.finished == 1) outBitStream.Write<float>(1.0f);
|
||||
else outBitStream.Write(player.data[3]);
|
||||
@@ -489,8 +509,8 @@ void RacingControlComponent::Serialize(RakNet::BitStream& outBitStream, bool bIs
|
||||
if (player.finished == 0) continue;
|
||||
outBitStream.Write1(); // Has more data
|
||||
outBitStream.Write(player.playerID);
|
||||
outBitStream.Write<float>(player.bestLapTime.count() / 1000.0f);
|
||||
outBitStream.Write<float>(player.raceTime.count() / 1000.0f);
|
||||
outBitStream.Write<float>(player.bestLapTime);
|
||||
outBitStream.Write<float>(player.raceTime);
|
||||
}
|
||||
|
||||
outBitStream.Write0(); // No more data
|
||||
@@ -720,7 +740,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
m_StartTime = std::chrono::high_resolution_clock::now();
|
||||
m_StartTime = std::time(nullptr);
|
||||
}
|
||||
|
||||
m_StartTimer += deltaTime;
|
||||
@@ -809,60 +829,46 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
|
||||
// Reached the start point, lapped
|
||||
if (respawnIndex == 0) {
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
const auto lapTime = std::chrono::duration_cast<std::chrono::milliseconds>(now - (player.lap == 0 ? m_StartTime : player.lapTime));
|
||||
time_t lapTime = std::time(nullptr) - (player.lap == 0 ? m_StartTime : player.lapTime);
|
||||
|
||||
// Cheating check
|
||||
if (lapTime.count() < 40000) {
|
||||
if (lapTime < 40) {
|
||||
continue;
|
||||
}
|
||||
|
||||
player.lapTime = now;
|
||||
player.lap++;
|
||||
|
||||
if (player.bestLapTime > lapTime || player.lap == 0) {
|
||||
player.lapTime = std::time(nullptr);
|
||||
|
||||
if (player.bestLapTime == 0 || player.bestLapTime > lapTime) {
|
||||
player.bestLapTime = lapTime;
|
||||
|
||||
LOG("Best lap time (%llu)", lapTime);
|
||||
}
|
||||
|
||||
player.lap++;
|
||||
|
||||
auto* missionComponent =
|
||||
playerEntity->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionComponent != nullptr) {
|
||||
|
||||
// Progress lap time tasks
|
||||
missionComponent->Progress(eMissionTaskType::RACING, lapTime.count(), static_cast<LWOOBJID>(eRacingTaskParam::LAP_TIME));
|
||||
missionComponent->Progress(eMissionTaskType::RACING, (lapTime) * 1000, static_cast<LWOOBJID>(eRacingTaskParam::LAP_TIME));
|
||||
|
||||
if (player.lap == 3) {
|
||||
m_Finished++;
|
||||
player.finished = m_Finished;
|
||||
|
||||
const auto raceTime = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_StartTime);
|
||||
const auto raceTime =
|
||||
(std::time(nullptr) - m_StartTime);
|
||||
|
||||
player.raceTime = raceTime;
|
||||
|
||||
LOG("Completed time %llums %fs", raceTime.count(), raceTime.count() / 1000.0f);
|
||||
LOG("Completed time %llu, %llu",
|
||||
raceTime, raceTime * 1000);
|
||||
|
||||
LeaderboardManager::SaveScore(playerEntity->GetObjectID(), m_ActivityID, static_cast<float>(player.raceTime.count()) / 1000, static_cast<float>(player.bestLapTime.count()) / 1000, static_cast<float>(player.finished == 1));
|
||||
LeaderboardManager::SaveScore(playerEntity->GetObjectID(), m_ActivityID, static_cast<float>(player.raceTime), static_cast<float>(player.bestLapTime), static_cast<float>(player.finished == 1));
|
||||
// Entire race time
|
||||
missionComponent->Progress(eMissionTaskType::RACING, player.raceTime.count(), static_cast<LWOOBJID>(eRacingTaskParam::TOTAL_TRACK_TIME));
|
||||
|
||||
missionComponent->Progress(eMissionTaskType::RACING, 0, static_cast<LWOOBJID>(eRacingTaskParam::COMPETED_IN_RACE)); // Progress task for competing in a race
|
||||
missionComponent->Progress(eMissionTaskType::RACING, player.smashedTimes, static_cast<LWOOBJID>(eRacingTaskParam::SAFE_DRIVER)); // Finish a race without being smashed.
|
||||
|
||||
// If solo racing is enabled OR if there are 3 players in the race, progress placement tasks.
|
||||
if (m_SoloRacing || m_RacingPlayers.size() > 2) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, player.finished, static_cast<LWOOBJID>(eRacingTaskParam::FINISH_WITH_PLACEMENT)); // Finish in 1st place on a race
|
||||
if (player.finished == 1) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS)); // Finish in 1st place on multiple tracks.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::WIN_RACE_IN_WORLD)); // Finished first place in specific world.
|
||||
}
|
||||
if (player.finished == m_RacingPlayers.size()) {
|
||||
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), static_cast<LWOOBJID>(eRacingTaskParam::LAST_PLACE_FINISH)); // Finished first place in specific world.
|
||||
}
|
||||
}
|
||||
missionComponent->Progress(eMissionTaskType::RACING, (raceTime) * 1000, static_cast<LWOOBJID>(eRacingTaskParam::TOTAL_TRACK_TIME));
|
||||
|
||||
auto* characterComponent = playerEntity->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
@@ -871,8 +877,8 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
LOG("Lapped (%i) in (%llums %fs)", player.lap,
|
||||
lapTime.count(), lapTime.count() / 1000.0f);
|
||||
LOG("Lapped (%i) in (%llu)", player.lap,
|
||||
lapTime);
|
||||
}
|
||||
|
||||
LOG("Reached point (%i)/(%i)", player.respawnIndex,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* Information for each player in the race
|
||||
@@ -73,12 +72,12 @@ struct RacingPlayerInfo {
|
||||
/**
|
||||
* The fastest lap time of the player
|
||||
*/
|
||||
std::chrono::milliseconds bestLapTime;
|
||||
time_t bestLapTime = 0;
|
||||
|
||||
/**
|
||||
* The current lap time of the player
|
||||
*/
|
||||
std::chrono::high_resolution_clock::time_point lapTime;
|
||||
time_t lapTime = 0;
|
||||
|
||||
/**
|
||||
* The number of times this player smashed their car
|
||||
@@ -98,7 +97,7 @@ struct RacingPlayerInfo {
|
||||
/**
|
||||
* Unused
|
||||
*/
|
||||
std::chrono::milliseconds raceTime;
|
||||
time_t raceTime = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -232,7 +231,7 @@ private:
|
||||
/**
|
||||
* The time the race was started
|
||||
*/
|
||||
std::chrono::high_resolution_clock::time_point m_StartTime;
|
||||
time_t m_StartTime;
|
||||
|
||||
/**
|
||||
* Timer for tracking how long a player was alone in this race
|
||||
|
||||
@@ -685,13 +685,6 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
|
||||
case eGameMessageType::REQUEST_VENDOR_STATUS_UPDATE:
|
||||
GameMessages::SendVendorStatusUpdate(entity, sysAddr, true);
|
||||
break;
|
||||
case eGameMessageType::UPDATE_INVENTORY_GROUP:
|
||||
GameMessages::HandleUpdateInventoryGroup(inStream, entity, sysAddr);
|
||||
break;
|
||||
case eGameMessageType::UPDATE_INVENTORY_GROUP_CONTENTS:
|
||||
GameMessages::HandleUpdateInventoryGroupContents(inStream, entity, sysAddr);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_DEBUG("Received Unknown GM with ID: %4i, %s", messageID, StringifiedEnum::ToString(messageID).data());
|
||||
break;
|
||||
|
||||
@@ -99,7 +99,6 @@
|
||||
#include "ActivityManager.h"
|
||||
#include "PlayerManager.h"
|
||||
#include "eVendorTransactionResult.h"
|
||||
#include "eReponseMoveItemBetweenInventoryTypeCode.h"
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDObjectsTable.h"
|
||||
@@ -4566,31 +4565,16 @@ void GameMessages::HandleRequestMoveItemBetweenInventoryTypes(RakNet::BitStream&
|
||||
if (inStream.ReadBit()) inStream.Read(itemLOT);
|
||||
|
||||
if (invTypeDst == invTypeSrc) {
|
||||
SendResponseMoveItemBetweenInventoryTypes(entity->GetObjectID(), sysAddr, invTypeDst, invTypeSrc, eReponseMoveItemBetweenInventoryTypeCode::FAIL_GENERIC);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventoryComponent) {
|
||||
if (inventoryComponent != nullptr) {
|
||||
if (itemID != LWOOBJID_EMPTY) {
|
||||
auto* item = inventoryComponent->FindItemById(itemID);
|
||||
|
||||
if (!item) {
|
||||
SendResponseMoveItemBetweenInventoryTypes(entity->GetObjectID(), sysAddr, invTypeDst, invTypeSrc, eReponseMoveItemBetweenInventoryTypeCode::FAIL_ITEM_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->GetLot() == 6086) { // Thinking hat
|
||||
SendResponseMoveItemBetweenInventoryTypes(entity->GetObjectID(), sysAddr, invTypeDst, invTypeSrc, eReponseMoveItemBetweenInventoryTypeCode::FAIL_CANT_MOVE_THINKING_HAT);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* destInv = inventoryComponent->GetInventory(invTypeDst);
|
||||
if (destInv && destInv->GetEmptySlots() == 0) {
|
||||
SendResponseMoveItemBetweenInventoryTypes(entity->GetObjectID(), sysAddr, invTypeDst, invTypeSrc, eReponseMoveItemBetweenInventoryTypeCode::FAIL_INV_FULL);
|
||||
return;
|
||||
}
|
||||
if (!item) return;
|
||||
|
||||
// Despawn the pet if we are moving that pet to the vault.
|
||||
auto* petComponent = PetComponent::GetActivePet(entity->GetObjectID());
|
||||
@@ -4599,32 +4583,10 @@ void GameMessages::HandleRequestMoveItemBetweenInventoryTypes(RakNet::BitStream&
|
||||
}
|
||||
|
||||
inventoryComponent->MoveItemToInventory(item, invTypeDst, iStackCount, showFlyingLoot, false, false, destSlot);
|
||||
SendResponseMoveItemBetweenInventoryTypes(entity->GetObjectID(), sysAddr, invTypeDst, invTypeSrc, eReponseMoveItemBetweenInventoryTypeCode::SUCCESS);
|
||||
}
|
||||
} else {
|
||||
SendResponseMoveItemBetweenInventoryTypes(entity->GetObjectID(), sysAddr, invTypeDst, invTypeSrc, eReponseMoveItemBetweenInventoryTypeCode::FAIL_GENERIC);
|
||||
}
|
||||
}
|
||||
|
||||
void GameMessages::SendResponseMoveItemBetweenInventoryTypes(LWOOBJID objectId, const SystemAddress& sysAddr, eInventoryType inventoryTypeDestination, eInventoryType inventoryTypeSource, eReponseMoveItemBetweenInventoryTypeCode response) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(objectId);
|
||||
bitStream.Write(eGameMessageType::RESPONSE_MOVE_ITEM_BETWEEN_INVENTORY_TYPES);
|
||||
|
||||
bitStream.Write(inventoryTypeDestination != eInventoryType::ITEMS);
|
||||
if (inventoryTypeDestination != eInventoryType::ITEMS) bitStream.Write(inventoryTypeDestination);
|
||||
|
||||
bitStream.Write(inventoryTypeSource != eInventoryType::ITEMS);
|
||||
if (inventoryTypeSource != eInventoryType::ITEMS) bitStream.Write(inventoryTypeSource);
|
||||
|
||||
bitStream.Write(response != eReponseMoveItemBetweenInventoryTypeCode::FAIL_GENERIC);
|
||||
if (response != eReponseMoveItemBetweenInventoryTypeCode::FAIL_GENERIC) bitStream.Write(response);
|
||||
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
void GameMessages::SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditionalSound, bool bPlayCountdownSound, std::u16string sndName, int32_t stateToPlaySoundOn, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
@@ -6251,69 +6213,6 @@ void GameMessages::SendSlashCommandFeedbackText(Entity* entity, std::u16string t
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::HandleUpdateInventoryGroup(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
std::string action;
|
||||
std::u16string groupName;
|
||||
InventoryComponent::GroupUpdate groupUpdate;
|
||||
bool locked{}; // All groups are locked by default
|
||||
|
||||
uint32_t size{};
|
||||
if (!inStream.Read(size)) return;
|
||||
action.resize(size);
|
||||
if (!inStream.Read(action.data(), size)) return;
|
||||
|
||||
if (!inStream.Read(size)) return;
|
||||
groupUpdate.groupId.resize(size);
|
||||
if (!inStream.Read(groupUpdate.groupId.data(), size)) return;
|
||||
|
||||
if (!inStream.Read(size)) return;
|
||||
groupName.resize(size);
|
||||
if (!inStream.Read(reinterpret_cast<char*>(groupName.data()), size * 2)) return;
|
||||
|
||||
if (!inStream.Read(groupUpdate.inventory)) return;
|
||||
if (!inStream.Read(locked)) return;
|
||||
|
||||
groupUpdate.groupName = GeneralUtils::UTF16ToWTF8(groupName);
|
||||
|
||||
if (action == "ADD") groupUpdate.command = InventoryComponent::GroupUpdateCommand::ADD;
|
||||
else if (action == "MODIFY") groupUpdate.command = InventoryComponent::GroupUpdateCommand::MODIFY;
|
||||
else if (action == "REMOVE") groupUpdate.command = InventoryComponent::GroupUpdateCommand::REMOVE;
|
||||
else {
|
||||
LOG("Invalid action %s", action.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
if (inventoryComponent) inventoryComponent->UpdateGroup(groupUpdate);
|
||||
}
|
||||
|
||||
void GameMessages::HandleUpdateInventoryGroupContents(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||
std::string action;
|
||||
InventoryComponent::GroupUpdate groupUpdate;
|
||||
|
||||
uint32_t size{};
|
||||
if (!inStream.Read(size)) return;
|
||||
action.resize(size);
|
||||
if (!inStream.Read(action.data(), size)) return;
|
||||
|
||||
if (action == "ADD") groupUpdate.command = InventoryComponent::GroupUpdateCommand::ADD_LOT;
|
||||
else if (action == "REMOVE") groupUpdate.command = InventoryComponent::GroupUpdateCommand::REMOVE_LOT;
|
||||
else {
|
||||
LOG("Invalid action %s", action.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inStream.Read(size)) return;
|
||||
groupUpdate.groupId.resize(size);
|
||||
if (!inStream.Read(groupUpdate.groupId.data(), size)) return;
|
||||
|
||||
if (!inStream.Read(groupUpdate.inventory)) return;
|
||||
if (!inStream.Read(groupUpdate.lot)) return;
|
||||
|
||||
auto* inventoryComponent = entity->GetComponent<InventoryComponent>();
|
||||
if (inventoryComponent) inventoryComponent->UpdateGroup(groupUpdate);
|
||||
}
|
||||
|
||||
void GameMessages::SendForceCameraTargetCycle(Entity* entity, bool bForceCycling, eCameraTargetCyclingMode cyclingMode, LWOOBJID optionalTargetID) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
@@ -39,7 +39,6 @@ enum class eQuickBuildFailReason : uint32_t;
|
||||
enum class eQuickBuildState : uint32_t;
|
||||
enum class BehaviorSlot : int32_t;
|
||||
enum class eVendorTransactionResult : uint32_t;
|
||||
enum class eReponseMoveItemBetweenInventoryTypeCode : int32_t;
|
||||
|
||||
enum class eCameraTargetCyclingMode : int32_t {
|
||||
ALLOW_CYCLE_TEAMMATES,
|
||||
@@ -595,7 +594,6 @@ namespace GameMessages {
|
||||
//NT:
|
||||
|
||||
void HandleRequestMoveItemBetweenInventoryTypes(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
void SendResponseMoveItemBetweenInventoryTypes(LWOOBJID objectId, const SystemAddress& sysAddr, eInventoryType inventoryTypeDestination, eInventoryType inventoryTypeSource, eReponseMoveItemBetweenInventoryTypeCode response);
|
||||
|
||||
void SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditionalSound, bool bPlayCountdownSound, std::u16string sndName, int32_t stateToPlaySoundOn, const SystemAddress& sysAddr);
|
||||
|
||||
@@ -673,9 +671,6 @@ namespace GameMessages {
|
||||
void HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity);
|
||||
|
||||
void SendSlashCommandFeedbackText(Entity* entity, std::u16string text);
|
||||
|
||||
void HandleUpdateInventoryGroup(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
void HandleUpdateInventoryGroupContents(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
void SendForceCameraTargetCycle(Entity* entity, bool bForceCycling, eCameraTargetCyclingMode cyclingMode, LWOOBJID optionalTargetID);
|
||||
};
|
||||
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
#include "eUseItemResponse.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "eDeletionRestrictionsCheckType.h"
|
||||
|
||||
#include "CDBrickIDTableTable.h"
|
||||
#include "CDObjectSkillsTable.h"
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPackageComponentTable.h"
|
||||
#include "CDDeletionRestrictionsTable.h"
|
||||
|
||||
namespace {
|
||||
const std::map<std::string, std::string> ExtraSettingAbbreviations = {
|
||||
@@ -568,3 +570,43 @@ void Item::LoadConfigXml(const tinyxml2::XMLElement& i) {
|
||||
config.push_back(LDFBaseData::DataFromString(value));
|
||||
}
|
||||
}
|
||||
|
||||
bool Item::CanDeleteItem(Item* item) {
|
||||
if (!item) return false;
|
||||
// TODO:
|
||||
// Check if item is being possessed
|
||||
// Check if the owner is mounting item? (how is this different than the above)
|
||||
// Allow GM 9 to freely delete
|
||||
// Finally, check Deletion Restriction
|
||||
const auto& itemComponent = item->inventory->FindItemComponent(item->lot);
|
||||
if (itemComponent.delResIndex == -1) return true;
|
||||
return CheckDeletionRestriction(itemComponent.delResIndex, item->lot);
|
||||
}
|
||||
|
||||
bool Item::CheckDeletionRestriction(uint32_t delResIndex, LOT item) {
|
||||
auto* delresTable = CDClientManager::GetTable<CDDeletionRestrictionsTable>();
|
||||
const auto restriction = delresTable->GetByID(delResIndex);
|
||||
|
||||
switch(restriction.checkType) {
|
||||
case eDeletionRestrictionsCheckType::INCLUDE_LOTS:
|
||||
if (std::ranges::find(restriction.ids, item) != restriction.ids.end()) return false;
|
||||
else return true;
|
||||
case eDeletionRestrictionsCheckType::EXCLUDE_LOTS:
|
||||
if (std::ranges::find(restriction.ids, item) != restriction.ids.end()) return true;
|
||||
else return false;
|
||||
case eDeletionRestrictionsCheckType::ANY_OF_THESE:
|
||||
// TODO: Implement
|
||||
return true;
|
||||
case eDeletionRestrictionsCheckType::ALL_OF_THESE:
|
||||
// TODO: Implement
|
||||
return true;
|
||||
case eDeletionRestrictionsCheckType::WHILE_IN_ZONE:
|
||||
if (std::ranges::find(restriction.ids, Game::zoneManager->GetZoneID().GetMapID()) != restriction.ids.end()) return false;
|
||||
else return true;
|
||||
case eDeletionRestrictionsCheckType::ALWAYS_RESTRICTED:
|
||||
return false;
|
||||
case eDeletionRestrictionsCheckType::MAX:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +228,13 @@ public:
|
||||
|
||||
void LoadConfigXml(const tinyxml2::XMLElement& i);
|
||||
|
||||
bool CanDeleteItem(Item* item);
|
||||
|
||||
bool CheckDeletionRestriction(uint32_t delResIndex, LOT item);
|
||||
|
||||
bool CheckDeletionRestrictionRecursion(std::set<uint32_t>& delResIndexs, uint32_t delResIndex);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* The object ID of this item
|
||||
|
||||
@@ -186,7 +186,7 @@ void MissionTask::Progress(int32_t value, LWOOBJID associate, const std::string&
|
||||
|
||||
if (count < 0) {
|
||||
if (mission->IsMission() && type == eMissionTaskType::GATHER && InAllTargets(value)) {
|
||||
if (parameters.size() > 0 && (parameters[0] & 4) != 0) {
|
||||
if (parameters.size() > 0 && (parameters[0] & 1) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "Action.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
#include "tinyxml2.h"
|
||||
|
||||
Action::Action(const AMFArrayValue& arguments) {
|
||||
for (const auto& [paramName, paramValue] : arguments.GetAssociative()) {
|
||||
if (paramName == "Type") {
|
||||
@@ -34,46 +32,3 @@ void Action::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
actionArgs->Insert(m_ValueParameterName, m_ValueParameterDouble);
|
||||
}
|
||||
}
|
||||
|
||||
void Action::Serialize(tinyxml2::XMLElement& action) const {
|
||||
action.SetAttribute("Type", m_Type.c_str());
|
||||
|
||||
if (m_ValueParameterName.empty()) return;
|
||||
|
||||
action.SetAttribute("ValueParameterName", m_ValueParameterName.c_str());
|
||||
|
||||
if (m_ValueParameterName == "Message") {
|
||||
action.SetAttribute("Value", m_ValueParameterString.c_str());
|
||||
} else {
|
||||
action.SetAttribute("Value", m_ValueParameterDouble);
|
||||
}
|
||||
}
|
||||
|
||||
void Action::Deserialize(const tinyxml2::XMLElement& action) {
|
||||
const char* type = nullptr;
|
||||
action.QueryAttribute("Type", &type);
|
||||
if (!type) {
|
||||
LOG("No type found for an action?");
|
||||
return;
|
||||
}
|
||||
|
||||
m_Type = type;
|
||||
|
||||
const char* valueParameterName = nullptr;
|
||||
action.QueryAttribute("ValueParameterName", &valueParameterName);
|
||||
if (valueParameterName) {
|
||||
m_ValueParameterName = valueParameterName;
|
||||
|
||||
if (m_ValueParameterName == "Message") {
|
||||
const char* value = nullptr;
|
||||
action.QueryAttribute("Value", &value);
|
||||
if (value) {
|
||||
m_ValueParameterString = value;
|
||||
} else {
|
||||
LOG("No value found for an action message?");
|
||||
}
|
||||
} else {
|
||||
action.QueryDoubleAttribute("Value", &m_ValueParameterDouble);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLElement;
|
||||
};
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
/**
|
||||
@@ -24,8 +20,6 @@ public:
|
||||
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
|
||||
void Serialize(tinyxml2::XMLElement& action) const;
|
||||
void Deserialize(const tinyxml2::XMLElement& action);
|
||||
private:
|
||||
double m_ValueParameterDouble{ 0.0 };
|
||||
std::string m_Type{ "" };
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "StripUiPosition.h"
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
StripUiPosition::StripUiPosition(const AMFArrayValue& arguments, const std::string& uiKeyName) {
|
||||
const auto* const uiArray = arguments.GetArray(uiKeyName);
|
||||
@@ -22,13 +21,3 @@ void StripUiPosition::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
uiArgs->Insert("x", m_XPosition);
|
||||
uiArgs->Insert("y", m_YPosition);
|
||||
}
|
||||
|
||||
void StripUiPosition::Serialize(tinyxml2::XMLElement& position) const {
|
||||
position.SetAttribute("x", m_XPosition);
|
||||
position.SetAttribute("y", m_YPosition);
|
||||
}
|
||||
|
||||
void StripUiPosition::Deserialize(const tinyxml2::XMLElement& position) {
|
||||
position.QueryDoubleAttribute("x", &m_XPosition);
|
||||
position.QueryDoubleAttribute("y", &m_YPosition);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The position of the first Action in a Strip
|
||||
*
|
||||
@@ -19,8 +15,6 @@ public:
|
||||
[[nodiscard]] double GetX() const noexcept { return m_XPosition; }
|
||||
[[nodiscard]] double GetY() const noexcept { return m_YPosition; }
|
||||
|
||||
void Serialize(tinyxml2::XMLElement& position) const;
|
||||
void Deserialize(const tinyxml2::XMLElement& position);
|
||||
private:
|
||||
double m_XPosition{ 0.0 };
|
||||
double m_YPosition{ 0.0 };
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Amf3.h"
|
||||
#include "BehaviorStates.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
PropertyBehavior::PropertyBehavior() {
|
||||
m_LastEditedState = BehaviorState::HOME_STATE;
|
||||
@@ -125,31 +124,3 @@ void PropertyBehavior::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
|
||||
// TODO Serialize the execution state of the behavior
|
||||
}
|
||||
|
||||
void PropertyBehavior::Serialize(tinyxml2::XMLElement& behavior) const {
|
||||
behavior.SetAttribute("id", m_BehaviorId);
|
||||
behavior.SetAttribute("name", m_Name.c_str());
|
||||
behavior.SetAttribute("isLocked", isLocked);
|
||||
behavior.SetAttribute("isLoot", isLoot);
|
||||
|
||||
for (const auto& [stateId, state] : m_States) {
|
||||
if (state.IsEmpty()) continue;
|
||||
auto* const stateElement = behavior.InsertNewChildElement("State");
|
||||
stateElement->SetAttribute("id", static_cast<uint32_t>(stateId));
|
||||
state.Serialize(*stateElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyBehavior::Deserialize(const tinyxml2::XMLElement& behavior) {
|
||||
m_Name = behavior.Attribute("name");
|
||||
behavior.QueryBoolAttribute("isLocked", &isLocked);
|
||||
behavior.QueryBoolAttribute("isLoot", &isLoot);
|
||||
|
||||
for (const auto* stateElement = behavior.FirstChildElement("State"); stateElement; stateElement = stateElement->NextSiblingElement("State")) {
|
||||
int32_t stateId = -1;
|
||||
stateElement->QueryIntAttribute("id", &stateId);
|
||||
if (stateId < 0 || stateId > 5) continue;
|
||||
m_States[static_cast<BehaviorState>(stateId)].Deserialize(*stateElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
|
||||
#include "State.h"
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
enum class BehaviorState : uint32_t;
|
||||
|
||||
class AMFArrayValue;
|
||||
@@ -29,8 +25,6 @@ public:
|
||||
[[nodiscard]] int32_t GetBehaviorId() const noexcept { return m_BehaviorId; }
|
||||
void SetBehaviorId(int32_t id) noexcept { m_BehaviorId = id; }
|
||||
|
||||
void Serialize(tinyxml2::XMLElement& behavior) const;
|
||||
void Deserialize(const tinyxml2::XMLElement& behavior);
|
||||
private:
|
||||
|
||||
// The states this behavior has.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
template <>
|
||||
void State::HandleMsg(AddStripMessage& msg) {
|
||||
@@ -135,20 +134,4 @@ void State::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
|
||||
strip.SendBehaviorBlocksToClient(*stripArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void State::Serialize(tinyxml2::XMLElement& state) const {
|
||||
for (const auto& strip : m_Strips) {
|
||||
if (strip.IsEmpty()) continue;
|
||||
|
||||
auto* const stripElement = state.InsertNewChildElement("Strip");
|
||||
strip.Serialize(*stripElement);
|
||||
}
|
||||
}
|
||||
|
||||
void State::Deserialize(const tinyxml2::XMLElement& state) {
|
||||
for (const auto* stripElement = state.FirstChildElement("Strip"); stripElement; stripElement = stripElement->NextSiblingElement("Strip")) {
|
||||
auto& strip = m_Strips.emplace_back();
|
||||
strip.Deserialize(*stripElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
|
||||
#include "Strip.h"
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
class State {
|
||||
@@ -17,8 +13,6 @@ public:
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
void Serialize(tinyxml2::XMLElement& state) const;
|
||||
void Deserialize(const tinyxml2::XMLElement& state);
|
||||
private:
|
||||
std::vector<Strip> m_Strips;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "ControlBehaviorMsgs.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
template <>
|
||||
void Strip::HandleMsg(AddStripMessage& msg) {
|
||||
@@ -84,25 +83,4 @@ void Strip::SendBehaviorBlocksToClient(AMFArrayValue& args) const {
|
||||
for (const auto& action : m_Actions) {
|
||||
action.SendBehaviorBlocksToClient(*actions);
|
||||
}
|
||||
}
|
||||
|
||||
void Strip::Serialize(tinyxml2::XMLElement& strip) const {
|
||||
auto* const positionElement = strip.InsertNewChildElement("Position");
|
||||
m_Position.Serialize(*positionElement);
|
||||
for (const auto& action : m_Actions) {
|
||||
auto* const actionElement = strip.InsertNewChildElement("Action");
|
||||
action.Serialize(*actionElement);
|
||||
}
|
||||
}
|
||||
|
||||
void Strip::Deserialize(const tinyxml2::XMLElement& strip) {
|
||||
const auto* positionElement = strip.FirstChildElement("Position");
|
||||
if (positionElement) {
|
||||
m_Position.Deserialize(*positionElement);
|
||||
}
|
||||
|
||||
for (const auto* actionElement = strip.FirstChildElement("Action"); actionElement; actionElement = actionElement->NextSiblingElement("Action")) {
|
||||
auto& action = m_Actions.emplace_back();
|
||||
action.Deserialize(*actionElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace tinyxml2 {
|
||||
class XMLElement;
|
||||
}
|
||||
|
||||
class AMFArrayValue;
|
||||
|
||||
class Strip {
|
||||
@@ -20,8 +16,6 @@ public:
|
||||
void SendBehaviorBlocksToClient(AMFArrayValue& args) const;
|
||||
bool IsEmpty() const noexcept { return m_Actions.empty(); }
|
||||
|
||||
void Serialize(tinyxml2::XMLElement& strip) const;
|
||||
void Deserialize(const tinyxml2::XMLElement& strip);
|
||||
private:
|
||||
std::vector<Action> m_Actions;
|
||||
StripUiPosition m_Position;
|
||||
|
||||
@@ -26,8 +26,7 @@ Precondition::Precondition(const uint32_t condition) {
|
||||
if (result.eof()) {
|
||||
this->type = PreconditionType::ItemEquipped;
|
||||
this->count = 1;
|
||||
this->values.clear();
|
||||
this->values.push_back(0);
|
||||
this->values = { 0 };
|
||||
|
||||
LOG("Failed to find precondition of id (%i)!", condition);
|
||||
|
||||
@@ -139,20 +138,21 @@ bool Precondition::CheckValue(Entity* player, const uint32_t value, bool evaluat
|
||||
case PreconditionType::DoesNotHaveItem:
|
||||
return inventoryComponent->IsEquipped(value) < count;
|
||||
case PreconditionType::HasAchievement:
|
||||
if (missionComponent == nullptr) return false;
|
||||
return missionComponent->GetMissionState(value) >= eMissionState::COMPLETE;
|
||||
mission = missionComponent->GetMission(value);
|
||||
|
||||
return mission == nullptr || mission->GetMissionState() >= eMissionState::COMPLETE;
|
||||
case PreconditionType::MissionAvailable:
|
||||
if (missionComponent == nullptr) return false;
|
||||
return missionComponent->GetMissionState(value) == eMissionState::AVAILABLE || missionComponent->GetMissionState(value) == eMissionState::COMPLETE_AVAILABLE;
|
||||
mission = missionComponent->GetMission(value);
|
||||
|
||||
return mission == nullptr || mission->GetMissionState() >= eMissionState::AVAILABLE;
|
||||
case PreconditionType::OnMission:
|
||||
if (missionComponent == nullptr) return false;
|
||||
return missionComponent->GetMissionState(value) == eMissionState::ACTIVE ||
|
||||
missionComponent->GetMissionState(value) == eMissionState::COMPLETE_ACTIVE ||
|
||||
missionComponent->GetMissionState(value) == eMissionState::READY_TO_COMPLETE ||
|
||||
missionComponent->GetMissionState(value) == eMissionState::COMPLETE_READY_TO_COMPLETE;
|
||||
mission = missionComponent->GetMission(value);
|
||||
|
||||
return mission == nullptr || mission->GetMissionState() >= eMissionState::ACTIVE;
|
||||
case PreconditionType::MissionComplete:
|
||||
if (missionComponent == nullptr) return false;
|
||||
return missionComponent->GetMissionState(value) >= eMissionState::COMPLETE;
|
||||
mission = missionComponent->GetMission(value);
|
||||
|
||||
return mission == nullptr ? false : mission->GetMissionState() >= eMissionState::COMPLETE;
|
||||
case PreconditionType::PetDeployed:
|
||||
return false; // TODO
|
||||
case PreconditionType::HasFlag:
|
||||
|
||||
@@ -31,6 +31,7 @@ void SlashCommandHandler::RegisterCommand(Command command) {
|
||||
}
|
||||
|
||||
for (const auto& alias : command.aliases) {
|
||||
LOG_DEBUG("Registering command %s", alias.c_str());
|
||||
auto [_, success] = RegisteredCommands.try_emplace(alias, command);
|
||||
// Don't allow duplicate commands
|
||||
if (!success) {
|
||||
|
||||
@@ -285,6 +285,7 @@ void ParseXml(const std::string& file) {
|
||||
}
|
||||
|
||||
if (zoneID.value() != currentZoneID) {
|
||||
LOG_DEBUG("Skipping (%s) %i location because it is in %i and not the current zone (%i)", name, lot, zoneID.value(), currentZoneID);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,4 +18,3 @@ target_link_libraries(MasterServer ${COMMON_LIBRARIES} bcrypt dMasterServer dSer
|
||||
if(WIN32)
|
||||
add_dependencies(MasterServer WorldServer AuthServer ChatServer)
|
||||
endif()
|
||||
DoAppleMariaDBCopy(MasterServer ${CMAKE_BINARY_DIR})
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
#include "BitStreamUtils.h"
|
||||
#include "Start.h"
|
||||
#include "Server.h"
|
||||
#include "CDZoneTableTable.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
namespace Game {
|
||||
Logger* logger = nullptr;
|
||||
@@ -188,20 +186,15 @@ int main(int argc, char** argv) {
|
||||
std::cout << "Enter a username: ";
|
||||
std::cin >> username;
|
||||
|
||||
const auto checkIsAdmin = []() {
|
||||
std::string admin;
|
||||
std::cout << "What level of privilege should this account have? Please enter a number between 0 (Player) and 9 (Admin) inclusive. No entry will default to 0." << std::endl;
|
||||
std::cin >> admin;
|
||||
return admin;
|
||||
};
|
||||
|
||||
auto accountId = Database::Get()->GetAccountInfo(username);
|
||||
if (accountId && accountId->id != 0) {
|
||||
if (accountId) {
|
||||
LOG("Account with name \"%s\" already exists", username.c_str());
|
||||
std::cout << "Do you want to change the password of that account? [y/n]?";
|
||||
std::string prompt = "";
|
||||
std::cin >> prompt;
|
||||
if (prompt == "y" || prompt == "yes") {
|
||||
if (accountId->id == 0) return EXIT_FAILURE;
|
||||
|
||||
//Read the password from the console without echoing it.
|
||||
#ifdef __linux__
|
||||
//This function is obsolete, but it only meant to be used by the
|
||||
@@ -226,20 +219,6 @@ int main(int argc, char** argv) {
|
||||
} else {
|
||||
LOG("Account \"%s\" was not updated.", username.c_str());
|
||||
}
|
||||
|
||||
std::cout << "Update admin privileges? [y/n]? ";
|
||||
std::string admin;
|
||||
std::cin >> admin;
|
||||
bool updateAdmin = admin == "y" || admin == "yes";
|
||||
if (updateAdmin) {
|
||||
auto gmLevel = GeneralUtils::TryParse<int32_t>(checkIsAdmin()).value_or(0);
|
||||
if (gmLevel > 9 || gmLevel < 0) {
|
||||
LOG("Invalid admin level. Defaulting to 0");
|
||||
gmLevel = 0;
|
||||
}
|
||||
Database::Get()->UpdateAccountGmLevel(accountId->id, static_cast<eGameMasterLevel>(gmLevel));
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -270,17 +249,6 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
LOG("Account created successfully!");
|
||||
|
||||
accountId = Database::Get()->GetAccountInfo(username);
|
||||
if (accountId) {
|
||||
auto gmLevel = GeneralUtils::TryParse<int32_t>(checkIsAdmin()).value_or(0);
|
||||
if (gmLevel > 9 || gmLevel < 0) {
|
||||
LOG("Invalid admin level. Defaulting to 0");
|
||||
gmLevel = 0;
|
||||
}
|
||||
Database::Get()->UpdateAccountGmLevel(accountId->id, static_cast<eGameMasterLevel>(gmLevel));
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -309,17 +277,6 @@ int main(int argc, char** argv) {
|
||||
PersistentIDManager::Initialize();
|
||||
Game::im = new InstanceManager(Game::logger, Game::server->GetIP());
|
||||
|
||||
//Get CDClient initial information
|
||||
try {
|
||||
CDClientManager::LoadValuesFromDatabase();
|
||||
} catch (CppSQLite3Exception& e) {
|
||||
LOG("Failed to initialize CDServer SQLite Database");
|
||||
LOG("May be caused by corrupted file: %s", (Game::assetManager->GetResPath() / "CDServer.sqlite").string().c_str());
|
||||
LOG("Error: %s", e.errorMessage());
|
||||
LOG("Error Code: %i", e.errorCode());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
//Depending on the config, start up servers:
|
||||
if (Game::config->GetValue("prestart_servers") != "0") {
|
||||
StartChatServer();
|
||||
@@ -589,7 +546,7 @@ void HandlePacket(Packet* packet) {
|
||||
inStream.Read(sessionKey);
|
||||
LUString username;
|
||||
inStream.Read(username);
|
||||
|
||||
|
||||
for (auto it : activeSessions) {
|
||||
if (it.second == username.string) {
|
||||
activeSessions.erase(it.first);
|
||||
|
||||
@@ -359,7 +359,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
//Warning if we ran slow
|
||||
if (deltaTime > currentFrameDelta) {
|
||||
LOG("We're running behind, dT: %f > %i (framerate %i)", deltaTime, currentFrameDelta, currentFramerate);
|
||||
LOG("We're running behind, dT: %f > %f (framerate %i)", deltaTime, currentFrameDelta, currentFramerate);
|
||||
}
|
||||
|
||||
//Check if we're still connected to master:
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
ALTER TABLE behaviors ADD COLUMN character_id BIGINT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE behaviors ADD COLUMN behavior_id BIGINT NOT NULL PRIMARY KEY;
|
||||
ALTER TABLE behaviors DROP COLUMN id;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE behaviors MODIFY behavior_info LONGTEXT DEFAULT NULL;
|
||||
Binary file not shown.
@@ -15,11 +15,6 @@ endif()
|
||||
add_custom_target(conncpp_tests
|
||||
${CMAKE_COMMAND} -E copy $<TARGET_FILE:MariaDB::ConnCpp> ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
|
||||
if(MSVC)
|
||||
add_custom_target(zlib_tests
|
||||
${CMAKE_COMMAND} -E copy $<TARGET_FILE:ZLIB::ZLIB> ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endif()
|
||||
|
||||
# Add the subdirectories
|
||||
add_subdirectory(dCommonTests)
|
||||
add_subdirectory(dGameTests)
|
||||
|
||||
@@ -18,11 +18,18 @@ list(APPEND DCOMMONTEST_SOURCES ${DENUMS_TESTS})
|
||||
# Set our executable
|
||||
add_executable(dCommonTests ${DCOMMONTEST_SOURCES})
|
||||
add_dependencies(dCommonTests conncpp_tests)
|
||||
if(MSVC)
|
||||
add_dependencies(dCommonTests zlib_tests)
|
||||
endif()
|
||||
|
||||
# Apple needs some special linkage for the mariadb connector for tests.
|
||||
DoAppleMariaDBCopy(dCommonTests ${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(APPLE)
|
||||
add_custom_command(TARGET dCommonTests POST_BUILD
|
||||
COMMAND otool ARGS -l dCommonTests
|
||||
COMMAND otool ARGS -L dCommonTests
|
||||
COMMAND ls
|
||||
COMMAND otool ARGS -D libmariadbcpp.dylib
|
||||
COMMAND install_name_tool ARGS -change libmariadbcpp.dylib @rpath/libmariadbcpp.dylib dCommonTests
|
||||
COMMAND otool ARGS -L dCommonTests
|
||||
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endif()
|
||||
|
||||
# Link needed libraries
|
||||
target_link_libraries(dCommonTests ${COMMON_LIBRARIES} GTest::gtest_main)
|
||||
|
||||
@@ -15,7 +15,12 @@ add_executable(dGameTests ${DGAMETEST_SOURCES})
|
||||
add_dependencies(dGameTests conncpp_tests)
|
||||
|
||||
# Apple needs some special linkage for the mariadb connector for tests.
|
||||
DoAppleMariaDBCopy(dGameTests ${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(APPLE)
|
||||
add_custom_command(TARGET dGameTests POST_BUILD
|
||||
COMMAND install_name_tool ARGS -change libmariadbcpp.dylib @rpath/libmariadbcpp.dylib dGameTests
|
||||
COMMAND otool ARGS -L dGameTests
|
||||
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
|
||||
endif()
|
||||
|
||||
target_link_libraries(dGameTests ${COMMON_LIBRARIES} GTest::gtest_main
|
||||
dGame dScripts dPhysics Detour Recast tinyxml2 dWorldServer dZoneManager dChatFilter dNavigation)
|
||||
|
||||
Reference in New Issue
Block a user