mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
Merge branches 'lsid' and 'master' of https://github.com/EQEmu/Server into lsid
This commit is contained in:
commit
eaf31fb14b
@ -18,6 +18,8 @@
|
||||
#EQEMU_BUILD_CLIENT_FILES
|
||||
#EQEMU_USE_MAP_MMFS
|
||||
#EQEMU_MAP_DIR
|
||||
#EQEMU_ARCH
|
||||
#EQEMU_ARCH_ALT
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
IF(POLICY CMP0074)
|
||||
@ -49,33 +51,37 @@ ENDIF(MSVC OR MINGW)
|
||||
|
||||
IF(MSVC)
|
||||
IF(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x64")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x64")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x64")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/x64/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
SET(EQEMU_ARCH "x64")
|
||||
SET(EQEMU_ARCH_ALT "x64")
|
||||
ELSE(CMAKE_CL_64)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_x86")
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86")
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86")
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
SET(EQEMU_ARCH "x86")
|
||||
SET(EQEMU_ARCH_ALT "Win32")
|
||||
ENDIF(CMAKE_CL_64)
|
||||
|
||||
|
||||
SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_${EQEMU_ARCH}")
|
||||
|
||||
IF(VCPKG_TOOLCHAIN)
|
||||
IF(NOT MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
ENDIF()
|
||||
ELSE(VCPKG_TOOLCHAIN)
|
||||
SET(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/zlib_${EQEMU_ARCH}")
|
||||
SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_${EQEMU_ARCH}")
|
||||
SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_${EQEMU_ARCH}")
|
||||
|
||||
SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include")
|
||||
ENDIF(VCPKG_TOOLCHAIN)
|
||||
|
||||
IF(SODIUM_INCLUDE_HINTS)
|
||||
IF(MSVC_VERSION GREATER 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v140/dynamic")
|
||||
ELSEIF(MSVC_VERSION EQUAL 1800)
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v120/dynamic")
|
||||
ELSE()
|
||||
SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/${EQEMU_ARCH_ALT}/Release/v110/dynamic")
|
||||
ENDIF()
|
||||
ENDIF(SODIUM_INCLUDE_HINTS)
|
||||
|
||||
#disable CRT warnings on windows cause they're annoying as shit and we use C functions everywhere
|
||||
OPTION(EQEMU_DISABLE_CRT_SECURE_WARNINGS "Disable Secure CRT Warnings" ON)
|
||||
IF(EQEMU_DISABLE_CRT_SECURE_WARNINGS)
|
||||
@ -243,6 +249,8 @@ IF(ZLIB_FOUND)
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
|
||||
SET(EQEMU_BUILD_ZLIB ON)
|
||||
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||
ENDIF()
|
||||
|
||||
@ -70,3 +70,9 @@ forum, although pull requests will be much quicker and easier on all parties.
|
||||
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
||||
* CPPUnit - GLP StringUtilities - Apache
|
||||
* LUA - MIT
|
||||
|
||||
## Contributors
|
||||
|
||||
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||
</a>
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 8/6/2019 ==
|
||||
Akkadius: Optimizations to movement updates to eliminate ghosting possibilities in larger zones
|
||||
|
||||
== 7/22/2019 ==
|
||||
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
|
||||
|
||||
== 7/10/2019 ==
|
||||
|
||||
Akkadius: Add #npcedit flymode [0 = ground, 1 = flying, 2 = levitate, 3 = water, 4 = floating]
|
||||
|
||||
@ -77,6 +77,10 @@ namespace EQEmu
|
||||
|
||||
} // namespace invtype
|
||||
|
||||
namespace DevTools {
|
||||
const int32 GM_ACCOUNT_STATUS_LEVEL = 150;
|
||||
}
|
||||
|
||||
namespace popupresponse {
|
||||
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
|
||||
const int32 MOB_INFO_DISMISS = 2000000001;
|
||||
|
||||
@ -1116,7 +1116,10 @@ namespace SoF
|
||||
}
|
||||
OUT(deity);
|
||||
OUT(intoxication);
|
||||
|
||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||
eq->spellSlotRefresh[9] = 0; // 10th slot is not valid in this release
|
||||
|
||||
OUT(abilitySlotRefresh);
|
||||
OUT(points); // Relocation Test
|
||||
// OUT(unknown0166[4]);
|
||||
@ -1177,7 +1180,10 @@ namespace SoF
|
||||
}
|
||||
|
||||
// OUT(unknown4184[128]);
|
||||
|
||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||
eq->mem_spells[9] = 0xFFFFFFFFU; // 10th slot is not valid in this release
|
||||
|
||||
// OUT(unknown04396[32]);
|
||||
OUT(platinum);
|
||||
OUT(gold);
|
||||
|
||||
@ -328,7 +328,11 @@ namespace SoF
|
||||
|
||||
const int SPELL_ID_MAX = 15999;
|
||||
const int SPELLBOOK_SIZE = 480;
|
||||
// Be careful not to confuse these two..SoF disc release has a special requirement...
|
||||
// - The number of available spell gems HAS NOT increased from 9 at this point
|
||||
// - The profile allocation HAS increased to 10 at this point
|
||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||
const int SPELL_GEM_PROFILE_SIZE = 10; // special case declaration
|
||||
|
||||
const int LONG_BUFFS = 25;
|
||||
const int SHORT_BUFFS = 15;
|
||||
|
||||
@ -885,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||
/*00160*/ uint32 deity; // deity
|
||||
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_PROFILE_SIZE]; // Refresh time (millis) - 4 Octets Each
|
||||
/*00208*/ uint32 abilitySlotRefresh;
|
||||
/*00212*/ uint8 haircolor; // Player hair color
|
||||
/*00213*/ uint8 beardcolor; // Player beard color
|
||||
@ -912,7 +912,7 @@ struct PlayerProfile_Struct //23576 Octets
|
||||
/*04173*/ uint8 unknown02264[147]; // was [139]
|
||||
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
|
||||
/*06232*/ uint8 unknown4184[128]; // was [136]
|
||||
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
||||
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_PROFILE_SIZE]; // List of spells memorized
|
||||
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
||||
/*06468*/ uint32 gold; // Gold Pieces on player
|
||||
@ -3768,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct {
|
||||
};
|
||||
|
||||
struct LoadSpellSet_Struct {
|
||||
uint32 spell[spells::SPELL_GEM_COUNT];
|
||||
uint32 spell[spells::SPELL_GEM_PROFILE_SIZE];
|
||||
uint32 unknown;
|
||||
};
|
||||
|
||||
|
||||
@ -240,7 +240,7 @@ RULE_BOOL (World, IPLimitDisconnectAll, false)
|
||||
RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules.
|
||||
RULE_INT (World, TellQueueSize, 20)
|
||||
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind?
|
||||
RULE_BOOL(World, DisallowDuplicateAccountLogins, true)
|
||||
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY(Zone)
|
||||
|
||||
@ -80,6 +80,7 @@
|
||||
#define ServerOP_GroupJoin 0x003e //for joining ooz folks
|
||||
#define ServerOP_UpdateSpawn 0x003f
|
||||
#define ServerOP_SpawnStatusChange 0x0040
|
||||
#define ServerOP_DropClient 0x0041 // DropClient
|
||||
#define ServerOP_ReloadTasks 0x0060
|
||||
#define ServerOP_DepopAllPlayersCorpses 0x0061
|
||||
#define ServerOP_ReloadTitles 0x0062
|
||||
@ -320,11 +321,17 @@ struct ServerZoneIncomingClient_Struct {
|
||||
uint32 accid;
|
||||
int16 admin;
|
||||
uint32 charid;
|
||||
uint32 lsid;
|
||||
bool tellsoff;
|
||||
char charname[64];
|
||||
char lskey[30];
|
||||
};
|
||||
|
||||
struct ServerZoneDropClient_Struct
|
||||
{
|
||||
uint32 lsid;
|
||||
};
|
||||
|
||||
struct ServerChangeWID_Struct {
|
||||
uint32 charid;
|
||||
uint32 newwid;
|
||||
|
||||
@ -379,6 +379,7 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3
|
||||
|
||||
}
|
||||
|
||||
// this function does not delete the ServerPacket, so it must be handled at call site
|
||||
void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||
/*
|
||||
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
|
||||
@ -393,7 +394,6 @@ void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||
Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||
}
|
||||
|
||||
safe_delete(pack);
|
||||
safe_delete_array(queryBuffer);
|
||||
}
|
||||
|
||||
|
||||
@ -470,7 +470,7 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) {
|
||||
Clientlist::Clientlist(int ChatPort) {
|
||||
EQStreamManagerInterfaceOptions chat_opts(ChatPort, false, false);
|
||||
chat_opts.opcode_size = 1;
|
||||
chat_opts.daybreak_options.stale_connection_ms = 300000;
|
||||
chat_opts.daybreak_options.stale_connection_ms = 600000;
|
||||
chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
|
||||
chat_opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
|
||||
chat_opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);
|
||||
|
||||
3
utils/scripts/.gitignore
vendored
3
utils/scripts/.gitignore
vendored
@ -1 +1,2 @@
|
||||
opcode_handlers_output
|
||||
opcode_handlers_output
|
||||
vcxproj_dependencies_output
|
||||
|
||||
@ -1587,22 +1587,24 @@ sub add_login_server_firewall_rules {
|
||||
print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n";
|
||||
print "\n";
|
||||
print "[Install] Instructions \n";
|
||||
print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n";
|
||||
print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.json to your local server similar to the following:\n";
|
||||
print "
|
||||
<loginserver1>
|
||||
<host>login.eqemulator.net</host>
|
||||
<port>5998</port>
|
||||
<account></account>
|
||||
<password></password>
|
||||
</loginserver1>
|
||||
<loginserver2>
|
||||
<host>127.0.0.1</host>
|
||||
<port>5998</port>
|
||||
<account></account>
|
||||
<password></password>
|
||||
</loginserver2>
|
||||
\"loginserver1\" : {
|
||||
\"account\" : \"\",
|
||||
\"host\" : \"login.eqemulator.net\",
|
||||
\"password\" : \"\",
|
||||
\"port\" : \"5998\",
|
||||
\"legacy\": \"1\"
|
||||
},
|
||||
\"loginserver2\" : {
|
||||
\"account\" : \"\",
|
||||
\"host\" : \"192.168.197.129\",
|
||||
\"password\" : \"\",
|
||||
\"port\" : \"5998\"
|
||||
},
|
||||
\"localaddress\" : \"192.168.197.129\",
|
||||
";
|
||||
print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n";
|
||||
print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 192.168.197.129) in the eqhosts.txt file\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
793
utils/scripts/vcxproj_dependencies.py
Normal file
793
utils/scripts/vcxproj_dependencies.py
Normal file
@ -0,0 +1,793 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
|
||||
"""
|
||||
'VCXProj-Dependencies' for EQEmulator
|
||||
|
||||
This script locates external dependency paths and generates lists for each
|
||||
project. In addition, it will cross-check these lists to determine if any
|
||||
discrepancies exist for any dependencies globally and across all projects.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import fnmatch
|
||||
|
||||
try:
|
||||
import xml.etree.cElementTree as ElementTree
|
||||
except ImportError:
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
|
||||
from time import time, ctime
|
||||
|
||||
|
||||
QUIET_REPORT = True
|
||||
|
||||
include_projects = []
|
||||
exclude_projects = ['VCTargetsPath', 'CompilerIdC', 'CompilerIdCXX'] # these three should be left in by default
|
||||
|
||||
base_path = os.getcwd()[:-14] # '/utils/scripts'
|
||||
base_path = base_path.replace('\\', '/')
|
||||
|
||||
file_extensions = ['vcxproj']
|
||||
project_paths = []
|
||||
master_dependencies = []
|
||||
# {[project]:{[build]:{[resource]:{[reference]:[paths]}}}}
|
||||
project_dependencies = {}
|
||||
|
||||
out_files = {}
|
||||
|
||||
col1 = '{0}'.format(' ' * 0)
|
||||
col2 = '{0}'.format(' ' * 2)
|
||||
col3 = '{0}'.format(' ' * 4)
|
||||
col4 = '{0}'.format(' ' * 6)
|
||||
col5 = '{0}'.format(' ' * 8)
|
||||
|
||||
|
||||
def main():
|
||||
""" main """
|
||||
|
||||
if not create_output_directory():
|
||||
exit()
|
||||
|
||||
if not open_output_files():
|
||||
exit()
|
||||
|
||||
print 'Locating project paths...'
|
||||
locate_project_paths()
|
||||
print '..project count: {0}'.format(len(project_paths))
|
||||
print 'Parsing project files...'
|
||||
parse_project_files()
|
||||
print 'Building master dependencies...'
|
||||
build_master_dependencies()
|
||||
print '..dependency count: {0}'.format(len(master_dependencies))
|
||||
print 'Checking for version discrepancies...'
|
||||
check_for_version_discrepancies()
|
||||
close_output_files()
|
||||
print '\n__fin__'
|
||||
|
||||
return
|
||||
|
||||
|
||||
def create_output_directory():
|
||||
""" Check for output directory - create if does not exist """
|
||||
|
||||
try:
|
||||
output_path = '{0}/utils/scripts/vcxproj_dependencies_output'.format(base_path)
|
||||
if not os.path.exists(output_path):
|
||||
os.mkdir(output_path)
|
||||
|
||||
return True
|
||||
|
||||
except IOError:
|
||||
print('(Exception Error: {0}) create_output_directory()'.format(sys.exc_info()[0]))
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def open_output_files():
|
||||
""" Open all output files """
|
||||
|
||||
try:
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ProjectPaths.txt'.format(base_path)
|
||||
out_files['ProjectPaths'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/MasterDependencies.txt'.format(base_path)
|
||||
out_files['MasterDependencies'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ProjectDependencies.txt'.format(base_path)
|
||||
out_files['ProjectDependencies'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ContextTree.txt'.format(base_path)
|
||||
out_files['ContextTree'] = open(file_name, 'w')
|
||||
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/DiscrepancyReport.txt'.format(base_path)
|
||||
out_files['DiscrepancyReport'] = open(file_name, 'w')
|
||||
for file in out_files:
|
||||
out_files[file].write('>> \'VCXProj-Dependencies\' {0} file\n'.format(file))
|
||||
out_files[file].write('>> file generated @ {0}\n\n'.format(ctime(time())))
|
||||
|
||||
return True
|
||||
|
||||
except IOError:
|
||||
print('(Exception Error: {0}) open_output_files()'.format(sys.exc_info()[0]))
|
||||
close_output_files()
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def locate_project_paths():
|
||||
""" Locate vcxproj files in the build folder """
|
||||
|
||||
for root, dirs, files in os.walk('{0}/build'.format(base_path)):
|
||||
for name in files:
|
||||
project = name.split('.')[0]
|
||||
if not len(include_projects) == 0 and project not in include_projects:
|
||||
continue
|
||||
if not len(exclude_projects) == 0 and project in exclude_projects:
|
||||
continue
|
||||
for extension in file_extensions:
|
||||
if fnmatch.fnmatch(name, '*.{0}'.format(extension)):
|
||||
project_paths.append(os.path.join(root, name).replace('\\', '/').lower())
|
||||
for path in project_paths:
|
||||
out_files['ProjectPaths'].write('{0};\n'.format(path))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def fixup_path(project_path, dependency_path):
|
||||
""" Fix-up malformed dependency paths """
|
||||
|
||||
trailing = dependency_path.replace('\\', '/')
|
||||
if '../' in trailing:
|
||||
if trailing[:3] == '../': # windows
|
||||
leading = project_path[:project_path.rfind('/')]
|
||||
while trailing[:3] == '../':
|
||||
leading = leading[:leading.rfind('/')]
|
||||
trailing = trailing[3:]
|
||||
trailing = trailing.lower()
|
||||
trailing = '{0}/{1}'.format(leading, trailing)
|
||||
else: # unix
|
||||
print '..processing unix-style path fix-up'
|
||||
while '../' in trailing:
|
||||
backout = trailing.find('../')
|
||||
backdir = trailing.rfind('/', 0, backout - 1)
|
||||
trailing = trailing.replace(trailing[backdir:backout + 2], '', 1)
|
||||
trailing = trailing.lower()
|
||||
else:
|
||||
trailing = trailing.lower()
|
||||
|
||||
return trailing
|
||||
|
||||
|
||||
def parse_project_files():
|
||||
""" Parse each vcxproj file's xml data """
|
||||
|
||||
for key1 in project_paths:
|
||||
with open(key1, 'r') as vcxproj_file:
|
||||
project_dependencies[key1] = {}
|
||||
xml_tree = ElementTree.ElementTree(file=vcxproj_file)
|
||||
for element1 in xml_tree.getroot():
|
||||
if not element1.tag[-19:] == 'ItemDefinitionGroup':
|
||||
continue
|
||||
# add '.split('|')[0]' to remove the '|Win##' attribute
|
||||
key2 = element1.attrib['Condition'].split('==')[1][1:-1]
|
||||
project_dependencies[key1][key2] = {}
|
||||
for element2 in element1.getiterator():
|
||||
if element2.tag[-9:] == 'ClCompile':
|
||||
key3 = element2.tag[-9:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
elif element2.tag[-15:] == 'ResourceCompile':
|
||||
key3 = element2.tag[-15:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
elif element2.tag[-4:] == 'Midl':
|
||||
key3 = element2.tag[-4:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
elif element2.tag[-4:] == 'Link':
|
||||
key3 = element2.tag[-4:]
|
||||
project_dependencies[key1][key2][key3] = {}
|
||||
for element3 in element2.getiterator():
|
||||
if element3.tag[-22:] == 'AdditionalDependencies':
|
||||
key4 = element3.tag[-22:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
if element3.tag[-28:] == 'AdditionalLibraryDirectories':
|
||||
key4 = element3.tag[-28:]
|
||||
project_dependencies[key1][key2][key3][key4] = []
|
||||
paths = element3.text.split(';')
|
||||
for path in paths:
|
||||
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
|
||||
vcxproj_file.close()
|
||||
|
||||
return
|
||||
|
||||
|
||||
def build_master_dependencies():
|
||||
""" Build master dependencies list """
|
||||
|
||||
def write(message):
|
||||
""" internal 'ProjectDependencies' write method - performed here so processing takes place after fix-up """
|
||||
|
||||
out_files['ProjectDependencies'].write('{0}\n'.format(message))
|
||||
|
||||
return
|
||||
|
||||
for key1 in project_dependencies:
|
||||
write('{0}<Project Path="{1}">'.format(col1, key1))
|
||||
for key2 in project_dependencies[key1]:
|
||||
write('{0}<Build Type="{1}">'.format(col2, key2))
|
||||
for key3 in project_dependencies[key1][key2]:
|
||||
write('{0}<Resource Type="{1}">'.format(col3, key3))
|
||||
for key4 in project_dependencies[key1][key2][key3]:
|
||||
write('{0}<Reference Type="{1}">'.format(col4, key4))
|
||||
for path in project_dependencies[key1][key2][key3][key4]:
|
||||
write('{0}{1}'.format(col4, path))
|
||||
if path not in master_dependencies:
|
||||
master_dependencies.append(path)
|
||||
write('{0}</Reference>'.format(col4))
|
||||
write('{0}</Resource>'.format(col3))
|
||||
write('{0}</Build>'.format(col2))
|
||||
write('{0}</Project>'.format(col1))
|
||||
master_dependencies.sort()
|
||||
for path in master_dependencies:
|
||||
out_files['MasterDependencies'].write('{0}\n'.format(path))
|
||||
|
||||
return
|
||||
|
||||
|
||||
def check_for_version_discrepancies():
|
||||
""" Check for dependency version discrepancies """
|
||||
|
||||
def twrite(message):
|
||||
""" internal 'ContextTree' write method """
|
||||
|
||||
out_files['ContextTree'].write('{0}\n'.format(message))
|
||||
|
||||
return
|
||||
|
||||
def rwrite(message):
|
||||
""" internal 'DiscrepancyReport' write method """
|
||||
|
||||
out_files['DiscrepancyReport'].write('{0}\n'.format(message))
|
||||
|
||||
return
|
||||
|
||||
libraries = [
|
||||
'mysql',
|
||||
'zlib',
|
||||
'perl',
|
||||
'lua',
|
||||
'boost',
|
||||
'sodium',
|
||||
'openssl'
|
||||
]
|
||||
references = [
|
||||
'include',
|
||||
'source',
|
||||
'library'
|
||||
]
|
||||
priorities = {
|
||||
0: 'NOT FOUND',
|
||||
1: 'install',
|
||||
2: 'dependencies',
|
||||
3: 'libs',
|
||||
4: 'vcpkg',
|
||||
5: 'static',
|
||||
6: 'submodule'
|
||||
}
|
||||
# use all lowercase for path description
|
||||
# use forward slash ('/') for directory name separators
|
||||
# use '|' token for multiple hints ('my_file_path_1|my_file_path_2')
|
||||
# use '!!' token for explicit argument ('/perl/core!!' will find '../perl/core' but not '../perl/core/perl512.lib')
|
||||
# use '##' token for joined hints ('my_file_##_1')
|
||||
# use '&&', '^' and '@' tokens for multiple argument hints ('my_file_&&path_1^path_2^path_3@')
|
||||
# (i.e., 'my_file_path_1|my_file_##_2|my_##_##&&_3^_4!!@')
|
||||
# {[library]:{[reference]:[[priority]:hint]}}
|
||||
hints = {
|
||||
# Notes:
|
||||
'mysql': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/dependencies/mysql_##/include', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'dependencies/mysql_##/lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'zlib': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/zlib_x##/include', # 'dependencies'
|
||||
# not sure if this should be '/libs/zlibng' or '/build/libs/zlibng' based on cmake behavior
|
||||
'/server/build/libs/zlibng!!', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'/server/build/libs/zlibng!!', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'/server/libs/zlibng!!', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/zlib_x##/lib/zdll.lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/zlib.lib!!'
|
||||
'^debug/lib/zlibd.lib!!@', # 'vcpkg'
|
||||
'/server/build/libs/zlibng/&&debug/zlibstaticd.lib!!^minsizerel/zlibstatic.lib!!'
|
||||
'^release/zlibstatic.lib!!^relwithdebinfo/zlibstatic.lib!!@', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'perl': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'/perl/lib/core!!', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'/perl/lib/core/perl51##.lib', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'lua': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/luaj_x##/src', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/luaj_x##/src', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/luaj_x##/bin/lua51.lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
# debug lua package likely incorrect..should be 'lua51d.lib' - or whatever debug version is
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/lua51.lib!!'
|
||||
'^debug/lib/lua51.lib!!@', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'boost': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/boost', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/boost', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/lib!!', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'sodium': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/libsodium/include', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/libsodium/##/dynamic/libsodium.lib', # 'dependencies'
|
||||
'', # 'libs'
|
||||
# debug libsodium package likely incorrect..should be 'libsodiumd.lib' - or whatever debug version is
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/libsodium.lib!!^'
|
||||
'debug/lib/libsodium.lib!!@', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
},
|
||||
'openssl': {
|
||||
'include': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/openssl_x##/include', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'source': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'', # 'dependencies'
|
||||
'', # 'libs'
|
||||
'', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
],
|
||||
'library': [
|
||||
'', # 'NOT FOUND'
|
||||
'', # 'install'
|
||||
'/server/dependencies/openssl_x##/lib/VC/&&libeay32MD.lib!!^libeay32MDd.lib!!^'
|
||||
'ssleay32MD.lib!!^ssleay32MDd.lib!!@', # 'dependencies'
|
||||
'', # 'libs'
|
||||
# debug openssl package likely incorrect..should be
|
||||
# 'libeay32d.lib' and 'ssleay32d.lib' - or whatever debug versions are
|
||||
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/libeay32.lib!!^'
|
||||
'lib/ssleay32.lib!!^debug/lib/libeay32.lib!!^debug/lib/ssleay32.lib!!@', # 'vcpkg'
|
||||
'', # 'static'
|
||||
'' # 'submodule'
|
||||
]
|
||||
}
|
||||
}
|
||||
# {[project]:{[build]:{[resource]:{[library]:{[reference]:priority}}}}}
|
||||
context_tree = {}
|
||||
# {[library]:priority}
|
||||
global_priorities = {}
|
||||
# {[build]:{[library]:priority}}
|
||||
build_priorities = {}
|
||||
# loop for discovering first occurence dependency sources (assumes same search precedence as compiler includes)
|
||||
for project in project_dependencies:
|
||||
if project not in context_tree.keys():
|
||||
context_tree[project] = {}
|
||||
for build in project_dependencies[project]:
|
||||
if build not in context_tree[project].keys():
|
||||
context_tree[project][build] = {}
|
||||
if build not in build_priorities.keys():
|
||||
build_priorities[build] = {}
|
||||
for resource in project_dependencies[project][build]:
|
||||
if resource not in context_tree[project][build].keys():
|
||||
context_tree[project][build][resource] = {}
|
||||
for reference_project in project_dependencies[project][build][resource]:
|
||||
for path in project_dependencies[project][build][resource][reference_project]:
|
||||
for library in libraries:
|
||||
if library not in context_tree[project][build][resource].keys():
|
||||
context_tree[project][build][resource][library] = {}
|
||||
if library not in build_priorities[build].keys():
|
||||
build_priorities[build][library] = 0
|
||||
if library not in global_priorities.keys():
|
||||
global_priorities[library] = 0
|
||||
for reference in references:
|
||||
if reference not in context_tree[project][build][resource][library].keys():
|
||||
context_tree[project][build][resource][library][reference] = 0
|
||||
elif not context_tree[project][build][resource][library][reference] == 0:
|
||||
continue
|
||||
for priority in priorities:
|
||||
if hints[library][reference][priority] == '':
|
||||
continue
|
||||
hint_found = False
|
||||
for hint in hints[library][reference][priority].split('|'):
|
||||
if not find_hint_in_path(hint, path) == -1:
|
||||
context_tree[project][build][resource][library][reference] = priority
|
||||
if context_tree[project][build][resource][library][reference] >\
|
||||
build_priorities[build][library]:
|
||||
build_priorities[build][library] =\
|
||||
context_tree[project][build][resource][library][reference]
|
||||
if context_tree[project][build][resource][library][reference] >\
|
||||
global_priorities[library]:
|
||||
global_priorities[library] =\
|
||||
context_tree[project][build][resource][library][reference]
|
||||
hint_found = True
|
||||
break
|
||||
if hint_found is True:
|
||||
break
|
||||
# loop for hack to fix odd behavior caused by 'FindZLIB.cmake' - ref: '../server/build/libs/zlibng/zconf.h'
|
||||
# this does not change anything in the build files..only silences a false discrepancy due to mixing priority types
|
||||
if global_priorities['zlib'] == 5:
|
||||
for project in context_tree:
|
||||
for build in context_tree[project]:
|
||||
for resource in context_tree[project][build]:
|
||||
if context_tree[project][build][resource]['zlib']['source'] == 3:
|
||||
context_tree[project][build][resource]['zlib']['source'] = 5
|
||||
if context_tree[project][build][resource]['zlib']['include'] == 3:
|
||||
context_tree[project][build][resource]['zlib']['include'] = 5
|
||||
# loop for dumping 'global_priorities'
|
||||
twrite('{0}<Global>'.format(col1))
|
||||
for library in libraries:
|
||||
twrite('{0}<Library Name="{1}">{2}</Library>'.format(col2, library, global_priorities[library]))
|
||||
twrite('{0}</Global>'.format(col1))
|
||||
twrite('')
|
||||
# loop for dumping 'build_priorities'
|
||||
for build in build_priorities:
|
||||
twrite('{0}<Build Type="{1}">'.format(col1, build))
|
||||
for library in libraries:
|
||||
twrite('{0}<Library Name="{1}">{2}</Library>'.format(col2, library, build_priorities[build][library]))
|
||||
twrite('{0}</Build>'.format(col1))
|
||||
twrite('')
|
||||
# loop for dumping 'context_tree'
|
||||
for project in context_tree:
|
||||
twrite('{0}<Project Path="{1}">'.format(col1, project))
|
||||
for build in context_tree[project]:
|
||||
twrite('{0}<Built Type="{1}">'.format(col2, build))
|
||||
for resource in context_tree[project][build]:
|
||||
twrite('{0}<Resource Name="{1}">'.format(col3, resource))
|
||||
for library in context_tree[project][build][resource]:
|
||||
twrite('{0}<Library Name="{1}">'.format(col4, library))
|
||||
for reference in context_tree[project][build][resource][library]:
|
||||
twrite(
|
||||
'{0}<Reference Name="{1}">{2}</Reference>'.format(
|
||||
col5,
|
||||
reference,
|
||||
context_tree[project][build][resource][library][reference]
|
||||
)
|
||||
)
|
||||
twrite('{0}</Library>'.format(col4))
|
||||
twrite('{0}</Resource>'.format(col3))
|
||||
twrite('{0}</Build>'.format(col2))
|
||||
twrite('{0}</Project>'.format(col1))
|
||||
if QUIET_REPORT is False:
|
||||
for library in libraries:
|
||||
rwrite(
|
||||
'> Global Library \'{0}\' status: \'{1}\' ({2})'.format(
|
||||
library,
|
||||
priorities[global_priorities[library]],
|
||||
global_priorities[library]
|
||||
)
|
||||
)
|
||||
# loop for identifying dependency discrepancies
|
||||
for project in context_tree:
|
||||
for build in context_tree[project]:
|
||||
for resource in context_tree[project][build]:
|
||||
for library in context_tree[project][build][resource]:
|
||||
if global_priorities[library] == 0:
|
||||
if QUIET_REPORT is False:
|
||||
rwrite(
|
||||
'> No Global Library \'{0}\' .. skipping Project:Build:Resource'
|
||||
' "{1}":"{2}":"{3}"'.format(
|
||||
library,
|
||||
project,
|
||||
build,
|
||||
resource
|
||||
)
|
||||
)
|
||||
continue
|
||||
if build_priorities[build][library] == 0:
|
||||
if QUIET_REPORT is False:
|
||||
rwrite(
|
||||
'> No Build Library \'{0}\' .. skipping Project:Build:Resource'
|
||||
' "{1}":"{2}":"{3}"'.format(
|
||||
library,
|
||||
project,
|
||||
build,
|
||||
resource
|
||||
)
|
||||
)
|
||||
continue
|
||||
for reference in context_tree[project][build][resource][library]:
|
||||
if context_tree[project][build][resource][library][reference] == 0:
|
||||
continue
|
||||
if not global_priorities[library] == context_tree[project][build][resource][library][reference]:
|
||||
rwrite(
|
||||
'> Global-Project Library \'{0}\' mis-match \'{1}!={2}\''
|
||||
' ({3}!={4}) Project:Build:Resource "{5}":"{6}":"{7}"'.format(
|
||||
library,
|
||||
priorities[global_priorities[library]],
|
||||
priorities[context_tree[project][build][resource][library][reference]],
|
||||
global_priorities[library],
|
||||
context_tree[project][build][resource][library][reference],
|
||||
project,
|
||||
build,
|
||||
resource
|
||||
)
|
||||
)
|
||||
# 'builds' are allowed to have different dependencies..so, we'll start crossing at 'resource'
|
||||
for cross_resource in context_tree[project][build]:
|
||||
for cross_reference in context_tree[project][build][cross_resource][library]:
|
||||
if cross_resource == resource and cross_reference == reference:
|
||||
continue
|
||||
if context_tree[project][build][cross_resource][library][cross_reference] == 0:
|
||||
continue
|
||||
if QUIET_REPORT is False and\
|
||||
not context_tree[project][build][cross_resource][library][cross_reference] ==\
|
||||
context_tree[project][build][resource][library][reference]:
|
||||
rwrite(
|
||||
'> Project Library \'{0}\' mis-match \'{1}:{2}:{3}!={4}:{5}:{6}\''
|
||||
' ({7}!={8}) Project:Build "{9}":"{10}"'.format(
|
||||
library,
|
||||
resource,
|
||||
reference,
|
||||
priorities[context_tree[project][build][resource][library][reference]],
|
||||
cross_resource,
|
||||
cross_reference,
|
||||
priorities[context_tree[project][build][cross_resource][library]
|
||||
[cross_reference]],
|
||||
context_tree[project][build][resource][library][reference],
|
||||
context_tree[project][build][cross_resource][library][cross_reference],
|
||||
project,
|
||||
build
|
||||
)
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def find_hint_in_path(hint, path):
|
||||
"""
|
||||
Helper function for parsing and checking for hints in paths
|
||||
|
||||
Hints strings should be split ('|') and passed as a singular hint into this function
|
||||
|
||||
"""
|
||||
|
||||
if hint == '' or path == '':
|
||||
return -1
|
||||
|
||||
joined_index = hint.find('##')
|
||||
pretext_index = hint.find('&&')
|
||||
if joined_index == -1 and pretext_index == -1:
|
||||
if '^' in hint or '@' in hint:
|
||||
print '..malformed or improper handling of hint: \'{0}\' path: \'{1}\''.format(hint, path)
|
||||
|
||||
return -1
|
||||
|
||||
explicit_index = hint.find('!!')
|
||||
if explicit_index == -1:
|
||||
return path.find(hint)
|
||||
|
||||
else:
|
||||
explicit_hint = hint[:explicit_index]
|
||||
found_index = path.find(explicit_hint)
|
||||
if (len(explicit_hint) + found_index) == len(path):
|
||||
return found_index
|
||||
|
||||
else:
|
||||
return -1
|
||||
|
||||
elif (not joined_index == -1 and pretext_index == -1) or\
|
||||
(not joined_index == -1 and not pretext_index == -1 and joined_index < pretext_index):
|
||||
start_index = 0
|
||||
for partial_hint in hint.split('##', 1):
|
||||
if partial_hint == '':
|
||||
continue
|
||||
found_index = find_hint_in_path(partial_hint, path[start_index:])
|
||||
if found_index == -1:
|
||||
return found_index
|
||||
|
||||
start_index = found_index + len(partial_hint)
|
||||
|
||||
return start_index
|
||||
|
||||
elif (joined_index == -1 and not pretext_index == -1) or\
|
||||
(not joined_index == -1 and not pretext_index == -1 and joined_index > pretext_index):
|
||||
pretext_hints = hint.split('&&', 1)
|
||||
found_index = 0
|
||||
if not pretext_hints[0] == '':
|
||||
found_index = find_hint_in_path(pretext_hints[0], path)
|
||||
if found_index == -1:
|
||||
return found_index
|
||||
|
||||
start_index = found_index + len(pretext_hints[0])
|
||||
partial_hints = pretext_hints[1].split('@', 1)
|
||||
for partial_hint in partial_hints:
|
||||
if partial_hint == '':
|
||||
continue
|
||||
for alt_hint in partial_hint.split('^'):
|
||||
if alt_hint == '':
|
||||
continue
|
||||
found_index = find_hint_in_path(alt_hint, path[start_index:])
|
||||
if found_index == 0:
|
||||
if not partial_hints[1] == '':
|
||||
print '..unhandled hint method: \'{0}\''.format(partial_hints[1])
|
||||
else:
|
||||
return found_index
|
||||
|
||||
return -1
|
||||
|
||||
else:
|
||||
return -1
|
||||
|
||||
|
||||
def close_output_files():
|
||||
""" Close all output files """
|
||||
|
||||
while not len(out_files) == 0:
|
||||
key = out_files.keys()[0]
|
||||
out_files[key].close()
|
||||
del out_files[key]
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -393,7 +393,7 @@
|
||||
9137|2018_12_12_client_faction_tables.sql|SHOW TABLES LIKE 'faction_base_data'|empty|
|
||||
9138|2018_12_12_convert_to_client_functions.sql|SELECT `id` FROM `faction_list` WHERE `id` > 4999|empty|
|
||||
9139|2019_03_25_optional_npc_model.sql|SHOW COLUMNS FROM `npc_types` LIKE 'model'|empty|
|
||||
9140|2019_07_03_update_range.sql|SHOW COLUMNS FROM `npc_types` LIKE 'max_movement_update_range'|empty|
|
||||
9140|2019_07_03_update_range.sql|SHOW COLUMNS FROM `zone` LIKE 'max_movement_update_range'|empty|
|
||||
9141|2019_07_10_npc_flymode.sql|SHOW COLUMNS FROM `npc_types` LIKE 'flymode'|empty|
|
||||
|
||||
# Upgrade conditions:
|
||||
|
||||
@ -287,7 +287,7 @@ void Adventure::Finished(AdventureWinStatus ws)
|
||||
ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
|
||||
if(current)
|
||||
{
|
||||
if(current->Online() == CLE_Status_InZone)
|
||||
if(current->Online() == CLE_Status::InZone)
|
||||
{
|
||||
//We can send our packets only.
|
||||
auto pack =
|
||||
|
||||
@ -88,7 +88,6 @@ extern volatile bool UCSServerAvailable_;
|
||||
|
||||
Client::Client(EQStreamInterface* ieqs)
|
||||
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
|
||||
CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)),
|
||||
connect(1000),
|
||||
eqs(ieqs)
|
||||
{
|
||||
@ -105,6 +104,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
char_name[0] = 0;
|
||||
charid = 0;
|
||||
zone_waiting_for_bootup = 0;
|
||||
enter_world_triggered = false;
|
||||
StartInTutorial = false;
|
||||
|
||||
m_ClientVersion = eqs->ClientVersion();
|
||||
@ -115,7 +115,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
|
||||
Client::~Client() {
|
||||
if (RunLoops && cle && zone_id == 0)
|
||||
cle->SetOnline(CLE_Status_Offline);
|
||||
cle->SetOnline(CLE_Status::Offline);
|
||||
|
||||
numclients--;
|
||||
|
||||
@ -185,7 +185,7 @@ void Client::SendExpansionInfo() {
|
||||
|
||||
void Client::SendCharInfo() {
|
||||
if (cle) {
|
||||
cle->SetOnline(CLE_Status_CharSelect);
|
||||
cle->SetOnline(CLE_Status::CharSelect);
|
||||
}
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater) {
|
||||
@ -428,7 +428,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app)
|
||||
// Track who is in and who is out of the game
|
||||
char *inout= (char *) "";
|
||||
|
||||
if (cle->GetOnline() == CLE_Status_Never) {
|
||||
if (cle->GetOnline() == CLE_Status::Never){
|
||||
// Desktop -> Char Select
|
||||
inout = (char *) "In";
|
||||
}
|
||||
@ -441,7 +441,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app)
|
||||
// Either from a fresh client launch or coming back from the game.
|
||||
// Exiting the game entirely does not come through here.
|
||||
// Could use a Logging Out Completely message somewhere.
|
||||
cle->SetOnline(CLE_Status_CharSelect);
|
||||
cle->SetOnline(CLE_Status::CharSelect);
|
||||
|
||||
Log(Logs::General, Logs::World_Server,
|
||||
"Account (%s) Logging(%s) to character select :: LSID: %d ",
|
||||
@ -1038,7 +1038,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
|
||||
{
|
||||
// I don't see this getting executed on logout
|
||||
eqs->Close();
|
||||
cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction.
|
||||
cle->SetOnline(CLE_Status::Offline); //allows this player to log in again without an ip restriction.
|
||||
return false;
|
||||
}
|
||||
case OP_ZoneChange:
|
||||
@ -1081,15 +1081,15 @@ bool Client::Process() {
|
||||
Log(Logs::General, Logs::World_Server, "Zone bootup timer expired, bootup failed or too slow.");
|
||||
TellClientZoneUnavailable();
|
||||
}
|
||||
|
||||
if(connect.Check()){
|
||||
SendGuildList();// Send OPCode: OP_GuildsList
|
||||
SendApproveWorld();
|
||||
connect.Disable();
|
||||
}
|
||||
if (CLE_keepalive_timer.Check()) {
|
||||
if (cle)
|
||||
cle->KeepAlive();
|
||||
}
|
||||
|
||||
if (cle)
|
||||
cle->KeepAlive();
|
||||
|
||||
/************ Get all packets from packet manager out queue and process them ************/
|
||||
EQApplicationPacket *app = 0;
|
||||
@ -1153,11 +1153,18 @@ void Client::EnterWorld(bool TryBootup) {
|
||||
else
|
||||
zone_server = zoneserver_list.FindByZoneID(zone_id);
|
||||
|
||||
|
||||
const char *zone_name = database.GetZoneName(zone_id, true);
|
||||
if (zone_server) {
|
||||
// warn the world we're comming, so it knows not to shutdown
|
||||
zone_server->IncomingClient(this);
|
||||
if (false == enter_world_triggered) {
|
||||
//Drop any clients we own in other zones.
|
||||
zoneserver_list.DropClient(GetLSID(), zone_server);
|
||||
|
||||
// warn the zone we're coming
|
||||
zone_server->IncomingClient(this);
|
||||
|
||||
//tell the server not to trigger this multiple times before we get a zone unavailable
|
||||
enter_world_triggered = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (TryBootup) {
|
||||
@ -1176,9 +1183,17 @@ void Client::EnterWorld(bool TryBootup) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
zone_waiting_for_bootup = 0;
|
||||
|
||||
if(!cle) {
|
||||
if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) {
|
||||
Log(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked.");
|
||||
TellClientZoneUnavailable();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cle) {
|
||||
TellClientZoneUnavailable();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1195,12 +1210,6 @@ void Client::EnterWorld(bool TryBootup) {
|
||||
);
|
||||
|
||||
if (seen_character_select) {
|
||||
if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) {
|
||||
Log(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked.");
|
||||
TellClientZoneUnavailable();
|
||||
return;
|
||||
}
|
||||
|
||||
auto pack = new ServerPacket;
|
||||
pack->opcode = ServerOP_AcceptWorldEntrance;
|
||||
pack->size = sizeof(WorldToZone_Struct);
|
||||
@ -1306,7 +1315,7 @@ void Client::Clearance(int8 response)
|
||||
safe_delete(outapp);
|
||||
|
||||
if (cle)
|
||||
cle->SetOnline(CLE_Status_Zoning);
|
||||
cle->SetOnline(CLE_Status::Zoning);
|
||||
}
|
||||
|
||||
void Client::TellClientZoneUnavailable() {
|
||||
@ -1320,6 +1329,7 @@ void Client::TellClientZoneUnavailable() {
|
||||
|
||||
zone_id = 0;
|
||||
zone_waiting_for_bootup = 0;
|
||||
enter_world_triggered = false;
|
||||
autobootup_timeout.Disable();
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,7 @@ private:
|
||||
bool is_player_zoning;
|
||||
Timer autobootup_timeout;
|
||||
uint32 zone_waiting_for_bootup;
|
||||
bool enter_world_triggered;
|
||||
|
||||
bool StartInTutorial;
|
||||
EQEmu::versions::ClientVersion m_ClientVersion;
|
||||
@ -94,7 +95,6 @@ private:
|
||||
void SetClassLanguages(PlayerProfile_Struct *pp);
|
||||
|
||||
ClientListEntry* cle;
|
||||
Timer CLE_keepalive_timer;
|
||||
Timer connect;
|
||||
bool firstlogin;
|
||||
bool seen_character_select;
|
||||
|
||||
@ -83,8 +83,8 @@ ClientListEntry::ClientListEntry(
|
||||
memset(pLFGComments, 0, 64);
|
||||
}
|
||||
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer *iZS, ServerClientList_Struct *scl, int8 iOnline)
|
||||
: id(in_id)
|
||||
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline)
|
||||
: id(in_id)
|
||||
{
|
||||
ClearVars(true);
|
||||
|
||||
@ -104,7 +104,7 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer *iZS, ServerClientList
|
||||
pLFGMatchFilter = false;
|
||||
memset(pLFGComments, 0, 64);
|
||||
|
||||
if (iOnline >= CLE_Status_Zoning) {
|
||||
if (iOnline >= CLE_Status::Zoning) {
|
||||
Update(iZS, scl, iOnline);
|
||||
}
|
||||
else {
|
||||
@ -129,31 +129,39 @@ void ClientListEntry::SetChar(uint32 iCharID, const char *iCharName)
|
||||
strn0cpy(pname, iCharName, sizeof(pname));
|
||||
}
|
||||
|
||||
void ClientListEntry::SetOnline(ZoneServer *iZS, int8 iOnline)
|
||||
{
|
||||
void ClientListEntry::SetOnline(ZoneServer* iZS, CLE_Status iOnline) {
|
||||
if (iZS == this->Server()) {
|
||||
SetOnline(iOnline);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientListEntry::SetOnline(int8 iOnline)
|
||||
void ClientListEntry::SetOnline(CLE_Status iOnline)
|
||||
{
|
||||
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online) {
|
||||
Log(Logs::General,
|
||||
Logs::World_Server,
|
||||
"ClientListEntry::SetOnline for %s(%i) = %i",
|
||||
AccountName(),
|
||||
AccountID(),
|
||||
iOnline);
|
||||
|
||||
if (iOnline >= CLE_Status::Online && pOnline < CLE_Status::Online) {
|
||||
numplayers++;
|
||||
}
|
||||
else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) {
|
||||
else if (iOnline < CLE_Status::Online && pOnline >= CLE_Status::Online) {
|
||||
numplayers--;
|
||||
}
|
||||
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online) {
|
||||
if (iOnline != CLE_Status::Online || pOnline < CLE_Status::Online) {
|
||||
pOnline = iOnline;
|
||||
}
|
||||
if (iOnline < CLE_Status_Zoning) {
|
||||
if (iOnline < CLE_Status::Zoning) {
|
||||
Camp();
|
||||
}
|
||||
if (pOnline >= CLE_Status_Online) {
|
||||
if (pOnline >= CLE_Status::Online) {
|
||||
stale = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ClientListEntry::LSUpdate(ZoneServer *iZS)
|
||||
{
|
||||
if (WorldConfig::get()->UpdateStats) {
|
||||
@ -184,8 +192,8 @@ void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
|
||||
safe_delete(pack);
|
||||
}
|
||||
}
|
||||
void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, int8 iOnline)
|
||||
{
|
||||
|
||||
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline) {
|
||||
if (pzoneserver != iZS) {
|
||||
if (pzoneserver) {
|
||||
pzoneserver->RemovePlayer();
|
||||
@ -232,7 +240,7 @@ void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, int8
|
||||
SetOnline(iOnline);
|
||||
}
|
||||
|
||||
void ClientListEntry::LeavingZone(ZoneServer *iZS, int8 iOnline)
|
||||
void ClientListEntry::LeavingZone(ZoneServer *iZS, CLE_Status iOnline)
|
||||
{
|
||||
if (iZS != 0 && iZS != pzoneserver) {
|
||||
return;
|
||||
@ -250,8 +258,8 @@ void ClientListEntry::LeavingZone(ZoneServer *iZS, int8 iOnline)
|
||||
void ClientListEntry::ClearVars(bool iAll)
|
||||
{
|
||||
if (iAll) {
|
||||
pOnline = CLE_Status_Never;
|
||||
stale = 0;
|
||||
pOnline = CLE_Status::Never;
|
||||
stale = 0;
|
||||
|
||||
pLSID = 0;
|
||||
memset(loginserver_account_name, 0, sizeof(loginserver_account_name));
|
||||
@ -299,12 +307,10 @@ bool ClientListEntry::CheckStale()
|
||||
{
|
||||
stale++;
|
||||
if (stale > 20) {
|
||||
if (pOnline > CLE_Status_Offline) {
|
||||
SetOnline(CLE_Status_Offline);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
if (pOnline > CLE_Status::Offline)
|
||||
SetOnline(CLE_Status::Offline);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -8,13 +8,15 @@
|
||||
#include "../common/rulesys.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
#define CLE_Status_Never -1
|
||||
#define CLE_Status_Offline 0
|
||||
#define CLE_Status_Online 1 // Will not overwrite more specific online status
|
||||
#define CLE_Status_CharSelect 2
|
||||
#define CLE_Status_Zoning 3
|
||||
#define CLE_Status_InZone 4
|
||||
typedef enum
|
||||
{
|
||||
Never,
|
||||
Offline,
|
||||
Online,
|
||||
CharSelect,
|
||||
Zoning,
|
||||
InZone
|
||||
} CLE_Status;
|
||||
|
||||
class ZoneServer;
|
||||
struct ServerClientList_Struct;
|
||||
@ -49,23 +51,26 @@ public:
|
||||
* @param scl
|
||||
* @param iOnline
|
||||
*/
|
||||
ClientListEntry(uint32 id, ZoneServer *iZS, ServerClientList_Struct *scl, int8 iOnline);
|
||||
ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = 0);
|
||||
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline);
|
||||
~ClientListEntry();
|
||||
bool CheckStale();
|
||||
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone);
|
||||
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, CLE_Status iOnline = CLE_Status::InZone);
|
||||
void LSUpdate(ZoneServer* zoneserver);
|
||||
void LSZoneChange(ZoneToZone_Struct* ztz);
|
||||
bool CheckAuth(uint32 loginserver_account_id, const char* key_password);
|
||||
void SetOnline(ZoneServer* iZS, int8 iOnline);
|
||||
void SetOnline(int8 iOnline = CLE_Status_Online);
|
||||
bool CheckAuth(const char* iName, MD5& iMD5Password);
|
||||
bool CheckAuth(uint32 id, const char* key, uint32 ip);
|
||||
void SetOnline(ZoneServer* iZS, CLE_Status iOnline);
|
||||
void SetOnline(CLE_Status iOnline = CLE_Status::Online);
|
||||
void SetChar(uint32 iCharID, const char* iCharName);
|
||||
inline int8 Online() { return pOnline; }
|
||||
inline CLE_Status Online() { return pOnline; }
|
||||
inline const uint32 GetID() const { return id; }
|
||||
inline const uint32 GetIP() const { return pIP; }
|
||||
inline void SetIP(const uint32& iIP) { pIP = iIP; }
|
||||
inline void KeepAlive() { stale = 0; }
|
||||
inline uint8 GetStaleCounter() const { return stale; }
|
||||
void LeavingZone(ZoneServer* iZS = 0, int8 iOnline = CLE_Status_Offline);
|
||||
void LeavingZone(ZoneServer* iZS = 0, CLE_Status iOnline = CLE_Status::Offline);
|
||||
void Camp(ZoneServer* iZS = 0);
|
||||
|
||||
// Login Server stuff
|
||||
@ -75,7 +80,7 @@ public:
|
||||
inline const char* LSName() const { return loginserver_account_name; }
|
||||
inline int16 WorldAdmin() const { return pworldadmin; }
|
||||
inline const char* GetLSKey() const { return plskey; }
|
||||
inline const int8 GetOnline() const { return pOnline; }
|
||||
inline const CLE_Status GetOnline() const { return pOnline; }
|
||||
|
||||
// Account stuff
|
||||
inline uint32 AccountID() const { return paccountid; }
|
||||
@ -118,8 +123,8 @@ private:
|
||||
|
||||
const uint32 id;
|
||||
uint32 pIP;
|
||||
int8 pOnline{};
|
||||
uint8 stale{};
|
||||
CLE_Status pOnline;
|
||||
uint8 stale;
|
||||
|
||||
// Login Server stuff
|
||||
char source_loginserver[64]{}; //Loginserver we came from.
|
||||
|
||||
@ -41,7 +41,7 @@ extern ZSList zoneserver_list;
|
||||
uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
|
||||
|
||||
ClientList::ClientList()
|
||||
: CLStale_timer(45000)
|
||||
: CLStale_timer(10000)
|
||||
{
|
||||
NextCLEID = 1;
|
||||
|
||||
@ -64,8 +64,6 @@ void ClientList::Process() {
|
||||
struct in_addr in;
|
||||
in.s_addr = iterator.GetData()->GetIP();
|
||||
Log(Logs::Detail, Logs::World_Server,"Removing client from %s:%d", inet_ntoa(in), iterator.GetData()->GetPort());
|
||||
//the client destructor should take care of this.
|
||||
// iterator.GetData()->Free();
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
else
|
||||
@ -122,7 +120,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline);
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline);
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@ -138,7 +136,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@ -150,7 +148,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@ -161,7 +159,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
|
||||
return;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
@ -182,7 +180,7 @@ uint32 ClientList::GetCLEIPCount(uint32 iIP) {
|
||||
|
||||
while (iterator.MoreElements()) {
|
||||
countCLEIPs = iterator.GetData();
|
||||
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status_Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
|
||||
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status::Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
|
||||
IPInstances++; // Increment the occurences of this IP address
|
||||
}
|
||||
iterator.Advance();
|
||||
@ -208,7 +206,7 @@ void ClientList::DisconnectByIP(uint32 iIP) {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
countCLEIPs->SetOnline(CLE_Status_Offline);
|
||||
countCLEIPs->SetOnline(CLE_Status::Offline);
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
iterator.Advance();
|
||||
@ -255,19 +253,6 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClientListEntry* ClientList::FindCLEByLSID(uint32 iLSID) {
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->LSID() == iLSID) {
|
||||
return iterator.GetData();
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) {
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
char* output = 0;
|
||||
@ -343,10 +328,10 @@ void ClientList::ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* s
|
||||
if (iterator.GetData()->GetID() == scl->wid) {
|
||||
cle = iterator.GetData();
|
||||
if (scl->remove == 2){
|
||||
cle->LeavingZone(zoneserver, CLE_Status_Offline);
|
||||
cle->LeavingZone(zoneserver, CLE_Status::Offline);
|
||||
}
|
||||
else if (scl->remove == 1)
|
||||
cle->LeavingZone(zoneserver, CLE_Status_Zoning);
|
||||
cle->LeavingZone(zoneserver, CLE_Status::Zoning);
|
||||
else
|
||||
cle->Update(zoneserver, scl);
|
||||
return;
|
||||
@ -354,11 +339,11 @@ void ClientList::ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* s
|
||||
iterator.Advance();
|
||||
}
|
||||
if (scl->remove == 2)
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_Online);
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Online);
|
||||
else if (scl->remove == 1)
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_Zoning);
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Zoning);
|
||||
else
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_InZone);
|
||||
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::InZone);
|
||||
clientlist.Insert(cle);
|
||||
zoneserver->ChangeWID(scl->charid, cle->GetID());
|
||||
}
|
||||
@ -504,7 +489,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
countcle = countclients.GetData();
|
||||
const char* tmpZone = database.GetZoneName(countcle->zone());
|
||||
if (
|
||||
(countcle->Online() >= CLE_Status_Zoning) &&
|
||||
(countcle->Online() >= CLE_Status::Zoning) &&
|
||||
(!countcle->GetGM() || countcle->Anon() != 1 || admin >= countcle->Admin()) &&
|
||||
(whom == 0 || (
|
||||
((countcle->Admin() >= 80 && countcle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
@ -584,7 +569,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
|
||||
|
||||
const char* tmpZone = database.GetZoneName(cle->zone());
|
||||
if (
|
||||
(cle->Online() >= CLE_Status_Zoning) &&
|
||||
(cle->Online() >= CLE_Status::Zoning) &&
|
||||
(!cle->GetGM() || cle->Anon() != 1 || admin >= cle->Admin()) &&
|
||||
(whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
@ -757,7 +742,7 @@ void ClientList::SendFriendsWho(ServerFriendsWho_Struct *FriendsWho, WorldTCPCon
|
||||
Friend_[Seperator - FriendsPointer] = 0;
|
||||
|
||||
ClientListEntry* CLE = FindCharacter(Friend_);
|
||||
if(CLE && CLE->name() && (CLE->Online() >= CLE_Status_Zoning) && !(CLE->GetGM() && CLE->Anon())) {
|
||||
if(CLE && CLE->name() && (CLE->Online() >= CLE_Status::Zoning) && !(CLE->GetGM() && CLE->Anon())) {
|
||||
FriendsCLEs.push_back(CLE);
|
||||
TotalLength += strlen(CLE->name());
|
||||
int GuildNameLength = strlen(guild_mgr.GetGuildName(CLE->GuildID()));
|
||||
@ -969,7 +954,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
cle = iterator.GetData();
|
||||
const char* tmpZone = database.GetZoneName(cle->zone());
|
||||
if (
|
||||
(cle->Online() >= CLE_Status_Zoning)
|
||||
(cle->Online() >= CLE_Status::Zoning)
|
||||
&& (whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) &&
|
||||
@ -1258,6 +1243,19 @@ void ClientList::RemoveCLEByLSID(uint32 iLSID)
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientList::IsAccountInGame(uint32 iLSID) {
|
||||
LinkedListIterator<ClientListEntry*> iterator(clientlist);
|
||||
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->LSID() == iLSID && iterator.GetData()->Online() == CLE_Status::InZone) {
|
||||
return true;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ClientList::GetClientCount() {
|
||||
return(numplayers);
|
||||
}
|
||||
|
||||
@ -55,7 +55,6 @@ public:
|
||||
ClientListEntry* FindCharacter(const char* name);
|
||||
ClientListEntry* FindCLEByAccountID(uint32 iAccID);
|
||||
ClientListEntry* FindCLEByCharacterID(uint32 iCharID);
|
||||
ClientListEntry* FindCLEByLSID(uint32 iLSID);
|
||||
ClientListEntry* GetCLE(uint32 iID);
|
||||
void GetCLEIP(uint32 iIP);
|
||||
uint32 GetCLEIPCount(uint32 iLSAccountID);
|
||||
@ -65,6 +64,7 @@ public:
|
||||
void CLEAdd(uint32 iLSID, const char* iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
|
||||
void UpdateClientGuild(uint32 char_id, uint32 guild_id);
|
||||
void RemoveCLEByLSID(uint32 iLSID);
|
||||
bool IsAccountInGame(uint32 iLSID);
|
||||
|
||||
int GetClientCount();
|
||||
void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into);
|
||||
|
||||
@ -108,19 +108,11 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
if (RuleB(World, DisallowDuplicateAccountLogins)) {
|
||||
auto cle = client_list.FindCLEByLSID(utwr->lsaccountid);
|
||||
if (cle != nullptr) {
|
||||
auto status = cle->GetOnline();
|
||||
if (CLE_Status_Zoning == status || CLE_Status_InZone == status) {
|
||||
utwrs->response = UserToWorldStatusAlreadyOnline;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
//our existing cle is in a state we can login to, mark the old as stale and remove it.
|
||||
client_list.RemoveCLEByLSID(utwr->lsaccountid);
|
||||
}
|
||||
if (RuleB(World, EnforceCharacterLimitAtLogin)) {
|
||||
if (client_list.IsAccountInGame(utwr->lsaccountid)) {
|
||||
utwrs->response = UserToWorldStatusAlreadyOnline;
|
||||
SendPacket(&outpack);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -708,6 +708,18 @@ void ZSList::WorldShutDown(uint32 time, uint32 interval)
|
||||
}
|
||||
}
|
||||
|
||||
void ZSList::DropClient(uint32 lsid, ZoneServer *ignore_zoneserver) {
|
||||
ServerPacket packet(ServerOP_DropClient, sizeof(ServerZoneDropClient_Struct));
|
||||
auto drop = (ServerZoneDropClient_Struct*)packet.pBuffer;
|
||||
drop->lsid = lsid;
|
||||
|
||||
for (auto &zs : zone_server_list) {
|
||||
if (zs.get() != ignore_zoneserver) {
|
||||
zs->SendPacket(&packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ZSList::OnTick(EQ::Timer *t)
|
||||
{
|
||||
if (!EventSubscriptionWatcher::Get()->IsSubscribed("EQW::ZoneUpdate")) {
|
||||
|
||||
@ -57,6 +57,7 @@ public:
|
||||
void SOPZoneBootup(const char *adminname, uint32 ZoneServerID, const char *zonename, bool iMakeStatic = false);
|
||||
void UpdateUCSServerAvailable(bool ucss_available = true);
|
||||
void WorldShutDown(uint32 time, uint32 interval);
|
||||
void DropClient(uint32 lsid, ZoneServer *ignore_zoneserver);
|
||||
|
||||
ZoneServer* FindByPort(uint16 port);
|
||||
ZoneServer* FindByID(uint32 ZoneID);
|
||||
|
||||
@ -437,7 +437,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
}
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
|
||||
if (cle == 0 || cle->Online() < CLE_Status_Zoning ||
|
||||
if (cle == 0 || cle->Online() < CLE_Status::Zoning ||
|
||||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
@ -450,7 +450,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
sender->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
else if (cle->Online() == CLE_Status_Zoning) {
|
||||
else if (cle->Online() == CLE_Status::Zoning) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (cle->TellQueueFull()) {
|
||||
@ -518,7 +518,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
|
||||
ClientListEntry* cle = client_list.FindCharacter(svm->To);
|
||||
|
||||
if (!cle || (cle->Online() < CLE_Status_Zoning) || !cle->Server()) {
|
||||
if (!cle || (cle->Online() < CLE_Status::Zoning) || !cle->Server()) {
|
||||
|
||||
zoneserver_list.SendEmoteMessage(svm->From, 0, 0, 0, "'%s is not online at this time'", svm->To);
|
||||
|
||||
@ -1457,6 +1457,7 @@ void ZoneServer::IncomingClient(Client* client) {
|
||||
s->accid = client->GetAccountID();
|
||||
s->admin = client->GetAdmin();
|
||||
s->charid = client->GetCharID();
|
||||
s->lsid = client->GetLSID();
|
||||
if (client->GetCLE())
|
||||
s->tellsoff = client->GetCLE()->TellsOff();
|
||||
strn0cpy(s->charname, client->GetCharName(), sizeof(s->charname));
|
||||
|
||||
@ -489,7 +489,7 @@ void Client::ResetAA() {
|
||||
database.DeleteCharacterLeadershipAAs(CharacterID());
|
||||
// undefined for these clients
|
||||
if (ClientVersionBit() & EQEmu::versions::maskTitaniumAndEarlier)
|
||||
Kick();
|
||||
Kick("AA Reset on client that doesn't support it");
|
||||
}
|
||||
|
||||
void Client::SendClearAA()
|
||||
|
||||
@ -136,6 +136,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
forget_timer(0),
|
||||
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
||||
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
|
||||
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
|
||||
tribute_timer(Tribute_duration),
|
||||
proximity_timer(ClientProximity_interval),
|
||||
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
|
||||
@ -446,7 +447,7 @@ Client::~Client() {
|
||||
numclients--;
|
||||
UpdateWindowTitle();
|
||||
if(zone)
|
||||
zone->RemoveAuth(GetName());
|
||||
zone->RemoveAuth(GetName(), lskey);
|
||||
|
||||
//let the stream factory know were done with this stream
|
||||
eqs->Close();
|
||||
@ -845,7 +846,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
{
|
||||
if(AttemptedMessages > RuleI(Chat, MaxMessagesBeforeKick))
|
||||
{
|
||||
Kick();
|
||||
Kick("Sent too many chat messages at once.");
|
||||
return;
|
||||
}
|
||||
if(GlobalChatLimiterTimer)
|
||||
@ -2586,13 +2587,19 @@ void Client::SetPVP(bool toggle, bool message) {
|
||||
Save();
|
||||
}
|
||||
|
||||
void Client::Kick(const std::string &reason) {
|
||||
client_state = CLIENT_KICKED;
|
||||
|
||||
Log(Logs::General, Logs::Client_Login, "Client [%s] kicked, reason [%s]", GetCleanName(), reason.c_str());
|
||||
}
|
||||
|
||||
void Client::WorldKick() {
|
||||
auto outapp = new EQApplicationPacket(OP_GMKick, sizeof(GMKick_Struct));
|
||||
GMKick_Struct* gmk = (GMKick_Struct *)outapp->pBuffer;
|
||||
strcpy(gmk->name,GetName());
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
Kick();
|
||||
Kick("World kick issued");
|
||||
}
|
||||
|
||||
void Client::GMKill() {
|
||||
@ -9115,3 +9122,16 @@ bool Client::GotoPlayer(std::string player_name)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec4 &Client::GetLastPositionBeforeBulkUpdate()
|
||||
{
|
||||
return last_position_before_bulk_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in_last_position_before_bulk_update
|
||||
*/
|
||||
void Client::SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update)
|
||||
{
|
||||
Client::last_position_before_bulk_update = in_last_position_before_bulk_update;
|
||||
}
|
||||
@ -371,9 +371,9 @@ public:
|
||||
inline bool ClientDataLoaded() const { return client_data_loaded; }
|
||||
inline bool Connected() const { return (client_state == CLIENT_CONNECTED); }
|
||||
inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); }
|
||||
inline void Kick() { client_state = CLIENT_KICKED; }
|
||||
inline void Disconnect() { eqs->Close(); client_state = DISCONNECTED; }
|
||||
inline bool IsLD() const { return (bool) (client_state == CLIENT_LINKDEAD); }
|
||||
void Kick(const std::string &reason);
|
||||
void WorldKick();
|
||||
inline uint8 GetAnon() const { return m_pp.anon; }
|
||||
inline PlayerProfile_Struct& GetPP() { return m_pp; }
|
||||
@ -1309,6 +1309,9 @@ public:
|
||||
|
||||
uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns.
|
||||
|
||||
void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update);
|
||||
glm::vec4 &GetLastPositionBeforeBulkUpdate();
|
||||
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
@ -1518,6 +1521,7 @@ private:
|
||||
Timer forget_timer; // our 2 min everybody forgets you timer
|
||||
Timer autosave_timer;
|
||||
Timer client_scan_npc_aggro_timer;
|
||||
Timer client_zone_wide_full_position_update_timer;
|
||||
Timer tribute_timer;
|
||||
|
||||
Timer proximity_timer;
|
||||
@ -1540,6 +1544,7 @@ private:
|
||||
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
|
||||
|
||||
glm::vec3 m_Proximity;
|
||||
glm::vec4 last_position_before_bulk_update;
|
||||
|
||||
void BulkSendInventoryItems();
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "zone.h"
|
||||
#include "mob_movement_manager.h"
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
@ -805,6 +806,8 @@ void Client::CompleteConnect()
|
||||
|
||||
parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0);
|
||||
|
||||
SetLastPositionBeforeBulkUpdate(GetPosition());
|
||||
|
||||
/* This sub event is for if a player logs in for the first time since entering world. */
|
||||
if (firstlogon == 1) {
|
||||
parse->EventPlayer(EVENT_CONNECT, this, "", 0);
|
||||
@ -1166,13 +1169,11 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
*/
|
||||
Client* client = entity_list.GetClientByName(cze->char_name);
|
||||
if (!zone->GetAuth(ip, cze->char_name, &WID, &account_id, &character_id, &admin, lskey, &tellsoff)) {
|
||||
Log(Logs::General, Logs::Error, "GetAuth() returned false kicking client");
|
||||
if (client != 0) {
|
||||
Log(Logs::General, Logs::Client_Login, "%s failed zone auth check.", cze->char_name);
|
||||
if (nullptr != client) {
|
||||
client->Save();
|
||||
client->Kick();
|
||||
client->Kick("Failed auth check");
|
||||
}
|
||||
//ret = false; // TODO: Can we tell the client to get lost in a good way
|
||||
client_state = CLIENT_KICKED;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1682,7 +1683,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
/**
|
||||
* DevTools Load Settings
|
||||
*/
|
||||
if (Admin() >= 200) {
|
||||
if (Admin() >= EQEmu::DevTools::GM_ACCOUNT_STATUS_LEVEL) {
|
||||
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID());
|
||||
if (DataBucket::GetData(dev_tools_window_key) == "true") {
|
||||
dev_tools_window_enabled = false;
|
||||
@ -4467,16 +4468,16 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
|
||||
/* Handle client aggro scanning timers NPCs */
|
||||
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
|
||||
|
||||
|
||||
if (is_client_moving) {
|
||||
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
|
||||
client_scan_npc_aggro_timer.GetDuration());
|
||||
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
|
||||
client_scan_npc_aggro_timer.Disable();
|
||||
client_scan_npc_aggro_timer.Start(500);
|
||||
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
|
||||
client_scan_npc_aggro_timer.GetDuration());
|
||||
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
|
||||
@ -4484,7 +4485,51 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
client_scan_npc_aggro_timer.Start(3000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On a normal basis we limit mob movement updates based on distance
|
||||
* This ensures we send a periodic full zone update to a client that has started moving after 5 or so minutes
|
||||
*
|
||||
* For very large zones we will also force a full update based on distance
|
||||
*
|
||||
* We ignore a small distance around us so that we don't interrupt already pathing deltas as those npcs will appear
|
||||
* to full stop when they are actually still pathing
|
||||
*/
|
||||
|
||||
float distance_moved = DistanceNoZ(GetLastPositionBeforeBulkUpdate(), GetPosition());
|
||||
bool moved_far_enough_before_bulk_update = distance_moved >= zone->GetNpcPositionUpdateDistance();
|
||||
bool is_ready_to_update = (
|
||||
client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update
|
||||
);
|
||||
|
||||
if (is_client_moving && is_ready_to_update) {
|
||||
Log(Logs::Detail, Logs::Normal, "[%s] Client Zone Wide Position Update NPCs", GetCleanName());
|
||||
|
||||
auto &mob_movement_manager = MobMovementManager::Get();
|
||||
auto &mob_list = entity_list.GetMobList();
|
||||
|
||||
for (auto &it : mob_list) {
|
||||
Mob *entity = it.second;
|
||||
if (!entity->IsNPC()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int animation_speed = 0;
|
||||
if (entity->IsMoving()) {
|
||||
if (entity->IsRunning()) {
|
||||
animation_speed = (entity->IsFeared() ? entity->GetFearSpeed() : entity->GetRunspeed());
|
||||
}
|
||||
else {
|
||||
animation_speed = entity->GetWalkspeed();
|
||||
}
|
||||
}
|
||||
|
||||
mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, animation_speed, ClientRangeAny, this);
|
||||
}
|
||||
|
||||
SetLastPositionBeforeBulkUpdate(GetPosition());
|
||||
}
|
||||
|
||||
float new_heading = EQ12toFloat(ppu->heading);
|
||||
int32 new_animation = ppu->animation;
|
||||
|
||||
@ -9757,7 +9802,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
casting_spell_id);
|
||||
database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName());
|
||||
safe_delete_array(detect);
|
||||
Kick(); // Kick client to prevent client and server from getting out-of-sync inventory slots
|
||||
Kick("Inventory desync"); // Kick client to prevent client and server from getting out-of-sync inventory slots
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -9801,7 +9846,7 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_MoveMultipleItems(const EQApplicationPacket *app)
|
||||
{
|
||||
Kick(); // TODO: lets not desync though
|
||||
Kick("Unimplemented move multiple items"); // TODO: lets not desync though
|
||||
}
|
||||
|
||||
void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app)
|
||||
|
||||
@ -591,8 +591,8 @@ bool Client::Process() {
|
||||
// only if client is not feigned
|
||||
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
|
||||
int npc_scan_count = 0;
|
||||
for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) {
|
||||
Mob *mob = it->first;
|
||||
for (auto & close_mob : close_mobs) {
|
||||
Mob *mob = close_mob.first;
|
||||
|
||||
if (!mob)
|
||||
continue;
|
||||
@ -603,6 +603,7 @@ bool Client::Process() {
|
||||
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
|
||||
mob->AddToHateList(this, 25);
|
||||
}
|
||||
|
||||
npc_scan_count++;
|
||||
}
|
||||
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
|
||||
|
||||
@ -1912,7 +1912,7 @@ void command_permaclass(Client *c, const Seperator *sep)
|
||||
Log(Logs::General, Logs::Normal, "Class change request from %s for %s, requested class:%i", c->GetName(), t->GetName(), atoi(sep->arg[1]) );
|
||||
t->SetBaseClass(atoi(sep->arg[1]));
|
||||
t->Save();
|
||||
t->Kick();
|
||||
t->Kick("Class was changed.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3904,7 +3904,7 @@ void command_kick(Client *c, const Seperator *sep)
|
||||
client->Message(0, "You have been kicked by %s", c->GetName());
|
||||
auto outapp = new EQApplicationPacket(OP_GMKick, 0);
|
||||
client->QueuePacket(outapp);
|
||||
client->Kick();
|
||||
client->Kick("Ordered kicked by command");
|
||||
c->Message(0, "Kick: local: kicking %s", sep->arg[1]);
|
||||
}
|
||||
}
|
||||
@ -4499,7 +4499,7 @@ void command_gmzone(Client *c, const Seperator *sep)
|
||||
identifier = sep->arg[3];
|
||||
}
|
||||
|
||||
std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str());
|
||||
std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, identifier.c_str(), zone_version);
|
||||
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
|
||||
|
||||
if (existing_zone_instance.length() > 0) {
|
||||
@ -5196,7 +5196,7 @@ void command_name(Client *c, const Seperator *sep)
|
||||
c->Message(0, "Successfully renamed %s to %s", oldname, sep->arg[1]);
|
||||
// until we get the name packet working right this will work
|
||||
c->Message(0, "Sending player to char select.");
|
||||
target->Kick();
|
||||
target->Kick("Name was changed");
|
||||
}
|
||||
else
|
||||
c->Message(13, "ERROR: Unable to rename %s. Check that the new name '%s' isn't already taken.", oldname, sep->arg[2]);
|
||||
|
||||
@ -1713,6 +1713,18 @@ Client *EntityList::GetClientByWID(uint32 iWID)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Client *EntityList::GetClientByLSID(uint32 iLSID)
|
||||
{
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
if (it->second->LSAccountID() == iLSID) {
|
||||
return it->second;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient)
|
||||
{
|
||||
std::vector<Client *> ClientsInRange;
|
||||
|
||||
@ -176,6 +176,7 @@ public:
|
||||
}
|
||||
Client *GetClientByCharID(uint32 iCharID);
|
||||
Client *GetClientByWID(uint32 iWID);
|
||||
Client *GetClientByLSID(uint32 iLSID);
|
||||
Client *GetClient(uint32 ip, uint16 port);
|
||||
Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr);
|
||||
Group *GetGroupByMob(Mob* mob);
|
||||
|
||||
@ -1608,7 +1608,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
banker ? banker->GetName() : "UNKNOWN NPC", distance);
|
||||
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
|
||||
safe_delete_array(hacked_string);
|
||||
Kick(); // Kicking player to avoid item loss do to client and server inventories not being sync'd
|
||||
Kick("Inventory desync"); // Kicking player to avoid item loss do to client and server inventories not being sync'd
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1822,7 +1822,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
|
||||
// Step 4: Check for entity trade
|
||||
if (dst_slot_id >= EQEmu::invslot::TRADE_BEGIN && dst_slot_id <= EQEmu::invslot::TRADE_END) {
|
||||
if (src_slot_id != EQEmu::invslot::slotCursor) {
|
||||
Kick();
|
||||
Kick("Trade with non-cursor item");
|
||||
return false;
|
||||
}
|
||||
if (with) {
|
||||
|
||||
@ -47,7 +47,7 @@ bool Lua_Client::InZone() {
|
||||
|
||||
void Lua_Client::Kick() {
|
||||
Lua_Safe_Call_Void();
|
||||
self->Kick();
|
||||
self->Kick("Lua Quest");
|
||||
}
|
||||
|
||||
void Lua_Client::Disconnect() {
|
||||
|
||||
@ -1128,7 +1128,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
||||
UpdateActiveLight();
|
||||
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];
|
||||
|
||||
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
|
||||
if (IsNPC() && race == ERUDITE)
|
||||
ns->spawn.showhelm = 1;
|
||||
else
|
||||
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
|
||||
|
||||
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
|
||||
ns->spawn.NPC = IsClient() ? 0 : 1;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -41,18 +41,29 @@ class MobMovementManager
|
||||
public:
|
||||
~MobMovementManager();
|
||||
void Process();
|
||||
void AddMob(Mob *m);
|
||||
void RemoveMob(Mob *m);
|
||||
void AddClient(Client *c);
|
||||
void RemoveClient(Client *c);
|
||||
void AddMob(Mob *mob);
|
||||
void RemoveMob(Mob *mob);
|
||||
void AddClient(Client *client);
|
||||
void RemoveClient(Client *client);
|
||||
|
||||
void RotateTo(Mob *who, float to, MobMovementMode mode = MovementRunning);
|
||||
void RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode = MovementRunning);
|
||||
void Teleport(Mob *who, float x, float y, float z, float heading);
|
||||
void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
|
||||
void StopNavigation(Mob *who);
|
||||
void SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range);
|
||||
|
||||
void SendCommandToClients(
|
||||
Mob *mob,
|
||||
float delta_x,
|
||||
float delta_y,
|
||||
float delta_z,
|
||||
float delta_heading,
|
||||
int anim,
|
||||
ClientRange range,
|
||||
Client* single_client = nullptr
|
||||
);
|
||||
|
||||
float FixHeading(float in);
|
||||
void DumpStats(Client *to);
|
||||
void DumpStats(Client *client);
|
||||
void ClearStats();
|
||||
|
||||
static MobMovementManager &Get() {
|
||||
@ -65,18 +76,18 @@ private:
|
||||
MobMovementManager(const MobMovementManager&);
|
||||
MobMovementManager& operator=(const MobMovementManager&);
|
||||
|
||||
void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
|
||||
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim);
|
||||
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode);
|
||||
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
|
||||
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
|
||||
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
|
||||
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode);
|
||||
void PushStopMoving(MobMovementEntry &ent);
|
||||
void PushEvadeCombat(MobMovementEntry &ent);
|
||||
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
|
||||
void PushStopMoving(MobMovementEntry &mob_movement_entry);
|
||||
void PushEvadeCombat(MobMovementEntry &mob_movement_entry);
|
||||
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||
|
||||
struct Implementation;
|
||||
std::unique_ptr<Implementation> _impl;
|
||||
|
||||
@ -174,7 +174,7 @@ XS(XS_Client_Kick) {
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
THIS->Kick();
|
||||
THIS->Kick("Perl Quest");
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
@ -809,7 +809,7 @@ void QuestManager::changedeity(int diety_id) {
|
||||
initiator->SetDeity(diety_id);
|
||||
initiator->Message(15,"Your Deity has been changed/set to: %i", diety_id);
|
||||
initiator->Save(1);
|
||||
initiator->Kick();
|
||||
initiator->Kick("Deity change by QuestManager");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -943,7 +943,7 @@ void QuestManager::permaclass(int class_id) {
|
||||
//Makes the client the class specified
|
||||
initiator->SetBaseClass(class_id);
|
||||
initiator->Save(2);
|
||||
initiator->Kick();
|
||||
initiator->Kick("Base class change by QuestManager");
|
||||
}
|
||||
|
||||
void QuestManager::permarace(int race_id) {
|
||||
@ -951,7 +951,7 @@ void QuestManager::permarace(int race_id) {
|
||||
//Makes the client the race specified
|
||||
initiator->SetBaseRace(race_id);
|
||||
initiator->Save(2);
|
||||
initiator->Kick();
|
||||
initiator->Kick("Base race change by QuestManager");
|
||||
}
|
||||
|
||||
void QuestManager::permagender(int gender_id) {
|
||||
@ -959,7 +959,7 @@ void QuestManager::permagender(int gender_id) {
|
||||
//Makes the client the gender specified
|
||||
initiator->SetBaseGender(gender_id);
|
||||
initiator->Save(2);
|
||||
initiator->Kick();
|
||||
initiator->Kick("Base gender change by QuestManager");
|
||||
}
|
||||
|
||||
uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
||||
|
||||
@ -298,7 +298,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
if(IsClient()) {
|
||||
char temp[64];
|
||||
sprintf(temp, "%d", spell_id);
|
||||
parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0);
|
||||
if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0) != 0)
|
||||
return false;
|
||||
} else if(IsNPC()) {
|
||||
char temp[64];
|
||||
sprintf(temp, "%d", spell_id);
|
||||
|
||||
@ -112,7 +112,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) {
|
||||
// (it just didn't handle partial stack move actions)
|
||||
if (stack_size > 0) {
|
||||
if (!inst->IsStackable() || !inst2 || !inst2->GetItem() || (inst->GetID() != inst2->GetID()) || (stack_size > inst->GetCharges())) {
|
||||
client->Kick();
|
||||
client->Kick("Error stacking item in trade");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ void Trade::AddEntity(uint16 trade_slot_id, uint32 stack_size) {
|
||||
}
|
||||
else {
|
||||
if (inst2 && inst2->GetID()) {
|
||||
client->Kick();
|
||||
client->Kick("Attempting to add null item to trade");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -534,7 +534,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
ServerZoneIncomingClient_Struct* szic = (ServerZoneIncomingClient_Struct*)pack->pBuffer;
|
||||
if (is_zone_loaded) {
|
||||
SetZoneData(zone->GetZoneID(), zone->GetInstanceID());
|
||||
|
||||
if (szic->zoneid == zone->GetZoneID()) {
|
||||
auto client = entity_list.GetClientByLSID(szic->lsid);
|
||||
if (client) {
|
||||
client->Kick("Dropped by world CLE subsystem");
|
||||
client->Save();
|
||||
}
|
||||
|
||||
zone->RemoveAuth(szic->lsid);
|
||||
zone->AddAuth(szic);
|
||||
// This packet also doubles as "incoming client" notification, lets not shut down before they get here
|
||||
zone->StartShutdownTimer(AUTHENTICATION_TIMEOUT * 1000);
|
||||
@ -547,6 +555,23 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_DropClient: {
|
||||
if (pack->size != sizeof(ServerZoneDropClient_Struct)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ServerZoneDropClient_Struct* drop = (ServerZoneDropClient_Struct*)pack->pBuffer;
|
||||
if (zone) {
|
||||
zone->RemoveAuth(drop->lsid);
|
||||
|
||||
auto client = entity_list.GetClientByLSID(drop->lsid);
|
||||
if (client) {
|
||||
client->Kick("Dropped by world CLE subsystem");
|
||||
client->Save();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ZonePlayer: {
|
||||
ServerZonePlayer_Struct* szp = (ServerZonePlayer_Struct*)pack->pBuffer;
|
||||
Client* client = entity_list.GetClientByName(szp->name);
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "zone_config.h"
|
||||
#include "mob_movement_manager.h"
|
||||
#include "npc_scale_manager.h"
|
||||
#include "../common/data_verification.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <ctime>
|
||||
@ -864,6 +865,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
||||
m_last_ucss_update = 0;
|
||||
|
||||
mMovementManager = &MobMovementManager::Get();
|
||||
|
||||
SetNpcPositionUpdateDistance(0);
|
||||
}
|
||||
|
||||
Zone::~Zone() {
|
||||
@ -1106,6 +1109,7 @@ void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
|
||||
zca->accid = szic->accid;
|
||||
zca->admin = szic->admin;
|
||||
zca->charid = szic->charid;
|
||||
zca->lsid = szic->lsid;
|
||||
zca->tellsoff = szic->tellsoff;
|
||||
strn0cpy(zca->charname, szic->charname, sizeof(zca->charname));
|
||||
strn0cpy(zca->lskey, szic->lskey, sizeof(zca->lskey));
|
||||
@ -1113,16 +1117,31 @@ void Zone::AddAuth(ServerZoneIncomingClient_Struct* szic) {
|
||||
client_auth_list.Insert(zca);
|
||||
}
|
||||
|
||||
void Zone::RemoveAuth(const char* iCharName)
|
||||
void Zone::RemoveAuth(const char* iCharName, const char* iLSKey)
|
||||
{
|
||||
LinkedListIterator<ZoneClientAuth_Struct*> iterator(client_auth_list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ZoneClientAuth_Struct* zca = iterator.GetData();
|
||||
if (strcasecmp(zca->charname, iCharName) == 0) {
|
||||
iterator.RemoveCurrent();
|
||||
return;
|
||||
if (strcasecmp(zca->charname, iCharName) == 0 && strcasecmp(zca->lskey, iLSKey) == 0) {
|
||||
iterator.RemoveCurrent();
|
||||
return;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
void Zone::RemoveAuth(uint32 lsid)
|
||||
{
|
||||
LinkedListIterator<ZoneClientAuth_Struct*> iterator(client_auth_list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
ZoneClientAuth_Struct* zca = iterator.GetData();
|
||||
if (zca->lsid == lsid) {
|
||||
iterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
@ -1178,9 +1197,9 @@ uint32 Zone::CountAuth() {
|
||||
bool Zone::Process() {
|
||||
spawn_conditions.Process();
|
||||
|
||||
if(spawn2_timer.Check()) {
|
||||
if (spawn2_timer.Check()) {
|
||||
|
||||
LinkedListIterator<Spawn2*> iterator(spawn2_list);
|
||||
LinkedListIterator<Spawn2 *> iterator(spawn2_list);
|
||||
|
||||
EQEmu::InventoryProfile::CleanDirty();
|
||||
|
||||
@ -1196,10 +1215,15 @@ bool Zone::Process() {
|
||||
}
|
||||
}
|
||||
|
||||
if(adv_data && !did_adventure_actions)
|
||||
if (adv_data && !did_adventure_actions) {
|
||||
DoAdventureActions();
|
||||
}
|
||||
|
||||
if (GetNpcPositionUpdateDistance() == 0) {
|
||||
CalculateNpcUpdateDistanceSpread();
|
||||
}
|
||||
}
|
||||
|
||||
if(initgrids_timer.Check()) {
|
||||
//delayed grid loading stuff.
|
||||
initgrids_timer.Disable();
|
||||
@ -2349,3 +2373,59 @@ void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
|
||||
if (m_last_ucss_update < update_timestamp)
|
||||
m_ucss_available = ucss_available;
|
||||
}
|
||||
|
||||
int Zone::GetNpcPositionUpdateDistance() const
|
||||
{
|
||||
return npc_position_update_distance;
|
||||
}
|
||||
|
||||
void Zone::SetNpcPositionUpdateDistance(int in_npc_position_update_distance)
|
||||
{
|
||||
Zone::npc_position_update_distance = in_npc_position_update_distance;
|
||||
}
|
||||
|
||||
void Zone::CalculateNpcUpdateDistanceSpread()
|
||||
{
|
||||
float max_x = 0;
|
||||
float max_y = 0;
|
||||
float min_x = 0;
|
||||
float min_y = 0;
|
||||
|
||||
auto &mob_list = entity_list.GetMobList();
|
||||
|
||||
for (auto &it : mob_list) {
|
||||
Mob *entity = it.second;
|
||||
if (!entity->IsNPC()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entity->GetX() <= min_x) {
|
||||
min_x = entity->GetX();
|
||||
}
|
||||
|
||||
if (entity->GetY() <= min_y) {
|
||||
min_y = entity->GetY();
|
||||
}
|
||||
|
||||
if (entity->GetX() >= max_x) {
|
||||
max_x = entity->GetX();
|
||||
}
|
||||
|
||||
if (entity->GetY() >= max_y) {
|
||||
max_y = entity->GetY();
|
||||
}
|
||||
}
|
||||
|
||||
int x_spread = int(abs(max_x - min_x));
|
||||
int y_spread = int(abs(max_y - min_y));
|
||||
int combined_spread = int(abs((x_spread + y_spread) / 2));
|
||||
int update_distance = EQEmu::ClampLower(int(combined_spread / 4), int(zone->GetMaxMovementUpdateRange()));
|
||||
|
||||
SetNpcPositionUpdateDistance(update_distance);
|
||||
|
||||
Log(Logs::General, Logs::Debug,
|
||||
"NPC update spread distance set to [%i] combined_spread [%i]",
|
||||
update_distance,
|
||||
combined_spread
|
||||
);
|
||||
}
|
||||
11
zone/zone.h
11
zone/zone.h
@ -52,6 +52,7 @@ struct ZoneClientAuth_Struct {
|
||||
uint32 accid;
|
||||
int16 admin;
|
||||
uint32 charid;
|
||||
uint32 lsid;
|
||||
bool tellsoff;
|
||||
char charname[64];
|
||||
char lskey[30];
|
||||
@ -125,6 +126,9 @@ public:
|
||||
bool Process();
|
||||
bool SaveZoneCFG();
|
||||
|
||||
int GetNpcPositionUpdateDistance() const;
|
||||
void SetNpcPositionUpdateDistance(int in_npc_position_update_distance);
|
||||
|
||||
char *adv_data;
|
||||
|
||||
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
|
||||
@ -218,6 +222,7 @@ public:
|
||||
void ChangeWeather();
|
||||
void ClearBlockedSpells();
|
||||
void ClearNPCTypeCache(int id);
|
||||
void CalculateNpcUpdateDistanceSpread();
|
||||
void DelAggroMob() { aggroedmobs--; }
|
||||
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
|
||||
void Despawn(uint32 spawngroupID);
|
||||
@ -243,7 +248,8 @@ public:
|
||||
void LoadZoneDoors(const char *zone, int16 version);
|
||||
void ReloadStaticData();
|
||||
void ReloadWorld(uint32 Option);
|
||||
void RemoveAuth(const char *iCharName);
|
||||
void RemoveAuth(const char *iCharName, const char *iLSKey);
|
||||
void RemoveAuth(uint32 lsid);
|
||||
void Repop(uint32 delay = 0);
|
||||
void RepopClose(const glm::vec4 &client_position, uint32 repop_distance);
|
||||
void RequestUCSServerStatus();
|
||||
@ -288,7 +294,7 @@ public:
|
||||
*/
|
||||
find_replace(message, std::string("%"), std::string("."));
|
||||
|
||||
if (message.find("\n") != std::string::npos) {
|
||||
if (message.find('\n') != std::string::npos) {
|
||||
auto message_split = SplitString(message, '\n');
|
||||
entity_list.MessageStatus(
|
||||
0,
|
||||
@ -343,6 +349,7 @@ private:
|
||||
glm::vec4 m_Graveyard;
|
||||
int default_ruleset;
|
||||
int totalBS;
|
||||
int npc_position_update_distance;
|
||||
int32 aggroedmobs;
|
||||
uint8 zone_type;
|
||||
uint16 instanceversion;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user