mirror of
https://github.com/EQEmu/Server.git
synced 2026-02-25 13:32:26 +00:00
Hopefully completely merged from master in what is the biggest merge ever
This commit is contained in:
commit
29b4498534
@ -8,7 +8,9 @@ script:
|
||||
- make
|
||||
- ./bin/tests
|
||||
branches:
|
||||
only: master
|
||||
only:
|
||||
- master
|
||||
- stable
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
|
||||
@ -24,8 +24,8 @@
|
||||
#EQEMU_DISABLE_LOGSYS
|
||||
#EQEMU_COMMANDS_LOGGING
|
||||
#EQEMU_BUILD_SERVER
|
||||
#EQEMU_BUILD_LOGIN
|
||||
#EQEMU_BUILD_TESTS
|
||||
#EQEMU_BUILD_LOGIN
|
||||
#EQEMU_BUILD_TESTS
|
||||
#EQEMU_BUILD_PERL
|
||||
#EQEMU_BUILD_LUA
|
||||
#EQEMU_SANITIZE_LUA_LIBS
|
||||
@ -103,7 +103,7 @@ IF(MSVC)
|
||||
SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
|
||||
SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
|
||||
ENDIF(EQEMU_DISABLE_SAFESEH)
|
||||
|
||||
|
||||
OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON)
|
||||
IF(EQEMU_BUILD_MSVC_MP)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
@ -115,7 +115,7 @@ IF(MSVC)
|
||||
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
|
||||
ENDIF(${flag_var} MATCHES "/MD")
|
||||
ENDFOREACH(flag_var)
|
||||
|
||||
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
ELSE(MSVC)
|
||||
#Normally set by perl but we don't use the perl flags anymore so we set it.
|
||||
@ -126,6 +126,7 @@ ENDIF(MSVC)
|
||||
IF(UNIX)
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
ADD_DEFINITIONS(-DFREEBSD)
|
||||
ADD_DEFINITIONS(-D_GLIBCXX_USE_C99)
|
||||
SET(FREEBSD TRUE)
|
||||
ENDIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
@ -259,7 +260,10 @@ OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Inport/Export Data Programs." ON)
|
||||
|
||||
#C++11 stuff
|
||||
IF(NOT MSVC)
|
||||
ADD_DEFINITIONS(-std=c++0x)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reserved-user-defined-literal")
|
||||
ENDIF()
|
||||
ENDIF(NOT MSVC)
|
||||
|
||||
#Various definitions
|
||||
@ -289,6 +293,7 @@ ADD_DEFINITIONS(-DLOG_LEVEL_DEBUG=${EQEMU_LOG_LEVEL_DEBUG})
|
||||
ADD_DEFINITIONS(-DLOG_LEVEL_QUEST=${EQEMU_LOG_LEVEL_QUEST})
|
||||
ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS})
|
||||
ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH})
|
||||
ADD_DEFINITIONS(-DGLM_FORCE_RADIANS)
|
||||
|
||||
IF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS)
|
||||
ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=true)
|
||||
@ -301,26 +306,26 @@ FIND_PACKAGE(ZLIB REQUIRED)
|
||||
FIND_PACKAGE(MySQL REQUIRED)
|
||||
IF(EQEMU_BUILD_PERL)
|
||||
FIND_PACKAGE(PerlLibs REQUIRED)
|
||||
INCLUDE_DIRECTORIES("${PERL_INCLUDE_PATH}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
|
||||
ENDIF(EQEMU_BUILD_PERL)
|
||||
|
||||
IF(EQEMU_BUILD_LUA)
|
||||
FIND_PACKAGE(EQLua51 REQUIRED)
|
||||
SET(Boost_USE_STATIC_LIBS OFF)
|
||||
SET(Boost_USE_MULTITHREADED ON)
|
||||
SET(Boost_USE_MULTITHREADED ON)
|
||||
SET(Boost_USE_STATIC_RUNTIME OFF)
|
||||
SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost")
|
||||
|
||||
FIND_PACKAGE(Boost REQUIRED)
|
||||
INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "dependencies/luabind")
|
||||
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luabind")
|
||||
|
||||
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
|
||||
IF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm" "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libwebsockets" "${CMAKE_CURRENT_SOURCE_DIR}/common/rapidjson")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm/glm" "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libwebsockets" "${CMAKE_CURRENT_SOURCE_DIR}/common/rapidjson")
|
||||
|
||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
|
||||
519
changelog.txt
519
changelog.txt
@ -1,5 +1,524 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 12/01/2014 ==
|
||||
Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from.
|
||||
Trevius: Mercenaries now spawn with randomized facial features when purchased.
|
||||
Trevius: Setting a lastname for NPCs will now override any hard coded lastname (such as GM Trainers).
|
||||
|
||||
Required SQL: utils/sql/git/required/2014_12_01_mercs_table_update.sql
|
||||
|
||||
== 11/28/2014 ==
|
||||
Trevius: Fixed a zone crash related to numhits for spells.
|
||||
Trevius: Fixed a query related to group leaders logging in.
|
||||
Trevius (Natedog): Fixed a world crash related to attempting to join an adventure with Mercenaries.
|
||||
|
||||
== 11/27/2014 ==
|
||||
Kayen: Projectiles (ie Arrows) fired from archery will now do damage upon impact instead of instantly (consistent w/ live).
|
||||
Optional SQL: utils/sql/git/optional/2014_11_27_ProjectileDmgOnImpact.sql
|
||||
|
||||
== 11/25/2014 ==
|
||||
Trevius: Spells that modify model size are now limited to 2 size adjustments from the base size.
|
||||
Trevius: Fix to prevent Mercenaries from being set as Group Leader.
|
||||
|
||||
== 11/24/2014 ==
|
||||
Trevius: Added Rule NPC:EnableMeritBasedFaction (disabled by default) - Allows faction gain to work similar to experience.
|
||||
|
||||
== 11/22/2014 ==
|
||||
Trevius: Grouping with Mercenaries is now considerably less buggy.
|
||||
Trevius: Fixed an issue with Spell Globals related to high Character IDs.
|
||||
Trevius: Crash fix for Swarm Pets.
|
||||
|
||||
== 11/19/2014 ==
|
||||
Trevius: Mercenaries now Dismiss, Suspend, Unsuspend, and Die correctly.
|
||||
|
||||
== 11/18/2014 ==
|
||||
Trevius: Mercenaries can now zone once again.
|
||||
|
||||
== 11/17/2014 ==
|
||||
demonstar55: Correct OP_AugmentInfo reply. This fixes RoF display issue with Adventurer's Stone. Still issues with UF/SoF/SoD though.
|
||||
|
||||
== 11/16/2014 ==
|
||||
demonstar55: fix size issue with ControlBoat_Struct and exploit fix in OP_BoardBoat
|
||||
|
||||
Akkadius: Implemented Automatic Database update and versioning system
|
||||
Akkadius: Created database revision define, this is located in version.h in common #define CURRENT_BINARY_DATABASE_VERSION 9057
|
||||
- This revision define will need to be incremented each time a database update is made
|
||||
- Along with a revision define increment, you will need to update the db_update manifest located in:
|
||||
- https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt
|
||||
- An entry needs to be made at the bottom of the manifest, the entry is quite simple
|
||||
- Example: 9057|2014_11_13_spells_new_updates.sql|SHOW COLUMNS FROM `spells_new` LIKE 'disallow_sit'|empty|
|
||||
- This latest example is checking to see if the spells_new table contains the column 'disallow_sit', if its empty, the update needs to be ran
|
||||
- More examples of match types below:
|
||||
# Example: Version|Filename.sql|Query_to_Check_Condition_For_Needed_Update|match type|text to match
|
||||
# 0 = Database Version
|
||||
# 1 = Filename.sql
|
||||
# 2 = Query_to_Check_Condition_For_Needed_Update
|
||||
# 3 = Match Type - If condition from match type to Value 4 is true, update will flag for needing to be ran
|
||||
# contains = If query results contains text from 4th value
|
||||
# match = If query results matches text from 4th value
|
||||
# missing = If query result is missing text from 4th value
|
||||
# empty = If the query results in no results
|
||||
# not_empty = If the query is not empty
|
||||
# 4 = Text to match
|
||||
- The manifest contains all database updates 'Required' to be made to the schema, and it will contain a working backport all the way back to SVN -
|
||||
currently it is tested and backported through the beginning of our Github repo
|
||||
- On world bootup or standalone run of db_update.pl, users will be prompted with a simple menu that we will expand upon later:
|
||||
|
||||
============================================================
|
||||
EQEmu: Automatic Database Upgrade Check
|
||||
============================================================
|
||||
Operating System is: MSWin32
|
||||
(Windows) MySQL is in system path
|
||||
Path = C:\Program Files\MariaDB 10.0\bin/mysql
|
||||
============================================================
|
||||
Binary Database Version: (9057)
|
||||
Local Database Version: (9057)
|
||||
|
||||
Database up to Date: Continuing World Bootup...
|
||||
============================================================
|
||||
Retrieving latest database manifest...
|
||||
URL: https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt
|
||||
Saved: db_update/db_update_manifest.txt
|
||||
|
||||
Database Management Menu (Please Select):
|
||||
1) Backup Database - (Saves to Backups folder)
|
||||
Ideal to perform before performing updates
|
||||
2) Backup Database Compressed - (Saves to Backups folder)
|
||||
Ideal to perform before performing updates
|
||||
3) Check for pending Database updates
|
||||
Stages updates for automatic upgrade...
|
||||
0) Exit
|
||||
|
||||
Akkadius: Created db_update.pl, placed in utils/scripts folder, used for the automatic database update routine (Linux/Windows)
|
||||
- db_update.pl script created db_version table if not created, if old one is present it will remove it
|
||||
Akkadius: Created db_dumper.pl, placed in utils/scripts folder, used for the automatic database update routine backups and standalone backups (Linux/Windows)
|
||||
Akkadius: World will now check the db_update.pl script on bootup, if the db_update.pl script is not present, it will fetch it remotely before running -
|
||||
when db_update.pl is done running, world will continue with bootup
|
||||
|
||||
== 11/15/2014 ==
|
||||
Uleat(Natedog): A better fix for OP_ShopPlayerBuy - doesn't cause the issues that I introduced
|
||||
Kayen: Implemented NPC Special Ability 41 'Allow To Tank', gives NPC opportunity to take aggro over a client in melee range.
|
||||
Kayen: Updated swarm pet AI to be consistent with live.
|
||||
|
||||
*OLD AI: Swarm pet would lock on to target until target died, then depop as soon as target died.
|
||||
|
||||
*NEW AI: Swarm pet will attack cast on target, NOT perma locked it can change targets if attacked
|
||||
by something else that generate more hate. When target dies swarm pet will follow owner, if owner is
|
||||
attacked by something else the swarm pet will attack it (until duration timer despawns the pet).
|
||||
|
||||
Kayen: Updated perl quest function: MakeTempPet(Tspell_id, name=nullptr, duration=0, target=nullptr, sticktarg=0)
|
||||
Kayen: Implemented perl quest function: Mob::TypesTempPet(npctypesid, name=nullptr, duration=0, follow=0, target=nullptr, sticktarg=0)
|
||||
Note: 'sticktarg' field will cause the swarm pet to use the OLD AI
|
||||
|
||||
Rule to use OLD AI only - default is disabled.
|
||||
Optional SQL: utils/sql/git/optional/2014_11_15_SwarmPetTargetLock.sql
|
||||
|
||||
== 11/14/2014 ==
|
||||
Secrets: Identified object size and solidtype as flags. Exported them as functions to Perl.
|
||||
demonstar55: Don't use the hack for charms that doesn't work on RoF
|
||||
demonstar55: UF too
|
||||
demonstar55: Tit
|
||||
demonstar55: SoF
|
||||
demonstar55: SoD
|
||||
demonstar55: 62 (untested)
|
||||
|
||||
== 11/13/2014 ==
|
||||
Kayen: Implemented target type (44) 'Beams' (which projects an AE infront of caster with a specified length and width).
|
||||
Kayen: Implemented target type (32) AE Target HateList
|
||||
Kayen: Implemented target type (36) Area Client Only
|
||||
Kayen: Implemented target type (37) Area PC Only
|
||||
Kayen: Implemented target type (39) Group No Pet
|
||||
Uleat: PlayerLogMerchantTransactions does not support partial stack purchase logging at this time
|
||||
|
||||
== 11/12/2014 ==
|
||||
Uleat: Changed 'GMTrainee' struct to reflect the actual client hard-coded max skill count (100) - applies to all currently supported clients (6.2->RoF)
|
||||
|
||||
== 11/11/2014 ==
|
||||
Uleat: Third attempt at a fix for GM trainer zone crashes... (this is starting to look like a KLS fix...)
|
||||
|
||||
== 11/10/2014 ==
|
||||
Uleat: Fix for GM Trainer crashing server (really!)
|
||||
JJ: Yellow faction messages.
|
||||
|
||||
== 11/09/2014 ==
|
||||
Kayen: Implemented support for spell target type (45) 'Target Rings' on Underfoot (does work earlier expansions). Thanks to Lecht for figuring out the op_code side.
|
||||
JJ: Implement new Live-like faction adjustment message using rule Client:UseLiveFactionMessage.
|
||||
Optional SQL: utils/sql/git/optional/2014_11_09_LiveFactionMessages.sql
|
||||
|
||||
== 11/06/2014 ==
|
||||
demonstar55: Tracking default sort will now be correct order
|
||||
Trevius: Fixed dynamic merchant list loading. Allows any merchant to be used in any zone.
|
||||
|
||||
== 11/03/2014 ==
|
||||
Secrets: Fixed an overflow in melee lifetap calculations (int16 vs int32)
|
||||
Secrets: Fixed overflow on AC and ATK values that can go out of range.
|
||||
Secrets: Merc/Bot fixes for previous updates.
|
||||
Secrets: Changed a lot of int16s for stat-related functions to int32 because they were causing combat formula overflows (int16/int32 mismatch).
|
||||
Secrets: Linux fix?
|
||||
|
||||
== 11/02/2014 ==
|
||||
Akkadius: Added out of range checking for Spell Save/Loads
|
||||
|
||||
== 11/01/2014 ==
|
||||
Trevius: Fixed potential crash related to Pets/Mercs buffs when targeting themselves.
|
||||
JJ: (noudess) Revamped faction system. See https://github.com/EQEmu/Server/pull/256
|
||||
|
||||
== 10/28/2014 ==
|
||||
Uleat: Added Client::InterrogateInventory(). Can be invoked by #interrogateinv and is also called when Handle_OP_MoveItem() calls for SwapItemResync()
|
||||
|
||||
== 10/22/2014 ==
|
||||
Uleat: Fix for stacking items in a world object..added a new command option: #peekinv world - will show world container contents, if one is in use by target.
|
||||
|
||||
== 10/20/2014 ==
|
||||
demonstar55: Inspect Buffs rank 1 will now show NPC buffs in target window (SoD+)
|
||||
|
||||
== 10/19/2014 ==
|
||||
Uleat: Updated command #peekinv to display item links properly in RoF clients
|
||||
demonstar55: Group Mentoring in raids
|
||||
demonstar55: Inspect Buffs (text only version) works in raid groups
|
||||
demonstar55: Make use of the Inspect Buffs op/packet. 62 SOL until someone finds its op
|
||||
|
||||
== 10/18/2014==
|
||||
demonstar55: Implement group mentor, sharing leadership exp (SoF+ only)
|
||||
demonstar55: Add gaining of group leadership while in raids
|
||||
|
||||
== 10/16/2014 ==
|
||||
Uleat: Fixed the auto-conversion view naming error and renamed the views in the script files. Added a fix sql for databases that auto-converted.
|
||||
Fix SQL: ../sql/git/bots/deprecated/2014_10_16_Lower_Case_View_Fix.sql
|
||||
|
||||
== 10/15/2014 ==
|
||||
Uleat: Cleaned up load/drop bots sqls, added '../utils/sql/git/bots/deprecated' and '../deprecated/load_bots_old.sql' (use this file on pre-player blob conversion databases.)
|
||||
Notes: I modifed the behavior of both load and drop bots to fail on the first operation if their modifications have been performed already.
|
||||
'load_bots.sql' will explicitly add bot schema, while 'drop_bots.sql' will explicitly drop it. I also added a few lines to change
|
||||
a few altered tables back to their original state - as of the date in the file.
|
||||
|
||||
== 10/13/2014 ==
|
||||
demonstar55: Partially implement leadership and raids
|
||||
Currently working: client side only effects and stat bonuses.
|
||||
Not working: Mark NPC, and other stuff that need extra server side support
|
||||
Currently only UF tested (Tit and 62 may just work, others need packet work)
|
||||
|
||||
== 10/12/2014 ==
|
||||
Akkadius: Fix for LDON Character Stat load
|
||||
|
||||
== 10/11/2014 ==
|
||||
demonstar55: Implement Raid MOTD for UF
|
||||
Don't forget 2014_10_11_RaidMOTD.sql!
|
||||
|
||||
== 10/09/2014 ==
|
||||
Uleat: Added 'BOTS' conversion code to supplement the database 'PlayerProfile' blob conversion that Akkadius recently implemented.
|
||||
Note: This automatic conversion uses the view `vwbotcharactermobs` as an update vector. If you need/would like for the converter to run on
|
||||
previously and/or manually changed code, or just have a need for it to re-run, change the following in the database view and save:
|
||||
"c.`last_login`," to "c.`timelaston`,"
|
||||
"c.`zone_id`" to "c.`zoneid`"
|
||||
"FROM `character_data` AS c" to "FROM `character_old` AS c"
|
||||
** This will only work if you haven't deleted your `character_old` table **
|
||||
|
||||
== 10/07/2014 ==
|
||||
demonstar55: Identified tutorial flag in all charcreate packets, reworked logic to correctly set homes binds
|
||||
|
||||
== 10/05/2014 ==
|
||||
Uleat: Added Server<->Corpse slot translators needed for re-enumeration (inactive until phased in)
|
||||
|
||||
== 10/03/2014 ==
|
||||
Uleat: Fixed Ti(6.2) OP_AugmentInfo translation that I broke (does not currently need and I mis-read a process)
|
||||
Uleat: Moved client patch OP_LootItem slot translation to external handlers
|
||||
|
||||
== 10/02/2014 ==
|
||||
Kayen: Exported to PERL $client->SendSpellAnim(targetid, spellid)
|
||||
This function sends the spell graphic of a spell without actually having to cast the spell.
|
||||
|
||||
== 10/02/2014 ==
|
||||
Uleat: First round of Ti/6.2 translators added - needed for re-enumeration
|
||||
|
||||
== 10/01/2014 ==
|
||||
Kayen: Exported to PERL $client->SendColoredText(color, msg)
|
||||
demonstar55: Exported SendColoredText to lua
|
||||
|
||||
== 09/30/2014 ==
|
||||
Uleat: Implemented click-casting from bag slots for clients that natively support it (RoF)
|
||||
|
||||
== 09/28/2014 ==
|
||||
demonstar55: Add support for post June 18, 2014 Hundred Hands Effect spells (they changed the formula and stuff)
|
||||
set Spells:Jun182014HundredHandsRevamp to true if you're using a spell file from June 18, 2014+
|
||||
|
||||
== 09/27/2014 ==
|
||||
Kayen: Implemented perl function $mob->GetSpellStat(spell_id, identifier, slot);
|
||||
Note: identifier is the stat field in spells_new, slot is used for certain effects like effectid, base,base2, max ect.
|
||||
Example $mob->GetSpellStat(121, "range"); //Returns spell range
|
||||
Example $mob->GetSpellStat(121, "effectid", 1); //Returns the the value of effectid1
|
||||
This will allow you to pull almost all the data for any spell in quest files.
|
||||
demonstar55: Move the client's SetAttackTimer to the end of Client::CalcBonuses to keep the haste in sync
|
||||
demonstar55: Correct haste/slow "stacking" rules
|
||||
demonstar55: Correct SE_AttackSpeed4 to respect unslowable
|
||||
demonstar55: Make the haste be between 1-225 like the client (<100 = slow, >100 = haste) to ...
|
||||
demonstar55: Correct Hundred Hands effect and use formula provided by devs
|
||||
|
||||
== 09/24/2014 ==
|
||||
Uleat: Re-ordered server opcodes and handlers to give them some predictability of location (I need this for the inventory re-enumeration.)
|
||||
demonstar55: Added helper function bool EQEmu::IsTradeskill(uint32 skill)
|
||||
|
||||
== 09/23/2014 ==
|
||||
Kayen: Spell recourse effects will now be applied AFTER the base spells effects have been applied (consistent with live).
|
||||
Kayen: SE_ApplySpell and SE_TriggerSpell will now be applied based on which effect slot they are used in (instead of always before all spell effects are checked).
|
||||
Note: If a spell has multiple SE_TriggerSpell effects within it. Only one will be able to trigger. (If you want multiple spells use SE_ApplySpell)
|
||||
|
||||
== 09/22/2014 ==
|
||||
Akkadius: #resetaa now covers the function of #resetaa and #refundaa
|
||||
- #resetaa will wipe all AA data, refund the spent points into the available points and send character to character select properly
|
||||
Akkadius: Removed #refundaa
|
||||
Akkadius: Removed a lot of debug code for blob conversion
|
||||
Akkadius: Changed status logging for loads/saves to Debug category
|
||||
|
||||
== 09/21/2014 ==
|
||||
Akkadius: Player Profile Blob to Database Conversion
|
||||
- Summary: HUGE difference in database speeds reads/writes and 1:10 datasize difference
|
||||
- The new character storage engine unlike the character_ table before, is able to properly index data and make use of
|
||||
proper MySQL/MariaDB caching optimizations and performance has increased phenominally
|
||||
PERFORMANCE AND STATISTICS FIGURES (Varies on hardware):
|
||||
- EZ Server Character data size of 2.6GB `character_` table alone now takes up approx 600MB
|
||||
- Character Data Loads take approx .03 seconds BEFORE MySQL/MariaDB cache
|
||||
- Character Data Loads take approx .001-.0035 seconds AFTER MySQL/MariaDB cache
|
||||
- Character Data Saves take approx .0001 - .003 for any particular save operation
|
||||
- Database Auto Conversion: When the 'character_' table exists, World boot-up will queue an auto-conversion prompt and convert all of your characters, BACKUP
|
||||
YOUR DATABASE BEFORE CONVERTING, here is an EASY backup script: http://wiki.eqemulator.org/p?MySQL_DB_Backup_Script
|
||||
- On auto conversion, the following tables are created automatically:
|
||||
- Table: `character_skills` - Stores Character Skills
|
||||
- Table: `character_languages` - Stores Character Language
|
||||
- Table: `character_bind` - Stores Character Bind point and Home Bind point designated by is_home bool field
|
||||
- Table: `character_alternate_abilities` - Stores all Character AA
|
||||
- Table: `character_currency` - Stores all Platinum/Gold/Silver/Copper and character related currencies
|
||||
- Table: `character_data` - Stores basic character data (Fields from `character_` table migrated to this table)
|
||||
- Table: `character_spells` - Stores character spells
|
||||
- Table: `character_memmed_spells` - Stores character memorized spells
|
||||
- Table: `character_disciplines` - Stores character disciplines
|
||||
- Table: `character_material` - Stores character armor dye textures
|
||||
- Table: `character_tribute` - Stores character tributes
|
||||
- Table: `character_bandolier` - Stores character bandoliers
|
||||
- Table: `character_inspect_messages` - Stores character inspection messages (Moved from `character_` table)
|
||||
- Table: `character_leadership_abilities` - Stores character Leadership AAs
|
||||
- Loads: Majority of Player profile loads now occur at Client::Handle_Connect_OP_ZoneEntry
|
||||
LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
|
||||
LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
- Saves: Occur all over the code now instead of calling full saves
|
||||
SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, float x, float y, float z, float heading, uint8 is_home);
|
||||
SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level);
|
||||
SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
|
||||
SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
|
||||
SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
|
||||
SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
|
||||
SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
|
||||
SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
|
||||
SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
- Deletes:
|
||||
DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
|
||||
DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
|
||||
DeleteCharacterLeadershipAAs(uint32 character_id);
|
||||
- Now occur all over the code and only trigger when necessary
|
||||
- Two FULL saves when looting a corpse, this has been reduced to just currency saves on initial loot and trimmed to one save since AddToMoneyPP did it already
|
||||
- Every time a player moves coin with any situation (Splits/Trades/Merchant/Skills/Bank Coin Exchange/Coin Moves), a full save is made, this is now just a currency save
|
||||
- Every time a player skilled up at a skill vendor, a full blob save hit was made, this is not just a currency hit
|
||||
- Every time an AA was purchased, a full save was made
|
||||
- Every time a spell was scribed/swapped, disc was trained
|
||||
- When a client exists a zone, when a client enters a zone
|
||||
- NOTE: These amount of excessive saves have caused scalability issues that cause the `character_` table to hang which causes process hangs that affect the whole server
|
||||
because of the slowness of the `character_` table and the blob not allowing any indexing to occur
|
||||
- All functions that once depended on the `character_` table are now rewritten to appropriately read from the `character_data` table
|
||||
- Database query errors that occur during conversion or from and load/save/delete character functions are now leveraged via ThrowDBError and logs now go to
|
||||
Server_Folder_Root/eqemu_query_error_log.txt (You cannot log errors natively through MySQL)
|
||||
- DBASYNC IS NOW COMPLETELY REMOVED - This was mainly for Character data async loads/saves and merchantlist loads
|
||||
- Side implementations:
|
||||
Perl Exports:
|
||||
- quest::crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var) - Sets entity variables world wide with specified npctype_id
|
||||
- quest::crosszonesignalnpcbynpctypeid(npctype_id, data) - Signals all NPC entities world wide with specified npctype_id
|
||||
- $client->GetTaskActivityDoneCount(TaskID, ActivityID) - Gets task activity done count by task id and activity id for client entity
|
||||
|
||||
VIEW TABLE SIZE AFTER CONVERT:
|
||||
|
||||
SELECT CONCAT(table_schema, '.', table_name) as table_name,
|
||||
CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows,
|
||||
CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA,
|
||||
CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') idx,
|
||||
CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size,
|
||||
ROUND(index_length / data_length, 2) idxfrac
|
||||
FROM information_schema.TABLES
|
||||
WHERE `table_name` LIKE 'character_%'
|
||||
ORDER BY DATA DESC;
|
||||
|
||||
== 09/20/2014 ==
|
||||
demonstar55: Fix crash in SendEnterWorld on illegally long names
|
||||
demonstar55: The client only lets you enter 15 characters for your name (UF at least)
|
||||
demonstar55: Add rule Spells:SHDProcIDOffByOne for pre-UF spell file, set to true, UF+ set to false
|
||||
KLS: #suspend and #ban now have required messages to record the reason for the ban/suspension.
|
||||
|
||||
== 09/19/2014 ==
|
||||
demonstar55: Added Client::Tell_StringID (used in tell queue messages)
|
||||
demonstar55: Tell queues (and offline) messages now show correctly
|
||||
demonstar55: Fix starting with capital check
|
||||
|
||||
== 09/18/2014==
|
||||
demonstar55: Implement tell queues
|
||||
Currently set to a limit of 20 by default (World:TellQueueSize) I was unable to hit the limit on live though (100+)
|
||||
The required SQL nukes the old tell queue table, which may or may not be in your DB
|
||||
Optional SQL adds the rule to the DB to allow easy of change
|
||||
Note: this does not play well with multiple sessions with the same name on (crash and relog and have multiple sessions) but normal tells don't play well either
|
||||
|
||||
== 09/16/2014 ==
|
||||
demonstar55: Implement spell formula 137 (BER AA Desperation)
|
||||
Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded.
|
||||
demonstar55: Fix some effect calcs + implement more (derived from the client)
|
||||
|
||||
== 09/15/2014 ==
|
||||
Kayen: Nimbus effects will now be reapplied after zoning and will be removed when associated buff fades.
|
||||
|
||||
== 09/13/2014 ==
|
||||
demonstar55: Fix rogues not having Thieves' Cant
|
||||
|
||||
== 09/09/2014 ==
|
||||
demonstar55: Incrase Mob kick/bash timer by 3
|
||||
see: http://www.eqemulator.org/forums/showthread.php?t=38734
|
||||
demonstar55: Fix slow effect on NPC special attack reuse timers
|
||||
see: http://www.eqemulator.org/forums/showthread.php?t=38734
|
||||
demonstar55: Slow fixes to bots!
|
||||
demonstar55: Revamped how NPC attack rate is set
|
||||
SQL: 2014_09_09_attack_delay.sql
|
||||
demonstar55: Added attackdelay to #npcedit
|
||||
|
||||
== 09/08/2014 ==
|
||||
demonstar55: Fix slow calc
|
||||
see: http://www.eqemulator.org/forums/showthread.php?t=38734
|
||||
|
||||
== 09/07/2014 ==
|
||||
Akkadius: Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance
|
||||
|
||||
== 09/06/2014 ==
|
||||
Uleat: Tweaked 'Smart' trading code to return main slots before sub slots in stackable and free space search processes. (If enough people ask for it, I'll add an optional rule to allow 'bag packing' - the original implementation behavior)
|
||||
|
||||
== 09/05/2014 ==
|
||||
Uleat: Fix for cursor item loss when zoning. (Thanks to the other devs who traced and fixed the 'macro' issue!)
|
||||
demonstar55: Fix size getting nuked with lua's SendIllusionPacket
|
||||
|
||||
== 09/03/2014 ==
|
||||
Secrets: Identified the routines needed to augment items in RoF. Currently, only Insert and Remove are supported. Swap and Destroy do not work due to missing functions related to the cursor.
|
||||
demonstar55: Added work around command to show numhits on your buffs (#shownumhits)
|
||||
Uleat: Fix for timer issue introduced by Zone::ShutDown() fix.
|
||||
|
||||
== 09/02/2014 ==
|
||||
Secrets: Identified OP_GuildPromote for RoF clients.
|
||||
Secrets: Fixed promotion, demotion, transferring a leader and displaying of client ranks in the Rain of Fear client. The rain of fear client, as such, will only have 3 ranks like the other clients, but supports a theoretical 8 ranks later.
|
||||
Secrets/Akkadius: Fixed an issue involving character name lookup in the new DB code.
|
||||
demonstar55: crash fix checking DivineAura in hate_list.cpp
|
||||
Secrets: Reverted some code that got in the main branch that shouldn't have gotten there.
|
||||
Uleat: Changed #loc to report the same precision as /loc for Cartesians
|
||||
|
||||
== 08/31/2014 ==
|
||||
KLS: Fixed a bug in fishing in S3D zones
|
||||
KLS: Fixed a bug in turnins with new any abstraction
|
||||
KLS: Fixed a few quest related inconsistencies.
|
||||
KLS: Added Lua EntityList::ChannelMessage(from, type, msg, language)
|
||||
|
||||
== 08/30/2014 ==
|
||||
demonstar55: (noudess) Merchants should be more descriptive of why they don't sell to you
|
||||
|
||||
== 08/26/2014 ==
|
||||
Uleat: Implemented 'Smart' Player Trade transfers. Trades are processed by containers, stackables and then all remaining. QueryServ logs have been updated to match these transactions.
|
||||
Note: QueryServ logs previously listed 'Items' on the main entry table. This indicated the number of slots affected and not the actual number of items.
|
||||
This field now indicates the actual number of items transferred. For non-stackable, the value is '1' and stackable is the number of charges. A _detail_count
|
||||
property has been added to both 'Trade' and 'Handin' structs to indicate the number of details recorded..though, not tracked..it could be added.
|
||||
|
||||
== 08/24/2014 ==
|
||||
Uleat: Fix (attempted) for zone crashes related to zone shut-down. This change disables all Mob AI and disables/deletes all Mob timers once Zone::ShutDown() is called. More areas will be addressed as reports come in.
|
||||
Note: Perl and Lua quests tested to work..please post any aberrant behavior. (I finally set my spell-check to US English...)
|
||||
Akkadius: Character creation process crash fix and query cleanup
|
||||
Akkadius: Created `character_lookup` table for applications that mirrors all `character_` table fields minus blob fields for application lookups
|
||||
- A 2.4GB character_ table will take 7 seconds to query on a SSD versus .1s on the character_lookup table
|
||||
- This also causes applications like Magelo to burst reads of the entire character table because of the blob fields that come with the reads, as much as 500-600MB/s even if a indexed id filter is provided
|
||||
- This field is synchronized on player save and has 0.001s DB hit
|
||||
- When we split out from the blob, ideally this table can be removed
|
||||
- Required SQL: utils\sql\git\required\2014_08_24_character_lookup.sql
|
||||
|
||||
== 08/23/2014 ==
|
||||
Akkadius: Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
|
||||
Akkadius: Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
|
||||
intensive or metric based logging to a remote server process that could exist on another server entirely
|
||||
Akkadius: Implemented Player Event Logging Types (Go to table `qs_player_events`):
|
||||
1 = Player_Log_Quest,
|
||||
2 = Player_Log_Zoning,
|
||||
3 = Player_Log_Deaths,
|
||||
4 = Player_Log_Connect_State,
|
||||
5 = Player_Log_Levels,
|
||||
6 = Player_Log_Keyring_Addition,
|
||||
7 = Player_Log_QGlobal_Update,
|
||||
8 = Player_Log_Task_Updates,
|
||||
9 = Player_Log_AA_Purchases,
|
||||
10 = Player_Log_Trade_Skill_Events,
|
||||
11 = Player_Log_Issued_Commands,
|
||||
12 = Player_Log_Money_Transactions,
|
||||
13 = Player_Log_Alternate_Currency_Transactions,
|
||||
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
|
||||
- Architecture page: http://wiki.eqemulator.org/p?QueryServ_Architecture
|
||||
Akkadius: Changed all QS Error related logging to 'QUERYSERV__ERROR'
|
||||
Akkadius: (Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
|
||||
Akkadius: Implemented Perl Quest objects (LUA still needed to be exported):
|
||||
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
|
||||
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
|
||||
Akkadius: Added MySQL Tables
|
||||
- `qs_player_aa_rate_hourly`
|
||||
- `qs_player_events`
|
||||
- Source table structures from:
|
||||
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
|
||||
To get the complete QueryServ schema, source from here:
|
||||
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
|
||||
Akkadius: Added rules for each logging type, source rules here with them enabled by default:
|
||||
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
|
||||
Akkadius: Spawn related logging cleanup
|
||||
Akkadius: General code cleanup
|
||||
Akkadius: More to come for QueryServ
|
||||
|
||||
== 08/22/2014 ==
|
||||
Uleat: Rework of Trade::FinishedTrade() and Trade::ResetTrade() to parse items a little more intelligently.
|
||||
|
||||
Trade window items are now sent to client inventory in this order:
|
||||
- Bags
|
||||
- Partial stack movements
|
||||
- All remaining items
|
||||
|
||||
If any of these procedures cause any problems, please post them immediately.
|
||||
|
||||
== 08/20/2014 ==
|
||||
Uleat: Rework of Trade::AddEntity() - function used to move items into the trade window. Now accepts argument for 'stack_size' and updates client properly.
|
||||
Note: I tested trade with Titanium:{SoF,SoD,UF,RoF} in both directions and no client generated an OP_MoveItem event for attempting to place a stackable
|
||||
onto a partial stack already in the trade window. The only way to achieve stacking is to click on the receiving client. If there is a partial stack remaining
|
||||
on the cursor after the OP_MoveItem event, and there is room available, the client will generate subsequent events to move the remaining count.
|
||||
|
||||
== 08/19/2014 ==
|
||||
Akkadius: Implemented a Stop_Return feature (Accidental item handin prevention) that will be symmetrically used with plugin::return_items that I am currently running live testing on EZ before releasing to EQEmu. This does not hurt to have this in the source.
|
||||
Akkadius: Fixed crash where 'attacker' validation is not being checked
|
||||
Akkadius: Removed petition console spam that does not follow traditional logging and is useless
|
||||
Akkadius: Made fix with SympatheticProcChances where it was checking for TempItem->Focus.Effect instead of TempItemAug->Focus.Effect
|
||||
|
||||
== 08/18/2014 ==
|
||||
Uleat: Fix for https://github.com/EQEmu/Server/issues/127 -- also activated a remarked action in doors.cpp to eliminate a memory leak.
|
||||
|
||||
== 08/16/2014 ==
|
||||
KLS: (addmoreice) Trying out some unstable DB changes. Do backup your database before trying them as master will be considered unstable for a few days at least.
|
||||
Uleat (Noudness): Fixed a floating-point comparison error that led to the notorious 'client bounce' (this is not related to the
|
||||
|
||||
@ -19,11 +19,11 @@
|
||||
#include <stdio.h>
|
||||
#include "../../common/debug.h"
|
||||
#include "../../common/shareddb.h"
|
||||
#include "../../common/EQEmuConfig.h"
|
||||
#include "../../common/eqemu_config.h"
|
||||
#include "../../common/platform.h"
|
||||
#include "../../common/crash.h"
|
||||
#include "../../common/rulesys.h"
|
||||
#include "../../common/StringUtil.h"
|
||||
#include "../../common/string_util.h"
|
||||
|
||||
void ExportSpells(SharedDatabase *db);
|
||||
void ExportSkillCaps(SharedDatabase *db);
|
||||
@ -32,7 +32,7 @@ void ExportBaseData(SharedDatabase *db);
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientExport);
|
||||
set_exception_handler();
|
||||
|
||||
|
||||
LogFile->write(EQEMuLog::Status, "Client Files Export Utility");
|
||||
if(!EQEmuConfig::LoadConfig()) {
|
||||
LogFile->write(EQEMuLog::Error, "Unable to load configuration file.");
|
||||
@ -52,11 +52,11 @@ int main(int argc, char **argv) {
|
||||
"database connection");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
ExportSpells(&database);
|
||||
ExportSkillCaps(&database);
|
||||
ExportBaseData(&database);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -69,72 +69,69 @@ void ExportSpells(SharedDatabase *db) {
|
||||
return;
|
||||
}
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
const char *query = "SELECT * FROM spells_new ORDER BY id";
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
if(db->RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
while(row = mysql_fetch_row(result)) {
|
||||
const std::string query = "SELECT * FROM spells_new ORDER BY id";
|
||||
auto results = db->QueryDatabase(query);
|
||||
|
||||
if(results.Success()) {
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
std::string line;
|
||||
unsigned int fields = mysql_num_fields(result);
|
||||
unsigned int fields = results.ColumnCount();
|
||||
for(unsigned int i = 0; i < fields; ++i) {
|
||||
if(i != 0) {
|
||||
line.push_back('^');
|
||||
}
|
||||
|
||||
line += row[i];
|
||||
|
||||
if(row[i] != nullptr) {
|
||||
line += row[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in ExportSpells query '%s' %s", query, errbuf);
|
||||
LogFile->write(EQEMuLog::Error, "Error in ExportSpells query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
}
|
||||
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
bool SkillUsable(SharedDatabase *db, int skill_id, int class_id) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = nullptr;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
bool res = false;
|
||||
if(db->RunQuery(query, MakeAnyLenString(&query, "SELECT max(cap) FROM skill_caps WHERE class=%d AND skillID=%d",
|
||||
class_id, skill_id), errbuf, &result)) {
|
||||
if(row = mysql_fetch_row(result)) {
|
||||
if(row[0] && atoi(row[0]) > 0) {
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in skill_usable query '%s' %s", query, errbuf);
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
return res;
|
||||
bool res = false;
|
||||
|
||||
std::string query = StringFormat("SELECT max(cap) FROM skill_caps WHERE class=%d AND skillID=%d",
|
||||
class_id, skill_id);
|
||||
auto results = db->QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in skill_usable query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return false;
|
||||
|
||||
auto row = results.begin();
|
||||
if(row[0] && atoi(row[0]) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = nullptr;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
int res = 0;
|
||||
if(db->RunQuery(query, MakeAnyLenString(&query, "SELECT cap FROM skill_caps WHERE class=%d AND skillID=%d AND level=%d",
|
||||
class_id, skill_id, level), errbuf, &result)) {
|
||||
if(row = mysql_fetch_row(result)) {
|
||||
res = atoi(row[0]);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in get_skill query '%s' %s", query, errbuf);
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
return res;
|
||||
std::string query = StringFormat("SELECT cap FROM skill_caps WHERE class=%d AND skillID=%d AND level=%d",
|
||||
class_id, skill_id, level);
|
||||
auto results = db->QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in get_skill query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
return atoi(row[0]);
|
||||
}
|
||||
|
||||
void ExportSkillCaps(SharedDatabase *db) {
|
||||
@ -175,27 +172,25 @@ void ExportBaseData(SharedDatabase *db) {
|
||||
return;
|
||||
}
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
const char *query = "SELECT * FROM base_data ORDER BY level, class";
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
if(db->RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
while(row = mysql_fetch_row(result)) {
|
||||
const std::string query = "SELECT * FROM base_data ORDER BY level, class";
|
||||
auto results = db->QueryDatabase(query);
|
||||
if(results.Success()) {
|
||||
for (auto row = results.begin();row != results.end();++row) {
|
||||
std::string line;
|
||||
unsigned int fields = mysql_num_fields(result);
|
||||
for(unsigned int i = 0; i < fields; ++i) {
|
||||
if(i != 0) {
|
||||
unsigned int fields = results.ColumnCount();
|
||||
for(unsigned int rowIndex = 0; rowIndex < fields; ++rowIndex) {
|
||||
if(rowIndex != 0)
|
||||
line.push_back('^');
|
||||
}
|
||||
|
||||
line += row[i];
|
||||
if(row[rowIndex] != nullptr) {
|
||||
line += row[rowIndex];
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in ExportBaseData query '%s' %s", query, errbuf);
|
||||
LogFile->write(EQEMuLog::Error, "Error in ExportBaseData query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
@ -18,11 +18,11 @@
|
||||
|
||||
#include "../../common/debug.h"
|
||||
#include "../../common/shareddb.h"
|
||||
#include "../../common/EQEmuConfig.h"
|
||||
#include "../../common/eqemu_config.h"
|
||||
#include "../../common/platform.h"
|
||||
#include "../../common/crash.h"
|
||||
#include "../../common/rulesys.h"
|
||||
#include "../../common/StringUtil.h"
|
||||
#include "../../common/string_util.h"
|
||||
|
||||
void ImportSpells(SharedDatabase *db);
|
||||
void ImportSkillCaps(SharedDatabase *db);
|
||||
@ -31,7 +31,7 @@ void ImportBaseData(SharedDatabase *db);
|
||||
int main(int argc, char **argv) {
|
||||
RegisterExecutablePlatform(ExePlatformClientImport);
|
||||
set_exception_handler();
|
||||
|
||||
|
||||
LogFile->write(EQEMuLog::Status, "Client Files Import Utility");
|
||||
if(!EQEmuConfig::LoadConfig()) {
|
||||
LogFile->write(EQEMuLog::Error, "Unable to load configuration file.");
|
||||
@ -55,26 +55,20 @@ int main(int argc, char **argv) {
|
||||
ImportSpells(&database);
|
||||
ImportSkillCaps(&database);
|
||||
ImportBaseData(&database);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetSpellColumns(SharedDatabase *db) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
const char *query = "DESCRIBE spells_new";
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
int res = 0;
|
||||
if(db->RunQuery(query, (uint32)strlen(query), errbuf, &result)) {
|
||||
while(row = mysql_fetch_row(result)) {
|
||||
++res;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetSpellColumns query '%s' %s", query, errbuf);
|
||||
}
|
||||
|
||||
return res;
|
||||
const std::string query = "DESCRIBE spells_new";
|
||||
auto results = db->QueryDatabase(query);
|
||||
if(!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetSpellColumns query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
return results.RowCount();
|
||||
}
|
||||
|
||||
void ImportSpells(SharedDatabase *db) {
|
||||
@ -85,8 +79,8 @@ void ImportSpells(SharedDatabase *db) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string delete_sql = "DELETE FROM spells_new";
|
||||
db->RunQuery(delete_sql.c_str(), (uint32)delete_sql.length());
|
||||
std::string query = "DELETE FROM spells_new";
|
||||
db->QueryDatabase(query);
|
||||
|
||||
int columns = GetSpellColumns(db);
|
||||
int spells_imported = 0;
|
||||
@ -103,8 +97,8 @@ void ImportSpells(SharedDatabase *db) {
|
||||
std::string escaped = ::EscapeString(buffer);
|
||||
auto split = SplitString(escaped, '^');
|
||||
int line_columns = (int)split.size();
|
||||
|
||||
std::string sql;
|
||||
|
||||
if(line_columns >= columns) {
|
||||
sql = "INSERT INTO spells_new VALUES(";
|
||||
for(int i = 0; i < columns; ++i) {
|
||||
@ -140,7 +134,7 @@ void ImportSpells(SharedDatabase *db) {
|
||||
sql += ");";
|
||||
}
|
||||
|
||||
db->RunQuery(sql.c_str(), (uint32)sql.length());
|
||||
db->QueryDatabase(sql);
|
||||
|
||||
spells_imported++;
|
||||
if(spells_imported % 1000 == 0) {
|
||||
@ -165,17 +159,17 @@ void ImportSkillCaps(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
std::string delete_sql = "DELETE FROM skill_caps";
|
||||
db->RunQuery(delete_sql.c_str(), (uint32)delete_sql.length());
|
||||
db->QueryDatabase(delete_sql);
|
||||
|
||||
char buffer[2048];
|
||||
while(fgets(buffer, 2048, f)) {
|
||||
auto split = SplitString(buffer, '^');
|
||||
|
||||
|
||||
if(split.size() < 4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int class_id, skill_id, level, cap;
|
||||
class_id = atoi(split[0].c_str());
|
||||
skill_id = atoi(split[1].c_str());
|
||||
@ -185,7 +179,7 @@ void ImportSkillCaps(SharedDatabase *db) {
|
||||
std::string sql = StringFormat("INSERT INTO skill_caps(class, skillID, level, cap) VALUES(%d, %d, %d, %d)",
|
||||
class_id, skill_id, level, cap);
|
||||
|
||||
db->RunQuery(sql.c_str(), (uint32)sql.length());
|
||||
db->QueryDatabase(sql);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
@ -201,7 +195,7 @@ void ImportBaseData(SharedDatabase *db) {
|
||||
}
|
||||
|
||||
std::string delete_sql = "DELETE FROM base_data";
|
||||
db->RunQuery(delete_sql.c_str(), (uint32)delete_sql.length());
|
||||
db->QueryDatabase(delete_sql);
|
||||
|
||||
char buffer[2048];
|
||||
while(fgets(buffer, 2048, f)) {
|
||||
@ -230,7 +224,7 @@ void ImportBaseData(SharedDatabase *db) {
|
||||
"mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)",
|
||||
level, class_id, hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac);
|
||||
|
||||
db->RunQuery(sql.c_str(), (uint32)sql.length());
|
||||
db->QueryDatabase(sql);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
@ -1,82 +1,81 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
SET(common_sources
|
||||
BasePacket.cpp
|
||||
base_packet.cpp
|
||||
classes.cpp
|
||||
Condition.cpp
|
||||
condition.cpp
|
||||
crash.cpp
|
||||
CRC16.cpp
|
||||
crc16.cpp
|
||||
crc32.cpp
|
||||
database.cpp
|
||||
dbasync.cpp
|
||||
dbcore.cpp
|
||||
debug.cpp
|
||||
emu_opcodes.cpp
|
||||
EmuTCPConnection.cpp
|
||||
EmuTCPServer.cpp
|
||||
emu_tcp_connection.cpp
|
||||
emu_tcp_server.cpp
|
||||
eq_dictionary.cpp
|
||||
EQDB.cpp
|
||||
EQDBRes.cpp
|
||||
eqdb.cpp
|
||||
eqdb_res.cpp
|
||||
eqemu_exception.cpp
|
||||
EQEmuConfig.cpp
|
||||
EQEMuError.cpp
|
||||
EQPacket.cpp
|
||||
EQStream.cpp
|
||||
EQStreamFactory.cpp
|
||||
EQStreamIdent.cpp
|
||||
EQStreamProxy.cpp
|
||||
eqemu_config.cpp
|
||||
eqemu_error.cpp
|
||||
eq_packet.cpp
|
||||
eq_stream.cpp
|
||||
eq_stream_factory.cpp
|
||||
eq_stream_ident.cpp
|
||||
eq_stream_proxy.cpp
|
||||
eqtime.cpp
|
||||
extprofile.cpp
|
||||
faction.cpp
|
||||
guild_base.cpp
|
||||
guilds.cpp
|
||||
ipc_mutex.cpp
|
||||
Item.cpp
|
||||
item.cpp
|
||||
logsys.cpp
|
||||
logsys_eqemu.cpp
|
||||
md5.cpp
|
||||
memory_mapped_file.cpp
|
||||
misc.cpp
|
||||
MiscFunctions.cpp
|
||||
misc_functions.cpp
|
||||
moremath.cpp
|
||||
Mutex.cpp
|
||||
MySQLRequestResult.cpp
|
||||
MySQLRequestRow.cpp
|
||||
mutex.cpp
|
||||
mysql_request_result.cpp
|
||||
mysql_request_row.cpp
|
||||
opcode_map.cpp
|
||||
opcodemgr.cpp
|
||||
packet_dump.cpp
|
||||
packet_dump_file.cpp
|
||||
packet_functions.cpp
|
||||
perl_EQDB.cpp
|
||||
perl_EQDBRes.cpp
|
||||
ProcLauncher.cpp
|
||||
perl_eqdb.cpp
|
||||
perl_eqdb_res.cpp
|
||||
proc_launcher.cpp
|
||||
ptimer.cpp
|
||||
races.cpp
|
||||
rdtsc.cpp
|
||||
rulesys.cpp
|
||||
serverinfo.cpp
|
||||
shareddb.cpp
|
||||
skills.cpp
|
||||
spdat.cpp
|
||||
StringUtil.cpp
|
||||
StructStrategy.cpp
|
||||
TCPConnection.cpp
|
||||
TCPServer.cpp
|
||||
string_util.cpp
|
||||
struct_strategy.cpp
|
||||
tcp_connection.cpp
|
||||
tcp_server.cpp
|
||||
timeoutmgr.cpp
|
||||
timer.cpp
|
||||
unix.cpp
|
||||
uuid.cpp
|
||||
worldconn.cpp
|
||||
web_interface_utils.cpp
|
||||
XMLParser.cpp
|
||||
xml_parser.cpp
|
||||
platform.cpp
|
||||
patches/Client62.cpp
|
||||
patches/client62.cpp
|
||||
patches/patches.cpp
|
||||
patches/SoD.cpp
|
||||
patches/SoF.cpp
|
||||
patches/RoF.cpp
|
||||
#patches/RoF2.cpp
|
||||
patches/Titanium.cpp
|
||||
patches/Underfoot.cpp
|
||||
patches/sod.cpp
|
||||
patches/sof.cpp
|
||||
patches/rof.cpp
|
||||
patches/titanium.cpp
|
||||
patches/underfoot.cpp
|
||||
SocketLib/Base64.cpp
|
||||
SocketLib/File.cpp
|
||||
SocketLib/HttpdCookies.cpp
|
||||
@ -96,41 +95,42 @@ SET(common_sources
|
||||
)
|
||||
|
||||
SET(common_headers
|
||||
BasePacket.h
|
||||
any.h
|
||||
base_packet.h
|
||||
base_data.h
|
||||
bodytypes.h
|
||||
breakdowns.h
|
||||
classes.h
|
||||
Condition.h
|
||||
condition.h
|
||||
crash.h
|
||||
CRC16.h
|
||||
crc16.h
|
||||
crc32.h
|
||||
data_verification.h
|
||||
database.h
|
||||
dbasync.h
|
||||
dbcore.h
|
||||
debug.h
|
||||
deity.h
|
||||
emu_opcodes.h
|
||||
emu_oplist.h
|
||||
EmuTCPConnection.h
|
||||
EmuTCPServer.h
|
||||
emu_tcp_connection.h
|
||||
emu_tcp_server.h
|
||||
eq_constants.h
|
||||
eq_dictionary.h
|
||||
eq_packet_structs.h
|
||||
EQDB.h
|
||||
EQDBRes.h
|
||||
eqdb.h
|
||||
eqdb_res.h
|
||||
eqemu_exception.h
|
||||
EQEmuConfig.h
|
||||
EQEmuConfig_elements.h
|
||||
EQEMuError.h
|
||||
EQPacket.h
|
||||
EQStream.h
|
||||
EQStreamFactory.h
|
||||
EQStreamIdent.h
|
||||
EQStreamIntf.h
|
||||
EQStreamLocator.h
|
||||
EQStreamProxy.h
|
||||
EQStreamType.h
|
||||
eqemu_config.h
|
||||
eqemu_config_elements.h
|
||||
eqemu_error.h
|
||||
eq_packet.h
|
||||
eq_stream.h
|
||||
eq_stream_factory.h
|
||||
eq_stream_ident.h
|
||||
eq_stream_intf.h
|
||||
eq_stream_locator.h
|
||||
eq_stream_proxy.h
|
||||
eq_stream_type.h
|
||||
eqtime.h
|
||||
errmsg.h
|
||||
extprofile.h
|
||||
@ -141,7 +141,7 @@ SET(common_headers
|
||||
guild_base.h
|
||||
guilds.h
|
||||
ipc_mutex.h
|
||||
Item.h
|
||||
item.h
|
||||
item_fieldlist.h
|
||||
item_struct.h
|
||||
languages.h
|
||||
@ -153,18 +153,19 @@ SET(common_headers
|
||||
md5.h
|
||||
memory_mapped_file.h
|
||||
misc.h
|
||||
MiscFunctions.h
|
||||
misc_functions.h
|
||||
moremath.h
|
||||
Mutex.h
|
||||
MySQLRequestResult.h
|
||||
MySQLRequestRow.h
|
||||
mutex.h
|
||||
mysql_request_result.h
|
||||
mysql_request_row.h
|
||||
op_codes.h
|
||||
opcode_dispatch.h
|
||||
opcodemgr.h
|
||||
packet_dump.h
|
||||
packet_dump_file.h
|
||||
packet_functions.h
|
||||
ProcLauncher.h
|
||||
platform.h
|
||||
proc_launcher.h
|
||||
profiler.h
|
||||
ptimer.h
|
||||
queue.h
|
||||
@ -178,11 +179,11 @@ SET(common_headers
|
||||
shareddb.h
|
||||
skills.h
|
||||
spdat.h
|
||||
StringUtil.h
|
||||
StructStrategy.h
|
||||
TCPBasicServer.h
|
||||
TCPConnection.h
|
||||
TCPServer.h
|
||||
string_util.h
|
||||
struct_strategy.h
|
||||
tcp_basic_server.h
|
||||
tcp_connection.h
|
||||
tcp_server.h
|
||||
timeoutmgr.h
|
||||
timer.h
|
||||
types.h
|
||||
@ -192,8 +193,8 @@ SET(common_headers
|
||||
version.h
|
||||
worldconn.h
|
||||
web_interface_utils.h
|
||||
XMLParser.h
|
||||
ZoneNumbers.h
|
||||
xml_parser.h
|
||||
zone_numbers.h
|
||||
platform.h
|
||||
patches/Client62.h
|
||||
patches/Client62_constants.h
|
||||
@ -201,40 +202,35 @@ SET(common_headers
|
||||
patches/Client62_ops.h
|
||||
patches/Client62_structs.h
|
||||
patches/patches.h
|
||||
patches/SoD.h
|
||||
patches/SoD_constants.h
|
||||
patches/SoD_itemfields.h
|
||||
patches/SoD_ops.h
|
||||
patches/SoD_structs.h
|
||||
patches/SoF.h
|
||||
patches/SoF_constants.h
|
||||
patches/SoF_itemfields.h
|
||||
patches/SoF_opcode_list.h
|
||||
patches/SoF_ops.h
|
||||
patches/SoF_structs.h
|
||||
patches/SSDeclare.h
|
||||
patches/SSDefine.h
|
||||
patches/SSRegister.h
|
||||
patches/RoF.h
|
||||
patches/RoF_constants.h
|
||||
patches/RoF_itemfields.h
|
||||
patches/RoF_ops.h
|
||||
patches/RoF_structs.h
|
||||
#patches/RoF2.h
|
||||
#patches/RoF2_constants.h
|
||||
#patches/RoF2_itemfields.h
|
||||
#patches/RoF2_ops.h
|
||||
#patches/RoF2_structs.h
|
||||
patches/Titanium.h
|
||||
patches/Titanium_constants.h
|
||||
patches/Titanium_itemfields.h
|
||||
patches/Titanium_ops.h
|
||||
patches/Titanium_structs.h
|
||||
patches/Underfoot.h
|
||||
patches/Underfoot_constants.h
|
||||
patches/Underfoot_itemfields.h
|
||||
patches/Underfoot_ops.h
|
||||
patches/Underfoot_structs.h
|
||||
patches/sod.h
|
||||
patches/sod_constants.h
|
||||
patches/sod_itemfields.h
|
||||
patches/sod_ops.h
|
||||
patches/sod_structs.h
|
||||
patches/sof.h
|
||||
patches/sof_constants.h
|
||||
patches/sof_itemfields.h
|
||||
patches/sof_opcode_list.h
|
||||
patches/sof_ops.h
|
||||
patches/sof_structs.h
|
||||
patches/ss_declare.h
|
||||
patches/ss_define.h
|
||||
patches/ss_register.h
|
||||
patches/rof.h
|
||||
patches/rof_constants.h
|
||||
patches/rof_itemfields.h
|
||||
patches/rof_ops.h
|
||||
patches/rof_structs.h
|
||||
patches/titanium.h
|
||||
patches/titanium_constants.h
|
||||
patches/titanium_itemfields.h
|
||||
patches/titanium_ops.h
|
||||
patches/titanium_structs.h
|
||||
patches/underfoot.h
|
||||
patches/underfoot_constants.h
|
||||
patches/underfoot_itemfields.h
|
||||
patches/underfoot_ops.h
|
||||
patches/underfoot_structs.h
|
||||
SocketLib/Base64.h
|
||||
SocketLib/File.h
|
||||
SocketLib/HttpdCookies.h
|
||||
@ -253,54 +249,48 @@ SET(common_headers
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Patches FILES
|
||||
patches/Client62.h
|
||||
patches/Client62_itemfields.h
|
||||
patches/Client62_ops.h
|
||||
patches/Client62_constants.h
|
||||
patches/Client62_structs.h
|
||||
patches/client62.h
|
||||
patches/client62_itemfields.h
|
||||
patches/client62_ops.h
|
||||
patches/client62_constants.h
|
||||
patches/client62_structs.h
|
||||
patches/patches.h
|
||||
patches/SoD.h
|
||||
patches/SoD_itemfields.h
|
||||
patches/SoD_ops.h
|
||||
patches/SoD_constants.h
|
||||
patches/SoD_structs.h
|
||||
patches/SoF.h
|
||||
patches/SoF_itemfields.h
|
||||
patches/SoF_opcode_list.h
|
||||
patches/SoF_ops.h
|
||||
patches/SoF_constants.h
|
||||
patches/SoF_structs.h
|
||||
patches/SSDeclare.h
|
||||
patches/SSDefine.h
|
||||
patches/SSRegister.h
|
||||
patches/RoF.h
|
||||
patches/RoF_itemfields.h
|
||||
patches/RoF_ops.h
|
||||
patches/RoF_constants.h
|
||||
patches/RoF_structs.h
|
||||
#patches/RoF2.h
|
||||
#patches/RoF2_itemfields.h
|
||||
#patches/RoF2_ops.h
|
||||
#patches/RoF2_constants.h
|
||||
#patches/RoF2_structs.h
|
||||
patches/Titanium.h
|
||||
patches/Titanium_itemfields.h
|
||||
patches/Titanium_ops.h
|
||||
patches/Titanium_constants.h
|
||||
patches/Titanium_structs.h
|
||||
patches/Underfoot.h
|
||||
patches/Underfoot_itemfields.h
|
||||
patches/Underfoot_ops.h
|
||||
patches/Underfoot_constants.h
|
||||
patches/Underfoot_structs.h
|
||||
patches/Client62.cpp
|
||||
patches/sod.h
|
||||
patches/sod_itemfields.h
|
||||
patches/sod_ops.h
|
||||
patches/sod_constants.h
|
||||
patches/sod_structs.h
|
||||
patches/sof.h
|
||||
patches/sof_itemfields.h
|
||||
patches/sof_opcode_list.h
|
||||
patches/sof_ops.h
|
||||
patches/sof_constants.h
|
||||
patches/sof_structs.h
|
||||
patches/ss_declare.h
|
||||
patches/ss_define.h
|
||||
patches/ss_register.h
|
||||
patches/rof.h
|
||||
patches/rof_itemfields.h
|
||||
patches/rof_ops.h
|
||||
patches/rof_constants.h
|
||||
patches/rof_structs.h
|
||||
patches/titanium.h
|
||||
patches/titanium_itemfields.h
|
||||
patches/titanium_ops.h
|
||||
patches/titanium_constants.h
|
||||
patches/titanium_structs.h
|
||||
patches/underfoot.h
|
||||
patches/underfoot_itemfields.h
|
||||
patches/underfoot_ops.h
|
||||
patches/underfoot_constants.h
|
||||
patches/underfoot_structs.h
|
||||
patches/client62.cpp
|
||||
patches/patches.cpp
|
||||
patches/SoD.cpp
|
||||
patches/SoF.cpp
|
||||
patches/RoF.cpp
|
||||
#patches/RoF2.cpp
|
||||
patches/Titanium.cpp
|
||||
patches/Underfoot.cpp
|
||||
patches/sod.cpp
|
||||
patches/sof.cpp
|
||||
patches/rof.cpp
|
||||
patches/titanium.cpp
|
||||
patches/underfoot.cpp
|
||||
)
|
||||
|
||||
SOURCE_GROUP(SocketLib FILES
|
||||
@ -349,8 +339,9 @@ ADD_LIBRARY(common ${common_sources} ${common_headers})
|
||||
|
||||
IF(UNIX)
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
#TODO: Add "patches/RoF2.cpp" when it becomes active
|
||||
SET_SOURCE_FILES_PROPERTIES("patches/SoD.cpp" "patches/SoF.cpp" "patches/RoF.cpp" "patches/Underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
|
||||
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||
ENDIF(UNIX)
|
||||
|
||||
|
||||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
@ -1,405 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* EQStream classes, by Quagmire
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#ifdef WIN32
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include "../common/unix.h"
|
||||
#define SOCKET_ERROR -1
|
||||
#endif
|
||||
#include "EQNetwork.h"
|
||||
#include "EQStream.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "../common/packet_dump_file.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "../common/crc32.h"
|
||||
#include "../common/eq_packet_structs.h"
|
||||
|
||||
#define EQN_DEBUG 0
|
||||
#define EQN_DEBUG_Error 0
|
||||
#define EQN_DEBUG_Packet 0
|
||||
#define EQN_DEBUG_Fragment 0
|
||||
#define EQN_DEBUG_ACK 0
|
||||
#define EQN_DEBUG_Unknown 0
|
||||
#define EQN_DEBUG_NewStream 0
|
||||
#define LOG_PACKETS 0
|
||||
#define LOG_RAW_PACKETS_OUT 0
|
||||
#define LOG_RAW_PACKETS_IN 0
|
||||
//#define PRIORITYTEST
|
||||
|
||||
template <typename type> // LO_BYTE
|
||||
type LO_BYTE (type a) {return (a&=0xff);}
|
||||
template <typename type> // HI_BYTE
|
||||
type HI_BYTE (type a) {return (a&=0xff00);}
|
||||
template <typename type> // LO_WORD
|
||||
type LO_WORD (type a) {return (a&=0xffff);}
|
||||
template <typename type> // HI_WORD
|
||||
type HI_WORD (type a) {return (a&=0xffff0000);}
|
||||
template <typename type> // HI_LOSWAPshort
|
||||
type HI_LOSWAPshort (type a) {return (LO_BYTE(a)<<8) | (HI_BYTE(a)>>8);}
|
||||
template <typename type> // HI_LOSWAPlong
|
||||
type HI_LOSWAPlong (type x) {return (LO_WORD(a)<<16) | (HIWORD(a)>>16);}
|
||||
|
||||
EQStreamServer::EQStreamServer(uint16 iPort) {
|
||||
RunLoop = false;
|
||||
pPort = iPort;
|
||||
pOpen = false;
|
||||
#ifdef WIN32
|
||||
WORD version = MAKEWORD (1,1);
|
||||
WSADATA wsadata;
|
||||
WSAStartup (version, &wsadata);
|
||||
#endif
|
||||
sock = 0;
|
||||
}
|
||||
|
||||
EQStreamServer::~EQStreamServer() {
|
||||
Close();
|
||||
RunLoop = false;
|
||||
MLoopRunning.lock();
|
||||
MLoopRunning.unlock();
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
connection_list.clear();
|
||||
while (!NewQueue.empty())
|
||||
NewQueue.pop(); // they're deleted with the list, clear this queue so it doesnt try to delete them again
|
||||
}
|
||||
|
||||
bool EQStreamServer::Open(uint16 iPort) {
|
||||
LockMutex lock(&MOpen);
|
||||
if (iPort && pPort != iPort) {
|
||||
if (pOpen)
|
||||
return false;
|
||||
pPort = iPort;
|
||||
}
|
||||
if (!RunLoop) {
|
||||
RunLoop = true;
|
||||
#ifdef WIN32
|
||||
_beginthread(EQStreamServerLoop, 0, this);
|
||||
#else
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, &EQStreamServerLoop, this);
|
||||
#endif
|
||||
}
|
||||
if (pOpen) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
struct sockaddr_in address;
|
||||
// int reuse_addr = 1;
|
||||
int bufsize = 64 * 1024; // 64kbyte send/recieve buffers, up from default of 8k
|
||||
#ifdef WIN32
|
||||
unsigned long nonblocking = 1;
|
||||
#endif
|
||||
|
||||
/* Setup internet address information.
|
||||
This is used with the bind() call */
|
||||
memset((char *) &address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(pPort);
|
||||
address.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
/* Setting up UDP port for new clients */
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//#ifdef WIN32
|
||||
// setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr));
|
||||
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize));
|
||||
setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*) &bufsize, sizeof(bufsize));
|
||||
//#else
|
||||
// setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
|
||||
// setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
|
||||
// setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
|
||||
//#endif
|
||||
|
||||
if (bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) {
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
ioctlsocket (sock, FIONBIO, &nonblocking);
|
||||
#else
|
||||
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
pOpen = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void EQStreamServer::Close() {
|
||||
SetOpen(false);
|
||||
if (sock) {
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
sock = 0;
|
||||
}
|
||||
|
||||
bool EQStreamServer::IsOpen() {
|
||||
MOpen.lock();
|
||||
bool ret = pOpen;
|
||||
MOpen.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EQStreamServer::SetOpen(bool iOpen) {
|
||||
MOpen.lock();
|
||||
pOpen = iOpen;
|
||||
MOpen.unlock();
|
||||
}
|
||||
|
||||
void EQStreamServer::Process() {
|
||||
_CP(EQStreamServer_Process);
|
||||
if (!IsOpen()) {
|
||||
if (sock) {
|
||||
#ifdef WIN32
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
sock = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uchar buffer[1518];
|
||||
|
||||
int status;
|
||||
struct sockaddr_in from;
|
||||
unsigned int fromlen;
|
||||
|
||||
from.sin_family = AF_INET;
|
||||
fromlen = sizeof(from);
|
||||
|
||||
while (1) {
|
||||
#ifdef WIN32
|
||||
status = recvfrom(sock, (char *) buffer, sizeof(buffer), 0,(struct sockaddr*) &from, (int *) &fromlen);
|
||||
#else
|
||||
status = recvfrom(sock, buffer, sizeof(buffer), 0,(struct sockaddr*) &from, &fromlen);
|
||||
#endif
|
||||
if (status >= 1) {
|
||||
cout << "Got data from recvfrom" << endl;
|
||||
RecvData(buffer, status, from.sin_addr.s_addr, from.sin_port);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::map <std::string, EQStream*>::iterator connection;
|
||||
for (connection = connection_list.begin(); connection != connection_list.end();) {
|
||||
if (!connection->second) {
|
||||
connection = connection_list.erase(connection);
|
||||
continue;
|
||||
}
|
||||
EQStream* eqs_data = connection->second;
|
||||
if (eqs_data->IsFree() && (!eqs_data->CheckNetActive())) {
|
||||
safe_delete(eqs_data);
|
||||
connection = connection_list.erase(connection);
|
||||
} else if (!eqs_data->RunLoop) {
|
||||
eqs_data->Process(sock);
|
||||
++connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQStreamServer::RecvData(uchar* data, uint32 size, uint32 irIP, uint16 irPort) {
|
||||
/*
|
||||
CHANGE HISTORY
|
||||
|
||||
Version Author Date Comment
|
||||
1 Unknown Unknown Initial Revision
|
||||
2 Joolz 05-Jan-2003 Optimised
|
||||
3 Quagmire 05-Feb-2003 Changed so 2 connection objects wouldnt be created for the same ip/port pair, often happened
|
||||
*/
|
||||
|
||||
// Check for invalid data
|
||||
if (!data || size <= 4) return;
|
||||
//if (CRC32::Generate(data, size-4) != ntohl(*((uint32*) &data[size-4]))) {
|
||||
#if EQN_DEBUG_Error >= 1
|
||||
//cout << "Incomming Packet failed checksum" << endl;
|
||||
#endif
|
||||
//return;
|
||||
//}
|
||||
|
||||
char temp[25];
|
||||
sprintf(temp,"%lu:%u",(unsigned long)irIP,irPort);
|
||||
cout << "Data from " << temp << endl;
|
||||
EQStream* tmp = NULL;
|
||||
std::map <std::string, EQStream*>::iterator connection;
|
||||
if ((connection=connection_list.find(temp))!=connection_list.end())
|
||||
tmp=connection->second;
|
||||
if(tmp != NULL && tmp->GetrPort() == irPort)
|
||||
{
|
||||
tmp->RecvData(data, size);
|
||||
return;
|
||||
}
|
||||
else if(tmp != NULL && tmp->GetrPort() != irPort)
|
||||
{
|
||||
printf("Conflicting IPs & Ports: IP %i and Port %i is conflicting with IP %i and Port %i\n",irIP,irPort,tmp->GetrIP(),tmp->GetrPort());
|
||||
return;
|
||||
}
|
||||
|
||||
if (data[1]==0x01) {
|
||||
cout << "New EQStream Connection." << endl;
|
||||
EQStream* tmp = new EQStream(irIP, irPort);
|
||||
tmp->RecvData(data, size);
|
||||
connection_list[temp]=tmp;
|
||||
if (connection_list.find(temp)==connection_list.end()) {
|
||||
cerr <<"Could not find new connection we just added!" << endl;
|
||||
}
|
||||
MNewQueue.lock();
|
||||
NewQueue.push(tmp);
|
||||
MNewQueue.unlock();
|
||||
return;
|
||||
}
|
||||
#if EQN_DEBUG >= 4
|
||||
struct in_addr in;
|
||||
in.s_addr = irIP;
|
||||
cout << "WARNING: Stray packet? " << inet_ntoa(in) << ":" << irPort << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
EQStream* EQStreamServer::NewQueuePop() {
|
||||
EQStream* ret = 0;
|
||||
MNewQueue.lock();
|
||||
if (!NewQueue.empty()) {
|
||||
ret = NewQueue.front();
|
||||
NewQueue.pop();
|
||||
}
|
||||
MNewQueue.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void EQStreamServerLoop(void* tmp)
|
||||
#else
|
||||
void* EQStreamServerLoop(void* tmp)
|
||||
#endif
|
||||
{
|
||||
#ifdef WIN32
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
#endif
|
||||
EQStreamServer* eqns = (EQStreamServer*) tmp;
|
||||
eqns->MLoopRunning.lock();
|
||||
while (eqns->RunLoop) {
|
||||
{
|
||||
_CP(EQStreamServerLoop);
|
||||
eqns->Process();
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
eqns->MLoopRunning.unlock();
|
||||
#ifdef WIN32
|
||||
_endthread();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void EQStreamInLoop(void* tmp)
|
||||
#else
|
||||
void* EQStreamInLoop(void* tmp)
|
||||
#endif
|
||||
{
|
||||
EQStream* eqs = (EQStream*) tmp;
|
||||
#ifdef _DEBUG
|
||||
if (eqs->ConnectionType != Outgoing) {
|
||||
ThrowError("EQStreamInLoop: eqs->ConnectionType != Outgoing");
|
||||
}
|
||||
#endif
|
||||
eqs->MLoopRunning.lock();
|
||||
Timer* tmp_timer = new Timer(100);
|
||||
tmp_timer->Start();
|
||||
while (eqs->RunLoop) {
|
||||
{
|
||||
_CP(EQStreamInLoop);
|
||||
if(tmp_timer->Check())
|
||||
eqs->DoRecvData();
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
safe_delete(tmp_timer);
|
||||
eqs->MLoopRunning.unlock();
|
||||
#ifdef WIN32
|
||||
_endthread();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void EQStreamOutLoop(void* tmp)
|
||||
#else
|
||||
void* EQStreamOutLoop(void* tmp)
|
||||
#endif
|
||||
{
|
||||
EQStream* eqs = (EQStream*) tmp;
|
||||
#ifdef _DEBUG
|
||||
if (eqs->ConnectionType != Outgoing) {
|
||||
ThrowError("EQStreamOutLoop: eqs->ConnectionType != Outgoing");
|
||||
}
|
||||
#endif
|
||||
eqs->MLoopRunning.lock();
|
||||
Timer* tmp_timer = new Timer(100);
|
||||
tmp_timer->Start();
|
||||
while (eqs->RunLoop) {
|
||||
{
|
||||
_CP(EQStreamOutLoop);
|
||||
if(tmp_timer->Check())
|
||||
eqs->Process(eqs->outsock);
|
||||
}
|
||||
Sleep(1);
|
||||
}
|
||||
safe_delete(tmp_timer);
|
||||
eqs->MLoopRunning.unlock();
|
||||
#ifdef WIN32
|
||||
_endthread();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef EQNETWORK_H
|
||||
#define EQNETWORK_H
|
||||
|
||||
#include "../common/debug.h"
|
||||
|
||||
//uncomment this to enable the packet profiler. Counts the number
|
||||
//of each type of packet sent or received on a connection.
|
||||
#ifdef ZONE
|
||||
//#define PACKET_PROFILER 1
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/queue.h"
|
||||
#include "../common/Mutex.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "EQStream.h"
|
||||
#ifdef PACKET_PROFILER
|
||||
#include "../common/rdtsc.h"
|
||||
#endif
|
||||
|
||||
#define EQNC_TIMEOUT 60000
|
||||
#define NAS_TIMER 100
|
||||
#define KA_TIMER 400 /* keeps the lag bar constant */
|
||||
#define MAX_HEADER_SIZE 39 // Quag: 39 is the max header + opcode + crc32 + unknowns size
|
||||
|
||||
class EQStreamServer;
|
||||
class EQStream;
|
||||
class EQStreamPacket;
|
||||
class EQStreamFragmentGroupList;
|
||||
class EQStreamFragmentGroup;
|
||||
typedef EQStreamServer EQNServer;
|
||||
typedef EQStream EQNConnection;
|
||||
typedef EQStreamPacket EQNPacket;
|
||||
typedef EQStreamFragmentGroupList EQNFragmentGroupList;
|
||||
typedef EQStreamFragmentGroup EQNFragmentGroup;
|
||||
|
||||
#define FLAG_COMPRESSED 0x1000
|
||||
#define FLAG_COMBINED 0x2000
|
||||
#define FLAG_ENCRYPTED 0x4000
|
||||
#define FLAG_IMPLICIT 0x8000
|
||||
#define FLAG_ALL 0xF000
|
||||
#define StripFlags(x) (x & ~FLAG_ALL)
|
||||
|
||||
// Optimistic compression, used for guessing pre-alloc size on debug output
|
||||
#define BEST_COMPR_RATIO 300
|
||||
|
||||
enum eappCompressed { appNormal, appInflated, appDeflated };
|
||||
|
||||
#ifdef WIN32
|
||||
void EQStreamServerLoop(void* tmp);
|
||||
void EQStreamInLoop(void* tmp);
|
||||
void EQStreamOutLoop(void* tmp);
|
||||
#else
|
||||
void* EQStreamServerLoop(void* tmp);
|
||||
void* EQStreamInLoop(void* tmp);
|
||||
void* EQStreamOutLoop(void* tmp);
|
||||
#endif
|
||||
class EQStreamServer {
|
||||
public:
|
||||
EQStreamServer(uint16 iPort = 0);
|
||||
virtual ~EQStreamServer();
|
||||
|
||||
bool Open(uint16 iPort = 0); // opens the port
|
||||
void Close(); // closes the port
|
||||
void KillAll(); // kills all clients
|
||||
inline uint16 GetPort() { return pPort; }
|
||||
|
||||
EQStream* NewQueuePop();
|
||||
protected:
|
||||
#ifdef WIN32
|
||||
friend void EQStreamServerLoop(void* tmp);
|
||||
#else
|
||||
friend void* EQStreamServerLoop(void* tmp);
|
||||
#endif
|
||||
void Process();
|
||||
bool IsOpen();
|
||||
void SetOpen(bool iOpen);
|
||||
bool RunLoop;
|
||||
Mutex MLoopRunning;
|
||||
private:
|
||||
void RecvData(uchar* data, uint32 size, uint32 irIP, uint16 irPort);
|
||||
#ifdef WIN32
|
||||
SOCKET sock;
|
||||
#else
|
||||
int sock;
|
||||
#endif
|
||||
uint16 pPort;
|
||||
bool pOpen;
|
||||
Mutex MNewQueue;
|
||||
Mutex MOpen;
|
||||
|
||||
std::map<std::string,EQStream*> connection_list;
|
||||
std::queue<EQStream *> NewQueue;
|
||||
};
|
||||
|
||||
#endif
|
||||
1900
common/MaxSkill.cpp
1900
common/MaxSkill.cpp
File diff suppressed because it is too large
Load Diff
@ -46,7 +46,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#include <stdarg.h>
|
||||
#include "Parse.h"
|
||||
#include "HTTPSocket.h"
|
||||
#include "../TCPConnection.h"
|
||||
#include "../tcp_connection.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "../TCPConnection.h"
|
||||
#include "../tcp_connection.h"
|
||||
|
||||
|
||||
#ifdef SOCKETS_NAMESPACE
|
||||
|
||||
@ -211,7 +211,7 @@ typedef unsigned short port_t;
|
||||
#endif
|
||||
|
||||
#ifdef _THREADSAFE_SOCKETS
|
||||
#include "Mutex.h"
|
||||
#include "mutex.h"
|
||||
#include "Lock.h"
|
||||
#endif
|
||||
|
||||
|
||||
190
common/any.h
Normal file
190
common/any.h
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Boost Software License - Version 1.0 - August 17th, 2003
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person or organization
|
||||
* obtaining a copy of the software and accompanying documentation covered by
|
||||
* this license (the "Software") to use, reproduce, display, distribute,
|
||||
* execute, and transmit the Software, and to prepare derivative works of the
|
||||
* Software, and to permit third-parties to whom the Software is furnished to
|
||||
* do so, all subject to the following:
|
||||
*
|
||||
* The copyright notices in the Software and this entire statement, including
|
||||
* the above license grant, this restriction and the following disclaimer,
|
||||
* must be included in all copies of the Software, in whole or in part, and
|
||||
* all derivative works of the Software, unless such copies or derivative
|
||||
* works are solely in the form of machine-executable object code generated by
|
||||
* a source language processor.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
* FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// EQEmu::Any is a modified version of Boost::Any and as such retains the Boost licensing.
|
||||
|
||||
#ifndef EQEMU_COMMON_ANY_H
|
||||
#define EQEMU_COMMON_ANY_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class Any
|
||||
{
|
||||
public:
|
||||
Any()
|
||||
: content(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any(const ValueType &value)
|
||||
: content(new Holder<ValueType>(value))
|
||||
{
|
||||
}
|
||||
|
||||
Any(const Any &other)
|
||||
: content(other.content ? other.content->clone() : 0)
|
||||
{
|
||||
}
|
||||
|
||||
~Any()
|
||||
{
|
||||
if(content)
|
||||
delete content;
|
||||
}
|
||||
|
||||
Any& swap(Any &rhs)
|
||||
{
|
||||
std::swap(content, rhs.content);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any& operator=(const ValueType &rhs)
|
||||
{
|
||||
Any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Any& operator=(Any rhs)
|
||||
{
|
||||
rhs.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return !content;
|
||||
}
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return content ? content->type() : typeid(void);
|
||||
}
|
||||
|
||||
class Placeholder
|
||||
{
|
||||
public:
|
||||
virtual ~Placeholder()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const std::type_info& type() const = 0;
|
||||
virtual Placeholder* clone() const = 0;
|
||||
};
|
||||
|
||||
|
||||
template<typename ValueType>
|
||||
class Holder : public Placeholder
|
||||
{
|
||||
public:
|
||||
Holder(const ValueType &value)
|
||||
: held(value)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const std::type_info& type() const
|
||||
{
|
||||
return typeid(ValueType);
|
||||
}
|
||||
|
||||
virtual Placeholder* clone() const
|
||||
{
|
||||
return new Holder(held);
|
||||
}
|
||||
|
||||
ValueType held;
|
||||
|
||||
private:
|
||||
Holder& operator=(const Holder&);
|
||||
};
|
||||
|
||||
private:
|
||||
template<typename ValueType>
|
||||
friend ValueType* any_cast(Any*);
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType* unsafe_any_cast(Any*);
|
||||
|
||||
Placeholder* content;
|
||||
};
|
||||
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
virtual const char * what() const throw()
|
||||
{
|
||||
return "DBI::bad_any_cast: failed conversion using DBI::any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType* any_cast(Any* operand)
|
||||
{
|
||||
return operand &&
|
||||
operand->type() == typeid(ValueType) ? &static_cast<Any::Holder<ValueType>*>(operand->content)->held : nullptr;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType* any_cast(const Any* operand)
|
||||
{
|
||||
return any_cast<ValueType>(const_cast<Any*>(operand));
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType any_cast(Any& operand)
|
||||
{
|
||||
typedef typename std::remove_reference<ValueType>::type nonref;
|
||||
nonref* result = any_cast<nonref>(&operand);
|
||||
if(!result)
|
||||
throw bad_any_cast();
|
||||
return *result;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(const Any& operand)
|
||||
{
|
||||
typedef typename std::remove_reference<ValueType>::type nonref;
|
||||
return any_cast<const nonref&>(const_cast<Any&>(operand));
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType* unsafe_any_cast(Any* operand)
|
||||
{
|
||||
return &static_cast<Any::Holder<ValueType>*>(operand->content)->held;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType* unsafe_any_cast(const Any* operand)
|
||||
{
|
||||
return unsafe_any_cast<ValueType>(const_cast<Any*>(operand));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -16,7 +16,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "debug.h"
|
||||
#include "BasePacket.h"
|
||||
#include "base_packet.h"
|
||||
#include "misc.h"
|
||||
#include "packet_dump.h"
|
||||
|
||||
@ -290,50 +290,3 @@ const char* GetEQClassName(uint8 class_, uint8 level) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32 GetArrayEQClass(uint8 eqclass) {
|
||||
switch (eqclass) {
|
||||
case WARRIOR:
|
||||
return WARRIOR;
|
||||
case CLERIC:
|
||||
return CLERIC;
|
||||
case PALADIN:
|
||||
return PALADIN;
|
||||
case RANGER:
|
||||
return RANGER;
|
||||
case SHADOWKNIGHT:
|
||||
return SHADOWKNIGHT;
|
||||
case DRUID:
|
||||
return DRUID;
|
||||
case MONK:
|
||||
return MONK;
|
||||
case BARD:
|
||||
return BARD;
|
||||
case ROGUE:
|
||||
return ROGUE;
|
||||
case SHAMAN:
|
||||
return SHAMAN;
|
||||
case NECROMANCER:
|
||||
return NECROMANCER;
|
||||
case WIZARD:
|
||||
return WIZARD;
|
||||
case MAGICIAN:
|
||||
return MAGICIAN;
|
||||
case ENCHANTER:
|
||||
return ENCHANTER;
|
||||
case BEASTLORD:
|
||||
return BEASTLORD;
|
||||
case BERSERKER:
|
||||
return BERSERKER;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 GetEQArrayEQClass(uint8 eqclass) {
|
||||
if (eqclass >= WARRIOR && eqclass <= BERSERKER)
|
||||
return eqclass - WARRIOR;
|
||||
if (eqclass >= WARRIORGM && eqclass <= BERSERKERGM)
|
||||
return eqclass - WARRIORGM;
|
||||
return WARRIOR;
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,5 @@
|
||||
#define call_1 65536
|
||||
|
||||
const char* GetEQClassName(uint8 class_, uint8 level = 0);
|
||||
uint32 GetArrayEQClass(uint8 eqclass);
|
||||
uint8 GetEQArrayEQClass(uint8 eqclass);
|
||||
#endif
|
||||
|
||||
|
||||
@ -17,7 +17,8 @@ static const uint32 BIT_RoFAndLater = 0xFFFFFFE0;
|
||||
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
|
||||
static const uint32 BIT_AllClients = 0xFFFFFFFF;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
EQClientUnknown = 0,
|
||||
EQClient62, // Build: 'Aug 4 2005 15:40:59'
|
||||
EQClientTitanium, // Build: 'Oct 31 2005 10:33:37'
|
||||
@ -26,17 +27,50 @@ typedef enum {
|
||||
EQClientUnderfoot, // Build: 'Jun 8 2010 16:44:32'
|
||||
EQClientRoF, // Build: 'Dec 10 2012 17:35:44'
|
||||
EQClientRoF2, // Build: 'May 10 2013 23:30:08'
|
||||
|
||||
|
||||
_EQClientCount, // place new clients before this point (preferably, in release/attribute order)
|
||||
|
||||
|
||||
// Values below are not implemented, as yet...
|
||||
|
||||
|
||||
EmuNPC = _EQClientCount,
|
||||
EmuMerc,
|
||||
EmuBot,
|
||||
EmuPet,
|
||||
|
||||
|
||||
_EmuClientCount // array size for EQLimits
|
||||
} EQClientVersion;
|
||||
|
||||
static const char* EQClientVersionName(EQClientVersion version)
|
||||
{
|
||||
switch (version)
|
||||
{
|
||||
case EQClientUnknown:
|
||||
return "EQClientUnknown";
|
||||
case EQClient62:
|
||||
return "EQClient62";
|
||||
case EQClientTitanium:
|
||||
return "EQClientTitanium";
|
||||
case EQClientSoF:
|
||||
return "EQClientSoF";
|
||||
case EQClientSoD:
|
||||
return "EQClientSoD";
|
||||
case EQClientUnderfoot:
|
||||
return "EQClientUnderfoot";
|
||||
case EQClientRoF:
|
||||
return "EQClientRoF";
|
||||
case EQClientRoF2:
|
||||
return "EQClientRoF2";
|
||||
case EmuNPC:
|
||||
return "EmuNPC";
|
||||
case EmuMerc:
|
||||
return "EmuMerc";
|
||||
case EmuBot:
|
||||
return "EmuBot";
|
||||
case EmuPet:
|
||||
return "EmuPet";
|
||||
default:
|
||||
return "ERROR: Invalid EQClientVersion";
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* CLIENTVERSIONS_H */
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "Condition.h"
|
||||
#include "condition.h"
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
48
common/data_verification.h
Normal file
48
common/data_verification.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef COMMON_DATA_VERIFICATION_H
|
||||
#define COMMON_DATA_VERIFICATION_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
T Clamp(const T& value, const T& lower, const T& upper) {
|
||||
return std::max(lower, std::min(value, upper));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ClampLower(const T& value, const T& lower) {
|
||||
return std::max(lower, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ClampUpper(const T& value, const T& upper) {
|
||||
return std::min(value, upper);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ValueWithin(const T& value, const T& lower, const T& upper) {
|
||||
return value >= lower && value <= upper;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
2835
common/database.cpp
2835
common/database.cpp
File diff suppressed because it is too large
Load Diff
@ -26,12 +26,6 @@
|
||||
#include "dbcore.h"
|
||||
#include "linked_list.h"
|
||||
#include "eq_packet_structs.h"
|
||||
/*#include "EQStream.h"
|
||||
#include "guilds.h"
|
||||
#include "MiscFunctions.h"
|
||||
#include "Mutex.h"
|
||||
#include "Item.h"
|
||||
#include "extprofile.h"*/
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -47,6 +41,7 @@ class SpawnGroupList;
|
||||
class Petition;
|
||||
class Client;
|
||||
class Merc;
|
||||
class MySQLRequestResult;
|
||||
struct Combine_Struct;
|
||||
//struct Faction;
|
||||
//struct FactionMods;
|
||||
@ -74,21 +69,15 @@ uint8 eventid;
|
||||
EventLogDetails_Struct eld[255];
|
||||
};
|
||||
|
||||
|
||||
// Added By Hogie
|
||||
// INSERT into variables (varname,value) values('decaytime [minlevel] [maxlevel]','[number of seconds]');
|
||||
// IE: decaytime 1 54 = Levels 1 through 54
|
||||
// decaytime 55 100 = Levels 55 through 100
|
||||
// It will always put the LAST time for the level (I think) from the Database
|
||||
struct npcDecayTimes_Struct {
|
||||
uint16 minlvl;
|
||||
uint16 maxlvl;
|
||||
uint32 seconds;
|
||||
};
|
||||
// Added By Hogie -- End
|
||||
|
||||
|
||||
struct VarCache_Struct {
|
||||
char varname[26]; // varname is char(25) in database
|
||||
char varname[26];
|
||||
char value[0];
|
||||
};
|
||||
|
||||
@ -99,6 +88,411 @@ struct ExtendedProfile_Struct;
|
||||
struct GuildMember_Struct;
|
||||
class PTimerList;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Conversion Structs */
|
||||
|
||||
namespace Convert {
|
||||
struct BindStruct {
|
||||
/*000*/ uint32 zoneId;
|
||||
/*004*/ float x;
|
||||
/*008*/ float y;
|
||||
/*012*/ float z;
|
||||
/*016*/ float heading;
|
||||
};
|
||||
struct Color_Struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8 blue;
|
||||
uint8 green;
|
||||
uint8 red;
|
||||
uint8 use_tint; // if there's a tint this is FF
|
||||
} rgb;
|
||||
uint32 color;
|
||||
};
|
||||
};
|
||||
struct AA_Array
|
||||
{
|
||||
uint32 AA;
|
||||
uint32 value;
|
||||
};
|
||||
struct SpellBuff_Struct
|
||||
{
|
||||
/*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise
|
||||
/*001*/ uint8 level;
|
||||
/*002*/ uint8 bard_modifier;
|
||||
/*003*/ uint8 effect; //not real
|
||||
/*004*/ uint32 spellid;
|
||||
/*008*/ uint32 duration;
|
||||
/*012*/ uint32 counters;
|
||||
/*016*/ uint32 player_id; //'global' ID of the caster, for wearoff messages
|
||||
/*020*/
|
||||
};
|
||||
struct Tribute_Struct {
|
||||
uint32 tribute;
|
||||
uint32 tier;
|
||||
};
|
||||
struct Disciplines_Struct {
|
||||
uint32 values[MAX_PP_DISCIPLINES];
|
||||
};
|
||||
struct GroupLeadershipAA_Struct {
|
||||
union {
|
||||
struct {
|
||||
uint32 groupAAMarkNPC;
|
||||
uint32 groupAANPCHealth;
|
||||
uint32 groupAADelegateMainAssist;
|
||||
uint32 groupAADelegateMarkNPC;
|
||||
uint32 groupAA4;
|
||||
uint32 groupAA5;
|
||||
uint32 groupAAInspectBuffs;
|
||||
uint32 groupAA7;
|
||||
uint32 groupAASpellAwareness;
|
||||
uint32 groupAAOffenseEnhancement;
|
||||
uint32 groupAAManaEnhancement;
|
||||
uint32 groupAAHealthEnhancement;
|
||||
uint32 groupAAHealthRegeneration;
|
||||
uint32 groupAAFindPathToPC;
|
||||
uint32 groupAAHealthOfTargetsTarget;
|
||||
uint32 groupAA15;
|
||||
};
|
||||
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
};
|
||||
|
||||
struct RaidLeadershipAA_Struct {
|
||||
union {
|
||||
struct {
|
||||
uint32 raidAAMarkNPC;
|
||||
uint32 raidAANPCHealth;
|
||||
uint32 raidAADelegateMainAssist;
|
||||
uint32 raidAADelegateMarkNPC;
|
||||
uint32 raidAA4;
|
||||
uint32 raidAA5;
|
||||
uint32 raidAA6;
|
||||
uint32 raidAASpellAwareness;
|
||||
uint32 raidAAOffenseEnhancement;
|
||||
uint32 raidAAManaEnhancement;
|
||||
uint32 raidAAHealthEnhancement;
|
||||
uint32 raidAAHealthRegeneration;
|
||||
uint32 raidAAFindPathToPC;
|
||||
uint32 raidAAHealthOfTargetsTarget;
|
||||
uint32 raidAA14;
|
||||
uint32 raidAA15;
|
||||
};
|
||||
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
};
|
||||
|
||||
struct LeadershipAA_Struct {
|
||||
union {
|
||||
struct {
|
||||
Convert::GroupLeadershipAA_Struct group;
|
||||
Convert::RaidLeadershipAA_Struct raid;
|
||||
};
|
||||
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
};
|
||||
typedef struct
|
||||
{
|
||||
/*00*/ char Name[64];
|
||||
/*64*/ uint32 Level;
|
||||
/*68*/ uint32 Race;
|
||||
/*72*/ uint32 Class;
|
||||
/*76*/ uint32 Zone;
|
||||
/*80*/ uint32 Time;
|
||||
/*84*/ uint32 Points;
|
||||
/*88*/
|
||||
} PVPStatsEntry_Struct;
|
||||
struct BandolierItem_Struct {
|
||||
uint32 item_id;
|
||||
uint32 icon;
|
||||
char item_name[64];
|
||||
};
|
||||
struct Bandolier_Struct {
|
||||
char name[32];
|
||||
Convert::BandolierItem_Struct items[EmuConstants::BANDOLIER_SIZE];
|
||||
};
|
||||
struct PotionBelt_Struct {
|
||||
Convert::BandolierItem_Struct items[EmuConstants::POTION_BELT_SIZE];
|
||||
};
|
||||
struct SuspendedMinion_Struct
|
||||
{
|
||||
/*000*/ uint16 SpellID;
|
||||
/*002*/ uint32 HP;
|
||||
/*006*/ uint32 Mana;
|
||||
/*010*/ Convert::SpellBuff_Struct Buffs[BUFF_COUNT];
|
||||
/*510*/ uint32 Items[_MaterialCount];
|
||||
/*546*/ char Name[64];
|
||||
/*610*/
|
||||
};
|
||||
|
||||
struct PlayerProfile_Struct {
|
||||
/*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum
|
||||
/*0004*/ char name[64]; // Name of player sizes not right
|
||||
/*0068*/ char last_name[32]; // Last name of player sizes not right
|
||||
/*0100*/ uint32 gender; // Player Gender - 0 Male, 1 Female
|
||||
/*0104*/ uint32 race; // Player race
|
||||
/*0108*/ uint32 class_; // Player class
|
||||
/*0112*/ uint32 unknown0112; //
|
||||
/*0116*/ uint32 level; // Level of player (might be one byte)
|
||||
/*0120*/ Convert::BindStruct binds[5]; // Bind points (primary is first, home city is fifth)
|
||||
/*0220*/ uint32 deity; // deity
|
||||
/*0224*/ uint32 guild_id;
|
||||
/*0228*/ uint32 birthday; // characters bday
|
||||
/*0232*/ uint32 lastlogin; // last login or zone time
|
||||
/*0236*/ uint32 timePlayedMin; // in minutes
|
||||
/*0240*/ uint8 pvp;
|
||||
/*0241*/ uint8 level2; //no idea why this is here, but thats how it is on live
|
||||
/*0242*/ uint8 anon; // 2=roleplay, 1=anon, 0=not anon
|
||||
/*0243*/ uint8 gm;
|
||||
/*0244*/ uint8 guildrank;
|
||||
/*0245*/ uint8 guildbanker;
|
||||
/*0246*/ uint8 unknown0246[6]; //
|
||||
/*0252*/ uint32 intoxication;
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms
|
||||
/*0292*/ uint32 abilitySlotRefresh;
|
||||
/*0296*/ uint8 haircolor; // Player hair color
|
||||
/*0297*/ uint8 beardcolor; // Player beard color
|
||||
/*0298*/ uint8 eyecolor1; // Player left eye color
|
||||
/*0299*/ uint8 eyecolor2; // Player right eye color
|
||||
/*0300*/ uint8 hairstyle; // Player hair style
|
||||
/*0301*/ uint8 beard; // Beard type
|
||||
/*0302*/ uint8 ability_time_seconds; //The following four spots are unknown right now.....
|
||||
/*0303*/ uint8 ability_number; //ability used
|
||||
/*0304*/ uint8 ability_time_minutes;
|
||||
/*0305*/ uint8 ability_time_hours; //place holder
|
||||
/*0306*/ uint8 unknown0306[6]; // @bp Spacer/Flag?
|
||||
/*0312*/ uint32 item_material[_MaterialCount]; // Item texture/material of worn/held items
|
||||
/*0348*/ uint8 unknown0348[44];
|
||||
/*0392*/ Convert::Color_Struct item_tint[_MaterialCount];
|
||||
/*0428*/ Convert::AA_Array aa_array[MAX_PP_AA_ARRAY];
|
||||
/*2348*/ float unknown2384; //seen ~128, ~47
|
||||
/*2352*/ char servername[32]; // length probably not right
|
||||
/*2384*/ char title[32]; // length might be wrong
|
||||
/*2416*/ char suffix[32]; // length might be wrong
|
||||
/*2448*/ uint32 guildid2; //
|
||||
/*2452*/ uint32 exp; // Current Experience
|
||||
/*2456*/ uint32 unknown2492;
|
||||
/*2460*/ uint32 points; // Unspent Practice points
|
||||
/*2464*/ uint32 mana; // current mana
|
||||
/*2468*/ uint32 cur_hp; // current hp
|
||||
/*2472*/ uint32 unknown2508; // 0x05
|
||||
/*2476*/ uint32 STR; // Strength
|
||||
/*2480*/ uint32 STA; // Stamina
|
||||
/*2484*/ uint32 CHA; // Charisma
|
||||
/*2488*/ uint32 DEX; // Dexterity
|
||||
/*2492*/ uint32 INT; // Intelligence
|
||||
/*2496*/ uint32 AGI; // Agility
|
||||
/*2500*/ uint32 WIS; // Wisdom
|
||||
/*2504*/ uint8 face; // Player face
|
||||
/*2505*/ uint8 unknown2541[47]; // ?
|
||||
/*2552*/ uint8 languages[MAX_PP_LANGUAGE];
|
||||
/*2580*/ uint8 unknown2616[4];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
|
||||
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL];
|
||||
/*4668*/ uint8 unknown4704[32]; //
|
||||
/*4700*/ float y; // Player y position
|
||||
/*4704*/ float x; // Player x position
|
||||
/*4708*/ float z; // Player z position
|
||||
/*4712*/ float heading; // Direction player is facing
|
||||
/*4716*/ uint8 unknown4752[4]; //
|
||||
/*4720*/ int32 platinum; // Platinum Pieces on player
|
||||
/*4724*/ int32 gold; // Gold Pieces on player
|
||||
/*4728*/ int32 silver; // Silver Pieces on player
|
||||
/*4732*/ int32 copper; // Copper Pieces on player
|
||||
/*4736*/ int32 platinum_bank; // Platinum Pieces in Bank
|
||||
/*4740*/ int32 gold_bank; // Gold Pieces in Bank
|
||||
/*4744*/ int32 silver_bank; // Silver Pieces in Bank
|
||||
/*4748*/ int32 copper_bank; // Copper Pieces in Bank
|
||||
/*4752*/ int32 platinum_cursor; // Platinum on cursor
|
||||
/*4756*/ int32 gold_cursor; // Gold on cursor
|
||||
/*4760*/ int32 silver_cursor; // Silver on cursor
|
||||
/*4764*/ int32 copper_cursor; // Copper on cursor
|
||||
/*4768*/ int32 platinum_shared; // Platinum shared between characters
|
||||
/*4772*/ uint8 unknown4808[24];
|
||||
/*4796*/ uint32 skills[MAX_PP_SKILL]; // [400] List of skills // 100 dword buffer
|
||||
/*5196*/ uint8 unknown5132[184];
|
||||
/*5380*/ uint32 pvp2; //
|
||||
/*5384*/ uint32 unknown5420; //
|
||||
/*5388*/ uint32 pvptype; //
|
||||
/*5392*/ uint32 unknown5428; //
|
||||
/*5396*/ uint32 ability_down; // Guessing
|
||||
/*5400*/ uint8 unknown5436[8]; //
|
||||
/*5408*/ uint32 autosplit; //not used right now
|
||||
/*5412*/ uint8 unknown5448[8];
|
||||
/*5420*/ uint32 zone_change_count; // Number of times user has zoned in their career (guessing)
|
||||
/*5424*/ uint8 unknown5460[16]; //
|
||||
/*5440*/ uint32 drakkin_heritage; //
|
||||
/*5444*/ uint32 drakkin_tattoo; //
|
||||
/*5448*/ uint32 drakkin_details; //
|
||||
/*5452*/ uint32 expansions; // expansion setting, bit field of expansions avaliable
|
||||
/*5456*/ int32 toxicity; //from drinking potions, seems to increase by 3 each time you drink
|
||||
/*5460*/ char unknown5496[16]; //
|
||||
/*5476*/ int32 hunger_level;
|
||||
/*5480*/ int32 thirst_level;
|
||||
/*5484*/ uint32 ability_up;
|
||||
/*5488*/ char unknown5524[16];
|
||||
/*5504*/ uint16 zone_id; // Current zone of the player
|
||||
/*5506*/ uint16 zoneInstance; // Instance ID
|
||||
/*5508*/ Convert::SpellBuff_Struct buffs[BUFF_COUNT]; // Buffs currently on the player
|
||||
/*6008*/ char groupMembers[6][64];//
|
||||
/*6392*/ char unknown6428[656];
|
||||
/*7048*/ uint32 entityid;
|
||||
/*7052*/ uint32 leadAAActive;
|
||||
/*7056*/ uint32 unknown7092;
|
||||
/*7060*/ int32 ldon_points_guk; //client uses these as signed
|
||||
/*7064*/ int32 ldon_points_mir;
|
||||
/*7068*/ int32 ldon_points_mmc;
|
||||
/*7072*/ int32 ldon_points_ruj;
|
||||
/*7076*/ int32 ldon_points_tak;
|
||||
/*7080*/ int32 ldon_points_available;
|
||||
/*7084*/ int32 ldon_wins_guk;
|
||||
/*7088*/ int32 ldon_wins_mir;
|
||||
/*7092*/ int32 ldon_wins_mmc;
|
||||
/*7096*/ int32 ldon_wins_ruj;
|
||||
/*7100*/ int32 ldon_wins_tak;
|
||||
/*7104*/ int32 ldon_losses_guk;
|
||||
/*7108*/ int32 ldon_losses_mir;
|
||||
/*7112*/ int32 ldon_losses_mmc;
|
||||
/*7116*/ int32 ldon_losses_ruj;
|
||||
/*7120*/ int32 ldon_losses_tak;
|
||||
/*7124*/ uint8 unknown7160[72];
|
||||
/*7196*/ uint32 tribute_time_remaining; //in miliseconds
|
||||
/*7200*/ uint32 showhelm;
|
||||
/*7204*/ uint32 career_tribute_points;
|
||||
/*7208*/ uint32 unknown7244;
|
||||
/*7212*/ uint32 tribute_points;
|
||||
/*7216*/ uint32 unknown7252;
|
||||
/*7220*/ uint32 tribute_active; //1=active
|
||||
/*7224*/ Convert::Tribute_Struct tributes[EmuConstants::TRIBUTE_SIZE];
|
||||
/*7264*/ Convert::Disciplines_Struct disciplines;
|
||||
/*7664*/ uint32 recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use)
|
||||
/*7744*/ char unknown7780[160];
|
||||
/*7904*/ uint32 endurance;
|
||||
/*7908*/ uint32 group_leadership_exp; //0-1000
|
||||
/*7912*/ uint32 raid_leadership_exp; //0-2000
|
||||
/*7916*/ uint32 group_leadership_points;
|
||||
/*7920*/ uint32 raid_leadership_points;
|
||||
/*7924*/ Convert::LeadershipAA_Struct leader_abilities;
|
||||
/*8052*/ uint8 unknown8088[132];
|
||||
/*8184*/ uint32 air_remaining;
|
||||
/*8188*/ uint32 PVPKills;
|
||||
/*8192*/ uint32 PVPDeaths;
|
||||
/*8196*/ uint32 PVPCurrentPoints;
|
||||
/*8200*/ uint32 PVPCareerPoints;
|
||||
/*8204*/ uint32 PVPBestKillStreak;
|
||||
/*8208*/ uint32 PVPWorstDeathStreak;
|
||||
/*8212*/ uint32 PVPCurrentKillStreak;
|
||||
/*8216*/ Convert::PVPStatsEntry_Struct PVPLastKill;
|
||||
/*8304*/ Convert::PVPStatsEntry_Struct PVPLastDeath;
|
||||
/*8392*/ uint32 PVPNumberOfKillsInLast24Hours;
|
||||
/*8396*/ Convert::PVPStatsEntry_Struct PVPRecentKills[50];
|
||||
/*12796*/ uint32 aapoints_spent;
|
||||
/*12800*/ uint32 expAA;
|
||||
/*12804*/ uint32 aapoints; //avaliable, unspent
|
||||
/*12808*/ uint8 unknown12844[36];
|
||||
/*12844*/ Convert::Bandolier_Struct bandoliers[EmuConstants::BANDOLIERS_COUNT];
|
||||
/*14124*/ uint8 unknown14160[4506];
|
||||
/*18630*/ Convert::SuspendedMinion_Struct SuspendedMinion; // No longer in use
|
||||
/*19240*/ uint32 timeentitledonaccount;
|
||||
/*19244*/ Convert::PotionBelt_Struct potionbelt; //there should be 3 more of these
|
||||
/*19532*/ uint8 unknown19568[8];
|
||||
/*19540*/ uint32 currentRadCrystals; // Current count of radiant crystals
|
||||
/*19544*/ uint32 careerRadCrystals; // Total count of radiant crystals ever
|
||||
/*19548*/ uint32 currentEbonCrystals;// Current count of ebon crystals
|
||||
/*19552*/ uint32 careerEbonCrystals; // Total count of ebon crystals ever
|
||||
/*19556*/ uint8 groupAutoconsent; // 0=off, 1=on
|
||||
/*19557*/ uint8 raidAutoconsent; // 0=off, 1=on
|
||||
/*19558*/ uint8 guildAutoconsent; // 0=off, 1=on
|
||||
/*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005)
|
||||
/*19564*/ uint32 RestTimer;
|
||||
/*19568*/
|
||||
};
|
||||
|
||||
|
||||
namespace player_lootitem_temp
|
||||
{
|
||||
struct ServerLootItem_Struct_temp {
|
||||
uint32 item_id;
|
||||
int16 equipSlot;
|
||||
uint8 charges;
|
||||
uint16 lootslot;
|
||||
uint32 aug1;
|
||||
uint32 aug2;
|
||||
uint32 aug3;
|
||||
uint32 aug4;
|
||||
uint32 aug5;
|
||||
};
|
||||
}
|
||||
|
||||
struct DBPlayerCorpse_Struct_temp {
|
||||
uint32 crc;
|
||||
bool locked;
|
||||
uint32 itemcount;
|
||||
uint32 exp;
|
||||
float size;
|
||||
uint8 level;
|
||||
uint8 race;
|
||||
uint8 gender;
|
||||
uint8 class_;
|
||||
uint8 deity;
|
||||
uint8 texture;
|
||||
uint8 helmtexture;
|
||||
uint32 copper;
|
||||
uint32 silver;
|
||||
uint32 gold;
|
||||
uint32 plat;
|
||||
Color_Struct item_tint[9];
|
||||
uint8 haircolor;
|
||||
uint8 beardcolor;
|
||||
uint8 eyecolor1;
|
||||
uint8 eyecolor2;
|
||||
uint8 hairstyle;
|
||||
uint8 face;
|
||||
uint8 beard;
|
||||
uint32 drakkin_heritage;
|
||||
uint32 drakkin_tattoo;
|
||||
uint32 drakkin_details;
|
||||
player_lootitem_temp::ServerLootItem_Struct_temp items[0];
|
||||
};
|
||||
|
||||
namespace classic_db_temp {
|
||||
struct DBPlayerCorpse_Struct_temp {
|
||||
uint32 crc;
|
||||
bool locked;
|
||||
uint32 itemcount;
|
||||
uint32 exp;
|
||||
float size;
|
||||
uint8 level;
|
||||
uint8 race;
|
||||
uint8 gender;
|
||||
uint8 class_;
|
||||
uint8 deity;
|
||||
uint8 texture;
|
||||
uint8 helmtexture;
|
||||
uint32 copper;
|
||||
uint32 silver;
|
||||
uint32 gold;
|
||||
uint32 plat;
|
||||
Color_Struct item_tint[9];
|
||||
uint8 haircolor;
|
||||
uint8 beardcolor;
|
||||
uint8 eyecolor1;
|
||||
uint8 eyecolor2;
|
||||
uint8 hairstyle;
|
||||
uint8 face;
|
||||
uint8 beard;
|
||||
player_lootitem_temp::ServerLootItem_Struct_temp items[0];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#pragma pack()
|
||||
|
||||
class Database : public DBcore {
|
||||
public:
|
||||
Database();
|
||||
@ -106,9 +500,14 @@ public:
|
||||
bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
~Database();
|
||||
|
||||
|
||||
/*
|
||||
* General Character Related Stuff
|
||||
*/
|
||||
|
||||
/* Character Creation */
|
||||
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
|
||||
|
||||
bool MoveCharacterToZone(const char* charname, const char* zonename);
|
||||
bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid);
|
||||
bool MoveCharacterToZone(uint32 iCharID, const char* iZonename);
|
||||
@ -118,9 +517,8 @@ public:
|
||||
bool AddToNameFilter(const char* name);
|
||||
bool ReserveName(uint32 account_id, char* name);
|
||||
bool CreateCharacter(uint32 account_id, char* name, uint16 gender, uint16 race, uint16 class_, uint8 str, uint8 sta, uint8 cha, uint8 dex, uint8 int_, uint8 agi, uint8 wis, uint8 face);
|
||||
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv, ExtendedProfile_Struct *ext);
|
||||
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
|
||||
bool DeleteCharacter(char* name);
|
||||
uint8 CopyCharacter(const char* oldname, const char* newname, uint32 acctid);
|
||||
|
||||
/*
|
||||
* General Information Getting Queries
|
||||
@ -175,8 +573,7 @@ public:
|
||||
* Adventure related.
|
||||
*/
|
||||
void UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win);
|
||||
bool GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, uint32 &mmc_w, uint32 &ruj_w, uint32 &tak_w,
|
||||
uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l);
|
||||
bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
|
||||
|
||||
/*
|
||||
* Account Related
|
||||
@ -205,7 +602,7 @@ public:
|
||||
|
||||
void SetGroupLeaderName(uint32 gid, const char* name);
|
||||
char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr,
|
||||
GroupLeadershipAA_Struct* GLAA = nullptr);
|
||||
char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
|
||||
void ClearGroupLeader(uint32 gid = 0);
|
||||
|
||||
|
||||
@ -216,6 +613,18 @@ public:
|
||||
void ClearRaidDetails(uint32 rid = 0);
|
||||
uint32 GetRaidID(const char* name);
|
||||
const char *GetRaidLeaderName(uint32 rid);
|
||||
void GetGroupLeadershipInfo(uint32 gid, uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr,
|
||||
char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr);
|
||||
void GetRaidLeadershipInfo(uint32 rid, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr,
|
||||
RaidLeadershipAA_Struct* RLAA = nullptr);
|
||||
void SetRaidGroupLeaderInfo(uint32 gid, uint32 rid);
|
||||
void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0);
|
||||
|
||||
/* Database Conversions*/
|
||||
bool CheckDatabaseConversions();
|
||||
bool CheckDatabaseConvertPPDeblob();
|
||||
bool CheckDatabaseConvertCorpseDeblob();
|
||||
bool CheckDatabaseConvertBotsPostPPDeblob();
|
||||
|
||||
/*
|
||||
* Database Variables
|
||||
@ -250,10 +659,6 @@ public:
|
||||
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
|
||||
void AddReport(std::string who, std::string against, std::string lines);
|
||||
|
||||
|
||||
protected:
|
||||
void HandleMysqlError(uint32 errnum);
|
||||
|
||||
private:
|
||||
void DBInitVars();
|
||||
|
||||
@ -277,6 +682,7 @@ private:
|
||||
*/
|
||||
void ClearAllRaids();
|
||||
void ClearAllRaidDetails();
|
||||
void ClearAllRaidLeaders();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,669 +0,0 @@
|
||||
#include "debug.h"
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include "dbasync.h"
|
||||
#include "database.h"
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <limits.h>
|
||||
#include "dbcore.h"
|
||||
#include <string.h>
|
||||
//#include "../common/MiscFunctions.h"
|
||||
#include "StringUtil.h"
|
||||
#define ASYNC_LOOP_GRANULARITY 4 //# of ms between checking our work
|
||||
|
||||
bool DBAsyncCB_LoadVariables(DBAsyncWork* iWork) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
MYSQL_RES* result = 0;
|
||||
DBAsyncQuery* dbaq = iWork->PopAnswer();
|
||||
if (dbaq->GetAnswer(errbuf, &result))
|
||||
iWork->GetDB()->LoadVariables_result(result);
|
||||
else
|
||||
std::cout << "Error: DBAsyncCB_LoadVariables failed: !GetAnswer: '" << errbuf << "'" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AsyncLoadVariables(DBAsync *dba, Database *db) {
|
||||
char* query = 0;
|
||||
DBAsyncWork* dbaw = new DBAsyncWork(db, &DBAsyncCB_LoadVariables, 0, DBAsync::Read);
|
||||
dbaw->AddQuery(0, &query, db->LoadVariables_MQ(&query));
|
||||
dba->AddWork(&dbaw);
|
||||
}
|
||||
|
||||
|
||||
//we only need to do anything when somebody puts work on the queue
|
||||
//so instead of checking all the time, we will wait on a condition
|
||||
//which will get signaled when somebody puts something on the queue
|
||||
ThreadReturnType DBAsyncLoop(void* tmp) {
|
||||
DBAsync* dba = (DBAsync*) tmp;
|
||||
|
||||
#ifndef WIN32
|
||||
_log(COMMON__THREADS, "Starting DBAsyncLoop with thread ID %d", pthread_self());
|
||||
#endif
|
||||
|
||||
dba->MLoopRunning.lock();
|
||||
while (dba->RunLoop()) {
|
||||
//wait before working so we check the loop condition
|
||||
//as soon as were done working
|
||||
dba->CInList.Wait();
|
||||
//we could check dba->RunLoop() again to see if we
|
||||
//got turned off while we were waiting
|
||||
{
|
||||
dba->Process();
|
||||
}
|
||||
}
|
||||
dba->MLoopRunning.unlock();
|
||||
|
||||
#ifndef WIN32
|
||||
_log(COMMON__THREADS, "Ending DBAsyncLoop with thread ID %d", pthread_self());
|
||||
#endif
|
||||
|
||||
THREAD_RETURN(nullptr);
|
||||
}
|
||||
|
||||
DBAsync::DBAsync(DBcore* iDBC)
|
||||
: Timeoutable(10000)
|
||||
{
|
||||
pDBC = iDBC;
|
||||
pRunLoop = true;
|
||||
pNextID = 1;
|
||||
#ifdef _WINDOWS
|
||||
_beginthread(DBAsyncLoop, 0, this);
|
||||
#else
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, DBAsyncLoop, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
DBAsync::~DBAsync() {
|
||||
StopThread();
|
||||
}
|
||||
|
||||
bool DBAsync::StopThread() {
|
||||
bool ret;
|
||||
MRunLoop.lock();
|
||||
ret = pRunLoop;
|
||||
pRunLoop = false;
|
||||
MRunLoop.unlock();
|
||||
|
||||
//signal the condition so we exit the loop if were waiting
|
||||
CInList.Signal();
|
||||
|
||||
//this effectively waits for the processing thread to finish
|
||||
MLoopRunning.lock();
|
||||
MLoopRunning.unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 DBAsync::AddWork(DBAsyncWork** iWork, uint32 iDelay) {
|
||||
MInList.lock();
|
||||
uint32 ret = GetNextID();
|
||||
if (!(*iWork)->SetWorkID(ret)) {
|
||||
MInList.unlock();
|
||||
return 0;
|
||||
}
|
||||
InList.Append(*iWork);
|
||||
(*iWork)->SetStatus(Queued);
|
||||
if (iDelay)
|
||||
(*iWork)->pExecuteAfter = Timer::GetCurrentTime() + iDelay;
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "Adding AsyncWork #" << (*iWork)->GetWorkID() << std::endl;
|
||||
std::cout << "ExecuteAfter = " << (*iWork)->pExecuteAfter << " (" << Timer::GetCurrentTime() << " + " << iDelay << ")" << std::endl;
|
||||
#endif
|
||||
*iWork = 0;
|
||||
MInList.unlock();
|
||||
|
||||
//wake up the processing thread and tell it to get to work.
|
||||
CInList.Signal();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsync::CancelWork(uint32 iWorkID) {
|
||||
if (iWorkID == 0)
|
||||
return false;
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "DBAsync::CancelWork: " << iWorkID << std::endl;
|
||||
#endif
|
||||
MCurrentWork.lock();
|
||||
if (CurrentWork && CurrentWork->GetWorkID() == iWorkID) {
|
||||
CurrentWork->Cancel();
|
||||
MCurrentWork.unlock();
|
||||
return true;
|
||||
}
|
||||
MCurrentWork.unlock();
|
||||
MInList.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(InList);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->GetWorkID() == iWorkID) {
|
||||
iterator.RemoveCurrent(true);
|
||||
MInList.unlock();
|
||||
return true;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MInList.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DBAsync::RunLoop() {
|
||||
bool ret;
|
||||
MRunLoop.lock();
|
||||
ret = pRunLoop;
|
||||
MRunLoop.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsync::InListPop() {
|
||||
DBAsyncWork* ret = 0;
|
||||
MInList.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(InList);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->pExecuteAfter <= Timer::GetCurrentTime()) {
|
||||
ret = iterator.GetData();
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "Poping AsyncWork #" << ret->GetWorkID() << std::endl;
|
||||
std::cout << ret->pExecuteAfter << " <= " << Timer::GetCurrentTime() << std::endl;
|
||||
#endif
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MInList.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsync::InListPopWrite() {
|
||||
MInList.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(InList);
|
||||
|
||||
DBAsyncWork* ret = 0;
|
||||
DBAsync::Type tmpType;
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
tmpType = iterator.GetData()->Type();
|
||||
if (tmpType == Write || tmpType == Both) {
|
||||
ret = iterator.GetData();
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MInList.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBAsync::AddFQ(DBAsyncFinishedQueue* iDBAFQ) {
|
||||
MFQList.lock();
|
||||
DBAsyncFinishedQueue** tmp = new DBAsyncFinishedQueue*;
|
||||
*tmp = iDBAFQ;
|
||||
FQList.Append(tmp);
|
||||
MFQList.unlock();
|
||||
}
|
||||
|
||||
void DBAsync::Process() {
|
||||
DBAsyncWork* tmpWork;
|
||||
MCurrentWork.lock();
|
||||
while ((CurrentWork = InListPop())) {
|
||||
MCurrentWork.unlock();
|
||||
//move from queued to executing
|
||||
Status tmpStatus = CurrentWork->SetStatus(Executing);
|
||||
if (tmpStatus == Queued) {
|
||||
//execute the work
|
||||
ProcessWork(CurrentWork);
|
||||
tmpWork = CurrentWork;
|
||||
MCurrentWork.lock();
|
||||
CurrentWork = 0;
|
||||
MCurrentWork.unlock();
|
||||
//move from executing to finished
|
||||
tmpStatus = tmpWork->SetStatus(DBAsync::Finished);
|
||||
if (tmpStatus != Executing) {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #1" << std::endl;
|
||||
}
|
||||
MCurrentWork.lock();
|
||||
safe_delete(tmpWork);
|
||||
}
|
||||
else {
|
||||
//call callbacks or put results on finished queue
|
||||
DispatchWork(tmpWork);
|
||||
Sleep(25);
|
||||
MCurrentWork.lock();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::Process #2" << std::endl;
|
||||
}
|
||||
MCurrentWork.lock();
|
||||
safe_delete(CurrentWork);
|
||||
}
|
||||
}
|
||||
MCurrentWork.unlock();
|
||||
}
|
||||
|
||||
void DBAsync::CheckTimeout() {
|
||||
try{
|
||||
MFQList.lock();
|
||||
LinkedListIterator<DBAsyncFinishedQueue**> iterator(FQList);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
(*iterator.GetData())->CheckTimeouts();
|
||||
iterator.Advance();
|
||||
}
|
||||
MFQList.unlock();
|
||||
}
|
||||
catch(...){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DBAsync::CommitWrites() {
|
||||
#if DEBUG_MYSQL_QUERIES >= 2
|
||||
std::cout << "DBAsync::CommitWrites() called." << std::endl;
|
||||
#endif
|
||||
DBAsyncWork* tmpWork;
|
||||
while ((tmpWork = InListPopWrite())) {
|
||||
Status tmpStatus = tmpWork->SetStatus(Executing);
|
||||
if (tmpStatus == Queued) {
|
||||
ProcessWork(tmpWork);
|
||||
tmpStatus = tmpWork->SetStatus(DBAsync::Finished);
|
||||
if (tmpStatus != Executing) {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #1" << std::endl;
|
||||
}
|
||||
safe_delete(tmpWork);
|
||||
}
|
||||
else {
|
||||
DispatchWork(tmpWork);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tmpStatus != Canceled) {
|
||||
std::cout << "Error: Unexpected DBAsyncWork->Status in DBAsync::CommitWrites #2" << std::endl;
|
||||
}
|
||||
safe_delete(tmpWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBAsync::ProcessWork(DBAsyncWork* iWork, bool iSleep) {
|
||||
DBAsyncQuery* CurrentQuery;
|
||||
while ((CurrentQuery = iWork->PopQuery())) {
|
||||
CurrentQuery->Process(pDBC);
|
||||
iWork->PushAnswer(CurrentQuery);
|
||||
if (iSleep)
|
||||
Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DBAsync::DispatchWork(DBAsyncWork* iWork) {
|
||||
//if this work has a callback, call it
|
||||
//otherwise, stick the work on the finish queue
|
||||
if (iWork->pCB) {
|
||||
if (iWork->pCB(iWork))
|
||||
safe_delete(iWork);
|
||||
}
|
||||
else {
|
||||
if (!iWork->pDBAFQ->Push(iWork))
|
||||
safe_delete(iWork);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
DBAsyncFinishedQueue::DBAsyncFinishedQueue(uint32 iTimeout) {
|
||||
pTimeout = iTimeout;
|
||||
}
|
||||
|
||||
DBAsyncFinishedQueue::~DBAsyncFinishedQueue() {
|
||||
}
|
||||
|
||||
void DBAsyncFinishedQueue::CheckTimeouts() {
|
||||
if (pTimeout == 0xFFFFFFFF)
|
||||
return;
|
||||
MLock.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->CheckTimeout(pTimeout))
|
||||
iterator.RemoveCurrent(true);
|
||||
iterator.Advance();
|
||||
}
|
||||
MLock.unlock();
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsyncFinishedQueue::Pop() {
|
||||
DBAsyncWork* ret = 0;
|
||||
MLock.lock();
|
||||
ret = list.Pop();
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsyncFinishedQueue::Find(uint32 iWorkID) {
|
||||
DBAsyncWork* ret = 0;
|
||||
MLock.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->GetWorkID() == iWorkID) {
|
||||
ret = iterator.GetData();
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncWork* DBAsyncFinishedQueue::PopByWPT(uint32 iWPT) {
|
||||
DBAsyncWork* ret = 0;
|
||||
MLock.lock();
|
||||
LinkedListIterator<DBAsyncWork*> iterator(list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
if (iterator.GetData()->WPT() == iWPT) {
|
||||
ret = iterator.GetData();
|
||||
iterator.RemoveCurrent(false);
|
||||
break;
|
||||
}
|
||||
iterator.Advance();
|
||||
}
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncFinishedQueue::Push(DBAsyncWork* iDBAW) {
|
||||
if (!this)
|
||||
return false;
|
||||
MLock.lock();
|
||||
list.Append(iDBAW);
|
||||
MLock.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DBAsyncWork::DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout)
|
||||
: m_db(db)
|
||||
{
|
||||
pstatus = DBAsync::AddingWork;
|
||||
pType = iType;
|
||||
pExecuteAfter = 0;
|
||||
pWorkID = 0;
|
||||
pDBAFQ = iDBAFQ;
|
||||
pCB = 0;
|
||||
pWPT = iWPT;
|
||||
pQuestionCount = 0;
|
||||
pAnswerCount = 0;
|
||||
pTimeout = iTimeout;
|
||||
pTSFinish = 0;
|
||||
}
|
||||
|
||||
DBAsyncWork::DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT, DBAsync::Type iType, uint32 iTimeout)
|
||||
: m_db(db)
|
||||
{
|
||||
pstatus = DBAsync::AddingWork;
|
||||
pType = iType;
|
||||
pExecuteAfter = 0;
|
||||
pWorkID = 0;
|
||||
pDBAFQ = 0;
|
||||
pCB = iCB;
|
||||
pWPT = iWPT;
|
||||
pQuestionCount = 0;
|
||||
pAnswerCount = 0;
|
||||
pTimeout = iTimeout;
|
||||
pTSFinish = 0;
|
||||
}
|
||||
|
||||
DBAsyncWork::~DBAsyncWork() {
|
||||
DBAsyncQuery* dbaq = 0;
|
||||
while ((dbaq = todo.pop()))
|
||||
safe_delete(dbaq);
|
||||
while ((dbaq = done.pop()))
|
||||
safe_delete(dbaq);
|
||||
while ((dbaq = todel.pop()))
|
||||
safe_delete(dbaq);
|
||||
}
|
||||
|
||||
bool DBAsyncWork::AddQuery(DBAsyncQuery** iDBAQ) {
|
||||
bool ret;
|
||||
MLock.lock();
|
||||
if (pstatus != DBAsync::AddingWork)
|
||||
ret = false;
|
||||
else {
|
||||
ret = true;
|
||||
pQuestionCount++;
|
||||
todo.push(*iDBAQ);
|
||||
(*iDBAQ)->pstatus = DBAsync::Queued;
|
||||
*iDBAQ = 0;
|
||||
}
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
|
||||
DBAsyncQuery* DBAQ = new DBAsyncQuery(iQPT, iQuery, iQueryLen, iGetResultSet, iGetErrbuf);
|
||||
if (AddQuery(&DBAQ))
|
||||
return true;
|
||||
else {
|
||||
safe_delete(DBAQ);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DBAsyncWork::SetWorkID(uint32 iWorkID) {
|
||||
bool ret = true;
|
||||
MLock.lock();
|
||||
if (pWorkID)
|
||||
ret = false;
|
||||
else
|
||||
pWorkID = iWorkID;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 DBAsyncWork::GetWorkID() {
|
||||
uint32 ret;
|
||||
MLock.lock();
|
||||
ret = pWorkID;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 DBAsyncWork::WPT() {
|
||||
uint32 ret;
|
||||
MLock.lock();
|
||||
ret = pWPT;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsync::Type DBAsyncWork::Type() {
|
||||
DBAsync::Type ret;
|
||||
MLock.lock();
|
||||
ret = pType;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncQuery* DBAsyncWork::PopAnswer() {
|
||||
DBAsyncQuery* ret;
|
||||
MLock.lock();
|
||||
ret = done.pop();
|
||||
if (ret)
|
||||
pAnswerCount--;
|
||||
todel.push(ret);
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::CheckTimeout(uint32 iFQTimeout) {
|
||||
if (pTimeout == 0xFFFFFFFF)
|
||||
return false;
|
||||
bool ret = false;
|
||||
MLock.lock();
|
||||
if (pTimeout > iFQTimeout)
|
||||
iFQTimeout = pTimeout;
|
||||
if (Timer::GetCurrentTime() > (pTSFinish + iFQTimeout))
|
||||
ret = true;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
//sets the work's status to the supplied value and returns
|
||||
//the revious status
|
||||
DBAsync::Status DBAsyncWork::SetStatus(DBAsync::Status iStatus) {
|
||||
DBAsync::Status ret;
|
||||
MLock.lock();
|
||||
if (iStatus == DBAsync::Finished)
|
||||
pTSFinish = Timer::GetCurrentTime();
|
||||
ret = pstatus;
|
||||
pstatus = iStatus;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::Cancel() {
|
||||
bool ret;
|
||||
MLock.lock();
|
||||
if (pstatus != DBAsync::Finished) {
|
||||
pstatus = DBAsync::Canceled;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
ret = false;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DBAsyncWork::IsCancled() {
|
||||
bool ret;
|
||||
MLock.lock();
|
||||
ret = (bool) (pstatus == DBAsync::Canceled);
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
DBAsyncQuery* DBAsyncWork::PopQuery() {
|
||||
DBAsyncQuery* ret = 0;
|
||||
MLock.lock();
|
||||
ret = todo.pop();
|
||||
if (ret)
|
||||
pQuestionCount--;
|
||||
MLock.unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DBAsyncWork::PushAnswer(DBAsyncQuery* iDBAQ) {
|
||||
MLock.lock();
|
||||
done.push(iDBAQ);
|
||||
pAnswerCount++;
|
||||
MLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
DBAsyncQuery::DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
|
||||
if (iQueryLen == 0xFFFFFFFF)
|
||||
pQueryLen = strlen(*iQuery);
|
||||
else
|
||||
pQueryLen = iQueryLen;
|
||||
pQuery = *iQuery;
|
||||
*iQuery = 0;
|
||||
Init(iQPT, iGetResultSet, iGetErrbuf);
|
||||
}
|
||||
|
||||
DBAsyncQuery::DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen, bool iGetResultSet, bool iGetErrbuf) {
|
||||
if (iQueryLen == 0xFFFFFFFF)
|
||||
pQueryLen = strlen(iQuery);
|
||||
else
|
||||
pQueryLen = iQueryLen;
|
||||
pQuery = strn0cpy(new char[pQueryLen+1], iQuery, pQueryLen+1);
|
||||
Init(iQPT, iGetResultSet, iGetErrbuf);
|
||||
}
|
||||
|
||||
void DBAsyncQuery::Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf) {
|
||||
pstatus = DBAsync::AddingWork;
|
||||
pQPT = iQPT;
|
||||
pGetResultSet = iGetResultSet;
|
||||
pGetErrbuf = iGetErrbuf;
|
||||
|
||||
pmysqlsuccess = false;
|
||||
perrbuf = 0;
|
||||
perrnum = 0;
|
||||
presult = 0;
|
||||
paffected_rows = 0;
|
||||
plast_insert_id = 0;
|
||||
}
|
||||
|
||||
DBAsyncQuery::~DBAsyncQuery() {
|
||||
safe_delete_array(perrbuf);
|
||||
safe_delete_array(pQuery);
|
||||
if (presult)
|
||||
mysql_free_result(presult);
|
||||
}
|
||||
|
||||
bool DBAsyncQuery::GetAnswer(char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum) {
|
||||
if (pstatus != DBAsync::Finished) {
|
||||
if (errbuf)
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error: Query not finished.");
|
||||
if (errnum)
|
||||
*errnum = UINT_MAX;
|
||||
return false;
|
||||
}
|
||||
if (errbuf) {
|
||||
if (pGetErrbuf) {
|
||||
if (perrbuf)
|
||||
strn0cpy(errbuf, perrbuf, MYSQL_ERRMSG_SIZE);
|
||||
else
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message should've been saved, but hasnt. errno: %u", perrnum);
|
||||
}
|
||||
else
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "Error message not saved. errno: %u", perrnum);
|
||||
}
|
||||
if (errnum)
|
||||
*errnum = perrnum;
|
||||
if (affected_rows)
|
||||
*affected_rows = paffected_rows;
|
||||
if (last_insert_id)
|
||||
*last_insert_id = plast_insert_id;
|
||||
if (result)
|
||||
*result = presult;
|
||||
return pmysqlsuccess;
|
||||
}
|
||||
|
||||
void DBAsyncQuery::Process(DBcore* iDBC) {
|
||||
pstatus = DBAsync::Executing;
|
||||
if (pGetErrbuf)
|
||||
perrbuf = new char[MYSQL_ERRMSG_SIZE];
|
||||
MYSQL_RES** resultPP = 0;
|
||||
if (pGetResultSet)
|
||||
resultPP = &presult;
|
||||
pmysqlsuccess = iDBC->RunQuery(pQuery, pQueryLen, perrbuf, resultPP, &paffected_rows, &plast_insert_id, &perrnum);
|
||||
pstatus = DBAsync::Finished;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
176
common/dbasync.h
176
common/dbasync.h
@ -1,176 +0,0 @@
|
||||
#ifndef DBASYNC_H
|
||||
#define DBASYNC_H
|
||||
#include "../common/dbcore.h"
|
||||
#include "../common/timeoutmgr.h"
|
||||
|
||||
|
||||
class DBAsyncFinishedQueue;
|
||||
class DBAsyncWork;
|
||||
class DBAsyncQuery;
|
||||
class Database;
|
||||
|
||||
// Big daddy that owns the threads and does the work
|
||||
class DBAsync : private Timeoutable {
|
||||
public:
|
||||
enum Status { AddingWork, Queued, Executing, Finished, Canceled };
|
||||
enum Type { Read, Write, Both };
|
||||
|
||||
DBAsync(DBcore* iDBC);
|
||||
~DBAsync();
|
||||
bool StopThread();
|
||||
|
||||
uint32 AddWork(DBAsyncWork** iWork, uint32 iDelay = 0);
|
||||
bool CancelWork(uint32 iWorkID);
|
||||
void CommitWrites();
|
||||
|
||||
void AddFQ(DBAsyncFinishedQueue* iDBAFQ);
|
||||
protected:
|
||||
//things related to the processing thread:
|
||||
friend ThreadReturnType DBAsyncLoop(void* tmp);
|
||||
Mutex MLoopRunning;
|
||||
Condition CInList;
|
||||
bool RunLoop();
|
||||
void Process();
|
||||
|
||||
private:
|
||||
virtual void CheckTimeout();
|
||||
|
||||
void ProcessWork(DBAsyncWork* iWork, bool iSleep = true);
|
||||
void DispatchWork(DBAsyncWork* iWork);
|
||||
inline uint32 GetNextID() { return pNextID++; }
|
||||
DBAsyncWork* InListPop();
|
||||
DBAsyncWork* InListPopWrite(); // Ignores delay
|
||||
void OutListPush(DBAsyncWork* iDBAW);
|
||||
|
||||
Mutex MRunLoop;
|
||||
bool pRunLoop;
|
||||
|
||||
DBcore* pDBC;
|
||||
uint32 pNextID;
|
||||
Mutex MInList;
|
||||
LinkedList<DBAsyncWork*> InList;
|
||||
|
||||
Mutex MFQList;
|
||||
LinkedList<DBAsyncFinishedQueue**> FQList;
|
||||
|
||||
// Mutex for outside access to current work & when current work is being changed.
|
||||
// NOT locked when CurrentWork is being accessed by the DBAsync thread.
|
||||
// Never change pointer from outside DBAsync thread!
|
||||
// Only here for access to thread-safe DBAsyncWork functions.
|
||||
Mutex MCurrentWork;
|
||||
DBAsyncWork* CurrentWork;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
DB Work Complete Callback:
|
||||
This will be called under the DBAsync thread! Never access any non-threadsafe
|
||||
data/functions/classes. (ie: zone, entitylist, client, etc are not threadsafe)
|
||||
Function prototype:
|
||||
return value: true if we should delete the data, false if we should keep it
|
||||
*/
|
||||
typedef bool(*DBWorkCompleteCallBack)(DBAsyncWork*);
|
||||
|
||||
class DBAsyncFinishedQueue {
|
||||
public:
|
||||
DBAsyncFinishedQueue(uint32 iTimeout = 90000);
|
||||
~DBAsyncFinishedQueue();
|
||||
|
||||
DBAsyncWork* Pop();
|
||||
DBAsyncWork* PopByWPT(uint32 iWPT);
|
||||
DBAsyncWork* Find(uint32 iWPT);
|
||||
bool Push(DBAsyncWork* iDBAW);
|
||||
|
||||
void CheckTimeouts();
|
||||
private:
|
||||
Mutex MLock;
|
||||
uint32 pTimeout;
|
||||
LinkedList<DBAsyncWork*> list;
|
||||
};
|
||||
|
||||
// Container class for multiple queries
|
||||
class DBAsyncWork {
|
||||
public:
|
||||
DBAsyncWork(Database *db, DBAsyncFinishedQueue* iDBAFQ, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0);
|
||||
DBAsyncWork(Database *db, DBWorkCompleteCallBack iCB, uint32 iWPT = 0, DBAsync::Type iType = DBAsync::Both, uint32 iTimeout = 0);
|
||||
~DBAsyncWork();
|
||||
|
||||
bool AddQuery(DBAsyncQuery** iDBAQ);
|
||||
bool AddQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
|
||||
uint32 WPT();
|
||||
DBAsync::Type Type();
|
||||
|
||||
// Pops finished queries off the work
|
||||
DBAsyncQuery* PopAnswer();
|
||||
uint32 QueryCount();
|
||||
|
||||
Database *GetDB() const { return(m_db); }
|
||||
|
||||
bool CheckTimeout(uint32 iFQTimeout);
|
||||
bool SetWorkID(uint32 iWorkID);
|
||||
uint32 GetWorkID();
|
||||
protected:
|
||||
friend class DBAsync;
|
||||
DBAsync::Status SetStatus(DBAsync::Status iStatus);
|
||||
bool Cancel();
|
||||
bool IsCancled();
|
||||
DBAsyncQuery* PopQuery(); // Get query to be run
|
||||
void PushAnswer(DBAsyncQuery* iDBAQ); // Push answer back into workset
|
||||
|
||||
// not mutex'd cause only to be accessed from dbasync class
|
||||
uint32 pExecuteAfter;
|
||||
private:
|
||||
Mutex MLock;
|
||||
uint32 pQuestionCount;
|
||||
uint32 pAnswerCount;
|
||||
uint32 pWorkID;
|
||||
uint32 pWPT;
|
||||
uint32 pTimeout;
|
||||
uint32 pTSFinish; // timestamp when finished
|
||||
DBAsyncFinishedQueue* pDBAFQ; //we do now own this pointer
|
||||
DBWorkCompleteCallBack pCB;
|
||||
DBAsync::Status pstatus;
|
||||
DBAsync::Type pType;
|
||||
MyQueue<DBAsyncQuery> todo;
|
||||
MyQueue<DBAsyncQuery> done;
|
||||
MyQueue<DBAsyncQuery> todel;
|
||||
Database *const m_db; //we do now own this pointer
|
||||
};
|
||||
|
||||
// Container class for the query information
|
||||
class DBAsyncQuery {
|
||||
public:
|
||||
DBAsyncQuery(uint32 iQPT, char** iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
|
||||
DBAsyncQuery(uint32 iQPT, const char* iQuery, uint32 iQueryLen = 0xFFFFFFFF, bool iGetResultSet = true, bool iGetErrbuf = true);
|
||||
~DBAsyncQuery();
|
||||
|
||||
bool GetAnswer(char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0);
|
||||
inline uint32 QPT() { return pQPT; }
|
||||
protected:
|
||||
friend class DBAsyncWork;
|
||||
uint32 pQPT;
|
||||
|
||||
friend class DBAsync;
|
||||
void Process(DBcore* iDBC);
|
||||
|
||||
void Init(uint32 iQPT, bool iGetResultSet, bool iGetErrbuf);
|
||||
DBAsync::Status pstatus;
|
||||
char* pQuery;
|
||||
uint32 pQueryLen;
|
||||
bool pGetResultSet;
|
||||
bool pGetErrbuf;
|
||||
|
||||
bool pmysqlsuccess;
|
||||
char* perrbuf;
|
||||
uint32 perrnum;
|
||||
uint32 paffected_rows;
|
||||
uint32 plast_insert_id;
|
||||
MYSQL_RES* presult;
|
||||
};
|
||||
|
||||
|
||||
void AsyncLoadVariables(DBAsync *dba, Database *db);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -4,13 +4,14 @@
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <limits.h>
|
||||
#include "dbcore.h"
|
||||
#include <string.h>
|
||||
#include "../common/MiscFunctions.h"
|
||||
#include "../common/misc_functions.h"
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
@ -113,6 +114,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
#ifdef _EQDEBUG
|
||||
std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl;
|
||||
#endif
|
||||
|
||||
/* Implement Logging at the Root */
|
||||
if (mysql_errno(&mysql) > 0 && strlen(query) > 0){
|
||||
std::cout << "\n[MYSQL ERR] " << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << " [Query]: \n" << query << "\n" << std::endl;
|
||||
/* Write to log file */
|
||||
std::ofstream log("eqemu_query_error_log.txt", std::ios_base::app | std::ios_base::out);
|
||||
log << "[MYSQL ERR] " << mysql_error(&mysql) << "\n" << query << "\n";
|
||||
log.close();
|
||||
}
|
||||
|
||||
return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer);
|
||||
|
||||
}
|
||||
@ -126,7 +137,6 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
|
||||
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
|
||||
|
||||
|
||||
#if DEBUG_MYSQL_QUERIES >= 1
|
||||
if (requestResult.Success())
|
||||
{
|
||||
@ -145,93 +155,16 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
|
||||
return requestResult;
|
||||
}
|
||||
|
||||
bool DBcore::RunQuery(const char* query, uint32 querylen, char* errbuf, MYSQL_RES** result, uint32* affected_rows, uint32* last_insert_id, uint32* errnum, bool retry) {
|
||||
if (errnum)
|
||||
*errnum = 0;
|
||||
if (errbuf)
|
||||
errbuf[0] = 0;
|
||||
bool ret = false;
|
||||
LockMutex lock(&MDatabase);
|
||||
if (pStatus != Connected)
|
||||
Open();
|
||||
void DBcore::TransactionBegin() {
|
||||
QueryDatabase("START TRANSACTION");
|
||||
}
|
||||
|
||||
if (mysql_real_query(&mysql, query, querylen)) {
|
||||
if (mysql_errno(&mysql) == CR_SERVER_GONE_ERROR)
|
||||
pStatus = Error;
|
||||
if (mysql_errno(&mysql) == CR_SERVER_LOST || mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) {
|
||||
if (retry) {
|
||||
std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl;
|
||||
ret = RunQuery(query, querylen, errbuf, result, affected_rows, last_insert_id, errnum, false);
|
||||
if (ret)
|
||||
std::cout << "Reconnection to database successful." << std::endl;
|
||||
}
|
||||
else {
|
||||
pStatus = Error;
|
||||
if (errnum)
|
||||
*errnum = mysql_errno(&mysql);
|
||||
if (errbuf)
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||
std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl;
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (errnum)
|
||||
*errnum = mysql_errno(&mysql);
|
||||
if (errbuf)
|
||||
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
|
||||
#ifdef _EQDEBUG
|
||||
std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl;
|
||||
#endif
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (result && mysql_field_count(&mysql)) {
|
||||
*result = mysql_store_result(&mysql);
|
||||
#ifdef _EQDEBUG
|
||||
DBMemLeak::Alloc(*result, query);
|
||||
#endif
|
||||
}
|
||||
else if (result)
|
||||
*result = 0;
|
||||
if (affected_rows)
|
||||
*affected_rows = mysql_affected_rows(&mysql);
|
||||
if (last_insert_id)
|
||||
*last_insert_id = (uint32)mysql_insert_id(&mysql);
|
||||
if (result) {
|
||||
if (*result) {
|
||||
ret = true;
|
||||
}
|
||||
else {
|
||||
#ifdef _EQDEBUG
|
||||
std::cout << "DB Query Error: No Result" << std::endl;
|
||||
#endif
|
||||
if (errnum)
|
||||
*errnum = UINT_MAX;
|
||||
if (errbuf)
|
||||
strcpy(errbuf, "DBcore::RunQuery: No Result");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
#if DEBUG_MYSQL_QUERIES >= 1
|
||||
if (ret) {
|
||||
std::cout << "query successful";
|
||||
if (result && (*result))
|
||||
std::cout << ", " << (int) mysql_num_rows(*result) << " rows returned";
|
||||
if (affected_rows)
|
||||
std::cout << ", " << (*affected_rows) << " rows affected";
|
||||
std::cout<< std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "QUERY: query FAILED" << std::endl;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
void DBcore::TransactionCommit() {
|
||||
QueryDatabase("COMMIT");
|
||||
}
|
||||
|
||||
void DBcore::TransactionRollback() {
|
||||
QueryDatabase("ROLLBACK");
|
||||
}
|
||||
|
||||
uint32 DBcore::DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen) {
|
||||
|
||||
@ -9,12 +9,12 @@
|
||||
#include <mysql.h>
|
||||
#include <string.h>
|
||||
#include "../common/types.h"
|
||||
#include "../common/Mutex.h"
|
||||
#include "../common/mutex.h"
|
||||
#include "../common/linked_list.h"
|
||||
#include "../common/queue.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/Condition.h"
|
||||
#include "../common/MySQLRequestResult.h"
|
||||
#include "../common/condition.h"
|
||||
#include "../common/mysql_request_result.h"
|
||||
|
||||
class DBcore {
|
||||
public:
|
||||
@ -23,9 +23,11 @@ public:
|
||||
DBcore();
|
||||
~DBcore();
|
||||
eStatus GetStatus() { return pStatus; }
|
||||
bool RunQuery(const char* query, uint32 querylen, char* errbuf = 0, MYSQL_RES** result = 0, uint32* affected_rows = 0, uint32* last_insert_id = 0, uint32* errnum = 0, bool retry = true);
|
||||
MySQLRequestResult QueryDatabase(const char* query, uint32 querylen, bool retryOnFailureOnce = true);
|
||||
MySQLRequestResult QueryDatabase(std::string query, bool retryOnFailureOnce = true);
|
||||
void TransactionBegin();
|
||||
void TransactionCommit();
|
||||
void TransactionRollback();
|
||||
uint32 DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen);
|
||||
void ping();
|
||||
MYSQL* getMySQL(){ return &mysql; }
|
||||
|
||||
@ -19,8 +19,8 @@
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "StringUtil.h"
|
||||
#include "MiscFunctions.h"
|
||||
#include "string_util.h"
|
||||
#include "misc_functions.h"
|
||||
#include "platform.h"
|
||||
|
||||
#ifndef va_copy
|
||||
|
||||
@ -69,7 +69,7 @@
|
||||
|
||||
#include "logsys.h"
|
||||
|
||||
#include "../common/Mutex.h"
|
||||
#include "../common/mutex.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@ -80,14 +80,15 @@ public:
|
||||
~EQEMuLog();
|
||||
|
||||
enum LogIDs {
|
||||
Status = 0, //this must stay the first entry in this list
|
||||
Normal,
|
||||
Error,
|
||||
Debug,
|
||||
Quest,
|
||||
Commands,
|
||||
Crash,
|
||||
MaxLogID
|
||||
Status = 0, /* This must stay the first entry in this list */
|
||||
Normal, /* Normal Logs */
|
||||
Error, /* Error Logs */
|
||||
Debug, /* Debug Logs */
|
||||
Quest, /* Quest Logs */
|
||||
Commands, /* Issued Comamnds */
|
||||
Crash, /* Crash Logs */
|
||||
Save, /* Client Saves */
|
||||
MaxLogID /* Max, used in functions to get the max log ID */
|
||||
};
|
||||
|
||||
//these are callbacks called for each
|
||||
@ -113,6 +114,7 @@ private:
|
||||
Mutex MOpen;
|
||||
Mutex MLog[MaxLogID];
|
||||
FILE* fp[MaxLogID];
|
||||
|
||||
/* LogStatus: bitwise variable
|
||||
1 = output to file
|
||||
2 = output to stdout
|
||||
|
||||
1008
common/emu_oplist.h
1008
common/emu_oplist.h
File diff suppressed because it is too large
Load Diff
@ -30,8 +30,8 @@ tremendously.
|
||||
#include <stdio.h>
|
||||
#include <iomanip>
|
||||
|
||||
#include "EmuTCPConnection.h"
|
||||
#include "EmuTCPServer.h"
|
||||
#include "emu_tcp_connection.h"
|
||||
#include "emu_tcp_server.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/packet_dump.h"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#ifndef EmuTCPCONNECTION_H_
|
||||
#define EmuTCPCONNECTION_H_
|
||||
|
||||
#include "TCPConnection.h"
|
||||
#include "tcp_connection.h"
|
||||
#include "timer.h"
|
||||
|
||||
//moved out of TCPConnection:: to be more exportable
|
||||
@ -1,6 +1,6 @@
|
||||
#include "debug.h"
|
||||
#include "EmuTCPServer.h"
|
||||
#include "EmuTCPConnection.h"
|
||||
#include "emu_tcp_server.h"
|
||||
#include "emu_tcp_connection.h"
|
||||
|
||||
EmuTCPServer::EmuTCPServer(uint16 iPort, bool iOldFormat)
|
||||
: TCPServer<EmuTCPConnection>(iPort),
|
||||
@ -1,7 +1,7 @@
|
||||
#ifndef EmuTCPSERVER_H_
|
||||
#define EmuTCPSERVER_H_
|
||||
|
||||
#include "TCPServer.h"
|
||||
#include "tcp_server.h"
|
||||
|
||||
class EmuTCPConnection;
|
||||
struct EmuTCPNetPacket_Struct;
|
||||
@ -968,4 +968,6 @@ namespace legacy {
|
||||
} InventorySlot;
|
||||
}
|
||||
|
||||
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
|
||||
|
||||
#endif
|
||||
|
||||
@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "eq_dictionary.h"
|
||||
#include "StringUtil.h"
|
||||
#include "string_util.h"
|
||||
|
||||
//
|
||||
// class EmuConstants
|
||||
@ -1024,6 +1024,26 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
|
||||
//return local[ValidateMobVersion(version)];
|
||||
}
|
||||
|
||||
bool EQLimits::AllowsClickCastFromBag(uint32 version) {
|
||||
static const bool local[_EmuClientCount] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ Client62::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*Underfoot*/ Underfoot::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*RoF2*/ false,
|
||||
|
||||
/*NPC*/ false,
|
||||
/*Merc*/ false,
|
||||
/*Bot*/ false,
|
||||
/*Pet*/ false
|
||||
};
|
||||
|
||||
return local[ValidateMobVersion(version)];
|
||||
}
|
||||
|
||||
// items
|
||||
uint16 EQLimits::ItemCommonSize(uint32 version) {
|
||||
static const uint16 local[_EmuClientCount] = {
|
||||
|
||||
@ -26,13 +26,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "eq_constants.h"
|
||||
#include "clientversions.h"
|
||||
#include <string>
|
||||
#include "../common/patches/Client62_constants.h"
|
||||
#include "../common/patches/Titanium_constants.h"
|
||||
#include "../common/patches/SoF_constants.h"
|
||||
#include "../common/patches/SoD_constants.h"
|
||||
#include "../common/patches/Underfoot_constants.h"
|
||||
#include "../common/patches/RoF_constants.h"
|
||||
//#include "../common/patches/RoF2_constants.h"
|
||||
#include "../common/patches/client62_constants.h"
|
||||
#include "../common/patches/titanium_constants.h"
|
||||
#include "../common/patches/sof_constants.h"
|
||||
#include "../common/patches/sod_constants.h"
|
||||
#include "../common/patches/underfoot_constants.h"
|
||||
#include "../common/patches/rof_constants.h"
|
||||
//#include "../common/patches/rof2_constants.h"
|
||||
|
||||
// *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! ***
|
||||
// *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! ***
|
||||
@ -184,6 +184,7 @@ public:
|
||||
static uint64 CursorBitmask(uint32 version);
|
||||
|
||||
static bool AllowsEmptyBagInBag(uint32 version);
|
||||
static bool AllowsClickCastFromBag(uint32 version);
|
||||
|
||||
// items
|
||||
static uint16 ItemCommonSize(uint32 version);
|
||||
|
||||
@ -19,10 +19,10 @@
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "EQPacket.h"
|
||||
#include "eq_packet.h"
|
||||
#include "misc.h"
|
||||
#include "op_codes.h"
|
||||
#include "CRC16.h"
|
||||
#include "crc16.h"
|
||||
#include "platform.h"
|
||||
#ifndef STATIC_OPCODE
|
||||
#include "opcodemgr.h"
|
||||
@ -476,7 +476,7 @@ EQRawApplicationPacket::EQRawApplicationPacket(const unsigned char *buf, const u
|
||||
const unsigned char *packet_start = (buf + 3);
|
||||
const int32 packet_length = len - 3;
|
||||
safe_delete_array(pBuffer);
|
||||
if(len >= 0)
|
||||
if(packet_length >= 0)
|
||||
{
|
||||
size = packet_length;
|
||||
pBuffer = new unsigned char[size];
|
||||
@ -18,8 +18,8 @@
|
||||
#ifndef _EQPACKET_H
|
||||
#define _EQPACKET_H
|
||||
|
||||
#include "BasePacket.h"
|
||||
#include "EQStreamType.h"
|
||||
#include "base_packet.h"
|
||||
#include "eq_stream_type.h"
|
||||
#include "op_codes.h"
|
||||
#include "platform.h"
|
||||
|
||||
@ -97,16 +97,15 @@ protected:
|
||||
};
|
||||
|
||||
class EQApplicationPacket : public EQPacket {
|
||||
// friend class EQProtocolPacket;
|
||||
friend class EQStream;
|
||||
public:
|
||||
EQApplicationPacket() : EQPacket(OP_Unknown,nullptr,0)
|
||||
EQApplicationPacket() : EQPacket(OP_Unknown, nullptr, 0), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
EQApplicationPacket(const EmuOpcode op) : EQPacket(op,nullptr,0)
|
||||
EQApplicationPacket(const EmuOpcode op) : EQPacket(op, nullptr, 0), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(op,nullptr,len)
|
||||
EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(op, nullptr, len), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op,buf,len)
|
||||
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op, buf, len), opcode_bypass(0)
|
||||
{ app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; }
|
||||
bool combine(const EQApplicationPacket *rhs);
|
||||
uint32 serialize (uint16 opcode, unsigned char *dest) const;
|
||||
@ -119,12 +118,16 @@ public:
|
||||
virtual void DumpRawHeader(uint16 seq=0xffff, FILE *to = stdout) const;
|
||||
virtual void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const;
|
||||
|
||||
uint16 GetOpcodeBypass() { return opcode_bypass; }
|
||||
void SetOpcodeBypass(uint16 v) { opcode_bypass = v; }
|
||||
|
||||
protected:
|
||||
|
||||
uint8 app_opcode_size;
|
||||
uint16 opcode_bypass;
|
||||
private:
|
||||
|
||||
EQApplicationPacket(const EQApplicationPacket &p) : EQPacket(p.emu_opcode, p.pBuffer, p.size) { app_opcode_size = p.app_opcode_size; }
|
||||
EQApplicationPacket(const EQApplicationPacket &p) : EQPacket(p.emu_opcode, p.pBuffer, p.size), opcode_bypass(p.opcode_bypass) { app_opcode_size = p.app_opcode_size; }
|
||||
|
||||
};
|
||||
|
||||
@ -478,7 +478,11 @@ struct CastSpell_Struct
|
||||
uint32 spell_id;
|
||||
uint32 inventoryslot; // slot for clicky item, 0xFFFF = normal cast
|
||||
uint32 target_id;
|
||||
uint8 cs_unknown[4];
|
||||
uint32 cs_unknown1;
|
||||
uint32 cs_unknown2;
|
||||
float y_pos;
|
||||
float x_pos;
|
||||
float z_pos;
|
||||
};
|
||||
|
||||
struct SpellEffect_Struct
|
||||
@ -534,7 +538,7 @@ struct SpellBuffFade_Struct {
|
||||
/*007*/ uint8 unknown7;
|
||||
/*008*/ uint32 spellid;
|
||||
/*012*/ uint32 duration;
|
||||
/*016*/ uint32 unknown016;
|
||||
/*016*/ uint32 num_hits;
|
||||
/*020*/ uint32 unknown020; //prolly global player ID
|
||||
/*024*/ uint32 slotid;
|
||||
/*028*/ uint32 bufffade;
|
||||
@ -597,8 +601,8 @@ struct GMTrainee_Struct
|
||||
{
|
||||
/*000*/ uint32 npcid;
|
||||
/*004*/ uint32 playerid;
|
||||
/*008*/ uint32 skills[73];
|
||||
/*300*/ uint8 unknown300[148];
|
||||
/*008*/ uint32 skills[PACKET_SKILL_ARRAY_SIZE];
|
||||
/*408*/ uint8 unknown408[40];
|
||||
/*448*/
|
||||
};
|
||||
|
||||
@ -689,7 +693,7 @@ struct CharCreate_Struct
|
||||
/*0076*/ uint32 drakkin_heritage; // added for SoF
|
||||
/*0080*/ uint32 drakkin_tattoo; // added for SoF
|
||||
/*0084*/ uint32 drakkin_details; // added for SoF
|
||||
/*0088*/
|
||||
/*0088*/ uint32 tutorial;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -759,14 +763,62 @@ struct MovePotionToBelt_Struct {
|
||||
static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16;
|
||||
static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY);
|
||||
struct LeadershipAA_Struct {
|
||||
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
struct GroupLeadershipAA_Struct {
|
||||
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
|
||||
union {
|
||||
struct {
|
||||
uint32 groupAAMarkNPC;
|
||||
uint32 groupAANPCHealth;
|
||||
uint32 groupAADelegateMainAssist;
|
||||
uint32 groupAADelegateMarkNPC;
|
||||
uint32 groupAA4;
|
||||
uint32 groupAA5;
|
||||
uint32 groupAAInspectBuffs;
|
||||
uint32 groupAA7;
|
||||
uint32 groupAASpellAwareness;
|
||||
uint32 groupAAOffenseEnhancement;
|
||||
uint32 groupAAManaEnhancement;
|
||||
uint32 groupAAHealthEnhancement;
|
||||
uint32 groupAAHealthRegeneration;
|
||||
uint32 groupAAFindPathToPC;
|
||||
uint32 groupAAHealthOfTargetsTarget;
|
||||
uint32 groupAA15;
|
||||
};
|
||||
uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
};
|
||||
|
||||
struct RaidLeadershipAA_Struct {
|
||||
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
|
||||
union {
|
||||
struct {
|
||||
uint32 raidAAMarkNPC;
|
||||
uint32 raidAANPCHealth;
|
||||
uint32 raidAADelegateMainAssist;
|
||||
uint32 raidAADelegateMarkNPC;
|
||||
uint32 raidAA4;
|
||||
uint32 raidAA5;
|
||||
uint32 raidAA6;
|
||||
uint32 raidAASpellAwareness;
|
||||
uint32 raidAAOffenseEnhancement;
|
||||
uint32 raidAAManaEnhancement;
|
||||
uint32 raidAAHealthEnhancement;
|
||||
uint32 raidAAHealthRegeneration;
|
||||
uint32 raidAAFindPathToPC;
|
||||
uint32 raidAAHealthOfTargetsTarget;
|
||||
uint32 raidAA14;
|
||||
uint32 raidAA15;
|
||||
};
|
||||
uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
};
|
||||
|
||||
struct LeadershipAA_Struct {
|
||||
union {
|
||||
struct {
|
||||
GroupLeadershipAA_Struct group;
|
||||
RaidLeadershipAA_Struct raid;
|
||||
};
|
||||
uint32 ranks[MAX_LEADERSHIP_AA_ARRAY];
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@ -779,17 +831,18 @@ struct BindStruct {
|
||||
/*008*/ float y;
|
||||
/*012*/ float z;
|
||||
/*016*/ float heading;
|
||||
/*020*/
|
||||
/*020*/ uint32 instance_id;
|
||||
/*024*/
|
||||
};
|
||||
|
||||
struct SuspendedMinion_Struct
|
||||
{
|
||||
/*000*/ uint16 SpellID;
|
||||
/*002*/ uint32 HP;
|
||||
/*006*/ uint32 Mana;
|
||||
/*010*/ SpellBuff_Struct Buffs[BUFF_COUNT];
|
||||
/*510*/ uint32 Items[_MaterialCount];
|
||||
/*546*/ char Name[64];
|
||||
/*000*/ uint16 SpellID;
|
||||
/*002*/ uint32 HP;
|
||||
/*006*/ uint32 Mana;
|
||||
/*010*/ SpellBuff_Struct Buffs[BUFF_COUNT];
|
||||
/*510*/ uint32 Items[_MaterialCount];
|
||||
/*546*/ char Name[64];
|
||||
/*610*/
|
||||
};
|
||||
|
||||
@ -800,10 +853,13 @@ struct SuspendedMinion_Struct
|
||||
** Length: 4308 bytes
|
||||
** OpCode: 0x006a
|
||||
*/
|
||||
static const uint32 MAX_PP_LANGUAGE = 28;
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Increased to 480 to support SoF
|
||||
static const uint32 MAX_PP_MEMSPELL = 9;
|
||||
static const uint32 MAX_PP_SKILL = _SkillPacketArraySize; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_LANGUAGE = 28;
|
||||
static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions
|
||||
static const uint32 MAX_PP_MEMSPELL = 9; // Set to latest client so functions can work right
|
||||
static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain
|
||||
static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain
|
||||
|
||||
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
|
||||
static const uint32 MAX_PP_AA_ARRAY = 240;
|
||||
static const uint32 MAX_GROUP_MEMBERS = 6;
|
||||
static const uint32 MAX_RECAST_TYPES = 20;
|
||||
@ -880,7 +936,7 @@ struct PlayerProfile_Struct
|
||||
/*0245*/ uint8 guildbanker;
|
||||
/*0246*/ uint8 unknown0246[6]; //
|
||||
/*0252*/ uint32 intoxication;
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms
|
||||
/*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms
|
||||
/*0292*/ uint32 abilitySlotRefresh;
|
||||
/*0296*/ uint8 haircolor; // Player hair color
|
||||
/*0297*/ uint8 beardcolor; // Player beard color
|
||||
@ -919,9 +975,9 @@ struct PlayerProfile_Struct
|
||||
/*2505*/ uint8 unknown2541[47]; // ?
|
||||
/*2552*/ uint8 languages[MAX_PP_LANGUAGE];
|
||||
/*2580*/ uint8 unknown2616[4];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_SPELLBOOK];
|
||||
/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK];
|
||||
/*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL];
|
||||
/*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL];
|
||||
/*4668*/ uint8 unknown4704[32]; //
|
||||
/*4700*/ float y; // Player y position
|
||||
/*4704*/ float x; // Player x position
|
||||
@ -1446,17 +1502,18 @@ struct BulkItemPacket_Struct
|
||||
|
||||
struct Consume_Struct
|
||||
{
|
||||
/*0000*/ uint32 slot;
|
||||
/*0004*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click
|
||||
/*0008*/ uint8 c_unknown1[4];
|
||||
/*0012*/ uint8 type; // 0x01=Food 0x02=Water
|
||||
/*0013*/ uint8 unknown13[3];
|
||||
/*0000*/ uint32 slot;
|
||||
/*0004*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click
|
||||
/*0008*/ uint8 c_unknown1[4];
|
||||
/*0012*/ uint8 type; // 0x01=Food 0x02=Water
|
||||
/*0013*/ uint8 unknown13[3];
|
||||
};
|
||||
|
||||
struct DeleteItem_Struct {
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
/*0008*/ uint32 number_in_stack;
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
/*0008*/ uint32 number_in_stack;
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
struct MoveItem_Struct
|
||||
@ -1464,16 +1521,18 @@ struct MoveItem_Struct
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
/*0008*/ uint32 number_in_stack;
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
|
||||
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
|
||||
// info at the moment..but, it forwards it on to the server for handling/future use)
|
||||
// info at the moment..but, it is forwarded on to the server for handling/future use)
|
||||
struct ClientTimeStamp_Struct
|
||||
{
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
/*0008*/ uint32 number_in_stack;
|
||||
/*0000*/ uint32 from_slot;
|
||||
/*0004*/ uint32 to_slot;
|
||||
/*0008*/ uint32 number_in_stack;
|
||||
/*0012*/
|
||||
};
|
||||
|
||||
//
|
||||
@ -2177,6 +2236,12 @@ struct GroupLeaderChange_Struct
|
||||
/*128*/ char Unknown128[20];
|
||||
};
|
||||
|
||||
struct GroupMentor_Struct {
|
||||
/*000*/ int percent;
|
||||
/*004*/ char name[64];
|
||||
/*068*/
|
||||
};
|
||||
|
||||
struct FaceChange_Struct {
|
||||
/*000*/ uint8 haircolor;
|
||||
/*001*/ uint8 beardcolor;
|
||||
@ -2287,10 +2352,13 @@ struct Stun_Struct { // 4 bytes total
|
||||
};
|
||||
|
||||
struct AugmentItem_Struct {
|
||||
/*00*/ int16 container_slot;
|
||||
/*02*/ char unknown02[2];
|
||||
/*04*/ int32 augment_slot;
|
||||
/*08*/
|
||||
/*00*/ uint32 container_index;
|
||||
/*04*/ int32 container_slot;
|
||||
/*08*/ uint32 augment_index;
|
||||
/*12*/ int32 augment_slot;
|
||||
/*16*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented
|
||||
/*20*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug
|
||||
/*24*/
|
||||
};
|
||||
|
||||
// OP_Emote
|
||||
@ -2596,6 +2664,17 @@ struct Translocate_Struct {
|
||||
/*088*/ uint32 Complete;
|
||||
};
|
||||
|
||||
struct PendingTranslocate_Struct
|
||||
{
|
||||
uint32 zone_id;
|
||||
uint16 instance_id;
|
||||
float heading;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32 spell_id;
|
||||
};
|
||||
|
||||
struct Sacrifice_Struct {
|
||||
/*000*/ uint32 CasterID;
|
||||
/*004*/ uint32 TargetID;
|
||||
@ -3394,7 +3473,7 @@ struct Split_Struct
|
||||
*/
|
||||
struct NewCombine_Struct {
|
||||
/*00*/ int16 container_slot;
|
||||
/*02*/ char unknown02[2];
|
||||
/*02*/ int16 guildtribute_slot;
|
||||
/*04*/
|
||||
};
|
||||
|
||||
@ -3468,6 +3547,7 @@ struct MerchantList {
|
||||
int8 level_required;
|
||||
uint16 alt_currency_cost;
|
||||
uint32 classes_required;
|
||||
uint8 probability;
|
||||
};
|
||||
|
||||
struct TempMerchantList {
|
||||
@ -3904,6 +3984,11 @@ struct MarkNPC_Struct
|
||||
/*08**/ char Name[64];
|
||||
};
|
||||
|
||||
struct InspectBuffs_Struct {
|
||||
/*000*/ uint32 spell_id[BUFF_COUNT];
|
||||
/*100*/ uint32 tics_remaining[BUFF_COUNT];
|
||||
};
|
||||
|
||||
struct RaidGeneral_Struct {
|
||||
/*00*/ uint32 action; //=10
|
||||
/*04*/ char player_name[64]; //should both be the player's name
|
||||
@ -3919,6 +4004,19 @@ struct RaidAddMember_Struct {
|
||||
/*139*/ uint8 flags[5]; //no idea if these are needed...
|
||||
};
|
||||
|
||||
struct RaidMOTD_Struct {
|
||||
/*000*/ RaidGeneral_Struct general; // leader_name and action only used
|
||||
/*136*/ char motd[0]; // max size is 1024, but reply is variable
|
||||
};
|
||||
|
||||
struct RaidLeadershipUpdate_Struct {
|
||||
/*000*/ uint32 action;
|
||||
/*004*/ char player_name[64];
|
||||
/*068*/ char leader_name[64];
|
||||
/*132*/ GroupLeadershipAA_Struct group; //unneeded
|
||||
/*196*/ RaidLeadershipAA_Struct raid;
|
||||
/*260*/ char Unknown260[128]; //unverified
|
||||
};
|
||||
|
||||
struct RaidAdd_Struct {
|
||||
/*000*/ uint32 action; //=0
|
||||
@ -4060,7 +4158,7 @@ struct GroupInvite_Struct {
|
||||
// uint8 unknown128[65];
|
||||
};
|
||||
|
||||
struct BuffFadeMsg_Struct {
|
||||
struct ColoredText_Struct {
|
||||
uint32 color;
|
||||
char msg[1];
|
||||
};
|
||||
@ -4257,6 +4355,13 @@ struct ItemVerifyReply_Struct {
|
||||
/*012*/
|
||||
};
|
||||
|
||||
struct ItemRecastDelay_Struct {
|
||||
/*000*/ uint32 recast_delay; // in seconds
|
||||
/*004*/ uint32 recast_type;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/
|
||||
};
|
||||
|
||||
/**
|
||||
* Shroud yourself. For yourself shrouding, this has your spawnId, spawnStruct,
|
||||
* bits of your charProfileStruct (no checksum, then charProfile up till
|
||||
@ -4290,14 +4395,14 @@ typedef struct {
|
||||
struct ControlBoat_Struct {
|
||||
/*000*/ uint32 boatId; // entitylist id of the boat
|
||||
/*004*/ bool TakeControl; // 01 if taking control, 00 if releasing it
|
||||
/*007*/ // no idea what these last three bytes represent
|
||||
/*007*/ char unknown[3]; // no idea what these last three bytes represent
|
||||
};
|
||||
|
||||
struct AugmentInfo_Struct
|
||||
{
|
||||
/*000*/ uint32 itemid; // id of the solvent needed
|
||||
/*004*/ uint8 window; // window to display the information in
|
||||
/*005*/ uint8 unknown005[67]; // total packet length 72, all the rest were always 00
|
||||
/*000*/ uint32 itemid; // id of the solvent needed
|
||||
/*004*/ uint32 window; // window to display the information in
|
||||
/*008*/ char augment_info[64]; // the reply has the text here
|
||||
/*072*/
|
||||
};
|
||||
|
||||
@ -4460,6 +4565,14 @@ struct GuildBankPromote_Struct
|
||||
/*12*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
|
||||
};
|
||||
|
||||
struct GuildPromoteStruct {
|
||||
/*000*/ char target[64];
|
||||
/*064*/ char name[64];
|
||||
/*128*/ uint32 rank;
|
||||
/*132*/ uint32 myrank;
|
||||
/*136*/
|
||||
};
|
||||
|
||||
struct GuildBankPermissions_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 6
|
||||
@ -4577,11 +4690,13 @@ struct BuffIconEntry_Struct
|
||||
uint32 buff_slot;
|
||||
uint32 spell_id;
|
||||
uint32 tics_remaining;
|
||||
uint32 num_hits;
|
||||
};
|
||||
|
||||
struct BuffIcon_Struct
|
||||
{
|
||||
uint32 entity_id;
|
||||
uint8 all_buffs;
|
||||
uint16 count;
|
||||
BuffIconEntry_Struct entries[0];
|
||||
};
|
||||
@ -5094,17 +5209,17 @@ struct MercenaryMerchantResponse_Struct {
|
||||
};
|
||||
|
||||
struct ServerLootItem_Struct {
|
||||
uint32 item_id;
|
||||
int16 equipSlot;
|
||||
uint8 charges;
|
||||
uint16 lootslot;
|
||||
uint32 aug1;
|
||||
uint32 aug2;
|
||||
uint32 aug3;
|
||||
uint32 aug4;
|
||||
uint32 aug5;
|
||||
uint8 minlevel;
|
||||
uint8 maxlevel;
|
||||
uint32 item_id; // uint32 item_id;
|
||||
int16 equip_slot; // int16 equip_slot;
|
||||
uint16 charges; // uint8 charges;
|
||||
uint16 lootslot; // uint16 lootslot;
|
||||
uint32 aug_1; // uint32 aug_1;
|
||||
uint32 aug_2; // uint32 aug_2;
|
||||
uint32 aug_3; // uint32 aug_3;
|
||||
uint32 aug_4; // uint32 aug_4;
|
||||
uint32 aug_5; // uint32 aug_5;
|
||||
uint8 min_level; //
|
||||
uint8 max_level; //
|
||||
};
|
||||
|
||||
//Found in client near a ref to the string:
|
||||
|
||||
@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "EQPacket.h"
|
||||
#include "EQStream.h"
|
||||
#include "eq_packet.h"
|
||||
#include "eq_stream.h"
|
||||
#include "misc.h"
|
||||
#include "Mutex.h"
|
||||
#include "mutex.h"
|
||||
#include "op_codes.h"
|
||||
#include "CRC16.h"
|
||||
#include "crc16.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <string>
|
||||
@ -532,9 +532,12 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode);
|
||||
|
||||
_log(NET__APP_TRACE, "Queueing %sacked packet with opcode 0x%x (%s) and length %d", ack_req?"":"non-", opcode, OpcodeManager::EmuToName(pack->emu_opcode), pack->size);
|
||||
uint16 opcode = 0;
|
||||
if(pack->GetOpcodeBypass() != 0) {
|
||||
opcode = pack->GetOpcodeBypass();
|
||||
} else {
|
||||
opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode);
|
||||
}
|
||||
|
||||
if (!ack_req) {
|
||||
NonSequencedPush(new EQProtocolPacket(opcode, pack->pBuffer, pack->size));
|
||||
@ -877,43 +880,6 @@ sockaddr_in address;
|
||||
AddBytesSent(length);
|
||||
}
|
||||
|
||||
/*
|
||||
commented out since im not sure theres a lot of merit in it.
|
||||
Really it was bitterness towards allocating a 2k buffer on the stack each call.
|
||||
Im sure the thought was client side, but even then, they will
|
||||
likely need a whole thread to call this method, in which case, they should
|
||||
supply the buffer so we dont re-allocate it each time.
|
||||
EQProtocolPacket *EQStream::Read(int eq_fd, sockaddr_in *from)
|
||||
{
|
||||
int socklen;
|
||||
int length=0;
|
||||
EQProtocolPacket *p=nullptr;
|
||||
char temp[15];
|
||||
|
||||
socklen=sizeof(sockaddr);
|
||||
#ifdef _WINDOWS
|
||||
length=recvfrom(eq_fd, (char *)_tempBuffer, 2048, 0, (struct sockaddr*)from, (int *)&socklen);
|
||||
#else
|
||||
length=recvfrom(eq_fd, _tempBuffer, 2048, 0, (struct sockaddr*)from, (socklen_t *)&socklen);
|
||||
#endif
|
||||
|
||||
if (length>=2) {
|
||||
p=new EQProtocolPacket(_tempBuffer[1],&_tempBuffer[2],length-2);
|
||||
|
||||
uint32 ip=from->sin_addr.s_addr;
|
||||
sprintf(temp,"%d.%d.%d.%d:%d",
|
||||
*(unsigned char *)&ip,
|
||||
*((unsigned char *)&ip+1),
|
||||
*((unsigned char *)&ip+2),
|
||||
*((unsigned char *)&ip+3),
|
||||
ntohs(from->sin_port));
|
||||
//std::cout << timestamp() << "Data from: " << temp << " OpCode 0x" << std::hex << std::setw(2) << std::setfill('0') << (int)p->opcode << std::dec << std::endl;
|
||||
//dump_message(p->pBuffer,p->size,timestamp());
|
||||
|
||||
}
|
||||
return p;
|
||||
}*/
|
||||
|
||||
void EQStream::SendSessionResponse()
|
||||
{
|
||||
EQProtocolPacket *out=new EQProtocolPacket(OP_SessionResponse,nullptr,sizeof(SessionResponse));
|
||||
@ -1101,14 +1067,6 @@ EQProtocolPacket *p=nullptr;
|
||||
SequencedQueue.clear();
|
||||
}
|
||||
MOutboundQueue.unlock();
|
||||
|
||||
/*if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) {
|
||||
_log(NET__ERROR, _L "Out-bound Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq);
|
||||
}
|
||||
if(NextSequencedSend > SequencedQueue.size()) {
|
||||
_log(NET__ERROR, _L "Out-bound Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size());
|
||||
}*/
|
||||
//NOTE: we prolly want to reset counters if we are stupposed to do anything after this.
|
||||
}
|
||||
|
||||
void EQStream::PacketQueueClear()
|
||||
@ -9,13 +9,13 @@
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include "EQStreamType.h"
|
||||
#include "EQPacket.h"
|
||||
#include "EQStreamIntf.h"
|
||||
#include "Mutex.h"
|
||||
#include "eq_stream_type.h"
|
||||
#include "eq_packet.h"
|
||||
#include "eq_stream_intf.h"
|
||||
#include "mutex.h"
|
||||
#include "../common/opcodemgr.h"
|
||||
#include "../common/misc.h"
|
||||
#include "../common/Condition.h"
|
||||
#include "../common/condition.h"
|
||||
#include "../common/timer.h"
|
||||
|
||||
#define FLAG_COMPRESSED 0x01
|
||||
@ -1,5 +1,5 @@
|
||||
#include "debug.h"
|
||||
#include "EQStreamFactory.h"
|
||||
#include "eq_stream_factory.h"
|
||||
#ifdef _WINDOWS
|
||||
#include <winsock.h>
|
||||
#include <process.h>
|
||||
@ -16,7 +16,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include "op_codes.h"
|
||||
#include "EQStream.h"
|
||||
#include "eq_stream.h"
|
||||
#include "logsys.h"
|
||||
|
||||
ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs)
|
||||
@ -4,8 +4,8 @@
|
||||
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include "../common/EQStream.h"
|
||||
#include "../common/Condition.h"
|
||||
#include "../common/eq_stream.h"
|
||||
#include "../common/condition.h"
|
||||
#include "../common/timeoutmgr.h"
|
||||
#include "../common/opcodemgr.h"
|
||||
#include "../common/timer.h"
|
||||
@ -1,6 +1,6 @@
|
||||
#include "debug.h"
|
||||
#include "EQStreamIdent.h"
|
||||
#include "EQStreamProxy.h"
|
||||
#include "eq_stream_ident.h"
|
||||
#include "eq_stream_proxy.h"
|
||||
#include "logsys.h"
|
||||
|
||||
EQStreamIdentifier::~EQStreamIdentifier() {
|
||||
@ -1,7 +1,7 @@
|
||||
#ifndef EQSTREAMIDENT_H_
|
||||
#define EQSTREAMIDENT_H_
|
||||
|
||||
#include "EQStream.h"
|
||||
#include "eq_stream.h"
|
||||
#include "timer.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@ -1,8 +1,8 @@
|
||||
|
||||
#include "debug.h"
|
||||
#include "EQStreamProxy.h"
|
||||
#include "EQStream.h"
|
||||
#include "StructStrategy.h"
|
||||
#include "eq_stream_proxy.h"
|
||||
#include "eq_stream.h"
|
||||
#include "struct_strategy.h"
|
||||
|
||||
|
||||
EQStreamProxy::EQStreamProxy(EQStream *&stream, const StructStrategy *structs, OpcodeManager **opcodes)
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
#include "types.h"
|
||||
#include "EQStreamIntf.h"
|
||||
#include "eq_stream_intf.h"
|
||||
|
||||
class EQStream;
|
||||
class StructStrategy;
|
||||
@ -16,7 +16,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "debug.h"
|
||||
#include "EQDB.h"
|
||||
#include "eqdb.h"
|
||||
#include "database.h"
|
||||
#include <mysql.h>
|
||||
#include <cstring>
|
||||
@ -22,7 +22,7 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "types.h"
|
||||
#include "EQDBRes.h"
|
||||
#include "eqdb_res.h"
|
||||
#include <mysql.h>
|
||||
|
||||
//this is the main object exported to perl.
|
||||
@ -16,7 +16,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "debug.h"
|
||||
#include "EQDBRes.h"
|
||||
#include "eqdb_res.h"
|
||||
#include <mysql.h>
|
||||
|
||||
std::vector<std::string> EQDBRes::fetch_row_array() {
|
||||
@ -16,8 +16,8 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "EQEmuConfig.h"
|
||||
#include "MiscFunctions.h"
|
||||
#include "eqemu_config.h"
|
||||
#include "misc_functions.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
#ifndef __EQEmuConfig_H
|
||||
#define __EQEmuConfig_H
|
||||
|
||||
#include "XMLParser.h"
|
||||
#include "xml_parser.h"
|
||||
#include "linked_list.h"
|
||||
|
||||
struct LoginConfig {
|
||||
@ -118,14 +118,14 @@ protected:
|
||||
|
||||
#define ELEMENT(name) \
|
||||
void do_##name(TiXmlElement *ele);
|
||||
#include "EQEmuConfig_elements.h"
|
||||
#include "eqemu_config_elements.h"
|
||||
|
||||
|
||||
EQEmuConfig() {
|
||||
// import the needed handler prototypes
|
||||
#define ELEMENT(name) \
|
||||
Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name;
|
||||
#include "EQEmuConfig_elements.h"
|
||||
#include "eqemu_config_elements.h"
|
||||
|
||||
// Set sane defaults
|
||||
|
||||
@ -18,10 +18,10 @@
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "EQEMuError.h"
|
||||
#include "eqemu_error.h"
|
||||
#include "linked_list.h"
|
||||
#include "Mutex.h"
|
||||
#include "MiscFunctions.h"
|
||||
#include "mutex.h"
|
||||
#include "misc_functions.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef _WINDOWS
|
||||
@ -19,8 +19,7 @@
|
||||
#define EXTENDED_PROFILE_H
|
||||
|
||||
#include "eq_packet_structs.h"
|
||||
#include "Item.h"
|
||||
|
||||
#include "item.h"
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
@ -37,24 +36,24 @@
|
||||
*/
|
||||
struct ExtendedProfile_Struct {
|
||||
// Pet stuff
|
||||
uint16 pet_id;
|
||||
uint16 old_pet_hp;
|
||||
uint16 old_pet_mana;
|
||||
SpellBuff_Struct pet_buffs[BUFF_COUNT];
|
||||
uint32 pet_items[_MaterialCount];
|
||||
char merc_name[64];
|
||||
uint16 pet_id; /* Not Used */
|
||||
uint16 old_pet_hp; /* Not Used */
|
||||
uint16 old_pet_mana; /* Not Used */
|
||||
SpellBuff_Struct pet_buffs[BUFF_COUNT]; /* Not Used */
|
||||
uint32 pet_items[_MaterialCount]; /* Not Used */
|
||||
char merc_name[64]; /* Used */
|
||||
|
||||
uint32 aa_effects;
|
||||
uint32 perAA; //% of exp going to AAs
|
||||
uint32 expended_aa; // Total of expended AA
|
||||
uint32 pet_hp;
|
||||
uint32 pet_mana;
|
||||
uint32 mercTemplateID;
|
||||
uint32 mercSuspendedTime;
|
||||
bool mercIsSuspended;
|
||||
uint32 mercTimerRemaining;
|
||||
uint8 mercGender;
|
||||
int32 mercState;
|
||||
uint32 aa_effects; /* Used */
|
||||
uint32 perAA; /* Used: % of exp going to AAs */
|
||||
uint32 expended_aa; /* Used: Total of expended AA */
|
||||
uint32 pet_hp; /* Not Used */
|
||||
uint32 pet_mana; /* Not Used */
|
||||
uint32 mercTemplateID; /* Not Used */
|
||||
uint32 mercSuspendedTime; /* Not Used */
|
||||
bool mercIsSuspended; /* Not Used */
|
||||
uint32 mercTimerRemaining; /* Not Used */
|
||||
uint8 mercGender; /* Not Used */
|
||||
int32 mercState; /* Not Used */
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
@ -47,7 +47,7 @@ const char *FactionValueToString(FACTION_VALUE fv) {
|
||||
|
||||
|
||||
//o--------------------------------------------------------------
|
||||
//| Name: CalculateFaction; rembrant, Dec. 16, 2001
|
||||
//| Name: CalculateFaction; Dec. 16, 2001
|
||||
//o--------------------------------------------------------------
|
||||
//| Notes: Returns the faction message value.
|
||||
//| Modify these values to taste.
|
||||
@ -69,7 +69,7 @@ FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
|
||||
return FACTION_INDIFFERENT;
|
||||
}
|
||||
|
||||
// neotokyo: this function should check if some races have more than one race define
|
||||
// this function should check if some races have more than one race define
|
||||
bool IsOfEqualRace(int r1, int r2)
|
||||
{
|
||||
if (r1 == r2)
|
||||
@ -88,7 +88,7 @@ bool IsOfEqualRace(int r1, int r2)
|
||||
return false;
|
||||
}
|
||||
|
||||
// neotokyo: trolls endure ogres, dark elves, ...
|
||||
// trolls endure ogres, dark elves, ...
|
||||
bool IsOfIndiffRace(int r1, int r2)
|
||||
{
|
||||
if (r1 == r2)
|
||||
|
||||
@ -163,7 +163,7 @@ enum { //timer settings, all in milliseconds
|
||||
CombatEventTimer_expire = 12000,
|
||||
Tribute_duration = 600000,
|
||||
ZoneTimerResolution = 3, //sleep time between zone main loop runs (milliseconds)
|
||||
FeignMemoryDuration = 120000, // EverHood - Duration player must feign death to clear zonewide agro.
|
||||
FeignMemoryDuration = 120000, // Duration player must feign death to clear zonewide agro.
|
||||
EnragedTimer = 360000,
|
||||
EnragedDurationTimer = 10000
|
||||
};
|
||||
@ -208,12 +208,12 @@ enum { //some random constants
|
||||
//chance ratio that a
|
||||
#define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly
|
||||
|
||||
// max factions per npc faction list
|
||||
//max factions per npc faction list
|
||||
#define MAX_NPC_FACTIONS 20
|
||||
|
||||
//value caps
|
||||
#define MAX_FACTION 1500
|
||||
#define MIN_FACTION -1500
|
||||
//individual faction pool
|
||||
#define MAX_PERSONAL_FACTION 1200
|
||||
#define MIN_PERSONAL_FACTION -3000
|
||||
|
||||
//The Level Cap:
|
||||
//#define LEVEL_CAP RuleI(Character, MaxLevel) //hard cap is 127
|
||||
@ -261,7 +261,8 @@ enum {
|
||||
commandChangeFlags = 200, //ability to set/refresh flags
|
||||
commandBanPlayers = 100, //can set bans on players
|
||||
commandChangeDatarate = 201, //edit client's data rate
|
||||
commandZoneToCoords = 0 //can #zone with coords
|
||||
commandZoneToCoords = 0, //can #zone with coords
|
||||
commandInterrogateInv = 100 //below this == only log on error state and self-only target dump
|
||||
};
|
||||
|
||||
//default states for logging flag on NPCs and clients (having NPCs on by default is prolly a bad idea)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,7 @@ public:
|
||||
bool SetGuild(uint32 charid, uint32 guild_id, uint8 rank);
|
||||
bool SetGuildRank(uint32 charid, uint8 rank);
|
||||
bool SetBankerFlag(uint32 charid, bool is_banker);
|
||||
bool ForceRankUpdate(uint32 charid);
|
||||
bool GetAltFlag(uint32 CharID);
|
||||
bool SetAltFlag(uint32 charid, bool is_alt);
|
||||
bool GetBankerFlag(uint32 CharID);
|
||||
@ -108,7 +109,7 @@ protected:
|
||||
bool DBSetAltFlag(uint32 charid, bool is_alt);
|
||||
bool DBSetTributeFlag(uint32 charid, bool enabled);
|
||||
bool DBSetPublicNote(uint32 charid, const char *note);
|
||||
bool _RunQuery(char *&query, int len, const char *errmsg);
|
||||
bool QueryWithLogging(std::string query, const char *errmsg);
|
||||
// void DBSetPublicNote(uint32 guild_id,char* charname, char* note);
|
||||
|
||||
bool LocalDeleteGuild(uint32 guild_id);
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "MiscFunctions.h"
|
||||
#include "misc_functions.h"
|
||||
#include "guilds.h"
|
||||
#include "database.h"
|
||||
#include "eq_packet_structs.h"
|
||||
@ -24,318 +24,4 @@
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h> //for htonl
|
||||
#endif
|
||||
|
||||
/*
|
||||
void Database::GetGuildMembers(uint32 guild_id, GuildMember_Struct* gms){
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
uint32 count=0;
|
||||
uint32 length=0;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Select name,profile,timelaston,guildrank,publicnote from character_ where guild=%i", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
while( ( row = mysql_fetch_row(result) ) ){
|
||||
strcpy(gms->member[count].name,row[0]);
|
||||
length+=strlen(row[0])+strlen(row[4]);
|
||||
PlayerProfile_Struct* pps=(PlayerProfile_Struct*)row[1];
|
||||
gms->member[count].level=htonl(pps->level);
|
||||
gms->member[count].zoneid=(pps->zone_id*256);
|
||||
gms->member[count].timelaston=htonl(atol(row[2]));
|
||||
gms->member[count].class_=htonl(pps->class_);
|
||||
gms->member[count].rank=atoi(row[3]);
|
||||
strcpy(gms->member[count].publicnote,row[4]);
|
||||
count++;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetGuildMembers query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
gms->count=count;
|
||||
gms->length=length;
|
||||
}
|
||||
|
||||
uint32 Database::NumberInGuild(uint32 guild_id) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Select count(id) from character_ where guild=%i", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
uint32 ret = atoi(row[0]);
|
||||
mysql_free_result(result);
|
||||
return ret;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in NumberInGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool Database::SetGuild(char* name, uint32 guild_id, uint8 guildrank) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET guild=%i, guildrank=%i WHERE name='%s'", guild_id, guildrank, name), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::SetGuild(uint32 charid, uint32 guild_id, uint8 guildrank) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET guild=%i, guildrank=%i WHERE id=%i", guild_id, guildrank, charid), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::DeleteGuild(uint32 guild_id)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
char *query2 = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "DELETE FROM guilds WHERE id=%i;", guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1) {
|
||||
if(!RunQuery(query2, MakeAnyLenString(&query2, "update character_ set guild=0,guildrank=0 where guild=%i", guild_id), errbuf, 0, &affected_rows))
|
||||
LogFile->write(EQEMuLog::Error, "Error in DeleteGuild cleanup query '%s': %s", query2, errbuf);
|
||||
safe_delete_array(query2);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in DeleteGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::RenameGuild(uint32 guild_id, const char* name) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
char buf[65];
|
||||
DoEscapeString(buf, name, strlen(name)) ;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Update guilds set name='%s' WHERE id=%i;", buf, guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in RenameGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Database::EditGuild(uint32 guild_id, uint8 ranknum, GuildRankLevel_Struct* grl)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
int chars = 0;
|
||||
uint32 affected_rows = 0;
|
||||
char buf[203];
|
||||
char buf2[8];
|
||||
DoEscapeString(buf, grl->rankname, strlen(grl->rankname)) ;
|
||||
buf2[GUILD_HEAR] = grl->heargu + '0';
|
||||
buf2[GUILD_SPEAK] = grl->speakgu + '0';
|
||||
buf2[GUILD_INVITE] = grl->invite + '0';
|
||||
buf2[GUILD_REMOVE] = grl->remove + '0';
|
||||
buf2[GUILD_PROMOTE] = grl->promote + '0';
|
||||
buf2[GUILD_DEMOTE] = grl->demote + '0';
|
||||
buf2[GUILD_MOTD] = grl->motd + '0';
|
||||
buf2[GUILD_WARPEACE] = grl->warpeace + '0';
|
||||
|
||||
if (ranknum == 0)
|
||||
chars = MakeAnyLenString(&query, "Update guilds set rank%ititle='%s' WHERE id=%i;", ranknum, buf, guild_id);
|
||||
else
|
||||
chars = MakeAnyLenString(&query, "Update guilds set rank%ititle='%s', rank%i='%s' WHERE id=%i;", ranknum, buf, ranknum, buf2, guild_id);
|
||||
|
||||
if (RunQuery(query, chars, errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in EditGuild query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::GetGuildNameByID(uint32 guild_id, char * name) {
|
||||
if (!name || !guild_id) return false;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "select name from guilds where id='%i'", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
row = mysql_fetch_row(result);
|
||||
if (row[0])
|
||||
sprintf(name,"%s",row[0]);
|
||||
mysql_free_result(result);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetGuildNameByID query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 Database::GetGuildIDbyLeader(uint32 leader)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id FROM guilds WHERE leader=%i", leader), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1)
|
||||
{
|
||||
row = mysql_fetch_row(result);
|
||||
uint32 tmp = atoi(row[0]);
|
||||
mysql_free_result(result);
|
||||
return tmp;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in Getguild_idbyLeader query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Database::SetGuildLeader(uint32 guild_id, uint32 leader)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "UPDATE guilds SET leader=%i WHERE id=%i", leader, guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuildLeader query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Database::SetGuildMOTD(uint32 guild_id, const char* motd) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
char* motdbuf = 0;
|
||||
uint32 affected_rows = 0;
|
||||
|
||||
motdbuf = new char[(strlen(motd)*2)+3];
|
||||
|
||||
DoEscapeString(motdbuf, motd, strlen(motd)) ;
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "Update guilds set motd='%s' WHERE id=%i;", motdbuf, guild_id), errbuf, 0, &affected_rows)) {
|
||||
safe_delete_array(query);
|
||||
delete motdbuf;
|
||||
if (affected_rows == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile->write(EQEMuLog::Error, "Error in SetGuildMOTD query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
delete motdbuf;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string Database::GetGuildMOTD(uint32 guild_id)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
string motd_str;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT motd FROM guilds WHERE id=%i", guild_id), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
if (mysql_num_rows(result) == 1) {
|
||||
row = mysql_fetch_row(result);
|
||||
if (row[0])
|
||||
motd_str = row[0];
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in GetGuildMOTD query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
return motd_str;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Item.h"
|
||||
#include "string_util.h"
|
||||
#include "item.h"
|
||||
#include "database.h"
|
||||
#include "misc.h"
|
||||
#include "races.h"
|
||||
@ -654,6 +654,110 @@ int16 Inventory::FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size, boo
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
// This is a mix of HasSpaceForItem and FindFreeSlot..due to existing coding behavior, it was better to add a new helper function...
|
||||
int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
// Do not arbitrarily use this function..it is designed for use with Client::ResetTrade() and Client::FinishTrade().
|
||||
// If you have a need, use it..but, understand it is not a compatible replacement for Inventory::FindFreeSlot().
|
||||
//
|
||||
// I'll probably implement a bitmask in the new inventory system to avoid having to adjust stack bias -U
|
||||
|
||||
if (!inst || !inst->GetID())
|
||||
return INVALID_INDEX;
|
||||
|
||||
// step 1: find room for bags (caller should really ask for slots for bags first to avoid sending them to cursor..and bag item loss)
|
||||
if (inst->IsType(ItemClassContainer)) {
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot)
|
||||
if (!m_inv[free_slot])
|
||||
return free_slot;
|
||||
|
||||
return MainCursor; // return cursor since bags do not stack and will not fit inside other bags..yet...)
|
||||
}
|
||||
|
||||
// step 2: find partial room for stackables
|
||||
if (inst->IsStackable()) {
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst)
|
||||
continue;
|
||||
|
||||
if ((main_inst->GetID() == inst->GetID()) && (main_inst->GetCharges() < main_inst->GetItem()->StackSize))
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst)
|
||||
continue;
|
||||
|
||||
if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here...
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) {
|
||||
const ItemInst* sub_inst = main_inst->GetItem(free_bag_slot);
|
||||
|
||||
if (!sub_inst)
|
||||
continue;
|
||||
|
||||
if ((sub_inst->GetID() == inst->GetID()) && (sub_inst->GetCharges() < sub_inst->GetItem()->StackSize))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 3a: find room for container-specific items (ItemClassArrow)
|
||||
if (inst->GetItem()->ItemType == ItemTypeArrow) {
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst || (main_inst->GetItem()->BagType != BagTypeQuiver) || !main_inst->IsType(ItemClassContainer))
|
||||
continue;
|
||||
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot)
|
||||
if (!main_inst->GetItem(free_bag_slot))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
|
||||
// step 3b: find room for container-specific items (ItemClassSmallThrowing)
|
||||
if (inst->GetItem()->ItemType == ItemTypeSmallThrowing) {
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst || (main_inst->GetItem()->BagType != BagTypeBandolier) || !main_inst->IsType(ItemClassContainer))
|
||||
continue;
|
||||
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot)
|
||||
if (!main_inst->GetItem(free_bag_slot))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
|
||||
// step 4: just find an empty slot
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst)
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (main_inst && main_inst->IsType(ItemClassContainer)) {
|
||||
if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver))
|
||||
continue;
|
||||
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot)
|
||||
if (!main_inst->GetItem(free_bag_slot))
|
||||
return Inventory::CalcSlotId(free_slot, free_bag_slot);
|
||||
}
|
||||
}
|
||||
|
||||
//return INVALID_INDEX; // everything else pushes to the cursor
|
||||
return MainCursor;
|
||||
}
|
||||
|
||||
// Opposite of below: Get parent bag slot_id from a slot inside of bag
|
||||
int16 Inventory::CalcSlotId(int16 slot_id) {
|
||||
int16 parent_slot_id = INVALID_INDEX;
|
||||
@ -807,6 +911,30 @@ bool Inventory::CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_S
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Inventory::SupportsClickCasting(int16 slot_id)
|
||||
{
|
||||
// there are a few non-potion items that identify as ItemTypePotion..so, we still need to ubiquitously include the equipment range
|
||||
if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END)
|
||||
{
|
||||
if (EQLimits::AllowsClickCastFromBag(m_version))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Inventory::SupportsPotionBeltCasting(int16 slot_id)
|
||||
{
|
||||
if ((uint16)slot_id <= EmuConstants::GENERAL_END || slot_id == MainPowerSource || (slot_id >= EmuConstants::GENERAL_BAGS_BEGIN && slot_id <= EmuConstants::GENERAL_BAGS_END))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test whether a given slot can support a container item
|
||||
bool Inventory::SupportsContainers(int16 slot_id)
|
||||
{
|
||||
@ -1284,6 +1412,8 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) {
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
}
|
||||
|
||||
ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
|
||||
@ -1306,6 +1436,8 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
}
|
||||
|
||||
ItemInst::ItemInst(ItemInstTypes use_type) {
|
||||
@ -1323,6 +1455,8 @@ ItemInst::ItemInst(ItemInstTypes use_type) {
|
||||
m_scaledItem = nullptr;
|
||||
m_evolveInfo = nullptr;
|
||||
m_scaling = false;
|
||||
m_ornamenticon = 0;
|
||||
m_ornamentidfile = 0;
|
||||
}
|
||||
|
||||
// Make a copy of an ItemInst object
|
||||
@ -1373,6 +1507,8 @@ ItemInst::ItemInst(const ItemInst& copy)
|
||||
m_evolveInfo = nullptr;
|
||||
|
||||
m_scaling = copy.m_scaling;
|
||||
m_ornamenticon = copy.m_ornamenticon;
|
||||
m_ornamentidfile = copy.m_ornamentidfile;
|
||||
}
|
||||
|
||||
// Clean up container contents
|
||||
@ -1476,6 +1612,16 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const
|
||||
return (i < EmuConstants::ITEM_COMMON_SIZE) ? i : INVALID_INDEX;
|
||||
}
|
||||
|
||||
bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const {
|
||||
if (m_item->ItemClass != ItemClassCommon || !m_item)
|
||||
return false;
|
||||
|
||||
if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve item inside container
|
||||
ItemInst* ItemInst::GetItem(uint8 index) const
|
||||
{
|
||||
@ -1636,6 +1782,67 @@ ItemInst* ItemInst::GetAugment(uint8 slot) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ItemInst* ItemInst::GetOrnamentationAug(int ornamentationAugtype) const
|
||||
{
|
||||
for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) {
|
||||
if (GetAugment(i) && m_item->AugSlotType[i] == ornamentationAugtype) {
|
||||
const char *item_IDFile = GetAugment(i)->GetItem()->IDFile;
|
||||
if (strncmp(item_IDFile, "IT64", strlen(item_IDFile)) == 0 || strncmp(item_IDFile, "IT63", strlen(item_IDFile)) == 0)
|
||||
continue;
|
||||
|
||||
return this->GetAugment(i);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ItemInst::CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll) {
|
||||
if (!ItemToTry || !Container) return false;
|
||||
|
||||
if (ItemToTry->ItemType == ItemTypeArrow || strnlen(Container->CharmFile, 30) == 0)
|
||||
return false;
|
||||
|
||||
if (AllowAll && strncasecmp(Container->CharmFile, "ITEMTRANSFIGSHIELD", 18) && strncasecmp(Container->CharmFile, "ITEMTransfigBow", 15)) {
|
||||
switch (ItemToTry->ItemType) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 35:
|
||||
case 45:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static std::map<std::string, int> types;
|
||||
types["itemtransfig1hp"] = 2;
|
||||
types["itemtransfig1hs"] = 0;
|
||||
types["itemtransfig2hb"] = 4;
|
||||
types["itemtransfig2hp"] = 35;
|
||||
types["itemtransfig2hs"] = 1;
|
||||
types["itemtransfigblunt"] = 3;
|
||||
types["itemtransfigbow"] = 5;
|
||||
types["itemtransfighth"] = 45;
|
||||
types["itemtransfigshield"] = 8;
|
||||
types["itemtransfigslashing"] = 0;
|
||||
|
||||
auto i = types.find(MakeLowerString(Container->CharmFile));
|
||||
if (i != types.end() && i->second == ItemToTry->ItemType)
|
||||
return true;
|
||||
|
||||
static std::map<std::string, int> typestwo;
|
||||
typestwo["itemtransfigblunt"] = 4;
|
||||
typestwo["itemtransfigslashing"] = 1;
|
||||
|
||||
i = typestwo.find(MakeLowerString(Container->CharmFile));
|
||||
if (i != typestwo.end() && i->second == ItemToTry->ItemType)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 ItemInst::GetAugmentItemID(uint8 slot) const
|
||||
{
|
||||
uint32 id = NO_ITEM;
|
||||
@ -121,8 +121,22 @@ public:
|
||||
// Public Methods
|
||||
///////////////////////////////
|
||||
|
||||
Inventory() { m_version = EQClientUnknown; m_versionset = false; }
|
||||
~Inventory();
|
||||
|
||||
// Inventory v2 creep
|
||||
bool SetInventoryVersion(EQClientVersion version) {
|
||||
if (!m_versionset) {
|
||||
m_version = version;
|
||||
return (m_versionset = true);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EQClientVersion GetInventoryVersion() { return m_version; }
|
||||
|
||||
static void CleanDirty();
|
||||
static void MarkDirty(ItemInst *inst);
|
||||
|
||||
@ -132,7 +146,7 @@ public:
|
||||
|
||||
inline iter_queue cursor_begin() { return m_cursor.begin(); }
|
||||
inline iter_queue cursor_end() { return m_cursor.end(); }
|
||||
inline bool CursorEmpty() { return (m_cursor.size() == 0); }
|
||||
inline bool CursorEmpty() { return (m_cursor.size() == 0); }
|
||||
|
||||
// Retrieve a read-only item from inventory
|
||||
inline const ItemInst* operator[](int16 slot_id) const { return GetItem(slot_id); }
|
||||
@ -172,6 +186,7 @@ public:
|
||||
|
||||
// Locate an available inventory slot
|
||||
int16 FindFreeSlot(bool for_bag, bool try_cursor, uint8 min_size = 0, bool is_arrow = false);
|
||||
int16 FindFreeSlotForTradeItem(const ItemInst* inst);
|
||||
|
||||
// Calculate slot_id for an item within a bag
|
||||
static int16 CalcSlotId(int16 slot_id); // Calc parent bag's slot_id
|
||||
@ -182,6 +197,10 @@ public:
|
||||
|
||||
static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container);
|
||||
|
||||
// Test for valid inventory casting slot
|
||||
bool SupportsClickCasting(int16 slot_id);
|
||||
bool SupportsPotionBeltCasting(int16 slot_id);
|
||||
|
||||
// Test whether a given slot can support a container item
|
||||
static bool SupportsContainers(int16 slot_id);
|
||||
|
||||
@ -228,7 +247,12 @@ protected:
|
||||
std::map<int16, ItemInst*> m_bank; // Items in character bank
|
||||
std::map<int16, ItemInst*> m_shbank; // Items in character shared bank
|
||||
std::map<int16, ItemInst*> m_trade; // Items in a trade session
|
||||
ItemInstQueue m_cursor; // Items on cursor: FIFO
|
||||
ItemInstQueue m_cursor; // Items on cursor: FIFO
|
||||
|
||||
private:
|
||||
// Active inventory version
|
||||
EQClientVersion m_version;
|
||||
bool m_versionset;
|
||||
};
|
||||
|
||||
class SharedDatabase;
|
||||
@ -273,6 +297,7 @@ public:
|
||||
inline bool IsAugmentable() const { return m_item->AugSlotType[0]!=0 || m_item->AugSlotType[1]!=0 || m_item->AugSlotType[2]!=0 || m_item->AugSlotType[3]!=0 || m_item->AugSlotType[4]!=0; }
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augtype) const;
|
||||
bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return m_item->AugType; }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)); }
|
||||
@ -304,7 +329,9 @@ public:
|
||||
void DeleteAugment(uint8 slot);
|
||||
ItemInst* RemoveAugment(uint8 index);
|
||||
bool IsAugmented();
|
||||
|
||||
ItemInst* GetOrnamentationAug(int ornamentationAugtype) const;
|
||||
static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false);
|
||||
|
||||
// Has attack/delay?
|
||||
bool IsWeapon() const;
|
||||
bool IsAmmo() const;
|
||||
@ -366,6 +393,10 @@ public:
|
||||
void SetActivated(bool activated) { m_activated = activated; }
|
||||
int8 GetEvolveLvl() const { return m_evolveLvl; }
|
||||
void SetScaling(bool v) { m_scaling = v; }
|
||||
uint32 GetOrnamentationIcon() const { return m_ornamenticon; }
|
||||
void SetOrnamentIcon(uint32 ornament_icon) { m_ornamenticon = ornament_icon; }
|
||||
uint32 GetOrnamentationIDFile() const { return m_ornamentidfile; }
|
||||
void SetOrnamentationIDFile(uint32 ornament_idfile) { m_ornamentidfile = ornament_idfile; }
|
||||
|
||||
void Initialize(SharedDatabase *db = nullptr);
|
||||
void ScaleItem();
|
||||
@ -410,6 +441,8 @@ protected:
|
||||
Item_Struct* m_scaledItem;
|
||||
EvolveInfo* m_evolveInfo;
|
||||
bool m_scaling;
|
||||
uint32 m_ornamenticon;
|
||||
uint32 m_ornamentidfile;
|
||||
|
||||
//
|
||||
// Items inside of this item (augs or contents);
|
||||
@ -169,6 +169,7 @@ F(bardlevel)
|
||||
F(questitemflag)
|
||||
F(svcorruption)
|
||||
F(purity)
|
||||
F(evolvinglevel)
|
||||
F(backstabdmg)
|
||||
F(dsmitigation)
|
||||
F(heroic_str)
|
||||
|
||||
@ -217,6 +217,7 @@ struct Item_Struct {
|
||||
// Begin SoF Fields
|
||||
int32 SVCorruption;
|
||||
uint32 Purity;
|
||||
uint8 EvolvingLevel;
|
||||
uint32 BackstabDmg;
|
||||
uint32 DSMitigation;
|
||||
int32 HeroicStr;
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "misc.h"
|
||||
#include "EQPacket.h"
|
||||
#include "eq_packet.h"
|
||||
|
||||
|
||||
#define LOG_CATEGORY(category) #category ,
|
||||
|
||||
@ -92,8 +92,8 @@ extern void log_raw_packet(LogType type, uint16 seq, const BasePacket *p);
|
||||
class Mob;
|
||||
extern void log_message_mob(LogType type, Mob *who, const char *fmt, ...);
|
||||
#define mlog( type, format, ...) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_message_mob(type, this, format, ##__VA_ARGS__); \
|
||||
} \
|
||||
@ -150,16 +150,16 @@ extern void log_raw_packet(LogType type, uint16 seq, const BasePacket *p);
|
||||
class Mob;
|
||||
extern void log_hex_mob(LogType type, Mob *who, const char *data, uint32 length);
|
||||
#define mhex( type, data, len) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_hex_mob(type, this, data, len); \
|
||||
} \
|
||||
} while(false)
|
||||
extern void log_packet_mob(LogType type, Mob *who, const BasePacket *p);
|
||||
#define mpkt( type, packet) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_packet_mob(type, this, packet); \
|
||||
} \
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
#include "debug.h"
|
||||
#include "logsys.h"
|
||||
#include "StringUtil.h"
|
||||
#include "string_util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -60,7 +60,7 @@ LOG_TYPE( UCS, PACKETS, DISABLED)
|
||||
|
||||
LOG_CATEGORY( QUERYSERV )
|
||||
LOG_TYPE( QUERYSERV, INIT, ENABLED )
|
||||
LOG_TYPE( QUERYSERV, ERROR, ENABLED )
|
||||
LOG_TYPE( QUERYSERV, ERROR, ENABLED )
|
||||
LOG_TYPE( QUERYSERV, CLIENT, DISABLED )
|
||||
LOG_TYPE( QUERYSERV, TRACE, DISABLED )
|
||||
LOG_TYPE( QUERYSERV, PACKETS, DISABLED)
|
||||
@ -108,6 +108,7 @@ LOG_CATEGORY( FACTION )
|
||||
|
||||
LOG_CATEGORY( ZONE )
|
||||
LOG_TYPE( ZONE, GROUND_SPAWNS, DISABLED )
|
||||
LOG_TYPE( ZONE, SPAWNS, ENABLED)
|
||||
LOG_TYPE( ZONE, INIT, ENABLED )
|
||||
LOG_TYPE( ZONE, INIT_ERR, ENABLED )
|
||||
LOG_TYPE( ZONE, WORLD, ENABLED )
|
||||
@ -116,7 +117,7 @@ LOG_TYPE( ZONE, WORLD_TRACE, DISABLED )
|
||||
|
||||
LOG_CATEGORY( TASKS )
|
||||
LOG_TYPE( TASKS, GLOBALLOAD, DISABLED )
|
||||
LOG_TYPE( TASKS, CLIENTLOAD, DISABLED )
|
||||
LOG_TYPE( TASKS, CLIENTLOAD, DISABLED )
|
||||
LOG_TYPE( TASKS, UPDATE, DISABLED )
|
||||
LOG_TYPE( TASKS, CLIENTSAVE, DISABLED )
|
||||
LOG_TYPE( TASKS, PACKETS, DISABLED )
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
//Mail and Chat Channels
|
||||
N(OP_MailLogin),
|
||||
N(OP_Mail),
|
||||
N(OP_Buddy),
|
||||
N(OP_ChannelAnnounceJoin),
|
||||
N(OP_ChannelAnnounceLeave),
|
||||
N(OP_Buddy),
|
||||
N(OP_MailHeaderCount),
|
||||
N(OP_MailHeader),
|
||||
N(OP_MailSendBody),
|
||||
N(OP_MailNew),
|
||||
N(OP_MailDeliveryStatus),
|
||||
N(OP_MailboxChange),
|
||||
N(OP_Ignore),
|
||||
N(OP_Mail),
|
||||
N(OP_MailboxChange),
|
||||
N(OP_MailDeliveryStatus),
|
||||
N(OP_MailHeader),
|
||||
N(OP_MailHeaderCount),
|
||||
N(OP_MailLogin),
|
||||
N(OP_MailNew),
|
||||
N(OP_MailSendBody),
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
*/
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include "../common/md5.h"
|
||||
#include "../common/StringUtil.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/seperator.h"
|
||||
|
||||
MD5::MD5() {
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "MiscFunctions.h"
|
||||
#include "misc_functions.h"
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
@ -387,3 +387,26 @@ float EQHtoFloat(int d)
|
||||
{
|
||||
return(360.0f - float((d * 360) >> 11));
|
||||
}
|
||||
|
||||
// returns a swapped-bit value for use in client translator and inventory functions
|
||||
uint32 SwapBits21and22(uint32 mask)
|
||||
{
|
||||
static const uint32 BIT21 = 1 << 21;
|
||||
static const uint32 BIT22 = 1 << 22;
|
||||
static const uint32 SWAPBITS = (BIT21 | BIT22);
|
||||
|
||||
if ((bool)(mask & BIT21) != (bool)(mask & BIT22))
|
||||
mask ^= SWAPBITS;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
// returns an unset bit 22 value for use in client translators
|
||||
uint32 Catch22(uint32 mask)
|
||||
{
|
||||
static const uint32 KEEPBITS = ~(1 << 22);
|
||||
|
||||
mask &= KEEPBITS;
|
||||
|
||||
return mask;
|
||||
}
|
||||
@ -102,6 +102,8 @@ int FloatToEQ13(float d);
|
||||
int NewFloatToEQ13(float d);
|
||||
int FloatToEQ19(float d);
|
||||
int FloatToEQH(float d);
|
||||
uint32 SwapBits21and22(uint32 mask);
|
||||
uint32 Catch22(uint32 mask);
|
||||
|
||||
// macro to catch fp errors (provided by noudness)
|
||||
#define FCMP(a,b) (fabs(a-b) < FLT_EPSILON)
|
||||
@ -16,7 +16,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "../common/debug.h"
|
||||
#include "../common/Mutex.h"
|
||||
#include "../common/mutex.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "MySQLRequestResult.h"
|
||||
#include "mysql_request_result.h"
|
||||
|
||||
|
||||
MySQLRequestResult::MySQLRequestResult()
|
||||
@ -10,7 +10,7 @@ MySQLRequestResult::MySQLRequestResult()
|
||||
MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer)
|
||||
: m_CurrentRow(result), m_OneBeyondRow()
|
||||
{
|
||||
m_Result = result;
|
||||
m_Result = result;
|
||||
m_RowsAffected = rowsAffected;
|
||||
m_RowCount = rowCount;
|
||||
m_ColumnCount = columnCount;
|
||||
@ -22,16 +22,17 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u
|
||||
m_ColumnLengths = nullptr;
|
||||
m_Fields = nullptr;
|
||||
|
||||
if (errorBuffer != nullptr)
|
||||
m_Success = true;
|
||||
if (errorBuffer != nullptr)
|
||||
m_Success = false;
|
||||
|
||||
m_Success = true;
|
||||
m_ErrorNumber = errorNumber;
|
||||
m_ErrorBuffer = errorBuffer;
|
||||
m_ErrorNumber = errorNumber;
|
||||
m_ErrorBuffer = errorBuffer;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::FreeInternals()
|
||||
{
|
||||
|
||||
safe_delete_array(m_ErrorBuffer);
|
||||
|
||||
if (m_Result != nullptr)
|
||||
@ -100,6 +101,7 @@ MySQLRequestResult::MySQLRequestResult(MySQLRequestResult&& moveItem)
|
||||
m_RowsAffected = moveItem.m_RowsAffected;
|
||||
m_LastInsertedID = moveItem.m_LastInsertedID;
|
||||
m_ColumnLengths = moveItem.m_ColumnLengths;
|
||||
m_ColumnCount = moveItem.m_ColumnCount;
|
||||
m_Fields = moveItem.m_Fields;
|
||||
|
||||
// Keeps deconstructor from double freeing
|
||||
@ -127,6 +129,7 @@ MySQLRequestResult& MySQLRequestResult::operator=(MySQLRequestResult&& other)
|
||||
m_CurrentRow = other.m_CurrentRow;
|
||||
m_OneBeyondRow = other.m_OneBeyondRow;
|
||||
m_ColumnLengths = other.m_ColumnLengths;
|
||||
m_ColumnCount = other.m_ColumnCount;
|
||||
m_Fields = other.m_Fields;
|
||||
|
||||
// Keeps deconstructor from double freeing
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#include <mysql.h>
|
||||
#include "types.h"
|
||||
#include "MySQLRequestRow.h"
|
||||
#include "mysql_request_row.h"
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
@ -40,7 +40,7 @@ public:
|
||||
MySQLRequestResult& operator=(MySQLRequestResult&& other);
|
||||
|
||||
bool Success() const { return m_Success;}
|
||||
std::string ErrorMessage() const {return std::string(m_ErrorBuffer);}
|
||||
std::string ErrorMessage() const {return m_ErrorBuffer ? std::string(m_ErrorBuffer) : std::string("");}
|
||||
uint32 ErrorNumber() const {return m_ErrorNumber;}
|
||||
uint32 RowsAffected() const {return m_RowsAffected;}
|
||||
uint32 RowCount() const {return m_RowCount;}
|
||||
@ -1,4 +1,4 @@
|
||||
#include "MySQLRequestRow.h"
|
||||
#include "mysql_request_row.h"
|
||||
|
||||
MySQLRequestRow::MySQLRequestRow(const MySQLRequestRow& row)
|
||||
: m_Result(row.m_Result), m_MySQLRow(row.m_MySQLRow)
|
||||
@ -64,6 +64,5 @@ bool MySQLRequestRow::operator!=(const MySQLRequestRow& rhs)
|
||||
|
||||
char* MySQLRequestRow::operator[](int index)
|
||||
{
|
||||
|
||||
return m_MySQLRow[index];
|
||||
}
|
||||
@ -305,7 +305,8 @@ OUTz(OP_FinishWindow2);
|
||||
//OUTv(OP_AdventureInfo, strlen(p)+1);
|
||||
//OUTv(OP_AdventureMerchantResponse, strlen(msg)+2);
|
||||
OUTv(OP_ItemPacket, ItemPacket_Struct);
|
||||
OUTv(OP_BuffFadeMsg, BuffFadeMsg_Struct);
|
||||
OUTv(OP_ColoredText, ColoredText_Struct);
|
||||
OUTv(OP_ItemRecastDelay, ItemRecastDelay_Struct);
|
||||
OUTv(OP_FormattedMessage, FormattedMessage_Struct);
|
||||
OUTv(OP_GuildMemberList, uint32); //variable length, but nasty
|
||||
OUTv(OP_InterruptCast, InterruptCast_Struct);
|
||||
|
||||
@ -160,7 +160,7 @@ void load_opcode_names()
|
||||
opcode_map[0x0192]="LiveOP_YellForHelp";
|
||||
opcode_map[0x00ef]="LiveOP_SafePoint";
|
||||
opcode_map[0x0157]="LiveOP_Buff";
|
||||
opcode_map[0x00c0]="LiveOP_BuffFadeMsg";
|
||||
opcode_map[0x00c0]="LiveOP_ColoredText";
|
||||
opcode_map[0x0440]="LiveOP_MultiLineMsg";
|
||||
opcode_map[0x021c]="LiveOP_SpecialMesg";
|
||||
opcode_map[0x0013]="LiveOP_Consent";
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
#define OPCODE_MANAGER_H
|
||||
|
||||
#include "types.h"
|
||||
#include "Mutex.h"
|
||||
#include "mutex.h"
|
||||
#include "emu_opcodes.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "packet_dump.h"
|
||||
#include "EQPacket.h"
|
||||
#include "eq_packet.h"
|
||||
#include "../common/servertalk.h"
|
||||
|
||||
void DumpPacketAscii(const uchar* buf, uint32 size, uint32 cols, uint32 skip) {
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#include "EQStream.h"
|
||||
#include "eq_stream.h"
|
||||
#include "packet_dump_file.h"
|
||||
|
||||
void FileDumpPacketAscii(const char* filename, const uchar* buf, uint32 size, uint32 cols, uint32 skip) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1340
common/patches/client62.cpp
Normal file
1340
common/patches/client62.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
#ifndef CLIENT62_H_
|
||||
#define CLIENT62_H_
|
||||
|
||||
#include "../StructStrategy.h"
|
||||
#include "../Item.h"
|
||||
#include "../struct_strategy.h"
|
||||
#include "../item.h"
|
||||
|
||||
class EQStreamIdentifier;
|
||||
|
||||
@ -27,8 +27,8 @@ namespace Client62 {
|
||||
virtual const EQClientVersion ClientVersion() const;
|
||||
|
||||
//magic macro to declare our opcode processors
|
||||
#include "SSDeclare.h"
|
||||
#include "Client62_ops.h"
|
||||
#include "ss_declare.h"
|
||||
#include "client62_ops.h"
|
||||
|
||||
};
|
||||
|
||||
@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#ifndef CLIENT62_CONSTANTS_H_
|
||||
#define CLIENT62_CONSTANTS_H_
|
||||
|
||||
#include "../common/types.h"
|
||||
#include "../types.h"
|
||||
|
||||
namespace Client62 {
|
||||
namespace maps {
|
||||
@ -180,6 +180,7 @@ namespace Client62 {
|
||||
|
||||
namespace limits {
|
||||
static const bool ALLOWS_EMPTY_BAG_IN_BAG = false;
|
||||
static const bool ALLOWS_CLICK_CAST_FROM_BAG = false;
|
||||
static const bool COIN_HAS_WEIGHT = true;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user