mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-26 19:47:16 +00:00
Compare commits
10 Commits
v23.8.0
...
build-analyze
| Author | SHA1 | Date | |
|---|---|---|---|
| 588de15382 | |||
| aeb13e8fd3 | |||
| 98f824b0f5 | |||
| 605e23e8d0 | |||
| fc470d5f83 | |||
| 585ed3bd25 | |||
| 2eb291a461 | |||
| a1421af214 | |||
| 13aad6229f | |||
| 76d46ceaf0 |
+33
-1
@@ -30,6 +30,11 @@ steps:
|
|||||||
- name: cache
|
- name: cache
|
||||||
path: /home/eqemu/.ccache/
|
path: /home/eqemu/.ccache/
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
exclude:
|
||||||
|
- build-analyze
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
@@ -57,6 +62,11 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- .\utils\scripts\build\windows-build.ps1
|
- .\utils\scripts\build\windows-build.ps1
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
exclude:
|
||||||
|
- build-analyze
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
@@ -87,7 +97,10 @@ steps:
|
|||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- master
|
include:
|
||||||
|
- master
|
||||||
|
exclude:
|
||||||
|
- build-analyze
|
||||||
event:
|
event:
|
||||||
- push
|
- push
|
||||||
|
|
||||||
@@ -95,4 +108,23 @@ depends_on:
|
|||||||
- Build Windows
|
- Build Windows
|
||||||
- Build Linux
|
- Build Linux
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: Build Analyze
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Build Linux X64
|
||||||
|
image: akkadius/eqemu-server:v16
|
||||||
|
environment:
|
||||||
|
GITHUB_TOKEN:
|
||||||
|
from_secret: GH_RELEASE_GITHUB_API_TOKEN
|
||||||
|
commands:
|
||||||
|
- ./utils/scripts/build/linux-build-analyze.sh
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- build-analyze
|
||||||
|
event:
|
||||||
|
- push
|
||||||
@@ -1,3 +1,18 @@
|
|||||||
|
## [23.8.1] 6/28/2025
|
||||||
|
|
||||||
|
### Crash Fix
|
||||||
|
|
||||||
|
* Fix Possible Crashes with Raid Methods ([#4955](https://github.com/EQEmu/Server/pull/4955)) @Kinglykrab 2025-06-26
|
||||||
|
|
||||||
|
### Databuckets
|
||||||
|
|
||||||
|
* Revert Caching Changes of #4917 ([#4957](https://github.com/EQEmu/Server/pull/4957)) @Akkadius 2025-06-28
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fix FindCharacter Using content_db ([#4956](https://github.com/EQEmu/Server/pull/4956)) @Kinglykrab 2025-06-26
|
||||||
|
* Fix Hero Forge on Character Select ([#4954](https://github.com/EQEmu/Server/pull/4954)) @Kinglykrab 2025-06-26
|
||||||
|
|
||||||
## [23.8.0] 6/25/2025
|
## [23.8.0] 6/25/2025
|
||||||
|
|
||||||
### API
|
### API
|
||||||
|
|||||||
@@ -363,6 +363,8 @@ MESSAGE(STATUS "**************************************************")
|
|||||||
#setup server libs and headers
|
#setup server libs and headers
|
||||||
SET(SERVER_LIBS common ${DATABASE_LIBRARY_LIBS} ${ZLIB_LIBRARY_LIBS} ${Boost_LIBRARIES} uv_a fmt RecastNavigation::Detour)
|
SET(SERVER_LIBS common ${DATABASE_LIBRARY_LIBS} ${ZLIB_LIBRARY_LIBS} ${Boost_LIBRARIES} uv_a fmt RecastNavigation::Detour)
|
||||||
|
|
||||||
|
set(FMT_HEADER_ONLY OFF)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${DATABASE_LIBRARY_INCLUDE}")
|
INCLUDE_DIRECTORIES(SYSTEM "${DATABASE_LIBRARY_INCLUDE}")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}")
|
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}")
|
||||||
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
|
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
|
||||||
|
|||||||
@@ -841,7 +841,7 @@ IF (UNIX)
|
|||||||
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||||
ENDIF (UNIX)
|
ENDIF (UNIX)
|
||||||
|
|
||||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
IF (EQEMU_BUILD_PCH)
|
||||||
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h)
|
TARGET_PRECOMPILE_HEADERS(common PRIVATE pch/std-pch.h)
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
|
|||||||
+7
-81
@@ -19,37 +19,6 @@ extern WorldDatabase database;
|
|||||||
#error "You must define either ZONE or WORLD"
|
#error "You must define either ZONE or WORLD"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Key: compound cache key (e.g., account_id|character_id|zone_id|instance_id|top_key|full_key)
|
|
||||||
// Value: resolved DataBuckets with extracted nested value
|
|
||||||
static std::unordered_map<std::string, DataBucketsRepository::DataBuckets> g_nested_bucket_cache;
|
|
||||||
|
|
||||||
static std::string MakeNestedCacheKey(const DataBucketKey &k, const std::string &full_key) {
|
|
||||||
return fmt::format(
|
|
||||||
"account_id:{}|character_id:{}|npc_id:{}|bot_id:{}|zone_id:{}|instance_id:{}|top_key:{}|full_key:{}",
|
|
||||||
k.account_id, k.character_id, k.npc_id, k.bot_id, k.zone_id, k.instance_id,
|
|
||||||
Strings::Split(full_key, NESTED_KEY_DELIMITER).front(),
|
|
||||||
full_key
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string MakeNestedCacheKeyPrefix(const DataBucketKey &k, const std::string &top_key) {
|
|
||||||
return fmt::format(
|
|
||||||
"account_id:{}|character_id:{}|npc_id:{}|bot_id:{}|zone_id:{}|instance_id:{}|top_key:{}|",
|
|
||||||
k.account_id, k.character_id, k.npc_id, k.bot_id, k.zone_id, k.instance_id, top_key
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InvalidateNestedCacheForKey(const DataBucketKey &k, const std::string &top_key) {
|
|
||||||
std::string prefix = MakeNestedCacheKeyPrefix(k, top_key);
|
|
||||||
for (auto it = g_nested_bucket_cache.begin(); it != g_nested_bucket_cache.end(); ) {
|
|
||||||
if (it->first.find(prefix) == 0) {
|
|
||||||
it = g_nested_bucket_cache.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
|
void DataBucket::SetData(const std::string &bucket_key, const std::string &bucket_value, std::string expires_time)
|
||||||
{
|
{
|
||||||
auto k = DataBucketKey{
|
auto k = DataBucketKey{
|
||||||
@@ -167,15 +136,6 @@ void DataBucket::SetData(const DataBucketKey &k_)
|
|||||||
// Serialize JSON back to string
|
// Serialize JSON back to string
|
||||||
b.value = json_value.dump();
|
b.value = json_value.dump();
|
||||||
b.key_ = top_key; // Use the top-level key
|
b.key_ = top_key; // Use the top-level key
|
||||||
|
|
||||||
if (CanCache(k_)) {
|
|
||||||
InvalidateNestedCacheForKey(k_, top_key);
|
|
||||||
std::string nested_cache_key = MakeNestedCacheKey(k_, k_.key);
|
|
||||||
auto extracted = ExtractNestedValue(b, k_.key);
|
|
||||||
if (extracted.id > 0) {
|
|
||||||
g_nested_bucket_cache[nested_cache_key] = extracted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bucket_id) {
|
if (bucket_id) {
|
||||||
@@ -291,27 +251,12 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_,
|
|||||||
LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
|
LogDataBuckets("Returning key [{}] value [{}] from cache", e.key_, e.value);
|
||||||
|
|
||||||
if (is_nested_key && !k_.key.empty()) {
|
if (is_nested_key && !k_.key.empty()) {
|
||||||
std::string nested_cache_key = MakeNestedCacheKey(k_, k.key);
|
return ExtractNestedValue(e, k_.key);
|
||||||
|
|
||||||
auto it = g_nested_bucket_cache.find(nested_cache_key);
|
|
||||||
if (it != g_nested_bucket_cache.end()) {
|
|
||||||
LogDataBucketsDetail("Nested cache hit for key [{}]", nested_cache_key);
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto extracted = ExtractNestedValue(e, k_.key);
|
|
||||||
if (extracted.id > 0) {
|
|
||||||
g_nested_bucket_cache[nested_cache_key] = extracted;
|
|
||||||
}
|
|
||||||
return extracted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we can cache its assumed we didn't load this into the cache so we should not return a miss
|
|
||||||
return DataBucketsRepository::NewEntity(); // Not found in cache
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the value from the database
|
// Fetch the value from the database
|
||||||
@@ -370,42 +315,23 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the value to the cache if it doesn't exist
|
// Add the value to the cache if it doesn't exist
|
||||||
// If cacheable and not found in cache, short-circuit and assume it doesn't exist
|
|
||||||
if (can_cache) {
|
if (can_cache) {
|
||||||
bool found_in_cache = false;
|
bool has_cache = false;
|
||||||
for (const auto &e : g_data_bucket_cache) {
|
for (const auto &e : g_data_bucket_cache) {
|
||||||
if (CheckBucketMatch(e, k)) {
|
if (e.id == bucket.id) {
|
||||||
found_in_cache = true;
|
has_cache = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_in_cache) {
|
if (!has_cache) {
|
||||||
LogDataBuckets("Cache miss for key [{}] - skipping DB due to CanCache", k.key);
|
g_data_bucket_cache.emplace_back(bucket);
|
||||||
return DataBucketsRepository::NewEntity();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle nested key extraction
|
// Handle nested key extraction
|
||||||
if (is_nested_key && !k_.key.empty()) {
|
if (is_nested_key && !k_.key.empty()) {
|
||||||
if (CanCache(k_)) {
|
return ExtractNestedValue(bucket, k_.key);
|
||||||
std::string nested_cache_key = MakeNestedCacheKey(k_, k.key);
|
|
||||||
|
|
||||||
auto it = g_nested_bucket_cache.find(nested_cache_key);
|
|
||||||
if (it != g_nested_bucket_cache.end()) {
|
|
||||||
LogDataBucketsDetail("Nested cache hit for key [{}]", nested_cache_key);
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto extracted = ExtractNestedValue(bucket, k_.key);
|
|
||||||
if (extracted.id > 0) {
|
|
||||||
g_nested_bucket_cache[nested_cache_key] = extracted;
|
|
||||||
}
|
|
||||||
return extracted;
|
|
||||||
} else {
|
|
||||||
// Not cacheable, just extract and return
|
|
||||||
return ExtractNestedValue(bucket, k_.key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bucket;
|
return bucket;
|
||||||
|
|||||||
@@ -574,7 +574,7 @@ EQ::ItemInstance* EQ::ItemInstance::GetOrnamentationAugment() const
|
|||||||
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
uint32 EQ::ItemInstance::GetOrnamentHeroModel(int32 material_slot) const
|
||||||
{
|
{
|
||||||
// Not a Hero Forge item.
|
// Not a Hero Forge item.
|
||||||
if (m_ornament_hero_model == 0 || material_slot < 0) {
|
if (m_ornament_hero_model == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-27
@@ -1,34 +1,14 @@
|
|||||||
// types
|
#pragma once
|
||||||
#include <limits>
|
|
||||||
#include <string>
|
|
||||||
#include <cctype>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
// containers
|
// Lightweight, widely used
|
||||||
#include <iterator>
|
#include <string>
|
||||||
#include <set>
|
#include <vector>
|
||||||
#include <unordered_set>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// utilities
|
|
||||||
#include <iostream>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <limits>
|
||||||
#include <algorithm>
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <cassert>
|
||||||
#include <tuple>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
// fmt
|
// fmt
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
// lua
|
|
||||||
#include "lua.hpp"
|
|
||||||
#include <luabind/luabind.hpp>
|
|
||||||
#include <luabind/object.hpp>
|
|
||||||
|
|||||||
@@ -358,6 +358,7 @@ bool RequiresStackCheck(uint16 spell_type) {
|
|||||||
case BotSpellTypes::CompleteHeal:
|
case BotSpellTypes::CompleteHeal:
|
||||||
case BotSpellTypes::PetCompleteHeals:
|
case BotSpellTypes::PetCompleteHeals:
|
||||||
case BotSpellTypes::GroupCompleteHeals:
|
case BotSpellTypes::GroupCompleteHeals:
|
||||||
|
case BotSpellTypes::Resurrect:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// these get injected during the build pipeline
|
||||||
#define CURRENT_VERSION "23.8.0-dev" // always append -dev to the current version for custom-builds
|
#define CURRENT_VERSION "23.8.1-dev" // always append -dev to the current version for custom-builds
|
||||||
#define LOGIN_VERSION "0.8.0"
|
#define LOGIN_VERSION "0.8.0"
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
#define COMPILE_TIME __TIME__
|
#define COMPILE_TIME __TIME__
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "23.8.0",
|
"version": "23.8.1",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
Executable
+44
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
sudo chown eqemu:eqemu /drone/src/ * -R
|
||||||
|
|
||||||
|
# Install ClangBuildAnalyzer if missing
|
||||||
|
if ! command -v clang-build-analyzer &> /dev/null; then
|
||||||
|
echo "Installing latest Clang Build Analyzer..."
|
||||||
|
LATEST_VERSION=$(curl -s https://api.github.com/repos/aras-p/ClangBuildAnalyzer/releases/latest \
|
||||||
|
| grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
|
||||||
|
sudo curl -sSL "https://github.com/aras-p/ClangBuildAnalyzer/releases/download/v${LATEST_VERSION}/ClangBuildAnalyzer-linux" \
|
||||||
|
-o /usr/local/bin/clang-build-analyzer
|
||||||
|
sudo chmod +x /usr/local/bin/clang-build-analyzer
|
||||||
|
fi
|
||||||
|
|
||||||
|
git submodule init && git submodule update
|
||||||
|
perl utils/scripts/build/tag-version.pl
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
|
||||||
|
clang-build-analyzer --start build/
|
||||||
|
|
||||||
|
cd build && \
|
||||||
|
cmake -DEQEMU_BUILD_TESTS=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DEQEMU_BUILD_LUA=ON \
|
||||||
|
-DEQEMU_BUILD_PERL=ON \
|
||||||
|
-DEQEMU_BUILD_LOGIN=ON \
|
||||||
|
-DEQEMU_BUILD_STATIC=ON \
|
||||||
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
|
||||||
|
-DCMAKE_CXX_FLAGS:STRING="-O0 -g -Wno-everything -ftime-trace" \
|
||||||
|
-G 'Unix Makefiles' \
|
||||||
|
.. && \
|
||||||
|
make -j"$(nproc)"
|
||||||
|
|
||||||
|
# 🧠 Generate ClangBuildAnalyzer report
|
||||||
|
clang-build-analyzer --stop ./ /tmp/eqemu.capture
|
||||||
|
clang-build-analyzer --analyze /tmp/eqemu.capture > report.txt
|
||||||
|
cat report.txt
|
||||||
|
|
||||||
|
ldd ./bin/zone
|
||||||
|
|
||||||
|
cd /drone/src/
|
||||||
@@ -76,7 +76,7 @@ ADD_EXECUTABLE(world ${world_sources} ${world_headers})
|
|||||||
|
|
||||||
INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
INSTALL(TARGETS world RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||||
|
|
||||||
IF (WIN32 AND EQEMU_BUILD_PCH)
|
IF (EQEMU_BUILD_PCH)
|
||||||
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/std-pch.h)
|
TARGET_PRECOMPILE_HEADERS(world PRIVATE ../common/pch/std-pch.h)
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
|
|||||||
@@ -483,6 +483,7 @@ INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
|||||||
# precompiled headers
|
# precompiled headers
|
||||||
IF (EQEMU_BUILD_PCH)
|
IF (EQEMU_BUILD_PCH)
|
||||||
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/app-pch.h)
|
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/app-pch.h)
|
||||||
|
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ../common/pch/std-pch.h)
|
||||||
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ./pch/pch.h)
|
TARGET_PRECOMPILE_HEADERS(zone PRIVATE ./pch/pch.h)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
|||||||
@@ -318,32 +318,32 @@ void ZoneCLI::TestDataBuckets(int argc, char** argv, argh::parser& cmd, std::str
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Cold cache test — should return ""
|
// Cold cache test — should return ""
|
||||||
std::string cold_value = client->GetBucket(scoped_key);
|
// std::string cold_value = client->GetBucket(scoped_key);
|
||||||
RunTest("Cold Cache Scoped Key Returns Empty (Due to Skip DB)", "", cold_value);
|
// RunTest("Cold Cache Scoped Key Returns Empty (Due to Skip DB)", "", cold_value);
|
||||||
|
//
|
||||||
// ✅ Reload cache
|
// // ✅ Reload cache
|
||||||
client->LoadDataBucketsCache();
|
// client->LoadDataBucketsCache();
|
||||||
|
//
|
||||||
// Cache should now return the value
|
// // Cache should now return the value
|
||||||
std::string hot_value = client->GetBucket(scoped_key);
|
// std::string hot_value = client->GetBucket(scoped_key);
|
||||||
RunTest("Post-BulkLoad Scoped Key Returns Value", "cached_value", hot_value);
|
// RunTest("Post-BulkLoad Scoped Key Returns Value", "cached_value", hot_value);
|
||||||
|
//
|
||||||
// Also test nested key after preload
|
// // Also test nested key after preload
|
||||||
client->DeleteBucket("ac_nested.test");
|
// client->DeleteBucket("ac_nested.test");
|
||||||
client->SetBucket("ac_nested.test", "nested_val");
|
// client->SetBucket("ac_nested.test", "nested_val");
|
||||||
|
//
|
||||||
// Clear cache, then preload
|
// // Clear cache, then preload
|
||||||
DataBucket::ClearCache();
|
// DataBucket::ClearCache();
|
||||||
client->LoadDataBucketsCache();
|
// client->LoadDataBucketsCache();
|
||||||
|
//
|
||||||
std::string nested_value = client->GetBucket("ac_nested.test");
|
// std::string nested_value = client->GetBucket("ac_nested.test");
|
||||||
RunTest("Post-BulkLoad Nested Scoped Key Returns Value", "nested_val", nested_value);
|
// RunTest("Post-BulkLoad Nested Scoped Key Returns Value", "nested_val", nested_value);
|
||||||
|
//
|
||||||
// Remove and check that cache misses properly again
|
// // Remove and check that cache misses properly again
|
||||||
client->DeleteBucket("ac_nested.test");
|
// client->DeleteBucket("ac_nested.test");
|
||||||
DataBucket::ClearCache();
|
// DataBucket::ClearCache();
|
||||||
std::string post_delete_check = client->GetBucket("ac_nested.test");
|
// std::string post_delete_check = client->GetBucket("ac_nested.test");
|
||||||
RunTest("Post-Delete Nested Scoped Key Returns Empty", "", post_delete_check);
|
// RunTest("Post-Delete Nested Scoped Key Returns Empty", "", post_delete_check);
|
||||||
|
|
||||||
|
|
||||||
std::cout << "\n===========================================\n";
|
std::cout << "\n===========================================\n";
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
void FindCharacter(Client *c, const Seperator *sep)
|
void FindCharacter(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (sep->IsNumber(2)) {
|
if (sep->IsNumber(2)) {
|
||||||
const auto character_id = Strings::ToUnsignedInt(sep->arg[2]);
|
const uint32 character_id = Strings::ToUnsignedInt(sep->arg[2]);
|
||||||
|
|
||||||
const auto& e = CharacterDataRepository::FindOne(content_db, character_id);
|
const auto& e = CharacterDataRepository::FindOne(database, character_id);
|
||||||
if (!e.id) {
|
if (!e.id) {
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
@@ -31,10 +31,10 @@ void FindCharacter(Client *c, const Seperator *sep)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto search_criteria = Strings::ToLower(sep->argplus[2]);
|
const std::string& search_criteria = Strings::ToLower(sep->argplus[2]);
|
||||||
|
|
||||||
const auto& l = CharacterDataRepository::GetWhere(
|
const auto& l = CharacterDataRepository::GetWhere(
|
||||||
content_db,
|
database,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `id` ASC LIMIT 50",
|
"LOWER(`name`) LIKE '%%{}%%' AND `name` NOT LIKE '%-deleted-%' ORDER BY `id` ASC LIMIT 50",
|
||||||
search_criteria
|
search_criteria
|
||||||
@@ -51,7 +51,7 @@ void FindCharacter(Client *c, const Seperator *sep)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto found_count = 0;
|
uint32 found_count = 0;
|
||||||
|
|
||||||
for (const auto& e : l) {
|
for (const auto& e : l) {
|
||||||
c->Message(
|
c->Message(
|
||||||
|
|||||||
+59
-49
@@ -717,7 +717,7 @@ uint32 Raid::GetTotalRaidDamage(Mob* other)
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range)
|
void Raid::HealGroup(uint32 heal_amount, Mob* caster, uint32 group_id, float range)
|
||||||
{
|
{
|
||||||
if (!caster) {
|
if (!caster) {
|
||||||
return;
|
return;
|
||||||
@@ -728,26 +728,30 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range)
|
|||||||
}
|
}
|
||||||
|
|
||||||
float distance;
|
float distance;
|
||||||
float range2 = range*range;
|
float range_squared = range * range;
|
||||||
|
|
||||||
|
int member_count = 0;
|
||||||
|
|
||||||
int numMem = 0;
|
|
||||||
for (const auto& m : members) {
|
for (const auto& m : members) {
|
||||||
if (m.member && m.group_number == gid) {
|
if (m.member && m.group_number == group_id) {
|
||||||
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
||||||
|
|
||||||
if (distance <= range2) {
|
if (distance <= range_squared) {
|
||||||
numMem += 1;
|
member_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heal_amt /= numMem;
|
if (member_count > 0) {
|
||||||
|
heal_amount /= member_count;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& m : members) {
|
for (const auto& m : members) {
|
||||||
if (m.member && m.group_number == gid) {
|
if (m.member && m.group_number == group_id) {
|
||||||
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
||||||
|
|
||||||
if (distance <= range2) {
|
if (distance <= range_squared) {
|
||||||
m.member->SetHP(m.member->GetHP() + heal_amt);
|
m.member->SetHP(m.member->GetHP() + heal_amount);
|
||||||
m.member->SendHPUpdate();
|
m.member->SendHPUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -755,7 +759,7 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Raid::BalanceHP(int32 penalty, uint32 gid, float range, Mob* caster, int32 limit)
|
void Raid::BalanceHP(int32 penalty, uint32 group_id, float range, Mob* caster, int32 limit)
|
||||||
{
|
{
|
||||||
if (!caster) {
|
if (!caster) {
|
||||||
return;
|
return;
|
||||||
@@ -765,44 +769,48 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, float range, Mob* caster, int32
|
|||||||
range = 200;
|
range = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dmgtaken = 0, numMem = 0, dmgtaken_tmp = 0;
|
int damage_taken = 0;
|
||||||
|
int damage_taken_temporary = 0;
|
||||||
|
int member_count = 0;
|
||||||
|
|
||||||
float distance;
|
float distance;
|
||||||
float range2 = range*range;
|
float range_squared = range * range;
|
||||||
|
|
||||||
for (const auto& m : members) {
|
for (const auto& m : members) {
|
||||||
if (m.member && m.group_number == gid) {
|
if (m.member && m.group_number == group_id) {
|
||||||
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
||||||
|
|
||||||
if (distance <= range2) {
|
if (distance <= range_squared) {
|
||||||
dmgtaken_tmp = m.member->GetMaxHP() - m.member->GetHP();
|
damage_taken_temporary = m.member->GetMaxHP() - m.member->GetHP();
|
||||||
|
|
||||||
if (limit && (dmgtaken_tmp > limit)) {
|
if (limit && (damage_taken_temporary > limit)) {
|
||||||
dmgtaken_tmp = limit;
|
damage_taken_temporary = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
dmgtaken += dmgtaken_tmp;
|
damage_taken += damage_taken_temporary;
|
||||||
numMem += 1;
|
member_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dmgtaken += dmgtaken * penalty / 100;
|
damage_taken += damage_taken * penalty / 100;
|
||||||
dmgtaken /= numMem;
|
|
||||||
|
if (member_count > 0) {
|
||||||
|
damage_taken /= member_count;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& m : members) {
|
for (const auto& m : members) {
|
||||||
if (m.member && m.group_number == gid) {
|
if (m.member && m.group_number == group_id) {
|
||||||
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
||||||
|
|
||||||
//this way the ability will never kill someone
|
//this way the ability will never kill someone
|
||||||
//but it will come darn close
|
//but it will come darn close
|
||||||
if (distance <= range2) {
|
if (distance <= range_squared) {
|
||||||
if ((m.member->GetMaxHP() - dmgtaken) < 1) {
|
if ((m.member->GetMaxHP() - damage_taken) < 1) {
|
||||||
m.member->SetHP(1);
|
m.member->SetHP(1);
|
||||||
m.member->SendHPUpdate();
|
m.member->SendHPUpdate();
|
||||||
}
|
} else {
|
||||||
|
m.member->SetHP(m.member->GetMaxHP() - damage_taken);
|
||||||
else {
|
|
||||||
m.member->SetHP(m.member->GetMaxHP() - dmgtaken);
|
|
||||||
m.member->SendHPUpdate();
|
m.member->SendHPUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -810,7 +818,7 @@ void Raid::BalanceHP(int32 penalty, uint32 gid, float range, Mob* caster, int32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int32 limit)
|
void Raid::BalanceMana(int32 penalty, uint32 group_id, float range, Mob* caster, int32 limit)
|
||||||
{
|
{
|
||||||
if (!caster) {
|
if (!caster) {
|
||||||
return;
|
return;
|
||||||
@@ -821,54 +829,56 @@ void Raid::BalanceMana(int32 penalty, uint32 gid, float range, Mob* caster, int3
|
|||||||
}
|
}
|
||||||
|
|
||||||
float distance;
|
float distance;
|
||||||
float range2 = range*range;
|
float range_squared = range * range;
|
||||||
|
|
||||||
int manataken = 0;
|
int mana_taken = 0;
|
||||||
int numMem = 0;
|
int mana_taken_temporary = 0;
|
||||||
int manataken_tmp = 0;
|
int member_count = 0;
|
||||||
|
|
||||||
for (const auto& m : members) {
|
for (const auto& m : members) {
|
||||||
if (m.is_bot) {
|
if (m.is_bot) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.member && m.group_number == gid && m.member->GetMaxMana() > 0) {
|
if (m.member && m.group_number == group_id && m.member->GetMaxMana() > 0) {
|
||||||
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
||||||
|
|
||||||
if (distance <= range2) {
|
if (distance <= range_squared) {
|
||||||
manataken_tmp = m.member->GetMaxMana() - m.member->GetMana();
|
mana_taken_temporary = m.member->GetMaxMana() - m.member->GetMana();
|
||||||
|
|
||||||
if (limit && (manataken_tmp > limit)) {
|
if (limit && (mana_taken_temporary > limit)) {
|
||||||
manataken_tmp = limit;
|
mana_taken_temporary = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
manataken += manataken_tmp;
|
mana_taken += mana_taken_temporary;
|
||||||
numMem += 1;
|
member_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
manataken += manataken * penalty / 100;
|
mana_taken += mana_taken * penalty / 100;
|
||||||
manataken /= numMem;
|
|
||||||
|
if (member_count > 0) {
|
||||||
|
mana_taken /= member_count;
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& m : members) {
|
for (const auto& m : members) {
|
||||||
if (m.is_bot) {
|
if (m.is_bot) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.member && m.group_number == gid) {
|
if (m.member && m.group_number == group_id) {
|
||||||
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
distance = DistanceSquared(caster->GetPosition(), m.member->GetPosition());
|
||||||
|
|
||||||
if (distance <= range2) {
|
if (distance <= range_squared) {
|
||||||
if ((m.member->GetMaxMana() - manataken) < 1) {
|
if ((m.member->GetMaxMana() - mana_taken) < 1) {
|
||||||
m.member->SetMana(1);
|
m.member->SetMana(1);
|
||||||
|
|
||||||
if (m.member->IsClient()) {
|
if (m.member->IsClient()) {
|
||||||
m.member->CastToClient()->SendManaUpdate();
|
m.member->CastToClient()->SendManaUpdate();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
m.member->SetMana(m.member->GetMaxMana() - mana_taken);
|
||||||
m.member->SetMana(m.member->GetMaxMana() - manataken);
|
|
||||||
|
|
||||||
if (m.member->IsClient()) {
|
if (m.member->IsClient()) {
|
||||||
m.member->CastToClient()->SendManaUpdate();
|
m.member->CastToClient()->SendManaUpdate();
|
||||||
|
|||||||
+3
-3
@@ -167,9 +167,9 @@ public:
|
|||||||
void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid);
|
void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid);
|
||||||
void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other);
|
void SplitExp(ExpSource exp_source, const uint64 exp, Mob* other);
|
||||||
uint32 GetTotalRaidDamage(Mob* other);
|
uint32 GetTotalRaidDamage(Mob* other);
|
||||||
void BalanceHP(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0);
|
void BalanceHP(int32 penalty, uint32 group_id, float range = 0, Mob* caster = nullptr, int32 limit = 0);
|
||||||
void BalanceMana(int32 penalty, uint32 gid, float range = 0, Mob* caster = nullptr, int32 limit = 0);
|
void BalanceMana(int32 penalty, uint32 group_id, float range = 0, Mob* caster = nullptr, int32 limit = 0);
|
||||||
void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, float range = 0);
|
void HealGroup(uint32 heal_amount, Mob* caster, uint32 group_id, float range = 0);
|
||||||
void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
|
void SplitMoney(uint32 gid, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
|
||||||
|
|
||||||
void TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading, uint32 gid);
|
void TeleportGroup(Mob* sender, uint32 zoneID, uint16 instance_id, float x, float y, float z, float heading, uint32 gid);
|
||||||
|
|||||||
Reference in New Issue
Block a user