diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f9c5429b..494959cbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 Import/Export Data Programs." ON) #C++11 stuff IF(NOT MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -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 @@ -302,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}" "luabind") - + INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "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") +INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm") IF(EQEMU_BUILD_LUA) ADD_SUBDIRECTORY(luabind) diff --git a/changelog.txt b/changelog.txt index cdbda16e0..9494adfce 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,473 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 02/03/2015 == +Trevius: Crashfix for TempName() when numbers are passed at the end of the name. +Uleat: Tweaking of item type exclusions to alleviate strobing conditions with light sources + +== 02/02/2015 == +Akkadius: Implement Packet logs with dumps + - Category: 41: Packet: Server -> Client With Dump + - Category: 42: Packet: Server -> Client With Dump + See: http://wiki.eqemulator.org/p?Logging_System_Overhaul#packet-logging-levels + +== 02/01/2015 == +demonstar55: Add quest debugging to lua + eq.debug("Test debug level implicit 1") + eq.debug("Test debug level explicit 1", 1) + eq.debug("Test debug level explicit 2", 2) + eq.debug("Test debug level explicit 3", 3) +Akkadius: Add Packet Logging Categories + - 5 - Packet: Client -> Server - Logs::Client_Server_Packet + - 39 - Packet: Server -> Client - Logs::Server_Client_Packet + - 40 - Packet: Client -> Server Unhandled - Logs::Client_Server_Packet_Unhandled + See: http://wiki.eqemulator.org/p?Logging_System_Overhaul#packet-logging + +== 01/31/2015 == +Trevius: Fixed FindGroundZ() and GetGroundZ() to once again utilize the X and Y arguments that are passed to them. + +== 01/30/2015 == +Akkadius: Implemented event type "EVENT_ENVIRONMENTAL_DAMAGE" + - This event triggers when taking any sort of environmental damage. Example use: + sub EVENT_ENVIRONMENTAL_DAMAGE{ + quest::debug("EVENT_ENVIRONMENTAL_DAMAGE"); + quest::debug("env_damage is " . $env_damage); + quest::debug("env_damage_type is " . $env_damage_type); + quest::debug("env_final_damage is " . $env_final_damage); + } + Result: (Test falling in Velks): http://i.imgur.com/tPRL7yL.png + - Implemented LUA counterpart of this same implementation above +Akkadius (Bobaski): Add PoK New Merchant sql/git/optional/2015_01_30_poknowledge_spell_vendors.sql + +== 01/29/2015 == +Trevius: Added more information to Mercenary Logging. +Trevius: Added potential fix for Mercenaries that fail to unsuspend. +Trevius: Added a new "statscale" field to the merc_stats table that can be used to quickly balance Mercenary Stats based on Level. +Trevius: The new "statscale" field now combines with the Mercs::ScaleRate rule value (default 100 percent for both). + +== 01/28/2015 == +Akkadius: Added Logs::DebugQuest category per request from Trevius (Great idea) + - Exported quest::debug(log_message, [debug_level = 1) + - Example: + quest::debug("This is a test debug message, level 1 (default)"); + quest::debug("This is a test debug message, level 1", 1); + quest::debug("This is a test debug message, level 2", 2); + quest::debug("This is a test debug message, level 3", 3); + + Result: http://i.imgur.com/6VoafGE.png + - Uses traditional logging system to output this category + - Required MySQL Source in Database version 9070 + +== 01/27/2015 == +Trevius: Removed "Mercenary Debug:" from the Mercenary Log entries. +Trevius: Resolved duplicate "You have no Mercenaries" messages when zoning without owning a Mercenary. +Trevius: Mercenaries should now always be able to unsuspend if the timer is up. +Trevius: More work on Mercenaries and Grouping to reduce bugs and redundant queries. +Uleat: Finished ClientVersion update to include patch file and namespace updates - don't forget to copy the renamed 'patch_UF.conf' into your eqemu directory.) + +== 01/26/2015 == +Uleat: Changed Corpse::MoveItemToCorpse() to allow 'by address' passing of removed item slot list. Fixed a bug that kept soul-bound items inside of bags from attuning properly + +== 01/25/2015 == +Trevius: Fixed an issue where Mercenaries were causing several DB queries per second while suspended. +Trevius: Added Logs::Mercenaries to the new Logging System. Logging of Mercenary information is off by default with the required SQL. + +== 01/24/2015 == +Uleat: Added equipment light source functionality to all mob derived classes (may still need tweaking...) +Notes: + - In addition to equipment light sources, innate npc_type light sources have already been activated + - Valid light source values are 0 thru 15 (values are bitmask checked and limited to 0x0F) + - Not all classes handle equipment light sources the same way due to their equipment/loot list configurations + - Spell (casting?) light sources may be implemented at some point..more information is needed + - Currently, loot list (general inventory) light sources are limited to ItemTypeMisc and ItemTypeLight to avoid issues with worn-specific light sources emitting + - Augment light sources are not recognized by the client and, therefore, not implemented in the server code + +== 01/22/2015 == +Akkadius: Massive Log System overhaul, see: http://wiki.eqemulator.org/p?Logging_System_Overhaul&frm=Main + +== 01/21/2015 == +Uleat: Added `light` field to npc_types load query (all six clients tested positive for functionality.) +Note: This only affects 'innate' light. Equipment (other) light is still in-work. +Optional SQL: utils/sql/git/optional/2015_01_21_NPC_Types_Light_Field_Primer.sql + +== 01/20/2015 == +Uleat: Fix for Inventory::_HasItemByUse(bucket) using the parent container when searching for bag container items. + +== 01/19/2015 == +Uleat: Changed 'enum EQClientVersion' to 'enum class ClientVersion.' Other light modifications were made to accommodate this namespace. Added 'RoF2' to the lua client version enumeration. + +== 01/15/2015 == +Uleat: Attempted fix for elusive inventory bug: + - Removed 'iter_queue' typedef and converted lcast to explicit or auto defines + - Reworked several functions that manipulate the cursor queue + - Found/corrected one occurrence of post-processing iterator incrementing in an ItemInstQueue handler + - Added many scope declarations in code that handles inventory manipulation (loose macros are bad...) +Uleat: Added Item_Struct pointer checks to ItemInst methods that did not have them +Uleat: Changed IsEquippable(race,class) to use bit-wise 'and' (&) over '(x%2)==1' in conditional check. +Uleat: Changed DyeArmor() assignment of 'armor_color' to use bit-wise 'or' and bit-shifting (|,<<) over multiplication and addition (*,+). + +== 01/13/2015 == +Uleat: Placed an upper limit on the cursor queue save loop. +Trevius: (RoF2) Guild invites now add new members as members instead of recruits, and /guild chat works properly. +Trevius: (RoF2) Guild Promote is now functional. + +== 01/12/2015 == +Uleat: Fix for OP_FormattedMessage text link server crashes +Uleat: Added text link translators for OP_TaskDescription (RoF+ -- all clients current) +Uleat: Fix for load_bots.sql using '\\' as a delimiter (Changed to '$$') + +== 01/11/2015 == +Uleat: Added text link translators for OP_TaskDescription (Ti thru UF..RoF+ in-work) + +== 01/10/2015 == +Uleat: Added text link translators for OP_Emote + +== 01/09/2015 == +Uleat: Added text link translators for OP_FormattedMessage + +== 01/08/2015 == +Trevius: Added some extra checks and clean-up related to Groups and Mercenaries. + +== 01/07/2015 == +Uleat: Excluded text link body from message scrambling in Client::GarbleMessage() +Trevius: Mercenaries now load directly from tables only. The vwMercNpcTypes view is no longer required and can be deleted. +Trevius: Query fix for group_leaders table. This may resolve some crashes/bugs related to Mercs/Bots and Groups. + +== 01/06/2015 == +Trevius: Changed the pet command #defines to be based on RoF2 list of pet commands and added decodes to Titanium, SoF and SoD. +Trevius: (RoF+) The /pet focus on/off and /pet hold on/off commands are now functional. +Trevius: Added defines for all remaining pet commands and some support for them as well. + +== 01/05/2015 == +Uleat: Fixed (added translators for) item/text links. Only 'OP_ChannelMessage' and 'OP_SpecialMesg' are currently handled..more text channels will be added as the need arises. + +== 01/03/2015 == +Trevius: (RoF2) /shield (shielding) and /key (key ring) are both now functional after opcode updates. + +== 01/02/2015 == +Trevius: (RoF2) *Hopefully* Fixed looting incorrect items from NPCs. Please report any issues! +Trevius: (RoF2) Now able to loot items past the 10th slot on NPC corpses. +Trevius: Attuned Items can now be auto-looted and will equip properly. +Trevius: Mercenaries and Bots will no longer take a share from /split or /autosplit. + +== 12/30/2014 == +Trevius: (RoF2) Aug Type 21 no longer shows the "Buy Now" button in the aug slot of items. +Trevius: (RoF2) Identified the "Copied" item flag with the help of Uleat. + +== 12/29/2014 == +Trevius: (RoF2) Identified a few Item Fields and resolved an issue with cloth armor not accepting certain augments that they should. +Akkadius: Updated $client->UpdateTaskActivity to have optional argument ignore_quest_update IE: Client::UpdateTaskActivity(THIS, TaskID, ActivityID, Count, [ignore_quest_update]) +Akkadius: Also updated internal UpdateTaskActivity methods to optionally ignore quest based task updates to prevent feedback + +== 12/28/2014 == +Uleat: Implemented class Client::TextLink as a replacement for the dozens of individual link formatters. + +== 12/27/2014 == +Akkadius: Add option to automatic database upgrade script 5) Download latest Opcodes from Github +Trevius: (RoF2) Fixed dropping items on the ground so they go to ground level instead of camera height. +Trevius: Show Helm Option should be functional again. +Kayen: Implemened npc special ability (43) CASTING_RESIST_DIFF which sets innate resist modifier on +ALL spells used by that NPC. Ie. 43,1,-200 will set a -200 innate resist diff, so if your npc cast +a spell that has a -10 resist modifier the final resist diff would be -210. + +== 12/25/2014 == +Uleat: Updated 'links' code for all clients + +== 12/24/2014 == +Trevius: (RoF+) Added herosforgemodel field to the npc_types table. +Trevius: (RoF2) Updated item links from #npcstat command output. +Trevius: (RoF+) Implemented Hero's Forge Armor for NPCs. Set the herosforgemodel field in npc_types table to the model (example: 84 for full set, or 12107 for robe). +Trevius: (RoF+) Hero's Forge Armor now overrides NPC texture settings. To display Hero's Forge Armor Helms, set helmtexture field to anything other than 0. + +== 12/23/2014 == +Uleat: Tidied up some ItemInst* declarations and added some nullptr checks. +Trevius: (RoF+) Added support for Hero's Forge Robe Models. Set herosforgemodel field in items table to exact model such as 11607, 11707, etc. + +== 12/22/2014 == +Trevius: (RoF2) Fixed Tracking. +Trevius: (RoF+) Added a work-around for the cursor buffer issue. + +== 12/21/2014 == +Trevius: (RoF2) Fixed Extended Targets Window by correcting opcodes. +Trevius: (RoF/RoF2) Fixed Guild Rank in the Player Profile, which prevents the guild rank message on login/zone. + +== 12/20/2014 == +Akkadius: Updated #cvs to display RoF2 Client Stream count + +== 12/19/2014 == +Trevius: (RoF2) Fixed Leadership AA Purchasing and Recipe Search by correcting opcodes. +Trevius: Fixed Armor Tinting (players and NPCs) that was broken during a previous update. +Trevius: (RoF2) Fixed Rest Timer, Show Helm Option, Auto-Consent Options, and identified Krono in the PP. +Trevius: Fixed Selling for Alternate Currency Merchants for RoF and RoF2. + +== 12/18/2014 == +Trevius: Finished lining up the RoF2 Player Profile Struct. Zone times are now normal, and everything from the PP is accurate in game now. +Trevius: Fixed zoning after death for RoF2. + +== 12/17/2014 == +demonstar55: Use vectors for route stuff, should be more CPU cache friendly so faster +Secrets: EQStream changes as recommended by a community member in private. + +== 12/15/2014 == +Trevius: (RoF+) Implemented the 6th Augment Slot for Items. +Trevius: Player Corpses now saved attuned settings for Items. + +Required SQL: utils/sql/git/required/2014_12_15_multiple_table_updates.sql + +== 12/13/2014 == +demonstar55: Fix guild rank spam on zone (needed to be in OP_PP). +Trevius: (RoF+) Implemented Armor Ornamentation using Hero's Forge Armor Models. To use, create an ornamentation augment and set the herosforgemodel field in the items table. +Trevius: (RoF+) Added command #heromodel (#hm for short) - Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63) + +Be sure to run this or there will be item loss: +Required SQL: utils/sql/git/required/2014_12_13_inventory_table_update.sql + +== 12/12/2014 == +demonstar55: Add special attack 42, Ignore Root Aggro Rules. This allows you to root a mob and have them still use the normal aggro rules (so they will attack the one with most hate, not closest) + +== 12/09/2014 == +Trevius: (RoF+) Implemented Hero's Forge Armor Models for Items. To use, set herosforgemodel field in the item table to a model number such as 63 (for example). +demonstar55: SoF+ swarm pets will no longer be F8able (without a hack!) + +== 12/08/2014 == +Secrets: Added a feature that allows an EQ client to log in directly to World without having to enter the LoginServer, provided the 'password' field is set in WorldServer. + +== 12/04/2014 == +Kayen: Ranged attacks will now more accurately check MAX firing range, fixing the issue where you would +hit ranged attack and nothing would happpen due to incorrect server side range checks. +Trevius: Initial addition of the RoF2 client from May 10th 2013 (currently available on Steam as the F2P client). +Trevius: RoF2 is disabled by default, but you can enable by editing /common/patches/patches.cpp (see comments) + +== 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 diff --git a/client_files/export/main.cpp b/client_files/export/main.cpp index e9b127aad..865fbd6d8 100644 --- a/client_files/export/main.cpp +++ b/client_files/export/main.cpp @@ -17,7 +17,9 @@ */ #include -#include "../../common/debug.h" + +#include "../../common/eqemu_logsys.h" +#include "../../common/global_define.h" #include "../../common/shareddb.h" #include "../../common/eqemu_config.h" #include "../../common/platform.h" @@ -25,47 +27,53 @@ #include "../../common/rulesys.h" #include "../../common/string_util.h" +EQEmuLogSys Log; + void ExportSpells(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db); void ExportBaseData(SharedDatabase *db); int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformClientExport); + Log.LoadLogSettingsDefaults(); set_exception_handler(); - LogFile->write(EQEMuLog::Status, "Client Files Export Utility"); + Log.Out(Logs::General, Logs::Status, "Client Files Export Utility"); if(!EQEmuConfig::LoadConfig()) { - LogFile->write(EQEMuLog::Error, "Unable to load configuration file."); + Log.Out(Logs::General, Logs::Error, "Unable to load configuration file."); return 1; } const EQEmuConfig *config = EQEmuConfig::get(); - if(!load_log_settings(config->LogSettingsFile.c_str())) { - LogFile->write(EQEMuLog::Error, "Warning: unable to read %s.", config->LogSettingsFile.c_str()); - } SharedDatabase database; - LogFile->write(EQEMuLog::Status, "Connecting to database..."); + Log.Out(Logs::General, Logs::Status, "Connecting to database..."); if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { - LogFile->write(EQEMuLog::Error, "Unable to connect to the database, cannot continue without a " + Log.Out(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a " "database connection"); return 1; } + /* Register Log System and Settings */ + database.LoadLogSettings(Log.log_settings); + Log.StartFileLogs(); + ExportSpells(&database); ExportSkillCaps(&database); ExportBaseData(&database); + Log.CloseFileLogs(); + return 0; } void ExportSpells(SharedDatabase *db) { - LogFile->write(EQEMuLog::Status, "Exporting Spells..."); + Log.Out(Logs::General, Logs::Status, "Exporting Spells..."); FILE *f = fopen("export/spells_us.txt", "w"); if(!f) { - LogFile->write(EQEMuLog::Error, "Unable to open export/spells_us.txt to write, skipping."); + Log.Out(Logs::General, Logs::Error, "Unable to open export/spells_us.txt to write, skipping."); return; } @@ -89,7 +97,6 @@ void ExportSpells(SharedDatabase *db) { fprintf(f, "%s\n", line.c_str()); } } else { - LogFile->write(EQEMuLog::Error, "Error in ExportSpells query '%s' %s", query.c_str(), results.ErrorMessage().c_str()); } fclose(f); @@ -103,7 +110,6 @@ bool SkillUsable(SharedDatabase *db, int skill_id, int class_id) { 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; } @@ -123,7 +129,6 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) { 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; } @@ -135,11 +140,11 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) { } void ExportSkillCaps(SharedDatabase *db) { - LogFile->write(EQEMuLog::Status, "Exporting Skill Caps..."); + Log.Out(Logs::General, Logs::Status, "Exporting Skill Caps..."); FILE *f = fopen("export/SkillCaps.txt", "w"); if(!f) { - LogFile->write(EQEMuLog::Error, "Unable to open export/SkillCaps.txt to write, skipping."); + Log.Out(Logs::General, Logs::Error, "Unable to open export/SkillCaps.txt to write, skipping."); return; } @@ -164,11 +169,11 @@ void ExportSkillCaps(SharedDatabase *db) { } void ExportBaseData(SharedDatabase *db) { - LogFile->write(EQEMuLog::Status, "Exporting Base Data..."); + Log.Out(Logs::General, Logs::Status, "Exporting Base Data..."); FILE *f = fopen("export/BaseData.txt", "w"); if(!f) { - LogFile->write(EQEMuLog::Error, "Unable to open export/BaseData.txt to write, skipping."); + Log.Out(Logs::General, Logs::Error, "Unable to open export/BaseData.txt to write, skipping."); return; } @@ -190,7 +195,6 @@ void ExportBaseData(SharedDatabase *db) { fprintf(f, "%s\n", line.c_str()); } } else { - LogFile->write(EQEMuLog::Error, "Error in ExportBaseData query '%s' %s", query.c_str(), results.ErrorMessage().c_str()); } fclose(f); diff --git a/client_files/import/main.cpp b/client_files/import/main.cpp index 9683e3bfe..a8477f77a 100644 --- a/client_files/import/main.cpp +++ b/client_files/import/main.cpp @@ -16,7 +16,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../../common/debug.h" +#include "../../common/eqemu_logsys.h" +#include "../../common/global_define.h" #include "../../common/shareddb.h" #include "../../common/eqemu_config.h" #include "../../common/platform.h" @@ -24,38 +25,43 @@ #include "../../common/rulesys.h" #include "../../common/string_util.h" +EQEmuLogSys Log; + void ImportSpells(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db); void ImportBaseData(SharedDatabase *db); int main(int argc, char **argv) { RegisterExecutablePlatform(ExePlatformClientImport); + Log.LoadLogSettingsDefaults(); set_exception_handler(); - LogFile->write(EQEMuLog::Status, "Client Files Import Utility"); + Log.Out(Logs::General, Logs::Status, "Client Files Import Utility"); if(!EQEmuConfig::LoadConfig()) { - LogFile->write(EQEMuLog::Error, "Unable to load configuration file."); + Log.Out(Logs::General, Logs::Error, "Unable to load configuration file."); return 1; } const EQEmuConfig *config = EQEmuConfig::get(); - if(!load_log_settings(config->LogSettingsFile.c_str())) { - LogFile->write(EQEMuLog::Error, "Warning: unable to read %s.", config->LogSettingsFile.c_str()); - } SharedDatabase database; - LogFile->write(EQEMuLog::Status, "Connecting to database..."); + Log.Out(Logs::General, Logs::Status, "Connecting to database..."); if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(), config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { - LogFile->write(EQEMuLog::Error, "Unable to connect to the database, cannot continue without a " + Log.Out(Logs::General, Logs::Error, "Unable to connect to the database, cannot continue without a " "database connection"); return 1; } + database.LoadLogSettings(Log.log_settings); + Log.StartFileLogs(); + ImportSpells(&database); ImportSkillCaps(&database); ImportBaseData(&database); + Log.CloseFileLogs(); + return 0; } @@ -64,7 +70,6 @@ int GetSpellColumns(SharedDatabase *db) { 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; } @@ -72,10 +77,10 @@ int GetSpellColumns(SharedDatabase *db) { } void ImportSpells(SharedDatabase *db) { - LogFile->write(EQEMuLog::Status, "Importing Spells..."); + Log.Out(Logs::General, Logs::Status, "Importing Spells..."); FILE *f = fopen("import/spells_us.txt", "r"); if(!f) { - LogFile->write(EQEMuLog::Error, "Unable to open import/spells_us.txt to read, skipping."); + Log.Out(Logs::General, Logs::Error, "Unable to open import/spells_us.txt to read, skipping."); return; } @@ -138,23 +143,23 @@ void ImportSpells(SharedDatabase *db) { spells_imported++; if(spells_imported % 1000 == 0) { - LogFile->write(EQEMuLog::Status, "%d spells imported.", spells_imported); + Log.Out(Logs::General, Logs::Status, "%d spells imported.", spells_imported); } } if(spells_imported % 1000 != 0) { - LogFile->write(EQEMuLog::Status, "%d spells imported.", spells_imported); + Log.Out(Logs::General, Logs::Status, "%d spells imported.", spells_imported); } fclose(f); } void ImportSkillCaps(SharedDatabase *db) { - LogFile->write(EQEMuLog::Status, "Importing Skill Caps..."); + Log.Out(Logs::General, Logs::Status, "Importing Skill Caps..."); FILE *f = fopen("import/SkillCaps.txt", "r"); if(!f) { - LogFile->write(EQEMuLog::Error, "Unable to open import/SkillCaps.txt to read, skipping."); + Log.Out(Logs::General, Logs::Error, "Unable to open import/SkillCaps.txt to read, skipping."); return; } @@ -186,11 +191,11 @@ void ImportSkillCaps(SharedDatabase *db) { } void ImportBaseData(SharedDatabase *db) { - LogFile->write(EQEMuLog::Status, "Importing Base Data..."); + Log.Out(Logs::General, Logs::Status, "Importing Base Data..."); FILE *f = fopen("import/BaseData.txt", "r"); if(!f) { - LogFile->write(EQEMuLog::Error, "Unable to open import/BaseData.txt to read, skipping."); + Log.Out(Logs::General, Logs::Error, "Unable to open import/BaseData.txt to read, skipping."); return; } diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ac42f5e4e..f847957db 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -8,8 +8,9 @@ SET(common_sources crc16.cpp crc32.cpp database.cpp + database_conversions.cpp + database_instances.cpp dbcore.cpp - debug.cpp emu_opcodes.cpp emu_tcp_connection.cpp emu_tcp_server.cpp @@ -18,7 +19,7 @@ SET(common_sources eqdb_res.cpp eqemu_exception.cpp eqemu_config.cpp - eqemu_error.cpp + eqemu_logsys.cpp eq_packet.cpp eq_stream.cpp eq_stream_factory.cpp @@ -31,13 +32,10 @@ SET(common_sources guilds.cpp ipc_mutex.cpp item.cpp - logsys.cpp - logsys_eqemu.cpp md5.cpp memory_mapped_file.cpp misc.cpp misc_functions.cpp - moremath.cpp mutex.cpp mysql_request_result.cpp mysql_request_row.cpp @@ -67,13 +65,13 @@ SET(common_sources worldconn.cpp xml_parser.cpp platform.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/uf.cpp SocketLib/Base64.cpp SocketLib/File.cpp SocketLib/HttpdCookies.cpp @@ -97,7 +95,6 @@ SET(common_headers base_packet.h base_data.h bodytypes.h - breakdowns.h classes.h condition.h crash.h @@ -106,7 +103,6 @@ SET(common_headers data_verification.h database.h dbcore.h - debug.h deity.h emu_opcodes.h emu_oplist.h @@ -120,7 +116,7 @@ SET(common_headers eqemu_exception.h eqemu_config.h eqemu_config_elements.h - eqemu_error.h + eqemu_logsys.h eq_packet.h eq_stream.h eq_stream_factory.h @@ -136,6 +132,7 @@ SET(common_headers features.h fixed_memory_hash_set.h fixed_memory_variable_hash_set.h + global_define.h guild_base.h guilds.h ipc_mutex.h @@ -144,15 +141,12 @@ SET(common_headers item_struct.h languages.h linked_list.h - logsys.h - logtypes.h loottable.h mail_oplist.h md5.h memory_mapped_file.h misc.h misc_functions.h - moremath.h mutex.h mysql_request_result.h mysql_request_row.h @@ -168,6 +162,7 @@ SET(common_headers ptimer.h queue.h races.h + random.h rdtsc.h rulesys.h ruletypes.h @@ -191,11 +186,6 @@ SET(common_headers worldconn.h xml_parser.h zone_numbers.h - patches/client62.h - patches/client62_constants.h - patches/client62_itemfields.h - patches/client62_ops.h - patches/client62_structs.h patches/patches.h patches/sod.h patches/sod_constants.h @@ -216,16 +206,21 @@ SET(common_headers 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/uf.h + patches/uf_constants.h + patches/uf_itemfields.h + patches/uf_ops.h + patches/uf_structs.h SocketLib/Base64.h SocketLib/File.h SocketLib/HttpdCookies.h @@ -244,11 +239,6 @@ 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/patches.h patches/sod.h patches/sod_itemfields.h @@ -269,23 +259,28 @@ SOURCE_GROUP(Patches FILES 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/uf.h + patches/uf_itemfields.h + patches/uf_ops.h + patches/uf_constants.h + patches/uf_structs.h patches/patches.cpp patches/sod.cpp patches/sof.cpp patches/rof.cpp + patches/rof2.cpp patches/titanium.cpp - patches/underfoot.cpp + patches/uf.cpp ) SOURCE_GROUP(SocketLib FILES @@ -334,7 +329,9 @@ ADD_LIBRARY(common ${common_sources} ${common_headers}) IF(UNIX) ADD_DEFINITIONS(-fPIC) - 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/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0) ENDIF(UNIX) + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) diff --git a/common/SocketLib/HTTPSocket.cpp b/common/SocketLib/HTTPSocket.cpp index ecde78403..da4f2264c 100644 --- a/common/SocketLib/HTTPSocket.cpp +++ b/common/SocketLib/HTTPSocket.cpp @@ -40,7 +40,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef _WIN32 #pragma warning(disable:4786) #endif -#include "../debug.h" +#include "../global_define.h" #include #include #include diff --git a/common/SocketLib/HttpdCookies.cpp b/common/SocketLib/HttpdCookies.cpp index 4d9fccb1b..a40200aab 100644 --- a/common/SocketLib/HttpdCookies.cpp +++ b/common/SocketLib/HttpdCookies.cpp @@ -26,7 +26,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "../debug.h" +#include "../global_define.h" #ifdef _WIN32 #pragma warning(disable:4786) #endif diff --git a/common/SocketLib/HttpdSocket.cpp b/common/SocketLib/HttpdSocket.cpp index bd803877a..21c2938d4 100644 --- a/common/SocketLib/HttpdSocket.cpp +++ b/common/SocketLib/HttpdSocket.cpp @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef _WIN32 #pragma warning(disable:4786) #endif -#include "../debug.h" +#include "../global_define.h" #include "Utility.h" #include "HttpdCookies.h" #include "HttpdForm.h" @@ -194,7 +194,6 @@ void HttpdSocket::OnHeaderComplete() void HttpdSocket::OnData(const char *p,size_t l) { -//printf("Got %d bytes: %.*s\n", l, l, p); if (m_file) { m_file -> fwrite(p,1,l); diff --git a/common/SocketLib/MemFile.cpp b/common/SocketLib/MemFile.cpp index 7c50356f8..c621666e5 100644 --- a/common/SocketLib/MemFile.cpp +++ b/common/SocketLib/MemFile.cpp @@ -110,7 +110,6 @@ size_t MemFile::fread(char *ptr, size_t size, size_t nmemb) size_t sz = size * nmemb; if (p + sz < BLOCKSIZE) { -//printf("Read @ %d(%d). %d bytes. (%c)\n", m_read_ptr, p, sz, *(m_current_read -> data + p)); memcpy(ptr, m_current_read -> data + p, sz); m_read_ptr += sz; } @@ -142,7 +141,6 @@ size_t MemFile::fwrite(const char *ptr, size_t size, size_t nmemb) size_t sz = size * nmemb; if (p + sz < BLOCKSIZE) { -//printf("Write @ %d(%d). %d bytes.\n", m_write_ptr, p, sz); memcpy(m_current_write -> data + p, ptr, sz); m_write_ptr += sz; } diff --git a/common/StackWalker/StackWalker.cpp b/common/StackWalker/StackWalker.cpp index 6931c30f5..d457a2231 100644 --- a/common/StackWalker/StackWalker.cpp +++ b/common/StackWalker/StackWalker.cpp @@ -1128,7 +1128,6 @@ BOOL __stdcall StackWalker::myReadProcMem( SIZE_T st; BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st); *lpNumberOfBytesRead = (DWORD) st; - //printf("ReadMemory: hProcess: %p, baseAddr: %p, buffer: %p, size: %d, read: %d, result: %d\n", hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, (DWORD) st, (DWORD) bRet); return bRet; } else diff --git a/common/base_packet.cpp b/common/base_packet.cpp index 44b3643b5..ce6afe978 100644 --- a/common/base_packet.cpp +++ b/common/base_packet.cpp @@ -15,13 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" + +#include "global_define.h" #include "base_packet.h" #include "misc.h" #include "packet_dump.h" - - BasePacket::BasePacket(const unsigned char *buf, uint32 len) { this->pBuffer=nullptr; diff --git a/common/base_packet.h b/common/base_packet.h index 4952e29d2..facd98809 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -21,7 +21,6 @@ #include "types.h" #include #include -#include #ifdef WIN32 #include diff --git a/common/breakdowns.h b/common/breakdowns.h deleted file mode 100644 index 18dfb803f..000000000 --- a/common/breakdowns.h +++ /dev/null @@ -1,134 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 BREAKDOWNS_H_ -#define BREAKDOWNS_H_ - -#include "types.h" - - -#pragma pack(1) -struct uint16_breakdown { - union { - uint16 all; - struct { - uint8 b1; - uint8 b2; - } bytes; - }; - inline uint16& operator=(const uint16& val) { return (all=val); } - inline uint16* operator&() { return &all; } - inline operator uint16&() { return all; } - inline uint8& b1() { return bytes.b1; } - inline uint8& b2() { return bytes.b2; } -}; - -struct uint32_breakdown { - union { - uint32 all; - struct { - uint16 w1; - uint16 w2; - } words; - struct { - uint8 b1; - union { - struct { - uint8 b2; - uint8 b3; - } middle; - uint16 w2_3; // word bytes 2 to 3 - }; - uint8 b4; - } bytes; - }; - inline uint32& operator=(const uint32& val) { return (all=val); } - inline uint32* operator&() { return &all; } - inline operator uint32&() { return all; } - - inline uint16& w1() { return words.w1; } - inline uint16& w2() { return words.w2; } - inline uint16& w2_3() { return bytes.w2_3; } - inline uint8& b1() { return bytes.b1; } - inline uint8& b2() { return bytes.middle.b2; } - inline uint8& b3() { return bytes.middle.b3; } - inline uint8& b4() { return bytes.b4; } -}; -/* -struct uint64_breakdown { - union { - uint64 all; - struct { - uint16 w1; // 1 2 - uint16 w2; // 3 4 - uint16 w3; // 5 6 - uint16 w4; // 7 8 - }; - struct { - uint32 dw1; // 1 4 - uint32 dw2; // 5 6 - }; - struct { - uint8 b1; - union { - struct { - uint16 w2_3; - uint16 w4_5; - uint16 w6_7; - }; - uint32 dw2_5; - struct { - uint8 b2; - union { - uint32 dw3_6; - struct { - uint8 b3; - union { - uint32 dw4_7; - struct { - uint8 b4; - uint8 b5; - uint8 b6; - uint8 b7; - }; - }; - }; - }; - }; - }; - }; - }; - inline uint64* operator&() { return &all; } - inline operator uint64&() { return all; } -}; -*/ -#pragma pack() - - - - - - - - - - - - - - -#endif /*BREAKDOWNS_H_*/ diff --git a/common/classes.cpp b/common/classes.cpp index a1a3bf05a..1f54c9234 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -14,8 +14,8 @@ 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 -*/ -#include "../common/debug.h" + */ +#include "../common/global_define.h" #include "../common/classes.h" const char* GetEQClassName(uint8 class_, uint8 level) { @@ -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; -} - diff --git a/common/classes.h b/common/classes.h index b70609379..c2f0c8acf 100644 --- a/common/classes.h +++ b/common/classes.h @@ -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 diff --git a/common/clientversions.h b/common/clientversions.h index ee70d481c..d0b5f7c41 100644 --- a/common/clientversions.h +++ b/common/clientversions.h @@ -1,75 +1,76 @@ #ifndef CLIENTVERSIONS_H #define CLIENTVERSIONS_H +#include "types.h" + static const uint32 BIT_Client62 = 1; static const uint32 BIT_Titanium = 2; static const uint32 BIT_SoF = 4; static const uint32 BIT_SoD = 8; -static const uint32 BIT_Underfoot = 16; +static const uint32 BIT_UF = 16; static const uint32 BIT_RoF = 32; static const uint32 BIT_RoF2 = 64; static const uint32 BIT_TitaniumAndEarlier = 0x00000003; static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; -static const uint32 BIT_UnderfootAndLater = 0xFFFFFFF0; +static const uint32 BIT_UFAndLater = 0xFFFFFFF0; static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; static const uint32 BIT_AllClients = 0xFFFFFFFF; -typedef enum +enum class ClientVersion { - EQClientUnknown = 0, - EQClient62, // Build: 'Aug 4 2005 15:40:59' - EQClientTitanium, // Build: 'Oct 31 2005 10:33:37' - EQClientSoF, // Build: 'Sep 7 2007 09:11:49' - EQClientSoD, // Build: 'Dec 19 2008 15:22:49' - EQClientUnderfoot, // Build: 'Jun 8 2010 16:44:32' - EQClientRoF, // Build: 'Dec 10 2012 17:35:44' - EQClientRoF2, // Build: 'May 10 2013 23:30:08' + Unknown = 0, + Client62, // Build: 'Aug 4 2005 15:40:59' + Titanium, // Build: 'Oct 31 2005 10:33:37' + SoF, // Build: 'Sep 7 2007 09:11:49' + SoD, // Build: 'Dec 19 2008 15:22:49' + UF, // Build: 'Jun 8 2010 16:44:32' + RoF, // Build: 'Dec 10 2012 17:35:44' + RoF2, // Build: 'May 10 2013 23:30:08' - _EQClientCount, // place new clients before this point (preferably, in release/attribute order) + MobNPC, + MobMerc, + MobBot, + MobPet, +}; - // Values below are not implemented, as yet... +#define CLIENT_VERSION_COUNT 12 +#define LAST_PC_CLIENT ClientVersion::RoF2 +#define LAST_NPC_CLIENT ClientVersion::MobPet - EmuNPC = _EQClientCount, - EmuMerc, - EmuBot, - EmuPet, - _EmuClientCount // array size for EQLimits -} EQClientVersion; - -static const char* EQClientVersionName(EQClientVersion version) +static const char* ClientVersionName(ClientVersion 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"; + case ClientVersion::Unknown: + return "ClientVersion::Unknown"; + case ClientVersion::Client62: + return "ClientVersion::Client62"; + case ClientVersion::Titanium: + return "ClientVersion::Titanium"; + case ClientVersion::SoF: + return "ClientVersion::SoF"; + case ClientVersion::SoD: + return "ClientVersion::SoD"; + case ClientVersion::UF: + return "ClientVersion::UF"; + case ClientVersion::RoF: + return "ClientVersion::RoF"; + case ClientVersion::RoF2: + return "ClientVersion::RoF2"; + case ClientVersion::MobNPC: + return "ClientVersion::MobNPC"; + case ClientVersion::MobMerc: + return "ClientVersion::MobMerc"; + case ClientVersion::MobBot: + return "ClientVersion::MobBot"; + case ClientVersion::MobPet: + return "ClientVersion::MobPet"; default: - return "ERROR: Invalid EQClientVersion"; + return " Invalid ClientVersion"; }; } diff --git a/common/condition.cpp b/common/condition.cpp index 2dc90b26d..334ce5d45 100644 --- a/common/condition.cpp +++ b/common/condition.cpp @@ -16,7 +16,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" #include "condition.h" #ifdef _WINDOWS diff --git a/common/condition.h b/common/condition.h index bfbffe760..9c4cd9f7b 100644 --- a/common/condition.h +++ b/common/condition.h @@ -18,7 +18,8 @@ #ifndef __CONDITION_H #define __CONDITION_H -#include "debug.h" +#include "global_define.h" +#include "mutex.h" #ifndef WIN32 #include #endif diff --git a/common/crash.cpp b/common/crash.cpp index 5ce1229a5..1f700f151 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -1,4 +1,5 @@ -#include "debug.h" +#include "global_define.h" +#include "eqemu_logsys.h" #include "crash.h" #if defined(_WINDOWS) && defined(CRASH_LOGGING) @@ -24,7 +25,7 @@ public: } } - LogFile->write(EQEMuLog::Crash, buffer); + Log.Out(Logs::General, Logs::Crash, buffer); StackWalker::OnOutput(szText); } }; @@ -34,67 +35,67 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) switch(ExceptionInfo->ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_ACCESS_VIOLATION"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_ACCESS_VIOLATION"); break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); break; case EXCEPTION_BREAKPOINT: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_BREAKPOINT"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_BREAKPOINT"); break; case EXCEPTION_DATATYPE_MISALIGNMENT: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_DATATYPE_MISALIGNMENT"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_DATATYPE_MISALIGNMENT"); break; case EXCEPTION_FLT_DENORMAL_OPERAND: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_DENORMAL_OPERAND"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_DENORMAL_OPERAND"); break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_DIVIDE_BY_ZERO"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_DIVIDE_BY_ZERO"); break; case EXCEPTION_FLT_INEXACT_RESULT: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_INEXACT_RESULT"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_INEXACT_RESULT"); break; case EXCEPTION_FLT_INVALID_OPERATION: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_INVALID_OPERATION"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_INVALID_OPERATION"); break; case EXCEPTION_FLT_OVERFLOW: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_OVERFLOW"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_OVERFLOW"); break; case EXCEPTION_FLT_STACK_CHECK: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_STACK_CHECK"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_STACK_CHECK"); break; case EXCEPTION_FLT_UNDERFLOW: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_UNDERFLOW"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_UNDERFLOW"); break; case EXCEPTION_ILLEGAL_INSTRUCTION: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_ILLEGAL_INSTRUCTION"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_ILLEGAL_INSTRUCTION"); break; case EXCEPTION_IN_PAGE_ERROR: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_IN_PAGE_ERROR"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_IN_PAGE_ERROR"); break; case EXCEPTION_INT_DIVIDE_BY_ZERO: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_INT_DIVIDE_BY_ZERO"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_INT_DIVIDE_BY_ZERO"); break; case EXCEPTION_INT_OVERFLOW: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_INT_OVERFLOW"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_INT_OVERFLOW"); break; case EXCEPTION_INVALID_DISPOSITION: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_INVALID_DISPOSITION"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_INVALID_DISPOSITION"); break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_NONCONTINUABLE_EXCEPTION"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_NONCONTINUABLE_EXCEPTION"); break; case EXCEPTION_PRIV_INSTRUCTION: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_PRIV_INSTRUCTION"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_PRIV_INSTRUCTION"); break; case EXCEPTION_SINGLE_STEP: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_SINGLE_STEP"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_SINGLE_STEP"); break; case EXCEPTION_STACK_OVERFLOW: - LogFile->write(EQEMuLog::Crash, "EXCEPTION_STACK_OVERFLOW"); + Log.Out(Logs::General, Logs::Crash, "EXCEPTION_STACK_OVERFLOW"); break; default: - LogFile->write(EQEMuLog::Crash, "Unknown Exception"); + Log.Out(Logs::General, Logs::Crash, "Unknown Exception"); break; } diff --git a/common/database.cpp b/common/database.cpp index 1af4d05a0..736104f6e 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1,5 +1,5 @@ /* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net) + Copyright (C) 2001-2015 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 @@ -15,21 +15,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/debug.h" + +#include "../common/global_define.h" #include "../common/rulesys.h" -#include -#include + +#include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include // Disgrace: for windows compile #ifdef _WINDOWS @@ -45,31 +42,12 @@ #include "database.h" #include "eq_packet_structs.h" -#include "guilds.h" -#include "string_util.h" #include "extprofile.h" +#include "string_util.h" + extern Client client; -#ifdef _WINDOWS -#if _MSC_VER > 1700 // greater than 2012 (2013+) -# define _ISNAN_(a) std::isnan(a) -#else -# include -# define _ISNAN_(a) _isnan(a) -#endif -#else -# define _ISNAN_(a) std::isnan(a) -#endif - -/* -Establish a connection to a mysql database with the supplied parameters - - Added a very simple .ini file parser - Bounce - - Modify to use for win32 & linux - misanthropicfiend -*/ -Database::Database () -{ +Database::Database () { DBInitVars(); } @@ -87,12 +65,11 @@ bool Database::Connect(const char* host, const char* user, const char* passwd, c uint32 errnum= 0; char errbuf[MYSQL_ERRMSG_SIZE]; if (!Open(host, user, passwd, database, port, &errnum, errbuf)) { - LogFile->write(EQEMuLog::Error, "Failed to connect to database: Error: %s", errbuf); - + Log.Out(Logs::General, Logs::Error, "Failed to connect to database: Error: %s", errbuf); return false; } else { - LogFile->write(EQEMuLog::Status, "Using database '%s' at %s:%d",database,host,port); + Log.Out(Logs::General, Logs::Status, "Using database '%s' at %s:%d", database, host,port); return true; } } @@ -102,10 +79,11 @@ void Database::DBInitVars() { varcache_max = 0; varcache_lastupdate = 0; } -/* -Close the connection to the database +/* + Close the connection to the database */ + Database::~Database() { unsigned int x; @@ -118,9 +96,9 @@ Database::~Database() } /* -Check if there is an account with name "name" and password "password" -Return the account id or zero if no account matches. -Zero will also be returned if there is a database error. + Check if there is an account with name "name" and password "password" + Return the account id or zero if no account matches. + Zero will also be returned if there is a database error. */ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStatus) { @@ -140,7 +118,6 @@ uint32 Database::CheckLogin(const char* name, const char* password, int16* oStat if (!results.Success()) { - std::cerr << "Error in CheckLogin query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -166,7 +143,6 @@ bool Database::CheckBannedIPs(const char* loginIP) if (!results.Success()) { - std::cerr << "Error in CheckBannedIPs query '" << query << "' " << results.ErrorMessage() << std::endl; return true; } @@ -180,7 +156,6 @@ bool Database::AddBannedIP(char* bannedIP, const char* notes) { std::string query = StringFormat("INSERT into Banned_IPs SET ip_address='%s', notes='%s'", bannedIP, notes); auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in Database::AddBannedIP query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } return true; @@ -207,9 +182,7 @@ bool Database::AddGMIP(char* ip_address, char* name) { void Database::LoginIP(uint32 AccountID, const char* LoginIP) { std::string query = StringFormat("INSERT INTO account_ip SET accid=%i, ip='%s' ON DUPLICATE KEY UPDATE count=count+1, lastused=now()", AccountID, LoginIP); - auto results = QueryDatabase(query); - if (!results.Success()) - std::cerr << "Error in Log IP query '" << query << "' " << results.ErrorMessage() << std::endl; + QueryDatabase(query); } int16 Database::CheckStatus(uint32 account_id) { @@ -218,7 +191,6 @@ int16 Database::CheckStatus(uint32 account_id) { auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in CheckStatus query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -250,17 +222,15 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta else query = StringFormat("INSERT INTO account SET name='%s', status=%i, lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, lsaccount_id); - std::cerr << "Account Attempting to be created:" << name << " " << (int16) status << std::endl; + Log.Out(Logs::General, Logs::World_Server, "Account Attempting to be created: '%s' status: %i", name, status); auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } if (results.LastInsertedID() == 0) { - std::cerr << "Error in CreateAccount query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -269,13 +239,10 @@ uint32 Database::CreateAccount(const char* name, const char* password, int16 sta bool Database::DeleteAccount(const char* name) { std::string query = StringFormat("DELETE FROM account WHERE name='%s';",name); - std::cout << "Account Attempting to be deleted:" << name << std::endl; + Log.Out(Logs::General, Logs::World_Server, "Account Attempting to be deleted:'%s'", name); - auto results = QueryDatabase(query); - - if (!results.Success()) - { - std::cerr << "Error in DeleteAccount query '" << query << "' " << results.ErrorMessage() << std::endl; + auto results = QueryDatabase(query); + if (!results.Success()) { return false; } @@ -288,7 +255,6 @@ bool Database::SetLocalPassword(uint32 accid, const char* password) { auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in SetLocalPassword query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -316,37 +282,32 @@ bool Database::SetAccountStatus(const char* name, int16 status) { /* This initially creates the character during character create */ bool Database::ReserveName(uint32 account_id, char* name) { - std::string query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); + std::string query = StringFormat("SELECT `account_id`, `name` FROM `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + if (row[0] && atoi(row[0]) > 0){ + Log.Out(Logs::General, Logs::World_Server, "Account: %i tried to request name: %s, but it is already taken...", account_id, name); + return false; + } + } + + query = StringFormat("INSERT INTO `character_data` SET `account_id` = %i, `name` = '%s'", account_id, name); + results = QueryDatabase(query); if (!results.Success() || results.ErrorMessage() != ""){ return false; } return true; } -bool Database::ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query){ - if (ErrorMessage != ""){ - std::cout << "\nERROR " << query_title << ": " << ErrorMessage << "\n\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 << "ERROR " << query_title << ": " << ErrorMessage << "\n" << query << "\n"; - log.close(); - - return true; - } - return false; -} - /* Delete the character with the name "name" returns false on failure, true otherwise */ bool Database::DeleteCharacter(char *name) { uint32 charid = 0; - printf("Database::DeleteCharacter name : %s \n", name); if(!name || !strlen(name)) { - std::cerr << "DeleteCharacter: request to delete without a name (empty char slot)" << std::endl; + Log.Out(Logs::General, Logs::World_Server, "DeleteCharacter: request to delete without a name (empty char slot)"); return false; } + Log.Out(Logs::General, Logs::World_Server, "Database::DeleteCharacter name : '%s'", name); /* Get id from character_data before deleting record so we can clean up the rest of the tables */ std::string query = StringFormat("SELECT `id` from `character_data` WHERE `name` = '%s'", name); @@ -354,39 +315,39 @@ bool Database::DeleteCharacter(char *name) { for (auto row = results.begin(); row != results.end(); ++row) { charid = atoi(row[0]); } if (charid <= 0){ std::cerr << "Database::DeleteCharacter :: Character not found, stopping delete...\n"; return false; } - query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); - query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::DeleteCharacter", query); + query = StringFormat("DELETE FROM `quest_globals` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_activities` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_enabledtasks` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `completed_tasks` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `friends` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `mail` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `timers` WHERE `char_id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `inventory` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `char_recipe_list` WHERE `char_id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `adventure_stats` WHERE `player_id` ='%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `zone_flags` WHERE `charID` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `titles` WHERE `char_id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `player_titlesets` WHERE `char_id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `keyring` WHERE `char_id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `faction_values` WHERE `char_id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `instance_list_player` WHERE `charid` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = '%d'", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_skills` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_languages` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_bind` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_currency` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_data` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_spells` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_memmed_spells` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_disciplines` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_material` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_tribute` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_bandolier` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_potionbelt` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query); + query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query); #ifdef BOTS query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); #else @@ -674,14 +635,13 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe pp->RestTimer // " RestTimer) " ); auto results = QueryDatabase(query); - ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Character Data", query); /* Save Bind Points */ query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " "(%u, %u, %u, %f, %f, %f, %f, %i)", character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 1 - ); results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Bind Point", query); + ); results = QueryDatabase(query); /* Save Skills */ int firstquery = 0; @@ -696,7 +656,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe } } } - results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Starting Skills", query); + results = QueryDatabase(query); /* Save Language */ firstquery = 0; @@ -711,7 +671,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe } } } - results = QueryDatabase(query); ThrowDBError(results.ErrorMessage(), "Database::SaveCharacterCreate Starting Languages", query); + results = QueryDatabase(query); return true; } @@ -724,7 +684,7 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven charid = GetCharacterID(pp->name); if(!charid) { - LogFile->write(EQEMuLog::Error, "StoreCharacter: no character id"); + Log.Out(Logs::General, Logs::Error, "StoreCharacter: no character id"); return false; } @@ -752,13 +712,6 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven charid, i, newinv->GetItem()->ID, newinv->GetCharges(), newinv->GetColor()); auto results = QueryDatabase(invquery); - - if (!results.RowsAffected()) - LogFile->write(EQEMuLog::Error, "StoreCharacter inventory failed. Query '%s' %s", invquery.c_str(), results.ErrorMessage().c_str()); -#if EQDEBUG >= 9 - else - LogFile->write(EQEMuLog::Debug, "StoreCharacter inventory succeeded. Query '%s'", invquery.c_str()); -#endif } if (i == MainCursor) { @@ -782,7 +735,10 @@ uint32 Database::GetCharacterID(const char *name) { std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); auto row = results.begin(); - if (row[0]){ return atoi(row[0]); } + if (results.RowCount() == 1) + { + return atoi(row[0]); + } return 0; } @@ -798,7 +754,6 @@ uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) { if (!results.Success()) { - std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -820,7 +775,6 @@ uint32 Database::GetAccountIDByChar(uint32 char_id) { std::string query = StringFormat("SELECT `account_id` FROM `character_data` WHERE `id` = %i LIMIT 1", char_id); auto results = QueryDatabase(query); if (!results.Success()) { - LogFile->write(EQEMuLog::Error, "Error in GetAccountIDByChar query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); return 0; } @@ -839,7 +793,6 @@ uint32 Database::GetAccountIDByName(const char* accname, int16* status, uint32* auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in GetAccountIDByAcc query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -868,7 +821,6 @@ void Database::GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in GetAccountName query '" << query << "' " << results.ErrorMessage() << std::endl; return; } @@ -889,7 +841,6 @@ void Database::GetCharName(uint32 char_id, char* name) { auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in GetCharName query '" << query << "' " << results.ErrorMessage() << std::endl; return; } @@ -899,1025 +850,6 @@ void Database::GetCharName(uint32 char_id, char* name) { } } -static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { - if ((x != n) && (x % (n / 100 + 1) != 0)) return; - float ratio = x / (float)n; - int c = ratio * w; - std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; - for (int x = 0; xexpended_aa > 4000000){ e_pp->expended_aa = 0; } - - /* Loading Status on conversion */ - if (runconvert == 1){ - std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; - loadbar(char_iter_count, number_of_characters, 50); - - /* Run inspect message convert */ - if (inspectmessage != ""){ - std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" - "VALUES (%u, '%s')", - character_id, - EscapeString(inspectmessage).c_str() - ); - auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Character Inspect Message Convert", rquery); - } - - /* Run Currency Convert */ - std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," - "platinum_bank, gold_bank, silver_bank, copper_bank," - "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " - "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" - "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", - character_id, - pp->platinum, - pp->gold, - pp->silver, - pp->copper, - pp->platinum_bank, - pp->gold_bank, - pp->silver_bank, - pp->copper_bank, - pp->platinum_cursor, - pp->gold_cursor, - pp->silver_cursor, - pp->copper_cursor, - pp->currentRadCrystals, - pp->careerRadCrystals, - pp->currentEbonCrystals, - pp->careerEbonCrystals - ); - auto results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Character Currency Convert", rquery); - - if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } - - /* Run Character Data Convert */ - rquery = StringFormat( - "REPLACE INTO `character_data` (" - "id," - "account_id," - "`name`," - "last_name," - "gender," - "race," - "class," - "`level`," - "deity," - "birthday," - "last_login," - "time_played," - "pvp_status," - "level2," - "anon," - "gm," - "intoxication," - "hair_color," - "beard_color," - "eye_color_1," - "eye_color_2," - "hair_style," - "beard," - "ability_time_seconds," - "ability_number," - "ability_time_minutes," - "ability_time_hours," - "title," - "suffix," - "exp," - "points," - "mana," - "cur_hp," - "str," - "sta," - "cha," - "dex," - "`int`," - "agi," - "wis," - "face," - "y," - "x," - "z," - "heading," - "pvp2," - "pvp_type," - "autosplit_enabled," - "zone_change_count," - "drakkin_heritage," - "drakkin_tattoo," - "drakkin_details," - "toxicity," - "hunger_level," - "thirst_level," - "ability_up," - "zone_id," - "zone_instance," - "leadership_exp_on," - "ldon_points_guk," - "ldon_points_mir," - "ldon_points_mmc," - "ldon_points_ruj," - "ldon_points_tak," - "ldon_points_available," - "tribute_time_remaining," - "show_helm," - "career_tribute_points," - "tribute_points," - "tribute_active," - "endurance," - "group_leadership_exp," - "raid_leadership_exp," - "group_leadership_points," - "raid_leadership_points," - "air_remaining," - "pvp_kills," - "pvp_deaths," - "pvp_current_points," - "pvp_career_points," - "pvp_best_kill_streak," - "pvp_worst_death_streak," - "pvp_current_kill_streak," - "aa_points_spent," - "aa_exp," - "aa_points," - "group_auto_consent," - "raid_auto_consent," - "guild_auto_consent," - "RestTimer," - "firstlogon," - "lfg," - "lfp," - "mailkey," - "xtargets," - "e_aa_effects," - "e_percent_to_aa," - "e_expended_aa_spent" - ")" - "VALUES (" - "%u," // id - "%u," // account_id - "'%s'," // `name` - "'%s'," // last_name - "%u," // gender - "%u," // race - "%u," // class - "%u," // `level` - "%u," // deity - "%u," // birthday - "%u," // last_login - "%u," // time_played - "%u," // pvp_status - "%u," // level2 - "%u," // anon - "%u," // gm - "%u," // intoxication - "%u," // hair_color - "%u," // beard_color - "%u," // eye_color_1 - "%u," // eye_color_2 - "%u," // hair_style - "%u," // beard - "%u," // ability_time_seconds - "%u," // ability_number - "%u," // ability_time_minutes - "%u," // ability_time_hours - "'%s'," // title - "'%s'," // suffix - "%u," // exp - "%u," // points - "%u," // mana - "%u," // cur_hp - "%u," // str - "%u," // sta - "%u," // cha - "%u," // dex - "%u," // `int` - "%u," // agi - "%u," // wis - "%u," // face - "%f," // y - "%f," // x - "%f," // z - "%f," // heading - "%u," // pvp2 - "%u," // pvp_type - "%u," // autosplit_enabled - "%u," // zone_change_count - "%u," // drakkin_heritage - "%u," // drakkin_tattoo - "%u," // drakkin_details - "%i," // toxicity - "%u," // hunger_level - "%u," // thirst_level - "%u," // ability_up - "%u," // zone_id - "%u," // zone_instance - "%u," // leadership_exp_on - "%u," // ldon_points_guk - "%u," // ldon_points_mir - "%u," // ldon_points_mmc - "%u," // ldon_points_ruj - "%u," // ldon_points_tak - "%u," // ldon_points_available - "%u," // tribute_time_remaining - "%u," // show_helm - "%u," // career_tribute_points - "%u," // tribute_points - "%u," // tribute_active - "%u," // endurance - "%u," // group_leadership_exp - "%u," // raid_leadership_exp - "%u," // group_leadership_points - "%u," // raid_leadership_points - "%u," // air_remaining - "%u," // pvp_kills - "%u," // pvp_deaths - "%u," // pvp_current_points - "%u," // pvp_career_points - "%u," // pvp_best_kill_streak - "%u," // pvp_worst_death_streak - "%u," // pvp_current_kill_streak - "%u," // aa_points_spent - "%u," // aa_exp - "%u," // aa_points - "%u," // group_auto_consent - "%u," // raid_auto_consent - "%u," // guild_auto_consent - "%u," // RestTimer - "%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt - "%u," // Looking for Group - "%u," // Looking for P? - "'%s'," // Mailkey - "%u," // X Targets - "%u," // AA Effects - "%u," // Percent to AA - "%u" // e_expended_aa_spent - ")", - character_id, - account_id, - EscapeString(pp->name).c_str(), - EscapeString(pp->last_name).c_str(), - pp->gender, - pp->race, - pp->class_, - pp->level, - pp->deity, - pp->birthday, - pp->lastlogin, - pp->timePlayedMin, - pp->pvp, - pp->level2, - pp->anon, - pp->gm, - pp->intoxication, - pp->haircolor, - pp->beardcolor, - pp->eyecolor1, - pp->eyecolor2, - pp->hairstyle, - pp->beard, - pp->ability_time_seconds, - pp->ability_number, - pp->ability_time_minutes, - pp->ability_time_hours, - EscapeString(pp->title).c_str(), - EscapeString(pp->suffix).c_str(), - pp->exp, - pp->points, - pp->mana, - pp->cur_hp, - pp->STR, - pp->STA, - pp->CHA, - pp->DEX, - pp->INT, - pp->AGI, - pp->WIS, - pp->face, - pp->y, - pp->x, - pp->z, - pp->heading, - pp->pvp2, - pp->pvptype, - pp->autosplit, - pp->zone_change_count, - pp->drakkin_heritage, - pp->drakkin_tattoo, - pp->drakkin_details, - pp->toxicity, - pp->hunger_level, - pp->thirst_level, - pp->ability_up, - pp->zone_id, - pp->zoneInstance, - pp->leadAAActive == 0 ? 0 : 1, - pp->ldon_points_guk, - pp->ldon_points_mir, - pp->ldon_points_mmc, - pp->ldon_points_ruj, - pp->ldon_points_tak, - pp->ldon_points_available, - pp->tribute_time_remaining, - pp->showhelm, - pp->career_tribute_points, - pp->tribute_points, - pp->tribute_active, - pp->endurance, - pp->group_leadership_exp, - pp->raid_leadership_exp, - pp->group_leadership_points, - pp->raid_leadership_points, - pp->air_remaining, - pp->PVPKills, - pp->PVPDeaths, - pp->PVPCurrentPoints, - pp->PVPCareerPoints, - pp->PVPBestKillStreak, - pp->PVPWorstDeathStreak, - pp->PVPCurrentKillStreak, - pp->aapoints_spent, - pp->expAA, - pp->aapoints, - pp->groupAutoconsent, - pp->raidAutoconsent, - pp->guildAutoconsent, - pp->RestTimer, - firstlogon, - lfg, - lfp, - mailkey.c_str(), - xtargets, - e_pp->aa_effects, - e_pp->perAA, - e_pp->expended_aa - ); - results = QueryDatabase(rquery); - ThrowDBError(results.ErrorMessage(), "Character Data Convert", rquery); - - - /* - We set a first entry variable because we need the first initial piece of the query to be declared - This is to speed up the INSERTS and trim down the amount of individual sends during the process. - The speed difference is dramatic - */ - /* Run AA Convert */ - int first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_AA_ARRAY; i++){ - if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" - " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - first_entry = 1; - } else { - rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); - } - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "AA Convert", rquery); } - - /* Run Bind Home Convert */ - if(pp->binds[4].zoneId < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) { - rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", - character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Bind Home Convert", rquery); } - } - - /* Run Bind Convert */ - if(pp->binds[0].zoneId < 999 && !_ISNAN_(pp->binds[0].x) && !_ISNAN_(pp->binds[0].y) && !_ISNAN_(pp->binds[0].z) && !_ISNAN_(pp->binds[0].heading)) { - rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", - character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bind Convert", rquery); } - } - /* Run Language Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_LANGUAGE; i++){ - if (pp->languages[i] > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Language Convert", rquery); } - /* Run Skill Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_SKILL; i++){ - if (pp->skills[i] > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Skills Convert Convert", rquery); } - /* Run Spell Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ - if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]); - } - } - // std::cout << rquery << "\n"; - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Spell Convert", rquery); } - /* Run Max Memmed Spell Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ - if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Memmed Spells Convert", rquery); } - /* Run Discipline Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_DISCIPLINES; i++){ - if(pp->disciplines.values[i] > 0 && pp->disciplines.values[i] < 60000){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Discipline Convert", rquery); } - /* Run Material Color Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < _MaterialCount; i++){ - if (pp->item_tint[i].color > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Material Convert", rquery); } - /* Run Tribute Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ - if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Tribute Convert", rquery); } - /* Run Bandolier Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++){ - if(strlen(pp->bandoliers[i].name) < 32) { - for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ - if (pp->bandoliers[i].items[si].item_id > 0){ - if (first_entry != 1) { - rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); - } - } - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Bandolier Convert", rquery); } - /* Run Potion Belt Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ - if (pp->potionbelt.items[i].item_id > 0){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); - - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Potion Belt Convert", rquery); } - /* Run Leadership AA Convert */ - first_entry = 0; rquery = ""; - for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){ - if(pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){ - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); - first_entry = 1; - } - rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); - } - } - if (rquery != ""){ results = QueryDatabase(rquery); ThrowDBError(results.ErrorMessage(), "Character Leadership AA Convert", rquery); } - } - } - if (runconvert == 1){ - std::string rquery = StringFormat("RENAME TABLE `character_` TO `character_old`"); QueryDatabase(rquery); - printf("\n\nRenaming `character_` table to `character_old`, this is a LARGE table so when you don't need it anymore, I would suggest deleting it yourself...\n"); - printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); - } - - return true; -} - bool Database::LoadVariables() { char *query = nullptr; @@ -1925,7 +857,6 @@ bool Database::LoadVariables() { if (!results.Success()) { - std::cerr << "Error in LoadVariables query '" << query << "' " << results.ErrorMessage() << std::endl; safe_delete_array(query); return false; } @@ -1940,7 +871,8 @@ uint32 Database::LoadVariables_MQ(char** query) } // always returns true? not sure about this. -bool Database::LoadVariables_result(MySQLRequestResult results) { +bool Database::LoadVariables_result(MySQLRequestResult results) +{ uint32 i = 0; LockMutex lock(&Mvarcache); @@ -2037,7 +969,6 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { if (!results.Success()) { - std::cerr << "Error in SetVariable query '" << query << "' " << results.ErrorMessage() << std::endl; free(varname); free(varvalue); return false; @@ -2063,19 +994,15 @@ bool Database::SetVariable(const char* varname_in, const char* varvalue_in) { return true; } -uint32 Database::GetMiniLoginAccount(char* ip){ - - std::string query = StringFormat("SELECT id FROM account WHERE minilogin_ip='%s'", ip); +uint32 Database::GetMiniLoginAccount(char* ip) +{ + std::string query = StringFormat("SELECT `id` FROM `account` WHERE `minilogin_ip` = '%s'", ip); auto results = QueryDatabase(query); if (!results.Success()) - { - std::cerr << "Error in GetMiniLoginAccount query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; - } - - auto row = results.begin(); + auto row = results.begin(); return atoi(row[0]); } @@ -2087,14 +1014,7 @@ bool Database::GetSafePoints(const char* short_name, uint32 version, float* safe auto results = QueryDatabase(query); if (!results.Success()) - { - std::cerr << "Error in GetSafePoint query '" << query << "' " << results.ErrorMessage() << std::endl; - std::cerr << "If it errors, run the following querys:\n"; - std::cerr << "ALTER TABLE `zone` CHANGE `minium_level` `min_level` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; - std::cerr << "ALTER TABLE `zone` CHANGE `minium_status` `min_status` TINYINT(3) UNSIGNED DEFAULT \"0\" NOT NULL;\n"; - std::cerr << "ALTER TABLE `zone` ADD flag_needed VARCHAR(128) NOT NULL DEFAULT '';\n"; return false; - } if (results.RowCount() == 0) return false; @@ -2123,7 +1043,6 @@ bool Database::GetZoneLongName(const char* short_name, char** long_name, char* f auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in GetZoneLongName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2162,10 +1081,7 @@ uint32 Database::GetZoneGraveyardID(uint32 zone_id, uint32 version) { auto results = QueryDatabase(query); if (!results.Success()) - { - std::cerr << "Error in GetZoneGraveyardID query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; - } if (results.RowCount() == 0) return 0; @@ -2180,7 +1096,6 @@ bool Database::GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zon auto results = QueryDatabase(query); if (!results.Success()){ - std::cerr << "Error in GetZoneGraveyard query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2210,7 +1125,6 @@ bool Database::LoadZoneNames() { if (!results.Success()) { - std::cerr << "Error in LoadZoneNames query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2253,9 +1167,7 @@ uint8 Database::GetPEQZone(uint32 zoneID, uint32 version){ std::string query = StringFormat("SELECT peqzone from zone where zoneidnumber='%i' AND (version=%i OR version=0) ORDER BY version DESC", zoneID, version); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cerr << "Error in GetPEQZone query '" << query << "' " << results.ErrorMessage() << std::endl; + if (!results.Success()) { return 0; } @@ -2326,7 +1238,6 @@ bool Database::CheckNameFilter(const char* name, bool surname) if (!results.Success()) { - std::cerr << "Error in CheckNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; // false through to true? shouldn't it be falls through to false? return true; } @@ -2352,7 +1263,6 @@ bool Database::AddToNameFilter(const char* name) { if (!results.Success()) { - std::cerr << "Error in AddToNameFilter query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2367,9 +1277,7 @@ uint32 Database::GetAccountIDFromLSID(uint32 iLSID, char* oAccountName, int16* o std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i", iLSID); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cerr << "Error in GetAccountIDFromLSID query '" << query << "' " << results.ErrorMessage() << std::endl; + if (!results.Success()) { return 0; } @@ -2393,9 +1301,7 @@ void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { std::string query = StringFormat("SELECT name, status FROM account WHERE id=%i", id); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cerr << "Error in GetAccountFromID query '" << query << "' " << results.ErrorMessage() << std::endl; + if (!results.Success()){ return; } @@ -2411,12 +1317,7 @@ void Database::GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus) { } void Database::ClearMerchantTemp(){ - - std::string query("delete from merchantlist_temp"); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cerr << "Error in ClearMerchantTemp query '" << query << "' " << results.ErrorMessage() << std::endl; + QueryDatabase("DELETE FROM merchantlist_temp"); } bool Database::UpdateName(const char* oldname, const char* newname) { @@ -2438,7 +1339,6 @@ bool Database::CheckUsedName(const char* name) { std::string query = StringFormat("SELECT `id` FROM `character_data` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in CheckUsedName query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2452,7 +1352,6 @@ uint8 Database::GetServerType() { std::string query("SELECT `value` FROM `variables` WHERE `varname` = 'ServerType' LIMIT 1"); auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in GetServerType query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -2471,7 +1370,6 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename, u auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in MoveCharacterToZone(name) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2490,7 +1388,6 @@ bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) { auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in MoveCharacterToZone(id) query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2502,7 +1399,6 @@ bool Database::SetHackerFlag(const char* accountname, const char* charactername, auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in SetHackerFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2516,7 +1412,6 @@ bool Database::SetMQDetectionFlag(const char* accountname, const char* character if (!results.Success()) { - std::cerr << "Error in SetMQDetectionFlag query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2596,7 +1491,6 @@ uint32 Database::GetCharacterInfo(const char* iName, uint32* oAccID, uint32* oZo auto results = QueryDatabase(query); if (!results.Success()) { - std::cerr << "Error in GetCharacterInfo query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; } @@ -2620,9 +1514,7 @@ bool Database::UpdateLiveChar(char* charname,uint32 lsaccount_id) { std::string query = StringFormat("UPDATE account SET charname='%s' WHERE id=%i;",charname, lsaccount_id); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cerr << "Error in UpdateLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; + if (!results.Success()){ return false; } @@ -2636,7 +1528,6 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { if (!results.Success()) { - std::cerr << "Error in GetLiveChar query '" << query << "' " << results.ErrorMessage() << std::endl; return false; } @@ -2651,30 +1542,22 @@ bool Database::GetLiveChar(uint32 account_id, char* cname) { void Database::SetLFP(uint32 CharID, bool LFP) { std::string query = StringFormat("UPDATE `character_data` SET `lfp` = %i WHERE `id` = %i",LFP, CharID); - auto results = QueryDatabase(query); - if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); + QueryDatabase(query); } void Database::SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon) { std::string query = StringFormat("update `character_data` SET `lfp` = %i, `lfg` = %i, `firstlogon` = %i WHERE `id` = %i",LFP, LFG, firstlogon, CharID); - auto results = QueryDatabase(query); - if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); + QueryDatabase(query); } void Database::SetLFG(uint32 CharID, bool LFG) { std::string query = StringFormat("update `character_data` SET `lfg` = %i WHERE `id` = %i",LFG, CharID); - auto results = QueryDatabase(query); - if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error updating LFP for character %i : %s", CharID, results.ErrorMessage().c_str()); + QueryDatabase(query); } void Database::SetFirstLogon(uint32 CharID, uint8 firstlogon) { std::string query = StringFormat( "UPDATE `character_data` SET `firstlogon` = %i WHERE `id` = %i",firstlogon, CharID); - auto results = QueryDatabase(query); - if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error updating firstlogon for character %i : %s", CharID, results.ErrorMessage().c_str()); + QueryDatabase(query); } void Database::AddReport(std::string who, std::string against, std::string lines) { @@ -2682,11 +1565,8 @@ void Database::AddReport(std::string who, std::string against, std::string lines DoEscapeString(escape_str, lines.c_str(), lines.size()); std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str); - auto results = QueryDatabase(query); + QueryDatabase(query); safe_delete_array(escape_str); - - if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error adding a report for %s: %s", who.c_str(), results.ErrorMessage().c_str()); } void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc) { @@ -2697,27 +1577,20 @@ void Database::SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ism auto results = QueryDatabase(query); if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str()); + Log.Out(Logs::General, Logs::Error, "Error deleting character from group id: %s", results.ErrorMessage().c_str()); return; } /* Add to the Group */ query = StringFormat("REPLACE INTO `group_id` SET `charid` = %i, `groupid` = %i, `name` = '%s', `ismerc` = '%i'", charid, id, name, ismerc); - auto results = QueryDatabase(query); - - if (!results.Success()) - LogFile->write(EQEMuLog::Error, "Error adding character to group id: %s", results.ErrorMessage().c_str()); + QueryDatabase(query); } void Database::ClearAllGroups(void) { - std::string query("delete from group_id"); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; - + std::string query("DELETE FROM `group_id`"); + QueryDatabase(query); return; } @@ -2733,26 +1606,21 @@ void Database::ClearGroup(uint32 gid) { //clear a specific group std::string query = StringFormat("delete from group_id where groupid = %lu", (unsigned long)gid); - auto results = QueryDatabase(query); - - if (!results.Success()) - std::cout << "Unable to clear groups: " << results.ErrorMessage() << std::endl; + QueryDatabase(query); } -uint32 Database::GetGroupID(const char* name){ - +uint32 Database::GetGroupID(const char* name){ std::string query = StringFormat("SELECT groupid from group_id where name='%s'", name); auto results = QueryDatabase(query); - if (!results.Success()) - { - LogFile->write(EQEMuLog::Error, "Error getting group id: %s", results.ErrorMessage().c_str()); + if (!results.Success()) { return 0; } if (results.RowCount() == 0) { - LogFile->write(EQEMuLog::Debug, "Character not in a group: %s", name); + // Commenting this out until logging levels can prevent this from going to console + //Log.Out(Logs::General, Logs::None,, "Character not in a group: %s", name); return 0; } @@ -2762,36 +1630,50 @@ uint32 Database::GetGroupID(const char* name){ } /* Is this really getting used properly... A half implementation ? Akkadius */ -char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf){ - leaderbuf = ""; - std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name = '%s'", name); - auto results = QueryDatabase(query); - auto row = results.begin(); uint32 group_id = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - if (row[0]){ group_id = atoi(row[0]); } - } +char* Database::GetGroupLeaderForLogin(const char* name, char* leaderbuf) { + strcpy(leaderbuf, ""); + uint32 group_id = 0; - if (group_id > 0){ - query = StringFormat("SELECT `leadername` FROM `group_leader` WHERE `gid` = '%u' AND `groupid` = %u LIMIT 1", group_id); - results = QueryDatabase(query); - for (auto row = results.begin(); row != results.end(); ++row) { - if (row[0]){ strcpy(leaderbuf, row[0]); } - } - } + std::string query = StringFormat("SELECT `groupid` FROM `group_id` WHERE `name` = '%s'", name); + auto results = QueryDatabase(query); + + for (auto row = results.begin(); row != results.end(); ++row) + if (row[0]) + group_id = atoi(row[0]); + + if (group_id == 0) + return leaderbuf; + + query = StringFormat("SELECT `leadername` FROM `group_leaders` WHERE `gid` = '%u' LIMIT 1", group_id); + results = QueryDatabase(query); + + for (auto row = results.begin(); row != results.end(); ++row) + if (row[0]) + strcpy(leaderbuf, row[0]); return leaderbuf; } void Database::SetGroupLeaderName(uint32 gid, const char* name) { - std::string query = StringFormat("REPLACE INTO `group_leaders` SET `gid` = %lu, `leadername` = '%s'",(unsigned long)gid,name); - auto results = QueryDatabase(query); + std::string query = StringFormat("UPDATE group_leaders SET leadername = '%s' WHERE gid = %u", EscapeString(name).c_str(), gid); + auto result = QueryDatabase(query); - if (!results.Success()) - std::cout << "Unable to set group leader: " << results.ErrorMessage() << std::endl; + if(result.RowsAffected() != 0) { + return; + } + + query = StringFormat("REPLACE INTO group_leaders(gid, leadername, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%u, '%s', '', '', '', '', '', '', '0')", + gid, EscapeString(name).c_str()); + result = QueryDatabase(query); + + if(!result.Success()) { + Log.Out(Logs::General, Logs::None, "Error in Database::SetGroupLeaderName: %s", result.ErrorMessage().c_str()); + } } -char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, GroupLeadershipAA_Struct* GLAA){ - std::string query = StringFormat("SELECT `leadername`, `maintank`, `assist`, `puller`, `marknpc`, `leadershipaa` FROM `group_leaders` WHERE `gid` = %lu",(unsigned long)gid); +char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank, char* assist, char* puller, char *marknpc, char *mentoree, int *mentor_percent, GroupLeadershipAA_Struct* GLAA) +{ + std::string query = StringFormat("SELECT `leadername`, `maintank`, `assist`, `puller`, `marknpc`, `mentoree`, `mentor_percent`, `leadershipaa` FROM `group_leaders` WHERE `gid` = %lu",(unsigned long)gid); auto results = QueryDatabase(query); if (!results.Success() || results.RowCount() == 0) { @@ -2810,6 +1692,12 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta if(marknpc) marknpc[0] = '\0'; + if (mentoree) + mentoree[0] = '\0'; + + if (mentor_percent) + *mentor_percent = 0; + return leaderbuf; } @@ -2830,8 +1718,14 @@ char *Database::GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* mainta if(marknpc) strcpy(marknpc, row[4]); - if(GLAA && results.LengthOfColumn(5) == sizeof(GroupLeadershipAA_Struct)) - memcpy(GLAA, row[5], sizeof(GroupLeadershipAA_Struct)); + if (mentoree) + strcpy(mentoree, row[5]); + + if (mentor_percent) + *mentor_percent = atoi(row[6]); + + if(GLAA && results.LengthOfColumn(7) == sizeof(GroupLeadershipAA_Struct)) + memcpy(GLAA, row[7], sizeof(GroupLeadershipAA_Struct)); return leaderbuf; } @@ -2937,22 +1831,17 @@ void Database::ClearRaidDetails(uint32 rid) { // returns 0 on error or no raid for that character, or // the raid id that the character is a member of. -uint32 Database::GetRaidID(const char* name){ - - std::string query = StringFormat("SELECT raidid from raid_members where name='%s'", name); +uint32 Database::GetRaidID(const char* name) +{ + std::string query = StringFormat("SELECT `raidid` FROM `raid_members` WHERE `name` = '%s'", name); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cout << "Unable to get raid id: " << results.ErrorMessage() << std::endl; + if (!results.Success()) { return 0; } - auto row = results.begin(); - - if (row == results.end()) - { - std::cout << "Unable to get raid id, char not found!" << std::endl; + auto row = results.begin(); + if (row == results.end()) { return 0; } @@ -2962,7 +1851,7 @@ uint32 Database::GetRaidID(const char* name){ return 0; } -const char* Database::GetRaidLeaderName(uint32 rid) +const char* Database::GetRaidLeaderName(uint32 raid_id) { // Would be a good idea to fix this to be a passed in variable and // make the caller responsible. static local variables like this are @@ -2971,20 +1860,17 @@ const char* Database::GetRaidLeaderName(uint32 rid) // but may not be fully supported in some compilers. static char name[128]; - std::string query = StringFormat("SELECT name FROM raid_members WHERE raidid=%u AND israidleader=1",rid); + std::string query = StringFormat("SELECT `name` FROM `raid_members` WHERE `raidid` = %u AND `israidleader` = 1", raid_id); auto results = QueryDatabase(query); - if (!results.Success()) - { - std::cout << "Unable to get raid id: " << results.ErrorMessage() << std::endl; + if (!results.Success()) { + Log.Out(Logs::General, Logs::Debug, "Unable to get Raid Leader Name for Raid ID: %u", raid_id); return "UNKNOWN"; } auto row = results.begin(); - if (row == results.end()) - { - std::cout << "Unable to get raid id, char not found!" << std::endl; + if (row == results.end()) { return "UNKNOWN"; } @@ -2994,492 +1880,146 @@ const char* Database::GetRaidLeaderName(uint32 rid) return name; } -bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) +// maintank, assist, puller, marknpc currently unused +void Database::GetGroupLeadershipInfo(uint32 gid, uint32 rid, char *maintank, + char *assist, char *puller, char *marknpc, char *mentoree, int *mentor_percent, GroupLeadershipAA_Struct *GLAA) { - //we are not saved to this instance so set our instance to 0 - if(!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id)) - return false; - - if(CheckInstanceExpired(instance_id)) - { - DeleteInstance(instance_id); - return false; - } - - return true; -} - -bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) -{ - - std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u",instance_id, zone_id); + std::string query = StringFormat( + "SELECT maintank, assist, puller, marknpc, mentoree, mentor_percent, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu", + (unsigned long)gid, (unsigned long)rid); auto results = QueryDatabase(query); - if (!results.Success()) - return false; + if (!results.Success() || results.RowCount() == 0) { + if (maintank) + maintank[0] = '\0'; - if (results.RowCount() == 0) - return false; + if (assist) + assist[0] = '\0'; - return true; -} + if (puller) + puller[0] = '\0'; -bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) -{ + if (marknpc) + marknpc[0] = '\0'; - std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u",instance_id, char_id); - auto results = QueryDatabase(query); + if (mentoree) + mentoree[0] = '\0'; - if (!results.Success()) - return false; + if (mentor_percent) + *mentor_percent = 0; - if (results.RowCount() != 1) - return false; - - return true; -} - -void Database::DeleteInstance(uint16 instance_id) -{ - - std::string query = StringFormat("DELETE FROM instance_list WHERE id=%u", instance_id); - QueryDatabase(query); - - query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id); - QueryDatabase(query); - - query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id); - QueryDatabase(query); - - query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id); - QueryDatabase(query); - - BuryCorpsesInInstance(instance_id); -} - -bool Database::CheckInstanceExpired(uint16 instance_id) -{ - - int32 start_time = 0; - int32 duration = 0; - uint32 never_expires = 0; - - std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return true; - - if (results.RowCount() == 0) - return true; - - auto row = results.begin(); - - start_time = atoi(row[0]); - duration = atoi(row[1]); - never_expires = atoi(row[2]); - - if(never_expires == 1) - return false; - - timeval tv; - gettimeofday(&tv, nullptr); - - if((start_time + duration) <= tv.tv_sec) - return true; - - return false; -} - -uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) -{ - - std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 Database::VersionFromInstanceID(uint16 instance_id) -{ - - std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) -{ - uint32 start_time = 0; - uint32 duration = 0; - uint32 never_expires = 0; - - std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - { - is_perma = false; - return 0; - } - - if (results.RowCount() == 0) - { - is_perma = false; - return 0; + return; } auto row = results.begin(); - start_time = atoi(row[0]); - duration = atoi(row[1]); - never_expires = atoi(row[2]); + if (maintank) + strcpy(maintank, row[0]); - if(never_expires == 1) - { - is_perma = true; - return 0; - } + if (assist) + strcpy(assist, row[1]); - is_perma = false; + if (puller) + strcpy(puller, row[2]); - timeval tv; - gettimeofday(&tv, nullptr); - return ((start_time + duration) - tv.tv_sec); + if (marknpc) + strcpy(marknpc, row[3]); + + if (mentoree) + strcpy(mentoree, row[4]); + + if (mentor_percent) + *mentor_percent = atoi(row[5]); + + if (GLAA && results.LengthOfColumn(6) == sizeof(GroupLeadershipAA_Struct)) + memcpy(GLAA, row[6], sizeof(GroupLeadershipAA_Struct)); + + return; } -bool Database::GetUnusedInstanceID(uint16 &instance_id) +// maintank, assist, puller, marknpc currently unused +void Database::GetRaidLeadershipInfo(uint32 rid, char *maintank, + char *assist, char *puller, char *marknpc, RaidLeadershipAA_Struct *RLAA) { - uint32 count = RuleI(Zone, ReservedInstances); - uint32 max = 65535; - - std::string query = StringFormat("SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count); + std::string query = StringFormat( + "SELECT maintank, assist, puller, marknpc, leadershipaa FROM raid_leaders WHERE gid = %lu AND rid = %lu", + (unsigned long)0xFFFFFFFF, (unsigned long)rid); auto results = QueryDatabase(query); - if (!results.Success()) - { - instance_id = 0; - return false; - } + if (!results.Success() || results.RowCount() == 0) { + if (maintank) + maintank[0] = '\0'; - if (results.RowCount() == 0) - { - instance_id = 0; - return false; + if (assist) + assist[0] = '\0'; + + if (puller) + puller[0] = '\0'; + + if (marknpc) + marknpc[0] = '\0'; + + return; } auto row = results.begin(); - if (atoi(row[0]) <= max) - { - instance_id = atoi(row[0]); - return true; - } + if (maintank) + strcpy(maintank, row[0]); - query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", count); + if (assist) + strcpy(assist, row[1]); + + if (puller) + strcpy(puller, row[2]); + + if (marknpc) + strcpy(marknpc, row[3]); + + if (RLAA && results.LengthOfColumn(4) == sizeof(RaidLeadershipAA_Struct)) + memcpy(RLAA, row[4], sizeof(RaidLeadershipAA_Struct)); + + return; +} + +void Database::SetRaidGroupLeaderInfo(uint32 gid, uint32 rid) +{ + std::string query = StringFormat("UPDATE raid_leaders SET leadershipaa = '', WHERE gid = %lu AND rid = %lu", + (unsigned long)gid, (unsigned long)rid); + auto results = QueryDatabase(query); + + if (results.RowsAffected() != 0) + return; + + query = StringFormat("REPLACE INTO raid_leaders(gid, rid, marknpc, leadershipaa, maintank, assist, puller, mentoree, mentor_percent) VALUES(%lu, %lu, '', '', '', '', '', '', 0)", + (unsigned long)gid, (unsigned long)rid); results = QueryDatabase(query); - if (!results.Success()) - { - instance_id = 0; - return false; - } - - if (results.RowCount() == 0) - { - instance_id = 0; - return false; - } - - count++; - for (auto row = results.begin();row != results.end();++row) - { - if(count < atoi(row[0])) - { - instance_id = count; - return true; - } - - if(count > max) - { - instance_id = 0; - return false; - } - - count++; - } - - instance_id = count; - return true; + return; } -//perhaps purge any expireds too -bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) +// Clearing all raid leaders +void Database::ClearAllRaidLeaders(void) { - - std::string query = StringFormat("INSERT INTO instance_list (id, zone, version, start_time, duration)" - " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", - (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration); - auto results = QueryDatabase(query); - - return results.Success(); + std::string query("DELETE from raid_leaders"); + QueryDatabase(query); + return; } -void Database::PurgeExpiredInstances() +void Database::ClearRaidLeader(uint32 gid, uint32 rid) { - - std::string query("SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0"); - auto results = QueryDatabase(query); - - if (!results.Success()) - return; - - if (results.RowCount() == 0) - return; - - for (auto row = results.begin();row != results.end();++row) - DeleteInstance(atoi(row[0])); -} - -bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) -{ - std::string query = StringFormat("INSERT INTO instance_list_player(id, charid) values(%lu, %lu)", - (unsigned long)instance_id, (unsigned long)char_id); - auto results = QueryDatabase(query); - - return results.Success(); -} - -bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) -{ - - std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", - (unsigned long)instance_id, (unsigned long)char_id); - auto results = QueryDatabase(query); - - return results.Success(); -} - -bool Database::RemoveClientsFromInstance(uint16 instance_id) -{ - std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id); - auto results = QueryDatabase(query); - - return results.Success(); -} - -bool Database::CheckInstanceExists(uint16 instance_id) -{ - - std::string query = StringFormat("SELECT * FROM instance_list where id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return false; - - if (results.RowCount() == 0) - return false; - - return true; -} - -void Database::BuryCorpsesInInstance(uint16 instance_id) -{ - - std::string query = StringFormat("UPDATE player_corpses SET IsBurried=1, instanceid=0 WHERE instanceid=%u", instance_id); - auto results = QueryDatabase(query); -} - -uint16 Database::GetInstanceVersion(uint16 instance_id) -{ - if(instance_id == 0) - return 0; - - std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - -uint16 Database::GetInstanceID(const char* zone, uint32 charid, int16 version) -{ - - std::string query = StringFormat("SELECT instance_list.id FROM instance_list, instance_list_player " - "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", GetZoneID(zone), version, charid, charid); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - return atoi(row[0]); -} - -uint16 Database::GetInstanceID(uint32 zone, uint32 charid, int16 version) -{ - if(!zone) - return 0; - - std::string query = StringFormat("SELECT instance_list.id FROM instance_list, instance_list_player " - "WHERE instance_list.zone=%u AND instance_list.version=%u AND instance_list.id=instance_list_player.id AND " - "instance_list_player.charid=%u LIMIT 1;", zone, version, charid); - auto results = QueryDatabase(query); - - if (!results.Success()) - return 0; - - if (results.RowCount() == 0) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { - - std::string query = StringFormat("SELECT charid FROM instance_list_player WHERE id=%u", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - { - LogFile->write(EQEMuLog::Error, "Error in GetCharactersInInstace query '%s': %s", query.c_str(), results.ErrorMessage().c_str()); + if (rid == 0) { + ClearAllRaidLeaders(); return; } - for(auto row=results.begin();row != results.end();++row) - charid_list.push_back(atoi(row[0])); -} - -void Database::AssignGroupToInstance(uint32 gid, uint32 instance_id) -{ - - uint32 zone_id = ZoneIDFromInstanceID(instance_id); - uint16 version = VersionFromInstanceID(instance_id); - - std::string query = StringFormat("SELECT charid FROM group_id WHERE groupid=%u", gid); - auto results = QueryDatabase(query); - - if (!results.Success()) - return; - - for (auto row=results.begin();row != results.end();++row) - { - uint32 charid = atoi(row[0]); - if(GetInstanceID(zone_id, charid, version) == 0) - AddClientToInstance(instance_id, charid); - } -} - -void Database::AssignRaidToInstance(uint32 rid, uint32 instance_id) -{ - - uint32 zone_id = ZoneIDFromInstanceID(instance_id); - uint16 version = VersionFromInstanceID(instance_id); - - std::string query = StringFormat("SELECT charid FROM raid_members WHERE raidid=%u", rid); - auto results = QueryDatabase(query); - - if (!results.Success()) - return; - - for (auto row=results.begin();row!=results.end();++row) - { - uint32 charid = atoi(row[0]); - if(GetInstanceID(zone_id, charid, version) == 0) - AddClientToInstance(instance_id, charid); - } -} - -void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid) -{ - uint16 id = GetInstanceID(zone, charid, version); - if(id != 0) - return; - - char ln[128]; - memset(ln, 0, 128); - strcpy(ln, GetGroupLeadershipInfo(gid, ln)); - uint32 l_charid = GetCharacterID((const char*)ln); - uint16 l_id = GetInstanceID(zone, l_charid, version); - - if(l_id == 0) - return; - - AddClientToInstance(l_id, charid); -} - -void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid) -{ - uint16 id = GetInstanceID(zone, charid, version); - if(id != 0) - return; - - uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid)); - uint16 l_id = GetInstanceID(zone, l_charid, version); - - if(l_id == 0) - return; - - AddClientToInstance(l_id, charid); -} - -void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) -{ - - std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " - "duration=%u WHERE id=%u", new_duration, instance_id); - auto results = QueryDatabase(query); -} - -bool Database::GlobalInstance(uint16 instance_id) -{ - - std::string query = StringFormat("SELECT is_global from instance_list where id=%u LIMIT 1", instance_id); - auto results = QueryDatabase(query); - - if (!results.Success()) - return false; - - if (results.RowCount() == 0) - return false; - - auto row = results.begin(); - - return (atoi(row[0]) == 1) ? true : false; + std::string query = StringFormat("DELETE from raid_leaders where gid = %lu and rid = %lu", (unsigned long)gid, (unsigned long)rid); + QueryDatabase(query); } void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) { - + std::string field; switch(theme) @@ -3530,12 +2070,26 @@ void Database::UpdateAdventureStatsEntry(uint32 char_id, uint8 theme, bool win) QueryDatabase(query); } -bool Database::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 Database::GetAdventureStats(uint32 char_id, AdventureStats_Struct *as) { - - std::string query = StringFormat("SELECT `guk_wins`, `mir_wins`, `mmc_wins`, `ruj_wins`, `tak_wins`, `guk_losses`, " - "`mir_losses`, `mmc_losses`, `ruj_losses`, `tak_losses` FROM `adventure_stats` WHERE player_id=%u", char_id); + std::string query = StringFormat( + "SELECT " + "`guk_wins`, " + "`mir_wins`, " + "`mmc_wins`, " + "`ruj_wins`, " + "`tak_wins`, " + "`guk_losses`, " + "`mir_losses`, " + "`mmc_losses`, " + "`ruj_losses`, " + "`tak_losses` " + "FROM " + "`adventure_stats` " + "WHERE " + "player_id = %u ", + char_id + ); auto results = QueryDatabase(query); if (!results.Success()) @@ -3546,31 +2100,29 @@ bool Database::GetAdventureStats(uint32 char_id, uint32 &guk_w, uint32 &mir_w, u auto row = results.begin(); - guk_w = atoi(row[0]); - mir_w = atoi(row[1]); - mmc_w = atoi(row[2]); - ruj_w = atoi(row[3]); - tak_w = atoi(row[4]); - guk_l = atoi(row[5]); - mir_l = atoi(row[6]); - mmc_l = atoi(row[7]); - ruj_l = atoi(row[8]); - tak_l = atoi(row[9]); + as->success.guk = atoi(row[0]); + as->success.mir = atoi(row[1]); + as->success.mmc = atoi(row[2]); + as->success.ruj = atoi(row[3]); + as->success.tak = atoi(row[4]); + as->failure.guk = atoi(row[5]); + as->failure.mir = atoi(row[6]); + as->failure.mmc = atoi(row[7]); + as->failure.ruj = atoi(row[8]); + as->failure.tak = atoi(row[9]); + as->failure.total = as->failure.guk + as->failure.mir + as->failure.mmc + as->failure.ruj + as->failure.tak; + as->success.total = as->success.guk + as->success.mir + as->success.mmc + as->success.ruj + as->success.tak; return true; } -uint32 Database::GetGuildIDByCharID(uint32 char_id) +uint32 Database::GetGuildIDByCharID(uint32 character_id) { - - std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id='%i'", char_id); + std::string query = StringFormat("SELECT guild_id FROM guild_members WHERE char_id='%i'", character_id); auto results = QueryDatabase(query); if (!results.Success()) - { - std::cerr << "Error in GetGuildIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl; return 0; - } if (results.RowCount() == 0) return 0; @@ -3578,3 +2130,46 @@ uint32 Database::GetGuildIDByCharID(uint32 char_id) auto row = results.begin(); return atoi(row[0]); } + +void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings) +{ + std::string query = + "SELECT " + "log_category_id, " + "log_category_description, " + "log_to_console, " + "log_to_file, " + "log_to_gmsay " + "FROM " + "logsys_categories " + "ORDER BY log_category_id"; + auto results = QueryDatabase(query); + + int log_category = 0; + Log.file_logs_enabled = false; + + for (auto row = results.begin(); row != results.end(); ++row) { + log_category = atoi(row[0]); + log_settings[log_category].log_to_console = atoi(row[2]); + log_settings[log_category].log_to_file = atoi(row[3]); + log_settings[log_category].log_to_gmsay = atoi(row[4]); + + /* Determine if any output method is enabled for the category + and set it to 1 so it can used to check if category is enabled */ + const bool log_to_console = log_settings[log_category].log_to_console > 0; + const bool log_to_file = log_settings[log_category].log_to_file > 0; + const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0; + const bool is_category_enabled = log_to_console || log_to_file || log_to_gmsay; + + if (is_category_enabled) + log_settings[log_category].is_category_enabled = 1; + + /* + This determines whether or not the process needs to actually file log anything. + If we go through this whole loop and nothing is set to any debug level, there is no point to create a file or keep anything open + */ + if (log_settings[log_category].log_to_file > 0){ + Log.file_logs_enabled = true; + } + } +} \ No newline at end of file diff --git a/common/database.h b/common/database.h index a24198ca4..f3b8ba8c1 100644 --- a/common/database.h +++ b/common/database.h @@ -21,11 +21,14 @@ #define AUTHENTICATION_TIMEOUT 60 #define INVALID_ID 0xFFFFFFFF -#include "debug.h" +#include "global_define.h" +#include "eqemu_logsys.h" #include "types.h" #include "dbcore.h" #include "linked_list.h" #include "eq_packet_structs.h" + +#include #include #include #include @@ -33,22 +36,9 @@ //atoi is not uint32 or uint32 safe!!!! #define atoul(str) strtoul(str, nullptr, 10) -//class Spawn; -class Corpse; -class Spawn2; -class NPC; -class SpawnGroupList; -class Petition; -class Client; -class Merc; -struct Combine_Struct; -//struct Faction; -//struct FactionMods; -//struct FactionValue; -struct ZonePoint; -struct NPCType; class Inventory; -class ItemInst; +class MySQLRequestResult; +class Client; struct EventLogDetails_Struct { uint32 id; @@ -63,193 +53,203 @@ struct EventLogDetails_Struct { }; struct CharacterEventLog_Struct { -uint32 count; -uint8 eventid; -EventLogDetails_Struct eld[255]; + uint32 count; + 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]; }; -struct PlayerProfile_Struct; -struct GuildRankLevel_Struct; -struct GuildRanks_Struct; -struct ExtendedProfile_Struct; -struct GuildMember_Struct; class PTimerList; +#ifdef _WINDOWS +#if _MSC_VER > 1700 // greater than 2012 (2013+) +# define _ISNAN_(a) std::isnan(a) +#else +# include +# define _ISNAN_(a) _isnan(a) +#endif +#else +# define _ISNAN_(a) std::isnan(a) +#endif + class Database : public DBcore { public: Database(); Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port); ~Database(); - bool ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query); - - - /* - * General Character Related Stuff - */ /* Character Creation */ - bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); + bool AddToNameFilter(const 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 DeleteCharacter(char* name); 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); - bool UpdateName(const char* oldname, const char* newname); + bool ReserveName(uint32 account_id, char* name); + bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp); bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked); bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone); - 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); - bool DeleteCharacter(char* name); + bool UpdateName(const char* oldname, const char* newname); - /* - * General Information Getting Queries - */ + /* General Information Queries */ + + bool AddBannedIP(char* bannedIP, const char* notes); //Add IP address to the Banned_IPs table. + bool AddGMIP(char* ip_address, char* name); + bool CheckBannedIPs(const char* loginIP); //Check incoming connection against banned IP table. + bool CheckGMIPs(const char* loginIP, uint32 account_id); bool CheckNameFilter(const char* name, bool surname = false); bool CheckUsedName(const char* name); + uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); + uint32 GetCharacterID(const char *name); + uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0, float* oX = 0, float* oY = 0, float* oZ = 0); uint32 GetGuildIDByCharID(uint32 char_id); + void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetCharName(uint32 char_id, char* name); - uint32 GetCharacterInfo(const char* iName, uint32* oAccID = 0, uint32* oZoneID = 0, uint32* oInstanceID = 0,float* oX = 0, float* oY = 0, float* oZ = 0); - uint32 GetCharacterID(const char *name); - bool CheckBannedIPs(const char* loginIP); //Lieka Edit: Check incomming connection against banned IP table. - bool AddBannedIP(char* bannedIP, const char* notes); //Lieka Edit: Add IP address to the Banned_IPs table. - bool CheckGMIPs(const char* loginIP, uint32 account_id); - bool AddGMIP(char* ip_address, char* name); void LoginIP(uint32 AccountID, const char* LoginIP); - /* - * Instancing Stuff - */ - bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); - bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id); - bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id); - void DeleteInstance(uint16 instance_id); - bool CheckInstanceExpired(uint16 instance_id); - uint32 ZoneIDFromInstanceID(uint16 instance_id); - uint32 VersionFromInstanceID(uint16 instance_id); - uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); - bool GetUnusedInstanceID(uint16 &instance_id); - bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); - void PurgeExpiredInstances(); + /* Instancing */ + bool AddClientToInstance(uint16 instance_id, uint32 char_id); + bool CharacterInInstanceGroup(uint16 instance_id, uint32 char_id); + bool CheckInstanceExists(uint16 instance_id); + bool CheckInstanceExpired(uint16 instance_id); + bool CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration); + bool GetUnusedInstanceID(uint16 &instance_id); + bool GlobalInstance(uint16 instance_id); bool RemoveClientFromInstance(uint16 instance_id, uint32 char_id); bool RemoveClientsFromInstance(uint16 instance_id); - bool CheckInstanceExists(uint16 instance_id); - void BuryCorpsesInInstance(uint16 instance_id); - uint16 GetInstanceVersion(uint16 instance_id); + bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id); + bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id); + uint16 GetInstanceID(const char* zone, uint32 charid, int16 version); uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); - void GetCharactersInInstance(uint16 instance_id, std::list &charid_list); + uint16 GetInstanceVersion(uint16 instance_id); + uint32 GetTimeRemainingInstance(uint16 instance_id, bool &is_perma); + uint32 VersionFromInstanceID(uint16 instance_id); + uint32 ZoneIDFromInstanceID(uint16 instance_id); + void AssignGroupToInstance(uint32 gid, uint32 instance_id); void AssignRaidToInstance(uint32 rid, uint32 instance_id); + void BuryCorpsesInInstance(uint16 instance_id); + void DeleteInstance(uint16 instance_id); void FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid); void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid); + void GetCharactersInInstance(uint16 instance_id, std::list &charid_list); + void PurgeExpiredInstances(); void SetInstanceDuration(uint16 instance_id, uint32 new_duration); - bool GlobalInstance(uint16 instance_id); - /* - * Adventure related. - */ + /* 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 */ - /* - * Account Related - */ - uint32 GetMiniLoginAccount(char* ip); - void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); - uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0); - int16 CheckStatus(uint32 account_id); - uint32 CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id = 0); bool DeleteAccount(const char* name); + bool GetLiveChar(uint32 account_id, char* cname); bool SetAccountStatus(const char* name, int16 status); bool SetLocalPassword(uint32 accid, const char* password); + bool UpdateLiveChar(char* charname, uint32 lsaccount_id); + + int16 CheckStatus(uint32 account_id); + + uint32 CheckLogin(const char* name, const char* password, int16* oStatus = 0); + uint32 CreateAccount(const char* name, const char* password, int16 status, uint32 lsaccount_id = 0); uint32 GetAccountIDFromLSID(uint32 iLSID, char* oAccountName = 0, int16* oStatus = 0); - bool UpdateLiveChar(char* charname,uint32 lsaccount_id); - bool GetLiveChar(uint32 account_id, char* cname); + uint32 GetMiniLoginAccount(char* ip); uint8 GetAgreementFlag(uint32 acctid); + + void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus); void SetAgreementFlag(uint32 acctid); - /* - * Groups - */ - uint32 GetGroupID(const char* name); - void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false); - void ClearGroup(uint32 gid = 0); - char* GetGroupLeaderForLogin(const char* name,char* leaderbuf); - 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); - void ClearGroupLeader(uint32 gid = 0); + /* Groups */ + char* GetGroupLeaderForLogin(const char* name,char* leaderbuf); + char* GetGroupLeadershipInfo(uint32 gid, char* leaderbuf, char* maintank = nullptr, char* assist = nullptr, char* puller = nullptr, char *marknpc = nullptr, char *mentoree = nullptr, int *mentor_percent = nullptr, GroupLeadershipAA_Struct* GLAA = nullptr); + + uint32 GetGroupID(const char* name); + + void ClearGroup(uint32 gid = 0); + void ClearGroupLeader(uint32 gid = 0); + void SetGroupID(const char* name, uint32 id, uint32 charid, uint32 ismerc = false); + void SetGroupLeaderName(uint32 gid, const char* name); + + /* Raids */ - /* - * Raids - */ - void ClearRaid(uint32 rid = 0); - void ClearRaidDetails(uint32 rid = 0); - uint32 GetRaidID(const char* name); const char *GetRaidLeaderName(uint32 rid); - bool CheckDatabaseConversions(); + uint32 GetRaidID(const char* name); + + void ClearRaid(uint32 rid = 0); + void ClearRaidDetails(uint32 rid = 0); + void ClearRaidLeader(uint32 gid = 0xFFFFFFFF, uint32 rid = 0); + 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); + + /* Database Conversions 'database_conversions.cpp' */ + + bool CheckDatabaseConversions(); + bool CheckDatabaseConvertBotsPostPPDeblob(); + bool CheckDatabaseConvertCorpseDeblob(); + bool CheckDatabaseConvertPPDeblob(); + + /* Database Variables */ - /* - * Database Variables - */ bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len); bool SetVariable(const char* varname, const char* varvalue); bool LoadVariables(); uint32 LoadVariables_MQ(char** query); bool LoadVariables_result(MySQLRequestResult results); - /* - * General Queries - */ - bool LoadZoneNames(); - bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0); - bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); - uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version); - uint32 GetZoneID(const char* zonename); - uint8 GetPEQZone(uint32 zoneID, uint32 version); - const char* GetZoneName(uint32 zoneID, bool ErrorUnknown = false); - uint8 GetServerType(); + /* General Queries */ + bool GetSafePoints(const char* short_name, uint32 version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr); bool GetSafePoints(uint32 zoneID, uint32 version, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, int16* minstatus = 0, uint8* minlevel = 0, char *flag_needed = nullptr) { return GetSafePoints(GetZoneName(zoneID), version, safe_x, safe_y, safe_z, minstatus, minlevel, flag_needed); } - uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); - uint8 GetRaceSkill(uint8 skillid, uint8 in_race); + bool GetZoneGraveyard(const uint32 graveyard_id, uint32* graveyard_zoneid = 0, float* graveyard_x = 0, float* graveyard_y = 0, float* graveyard_z = 0, float* graveyard_heading = 0); + bool GetZoneLongName(const char* short_name, char** long_name, char* file_name = 0, float* safe_x = 0, float* safe_y = 0, float* safe_z = 0, uint32* graveyard_id = 0, uint32* maxclients = 0); bool LoadPTimers(uint32 charid, PTimerList &into); - void ClearPTimers(uint32 charid); - void ClearMerchantTemp(); - void SetLFP(uint32 CharID, bool LFP); - void SetLFG(uint32 CharID, bool LFG); - void SetFirstLogon(uint32 CharID, uint8 firstlogon); - void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); + bool LoadZoneNames(); + + const char* GetZoneName(uint32 zoneID, bool ErrorUnknown = false); + + uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version); + uint32 GetZoneID(const char* zonename); + + uint8 GetPEQZone(uint32 zoneID, uint32 version); + uint8 GetRaceSkill(uint8 skillid, uint8 in_race); + uint8 GetServerType(); + uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level); + void AddReport(std::string who, std::string against, std::string lines); + void ClearMerchantTemp(); + void ClearPTimers(uint32 charid); + void SetFirstLogon(uint32 CharID, uint8 firstlogon); + void SetLFG(uint32 CharID, bool LFG); + void SetLFP(uint32 CharID, bool LFP); + void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); + + /* EQEmuLogSys */ + void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings); private: void DBInitVars(); @@ -261,19 +261,14 @@ private: VarCache_Struct** varcache_array; uint32 varcache_lastupdate; - - /* - * Groups, utility methods. - */ + /* Groups, utility methods. */ void ClearAllGroupLeaders(); void ClearAllGroups(); - - /* - * Raid, utility methods. - */ + /* Raid, utility methods. */ void ClearAllRaids(); void ClearAllRaidDetails(); + void ClearAllRaidLeaders(); }; #endif diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp new file mode 100644 index 000000000..8a938e8b5 --- /dev/null +++ b/common/database_conversions.cpp @@ -0,0 +1,1988 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 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 +*/ + +#include "../common/global_define.h" +#include "../common/rulesys.h" +#include "../common/string_util.h" +#include "../common/timer.h" + +#include "database.h" +#include "extprofile.h" + +#include +#include + +// Disgrace: for windows compile +#ifdef _WINDOWS +#include +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#else +#include "unix.h" +#include +#include +#endif + +#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; + uint32 aug6; + uint8 attuned; + }; + } + + 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() + +static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50) { + if ((x != n) && (x % (n / 100 + 1) != 0)) return; + float ratio = x / (float)n; + int c = ratio * w; + std::cout << std::setw(3) << (int)(ratio * 100) << "% ["; + for (int x = 0; x < c; x++) std::cout << "="; + for (int x = c; x < w; x++) std::cout << " "; + std::cout << "]\r" << std::flush; +} + + +bool Database::CheckDatabaseConversions() { + CheckDatabaseConvertPPDeblob(); + CheckDatabaseConvertBotsPostPPDeblob(); + CheckDatabaseConvertCorpseDeblob(); + + /* Fetch Automatic Upgrade Script */ + if (!std::ifstream("eqemu_update.pl")){ + std::cout << "Pulling down automatic database upgrade script..." << std::endl; +#ifdef _WIN32 + system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl'); if ($response->is_success){ open(FILE, '> eqemu_update.pl'); print FILE $response->decoded_content; close(FILE); }\""); +#else + system("wget --no-check-certificate -O eqemu_update.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_update.pl"); +#endif + } + + /* + Automatic (Database) Upgrade Script + Script: eqemu_update.pl V 1 - the number that world passes to the script will + force the script to check for a newer version to update itself with + eqemu_update.pl ran_from_world - won't bring up a menu if your database versions match + eqemu_update.pl - ran standalone will bring up a menu prompt + */ + + /* Check for a new version of this script, the arg passed + would have to be higher than the copy they have downloaded + locally and they will re fetch */ + system("perl eqemu_update.pl V 2"); + + /* Run Automatic Database Upgrade Script */ + system("perl eqemu_update.pl ran_from_world"); + + return true; +} + +bool Database::CheckDatabaseConvertPPDeblob(){ + unsigned int lengths; + unsigned int lengths_e; + std::string squery; + Convert::PlayerProfile_Struct* pp; + ExtendedProfile_Struct* e_pp; + uint32 pplen = 0; + uint32 i; + int character_id = 0; + int account_id = 0; + int number_of_characters = 0; + int printppdebug = 0; /* Prints Player Profile */ + int runconvert = 0; + + /* Check For Legacy Storage Method */ + std::string rquery = StringFormat("SHOW TABLES LIKE 'character_'"); + auto results = QueryDatabase(rquery); + if (results.RowCount() == 1){ + runconvert = 1; + printf("\n\n::: Legacy Character Data Binary Blob Storage Detected... \n"); + printf("----------------------------------------------------------\n\n"); + printf(" Database currently has character data being stored via \n"); + printf(" the legacy character storage method and will proceed with converting...\n\n"); + printf(" It is recommended that you backup your database \n"); + printf(" before continuing the automatic conversion process...\n\n"); + printf("----------------------------------------------------------\n\n"); + std::cout << "Press ENTER to continue....." << std::endl << std::endl; + std::cin.ignore(1); + } + + // runconvert = 0; + // printppdebug = 1; + + if (runconvert == 1){ + printf("Running character binary blob to database conversion... \n"); + /* Get the number of characters */ + rquery = StringFormat("SELECT COUNT(`id`) FROM `character_`"); + results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + number_of_characters = atoi(row[0]); + printf("Number of Characters in Database: %i \n", number_of_characters); + } + + /* Check for table `character_data` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_data'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_data` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_data` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`account_id` int(11) NOT NULL DEFAULT '0', " + "`name` varchar(64) NOT NULL DEFAULT '', " + "`last_name` varchar(64) NOT NULL DEFAULT '', " + "`title` varchar(32) NOT NULL DEFAULT '', " + "`suffix` varchar(32) NOT NULL DEFAULT '', " + "`zone_id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`zone_instance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`y` float NOT NULL DEFAULT '0', " + "`x` float NOT NULL DEFAULT '0', " + "`z` float NOT NULL DEFAULT '0', " + "`heading` float NOT NULL DEFAULT '0', " + "`gender` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`race` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`class` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`deity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`birthday` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`last_login` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`time_played` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`level2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`anon` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`gm` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`face` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hair_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hair_style` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`beard` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`beard_color` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`eye_color_1` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`eye_color_2` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_heritage` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_tattoo` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`drakkin_details` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_seconds` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_number` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_minutes` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_time_hours` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_points_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`aa_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_leadership_exp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_leadership_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`cur_hp` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`mana` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`endurance` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`intoxication` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`str` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`sta` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`cha` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`dex` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`int` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`agi` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`wis` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`zone_change_count` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`toxicity` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`hunger_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`thirst_level` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ability_up` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_guk` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_mir` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_mmc` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_ruj` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_tak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`ldon_points_available` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_time_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`career_tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`tribute_active` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_status` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_kills` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_deaths` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_current_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_career_points` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_best_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_worst_death_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_current_kill_streak` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp2` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`pvp_type` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`show_helm` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`group_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`raid_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`guild_auto_consent` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`leadership_exp_on` tinyint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`RestTimer` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`air_remaining` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`autosplit_enabled` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`lfp` tinyint(1) unsigned NOT NULL DEFAULT '0', " + "`lfg` tinyint(1) unsigned NOT NULL DEFAULT '0', " + "`mailkey` char(16) NOT NULL DEFAULT '', " + "`xtargets` tinyint(3) unsigned NOT NULL DEFAULT '5', " + "`firstlogon` tinyint(3) NOT NULL DEFAULT '0', " + "`e_aa_effects` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`e_percent_to_aa` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`e_expended_aa_spent` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "PRIMARY KEY(`id`), " + "UNIQUE KEY `name` (`name`), " + "KEY `account_id` (`account_id`) " + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_currency` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_currency'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_currency` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_currency` ( " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper_bank` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `platinum_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `gold_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `silver_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `copper_cursor` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `radiant_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_radiant_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `career_ebon_crystals` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY (`id`), " + " KEY `id` (`id`) " + " ) ENGINE=InnoDB DEFAULT CHARSET=latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_alternate_abilities` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_alternate_abilities'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_alternate_abilities` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_alternate_abilities` ( " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_id` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " `aa_value` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + " PRIMARY KEY(`id`,`slot`), " + " KEY `id` (`id`) " + " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_bind` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_bind'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_bind` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_bind` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`is_home` tinyint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`zone_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`instance_id` mediumint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`x` float NOT NULL DEFAULT '0', " + "`y` float NOT NULL DEFAULT '0', " + "`z` float NOT NULL DEFAULT '0', " + "`heading` float NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `is_home`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_languages` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_languages'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_languages` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_languages` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`lang_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `lang_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_skills` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_skills'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_skills` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_skills` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`skill_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`value` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `skill_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_spells` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_spells'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_spells` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_spells` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, " + "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `slot_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_memmed_spells` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_memmed_spells'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_memmed_spells` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_memmed_spells` ( " + "`id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "`spell_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`, `slot_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_disciplines` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_disciplines'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_disciplines` doesn't exist... creating..."); + rquery = StringFormat( + " CREATE TABLE `character_disciplines` ( " + " `id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + " `slot_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + " `disc_id` smallint(11) UNSIGNED NOT NULL DEFAULT '0', " + " PRIMARY KEY(`id`, `slot_id`), " + " KEY `id` (`id`) " + " ) ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_material` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_material'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_material` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_material` ( " + "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT," + "`slot` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`blue` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`green` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`red` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`use_tint` tinyint(11) UNSIGNED NOT NULL DEFAULT '0'," + "`color` int(11) UNSIGNED NOT NULL DEFAULT '0'," + "PRIMARY KEY(`id`, `slot`)," + "KEY `id` (`id`)" + ") ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_tribute` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_tribute'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_tribute` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_tribute` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`tier` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`tribute` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_bandolier` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_bandolier'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_bandolier` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_bandolier` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`bandolier_id` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`bandolier_slot` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`item_id` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "`icon` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "`bandolier_name` varchar(32) NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`,`bandolier_id`, `bandolier_slot`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_potionbelt` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_potionbelt'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_potionbelt` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_potionbelt` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`potion_id` tinyint(11) unsigned NOT NULL DEFAULT '0', " + "`item_id` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "`icon` int(11) UNSIGNED NOT NULL DEFAULT '0', " + "PRIMARY KEY(`id`,`potion_id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_potionbelt` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_inspect_messages'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_inspect_messages` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_inspect_messages` ( " + "`id` int(11) unsigned NOT NULL DEFAULT 0, " + "`inspect_message` varchar(255) NOT NULL DEFAULT '', " + "PRIMARY KEY(`id`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1;" + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + /* Check for table `character_leadership_abilities` */ + rquery = StringFormat("SHOW TABLES LIKE 'character_leadership_abilities'"); + results = QueryDatabase(rquery); + if (results.RowCount() == 0){ + printf("Table: `character_leadership_abilities` doesn't exist... creating..."); + rquery = StringFormat( + "CREATE TABLE `character_leadership_abilities` (" + "`id` int(11) UNSIGNED NOT NULL DEFAULT 0, " + "`slot` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "`rank` smallint(11) UNSIGNED NOT NULL DEFAULT 0, " + "PRIMARY KEY(`id`,`slot`), " + "KEY `id` (`id`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + auto results = QueryDatabase(rquery); + printf(" done...\n"); + } + + /* Done */ + printf("Starting conversion...\n\n"); + + + int char_iter_count = 0; + rquery = StringFormat("SELECT `id` FROM `character_`"); + results = QueryDatabase(rquery); + + uint8 firstlogon = 0; + uint8 lfg = 0; + uint8 lfp = 0; + std::string mailkey; + uint8 xtargets = 0; + std::string inspectmessage; + + for (auto row = results.begin(); row != results.end(); ++row) { + char_iter_count++; + squery = StringFormat("SELECT `id`, `profile`, `name`, `level`, `account_id`, `firstlogon`, `lfg`, `lfp`, `mailkey`, `xtargets`, `inspectmessage`, `extprofile` FROM `character_` WHERE `id` = %i", atoi(row[0])); + auto results2 = QueryDatabase(squery); + auto row2 = results2.begin(); + pp = (Convert::PlayerProfile_Struct*)row2[1]; + e_pp = (ExtendedProfile_Struct*)row2[11]; + character_id = atoi(row[0]); + account_id = atoi(row2[4]); + /* Convert some data from the character_ table that is still relevant */ + firstlogon = atoi(row2[5]); + lfg = atoi(row2[6]); + lfp = atoi(row2[7]); + mailkey = row2[8]; + xtargets = atoi(row2[9]); + inspectmessage = row2[10]; + + /* Verify PP Integrity */ + lengths = results2.LengthOfColumn(1); + if (lengths == sizeof(Convert::PlayerProfile_Struct)) { /* If PP is the size it is expected to be */ + memcpy(pp, row2[1], sizeof(Convert::PlayerProfile_Struct)); + } + /* Continue of PP Size does not match (Usually a created character never logged in) */ + else { + std::cout << (row2[2] ? row2[2] : "Unknown") << " ID: " << character_id << " size mismatch. Expected Size: " << sizeof(Convert::PlayerProfile_Struct) << " Seen: " << lengths << std::endl; + continue; + } + + lengths_e = results2.LengthOfColumn(11); + if (lengths_e == sizeof(ExtendedProfile_Struct)) { + memcpy(e_pp, row2[11], sizeof(ExtendedProfile_Struct)); + } + if (e_pp->expended_aa > 4000000){ e_pp->expended_aa = 0; } + + /* Loading Status on conversion */ + if (runconvert == 1){ + std::cout << "\r" << char_iter_count << "/" << number_of_characters << " " << std::flush; + loadbar(char_iter_count, number_of_characters, 50); + + /* Run inspect message convert */ + if (inspectmessage != ""){ + std::string rquery = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message)" + "VALUES (%u, '%s')", + character_id, + EscapeString(inspectmessage).c_str() + ); + auto results = QueryDatabase(rquery); + } + + /* Run Currency Convert */ + std::string rquery = StringFormat("REPLACE INTO `character_currency` (id, platinum, gold, silver, copper," + "platinum_bank, gold_bank, silver_bank, copper_bank," + "platinum_cursor, gold_cursor, silver_cursor, copper_cursor, " + "radiant_crystals, career_radiant_crystals, ebon_crystals, career_ebon_crystals)" + "VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u)", + character_id, + pp->platinum, + pp->gold, + pp->silver, + pp->copper, + pp->platinum_bank, + pp->gold_bank, + pp->silver_bank, + pp->copper_bank, + pp->platinum_cursor, + pp->gold_cursor, + pp->silver_cursor, + pp->copper_cursor, + pp->currentRadCrystals, + pp->careerRadCrystals, + pp->currentEbonCrystals, + pp->careerEbonCrystals + ); + auto results = QueryDatabase(rquery); + + if (pp->tribute_time_remaining < 0 || pp->tribute_time_remaining == 4294967295){ pp->tribute_time_remaining = 0; } + + /* Run Character Data Convert */ + rquery = StringFormat( + "REPLACE INTO `character_data` (" + "id," + "account_id," + "`name`," + "last_name," + "gender," + "race," + "class," + "`level`," + "deity," + "birthday," + "last_login," + "time_played," + "pvp_status," + "level2," + "anon," + "gm," + "intoxication," + "hair_color," + "beard_color," + "eye_color_1," + "eye_color_2," + "hair_style," + "beard," + "ability_time_seconds," + "ability_number," + "ability_time_minutes," + "ability_time_hours," + "title," + "suffix," + "exp," + "points," + "mana," + "cur_hp," + "str," + "sta," + "cha," + "dex," + "`int`," + "agi," + "wis," + "face," + "y," + "x," + "z," + "heading," + "pvp2," + "pvp_type," + "autosplit_enabled," + "zone_change_count," + "drakkin_heritage," + "drakkin_tattoo," + "drakkin_details," + "toxicity," + "hunger_level," + "thirst_level," + "ability_up," + "zone_id," + "zone_instance," + "leadership_exp_on," + "ldon_points_guk," + "ldon_points_mir," + "ldon_points_mmc," + "ldon_points_ruj," + "ldon_points_tak," + "ldon_points_available," + "tribute_time_remaining," + "show_helm," + "career_tribute_points," + "tribute_points," + "tribute_active," + "endurance," + "group_leadership_exp," + "raid_leadership_exp," + "group_leadership_points," + "raid_leadership_points," + "air_remaining," + "pvp_kills," + "pvp_deaths," + "pvp_current_points," + "pvp_career_points," + "pvp_best_kill_streak," + "pvp_worst_death_streak," + "pvp_current_kill_streak," + "aa_points_spent," + "aa_exp," + "aa_points," + "group_auto_consent," + "raid_auto_consent," + "guild_auto_consent," + "RestTimer," + "firstlogon," + "lfg," + "lfp," + "mailkey," + "xtargets," + "e_aa_effects," + "e_percent_to_aa," + "e_expended_aa_spent" + ")" + "VALUES (" + "%u," // id + "%u," // account_id + "'%s'," // `name` + "'%s'," // last_name + "%u," // gender + "%u," // race + "%u," // class + "%u," // `level` + "%u," // deity + "%u," // birthday + "%u," // last_login + "%u," // time_played + "%u," // pvp_status + "%u," // level2 + "%u," // anon + "%u," // gm + "%u," // intoxication + "%u," // hair_color + "%u," // beard_color + "%u," // eye_color_1 + "%u," // eye_color_2 + "%u," // hair_style + "%u," // beard + "%u," // ability_time_seconds + "%u," // ability_number + "%u," // ability_time_minutes + "%u," // ability_time_hours + "'%s'," // title + "'%s'," // suffix + "%u," // exp + "%u," // points + "%u," // mana + "%u," // cur_hp + "%u," // str + "%u," // sta + "%u," // cha + "%u," // dex + "%u," // `int` + "%u," // agi + "%u," // wis + "%u," // face + "%f," // y + "%f," // x + "%f," // z + "%f," // heading + "%u," // pvp2 + "%u," // pvp_type + "%u," // autosplit_enabled + "%u," // zone_change_count + "%u," // drakkin_heritage + "%u," // drakkin_tattoo + "%u," // drakkin_details + "%i," // toxicity + "%u," // hunger_level + "%u," // thirst_level + "%u," // ability_up + "%u," // zone_id + "%u," // zone_instance + "%u," // leadership_exp_on + "%u," // ldon_points_guk + "%u," // ldon_points_mir + "%u," // ldon_points_mmc + "%u," // ldon_points_ruj + "%u," // ldon_points_tak + "%u," // ldon_points_available + "%u," // tribute_time_remaining + "%u," // show_helm + "%u," // career_tribute_points + "%u," // tribute_points + "%u," // tribute_active + "%u," // endurance + "%u," // group_leadership_exp + "%u," // raid_leadership_exp + "%u," // group_leadership_points + "%u," // raid_leadership_points + "%u," // air_remaining + "%u," // pvp_kills + "%u," // pvp_deaths + "%u," // pvp_current_points + "%u," // pvp_career_points + "%u," // pvp_best_kill_streak + "%u," // pvp_worst_death_streak + "%u," // pvp_current_kill_streak + "%u," // aa_points_spent + "%u," // aa_exp + "%u," // aa_points + "%u," // group_auto_consent + "%u," // raid_auto_consent + "%u," // guild_auto_consent + "%u," // RestTimer + "%u," // First Logon - References online status for EVENT_CONNECT/EVENT_DISCONNECt + "%u," // Looking for Group + "%u," // Looking for P? + "'%s'," // Mailkey + "%u," // X Targets + "%u," // AA Effects + "%u," // Percent to AA + "%u" // e_expended_aa_spent + ")", + character_id, + account_id, + EscapeString(pp->name).c_str(), + EscapeString(pp->last_name).c_str(), + pp->gender, + pp->race, + pp->class_, + pp->level, + pp->deity, + pp->birthday, + pp->lastlogin, + pp->timePlayedMin, + pp->pvp, + pp->level2, + pp->anon, + pp->gm, + pp->intoxication, + pp->haircolor, + pp->beardcolor, + pp->eyecolor1, + pp->eyecolor2, + pp->hairstyle, + pp->beard, + pp->ability_time_seconds, + pp->ability_number, + pp->ability_time_minutes, + pp->ability_time_hours, + EscapeString(pp->title).c_str(), + EscapeString(pp->suffix).c_str(), + pp->exp, + pp->points, + pp->mana, + pp->cur_hp, + pp->STR, + pp->STA, + pp->CHA, + pp->DEX, + pp->INT, + pp->AGI, + pp->WIS, + pp->face, + pp->y, + pp->x, + pp->z, + pp->heading, + pp->pvp2, + pp->pvptype, + pp->autosplit, + pp->zone_change_count, + pp->drakkin_heritage, + pp->drakkin_tattoo, + pp->drakkin_details, + pp->toxicity, + pp->hunger_level, + pp->thirst_level, + pp->ability_up, + pp->zone_id, + pp->zoneInstance, + pp->leadAAActive == 0 ? 0 : 1, + pp->ldon_points_guk, + pp->ldon_points_mir, + pp->ldon_points_mmc, + pp->ldon_points_ruj, + pp->ldon_points_tak, + pp->ldon_points_available, + pp->tribute_time_remaining, + pp->showhelm, + pp->career_tribute_points, + pp->tribute_points, + pp->tribute_active, + pp->endurance, + pp->group_leadership_exp, + pp->raid_leadership_exp, + pp->group_leadership_points, + pp->raid_leadership_points, + pp->air_remaining, + pp->PVPKills, + pp->PVPDeaths, + pp->PVPCurrentPoints, + pp->PVPCareerPoints, + pp->PVPBestKillStreak, + pp->PVPWorstDeathStreak, + pp->PVPCurrentKillStreak, + pp->aapoints_spent, + pp->expAA, + pp->aapoints, + pp->groupAutoconsent, + pp->raidAutoconsent, + pp->guildAutoconsent, + pp->RestTimer, + firstlogon, + lfg, + lfp, + mailkey.c_str(), + xtargets, + e_pp->aa_effects, + e_pp->perAA, + e_pp->expended_aa + ); + results = QueryDatabase(rquery); + + + /* + We set a first entry variable because we need the first initial piece of the query to be declared + This is to speed up the INSERTS and trim down the amount of individual sends during the process. + The speed difference is dramatic + */ + /* Run AA Convert */ + int first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_AA_ARRAY; i++){ + if (pp->aa_array[i].AA > 0 && pp->aa_array[i].value > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value)" + " VALUES (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + first_entry = 1; + } + else { + rquery = rquery + StringFormat(", (%u, %u, %u, %u)", character_id, i, pp->aa_array[i].AA, pp->aa_array[i].value); + } + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + + /* Run Bind Home Convert */ + if (pp->binds[4].zoneId < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) { + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 1)", + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading); + if (rquery != ""){ results = QueryDatabase(rquery); } + } + + /* Run Bind Convert */ + if (pp->binds[0].zoneId < 999 && !_ISNAN_(pp->binds[0].x) && !_ISNAN_(pp->binds[0].y) && !_ISNAN_(pp->binds[0].z) && !_ISNAN_(pp->binds[0].heading)) { + rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + " VALUES (%u, %u, %u, %f, %f, %f, %f, 0)", + character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading); + if (rquery != ""){ results = QueryDatabase(rquery); } + } + /* Run Language Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_LANGUAGE; i++){ + if (pp->languages[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)", character_id, i, pp->languages[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Skill Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_SKILL; i++){ + if (pp->skills[i] > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)", character_id, i, pp->skills[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Spell Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ + if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->spell_book[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Max Memmed Spell Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ + if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->mem_spells[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Discipline Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_PP_DISCIPLINES; i++){ + if (pp->disciplines.values[i] > 0 && pp->disciplines.values[i] < 60000){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_disciplines` (id, slot_id, disc_id) VALUES (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, i, pp->disciplines.values[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Material Color Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < _MaterialCount; i++){ + if (pp->item_tint[i].color > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_material` (id, slot, blue, green, red, use_tint, color) VALUES (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u)", character_id, i, pp->item_tint[i].rgb.blue, pp->item_tint[i].rgb.green, pp->item_tint[i].rgb.red, pp->item_tint[i].rgb.use_tint, pp->item_tint[i].color); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Tribute Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::TRIBUTE_SIZE; i++){ + if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != 4294967295){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Bandolier Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++){ + if (strlen(pp->bandoliers[i].name) < 32) { + for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){ + if (pp->bandoliers[i].items[si].item_id > 0){ + if (first_entry != 1) { + rquery = StringFormat("REPLACE INTO `character_bandolier` (id, bandolier_id, bandolier_slot, item_id, icon, bandolier_name) VALUES (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %i, %u, %u, '%s')", character_id, i, si, pp->bandoliers[i].items[si].item_id, pp->bandoliers[i].items[si].icon, pp->bandoliers[i].name); + } + } + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Potion Belt Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < EmuConstants::POTION_BELT_SIZE; i++){ + if (pp->potionbelt.items[i].item_id > 0){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_potionbelt` (id, potion_id, item_id, icon) VALUES (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u, %u)", character_id, i, pp->potionbelt.items[i].item_id, pp->potionbelt.items[i].icon); + + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + /* Run Leadership AA Convert */ + first_entry = 0; rquery = ""; + for (i = 0; i < MAX_LEADERSHIP_AA_ARRAY; i++){ + if (pp->leader_abilities.ranks[i] > 0 && pp->leader_abilities.ranks[i] < 6){ + if (first_entry != 1){ + rquery = StringFormat("REPLACE INTO `character_leadership_abilities` (id, slot, rank) VALUES (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + first_entry = 1; + } + rquery = rquery + StringFormat(", (%i, %u, %u)", character_id, i, pp->leader_abilities.ranks[i]); + } + } + if (rquery != ""){ results = QueryDatabase(rquery); } + } + } + if (runconvert == 1){ + std::string rquery = StringFormat("RENAME TABLE `character_` TO `character_old`"); QueryDatabase(rquery); + printf("\n\nRenaming `character_` table to `character_old`, this is a LARGE table so when you don't need it anymore, I would suggest deleting it yourself...\n"); + printf("\n\nCharacter blob conversion complete, continuing world bootup...\n"); + } + } + return true; +} + +bool Database::CheckDatabaseConvertBotsPostPPDeblob(){ +#ifdef BOTS + int runbotsconvert = 0; + + /* Check For Legacy Bot References */ + std::string rquery = StringFormat("SHOW CREATE VIEW `vwBotCharacterMobs`"); + auto results = QueryDatabase(rquery); + if (results.RowCount() == 1){ + auto row = results.begin(); + std::string table_check = row[1]; + + if (table_check.find("character_data") == -1){ + runbotsconvert = 1; + printf("\n\n::: Legacy Bot Views and Function Detected... \n"); + printf("----------------------------------------------------------\n\n"); + printf(" Database currently has bot view/function linkage to obselete \n"); + printf(" table references and will now be converted...\n\n"); + printf(" It is recommended that you backup your database \n"); + printf(" before continuing the automatic conversion process...\n\n"); + printf("----------------------------------------------------------\n\n"); + std::cout << "Press ENTER to continue....." << std::endl << std::endl; + std::cin.ignore(1); + } + } + + if (runbotsconvert == 1){ + printf("Running bot views/function database conversion... \n"); + + /* Update view `vwbotcharactermobs` */ + rquery = StringFormat("DROP VIEW `vwBotCharacterMobs`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwBotCharacterMobs` AS\n" + "SELECT _utf8'C' AS mobtype,\n" // Natedog: '_utf8' + "c.`id`,\n" + "c.`name`,\n" + "c.`class`,\n" + "c.`level`,\n" + "c.`last_login`,\n" + "c.`zone_id`\n" + "FROM `character_data` AS c\n" + "UNION ALL\n" + "SELECT _utf8'B' AS mobtype,\n" // Natedog: '_utf8' + "b.`BotID` AS id,\n" + "b.`Name` AS name,\n" + "b.`Class` AS class,\n" + "b.`BotLevel` AS level,\n" + "0 AS timelaston,\n" + "0 AS zoneid\n" + "FROM bots AS b;" + ); + results = QueryDatabase(rquery); + + + /* Update function `GetMobType` */ + rquery = StringFormat("DROP FUNCTION IF EXISTS `GetMobType`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)\n" + "BEGIN\n" + " DECLARE Result CHAR(1);\n" + "\n" + " SET Result = NULL;\n" + "\n" + " IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN\n" + " SET Result = 'C';\n" + " ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN\n" + " SET Result = 'B';\n" + " END IF;\n " + "\n" + " RETURN Result;\n" + "END" + ); + results = QueryDatabase(rquery); + + + /* Update view `vwgroups` */ + rquery = StringFormat("DROP VIEW IF EXISTS `vwGroups`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwGroups` AS\n" + "SELECT g.`groupid` AS groupid,\n" + "GetMobType(g.`name`) AS mobtype,\n" + "g.`name` AS name,\n" + "g.`charid` AS mobid,\n" + "IFNULL(c.`level`, b.`BotLevel`) AS level\n" + "FROM `group_id` AS g\n" + "LEFT JOIN `character_data` AS c ON g.`name` = c.`name`\n" + "LEFT JOIN `bots` AS b ON g.`name` = b.`Name`;" + ); + results = QueryDatabase(rquery); + + + /* Update view `vwbotgroups` */ + rquery = StringFormat("DROP VIEW IF EXISTS `vwBotGroups`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwBotGroups` AS\n" + "SELECT g.`BotGroupId`,\n" + "g.`BotGroupName`,\n" + "g.`BotGroupLeaderBotId`,\n" + "b.`Name` AS BotGroupLeaderName,\n" + "b.`BotOwnerCharacterId`,\n" + "c.`name` AS BotOwnerCharacterName\n" + "FROM `botgroup` AS g\n" + "JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID`\n" + "JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id`\n" + "ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`;" + ); + results = QueryDatabase(rquery); + + + /* Update view `vwguildmembers` */ + rquery = StringFormat("DROP VIEW IF EXISTS `vwGuildMembers`;"); + results = QueryDatabase(rquery); + + rquery = StringFormat( + "CREATE VIEW `vwGuildMembers` AS\n" + "SELECT 'C' AS mobtype,\n" + "cm.`char_id`,\n" + "cm.`guild_id`,\n" + "cm.`rank`,\n" + "cm.`tribute_enable`,\n" + "cm.`total_tribute`,\n" + "cm.`last_tribute`,\n" + "cm.`banker`,\n" + "cm.`public_note`,\n" + "cm.`alt`\n" + "FROM `guild_members` AS cm\n" + "UNION ALL\n" + "SELECT 'B' AS mobtype,\n" + "bm.`char_id`,\n" + "bm.`guild_id`,\n" + "bm.`rank`,\n" + "bm.`tribute_enable`,\n" + "bm.`total_tribute`,\n" + "bm.`last_tribute`,\n" + "bm.`banker`,\n" + "bm.`public_note`,\n" + "bm.`alt`\n" + "FROM `botguildmembers` AS bm;" + ); + results = QueryDatabase(rquery); + } + + if (runbotsconvert == 1){ + printf("\n\nBot views/function conversion complete, continuing world bootup...\n"); + } + +#endif + return true; +} + +bool Database::CheckDatabaseConvertCorpseDeblob(){ + Convert::DBPlayerCorpse_Struct_temp* dbpc; + Convert::classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c; + uint32 in_datasize; + bool is_sof = false; + std::string c_type; + std::string scquery; + int8 first_entry = 0; + + std::string query = StringFormat("SHOW TABLES LIKE 'player_corpses'"); + auto results = QueryDatabase(query); + if (results.RowCount() != 0){ + query = StringFormat( + "CREATE TABLE `character_corpse_items` ( " + "`corpse_id` int(11) unsigned NOT NULL, " + "`equip_slot` int(11) unsigned NOT NULL, " + "`item_id` int(11) unsigned DEFAULT NULL, " + "`charges` int(11) unsigned DEFAULT NULL, " + "`aug_1` int(11) unsigned DEFAULT '0', " + "`aug_2` int(11) unsigned DEFAULT '0', " + "`aug_3` int(11) unsigned DEFAULT '0', " + "`aug_4` int(11) unsigned DEFAULT '0', " + "`aug_5` int(11) unsigned DEFAULT '0', " + "`aug_6` int(11) unsigned DEFAULT '0', " + "`attuned` smallint(5) NOT NULL DEFAULT '0', " + "PRIMARY KEY(`corpse_id`, `equip_slot`) " + ") ENGINE = InnoDB DEFAULT CHARSET = latin1; " + ); + results = QueryDatabase(query); + query = StringFormat("RENAME TABLE `player_corpses` TO `character_corpses`"); + results = QueryDatabase(query); + query = StringFormat( + " ALTER TABLE `character_corpses` \n" + " ADD COLUMN `is_locked` tinyint(11) NULL DEFAULT 0 AFTER `WasAtGraveyard`, \n" + " ADD COLUMN `exp` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `size` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `level` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `race` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `gender` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `class` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `deity` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `texture` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `helm_texture` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `copper` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `silver` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `gold` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `platinum` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `hair_color` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `beard_color` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `eye_color_1` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `eye_color_2` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `hair_style` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `face` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `beard` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `drakkin_heritage` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `drakkin_tattoo` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `drakkin_details` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_1` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_2` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_3` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_4` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_5` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_6` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_7` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_8` int(11) UNSIGNED NULL DEFAULT 0, \n" + " ADD COLUMN `wc_9` int(11) UNSIGNED NULL DEFAULT 0, \n" + " CHANGE COLUMN `zoneid` `zone_id` smallint(5) NOT NULL DEFAULT 0 AFTER `charname`, \n" + " CHANGE COLUMN `instanceid` `instance_id` smallint(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `zone_id`, \n" + " CHANGE COLUMN `timeofdeath` `time_of_death` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `data`, \n" + " CHANGE COLUMN `rezzed` `is_rezzed` tinyint(3) UNSIGNED NULL DEFAULT 0 AFTER `time_of_death`, \n" + " CHANGE COLUMN `IsBurried` `is_buried` tinyint(3) NOT NULL DEFAULT 0 AFTER `is_rezzed`; \n" + + ); + results = QueryDatabase(query); + query = StringFormat( + " ALTER TABLE `character_corpses` \n" + " CHANGE COLUMN `WasAtGraveyard` `was_at_graveyard` tinyint(3) NOT NULL DEFAULT 0 AFTER `is_buried` \n" + ); + results = QueryDatabase(query); + } + + std::string rquery = StringFormat("SHOW COLUMNS FROM `character_corpses` LIKE 'data'"); + results = QueryDatabase(rquery); + if (results.RowCount() != 0){ + rquery = StringFormat("SELECT DISTINCT charid FROM character_corpses"); + results = QueryDatabase(rquery); + for (auto row = results.begin(); row != results.end(); ++row) { + std::string squery = StringFormat("SELECT id, charname, data, time_of_death, is_rezzed FROM character_corpses WHERE `charid` = %i", atoi(row[0])); + auto results2 = QueryDatabase(squery); + for (auto row2 = results2.begin(); row2 != results2.end(); ++row2) { + in_datasize = results2.LengthOfColumn(2); + dbpc = (Convert::DBPlayerCorpse_Struct_temp*)row2[2]; + dbpc_c = (Convert::classic_db_temp::DBPlayerCorpse_Struct_temp*)row2[2]; + + if (dbpc == nullptr) + continue; + if (dbpc_c == nullptr) + continue; + + + /* SoF+ */ + uint32 esize1 = (sizeof(Convert::DBPlayerCorpse_Struct_temp) + (dbpc->itemcount * sizeof(Convert::player_lootitem_temp::ServerLootItem_Struct_temp))); + uint32 esize2 = (sizeof(Convert::classic_db_temp::DBPlayerCorpse_Struct_temp) + (dbpc_c->itemcount * sizeof(Convert::player_lootitem_temp::ServerLootItem_Struct_temp))); + + /* SoF */ + if (in_datasize == esize1) { + is_sof = true; + c_type = "SOF"; + } + /* Classic */ + if (in_datasize == esize2) { + is_sof = false; + c_type = "Legacy"; + } + if (in_datasize != esize2 && in_datasize != esize1) { + is_sof = false; + c_type = "NULL"; + continue; + } + std::cout << "Converting Corpse: [OK] [" << c_type << "]: " << "ID: " << atoi(row2[0]) << std::endl; + + if (is_sof){ + scquery = StringFormat("UPDATE `character_corpses` SET \n" + "`is_locked` = %d,\n" + "`exp` = %u,\n" + "`size` = %f,\n" + "`level` = %u,\n" + "`race` = %u,\n" + "`gender` = %u,\n" + "`class` = %u,\n" + "`deity` = %u,\n" + "`texture` = %u,\n" + "`helm_texture` = %u,\n" + "`copper` = %u,\n" + "`silver` = %u,\n" + "`gold` = %u,\n" + "`platinum` = %u,\n" + "`hair_color` = %u,\n" + "`beard_color` = %u,\n" + "`eye_color_1` = %u,\n" + "`eye_color_2` = %u,\n" + "`hair_style` = %u,\n" + "`face` = %u,\n" + "`beard` = %u,\n" + "`drakkin_heritage` = %u,\n" + "`drakkin_tattoo` = %u,\n" + "`drakkin_details` = %u,\n" + "`wc_1` = %u,\n" + "`wc_2` = %u,\n" + "`wc_3` = %u,\n" + "`wc_4` = %u,\n" + "`wc_5` = %u,\n" + "`wc_6` = %u,\n" + "`wc_7` = %u,\n" + "`wc_8` = %u,\n" + "`wc_9` = %u \n" + "WHERE `id` = %u \n", + dbpc->locked, + dbpc->exp, + dbpc->size, + dbpc->level, + dbpc->race, + dbpc->gender, + dbpc->class_, + dbpc->deity, + dbpc->texture, + dbpc->helmtexture, + dbpc->copper, + dbpc->silver, + dbpc->gold, + dbpc->plat, + dbpc->haircolor, + dbpc->beardcolor, + dbpc->eyecolor1, + dbpc->eyecolor2, + dbpc->hairstyle, + dbpc->face, + dbpc->beard, + dbpc->drakkin_heritage, + dbpc->drakkin_tattoo, + dbpc->drakkin_details, + dbpc->item_tint[0].color, + dbpc->item_tint[1].color, + dbpc->item_tint[2].color, + dbpc->item_tint[3].color, + dbpc->item_tint[4].color, + dbpc->item_tint[5].color, + dbpc->item_tint[6].color, + dbpc->item_tint[7].color, + dbpc->item_tint[8].color, + atoi(row2[0]) + ); + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + + first_entry = 0; + scquery = ""; + /* Print Items */ + for (unsigned int i = 0; i < dbpc->itemcount; i++) { + if (first_entry != 1){ + scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" + " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" + " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc->items[i].equipSlot, + dbpc->items[i].item_id, + dbpc->items[i].charges, + dbpc->items[i].aug1, + dbpc->items[i].aug2, + dbpc->items[i].aug3, + dbpc->items[i].aug4, + dbpc->items[i].aug5, + dbpc->items[i].aug6, + dbpc->items[i].attuned + ); + first_entry = 1; + } + else{ + scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc->items[i].equipSlot, + dbpc->items[i].item_id, + dbpc->items[i].charges, + dbpc->items[i].aug1, + dbpc->items[i].aug2, + dbpc->items[i].aug3, + dbpc->items[i].aug4, + dbpc->items[i].aug5, + dbpc->items[i].aug6, + dbpc->items[i].attuned + ); + } + } + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + } + else{ + /* Classic Converter */ + scquery = StringFormat("UPDATE `character_corpses` SET \n" + "`is_locked` = %d,\n" + "`exp` = %u,\n" + "`size` = %f,\n" + "`level` = %u,\n" + "`race` = %u,\n" + "`gender` = %u,\n" + "`class` = %u,\n" + "`deity` = %u,\n" + "`texture` = %u,\n" + "`helm_texture` = %u,\n" + "`copper` = %u,\n" + "`silver` = %u,\n" + "`gold` = %u,\n" + "`platinum` = %u,\n" + "`hair_color` = %u,\n" + "`beard_color` = %u,\n" + "`eye_color_1` = %u,\n" + "`eye_color_2` = %u,\n" + "`hair_style` = %u,\n" + "`face` = %u,\n" + "`beard` = %u,\n" + "`wc_1` = %u,\n" + "`wc_2` = %u,\n" + "`wc_3` = %u,\n" + "`wc_4` = %u,\n" + "`wc_5` = %u,\n" + "`wc_6` = %u,\n" + "`wc_7` = %u,\n" + "`wc_8` = %u,\n" + "`wc_9` = %u \n" + "WHERE `id` = %u \n", + dbpc_c->locked, + dbpc_c->exp, + dbpc_c->size, + dbpc_c->level, + dbpc_c->race, + dbpc_c->gender, + dbpc_c->class_, + dbpc_c->deity, + dbpc_c->texture, + dbpc_c->helmtexture, + dbpc_c->copper, + dbpc_c->silver, + dbpc_c->gold, + dbpc_c->plat, + dbpc_c->haircolor, + dbpc_c->beardcolor, + dbpc_c->eyecolor1, + dbpc_c->eyecolor2, + dbpc_c->hairstyle, + dbpc_c->face, + dbpc_c->beard, + dbpc_c->item_tint[0].color, + dbpc_c->item_tint[1].color, + dbpc_c->item_tint[2].color, + dbpc_c->item_tint[3].color, + dbpc_c->item_tint[4].color, + dbpc_c->item_tint[5].color, + dbpc_c->item_tint[6].color, + dbpc_c->item_tint[7].color, + dbpc_c->item_tint[8].color, + atoi(row2[0]) + ); + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + + first_entry = 0; + scquery = ""; + + /* Print Items */ + for (unsigned int i = 0; i < dbpc_c->itemcount; i++) { + if (first_entry != 1){ + scquery = StringFormat("REPLACE INTO `character_corpse_items` \n" + " (corpse_id, equip_slot, item_id, charges, aug_1, aug_2, aug_3, aug_4, aug_5, aug_6, attuned) \n" + " VALUES (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc_c->items[i].equipSlot, + dbpc_c->items[i].item_id, + dbpc_c->items[i].charges, + dbpc_c->items[i].aug1, + dbpc_c->items[i].aug2, + dbpc_c->items[i].aug3, + dbpc_c->items[i].aug4, + dbpc_c->items[i].aug5, + dbpc_c->items[i].aug6, + dbpc_c->items[i].attuned + ); + first_entry = 1; + } + else{ + scquery = scquery + StringFormat(", (%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u) \n", + atoi(row2[0]), + dbpc_c->items[i].equipSlot, + dbpc_c->items[i].item_id, + dbpc_c->items[i].charges, + dbpc_c->items[i].aug1, + dbpc_c->items[i].aug2, + dbpc_c->items[i].aug3, + dbpc_c->items[i].aug4, + dbpc_c->items[i].aug5, + dbpc_c->items[i].aug6, + dbpc_c->items[i].attuned + ); + } + } + if (scquery != ""){ auto sc_results = QueryDatabase(scquery); } + } + } + } + QueryDatabase(StringFormat("ALTER TABLE `character_corpses` DROP COLUMN `data`")); + } + return true; +} diff --git a/common/database_instances.cpp b/common/database_instances.cpp new file mode 100644 index 000000000..5350d71f9 --- /dev/null +++ b/common/database_instances.cpp @@ -0,0 +1,562 @@ +/* EQEMu: Everquest Server Emulator +Copyright (C) 2001-2015 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 +*/ + +#include "../common/global_define.h" +#include "../common/rulesys.h" +#include "../common/string_util.h" +#include "../common/timer.h" + +#include "database.h" + +#include +#include + +// Disgrace: for windows compile +#ifdef _WINDOWS +#include +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#else +#include "unix.h" +#include +#include +#endif + +bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) +{ + std::string query = StringFormat( + "REPLACE INTO `instance_list_player` (id, charid) " + "VALUES " + "(%lu, %lu)", + (unsigned long)instance_id, + (unsigned long)char_id + ); + auto results = QueryDatabase(query); + return results.Success(); +} + +bool Database::CharacterInInstanceGroup(uint16 instance_id, uint32 char_id) +{ + + std::string query = StringFormat("SELECT charid FROM instance_list_player where id=%u AND charid=%u", instance_id, char_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowCount() != 1) + return false; + + return true; +} + +bool Database::CheckInstanceExists(uint16 instance_id) { + std::string query = StringFormat( + "SELECT " + "`id` " + "FROM " + "`instance_list` " + "WHERE " + "`id` = %u", + instance_id + ); + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowCount() == 0) + return false; + + return true; +} + +bool Database::CheckInstanceExpired(uint16 instance_id) +{ + + int32 start_time = 0; + int32 duration = 0; + uint32 never_expires = 0; + + std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return true; + + if (results.RowCount() == 0) + return true; + + auto row = results.begin(); + + start_time = atoi(row[0]); + duration = atoi(row[1]); + never_expires = atoi(row[2]); + + if (never_expires == 1) + return false; + + timeval tv; + gettimeofday(&tv, nullptr); + + if ((start_time + duration) <= tv.tv_sec) + return true; + + return false; +} + +bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version, uint32 duration) +{ + std::string query = StringFormat("INSERT INTO instance_list (id, zone, version, start_time, duration)" + " values(%lu, %lu, %lu, UNIX_TIMESTAMP(), %lu)", + (unsigned long)instance_id, (unsigned long)zone_id, (unsigned long)version, (unsigned long)duration); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool Database::GetUnusedInstanceID(uint16 &instance_id) +{ + uint32 count = RuleI(Zone, ReservedInstances); + uint32 max = 65535; + + std::string query = StringFormat("SELECT IFNULL(MAX(id),%u)+1 FROM instance_list WHERE id > %u", count, count); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + instance_id = 0; + return false; + } + + if (results.RowCount() == 0) + { + instance_id = 0; + return false; + } + + auto row = results.begin(); + + if (atoi(row[0]) <= max) + { + instance_id = atoi(row[0]); + return true; + } + + query = StringFormat("SELECT id FROM instance_list where id > %u ORDER BY id", count); + results = QueryDatabase(query); + + if (!results.Success()) + { + instance_id = 0; + return false; + } + + if (results.RowCount() == 0) + { + instance_id = 0; + return false; + } + + count++; + for (auto row = results.begin(); row != results.end(); ++row) + { + if (count < atoi(row[0])) + { + instance_id = count; + return true; + } + + if (count > max) + { + instance_id = 0; + return false; + } + + count++; + } + + instance_id = count; + return true; +} + +bool Database::GlobalInstance(uint16 instance_id) +{ + std::string query = StringFormat( + "SELECT " + "is_global " + "FROM " + "instance_list " + "WHERE " + "id = %u " + "LIMIT 1 ", + instance_id + ); + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowCount() == 0) + return false; + + auto row = results.begin(); + + return (atoi(row[0]) == 1) ? true : false; +} + +bool Database::RemoveClientFromInstance(uint16 instance_id, uint32 char_id) +{ + std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu AND charid=%lu", + (unsigned long)instance_id, (unsigned long)char_id); + auto results = QueryDatabase(query); + + return results.Success(); +} + + +bool Database::RemoveClientsFromInstance(uint16 instance_id) +{ + std::string query = StringFormat("DELETE FROM instance_list_player WHERE id=%lu", (unsigned long)instance_id); + auto results = QueryDatabase(query); + + return results.Success(); +} + +bool Database::VerifyInstanceAlive(uint16 instance_id, uint32 char_id) +{ + //we are not saved to this instance so set our instance to 0 + if (!GlobalInstance(instance_id) && !CharacterInInstanceGroup(instance_id, char_id)) + return false; + + if (CheckInstanceExpired(instance_id)) + { + DeleteInstance(instance_id); + return false; + } + + return true; +} + +bool Database::VerifyZoneInstance(uint32 zone_id, uint16 instance_id) +{ + + std::string query = StringFormat("SELECT id FROM instance_list where id=%u AND zone=%u", instance_id, zone_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return false; + + if (results.RowCount() == 0) + return false; + + return true; +} + +uint16 Database::GetInstanceID(const char* zone, uint32 character_id, int16 version) { + + std::string query = StringFormat( + "SELECT " + "instance_list.id " + "FROM " + "instance_list, " + "instance_list_player " + "WHERE " + "instance_list.zone = %u " + "AND instance_list.version = %u " + "AND instance_list.id = instance_list_player.id " + "AND instance_list_player.charid = %u " + "LIMIT 1 ", + GetZoneID(zone), + version, + character_id + ); + auto results = QueryDatabase(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); +} + +uint16 Database::GetInstanceID(uint32 zone, uint32 character_id, int16 version) +{ + if (!zone) + return 0; + + std::string query = StringFormat( + "SELECT " + "instance_list.id " + "FROM " + "instance_list, " + "instance_list_player " + "WHERE " + "instance_list.zone = %u " + "AND instance_list.version = %u " + "AND instance_list.id = instance_list_player.id " + "AND instance_list_player.charid = %u " + "LIMIT 1; ", + zone, + version, + character_id + ); + auto results = QueryDatabase(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); +} + +uint16 Database::GetInstanceVersion(uint16 instance_id) { + if (instance_id == 0) + return 0; + + std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + return atoi(row[0]); +} + +uint32 Database::GetTimeRemainingInstance(uint16 instance_id, bool &is_perma) +{ + uint32 start_time = 0; + uint32 duration = 0; + uint32 never_expires = 0; + + std::string query = StringFormat("SELECT start_time, duration, never_expires FROM instance_list WHERE id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + { + is_perma = false; + return 0; + } + + if (results.RowCount() == 0) + { + is_perma = false; + return 0; + } + + auto row = results.begin(); + + start_time = atoi(row[0]); + duration = atoi(row[1]); + never_expires = atoi(row[2]); + + if (never_expires == 1) + { + is_perma = true; + return 0; + } + + is_perma = false; + + timeval tv; + gettimeofday(&tv, nullptr); + return ((start_time + duration) - tv.tv_sec); +} + +uint32 Database::VersionFromInstanceID(uint16 instance_id) +{ + + std::string query = StringFormat("SELECT version FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); +} + +uint32 Database::ZoneIDFromInstanceID(uint16 instance_id) +{ + + std::string query = StringFormat("SELECT zone FROM instance_list where id=%u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return 0; + + if (results.RowCount() == 0) + return 0; + + auto row = results.begin(); + + return atoi(row[0]); +} + +void Database::AssignGroupToInstance(uint32 group_id, uint32 instance_id) +{ + + uint32 zone_id = ZoneIDFromInstanceID(instance_id); + uint16 version = VersionFromInstanceID(instance_id); + + std::string query = StringFormat("SELECT `charid` FROM `group_id` WHERE `groupid` = %u", group_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + for (auto row = results.begin(); row != results.end(); ++row) + { + uint32 charid = atoi(row[0]); + if (GetInstanceID(zone_id, charid, version) == 0) + AddClientToInstance(instance_id, charid); + } +} + +void Database::AssignRaidToInstance(uint32 raid_id, uint32 instance_id) +{ + + uint32 zone_id = ZoneIDFromInstanceID(instance_id); + uint16 version = VersionFromInstanceID(instance_id); + + std::string query = StringFormat("SELECT `charid` FROM `raid_members` WHERE `raidid` = %u", raid_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + for (auto row = results.begin(); row != results.end(); ++row) + { + uint32 charid = atoi(row[0]); + if (GetInstanceID(zone_id, charid, version) == 0) + AddClientToInstance(instance_id, charid); + } +} + +void Database::BuryCorpsesInInstance(uint16 instance_id) { + std::string query = StringFormat( + "UPDATE `character_corpses` " + "SET `is_buried` = 1, " + "`instance_id` = 0 " + "WHERE " + "`instance_id` = %u ", + instance_id + ); + auto results = QueryDatabase(query); +} + +void Database::DeleteInstance(uint16 instance_id) +{ + + std::string query = StringFormat("DELETE FROM instance_list WHERE id=%u", instance_id); + QueryDatabase(query); + + query = StringFormat("DELETE FROM instance_list_player WHERE id=%u", instance_id); + QueryDatabase(query); + + query = StringFormat("DELETE FROM respawn_times WHERE instance_id=%u", instance_id); + QueryDatabase(query); + + query = StringFormat("DELETE FROM spawn_condition_values WHERE instance_id=%u", instance_id); + QueryDatabase(query); + + BuryCorpsesInInstance(instance_id); +} + +void Database::FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid) +{ + uint16 id = GetInstanceID(zone, charid, version); + if (id != 0) + return; + + char ln[128]; + memset(ln, 0, 128); + strcpy(ln, GetGroupLeadershipInfo(gid, ln)); + uint32 l_charid = GetCharacterID((const char*)ln); + uint16 l_id = GetInstanceID(zone, l_charid, version); + + if (l_id == 0) + return; + + AddClientToInstance(l_id, charid); +} + +void Database::FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid) +{ + uint16 id = GetInstanceID(zone, charid, version); + if (id != 0) + return; + + uint32 l_charid = GetCharacterID(GetRaidLeaderName(rid)); + uint16 l_id = GetInstanceID(zone, l_charid, version); + + if (l_id == 0) + return; + + AddClientToInstance(l_id, charid); +} + +void Database::GetCharactersInInstance(uint16 instance_id, std::list &charid_list) { + + std::string query = StringFormat("SELECT `charid` FROM `instance_list_player` WHERE `id` = %u", instance_id); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + for (auto row = results.begin(); row != results.end(); ++row) + charid_list.push_back(atoi(row[0])); +} + +void Database::PurgeExpiredInstances() +{ + std::string query("SELECT id FROM instance_list where (start_time+duration) <= UNIX_TIMESTAMP() and never_expires = 0"); + auto results = QueryDatabase(query); + + if (!results.Success()) + return; + + if (results.RowCount() == 0) + return; + + for (auto row = results.begin(); row != results.end(); ++row) + DeleteInstance(atoi(row[0])); +} + +void Database::SetInstanceDuration(uint16 instance_id, uint32 new_duration) +{ + std::string query = StringFormat("UPDATE `instance_list` SET start_time=UNIX_TIMESTAMP(), " + "duration=%u WHERE id=%u", new_duration, instance_id); + auto results = QueryDatabase(query); +} \ No newline at end of file diff --git a/common/dbcore.cpp b/common/dbcore.cpp index 21168efa0..d256f7b42 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -1,17 +1,17 @@ -#include "../common/debug.h" - #ifdef _WINDOWS #include #endif -#include -#include -#include -#include -#include "dbcore.h" -#include #include "../common/misc_functions.h" -#include +#include "../common/eqemu_logsys.h" + +#include "dbcore.h" + +#include +#include +#include +#include +#include #ifdef _WINDOWS #define snprintf _snprintf @@ -102,17 +102,18 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); - std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl; - return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer); } char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; snprintf(errorBuffer, 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 + /* Implement Logging at the Root */ + if (mysql_errno(&mysql) > 0 && strlen(query) > 0){ + if (Log.log_settings[Logs::MySQLError].is_category_enabled == 1) + Log.Out(Logs::General, Logs::MySQLError, "%i: %s \n %s", mysql_errno(&mysql), mysql_error(&mysql), query); + } + return MySQLRequestResult(nullptr, 0, 0, 0, 0, mysql_errno(&mysql),errorBuffer); } @@ -125,113 +126,23 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo rowCount = (uint32)mysql_num_rows(res); 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()) - { - std::cout << "query successful"; - if (requestResult.Result()) - std::cout << ", " << (int) mysql_num_rows(requestResult.Result()) << " rows returned"; - - std::cout << ", " << requestResult.RowCount() << " rows affected"; - std::cout<< std::endl; - } - else { - std::cout << "QUERY: query FAILED" << std::endl; - } -#endif + + if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1) + Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount()); 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) { diff --git a/common/dbcore.h b/common/dbcore.h index 56f326467..b23d58a9e 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -6,15 +6,12 @@ #include #endif +#include "../common/mutex.h" +#include "../common/mysql_request_result.h" +#include "../common/types.h" + #include #include -#include "../common/types.h" -#include "../common/mutex.h" -#include "../common/linked_list.h" -#include "../common/queue.h" -#include "../common/timer.h" -#include "../common/condition.h" -#include "../common/mysql_request_result.h" class DBcore { public: @@ -23,9 +20,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; } diff --git a/common/dbmemshare.cpp b/common/dbmemshare.cpp deleted file mode 100644 index 8447f6d0d..000000000 --- a/common/dbmemshare.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// Doors -#ifdef SHAREMEM -int32 Database::GetDoorsCount(uint32* oMaxID) { - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - strcpy(query, "SELECT MAX(id), count(*) FROM doors"); - if (RunQuery(query, strlen(query), errbuf, &result)) { - safe_delete(query); - row = mysql_fetch_row(result); - if (row && row[1]) { - int32 ret = atoi(row[1]); - if (oMaxID) { - if (row[0]) - *oMaxID = atoi(row[0]); - else - *oMaxID = 0; - } - mysql_free_result(result); - return ret; - } - } - else { - cerr << "Error in GetDoorsCount query '" << query << "' " << errbuf << endl; - delete[] query; - return -1; - } - - return -1; -} - -extern "C" bool extDBLoadDoors(uint32 iDoorCount, uint32 iMaxDoorID) { return database.DBLoadDoors(iDoorCount, iMaxDoorID); } -const Door* Database::GetDoor(uint8 door_id, const char* zone_name) { - for(uint32 i=0; idoor_id == door_id && strcasecmp(door->zone_name, zone_name) == 0) - return door; - } - return 0; -} - -const Door* Database::GetDoorDBID(uint32 db_id) { - return EMuShareMemDLL.Doors.GetDoor(db_id); -} - -bool Database::LoadDoors() { - if (!EMuShareMemDLL.Load()) - return false; - int32 tmp_max_door_type = -1; - uint32 tmp = 0; - tmp_max_door_type = GetDoorsCount(&tmp); - if (tmp_max_door_type < 0) { - cout << "Error: Database::LoadDoors-ShareMem: GetDoorsCount() returned < 0" << endl; - return false; - } - max_door_type = tmp_max_door_type; - bool ret = EMuShareMemDLL.Doors.DLLLoadDoors(&extDBLoadDoors, sizeof(Door), max_door_type, tmp); - return ret; -} - -bool Database::DBLoadDoors(uint32 iDoorCount, uint32 iMaxDoorID) { - cout << "Loading Doors from database..." << endl; - char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - query = new char[256]; - strcpy(query, "SELECT MAX(id), Count(*) FROM doors"); - if (RunQuery(query, strlen(query), errbuf, &result)) - { - safe_delete(query); - row = mysql_fetch_row(result); - if (row && row[0]) { - if (atoi(row[0]) > iMaxDoorID) { - cout << "Error: Insufficient shared memory to load doors." << endl; - cout << "Max(id): " << atoi(row[0]) << ", iMaxDoorID: " << iMaxDoorID << endl; - cout << "Fix this by increasing the MMF_MAX_Door_ID define statement" << endl; - return false; - } - if (atoi(row[1]) != iDoorCount) { - cout << "Error: Insufficient shared memory to load doors." << endl; - cout << "Count(*): " << atoi(row[1]) << ", iDoorCount: " << iDoorCount << endl; - return false; - } - max_door_type = atoi(row[0]); - mysql_free_result(result); - Door tmpDoor; - MakeAnyLenString(&query, "SELECT id,doorid,zone,name,pos_x,pos_y,pos_z,heading,opentype,guild,lockpick,keyitem,triggerdoor,triggertype from doors");//WHERE zone='%s'", zone_name - if (RunQuery(query, strlen(query), errbuf, &result)) - { - safe_delete(query); - while((row = mysql_fetch_row(result))) { - memset(&tmpDoor, 0, sizeof(Door)); - tmpDoor.db_id = atoi(row[0]); - tmpDoor.door_id = atoi(row[1]); - strn0cpy(tmpDoor.zone_name,row[2],32); - strn0cpy(tmpDoor.door_name,row[3],32); - tmpDoor.pos_x = (float)atof(row[4]); - tmpDoor.pos_y = (float)atof(row[5]); - tmpDoor.pos_z = (float)atof(row[6]); - tmpDoor.heading = atoi(row[7]); - tmpDoor.opentype = atoi(row[8]); - tmpDoor.guild_id = atoi(row[9]); - tmpDoor.lockpick = atoi(row[10]); - tmpDoor.keyitem = atoi(row[11]); - tmpDoor.trigger_door = atoi(row[12]); - tmpDoor.trigger_type = atoi(row[13]); - EMuShareMemDLL.Doors.cbAddDoor(tmpDoor.db_id, &tmpDoor); - Sleep(0); - } - mysql_free_result(result); - } - else - { - cerr << "Error in DBLoadDoors query '" << query << "' " << errbuf << endl; - delete[] query; - return false; - } - } - } - return true; -} -#endif - diff --git a/common/debug.cpp b/common/debug.cpp deleted file mode 100644 index 228d57631..000000000 --- a/common/debug.cpp +++ /dev/null @@ -1,441 +0,0 @@ -#include -#include -#include -#include - -#ifdef _WINDOWS - #include - - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #define strncasecmp _strnicmp - #define strcasecmp _stricmp - -#else - - #include - #include - -#endif - -#include "debug.h" -#include "string_util.h" -#include "misc_functions.h" -#include "platform.h" - -#ifndef va_copy - #define va_copy(d,s) ((d) = (s)) -#endif - -static volatile bool logFileValid = false; -static EQEMuLog realLogFile; -EQEMuLog *LogFile = &realLogFile; - -static const char* FileNames[EQEMuLog::MaxLogID] = { "logs/eqemu", "logs/eqemu", "logs/eqemu_error", "logs/eqemu_debug", "logs/eqemu_quest", "logs/eqemu_commands", "logs/crash" }; -static const char* LogNames[EQEMuLog::MaxLogID] = { "Status", "Normal", "Error", "Debug", "Quest", "Command", "Crash" }; - -EQEMuLog::EQEMuLog() { - for (int i=0; i= MaxLogID) { - return false; - } - LockMutex lock(&MOpen); - if (pLogStatus[id] & 4) { - return false; - } - if (fp[id]) { - //cerr<<"Warning: LogFile already open"<= MaxLogID) { - return false; - } - bool dofile = false; - if (pLogStatus[id] & 1) { - dofile = open(id); - } - if (!(dofile || pLogStatus[id] & 2)) - return false; - LockMutex lock(&MLog[id]); - if (!logFileValid) - return false; //check again for threading race reasons (to avoid two mutexes) - - time_t aclock; - struct tm *newtime; - - time( &aclock ); /* Get time in seconds */ - newtime = localtime( &aclock ); /* Convert time to struct */ - - if (dofile) -#ifndef NO_PIDLOG - fprintf(fp[id], "[%02d.%02d. - %02d:%02d:%02d] ", newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec); -#else - fprintf(fp[id], "%04i [%02d.%02d. - %02d:%02d:%02d] ", getpid(), newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec); -#endif - - va_list argptr, tmpargptr; - va_start(argptr, fmt); - if (dofile) { - va_copy(tmpargptr, argptr); - vfprintf( fp[id], fmt, tmpargptr ); - } - if(logCallbackFmt[id]) { - msgCallbackFmt p = logCallbackFmt[id]; - va_copy(tmpargptr, argptr); - p(id, fmt, tmpargptr ); - } - if (pLogStatus[id] & 2) { - if (pLogStatus[id] & 8) { - fprintf(stderr, "[%s] ", LogNames[id]); - vfprintf( stderr, fmt, argptr ); - } - else { - fprintf(stdout, "[%s] ", LogNames[id]); - vfprintf( stdout, fmt, argptr ); - } - } - va_end(argptr); - if (dofile) - fprintf(fp[id], "\n"); - if (pLogStatus[id] & 2) { - if (pLogStatus[id] & 8) { - fprintf(stderr, "\n"); - fflush(stderr); - } else { - fprintf(stdout, "\n"); - fflush(stdout); - } - } - if(dofile) - fflush(fp[id]); - return true; -} - -//write with Prefix and a VA_list -bool EQEMuLog::writePVA(LogIDs id, const char *prefix, const char *fmt, va_list argptr) { - if (!logFileValid) { - return false; - } - if (id >= MaxLogID) { - return false; - } - bool dofile = false; - if (pLogStatus[id] & 1) { - dofile = open(id); - } - if (!(dofile || pLogStatus[id] & 2)) { - return false; - } - LockMutex lock(&MLog[id]); - if (!logFileValid) - return false; //check again for threading race reasons (to avoid two mutexes) - - time_t aclock; - struct tm *newtime; - - time( &aclock ); /* Get time in seconds */ - newtime = localtime( &aclock ); /* Convert time to struct */ - - va_list tmpargptr; - - if (dofile) { -#ifndef NO_PIDLOG - fprintf(fp[id], "[%02d.%02d. - %02d:%02d:%02d] %s", newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec, prefix); -#else - fprintf(fp[id], "%04i [%02d.%02d. - %02d:%02d:%02d] %s", getpid(), newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec, prefix); -#endif - va_copy(tmpargptr, argptr); - vfprintf( fp[id], fmt, tmpargptr ); - } - if(logCallbackPva[id]) { - msgCallbackPva p = logCallbackPva[id]; - va_copy(tmpargptr, argptr); - p(id, prefix, fmt, tmpargptr ); - } - if (pLogStatus[id] & 2) { - if (pLogStatus[id] & 8) { - fprintf(stderr, "[%s] %s", LogNames[id], prefix); - vfprintf( stderr, fmt, argptr ); - } - else { - fprintf(stdout, "[%s] %s", LogNames[id], prefix); - vfprintf( stdout, fmt, argptr ); - } - } - va_end(argptr); - if (dofile) - fprintf(fp[id], "\n"); - if (pLogStatus[id] & 2) { - if (pLogStatus[id] & 8) - fprintf(stderr, "\n"); - else - fprintf(stdout, "\n"); - } - if(dofile) - fflush(fp[id]); - return true; -} - -bool EQEMuLog::writebuf(LogIDs id, const char *buf, uint8 size, uint32 count) { - if (!logFileValid) { - return false; - } - if (id >= MaxLogID) { - return false; - } - bool dofile = false; - if (pLogStatus[id] & 1) { - dofile = open(id); - } - if (!(dofile || pLogStatus[id] & 2)) - return false; - LockMutex lock(&MLog[id]); - if (!logFileValid) - return false; //check again for threading race reasons (to avoid two mutexes) - - time_t aclock; - struct tm *newtime; - - time( &aclock ); /* Get time in seconds */ - newtime = localtime( &aclock ); /* Convert time to struct */ - - if (dofile) -#ifndef NO_PIDLOG - fprintf(fp[id], "[%02d.%02d. - %02d:%02d:%02d] ", newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec); -#else - fprintf(fp[id], "%04i [%02d.%02d. - %02d:%02d:%02d] ", getpid(), newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec); -#endif - - if (dofile) { - fwrite(buf, size, count, fp[id]); - fprintf(fp[id], "\n"); - } - if(logCallbackBuf[id]) { - msgCallbackBuf p = logCallbackBuf[id]; - p(id, buf, size, count); - } - if (pLogStatus[id] & 2) { - if (pLogStatus[id] & 8) { - fprintf(stderr, "[%s] ", LogNames[id]); - fwrite(buf, size, count, stderr); - fprintf(stderr, "\n"); - } else { - fprintf(stdout, "[%s] ", LogNames[id]); - fwrite(buf, size, count, stdout); - fprintf(stdout, "\n"); - } - } - if(dofile) - fflush(fp[id]); - return true; -} - -bool EQEMuLog::writeNTS(LogIDs id, bool dofile, const char *fmt, ...) { - va_list argptr, tmpargptr; - va_start(argptr, fmt); - if (dofile) { - va_copy(tmpargptr, argptr); - vfprintf( fp[id], fmt, tmpargptr ); - } - if (pLogStatus[id] & 2) { - if (pLogStatus[id] & 8) - vfprintf( stderr, fmt, argptr ); - else - vfprintf( stdout, fmt, argptr ); - } - va_end(argptr); - return true; -}; - -bool EQEMuLog::Dump(LogIDs id, uint8* data, uint32 size, uint32 cols, uint32 skip) { - if (!logFileValid) { -#if EQDEBUG >= 10 - std::cerr << "Error: Dump() from null pointer" << std::endl; -#endif - return false; - } - if (size == 0) - return true; - if (!LogFile) - return false; - if (id >= MaxLogID) - return false; - bool dofile = false; - if (pLogStatus[id] & 1) { - dofile = open(id); - } - if (!(dofile || pLogStatus[id] & 2)) - return false; - LockMutex lock(&MLog[id]); - if (!logFileValid) - return false; //check again for threading race reasons (to avoid two mutexes) - - write(id, "Dumping Packet: %i", size); - // Output as HEX - - int beginningOfLineOffset = 0; - uint32 indexInData; - std::string asciiOutput; - - for(indexInData=skip; indexInData= 32 && data[indexInData] < 127) - { - // According to http://msdn.microsoft.com/en-us/library/vstudio/ee404875(v=vs.100).aspx - // Visual Studio 2010 doesn't have std::to_string(int) but it does have the long long - // version. - asciiOutput.append(std::to_string((long long)data[indexInData])); - } - else - { - asciiOutput.append("."); - } - } - uint32 k = ((indexInData-skip)-1)%cols; - if (k < 8) - writeNTS(id, dofile, " "); - for (uint32 h = k+1; h < cols; h++) { - writeNTS(id, dofile, " "); - } - writeNTS(id, dofile, " | %s\n", asciiOutput.c_str()); - if (dofile) - fflush(fp[id]); - return true; -} - -void EQEMuLog::SetCallback(LogIDs id, msgCallbackFmt proc) { - if (!logFileValid) - return; - if (id >= MaxLogID) { - return; - } - logCallbackFmt[id] = proc; -} - -void EQEMuLog::SetCallback(LogIDs id, msgCallbackBuf proc) { - if (!logFileValid) - return; - if (id >= MaxLogID) { - return; - } - logCallbackBuf[id] = proc; -} - -void EQEMuLog::SetCallback(LogIDs id, msgCallbackPva proc) { - if (!logFileValid) - return; - if (id >= MaxLogID) { - return; - } - logCallbackPva[id] = proc; -} - -void EQEMuLog::SetAllCallbacks(msgCallbackFmt proc) { - if (!logFileValid) - return; - int r; - for(r = Status; r < MaxLogID; r++) { - SetCallback((LogIDs)r, proc); - } -} - -void EQEMuLog::SetAllCallbacks(msgCallbackBuf proc) { - if (!logFileValid) - return; - int r; - for(r = Status; r < MaxLogID; r++) { - SetCallback((LogIDs)r, proc); - } -} - -void EQEMuLog::SetAllCallbacks(msgCallbackPva proc) { - if (!logFileValid) - return; - int r; - for(r = Status; r < MaxLogID; r++) { - SetCallback((LogIDs)r, proc); - } -} - diff --git a/common/debug.h b/common/debug.h deleted file mode 100644 index 5e2fff368..000000000 --- a/common/debug.h +++ /dev/null @@ -1,149 +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 -*/ - -// Debug Levels -#ifndef EQDEBUG -#define EQDEBUG 1 -#else -////// File/Console options -// 0 <= Quiet mode Errors to file Status and Normal ignored -// 1 >= Status and Normal to console, Errors to file -// 2 >= Status, Normal, and Error to console and logfile -// 3 >= Lite debug -// 4 >= Medium debug -// 5 >= Debug release (Anything higher is not recommended for regular use) -// 6 == (Reserved for special builds) Login opcode debug All packets dumped -// 7 == (Reserved for special builds) Chat Opcode debug All packets dumped -// 8 == (Reserved for special builds) World opcode debug All packets dumped -// 9 == (Reserved for special builds) Zone Opcode debug All packets dumped -// 10 >= More than you ever wanted to know -// -///// -// Add more below to reserve for file's functions ect. -///// -// Any setup code based on defines should go here -// -#endif - - -#if defined(_DEBUG) && defined(WIN32) - #ifndef _CRTDBG_MAP_ALLOC - #include - #include - #endif -#endif - -#ifndef EQDEBUG_H -#define EQDEBUG_H - -#ifndef _WINDOWS - #define DebugBreak() if(0) {} -#endif - -#define _WINSOCKAPI_ //stupid windows, trying to fix the winsock2 vs. winsock issues -#if defined(WIN32) && ( defined(PACKETCOLLECTOR) || defined(COLLECTOR) ) - // Packet Collector on win32 requires winsock.h due to latest pcap.h - // winsock.h must come before windows.h - #include -#endif - -#ifdef _WINDOWS - #include - #include -#endif - -#include "logsys.h" - -#include "../common/mutex.h" -#include -#include - - -class EQEMuLog { -public: - EQEMuLog(); - ~EQEMuLog(); - - enum LogIDs { - 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 - typedef void (* msgCallbackBuf)(LogIDs id, const char *buf, uint8 size, uint32 count); - typedef void (* msgCallbackFmt)(LogIDs id, const char *fmt, va_list ap); - typedef void (* msgCallbackPva)(LogIDs id, const char *prefix, const char *fmt, va_list ap); - - void SetAllCallbacks(msgCallbackFmt proc); - void SetAllCallbacks(msgCallbackBuf proc); - void SetAllCallbacks(msgCallbackPva proc); - void SetCallback(LogIDs id, msgCallbackFmt proc); - void SetCallback(LogIDs id, msgCallbackBuf proc); - void SetCallback(LogIDs id, msgCallbackPva proc); - - bool writebuf(LogIDs id, const char *buf, uint8 size, uint32 count); - bool write(LogIDs id, const char *fmt, ...); - bool writePVA(LogIDs id, const char *prefix, const char *fmt, va_list args); - bool Dump(LogIDs id, uint8* data, uint32 size, uint32 cols=16, uint32 skip=0); -private: - bool open(LogIDs id); - bool writeNTS(LogIDs id, bool dofile, const char *fmt, ...); // no error checking, assumes is open, no locking, no timestamp, no newline - - Mutex MOpen; - Mutex MLog[MaxLogID]; - FILE* fp[MaxLogID]; - -/* LogStatus: bitwise variable - 1 = output to file - 2 = output to stdout - 4 = fopen error, dont retry - 8 = use stderr instead (2 must be set) -*/ - uint8 pLogStatus[MaxLogID]; - - msgCallbackFmt logCallbackFmt[MaxLogID]; - msgCallbackBuf logCallbackBuf[MaxLogID]; - msgCallbackPva logCallbackPva[MaxLogID]; -}; - -extern EQEMuLog* LogFile; - -#ifdef _EQDEBUG -class PerformanceMonitor { -public: - PerformanceMonitor(int64* ip) { - p = ip; - QueryPerformanceCounter(&tmp); - } - ~PerformanceMonitor() { - LARGE_INTEGER tmp2; - QueryPerformanceCounter(&tmp2); - *p += tmp2.QuadPart - tmp.QuadPart; - } - LARGE_INTEGER tmp; - int64* p; -}; -#endif -#endif diff --git a/common/emu_opcodes.cpp b/common/emu_opcodes.cpp index 49da5e140..00f45fa25 100644 --- a/common/emu_opcodes.cpp +++ b/common/emu_opcodes.cpp @@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA */ -#include "debug.h" +#include "global_define.h" #include "emu_opcodes.h" const char *OpcodeNames[_maxEmuOpcode+1] = { diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 6ddd59123..62978655a 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -74,7 +74,9 @@ N(OP_CharacterCreateRequest), N(OP_CharInventory), N(OP_Charm), N(OP_ChatMessage), +N(OP_ClearAA), N(OP_ClearBlockedBuffs), +N(OP_ClearLeadershipAbilities), N(OP_ClearNPCMarks), N(OP_ClearObject), N(OP_ClearSurname), @@ -207,6 +209,7 @@ N(OP_GroupInvite2), N(OP_GroupLeaderChange), N(OP_GroupLeadershipAAUpdate), N(OP_GroupMakeLeader), +N(OP_GroupMentor), N(OP_GroupRoles), N(OP_GroupUpdate), N(OP_GroupUpdateB), @@ -244,6 +247,7 @@ N(OP_IncreaseStats), N(OP_InitialHPUpdate), N(OP_InitialMobHealth), N(OP_InspectAnswer), +N(OP_InspectBuffs), N(OP_InspectMessageUpdate), N(OP_InspectRequest), N(OP_InstillDoubt), diff --git a/common/emu_tcp_connection.cpp b/common/emu_tcp_connection.cpp index 41a39d3ab..da34f1ee7 100644 --- a/common/emu_tcp_connection.cpp +++ b/common/emu_tcp_connection.cpp @@ -23,17 +23,14 @@ crap into its own subclass of this object, it will clean things up tremendously. */ -#include "../common/debug.h" +#include "../common/global_define.h" #include #include -#include -#include #include "emu_tcp_connection.h" #include "emu_tcp_server.h" #include "../common/servertalk.h" -#include "../common/packet_dump.h" #ifdef FREEBSD //Timothy Whitman - January 7, 2003 #define MSG_NOSIGNAL 0 @@ -107,7 +104,7 @@ EmuTCPConnection::EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, EmuTCPConne RelayCount = 0; RemoteID = iRemoteID; pOldFormat = false; - ConnectionType = Incomming; + ConnectionType = Incoming; TCPMode = modePacket; PacketMode = packetModeZone; #if TCPN_DEBUG_Memory >= 7 @@ -717,7 +714,7 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) { SendNetErrorPacket("Switch to RelayServer mode by a Relay Client"); break; } - if (ConnectionType != Incomming) { + if (ConnectionType != Incoming) { SendNetErrorPacket("Switch to RelayServer mode on outgoing connection"); break; } @@ -738,7 +735,7 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) { SendNetErrorPacket("New RelayClient: wrong size, expected 11"); break; } - if (ConnectionType != Incomming) { + if (ConnectionType != Incoming) { SendNetErrorPacket("New RelayClient: illegal on outgoing connection"); break; } @@ -758,7 +755,7 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) { } EmuTCPConnection* con = Server->FindConnection(*((uint32*)data)); if (con) { - if (ConnectionType == Incomming) { + if (ConnectionType == Incoming) { if (con->GetRelayLink() != this) { SendNetErrorPacket("Delete RelayClient: RelayLink != this"); break; diff --git a/common/emu_tcp_connection.h b/common/emu_tcp_connection.h index c7d88965d..7f4d0710b 100644 --- a/common/emu_tcp_connection.h +++ b/common/emu_tcp_connection.h @@ -26,6 +26,7 @@ struct SPackSendQueue; class EmuTCPServer; +class ServerPacket; class EmuTCPConnection : public TCPConnection { public: diff --git a/common/emu_tcp_server.cpp b/common/emu_tcp_server.cpp index 985be6edd..4509c399f 100644 --- a/common/emu_tcp_server.cpp +++ b/common/emu_tcp_server.cpp @@ -1,4 +1,4 @@ -#include "debug.h" +#include "global_define.h" #include "emu_tcp_server.h" #include "emu_tcp_connection.h" diff --git a/common/eq_constants.h b/common/eq_constants.h index 1868d6c3e..14f695069 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -19,6 +19,7 @@ #define EQ_CONSTANTS_H #include "skills.h" +#include "types.h" /* ** Item attributes @@ -367,7 +368,7 @@ enum { #define AT_DamageState 44 // The damage state of a destructible object (0 through 4) //#define AT_Trader 300 // Bazzar Trader Mode -// solar: animations for AT_Anim +// animations for AT_Anim #define ANIM_FREEZE 102 #define ANIM_STAND 0x64 #define ANIM_SIT 0x6e @@ -968,4 +969,6 @@ namespace legacy { } InventorySlot; } +static const uint32 MAX_SPELL_DB_ID_VAL = 65535; + #endif diff --git a/common/eq_dictionary.cpp b/common/eq_dictionary.cpp index f85d3110f..ed3253260 100644 --- a/common/eq_dictionary.cpp +++ b/common/eq_dictionary.cpp @@ -25,8 +25,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // class EmuConstants // -uint16 EmuConstants::InventoryMapSize(int16 map) { - switch (map) { +uint16 EmuConstants::InventoryMapSize(int16 indexMap) { + switch (indexMap) { case MapPossessions: return MAP_POSSESSIONS_SIZE; case MapBank: @@ -91,8 +91,8 @@ std::string EmuConstants::InventoryLocationName(Location_Struct location) { } */ -std::string EmuConstants::InventoryMapName(int16 map) { - switch (map) { +std::string EmuConstants::InventoryMapName(int16 indexMap) { + switch (indexMap) { case INVALID_INDEX: return "Invalid Map"; case MapPossessions: @@ -150,8 +150,8 @@ std::string EmuConstants::InventoryMapName(int16 map) { } } -std::string EmuConstants::InventoryMainName(int16 main) { - switch (main) { +std::string EmuConstants::InventoryMainName(int16 indexMain) { + switch (indexMain) { case INVALID_INDEX: return "Invalid Main"; case MainCharm: @@ -229,293 +229,83 @@ std::string EmuConstants::InventoryMainName(int16 main) { } } -std::string EmuConstants::InventorySubName(int16 sub) { - if (sub == INVALID_INDEX) +std::string EmuConstants::InventorySubName(int16 indexSub) { + if (indexSub == INVALID_INDEX) return "Invalid Sub"; - if ((uint16)sub >= ITEM_CONTAINER_SIZE) + if ((uint16)indexSub >= ITEM_CONTAINER_SIZE) return "Unknown Sub"; std::string ret_str; - ret_str = StringFormat("Container %i", (sub + 1)); // zero-based index..but, count starts at one + ret_str = StringFormat("Container %i", (indexSub + 1)); // zero-based index..but, count starts at one return ret_str; } -std::string EmuConstants::InventoryAugName(int16 aug) { - if (aug == INVALID_INDEX) +std::string EmuConstants::InventoryAugName(int16 indexAug) { + if (indexAug == INVALID_INDEX) return "Invalid Aug"; - if ((uint16)aug >= ITEM_COMMON_SIZE) + if ((uint16)indexAug >= ITEM_COMMON_SIZE) return "Unknown Aug"; std::string ret_str; - ret_str = StringFormat("Augment %i", (aug + 1)); // zero-based index..but, count starts at one + ret_str = StringFormat("Augment %i", (indexAug + 1)); // zero-based index..but, count starts at one return ret_str; } -// legacy-related functions -// -// these should work for the first-stage coversions..but, once the new system is up and going..conversions will be incompatible -// without limiting server functions and other aspects, such as augment control, bag size, etc. A complete remapping will be -// required when bag sizes over 10 and direct manipulation of augments are implemented, due to the massive increase in range usage. -// -// (current personal/cursor bag range {251..340}, or 90 slots ... conversion translated range would be {10000..12804}, or 2805 slots... -// these would have to be hard-coded into all perl code to allow access to full range of the new system - actual limits would be -// less, based on bag size..but, the range must be full and consistent to avoid translation issues -- similar changes to other ranges -// (240 versus 6120 slots for bank bags, for example...)) -/* -int EmuConstants::ServerToPerlSlot(int server_slot) { // set r/s - switch (server_slot) { - case legacy::SLOT_CURSOR_END: - return legacy::SLOT_CURSOR_END; - case INVALID_INDEX: - return legacy::SLOT_INVALID; - case MainPowerSource: - return legacy::SLOT_POWER_SOURCE; - case MainAmmo: - return legacy::SLOT_AMMO; - case MainCursor: - return legacy::SLOT_CURSOR; - case legacy::SLOT_TRADESKILL: - return legacy::SLOT_TRADESKILL; - case legacy::SLOT_AUGMENT: - return legacy::SLOT_AUGMENT; - default: - int perl_slot = legacy::SLOT_INVALID; - - // activate the internal checks as needed - if (server_slot >= EmuConstants::EQUIPMENT_BEGIN && server_slot <= MainWaist) { - perl_slot = server_slot; - } - else if (server_slot >= EmuConstants::GENERAL_BEGIN && server_slot <= EmuConstants::GENERAL_END) { - perl_slot = server_slot;// + legacy::SLOT_PERSONAL_BEGIN - EmuConstants::GENERAL_BEGIN; - //if (perl_slot < legacy::SLOT_PERSONAL_BEGIN || perl_slot > legacy::SLOT_PERSONAL_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::GENERAL_BAGS_BEGIN && server_slot <= EmuConstants::GENERAL_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_PERSONAL_BAGS_BEGIN - EmuConstants::GENERAL_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_PERSONAL_BAGS_BEGIN || perl_slot > legacy::SLOT_PERSONAL_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::CURSOR_BAG_BEGIN && server_slot <= EmuConstants::CURSOR_BAG_END) { - perl_slot = server_slot;// + legacy::SLOT_CURSOR_BAG_BEGIN - EmuConstants::CURSOR_BAG_BEGIN; - //if (perl_slot < legacy::SLOT_CURSOR_BAG_BEGIN || perl_slot > legacy::SLOT_CURSOR_BAG_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::TRIBUTE_BEGIN && server_slot <= EmuConstants::TRIBUTE_END) { - perl_slot = server_slot;// + legacy::SLOT_TRIBUTE_BEGIN - EmuConstants::TRADE_BEGIN; - //if (perl_slot < legacy::SLOT_TRIBUTE_BEGIN || perl_slot > legacy::SLOT_TRIBUTE_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::BANK_BEGIN && server_slot <= EmuConstants::BANK_END) { - perl_slot = server_slot;// + legacy::SLOT_BANK_BEGIN - EmuConstants::BANK_BEGIN; - //if (perl_slot < legacy::SLOT_BANK_BEGIN || perl_slot > legacy::SLOT_BANK_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::BANK_BAGS_BEGIN && server_slot <= EmuConstants::BANK_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_BANK_BAGS_BEGIN - EmuConstants::BANK_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_BANK_BAGS_BEGIN || perl_slot > legacy::SLOT_BANK_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::SHARED_BANK_BEGIN && server_slot <= EmuConstants::SHARED_BANK_END) { - perl_slot = server_slot;// + legacy::SLOT_SHARED_BANK_BEGIN - EmuConstants::SHARED_BANK_BEGIN; - //if (perl_slot < legacy::SLOT_SHARED_BANK_BEGIN || perl_slot > legacy::SLOT_SHARED_BANK_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && server_slot <= EmuConstants::SHARED_BANK_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_SHARED_BANK_BAGS_BEGIN - EmuConstants::SHARED_BANK_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_SHARED_BANK_BAGS_BEGIN || perl_slot > legacy::SLOT_SHARED_BANK_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::TRADE_BEGIN && server_slot <= EmuConstants::TRADE_END) { - perl_slot = server_slot;// + legacy::SLOT_TRADE_BEGIN - EmuConstants::TRADE_BEGIN; - //if (perl_slot < legacy::SLOT_TRADE_BEGIN || perl_slot > legacy::SLOT_TRADE_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::TRADE_BAGS_BEGIN && server_slot <= EmuConstants::TRADE_BAGS_END) { - perl_slot = server_slot;// + legacy::SLOT_TRADE_BAGS_BEGIN - EmuConstants::TRADE_BAGS_BEGIN; - //if (perl_slot < legacy::SLOT_TRADE_BAGS_BEGIN || perl_slot > legacy::SLOT_TRADE_BAGS_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= EmuConstants::WORLD_BEGIN && server_slot <= EmuConstants::WORLD_END) { - perl_slot = server_slot;// + legacy::SLOT_WORLD_BEGIN - EmuConstants::WORLD_BEGIN; - //if (perl_slot < legacy::SLOT_WORLD_BEGIN || perl_slot > legacy::SLOT_WORLD_END) - // perl_slot = legacy::SLOT_INVALID; - } - else if (server_slot >= 8000 && server_slot <= 8999) { // this range may be limited to 36 in the future (client size) - perl_slot = server_slot; - } - - return perl_slot; - } -} -*/ -/* -int EmuConstants::PerlToServerSlot(int perl_slot) { // set r/s - switch (perl_slot) { - case legacy::SLOT_CURSOR_END: - return legacy::SLOT_CURSOR_END; - case legacy::SLOT_INVALID: - return INVALID_INDEX; - case legacy::SLOT_POWER_SOURCE: - return MainPowerSource; - case legacy::SLOT_AMMO: - return MainAmmo; - case legacy::SLOT_CURSOR: - return MainCursor; - case legacy::SLOT_TRADESKILL: - return legacy::SLOT_TRADESKILL; - case legacy::SLOT_AUGMENT: - return legacy::SLOT_AUGMENT; - default: - int server_slot = INVALID_INDEX; - - // activate the internal checks as needed - if (perl_slot >= legacy::SLOT_EQUIPMENT_BEGIN && perl_slot <= legacy::SLOT_WAIST) { - server_slot = perl_slot; - } - else if (perl_slot >= legacy::SLOT_PERSONAL_BEGIN && perl_slot <= legacy::SLOT_PERSONAL_END) { - server_slot = perl_slot;// + EmuConstants::GENERAL_BEGIN - legacy::SLOT_PERSONAL_BEGIN; - //if (server_slot < EmuConstants::GENERAL_BEGIN || server_slot > EmuConstants::GENERAL_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_PERSONAL_BAGS_BEGIN && perl_slot <= legacy::SLOT_PERSONAL_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::GENERAL_BAGS_BEGIN - legacy::SLOT_PERSONAL_BAGS_BEGIN; - //if (server_slot < EmuConstants::GENERAL_BAGS_BEGIN || server_slot > EmuConstants::GENERAL_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_CURSOR_BAG_BEGIN && perl_slot <= legacy::SLOT_CURSOR_BAG_END) { - server_slot = perl_slot;// + EmuConstants::CURSOR_BAG_BEGIN - legacy::SLOT_CURSOR_BAG_BEGIN; - //if (server_slot < EmuConstants::CURSOR_BAG_BEGIN || server_slot > EmuConstants::CURSOR_BAG_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_TRIBUTE_BEGIN && perl_slot <= legacy::SLOT_TRIBUTE_END) { - server_slot = perl_slot;// + EmuConstants::TRIBUTE_BEGIN - legacy::SLOT_TRIBUTE_BEGIN; - //if (server_slot < EmuConstants::TRIBUTE_BEGIN || server_slot > EmuConstants::TRIBUTE_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_BANK_BEGIN && perl_slot <= legacy::SLOT_BANK_END) { - server_slot = perl_slot;// + EmuConstants::BANK_BEGIN - legacy::SLOT_BANK_BEGIN; - //if (server_slot < EmuConstants::BANK_BEGIN || server_slot > EmuConstants::BANK_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_BANK_BAGS_BEGIN && perl_slot <= legacy::SLOT_BANK_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::BANK_BAGS_BEGIN - legacy::SLOT_BANK_BAGS_BEGIN; - //if (server_slot < EmuConstants::BANK_BAGS_BEGIN || server_slot > EmuConstants::BANK_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_SHARED_BANK_BEGIN && perl_slot <= legacy::SLOT_SHARED_BANK_END) { - server_slot = perl_slot;// + EmuConstants::SHARED_BANK_BEGIN - legacy::SLOT_SHARED_BANK_BEGIN; - //if (server_slot < EmuConstants::SHARED_BANK_BEGIN || server_slot > EmuConstants::SHARED_BANK_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_SHARED_BANK_BAGS_BEGIN && perl_slot <= legacy::SLOT_SHARED_BANK_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::SHARED_BANK_BAGS_BEGIN - legacy::SLOT_SHARED_BANK_BAGS_END; - //if (server_slot < EmuConstants::SHARED_BANK_BAGS_BEGIN || server_slot > EmuConstants::SHARED_BANK_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_TRADE_BEGIN && perl_slot <= legacy::SLOT_TRADE_END) { - server_slot = perl_slot;// + EmuConstants::TRADE_BEGIN - legacy::SLOT_TRADE_BEGIN; - //if (server_slot < EmuConstants::TRADE_BEGIN || server_slot > EmuConstants::TRADE_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_TRADE_BAGS_BEGIN && perl_slot <= legacy::SLOT_TRADE_BAGS_END) { - server_slot = perl_slot;// + EmuConstants::TRADE_BAGS_BEGIN - legacy::SLOT_TRADE_BAGS_BEGIN; - //if (server_slot < EmuConstants::TRADE_BAGS_BEGIN || server_slot > EmuConstants::TRADE_BAGS_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= legacy::SLOT_WORLD_BEGIN && perl_slot <= legacy::SLOT_WORLD_END) { - server_slot = perl_slot;// + EmuConstants::WORLD_BEGIN - legacy::SLOT_WORLD_BEGIN; - //if (server_slot < EmuConstants::WORLD_BEGIN || server_slot > EmuConstants::WORLD_END) - // server_slot = INVALID_INDEX; - } - else if (perl_slot >= 8000 && perl_slot <= 8999) { // this range may be limited to 36 in the future (client size) - server_slot = perl_slot; - } - - return server_slot; - } -} -*/ // // class EQLimits // // client validation -bool EQLimits::IsValidClientVersion(uint32 version) { - if (version < _EQClientCount) +bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion) { + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) return true; return false; } -uint32 EQLimits::ValidateClientVersion(uint32 version) { - if (version < _EQClientCount) - return version; +ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) { + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT) + return clientVersion; - return EQClientUnknown; -} - -EQClientVersion EQLimits::ValidateClientVersion(EQClientVersion version) { - if (version >= EQClientUnknown) - if (version < _EQClientCount) - return version; - - return EQClientUnknown; + return ClientVersion::Unknown; } // npc validation -bool EQLimits::IsValidNPCVersion(uint32 version) { - if (version >= _EQClientCount) - if (version < _EmuClientCount) - return true; - - return false; -} - -uint32 EQLimits::ValidateNPCVersion(uint32 version) { - if (version >= _EQClientCount) - if (version < _EmuClientCount) - return version; - - return EQClientUnknown; -} - -EQClientVersion EQLimits::ValidateNPCVersion(EQClientVersion version) { - if (version >= _EQClientCount) - if (version < _EmuClientCount) - return version; - - return EQClientUnknown; -} - -// mob validation -bool EQLimits::IsValidMobVersion(uint32 version) { - if (version < _EmuClientCount) +bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion) { + if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) return true; return false; } -uint32 EQLimits::ValidateMobVersion(uint32 version) { - if (version < _EmuClientCount) - return version; +ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) { + if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT) + return clientVersion; - return EQClientUnknown; + return ClientVersion::Unknown; } -EQClientVersion EQLimits::ValidateMobVersion(EQClientVersion version) { - if (version >= EQClientUnknown) - if (version < _EmuClientCount) - return version; +// mob validation +bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion) { + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) + return true; - return EQClientUnknown; + return false; +} + +ClientVersion EQLimits::ValidateMobClientVersion(ClientVersion clientVersion) { + if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT) + return clientVersion; + + return ClientVersion::Unknown; } // inventory -uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { +uint16 EQLimits::InventoryMapSize(int16 indexMap, ClientVersion clientVersion) { // not all maps will have an instantiated container..some are references for queue generators (i.e., bazaar, mail, etc...) // a zero '0' indicates a needed value..otherwise, change to '_NOTUSED' for a null value so indices requiring research can be identified // ALL of these values need to be verified before pushing to live @@ -527,7 +317,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { // // when setting NPC-based values, try to adhere to an EmuConstants:: or NOT_USED value to avoid unnecessary issues - static const uint16 local[_MapCount][_EmuClientCount] = { + static const uint16 local[_MapCount][CLIENT_VERSION_COUNT] = { // server and database are sync'd to current MapPossessions's client as set in 'using namespace RoF::slots;' and // 'EmuConstants::MAP_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask() // for partial range validation checks and 'EmuConstants::MAP_POSSESSIONS_SIZE' for full range iterations @@ -539,7 +329,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE, @@ -548,13 +338,13 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { }, { // local[MapBank] /*Unknown*/ NOT_USED, -/*62*/ Client62::consts::MAP_BANK_SIZE, +/*62*/ NOT_USED, /*Titanium*/ Titanium::consts::MAP_BANK_SIZE, /*SoF*/ EmuConstants::MAP_BANK_SIZE, /*SoD*/ EmuConstants::MAP_BANK_SIZE, /*Underfoot*/ EmuConstants::MAP_BANK_SIZE, /*RoF*/ EmuConstants::MAP_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -569,7 +359,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -584,7 +374,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_TRADE_SIZE, /*Underfoot*/ EmuConstants::MAP_TRADE_SIZE, /*RoF*/ EmuConstants::MAP_TRADE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_TRADE_SIZE, /*NPC*/ 4, /*Merc*/ 4, @@ -599,7 +389,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_WORLD_SIZE, /*Underfoot*/ EmuConstants::MAP_WORLD_SIZE, /*RoF*/ EmuConstants::MAP_WORLD_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_WORLD_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -614,7 +404,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_LIMBO_SIZE, /*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE, /*RoF*/ EmuConstants::MAP_LIMBO_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_LIMBO_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -629,7 +419,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE, /*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE, /*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -644,7 +434,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -659,7 +449,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -674,7 +464,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_MERCHANT_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_MERCHANT_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -689,7 +479,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_DELETED_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_DELETED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -698,13 +488,13 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { }, { // local[MapCorpse] /*Unknown*/ NOT_USED, -/*62*/ Client62::consts::MAP_CORPSE_SIZE, +/*62*/ NOT_USED, /*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE, /*SoF*/ SoF::consts::MAP_CORPSE_SIZE, /*SoD*/ SoD::consts::MAP_CORPSE_SIZE, -/*Underfoot*/ Underfoot::consts::MAP_CORPSE_SIZE, +/*Underfoot*/ UF::consts::MAP_CORPSE_SIZE, /*RoF*/ RoF::consts::MAP_CORPSE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ RoF2::consts::MAP_CORPSE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -719,7 +509,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ EmuConstants::MAP_BAZAAR_SIZE, /*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE, /*RoF*/ EmuConstants::MAP_BAZAAR_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_BAZAAR_SIZE, /*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc /*Merc*/ 0, @@ -728,13 +518,13 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { }, { // local[MapInspect] /*Unknown*/ NOT_USED, -/*62*/ Client62::consts::MAP_INSPECT_SIZE, +/*62*/ NOT_USED, /*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE, /*SoF*/ SoF::consts::MAP_INSPECT_SIZE, /*SoD*/ SoD::consts::MAP_INSPECT_SIZE, -/*Underfoot*/ Underfoot::consts::MAP_INSPECT_SIZE, +/*Underfoot*/ UF::consts::MAP_INSPECT_SIZE, /*RoF*/ RoF::consts::MAP_INSPECT_SIZE, -/*RoF2*/ 0, +/*RoF2*/ RoF2::consts::MAP_INSPECT_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -749,7 +539,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_REAL_ESTATE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -764,7 +554,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -779,7 +569,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -794,7 +584,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -809,7 +599,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -824,7 +614,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_ALT_STORAGE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -839,7 +629,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_ARCHIVED_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -854,7 +644,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_MAIL_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_MAIL_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -869,7 +659,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -884,7 +674,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ NOT_USED, /*Underfoot*/ NOT_USED, /*RoF*/ EmuConstants::MAP_KRONO_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_KRONO_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -899,7 +689,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { /*SoD*/ 0, /*Underfoot*/ 0, /*RoF*/ EmuConstants::MAP_OTHER_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::MAP_OTHER_SIZE, /*NPC*/ 0, /*Merc*/ 0, @@ -908,19 +698,19 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) { } }; - if ((uint16)map < _MapCount) - return local[map][ValidateMobVersion(version)]; + if ((uint16)indexMap < _MapCount) + return local[indexMap][static_cast(ValidateMobClientVersion(clientVersion))]; return NOT_USED; } -uint64 EQLimits::PossessionsBitmask(uint32 version) { +uint64 EQLimits::PossessionsBitmask(ClientVersion clientVersion) { // these are for the new inventory system (RoF)..not the current (Ti) one... // 0x0000000000200000 is SlotPowerSource (SoF+) // 0x0000000080000000 is SlotGeneral9 (RoF+) // 0x0000000100000000 is SlotGeneral10 (RoF+) - static const uint64 local[_EmuClientCount] = { + static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ 0x000000027FDFFFFF, /*Titanium*/ 0x000000027FDFFFFF, @@ -937,11 +727,11 @@ uint64 EQLimits::PossessionsBitmask(uint32 version) { }; return NOT_USED; - //return local[ValidateMobVersion(version)]; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQLimits::EquipmentBitmask(uint32 version) { - static const uint64 local[_EmuClientCount] = { +uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) { + static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ 0x00000000005FFFFF, /*Titanium*/ 0x00000000005FFFFF, @@ -958,11 +748,11 @@ uint64 EQLimits::EquipmentBitmask(uint32 version) { }; return NOT_USED; - //return local[ValidateMobVersion(version)]; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQLimits::GeneralBitmask(uint32 version) { - static const uint64 local[_EmuClientCount] = { +uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) { + static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ 0x000000007F800000, /*Titanium*/ 0x000000007F800000, @@ -979,11 +769,11 @@ uint64 EQLimits::GeneralBitmask(uint32 version) { }; return NOT_USED; - //return local[ValidateMobVersion(version)]; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint64 EQLimits::CursorBitmask(uint32 version) { - static const uint64 local[_EmuClientCount] = { +uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) { + static const uint64 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ 0x0000000200000000, /*Titanium*/ 0x0000000200000000, @@ -1000,19 +790,19 @@ uint64 EQLimits::CursorBitmask(uint32 version) { }; return NOT_USED; - //return local[ValidateMobVersion(version)]; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQLimits::AllowsEmptyBagInBag(uint32 version) { - static const bool local[_EmuClientCount] = { +bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) { + static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ false, -/*62*/ Client62::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*62*/ false, /*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*Underfoot*/ Underfoot::limits::ALLOWS_EMPTY_BAG_IN_BAG, +/*Underfoot*/ UF::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, -/*RoF2*/ false, +/*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*NPC*/ false, /*Merc*/ false, @@ -1021,19 +811,19 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) { }; return false; // not implemented - //return local[ValidateMobVersion(version)]; + //return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQLimits::AllowsClickCastFromBag(uint32 version) { - static const bool local[_EmuClientCount] = { +bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) { + static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ false, -/*62*/ Client62::limits::ALLOWS_CLICK_CAST_FROM_BAG, +/*62*/ false, /*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, +/*Underfoot*/ UF::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, -/*RoF2*/ false, +/*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*NPC*/ false, /*Merc*/ false, @@ -1041,12 +831,12 @@ bool EQLimits::AllowsClickCastFromBag(uint32 version) { /*Pet*/ false }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } // items -uint16 EQLimits::ItemCommonSize(uint32 version) { - static const uint16 local[_EmuClientCount] = { +uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) { + static const uint16 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ EmuConstants::ITEM_COMMON_SIZE, /*Titanium*/ EmuConstants::ITEM_COMMON_SIZE, @@ -1054,7 +844,7 @@ uint16 EQLimits::ItemCommonSize(uint32 version) { /*SoD*/ EmuConstants::ITEM_COMMON_SIZE, /*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, /*RoF*/ EmuConstants::ITEM_COMMON_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::ITEM_COMMON_SIZE, /*NPC*/ EmuConstants::ITEM_COMMON_SIZE, /*Merc*/ EmuConstants::ITEM_COMMON_SIZE, @@ -1062,11 +852,11 @@ uint16 EQLimits::ItemCommonSize(uint32 version) { /*Pet*/ EmuConstants::ITEM_COMMON_SIZE }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint16 EQLimits::ItemContainerSize(uint32 version) { - static const uint16 local[_EmuClientCount] = { +uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) { + static const uint16 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Titanium*/ EmuConstants::ITEM_CONTAINER_SIZE, @@ -1074,7 +864,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) { /*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, /*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::ITEM_CONTAINER_SIZE, /*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, @@ -1082,19 +872,19 @@ uint16 EQLimits::ItemContainerSize(uint32 version) { /*Pet*/ EmuConstants::ITEM_CONTAINER_SIZE }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -bool EQLimits::CoinHasWeight(uint32 version) { - static const bool local[_EmuClientCount] = { +bool EQLimits::CoinHasWeight(ClientVersion clientVersion) { + static const bool local[CLIENT_VERSION_COUNT] = { /*Unknown*/ true, -/*62*/ Client62::limits::COIN_HAS_WEIGHT, +/*62*/ true, /*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, /*SoF*/ SoF::limits::COIN_HAS_WEIGHT, /*SoD*/ SoD::limits::COIN_HAS_WEIGHT, -/*Underfoot*/ Underfoot::limits::COIN_HAS_WEIGHT, +/*Underfoot*/ UF::limits::COIN_HAS_WEIGHT, /*RoF*/ RoF::limits::COIN_HAS_WEIGHT, -/*RoF2*/ true, +/*RoF2*/ RoF::limits::COIN_HAS_WEIGHT, /*NPC*/ true, /*Merc*/ true, @@ -1102,11 +892,11 @@ bool EQLimits::CoinHasWeight(uint32 version) { /*Pet*/ true }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint32 EQLimits::BandoliersCount(uint32 version) { - static const uint32 local[_EmuClientCount] = { +uint32 EQLimits::BandoliersCount(ClientVersion clientVersion) { + static const uint32 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ EmuConstants::BANDOLIERS_COUNT, /*Titanium*/ EmuConstants::BANDOLIERS_COUNT, @@ -1114,7 +904,7 @@ uint32 EQLimits::BandoliersCount(uint32 version) { /*SoD*/ EmuConstants::BANDOLIERS_COUNT, /*Underfoot*/ EmuConstants::BANDOLIERS_COUNT, /*RoF*/ EmuConstants::BANDOLIERS_COUNT, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::BANDOLIERS_COUNT, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -1122,11 +912,11 @@ uint32 EQLimits::BandoliersCount(uint32 version) { /*Pet*/ NOT_USED }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint32 EQLimits::BandolierSize(uint32 version) { - static const uint32 local[_EmuClientCount] = { +uint32 EQLimits::BandolierSize(ClientVersion clientVersion) { + static const uint32 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ EmuConstants::BANDOLIER_SIZE, /*Titanium*/ EmuConstants::BANDOLIER_SIZE, @@ -1134,7 +924,7 @@ uint32 EQLimits::BandolierSize(uint32 version) { /*SoD*/ EmuConstants::BANDOLIER_SIZE, /*Underfoot*/ EmuConstants::BANDOLIER_SIZE, /*RoF*/ EmuConstants::BANDOLIER_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::BANDOLIER_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -1142,11 +932,11 @@ uint32 EQLimits::BandolierSize(uint32 version) { /*Pet*/ NOT_USED }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } -uint32 EQLimits::PotionBeltSize(uint32 version) { - static const uint32 local[_EmuClientCount] = { +uint32 EQLimits::PotionBeltSize(ClientVersion clientVersion) { + static const uint32 local[CLIENT_VERSION_COUNT] = { /*Unknown*/ NOT_USED, /*62*/ EmuConstants::POTION_BELT_SIZE, /*Titanium*/ EmuConstants::POTION_BELT_SIZE, @@ -1154,7 +944,7 @@ uint32 EQLimits::PotionBeltSize(uint32 version) { /*SoD*/ EmuConstants::POTION_BELT_SIZE, /*Underfoot*/ EmuConstants::POTION_BELT_SIZE, /*RoF*/ EmuConstants::POTION_BELT_SIZE, -/*RoF2*/ 0, +/*RoF2*/ EmuConstants::POTION_BELT_SIZE, /*NPC*/ NOT_USED, /*Merc*/ NOT_USED, @@ -1162,5 +952,5 @@ uint32 EQLimits::PotionBeltSize(uint32 version) { /*Pet*/ NOT_USED }; - return local[ValidateMobVersion(version)]; + return local[static_cast(ValidateMobClientVersion(clientVersion))]; } diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h index c08809a12..d1337856e 100644 --- a/common/eq_dictionary.h +++ b/common/eq_dictionary.h @@ -26,13 +26,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "eq_constants.h" #include "clientversions.h" #include -#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/uf_constants.h" #include "../common/patches/rof_constants.h" -//#include "../common/patches/rof2_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!! *** @@ -47,15 +46,15 @@ class EmuConstants { // an immutable value is required to initialize arrays, etc... use this class as a repository for those public: // database - static const EQClientVersion CHARACTER_CREATION_CLIENT = EQClientRoF; // adjust according to starting item placement and target client + static const ClientVersion CHARACTER_CREATION_CLIENT = ClientVersion::RoF2; // adjust according to starting item placement and target client // inventory - static uint16 InventoryMapSize(int16 map); + static uint16 InventoryMapSize(int16 indexMap); //static std::string InventoryLocationName(Location_Struct location); - static std::string InventoryMapName(int16 map); - static std::string InventoryMainName(int16 main); - static std::string InventorySubName(int16 sub); - static std::string InventoryAugName(int16 aug); + static std::string InventoryMapName(int16 indexMap); + static std::string InventoryMainName(int16 indexMain); + static std::string InventorySubName(int16 indexSub); + static std::string InventoryAugName(int16 indexAug); // these are currently hard-coded for existing inventory system..do not use in place of special client version handlers until ready static const uint16 MAP_POSSESSIONS_SIZE = _MainCount; @@ -138,8 +137,8 @@ public: // items // common and container sizes will not increase until the new 'location' struct is implemented - static const uint16 ITEM_COMMON_SIZE = Underfoot::consts::ITEM_COMMON_SIZE; - static const uint16 ITEM_CONTAINER_SIZE = Underfoot::consts::ITEM_CONTAINER_SIZE; + static const uint16 ITEM_COMMON_SIZE = RoF::consts::ITEM_COMMON_SIZE; + static const uint16 ITEM_CONTAINER_SIZE = Titanium::consts::ITEM_CONTAINER_SIZE; // player profile //static const uint32 CLASS_BITMASK = 0; // needs value @@ -150,6 +149,8 @@ public: static const uint32 BANDOLIER_SIZE = Titanium::consts::BANDOLIER_SIZE; // size = number of equipment slots in bandolier instance static const uint32 POTION_BELT_SIZE = Titanium::consts::POTION_BELT_SIZE; + static const size_t TEXT_LINK_BODY_LENGTH = 56; + // legacy-related functions //static int ServerToPerlSlot(int slot); // encode //static int PerlToServerSlot(int slot); // decode @@ -162,44 +163,41 @@ class EQLimits { public: // client version validation (checks to avoid crashing zone server when accessing reference arrays) // use this inside of class Client (limits to actual clients) - static bool IsValidClientVersion(uint32 version); - static uint32 ValidateClientVersion(uint32 version); - static EQClientVersion ValidateClientVersion(EQClientVersion version); + static bool IsValidPCClientVersion(ClientVersion clientVersion); + static ClientVersion ValidatePCClientVersion(ClientVersion clientVersion); // basically..any non-client classes - do not when setting a valid client - static bool IsValidNPCVersion(uint32 version); - static uint32 ValidateNPCVersion(uint32 version); - static EQClientVersion ValidateNPCVersion(EQClientVersion version); + static bool IsValidNPCClientVersion(ClientVersion clientVersion); + static ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion); // these are 'universal' - do not when setting a valid client - static bool IsValidMobVersion(uint32 version); - static uint32 ValidateMobVersion(uint32 version); - static EQClientVersion ValidateMobVersion(EQClientVersion version); + static bool IsValidMobClientVersion(ClientVersion clientVersion); + static ClientVersion ValidateMobClientVersion(ClientVersion clientVersion); // inventory - static uint16 InventoryMapSize(int16 map, uint32 version); - static uint64 PossessionsBitmask(uint32 version); - static uint64 EquipmentBitmask(uint32 version); - static uint64 GeneralBitmask(uint32 version); - static uint64 CursorBitmask(uint32 version); + static uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion); + static uint64 PossessionsBitmask(ClientVersion clientVersion); + static uint64 EquipmentBitmask(ClientVersion clientVersion); + static uint64 GeneralBitmask(ClientVersion clientVersion); + static uint64 CursorBitmask(ClientVersion clientVersion); - static bool AllowsEmptyBagInBag(uint32 version); - static bool AllowsClickCastFromBag(uint32 version); + static bool AllowsEmptyBagInBag(ClientVersion clientVersion); + static bool AllowsClickCastFromBag(ClientVersion clientVersion); // items - static uint16 ItemCommonSize(uint32 version); - static uint16 ItemContainerSize(uint32 version); + static uint16 ItemCommonSize(ClientVersion clientVersion); + static uint16 ItemContainerSize(ClientVersion clientVersion); // player profile - static bool CoinHasWeight(uint32 version); + static bool CoinHasWeight(ClientVersion clientVersion); - static uint32 BandoliersCount(uint32 version); - static uint32 BandolierSize(uint32 version); + static uint32 BandoliersCount(ClientVersion clientVersion); + static uint32 BandolierSize(ClientVersion clientVersion); - static uint32 PotionBeltSize(uint32 version); + static uint32 PotionBeltSize(ClientVersion clientVersion); }; -#endif /* EQ_LIMITS_H */ +#endif /* EQ_DICTIONARY_H */ /* Working Notes: diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index 3ea622040..e01f6a3f8 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -15,18 +15,22 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" -#include -#include -#include + +#include "crc16.h" +#include "global_define.h" #include "eq_packet.h" #include "misc.h" #include "op_codes.h" -#include "crc16.h" #include "platform.h" +#include +#include +#include +#include + #ifndef STATIC_OPCODE #include "opcodemgr.h" #endif + #include "packet_dump.h" #include "packet_functions.h" #include @@ -507,3 +511,8 @@ void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) { // DumpPacketAscii(app->pBuffer, app->size); } +std::string DumpPacketToString(const EQApplicationPacket* app){ + std::ostringstream out; + out << DumpPacketHexToString(app->pBuffer, app->size); + return out.str(); +} \ No newline at end of file diff --git a/common/eq_packet.h b/common/eq_packet.h index 04418f733..ed90d132a 100644 --- a/common/eq_packet.h +++ b/common/eq_packet.h @@ -19,9 +19,8 @@ #define _EQPACKET_H #include "base_packet.h" -#include "eq_stream_type.h" -#include "op_codes.h" #include "platform.h" +#include #ifdef STATIC_OPCODE typedef unsigned short EmuOpcode; @@ -30,9 +29,6 @@ #include "emu_opcodes.h" #endif -class EQStream; -class EQStreamPair; - class EQPacket : public BasePacket { friend class EQStream; public: @@ -151,6 +147,6 @@ protected: }; extern void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false); - +extern std::string DumpPacketToString(const EQApplicationPacket* app); #endif diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 2e4b29261..62f6072b3 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -145,6 +145,28 @@ struct Color_Struct }; }; +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct EquipStruct { + /*00*/ uint32 material; + /*04*/ uint32 unknown1; + /*08*/ uint32 elitematerial; + /*12*/ uint32 heroforgemodel; + /*16*/ uint32 material2; // Same as material? + /*20*/ +}; + +struct CharSelectEquip { + uint32 material; + uint32 unknown1; + uint32 elitematerial; + uint32 heroforgemodel; + uint32 material2; + Color_Struct color; +}; + /* ** Character Selection Struct ** Length: 1704 Bytes @@ -152,10 +174,11 @@ struct Color_Struct */ struct CharacterSelect_Struct { /*0000*/ uint32 race[10]; // Characters Race -/*0040*/ Color_Struct cs_colors[10][9]; // Characters Equipment Colors +/*0040*/ //Color_Struct cs_colors[10][9]; // Characters Equipment Colors /*0400*/ uint8 beardcolor[10]; // Characters beard Color /*0410*/ uint8 hairstyle[10]; // Characters hair style -/*0420*/ uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be) +/*0420*/ //uint32 equip[10][9]; // 0=helm, 1=chest, 2=arm, 3=bracer, 4=hand, 5=leg, 6=boot, 7=melee1, 8=melee2 (Might not be) +/*0000*/ CharSelectEquip equip[10][9]; /*0780*/ uint32 secondary[10]; // Characters secondary IDFile number /*0820*/ uint32 drakkin_heritage[10]; // added for SoF /*0860*/ uint32 drakkin_tattoo[10]; // added for SoF @@ -258,26 +281,26 @@ struct Spawn_Struct { /*0193*/ uint8 guildrank; // 0=normal, 1=officer, 2=leader /*0194*/ uint8 unknown0194[3]; /*0197*/ union - { - struct - { - /*0197*/ uint32 equip_helmet; // Equipment: Helmet Visual - /*0201*/ uint32 equip_chest; // Equipment: Chest Visual - /*0205*/ uint32 equip_arms; // Equipment: Arms Visual - /*0209*/ uint32 equip_bracers; // Equipment: Bracers Visual - /*0213*/ uint32 equip_hands; // Equipment: Hands Visual - /*0217*/ uint32 equip_legs; // Equipment: Legs Visual - /*0221*/ uint32 equip_feet; // Equipment: Feet Visual - /*0225*/ uint32 equip_primary; // Equipment: Primary Visual - /*0229*/ uint32 equip_secondary; // Equipment: Secondary Visual - } equip; - /*0197*/ uint32 equipment[_MaterialCount]; // Array elements correspond to struct equipment above - }; +{ + struct + { + /*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual + /*0000*/ EquipStruct equip_chest; // Equipment: Chest visual + /*0000*/ EquipStruct equip_arms; // Equipment: Arms visual + /*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual + /*0000*/ EquipStruct equip_hands; // Equipment: Hands visual + /*0000*/ EquipStruct equip_legs; // Equipment: Legs visual + /*0000*/ EquipStruct equip_feet; // Equipment: Boots visual + /*0000*/ EquipStruct equip_primary; // Equipment: Main visual + /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual + } equip; + /*0000*/ EquipStruct equipment[_MaterialCount]; +}; /*0233*/ float runspeed; // Speed when running /*0036*/ uint8 afk; // 0=no, 1=afk /*0238*/ uint32 guildID; // Current guild /*0242*/ char title[32]; // Title -/*0274*/ uint8 unknown0274; +/*0274*/ uint8 unknown0274; // non-zero prefixes name with '!' /*0275*/ uint8 set_to_0xFF[8]; // ***Placeholder (all ff) /*0283*/ uint8 helm; // Helm texture /*0284*/ uint32 race; // Spawn race @@ -340,6 +363,7 @@ union uint32 DestructibleUnk7; uint8 DestructibleUnk8; uint32 DestructibleUnk9; + bool targetable_with_hotkey; }; @@ -478,7 +502,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 @@ -512,7 +540,7 @@ struct SpawnAppearance_Struct }; -// solar: this is used inside profile +// this is used inside profile struct SpellBuff_Struct { /*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise @@ -534,7 +562,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 +625,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 +717,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 +787,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 +855,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*/ }; @@ -806,7 +883,7 @@ static const uint32 MAX_PP_MEMSPELL = 9; // Set to latest client so functions ca 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 = _SkillPacketArraySize; // 100 - actual skills buffer size +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; @@ -1191,7 +1268,7 @@ struct Animation_Struct { /*04*/ }; -// solar: this is what causes the caster to animate and the target to +// this is what causes the caster to animate and the target to // get the particle effects around them when a spell is cast // also causes a buff icon struct Action_Struct @@ -1215,7 +1292,7 @@ struct Action_Struct /* 31 */ }; -// solar: this is what prints the You have been struck. and the regular +// this is what prints the You have been struck. and the regular // melee messages like You try to pierce, etc. It's basically the melee // and spell damage message struct CombatDamage_Struct @@ -1303,19 +1380,19 @@ struct PlayerPositionUpdateServer_Struct struct PlayerPositionUpdateClient_Struct { /*0000*/ uint16 spawn_id; -/*0022*/ uint16 sequence; //increments one each packet +/*0002*/ uint16 sequence; //increments one each packet /*0004*/ float y_pos; // y coord /*0008*/ float delta_z; // Change in z -/*0016*/ float delta_x; // Change in x -/*0012*/ float delta_y; // Change in y +/*0012*/ float delta_x; // Change in x +/*0016*/ float delta_y; // Change in y /*0020*/ int32 animation:10, // animation delta_heading:10, // change in heading padding0020:12; // ***Placeholder (mostly 1) /*0024*/ float x_pos; // x coord /*0028*/ float z_pos; // z coord -/*0034*/ uint16 heading:12, // Directional heading +/*0032*/ uint16 heading:12, // Directional heading padding0004:4; // ***Placeholder -/*0032*/ uint8 unknown0006[2]; // ***Placeholder +/*0034*/ uint8 unknown0006[2]; // ***Placeholder /*0036*/ }; @@ -1432,7 +1509,8 @@ enum ItemPacketType ItemPacketTributeItem = 0x6C, ItemPacketMerchant = 0x64, ItemPacketWorldContainer = 0x6B, - ItemPacketCharmUpdate = 0x6E + ItemPacketCharmUpdate = 0x6E, + ItemPacketInvalid = 0xFF }; struct ItemPacket_Struct { @@ -1449,17 +1527,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 @@ -1467,16 +1546,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*/ }; // @@ -1730,7 +1811,7 @@ struct RandomReq_Struct { uint32 high; }; -/* solar: 9/23/03 reply to /random command; struct from Zaphod */ +/* 9/23/03 reply to /random command */ struct RandomReply_Struct { /* 00 */ uint32 low; /* 04 */ uint32 high; @@ -2180,6 +2261,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; @@ -2301,7 +2388,7 @@ struct AugmentItem_Struct { // OP_Emote struct Emote_Struct { -/*0000*/ uint32 unknown01; +/*0000*/ uint32 type; // 0 - custom, 0xffffffff - command (/dance, /flip, etc...) /*0004*/ char message[1024]; /*1028*/ }; @@ -2602,6 +2689,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; @@ -2822,7 +2920,7 @@ uint8 npccastfilters; // 0) No, 1) Ignore NPC Casts (all), 2) Ignore NPC Casts */ struct ItemViewRequest_Struct { /*000*/ uint32 item_id; -/*004*/ uint32 augments[5]; +/*004*/ uint32 augments[6]; /*024*/ uint32 link_hash; /*028*/ uint32 unknown028; /*032*/ char unknown032[12]; //probably includes loregroup & evolving info. see Client::MakeItemLink() in zone/inventory.cpp:469 @@ -2918,14 +3016,14 @@ struct ClientError_Struct }; struct Track_Struct { - uint16 entityid; - uint16 padding002; + uint32 entityid; float distance; // Fields for SoD and later uint8 level; - uint8 NPC; - uint8 GroupMember; + uint8 is_npc; char name[64]; + uint8 is_pet; + uint8 is_merc; }; struct Tracking_Struct { @@ -3400,7 +3498,7 @@ struct Split_Struct */ struct NewCombine_Struct { /*00*/ int16 container_slot; -/*02*/ char unknown02[2]; +/*02*/ int16 guildtribute_slot; /*04*/ }; @@ -3911,6 +4009,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 @@ -3926,6 +4029,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 @@ -4304,14 +4420,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*/ }; @@ -4599,11 +4715,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]; }; @@ -5116,17 +5234,19 @@ 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; + uint32 aug_6; // uint32 aug_5; + uint8 attuned; + uint8 min_level; + uint8 max_level; }; //Found in client near a ref to the string: @@ -5149,6 +5269,23 @@ struct ClientMarqueeMessage_Struct { typedef std::list ItemList; +struct TextLinkBody_Struct { + // Current server mask: EQClientRoF2 + uint8 unknown_1; /* %1X */ + uint32 item_id; /* %05X */ + uint32 augment_1; /* %05X */ + uint32 augment_2; /* %05X */ + uint32 augment_3; /* %05X */ + uint32 augment_4; /* %05X */ + uint32 augment_5; /* %05X */ + uint32 augment_6; /* %05X */ + uint8 is_evolving; /* %1X */ + uint32 evolve_group; /* %05X */ + uint8 evolve_level; /* %02X */ + uint32 ornament_icon; /* %05X */ + int hash; /* %08X */ +}; + // Restore structure packing to default #pragma pack() diff --git a/common/eq_stream.cpp b/common/eq_stream.cpp index 7b69decc2..be1ae50d4 100644 --- a/common/eq_stream.cpp +++ b/common/eq_stream.cpp @@ -16,18 +16,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" +#include "global_define.h" +#include "eqemu_logsys.h" #include "eq_packet.h" #include "eq_stream.h" -#include "misc.h" -#include "mutex.h" #include "op_codes.h" #include "crc16.h" #include "platform.h" +#include "string_util.h" #include #include -#include #include #include @@ -50,7 +49,13 @@ uint16 EQStream::MaxWindowSize=2048; -void EQStream::init() { +void EQStream::init(bool resetSession) { + // we only reset these statistics if it is a 'new' connection + if ( resetSession ) + { + streamactive = false; + sessionAttempts = 0; + } active_users = 0; Session=0; Key=0; @@ -77,19 +82,19 @@ void EQStream::init() { OpMgr = nullptr; if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "init Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "init Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "init Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } } EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) { EQRawApplicationPacket *ap=nullptr; - _log(NET__APP_CREATE, _L "Creating new application packet, length %d" __L, p->size); - _raw(NET__APP_CREATE_HEX, 0xFFFF, p); + Log.Out(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, p->size); + // _raw(NET__APP_CREATE_HEX, 0xFFFF, p); ap = p->MakeAppPacket(); return ap; } @@ -97,8 +102,7 @@ EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p) EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len) { EQRawApplicationPacket *ap=nullptr; - _log(NET__APP_CREATE, _L "Creating new application packet, length %d" __L, len); - _hex(NET__APP_CREATE_HEX, buf, len); + Log.Out(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, len); ap = new EQRawApplicationPacket(buf, len); return ap; } @@ -128,8 +132,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) } if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { - _log(NET__DEBUG, _L "Session not initialized, packet ignored" __L); - _raw(NET__DEBUG, 0xFFFF, p); + Log.Out(Logs::Detail, Logs::Netcode, _L "Session not initialized, packet ignored" __L); + // _raw(NET__DEBUG, 0xFFFF, p); return; } @@ -139,8 +143,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) while(processed < p->size) { subpacket_length=*(p->pBuffer+processed); EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length); - _log(NET__NET_CREATE, _L "Extracting combined packet of length %d" __L, subpacket_length); - _raw(NET__NET_CREATE_HEX, 0xFFFF, subp); + Log.Out(Logs::Detail, Logs::Netcode, _L "Extracting combined packet of length %d" __L, subpacket_length); + // _raw(NET__NET_CREATE_HEX, 0xFFFF, subp); subp->copyInfo(p); ProcessPacket(subp); delete subp; @@ -154,12 +158,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) while(processedsize) { EQRawApplicationPacket *ap=nullptr; if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) { - _log(NET__NET_CREATE, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length); + Log.Out(Logs::Detail, Logs::Netcode, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length); ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length); processed+=subpacket_length+1; } else { subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1)); - _log(NET__NET_CREATE, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length); + Log.Out(Logs::Detail, Logs::Netcode, _L "Extracting combined app packet of length %d, short len" __L, subpacket_length); ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length); processed+=subpacket_length+3; } @@ -174,29 +178,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_Packet: { if(!p->pBuffer || (p->Size() < 4)) { - _log(NET__ERROR, _L "Received OP_Packet that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_Packet that was of malformed size" __L); break; } uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); SeqOrder check=CompareSequence(NextInSeq,seq); if (check == SeqFuture) { - _log(NET__DEBUG, _L "Future OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); - _raw(NET__DEBUG, seq, p); + Log.Out(Logs::Detail, Logs::Netcode, _L "Future OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); + // _raw(NET__DEBUG, seq, p); PacketQueue[seq]=p->Copy(); - _log(NET__APP_TRACE, _L "OP_Packet Queue size=%d" __L, PacketQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size()); //SendOutOfOrderAck(seq); } else if (check == SeqPast) { - _log(NET__DEBUG, _L "Duplicate OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); - _raw(NET__DEBUG, seq, p); + Log.Out(Logs::Detail, Logs::Netcode, _L "Duplicate OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); + // _raw(NET__DEBUG, seq, p); SendOutOfOrderAck(seq); //we already got this packet but it was out of order } else { // In case we did queue one before as well. EQProtocolPacket *qp=RemoveQueue(seq); if (qp) { - _log(NET__NET_TRACE, "OP_Packet: Removing older queued packet with sequence %d", seq); + Log.Out(Logs::General, Logs::Netcode, "[NET_TRACE] OP_Packet: Removing older queued packet with sequence %d", seq); delete qp; } @@ -205,8 +209,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) // Check for an embedded OP_AppCombinded (protocol level 0x19) if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2); - _log(NET__NET_CREATE, _L "seq %d, Extracting combined packet of length %d" __L, seq, subp->size); - _raw(NET__NET_CREATE_HEX, seq, subp); + Log.Out(Logs::Detail, Logs::Netcode, _L "seq %d, Extracting combined packet of length %d" __L, seq, subp->size); + // _raw(NET__NET_CREATE_HEX, seq, subp); subp->copyInfo(p); ProcessPacket(subp); delete subp; @@ -224,29 +228,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_Fragment: { if(!p->pBuffer || (p->Size() < 4)) { - _log(NET__ERROR, _L "Received OP_Fragment that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_Fragment that was of malformed size" __L); break; } uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); SeqOrder check=CompareSequence(NextInSeq,seq); if (check == SeqFuture) { - _log(NET__DEBUG, _L "Future OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); - _raw(NET__DEBUG, seq, p); + Log.Out(Logs::Detail, Logs::Netcode, _L "Future OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); + // _raw(NET__DEBUG, seq, p); PacketQueue[seq]=p->Copy(); - _log(NET__APP_TRACE, _L "OP_Fragment Queue size=%d" __L, PacketQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_Fragment Queue size=%d" __L, PacketQueue.size()); //SendOutOfOrderAck(seq); } else if (check == SeqPast) { - _log(NET__DEBUG, _L "Duplicate OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); - _raw(NET__DEBUG, seq, p); + Log.Out(Logs::Detail, Logs::Netcode, _L "Duplicate OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); + // _raw(NET__DEBUG, seq, p); SendOutOfOrderAck(seq); } else { // In case we did queue one before as well. EQProtocolPacket *qp=RemoveQueue(seq); if (qp) { - _log(NET__NET_TRACE, "OP_Fragment: Removing older queued packet with sequence %d", seq); + Log.Out(Logs::General, Logs::Netcode, "[NET_TRACE] OP_Fragment: Removing older queued packet with sequence %d", seq); delete qp; } SetNextAckToSend(seq); @@ -254,18 +258,18 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) if (oversize_buffer) { memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2); oversize_offset+=p->size-2; - _log(NET__NET_TRACE, _L "Fragment of oversized of length %d, seq %d: now at %d/%d" __L, p->size-2, seq, oversize_offset, oversize_length); + Log.Out(Logs::Detail, Logs::Netcode, _L "Fragment of oversized of length %d, seq %d: now at %d/%d" __L, p->size-2, seq, oversize_offset, oversize_length); if (oversize_offset==oversize_length) { if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset); - _log(NET__NET_CREATE, _L "seq %d, Extracting combined oversize packet of length %d" __L, seq, subp->size); - //_raw(NET__NET_CREATE_HEX, subp); + Log.Out(Logs::Detail, Logs::Netcode, _L "seq %d, Extracting combined oversize packet of length %d" __L, seq, subp->size); + //// _raw(NET__NET_CREATE_HEX, subp); subp->copyInfo(p); ProcessPacket(subp); delete subp; } else { EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset); - _log(NET__NET_CREATE, _L "seq %d, completed combined oversize packet of length %d" __L, seq, ap->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "seq %d, completed combined oversize packet of length %d" __L, seq, ap->size); if (ap) { ap->copyInfo(p); InboundQueuePush(ap); @@ -280,7 +284,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) oversize_buffer=new unsigned char[oversize_length]; memcpy(oversize_buffer,p->pBuffer+6,p->size-6); oversize_offset=p->size-6; - _log(NET__NET_TRACE, _L "First fragment of oversized of seq %d: now at %d/%d" __L, seq, oversize_offset, oversize_length); + Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment of oversized of seq %d: now at %d/%d" __L, seq, oversize_offset, oversize_length); } } } @@ -288,14 +292,14 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_KeepAlive: { #ifndef COLLECTOR NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size)); - _log(NET__NET_TRACE, _L "Received and queued reply to keep alive" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received and queued reply to keep alive" __L); #endif } break; case OP_Ack: { if(!p->pBuffer || (p->Size() < 4)) { - _log(NET__ERROR, _L "Received OP_Ack that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_Ack that was of malformed size" __L); break; } #ifndef COLLECTOR @@ -311,28 +315,31 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_SessionRequest: { if(p->Size() < sizeof(SessionRequest)) { - _log(NET__ERROR, _L "Received OP_SessionRequest that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest that was of malformed size" __L); break; } #ifndef COLLECTOR if (GetState()==ESTABLISHED) { - _log(NET__ERROR, _L "Received OP_SessionRequest in ESTABLISHED state (%d)" __L, GetState()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest in ESTABLISHED state (%d) streamactive (%i) attempt (%i)" __L, GetState(),streamactive,sessionAttempts); - /*RemoveData(); - init(); - State=UNESTABLISHED;*/ - _SendDisconnect(); - SetState(CLOSED); - break; + // client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case + // streamactive means we identified the opcode for the stream, we cannot re-establish this connection + if ( streamactive || ( sessionAttempts > MAX_SESSION_RETRIES ) ) + { + _SendDisconnect(); + SetState(CLOSED); + break; + } } #endif - //std::cout << "Got OP_SessionRequest" << std::endl; - init(); + sessionAttempts++; + // we set established below, so statistics will not be reset for session attempts/stream active. + init(GetState()!=ESTABLISHED); OutboundQueueClear(); SessionRequest *Request=(SessionRequest *)p->pBuffer; Session=ntohl(Request->Session); SetMaxLen(ntohl(Request->MaxLength)); - _log(NET__NET_TRACE, _L "Received OP_SessionRequest: session %lu, maxlen %d" __L, (unsigned long)Session, MaxLen); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionRequest: session %lu, maxlen %d" __L, (unsigned long)Session, MaxLen); SetState(ESTABLISHED); #ifndef COLLECTOR Key=0x11223344; @@ -343,7 +350,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_SessionResponse: { if(p->Size() < sizeof(SessionResponse)) { - _log(NET__ERROR, _L "Received OP_SessionResponse that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionResponse that was of malformed size" __L); break; } @@ -359,7 +366,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) compressed=(Response->Format&FLAG_COMPRESSED); encoded=(Response->Format&FLAG_ENCODED); - _log(NET__NET_TRACE, _L "Received OP_SessionResponse: session %lu, maxlen %d, key %lu, compressed? %s, encoded? %s" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no"); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionResponse: session %lu, maxlen %d, key %lu, compressed? %s, encoded? %s" __L, (unsigned long)Session, MaxLen, (unsigned long)Key, compressed?"yes":"no", encoded?"yes":"no"); // Kinda kludgy, but trie for now if (StreamType==UnknownStream) { @@ -382,17 +389,17 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) EQStreamState state = GetState(); if(state == ESTABLISHED) { //client initiated disconnect? - _log(NET__NET_TRACE, _L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received unsolicited OP_SessionDisconnect. Treating like a client-initiated disconnect." __L); _SendDisconnect(); SetState(CLOSED); } else if(state == CLOSING) { //we were waiting for this anyways, ignore pending messages, send the reply and be closed. - _log(NET__NET_TRACE, _L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionDisconnect when we have a pending close, they beat us to it. Were happy though." __L); _SendDisconnect(); SetState(CLOSED); } else { //we are expecting this (or have already gotten it, but dont care either way) - _log(NET__NET_TRACE, _L "Received expected OP_SessionDisconnect. Moving to closed state." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received expected OP_SessionDisconnect. Moving to closed state." __L); SetState(CLOSED); } } @@ -400,7 +407,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_OutOfOrderAck: { if(!p->pBuffer || (p->Size() < 4)) { - _log(NET__ERROR, _L "Received OP_OutOfOrderAck that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck that was of malformed size" __L); break; } #ifndef COLLECTOR @@ -408,15 +415,15 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) MOutboundQueue.lock(); if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Pre-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } //if the packet they got out of order is between our last acked packet and the last sent packet, then its valid. if (CompareSequence(SequencedBase,seq) != SeqPast && CompareSequence(NextOutSeq,seq) == SeqPast) { - _log(NET__NET_TRACE, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for sequence %d, starting retransmit at the start of our unacked buffer (seq %d, was %d)." __L, seq, SequencedBase, SequencedBase+NextSequencedSend); bool retransmit_acked_packets = false; @@ -427,7 +434,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) if(!retransmit_acked_packets) { uint16 sqsize = SequencedQueue.size(); uint16 index = seq - SequencedBase; - _log(NET__NET_TRACE, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize); + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_OutOfOrderAck marking packet acked in queue (queue index = %d, queue size = %d)." __L, index, sqsize); if (index < sqsize) { std::deque::iterator sitr; sitr = SequencedQueue.begin(); @@ -442,15 +449,15 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) NextSequencedSend = 0; } else { - _log(NET__NET_TRACE, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfOrderAck for out-of-window %d. Window (%d->%d)." __L, seq, SequencedBase, NextOutSeq); } if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Post-OOA Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Post-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Post-OOA Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } MOutboundQueue.unlock(); #endif @@ -459,12 +466,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) case OP_SessionStatRequest: { if(p->Size() < sizeof(SessionStats)) { - _log(NET__ERROR, _L "Received OP_SessionStatRequest that was of malformed size" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatRequest that was of malformed size" __L); break; } #ifndef COLLECTOR SessionStats *Stats=(SessionStats *)p->pBuffer; - _log(NET__NET_TRACE, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L, + Log.Out(Logs::Detail, Logs::Netcode, _L "Received Stats: %lu packets received, %lu packets sent, Deltas: local %lu, (%lu <- %lu -> %lu) remote %lu" __L, (unsigned long)ntohl(Stats->packets_received), (unsigned long)ntohl(Stats->packets_sent), (unsigned long)ntohl(Stats->last_local_delta), (unsigned long)ntohl(Stats->low_delta), (unsigned long)ntohl(Stats->average_delta), (unsigned long)ntohl(Stats->high_delta), (unsigned long)ntohl(Stats->last_remote_delta)); @@ -485,18 +492,18 @@ void EQStream::ProcessPacket(EQProtocolPacket *p) } if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX) retransmittimeout = RETRANSMIT_TIMEOUT_MAX; - _log(NET__NET_TRACE, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout); + Log.Out(Logs::Detail, Logs::Netcode, _L "Retransmit timeout recalculated to %dms" __L, retransmittimeout); } } #endif } break; case OP_SessionStatResponse: { - _log(NET__NET_TRACE, _L "Received OP_SessionStatResponse. Ignoring." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_SessionStatResponse. Ignoring." __L); } break; case OP_OutOfSession: { - _log(NET__NET_TRACE, _L "Received OP_OutOfSession. Ignoring." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received OP_OutOfSession. Ignoring." __L); } break; default: @@ -527,7 +534,7 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req) return; if(OpMgr == nullptr || *OpMgr == nullptr) { - _log(NET__DEBUG, _L "Packet enqueued into a stream with no opcode manager, dropping." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Packet enqueued into a stream with no opcode manager, dropping." __L); delete pack; return; } @@ -549,12 +556,24 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req) void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) { - uint32 chunksize,used; + uint32 chunksize, used; uint32 length; + if (Log.log_settings[Logs::Server_Client_Packet].is_category_enabled == 1){ + if (p->GetOpcode() != OP_SpecialMesg){ + Log.Out(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size()); + } + } + + if (Log.log_settings[Logs::Server_Client_Packet_With_Dump].is_category_enabled == 1){ + if (p->GetOpcode() != OP_SpecialMesg){ + Log.Out(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str()); + } + } + // Convert the EQApplicationPacket to 1 or more EQProtocolPackets if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) - _log(NET__FRAGMENT, _L "Making oversized packet, len %d" __L, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Making oversized packet, len %d" __L, p->size); unsigned char *tmpbuff=new unsigned char[p->size+3]; length=p->serialize(opcode, tmpbuff); @@ -563,7 +582,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) *(uint32 *)(out->pBuffer+2)=htonl(p->Size()); used=MaxLen-10; memcpy(out->pBuffer+6,tmpbuff,used); - _log(NET__FRAGMENT, _L "First fragment: used %d/%d. Put size %d in the packet" __L, used, p->size, p->Size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "First fragment: used %d/%d. Put size %d in the packet" __L, used, p->size, p->Size()); SequencedPush(out); @@ -574,7 +593,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) out->size=chunksize+2; SequencedPush(out); used+=chunksize; - _log(NET__FRAGMENT, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Subsequent fragment: len %d, used %d/%d." __L, chunksize, used, p->size); } delete p; delete[] tmpbuff; @@ -598,22 +617,22 @@ void EQStream::SequencedPush(EQProtocolPacket *p) #else MOutboundQueue.lock(); if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Pre-Push Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Push Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } - _log(NET__APP_TRACE, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, NextOutSeq, p->size, SequencedBase); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pushing sequenced packet %d of length %d. Base Seq is %d." __L, NextOutSeq, p->size, SequencedBase); *(uint16 *)(p->pBuffer)=htons(NextOutSeq); SequencedQueue.push_back(p); NextOutSeq++; if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Push Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Push Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Push Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } MOutboundQueue.unlock(); #endif @@ -625,7 +644,7 @@ void EQStream::NonSequencedPush(EQProtocolPacket *p) delete p; #else MOutboundQueue.lock(); - _log(NET__APP_TRACE, _L "Pushing non-sequenced packet of length %d" __L, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pushing non-sequenced packet of length %d" __L, p->size); NonSequencedQueue.push(p); MOutboundQueue.unlock(); #endif @@ -634,14 +653,14 @@ void EQStream::NonSequencedPush(EQProtocolPacket *p) void EQStream::SendAck(uint16 seq) { uint16 Seq=htons(seq); - _log(NET__NET_ACKS, _L "Sending ack with sequence %d" __L, seq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Sending ack with sequence %d" __L, seq); SetLastAckSent(seq); NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16))); } void EQStream::SendOutOfOrderAck(uint16 seq) { - _log(NET__APP_TRACE, _L "Sending out of order ack with sequence %d" __L, seq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Sending out of order ack with sequence %d" __L, seq); uint16 Seq=htons(seq); NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16))); } @@ -657,7 +676,6 @@ void EQStream::Write(int eq_fd) int32 threshold=RateThreshold; MRate.unlock(); if (BytesWritten > threshold) { - //std::cout << "Over threshold: " << BytesWritten << " > " << threshold << std::endl; return; } @@ -677,7 +695,7 @@ void EQStream::Write(int eq_fd) // if we have a timeout defined and we have not received an ack recently enough, retransmit from beginning of queue if (RETRANSMIT_TIMEOUT_MULT && !SequencedQueue.empty() && NextSequencedSend && (GetState()==ESTABLISHED) && ((retransmittimer+retransmittimeout) < Timer::GetCurrentTime())) { - _log(NET__NET_TRACE, _L "Timeout since last ack received, starting retransmit at the start of our unacked " + Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout since last ack received, starting retransmit at the start of our unacked " "buffer (seq %d, was %d)." __L, SequencedBase, SequencedBase+NextSequencedSend); NextSequencedSend = 0; retransmittimer = Timer::GetCurrentTime(); // don't want to endlessly retransmit the first packet @@ -698,24 +716,24 @@ void EQStream::Write(int eq_fd) // If we don't have a packet to try to combine into, use this one as the base // And remove it form the queue p = NonSequencedQueue.front(); - _log(NET__NET_COMBINE, _L "Starting combined packet with non-seq packet of len %d" __L, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Starting combined packet with non-seq packet of len %d" __L, p->size); NonSequencedQueue.pop(); } else if (!p->combine(NonSequencedQueue.front())) { // Tryint to combine this packet with the base didn't work (too big maybe) // So just send the base packet (we'll try this packet again later) - _log(NET__NET_COMBINE, _L "Combined packet full at len %d, next non-seq packet is len %d" __L, p->size, (NonSequencedQueue.front())->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next non-seq packet is len %d" __L, p->size, (NonSequencedQueue.front())->size); ReadyToSend.push(p); BytesWritten+=p->size; p=nullptr; if (BytesWritten > threshold) { // Sent enough this round, lets stop to be fair - _log(NET__RATES, _L "Exceeded write threshold in nonseq (%d > %d)" __L, BytesWritten, threshold); + Log.Out(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in nonseq (%d > %d)" __L, BytesWritten, threshold); break; } } else { // Combine worked, so just remove this packet and it's spot in the queue - _log(NET__NET_COMBINE, _L "Combined non-seq packet of len %d, yeilding %d combined." __L, (NonSequencedQueue.front())->size, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined non-seq packet of len %d, yeilding %d combined." __L, (NonSequencedQueue.front())->size, p->size); delete NonSequencedQueue.front(); NonSequencedQueue.pop(); } @@ -726,48 +744,48 @@ void EQStream::Write(int eq_fd) if (sitr!=SequencedQueue.end()) { if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Pre-Send Seq NSS=%d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, NextSequencedSend, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Send Seq NSS=%d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, NextSequencedSend, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Pre-Send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } uint16 seq_send = SequencedBase + NextSequencedSend; //just for logging... if(SequencedQueue.empty()) { - _log(NET__ERROR, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Tried to write a packet with an empty queue (%d is past next out %d)" __L, seq_send, NextOutSeq); SeqEmpty=true; continue; } if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { if (!RETRANSMIT_ACKED_PACKETS && (*sitr)->acked) { - _log(NET__NET_TRACE, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send); + Log.Out(Logs::Detail, Logs::Netcode, _L "Not retransmitting seq packet %d because already marked as acked" __L, seq_send); sitr++; NextSequencedSend++; } else if (!p) { // If we don't have a packet to try to combine into, use this one as the base // Copy it first as it will still live until it is acked p=(*sitr)->Copy(); - _log(NET__NET_COMBINE, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size); ++sitr; NextSequencedSend++; } else if (!p->combine(*sitr)) { // Trying to combine this packet with the base didn't work (too big maybe) // So just send the base packet (we'll try this packet again later) - _log(NET__NET_COMBINE, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size); ReadyToSend.push(p); BytesWritten+=p->size; p=nullptr; if (BytesWritten > threshold) { // Sent enough this round, lets stop to be fair - _log(NET__RATES, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold); + Log.Out(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold); break; } } else { // Combine worked - _log(NET__NET_COMBINE, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); ++sitr; NextSequencedSend++; } @@ -776,35 +794,35 @@ void EQStream::Write(int eq_fd) // If we don't have a packet to try to combine into, use this one as the base // Copy it first as it will still live until it is acked p=(*sitr)->Copy(); - _log(NET__NET_COMBINE, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Starting combined packet with seq packet %d of len %d" __L, seq_send, p->size); ++sitr; NextSequencedSend++; } else if (!p->combine(*sitr)) { // Trying to combine this packet with the base didn't work (too big maybe) // So just send the base packet (we'll try this packet again later) - _log(NET__NET_COMBINE, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined packet full at len %d, next seq packet %d is len %d" __L, p->size, seq_send, (*sitr)->size); ReadyToSend.push(p); BytesWritten+=p->size; p=nullptr; if (BytesWritten > threshold) { // Sent enough this round, lets stop to be fair - _log(NET__RATES, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold); + Log.Out(Logs::Detail, Logs::Netcode, _L "Exceeded write threshold in seq (%d > %d)" __L, BytesWritten, threshold); break; } } else { // Combine worked - _log(NET__NET_COMBINE, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Combined seq packet %d of len %d, yeilding %d combined." __L, seq_send, (*sitr)->size, p->size); ++sitr; NextSequencedSend++; } } if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Post send Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Post send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Post send Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } } else { // No more sequenced packets @@ -816,7 +834,7 @@ void EQStream::Write(int eq_fd) // We have a packet still, must have run out of both seq and non-seq, so send it if (p) { - _log(NET__NET_COMBINE, _L "Final combined packet not full, len %d" __L, p->size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Final combined packet not full, len %d" __L, p->size); ReadyToSend.push(p); BytesWritten+=p->size; } @@ -833,7 +851,7 @@ void EQStream::Write(int eq_fd) if(SeqEmpty && NonSeqEmpty) { //no more data to send if(CheckState(CLOSING)) { - _log(NET__DEBUG, _L "All outgoing data flushed, closing stream." __L ); + Log.Out(Logs::Detail, Logs::Netcode, _L "All outgoing data flushed, closing stream." __L ); //we are waiting for the queues to empty, now we can do our disconnect. //this packet will not actually go out until the next call to Write(). _SendDisconnect(); @@ -896,7 +914,7 @@ EQProtocolPacket *out=new EQProtocolPacket(OP_SessionResponse,nullptr,sizeof(Ses out->size=sizeof(SessionResponse); - _log(NET__NET_TRACE, _L "Sending OP_SessionResponse: session %lu, maxlen=%d, key=0x%x, compressed? %s, encoded? %s" __L, + Log.Out(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionResponse: session %lu, maxlen=%d, key=0x%x, compressed? %s, encoded? %s" __L, (unsigned long)Session, MaxLen, Key, compressed?"yes":"no", encoded?"yes":"no"); NonSequencedPush(out); @@ -910,7 +928,7 @@ EQProtocolPacket *out=new EQProtocolPacket(OP_SessionRequest,nullptr,sizeof(Sess Request->Session=htonl(time(nullptr)); Request->MaxLength=htonl(512); - _log(NET__NET_TRACE, _L "Sending OP_SessionRequest: session %lu, maxlen=%d" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength)); + Log.Out(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionRequest: session %lu, maxlen=%d" __L, (unsigned long)ntohl(Request->Session), ntohl(Request->MaxLength)); NonSequencedPush(out); } @@ -924,7 +942,7 @@ void EQStream::_SendDisconnect() *(uint32 *)out->pBuffer=htonl(Session); NonSequencedPush(out); - _log(NET__NET_TRACE, _L "Sending OP_SessionDisconnect: session %lu" __L, (unsigned long)Session); + Log.Out(Logs::Detail, Logs::Netcode, _L "Sending OP_SessionDisconnect: session %lu" __L, (unsigned long)Session); } void EQStream::InboundQueuePush(EQRawApplicationPacket *p) @@ -946,15 +964,12 @@ EQRawApplicationPacket *p=nullptr; } MInboundQueue.unlock(); - //resolve the opcode if we can. - if(p) { - if(OpMgr != nullptr && *OpMgr != nullptr) { + if (p) { + if (OpMgr != nullptr && *OpMgr != nullptr) { EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); -#if EQDEBUG >= 4 - if(emu_op == OP_Unknown) { - _log(NET__ERROR, "Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode); - } -#endif + if (emu_op == OP_Unknown) { + // Log.Out(Logs::General, Logs::Client_Server_Packet_Unhandled, "Unknown :: [%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->opcode, p->Size(), DumpPacketToString(p).c_str()); + } p->SetOpcode(emu_op); } } @@ -978,11 +993,10 @@ EQRawApplicationPacket *p=nullptr; if(p) { if(OpMgr != nullptr && *OpMgr != nullptr) { EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); -#if EQDEBUG >= 4 if(emu_op == OP_Unknown) { - LogFile->write(EQEMuLog::Debug, "Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode); + Log.Out(Logs::General, Logs::Netcode, "Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode); } -#endif + p->SetOpcode(emu_op); } } @@ -1008,7 +1022,7 @@ void EQStream::InboundQueueClear() { EQApplicationPacket *p=nullptr; - _log(NET__APP_TRACE, _L "Clearing inbound queue" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Clearing inbound queue" __L); MInboundQueue.lock(); if (!InboundQueue.empty()) { @@ -1051,7 +1065,7 @@ void EQStream::OutboundQueueClear() { EQProtocolPacket *p=nullptr; - _log(NET__APP_TRACE, _L "Clearing outbound queue" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Clearing outbound queue" __L); MOutboundQueue.lock(); while(!NonSequencedQueue.empty()) { @@ -1073,7 +1087,7 @@ void EQStream::PacketQueueClear() { EQProtocolPacket *p=nullptr; - _log(NET__APP_TRACE, _L "Clearing future packet queue" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Clearing future packet queue" __L); if(!PacketQueue.empty()) { std::map::iterator itr; @@ -1105,8 +1119,7 @@ uint32 newlength=0; delete p; ProcessQueue(); } else { - _log(NET__DEBUG, _L "Incoming packet failed checksum" __L); - _hex(NET__NET_CREATE_HEX, buffer, length); + Log.Out(Logs::Detail, Logs::Netcode, _L "Incoming packet failed checksum" __L); } } @@ -1135,33 +1148,33 @@ std::deque::iterator itr, tmp; MOutboundQueue.lock(); //do a bit of sanity checking. if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Pre-Ack Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Ack Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Pre-Ack Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Pre-Ack Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } SeqOrder ord = CompareSequence(SequencedBase, seq); if(ord == SeqInOrder) { //they are not acking anything new... - _log(NET__NET_ACKS, _L "Received an ack with no window advancement (seq %d)." __L, seq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received an ack with no window advancement (seq %d)." __L, seq); } else if(ord == SeqPast) { //they are nacking blocks going back before our buffer, wtf? - _log(NET__NET_ACKS, _L "Received an ack with backward window advancement (they gave %d, our window starts at %d). This is bad." __L, seq, SequencedBase); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received an ack with backward window advancement (they gave %d, our window starts at %d). This is bad." __L, seq, SequencedBase); } else { - _log(NET__NET_ACKS, _L "Received an ack up through sequence %d. Our base is %d." __L, seq, SequencedBase); + Log.Out(Logs::Detail, Logs::Netcode, _L "Received an ack up through sequence %d. Our base is %d." __L, seq, SequencedBase); //this is a good ack, we get to ack some blocks. seq++; //we stop at the block right after their ack, counting on the wrap of both numbers. while(SequencedBase != seq) { if(SequencedQueue.empty()) { -_log(NET__ERROR, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, NextSequencedSend); +Log.Out(Logs::Detail, Logs::Netcode, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, NextSequencedSend); SequencedBase = NextOutSeq; NextSequencedSend = 0; break; } - _log(NET__NET_ACKS, _L "Removing acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, NextSequencedSend); + Log.Out(Logs::Detail, Logs::Netcode, _L "Removing acked packet with sequence %lu. Next send is %d before this." __L, (unsigned long)SequencedBase, NextSequencedSend); //clean out the acked packet delete SequencedQueue.front(); SequencedQueue.pop_front(); @@ -1172,10 +1185,10 @@ _log(NET__ERROR, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is SequencedBase++; } if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { - _log(NET__ERROR, _L "Post-Ack on %d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Post-Ack on %d Invalid Sequenced queue: BS %d + SQ %d != NOS %d" __L, seq, SequencedBase, SequencedQueue.size(), NextOutSeq); } if(NextSequencedSend > SequencedQueue.size()) { - _log(NET__ERROR, _L "Post-Ack Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "Post-Ack Next Send Sequence is beyond the end of the queue NSS %d > SQ %d" __L, NextSequencedSend, SequencedQueue.size()); } } @@ -1185,7 +1198,7 @@ if(NextSequencedSend > SequencedQueue.size()) { void EQStream::SetNextAckToSend(uint32 seq) { MAcks.lock(); - _log(NET__NET_ACKS, _L "Set Next Ack To Send to %lu" __L, (unsigned long)seq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Set Next Ack To Send to %lu" __L, (unsigned long)seq); NextAckToSend=seq; MAcks.unlock(); } @@ -1193,7 +1206,7 @@ void EQStream::SetNextAckToSend(uint32 seq) void EQStream::SetLastAckSent(uint32 seq) { MAcks.lock(); - _log(NET__NET_ACKS, _L "Set Last Ack Sent to %lu" __L, (unsigned long)seq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Set Last Ack Sent to %lu" __L, (unsigned long)seq); LastAckSent=seq; MAcks.unlock(); } @@ -1206,10 +1219,10 @@ void EQStream::ProcessQueue() EQProtocolPacket *qp=nullptr; while((qp=RemoveQueue(NextInSeq))!=nullptr) { - _log(NET__DEBUG, _L "Processing Queued Packet: Seq=%d" __L, NextInSeq); + Log.Out(Logs::Detail, Logs::Netcode, _L "Processing Queued Packet: Seq=%d" __L, NextInSeq); ProcessPacket(qp); delete qp; - _log(NET__APP_TRACE, _L "OP_Packet Queue size=%d" __L, PacketQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size()); } } @@ -1220,21 +1233,21 @@ EQProtocolPacket *qp=nullptr; if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) { qp=itr->second; PacketQueue.erase(itr); - _log(NET__APP_TRACE, _L "OP_Packet Queue size=%d" __L, PacketQueue.size()); + Log.Out(Logs::Detail, Logs::Netcode, _L "OP_Packet Queue size=%d" __L, PacketQueue.size()); } return qp; } void EQStream::SetStreamType(EQStreamType type) { - _log(NET__NET_TRACE, _L "Changing stream type from %s to %s" __L, StreamTypeString(StreamType), StreamTypeString(type)); + Log.Out(Logs::Detail, Logs::Netcode, _L "Changing stream type from %s to %s" __L, StreamTypeString(StreamType), StreamTypeString(type)); StreamType=type; switch (StreamType) { case LoginStream: app_opcode_size=1; compressed=false; encoded=false; - _log(NET__NET_TRACE, _L "Login stream has app opcode size %d, is not compressed or encoded." __L, app_opcode_size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Login stream has app opcode size %d, is not compressed or encoded." __L, app_opcode_size); break; case ChatOrMailStream: case ChatStream: @@ -1242,7 +1255,7 @@ void EQStream::SetStreamType(EQStreamType type) app_opcode_size=1; compressed=false; encoded=true; - _log(NET__NET_TRACE, _L "Chat/Mail stream has app opcode size %d, is not compressed, and is encoded." __L, app_opcode_size); + Log.Out(Logs::Detail, Logs::Netcode, _L "Chat/Mail stream has app opcode size %d, is not compressed, and is encoded." __L, app_opcode_size); break; case ZoneStream: case WorldStream: @@ -1250,7 +1263,7 @@ void EQStream::SetStreamType(EQStreamType type) app_opcode_size=2; compressed=true; encoded=false; - _log(NET__NET_TRACE, _L "World/Zone stream has app opcode size %d, is compressed, and is not encoded." __L, app_opcode_size); + Log.Out(Logs::Detail, Logs::Netcode, _L "World/Zone stream has app opcode size %d, is compressed, and is not encoded." __L, app_opcode_size); break; } } @@ -1300,7 +1313,7 @@ EQStream::SeqOrder EQStream::CompareSequence(uint16 expected_seq , uint16 seq) void EQStream::SetState(EQStreamState state) { MState.lock(); - _log(NET__NET_TRACE, _L "Changing state from %d to %d" __L, State, state); + Log.Out(Logs::Detail, Logs::Netcode, _L "Changing state from %d to %d" __L, State, state); State=state; MState.unlock(); } @@ -1312,29 +1325,29 @@ void EQStream::CheckTimeout(uint32 now, uint32 timeout) { EQStreamState orig_state = GetState(); if (orig_state == CLOSING && !outgoing_data) { - _log(NET__NET_TRACE, _L "Out of data in closing state, disconnecting." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Out of data in closing state, disconnecting." __L); _SendDisconnect(); SetState(DISCONNECTING); } else if (LastPacket && (now-LastPacket) > timeout) { switch(orig_state) { case CLOSING: //if we time out in the closing state, they are not acking us, just give up - _log(NET__DEBUG, _L "Timeout expired in closing state. Moving to closed state." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout expired in closing state. Moving to closed state." __L); _SendDisconnect(); SetState(CLOSED); break; case DISCONNECTING: //we timed out waiting for them to send us the disconnect reply, just give up. - _log(NET__DEBUG, _L "Timeout expired in disconnecting state. Moving to closed state." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout expired in disconnecting state. Moving to closed state." __L); SetState(CLOSED); break; case CLOSED: - _log(NET__DEBUG, _L "Timeout expired in closed state??" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout expired in closed state??" __L); break; case ESTABLISHED: //we timed out during normal operation. Try to be nice about it. //we will almost certainly time out again waiting for the disconnect reply, but oh well. - _log(NET__DEBUG, _L "Timeout expired in established state. Closing connection." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Timeout expired in established state. Closing connection." __L); _SendDisconnect(); SetState(DISCONNECTING); break; @@ -1363,11 +1376,11 @@ void EQStream::AdjustRates(uint32 average_delta) MRate.lock(); RateThreshold=RATEBASE/average_delta; DecayRate=DECAYBASE/average_delta; - _log(NET__RATES, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, + Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); MRate.unlock(); } else { - _log(NET__RATES, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, + Log.Out(Logs::Detail, Logs::Netcode, _L "Not adjusting data rate because avg delta over max (%d > %d)" __L, average_delta, AVERAGE_DELTA_MAX); } } else { @@ -1375,7 +1388,7 @@ void EQStream::AdjustRates(uint32 average_delta) MRate.lock(); RateThreshold=RATEBASE/average_delta; DecayRate=DECAYBASE/average_delta; - _log(NET__RATES, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, + Log.Out(Logs::Detail, Logs::Netcode, _L "Adjusting data rate to thresh %d, decay %d based on avg delta %d" __L, RateThreshold, DecayRate, average_delta); MRate.unlock(); } @@ -1385,12 +1398,12 @@ void EQStream::AdjustRates(uint32 average_delta) void EQStream::Close() { if(HasOutgoingData()) { //there is pending data, wait for it to go out. - _log(NET__DEBUG, _L "Stream requested to Close(), but there is pending data, waiting for it." __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Stream requested to Close(), but there is pending data, waiting for it." __L); SetState(CLOSING); } else { //otherwise, we are done, we can drop immediately. _SendDisconnect(); - _log(NET__DEBUG, _L "Stream closing immediate due to Close()" __L); + Log.Out(Logs::Detail, Logs::Netcode, _L "Stream closing immediate due to Close()" __L); SetState(DISCONNECTING); } } @@ -1418,19 +1431,19 @@ EQStream::MatchState EQStream::CheckSignature(const Signature *sig) { } else if(p->opcode == sig->first_eq_opcode) { //opcode matches, check length.. if(p->size == sig->first_length) { - _log(NET__IDENT_TRACE, "%s:%d: First opcode matched 0x%x and length matched %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); + Log.Out(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x and length matched %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); res = MatchSuccessful; } else if(sig->first_length == 0) { - _log(NET__IDENT_TRACE, "%s:%d: First opcode matched 0x%x and length (%d) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); + Log.Out(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x and length (%d) is ignored", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size); res = MatchSuccessful; } else { //opcode matched but length did not. - _log(NET__IDENT_TRACE, "%s:%d: First opcode matched 0x%x, but length %d did not match expected %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length); + Log.Out(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode matched 0x%x, but length %d did not match expected %d", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), sig->first_eq_opcode, p->size, sig->first_length); res = MatchFailed; } } else { //first opcode did not match.. - _log(NET__IDENT_TRACE, "%s:%d: First opcode 0x%x did not match expected 0x%x", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode); + Log.Out(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: First opcode 0x%x did not match expected 0x%x", long2ip(GetRemoteIP()).c_str(), ntohs(GetRemotePort()), p->opcode, sig->first_eq_opcode); res = MatchFailed; } } diff --git a/common/eq_stream.h b/common/eq_stream.h index 5a637c46e..72eb53cdd 100644 --- a/common/eq_stream.h +++ b/common/eq_stream.h @@ -1,22 +1,26 @@ #ifndef _EQSTREAM_H #define _EQSTREAM_H -#include #include #include #include #include + #ifndef WIN32 #include #endif -#include "eq_stream_type.h" + +#include "../common/misc.h" +#include "../common/opcodemgr.h" +#include "../common/timer.h" + #include "eq_packet.h" #include "eq_stream_intf.h" +#include "eq_stream_type.h" #include "mutex.h" -#include "../common/opcodemgr.h" -#include "../common/misc.h" -#include "../common/condition.h" -#include "../common/timer.h" + +class EQApplicationPacket; +class EQProtocolPacket; #define FLAG_COMPRESSED 0x01 #define FLAG_ENCODED 0x04 @@ -45,6 +49,10 @@ #define RETRANSMIT_ACKED_PACKETS true #endif +#ifndef MAX_SESSION_RETRIES +#define MAX_SESSION_RETRIES 30 +#endif + #pragma pack(1) struct SessionRequest { uint32 UnknownA; @@ -78,7 +86,6 @@ struct SessionStats { #pragma pack() class OpcodeManager; -class EQStreamPair; class EQRawApplicationPacket; class EQStream : public EQStreamInterface { @@ -101,6 +108,9 @@ class EQStream : public EQStreamInterface { uint32 retransmittimer; uint32 retransmittimeout; + uint16 sessionAttempts; + bool streamactive; + //uint32 buffer_len; uint32 Session, Key; @@ -194,10 +204,16 @@ class EQStream : public EQStreamInterface { void _SendDisconnect(); - void init(); + void init(bool resetSession=true); public: - EQStream() { init(); remote_ip = 0; remote_port = 0; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); } - EQStream(sockaddr_in addr) { init(); remote_ip=addr.sin_addr.s_addr; remote_port=addr.sin_port; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); } + EQStream() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED; + StreamType = UnknownStream; compressed = true; encoded = false; app_opcode_size = 2; + bytes_sent = 0; bytes_recv = 0; create_time = Timer::GetTimeSeconds(); sessionAttempts = 0; + streamactive = false; } + EQStream(sockaddr_in addr) { init(); remote_ip = addr.sin_addr.s_addr; + remote_port = addr.sin_port; State = UNESTABLISHED; StreamType = UnknownStream; + compressed = true; encoded = false; app_opcode_size = 2; bytes_sent = 0; bytes_recv = 0; + create_time = Timer::GetTimeSeconds(); } virtual ~EQStream() { RemoveData(); SetState(CLOSED); } void SetMaxLen(uint32 length) { MaxLen=length; } @@ -221,6 +237,9 @@ class EQStream : public EQStreamInterface { void SetLastPacketTime(uint32 t) {LastPacket=t;} void Write(int eq_fd); + // whether or not the stream has been assigned (we passed our stream match) + void SetActive(bool val) { streamactive = val; } + // inline bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; } inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); } diff --git a/common/eq_stream_factory.cpp b/common/eq_stream_factory.cpp index bc3e2e2ba..f48b0f723 100644 --- a/common/eq_stream_factory.cpp +++ b/common/eq_stream_factory.cpp @@ -1,5 +1,7 @@ -#include "debug.h" +#include "global_define.h" +#include "eqemu_logsys.h" #include "eq_stream_factory.h" + #ifdef _WINDOWS #include #include @@ -13,24 +15,24 @@ #include #include #endif -#include + #include +#include + #include "op_codes.h" -#include "eq_stream.h" -#include "logsys.h" ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs) { EQStreamFactory *fs=(EQStreamFactory *)eqfs; #ifndef WIN32 - _log(COMMON__THREADS, "Starting EQStreamFactoryReaderLoop with thread ID %d", pthread_self()); + Log.Out(Logs::Detail, Logs::None, "Starting EQStreamFactoryReaderLoop with thread ID %d", pthread_self()); #endif fs->ReaderLoop(); #ifndef WIN32 - _log(COMMON__THREADS, "Ending EQStreamFactoryReaderLoop with thread ID %d", pthread_self()); + Log.Out(Logs::Detail, Logs::None, "Ending EQStreamFactoryReaderLoop with thread ID %d", pthread_self()); #endif THREAD_RETURN(nullptr); @@ -41,13 +43,13 @@ ThreadReturnType EQStreamFactoryWriterLoop(void *eqfs) EQStreamFactory *fs=(EQStreamFactory *)eqfs; #ifndef WIN32 - _log(COMMON__THREADS, "Starting EQStreamFactoryWriterLoop with thread ID %d", pthread_self()); + Log.Out(Logs::Detail, Logs::None, "Starting EQStreamFactoryWriterLoop with thread ID %d", pthread_self()); #endif fs->WriterLoop(); #ifndef WIN32 - _log(COMMON__THREADS, "Ending EQStreamFactoryWriterLoop with thread ID %d", pthread_self()); + Log.Out(Logs::Detail, Logs::None, "Ending EQStreamFactoryWriterLoop with thread ID %d", pthread_self()); #endif THREAD_RETURN(nullptr); @@ -104,8 +106,6 @@ struct sockaddr_in address; fcntl(sock, F_SETFL, O_NONBLOCK); #endif //moved these because on windows the output was delayed and causing the console window to look bad - //std::cout << "Starting factory Reader" << std::endl; - //std::cout << "Starting factory Writer" << std::endl; #ifdef _WINDOWS _beginthread(EQStreamFactoryReaderLoop,0, this); _beginthread(EQStreamFactoryWriterLoop,0, this); @@ -116,44 +116,39 @@ struct sockaddr_in address; return true; } -EQStream *EQStreamFactory::Pop() +std::shared_ptr EQStreamFactory::Pop() { -EQStream *s=nullptr; - //std::cout << "Pop():Locking MNewStreams" << std::endl; + std::shared_ptr s = nullptr; MNewStreams.lock(); if (NewStreams.size()) { - s=NewStreams.front(); + s = NewStreams.front(); NewStreams.pop(); s->PutInUse(); } MNewStreams.unlock(); - //std::cout << "Pop(): Unlocking MNewStreams" << std::endl; return s; } -void EQStreamFactory::Push(EQStream *s) +void EQStreamFactory::Push(std::shared_ptr s) { - //std::cout << "Push():Locking MNewStreams" << std::endl; MNewStreams.lock(); NewStreams.push(s); MNewStreams.unlock(); - //std::cout << "Push(): Unlocking MNewStreams" << std::endl; } void EQStreamFactory::ReaderLoop() { -fd_set readset; -std::map,EQStream *>::iterator stream_itr; -int num; -int length; -unsigned char buffer[2048]; -sockaddr_in from; -int socklen=sizeof(sockaddr_in); -timeval sleep_time; -//time_t now; + fd_set readset; + std::map, std::shared_ptr>::iterator stream_itr; + int num; + int length; + unsigned char buffer[2048]; + sockaddr_in from; + int socklen = sizeof(sockaddr_in); + timeval sleep_time; + ReaderRunning = true; - ReaderRunning=true; while(sock!=-1) { MReaderRunning.lock(); if (!ReaderRunning) @@ -184,10 +179,10 @@ timeval sleep_time; // What do we wanna do? } else { MStreams.lock(); - stream_itr=Streams.find(std::make_pair(from.sin_addr.s_addr, from.sin_port)); + stream_itr = Streams.find(std::make_pair(from.sin_addr.s_addr, from.sin_port)); if (stream_itr == Streams.end()) { if (buffer[1]==OP_SessionRequest) { - EQStream *s = new EQStream(from); + std::shared_ptr s = std::make_shared(from); s->SetStreamType(StreamType); Streams[std::make_pair(from.sin_addr.s_addr, from.sin_port)]=s; WriterWork.Signal(); @@ -198,13 +193,13 @@ timeval sleep_time; } MStreams.unlock(); } else { - EQStream *curstream = stream_itr->second; + std::shared_ptr curstream = stream_itr->second; //dont bother processing incoming packets for closed connections if(curstream->CheckClosed()) curstream = nullptr; else curstream->PutInUse(); - MStreams.unlock(); //the in use flag prevents the stream from being deleted while we are using it. + //the in use flag prevents the stream from being deleted while we are using it. if(curstream) { curstream->AddBytesRecv(length); @@ -212,6 +207,7 @@ timeval sleep_time; curstream->SetLastPacketTime(Timer::GetCurrentTime()); curstream->ReleaseFromUse(); } + MStreams.unlock(); } } } @@ -224,10 +220,10 @@ void EQStreamFactory::CheckTimeout() MStreams.lock(); unsigned long now=Timer::GetCurrentTime(); - std::map,EQStream *>::iterator stream_itr; + std::map, std::shared_ptr>::iterator stream_itr; - for(stream_itr=Streams.begin();stream_itr!=Streams.end();) { - EQStream *s = stream_itr->second; + for(stream_itr = Streams.begin(); stream_itr != Streams.end();) { + std::shared_ptr s = stream_itr->second; s->CheckTimeout(now, stream_timeout); @@ -239,11 +235,9 @@ void EQStreamFactory::CheckTimeout() //give it a little time for everybody to finish with it } else { //everybody is done, we can delete it now - //std::cout << "Removing connection" << std::endl; - std::map,EQStream *>::iterator temp=stream_itr; + std::map, std::shared_ptr>::iterator temp = stream_itr; ++stream_itr; - //let whoever has the stream outside delete it - delete temp->second; + temp->second = nullptr; Streams.erase(temp); continue; } @@ -256,21 +250,17 @@ void EQStreamFactory::CheckTimeout() void EQStreamFactory::WriterLoop() { -std::map,EQStream *>::iterator stream_itr; -bool havework=true; -std::vector wants_write; -std::vector::iterator cur,end; -bool decay=false; -uint32 stream_count; - -Timer DecayTimer(20); - - WriterRunning=true; + std::map, std::shared_ptr>::iterator stream_itr; + bool havework=true; + std::vector> wants_write; + std::vector>::iterator cur, end; + bool decay = false; + uint32 stream_count; + Timer DecayTimer(20); + WriterRunning = true; DecayTimer.Enable(); + while(sock!=-1) { - //if (!havework) { - //WriterWork.Wait(); - //} MWriterRunning.lock(); if (!WriterRunning) break; @@ -291,7 +281,7 @@ Timer DecayTimer(20); //bullshit checking, to see if this is really happening, GDB seems to think so... if(stream_itr->second == nullptr) { - fprintf(stderr, "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i", stream_itr->first.first, stream_itr->first.second); + fprintf(stderr, "ERROR: nullptr Stream encountered in EQStreamFactory::WriterLoop for: %i:%i", stream_itr->first.first, stream_itr->first.second); continue; } @@ -314,12 +304,10 @@ Timer DecayTimer(20); Sleep(10); MStreams.lock(); - stream_count=Streams.size(); + stream_count = Streams.size(); MStreams.unlock(); if (!stream_count) { - //std::cout << "No streams, waiting on condition" << std::endl; WriterWork.Wait(); - //std::cout << "Awake from condition, must have a stream now" << std::endl; } } } diff --git a/common/eq_stream_factory.h b/common/eq_stream_factory.h index 7aa5d66ac..86ffff979 100644 --- a/common/eq_stream_factory.h +++ b/common/eq_stream_factory.h @@ -2,13 +2,16 @@ #define _EQSTREAMFACTORY_H +#include #include #include + #include "../common/eq_stream.h" #include "../common/condition.h" #include "../common/timeoutmgr.h" -#include "../common/opcodemgr.h" -#include "../common/timer.h" + +class EQStream; +class Timer; class EQStreamFactory : private Timeoutable { private: @@ -24,10 +27,10 @@ class EQStreamFactory : private Timeoutable { EQStreamType StreamType; - std::queue NewStreams; + std::queue> NewStreams; Mutex MNewStreams; - std::map,EQStream *> Streams; + std::map, std::shared_ptr> Streams; Mutex MStreams; virtual void CheckTimeout(); @@ -40,8 +43,8 @@ class EQStreamFactory : private Timeoutable { EQStreamFactory(EQStreamType type, uint32 timeout = 135000) : Timeoutable(5000), stream_timeout(timeout) { ReaderRunning=false; WriterRunning=false; StreamType=type; sock=-1; } EQStreamFactory(EQStreamType type, int port, uint32 timeout = 135000); - EQStream *Pop(); - void Push(EQStream *s); + std::shared_ptr Pop(); + void Push(std::shared_ptr s); bool Open(); bool Open(unsigned long port) { Port=port; return Open(); } diff --git a/common/eq_stream_ident.cpp b/common/eq_stream_ident.cpp index b60ac28d0..4640c75f1 100644 --- a/common/eq_stream_ident.cpp +++ b/common/eq_stream_ident.cpp @@ -1,20 +1,20 @@ -#include "debug.h" +#include "global_define.h" +#include "eqemu_logsys.h" #include "eq_stream_ident.h" #include "eq_stream_proxy.h" -#include "logsys.h" + EQStreamIdentifier::~EQStreamIdentifier() { while(!m_identified.empty()) { m_identified.front()->ReleaseFromUse(); m_identified.pop(); } - std::vector::iterator cur, end; + std::vector::iterator cur, end; cur = m_streams.begin(); end = m_streams.end(); for(; cur != end; ++cur) { - Record *r = *cur; - r->stream->ReleaseFromUse(); - delete r; + Record &r = *cur; + r.stream->ReleaseFromUse(); } std::vector::iterator curp, endp; curp = m_patches.begin(); @@ -34,54 +34,52 @@ void EQStreamIdentifier::RegisterPatch(const EQStream::Signature &sig, const cha } void EQStreamIdentifier::Process() { - std::vector::iterator cur; + std::vector::iterator cur; std::vector::iterator curp, endp; //foreach pending stream. cur = m_streams.begin(); while(cur != m_streams.end()) { - Record *r = *cur; + Record &r = *cur; //first see if this stream has expired - if(r->expire.Check(false)) { + if(r.expire.Check(false)) { //this stream has failed to match any pattern in our timeframe. - _log(NET__IDENTIFY, "Unable to identify stream from %s:%d before timeout.", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort())); - r->stream->ReleaseFromUse(); - delete r; + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d before timeout.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort())); + r.stream->ReleaseFromUse(); cur = m_streams.erase(cur); continue; } //then make sure the stream is still active //if stream hasn't finished initializing then continue; - if(r->stream->GetState() == UNESTABLISHED) + if(r.stream->GetState() == UNESTABLISHED) { ++cur; continue; } - if(r->stream->GetState() != ESTABLISHED) { + if(r.stream->GetState() != ESTABLISHED) { //the stream closed before it was identified. - _log(NET__IDENTIFY, "Unable to identify stream from %s:%d before it closed.", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort())); - switch(r->stream->GetState()) + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d before it closed.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort())); + switch(r.stream->GetState()) { case ESTABLISHED: - _log(NET__IDENTIFY, "Stream state was Established"); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Established"); break; case CLOSING: - _log(NET__IDENTIFY, "Stream state was Closing"); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closing"); break; case DISCONNECTING: - _log(NET__IDENTIFY, "Stream state was Disconnecting"); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Disconnecting"); break; case CLOSED: - _log(NET__IDENTIFY, "Stream state was Closed"); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closed"); break; default: - _log(NET__IDENTIFY, "Stream state was Unestablished or unknown"); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Unestablished or unknown"); break; } - r->stream->ReleaseFromUse(); - delete r; + r.stream->ReleaseFromUse(); cur = m_streams.erase(cur); continue; } @@ -98,20 +96,23 @@ void EQStreamIdentifier::Process() { Patch *p = *curp; //ask the stream to see if it matches the supplied signature - EQStream::MatchState res = r->stream->CheckSignature(&p->signature); + EQStream::MatchState res = r.stream->CheckSignature(&p->signature); switch(res) { case EQStream::MatchNotReady: //the stream has not received enough packets to compare with this signature -// _log(NET__IDENT_TRACE, "%s:%d: Tried patch %s, but stream is not ready for it.", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort()), p->name.c_str()); +// Log.LogDebugType(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: Tried patch %s, but stream is not ready for it.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str()); all_ready = false; break; case EQStream::MatchSuccessful: { //yay, a match. - _log(NET__IDENTIFY, "Identified stream %s:%d with signature %s", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort()), p->name.c_str()); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Identified stream %s:%d with signature %s", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str()); + + // before we assign the eqstream to an interface, let the stream recognize it is in use and the session should not be reset any further + r.stream->SetActive(true); //might want to do something less-specific here... some day.. - EQStreamInterface *s = new EQStreamProxy(r->stream, p->structs, p->opcodes); + EQStreamInterface *s = new EQStreamProxy(r.stream, p->structs, p->opcodes); m_identified.push(s); found_one = true; @@ -119,7 +120,7 @@ void EQStreamIdentifier::Process() { } case EQStream::MatchFailed: //do nothing... - _log(NET__IDENT_TRACE, "%s:%d: Tried patch %s, and it did not match.", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort()), p->name.c_str()); + Log.Out(Logs::General, Logs::Netcode, "[IDENT_TRACE] %s:%d: Tried patch %s, and it did not match.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort()), p->name.c_str()); break; } } @@ -127,14 +128,13 @@ void EQStreamIdentifier::Process() { //if we checked all patches and did not find a match. if(all_ready && !found_one) { //the stream cannot be identified. - _log(NET__IDENTIFY, "Unable to identify stream from %s:%d, no match found.", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort())); - r->stream->ReleaseFromUse(); + Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Unable to identify stream from %s:%d, no match found.", long2ip(r.stream->GetRemoteIP()).c_str(), ntohs(r.stream->GetRemotePort())); + r.stream->ReleaseFromUse(); } //if we found a match, or were not able to identify it if(found_one || all_ready) { - //cannot print ip/port here. r->stream is invalid. - delete r; + //cannot print ip/port here. r.stream is invalid. cur = m_streams.erase(cur); } else { ++cur; @@ -142,8 +142,8 @@ void EQStreamIdentifier::Process() { } //end foreach stream } -void EQStreamIdentifier::AddStream(EQStream *&eqs) { - m_streams.push_back(new Record(eqs)); +void EQStreamIdentifier::AddStream(std::shared_ptr &eqs) { + m_streams.push_back(Record(eqs)); eqs = nullptr; } @@ -155,7 +155,7 @@ EQStreamInterface *EQStreamIdentifier::PopIdentified() { return(res); } -EQStreamIdentifier::Record::Record(EQStream *s) +EQStreamIdentifier::Record::Record(std::shared_ptr s) : stream(s), expire(STREAM_IDENT_WAIT_MS) { diff --git a/common/eq_stream_ident.h b/common/eq_stream_ident.h index c038daf26..3b6a63ed9 100644 --- a/common/eq_stream_ident.h +++ b/common/eq_stream_ident.h @@ -4,13 +4,14 @@ #include "eq_stream.h" #include "timer.h" #include -#include #include +#include #define STREAM_IDENT_WAIT_MS 10000 class OpcodeManager; class StructStrategy; +class EQStreamInterface; class EQStreamIdentifier { public: @@ -21,7 +22,7 @@ public: //main processing interface void Process(); - void AddStream(EQStream *& eqs); + void AddStream(std::shared_ptr &eqs); EQStreamInterface *PopIdentified(); protected: @@ -39,11 +40,11 @@ protected: //pending streams.. class Record { public: - Record(EQStream *s); - EQStream *stream; //we own this + Record(std::shared_ptr s); + std::shared_ptr stream; //we own this Timer expire; }; - std::vector m_streams; //we own these objects, and the streams contained in them. + std::vector m_streams; //we own these objects, and the streams contained in them. std::queue m_identified; //we own these objects }; diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 9373f2262..68b8ffc96 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -35,7 +35,7 @@ public: virtual const uint32 GetBytesRecieved() const { return 0; } virtual const uint32 GetBytesSentPerSecond() const { return 0; } virtual const uint32 GetBytesRecvPerSecond() const { return 0; } - virtual const EQClientVersion ClientVersion() const { return EQClientUnknown; } + virtual const ClientVersion GetClientVersion() const { return ClientVersion::Unknown; } }; #endif /*EQSTREAMINTF_H_*/ diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index 20fc4ea06..117ae8c94 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -1,11 +1,11 @@ -#include "debug.h" +#include "global_define.h" #include "eq_stream_proxy.h" #include "eq_stream.h" #include "struct_strategy.h" -EQStreamProxy::EQStreamProxy(EQStream *&stream, const StructStrategy *structs, OpcodeManager **opcodes) +EQStreamProxy::EQStreamProxy(std::shared_ptr &stream, const StructStrategy *structs, OpcodeManager **opcodes) : m_stream(stream), m_structs(structs), m_opcodes(opcodes) @@ -15,16 +15,15 @@ EQStreamProxy::EQStreamProxy(EQStream *&stream, const StructStrategy *structs, O } EQStreamProxy::~EQStreamProxy() { - //delete m_stream; //released by the stream factory. } std::string EQStreamProxy::Describe() const { return(m_structs->Describe()); } -const EQClientVersion EQStreamProxy::ClientVersion() const +const ClientVersion EQStreamProxy::GetClientVersion() const { - return m_structs->ClientVersion(); + return m_structs->GetClientVersion(); } void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { @@ -85,12 +84,6 @@ const uint32 EQStreamProxy::GetBytesRecvPerSecond() const void EQStreamProxy::ReleaseFromUse() { m_stream->ReleaseFromUse(); - - //this is so ugly, but I cant think of a better way to deal with - //it right now... - if(!m_stream->IsInUse()) { - delete this; - } } void EQStreamProxy::RemoveData() { diff --git a/common/eq_stream_proxy.h b/common/eq_stream_proxy.h index 34ea3a9fc..93ad1d884 100644 --- a/common/eq_stream_proxy.h +++ b/common/eq_stream_proxy.h @@ -4,8 +4,9 @@ #include "types.h" #include "eq_stream_intf.h" +#include "eq_stream.h" +#include -class EQStream; class StructStrategy; class OpcodeManager; class EQApplicationPacket; @@ -13,7 +14,7 @@ class EQApplicationPacket; class EQStreamProxy : public EQStreamInterface { public: //takes ownership of the stream. - EQStreamProxy(EQStream *&stream, const StructStrategy *structs, OpcodeManager **opcodes); + EQStreamProxy(std::shared_ptr &stream, const StructStrategy *structs, OpcodeManager **opcodes); virtual ~EQStreamProxy(); //EQStreamInterface: @@ -27,7 +28,7 @@ public: virtual void RemoveData(); virtual bool CheckState(EQStreamState state); virtual std::string Describe() const; - virtual const EQClientVersion ClientVersion() const; + virtual const ClientVersion GetClientVersion() const; virtual const uint32 GetBytesSent() const; virtual const uint32 GetBytesRecieved() const; @@ -35,7 +36,7 @@ public: virtual const uint32 GetBytesRecvPerSecond() const; protected: - EQStream *const m_stream; //we own this stream object. + std::shared_ptr const m_stream; //we own this stream object. const StructStrategy *const m_structs; //we do not own this object. //this is a pointer to a pointer to make it less likely that a packet will //reference an invalid opcode manager when they are being reloaded. diff --git a/common/eqdb.cpp b/common/eqdb.cpp index 03746b0d4..2c912afba 100644 --- a/common/eqdb.cpp +++ b/common/eqdb.cpp @@ -15,7 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" +#include "global_define.h" #include "eqdb.h" #include "database.h" #include diff --git a/common/eqdb_res.cpp b/common/eqdb_res.cpp index f34229a1f..11d90459d 100644 --- a/common/eqdb_res.cpp +++ b/common/eqdb_res.cpp @@ -15,7 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" +#include "global_define.h" #include "eqdb_res.h" #include diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 165b0786f..6e1400904 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -15,62 +15,65 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../common/debug.h" + +#include "../common/global_define.h" #include "eqemu_config.h" #include "misc_functions.h" + #include #include std::string EQEmuConfig::ConfigFile = "eqemu_config.xml"; EQEmuConfig *EQEmuConfig::_config = nullptr; -void EQEmuConfig::do_world(TiXmlElement *ele) { +void EQEmuConfig::do_world(TiXmlElement *ele) +{ const char *text; TiXmlElement * sub_ele;; - - text= ParseTextBlock(ele,"shortname"); - if (text) - ShortName=text; - - text = ParseTextBlock(ele,"longname"); - if (text) - LongName=text; - - text = ParseTextBlock(ele,"address",true); - if (text) - WorldAddress=text; - - text = ParseTextBlock(ele,"localaddress",true); - if (text) - LocalAddress=text; - - text = ParseTextBlock(ele,"maxclients",true); - if (text) - MaxClients=atoi(text); - + text = ParseTextBlock(ele, "shortname"); + if (text) { + ShortName = text; + } + text = ParseTextBlock(ele, "longname"); + if (text) { + LongName = text; + } + text = ParseTextBlock(ele, "address", true); + if (text) { + WorldAddress = text; + } + text = ParseTextBlock(ele, "localaddress", true); + if (text) { + LocalAddress = text; + } + text = ParseTextBlock(ele, "maxclients", true); + if (text) { + MaxClients = atoi(text); + } // Get the element - text = ParseTextBlock(ele,"key",true); - if (text) - SharedKey=text; - + text = ParseTextBlock(ele, "key", true); + if (text) { + SharedKey = text; + } // Get the element sub_ele = ele->FirstChildElement("loginserver"); if (sub_ele) { - text=ParseTextBlock(sub_ele,"host",true); - if (text) - LoginHost=text; - - text=ParseTextBlock(sub_ele,"port",true); - if (text) - LoginPort=atoi(text); - - text=ParseTextBlock(sub_ele,"account",true); - if (text) - LoginAccount=text; - - text=ParseTextBlock(sub_ele,"password",true); - if (text) - LoginPassword=text; + text = ParseTextBlock(sub_ele, "host", true); + if (text) { + LoginHost = text; + } + text = ParseTextBlock(sub_ele, "port", true); + if (text) { + LoginPort = atoi(text); + } + text = ParseTextBlock(sub_ele, "account", true); + if (text) { + LoginAccount = text; + } + text = ParseTextBlock(sub_ele, "password", true); + if (text) { + LoginPassword = text; + } } else { char str[32]; do { @@ -78,329 +81,366 @@ void EQEmuConfig::do_world(TiXmlElement *ele) { sub_ele = ele->FirstChildElement(str); if (sub_ele) { LoginConfig* loginconfig = new LoginConfig; - text=ParseTextBlock(sub_ele,"host",true); - if (text) - loginconfig->LoginHost=text; - - text=ParseTextBlock(sub_ele,"port",true); - if (text) - loginconfig->LoginPort=atoi(text); - - text=ParseTextBlock(sub_ele,"account",true); - if (text) - loginconfig->LoginAccount=text; - - text=ParseTextBlock(sub_ele,"password",true); - if (text) - loginconfig->LoginPassword=text; + text = ParseTextBlock(sub_ele, "host", true); + if (text) { + loginconfig->LoginHost = text; + } + text = ParseTextBlock(sub_ele, "port", true); + if (text) { + loginconfig->LoginPort = atoi(text); + } + text = ParseTextBlock(sub_ele, "account", true); + if (text) { + loginconfig->LoginAccount = text; + } + text = ParseTextBlock(sub_ele, "password", true); + if (text) { + loginconfig->LoginPassword = text; + } loginlist.Insert(loginconfig); } - } while(sub_ele); + } while (sub_ele); } - // Check for locked sub_ele = ele->FirstChildElement("locked"); - if (sub_ele != nullptr) - Locked=true; - + if (sub_ele != nullptr) { + Locked = true; + } // Get the element sub_ele = ele->FirstChildElement("tcp"); - if(sub_ele != nullptr) { - + if (sub_ele != nullptr) { text = sub_ele->Attribute("ip"); - if (text) - WorldIP=text; - + if (text) { + WorldIP = text; + } text = sub_ele->Attribute("port"); - if (text) - WorldTCPPort=atoi(text); - + if (text) { + WorldTCPPort = atoi(text); + } text = sub_ele->Attribute("telnet"); - if (text && !strcasecmp(text,"enabled")) - TelnetEnabled=true; - + if (text && !strcasecmp(text, "enabled")) { + TelnetEnabled = true; + } } - // Get the element sub_ele = ele->FirstChildElement("http"); - if(sub_ele != nullptr) { - + if (sub_ele != nullptr) { // text = sub_ele->Attribute("ip"); // if (text) // WorldIP=text; - text = sub_ele->Attribute("mimefile"); - if (text) - WorldHTTPMimeFile=text; - + if (text) { + WorldHTTPMimeFile = text; + } text = sub_ele->Attribute("port"); - if (text) - WorldHTTPPort=atoi(text); - + if (text) { + WorldHTTPPort = atoi(text); + } text = sub_ele->Attribute("enabled"); - if (text && !strcasecmp(text,"true")) - WorldHTTPEnabled=true; - + if (text && !strcasecmp(text, "true")) { + WorldHTTPEnabled = true; + } } } -void EQEmuConfig::do_chatserver(TiXmlElement *ele) { +void EQEmuConfig::do_chatserver(TiXmlElement *ele) +{ const char *text; - - text=ParseTextBlock(ele,"host",true); - if (text) - ChatHost=text; - - text=ParseTextBlock(ele,"port",true); - if (text) - ChatPort=atoi(text); + text = ParseTextBlock(ele, "host", true); + if (text) { + ChatHost = text; + } + text = ParseTextBlock(ele, "port", true); + if (text) { + ChatPort = atoi(text); + } } -void EQEmuConfig::do_mailserver(TiXmlElement *ele) { +void EQEmuConfig::do_mailserver(TiXmlElement *ele) +{ const char *text; - - text=ParseTextBlock(ele,"host",true); - if (text) - MailHost=text; - - text=ParseTextBlock(ele,"port",true); - if (text) - MailPort=atoi(text); + text = ParseTextBlock(ele, "host", true); + if (text) { + MailHost = text; + } + text = ParseTextBlock(ele, "port", true); + if (text) { + MailPort = atoi(text); + } } -void EQEmuConfig::do_database(TiXmlElement *ele) { +void EQEmuConfig::do_database(TiXmlElement *ele) +{ const char *text; - - text=ParseTextBlock(ele,"host",true); - if (text) - DatabaseHost=text; - - text=ParseTextBlock(ele,"port",true); - if (text) - DatabasePort=atoi(text); - - text=ParseTextBlock(ele,"username",true); - if (text) - DatabaseUsername=text; - - text=ParseTextBlock(ele,"password",true); - if (text) - DatabasePassword=text; - - text=ParseTextBlock(ele,"db",true); - if (text) - DatabaseDB=text; + text = ParseTextBlock(ele, "host", true); + if (text) { + DatabaseHost = text; + } + text = ParseTextBlock(ele, "port", true); + if (text) { + DatabasePort = atoi(text); + } + text = ParseTextBlock(ele, "username", true); + if (text) { + DatabaseUsername = text; + } + text = ParseTextBlock(ele, "password", true); + if (text) { + DatabasePassword = text; + } + text = ParseTextBlock(ele, "db", true); + if (text) { + DatabaseDB = text; + } } -void EQEmuConfig::do_qsdatabase(TiXmlElement *ele) { +void EQEmuConfig::do_qsdatabase(TiXmlElement *ele) +{ const char *text; - - text=ParseTextBlock(ele,"host",true); - if (text) - QSDatabaseHost=text; - - text=ParseTextBlock(ele,"port",true); - if (text) - QSDatabasePort=atoi(text); - - text=ParseTextBlock(ele,"username",true); - if (text) - QSDatabaseUsername=text; - - text=ParseTextBlock(ele,"password",true); - if (text) - QSDatabasePassword=text; - - text=ParseTextBlock(ele,"db",true); - if (text) - QSDatabaseDB=text; + text = ParseTextBlock(ele, "host", true); + if (text) { + QSDatabaseHost = text; + } + text = ParseTextBlock(ele, "port", true); + if (text) { + QSDatabasePort = atoi(text); + } + text = ParseTextBlock(ele, "username", true); + if (text) { + QSDatabaseUsername = text; + } + text = ParseTextBlock(ele, "password", true); + if (text) { + QSDatabasePassword = text; + } + text = ParseTextBlock(ele, "db", true); + if (text) { + QSDatabaseDB = text; + } } -void EQEmuConfig::do_zones(TiXmlElement *ele) { +void EQEmuConfig::do_zones(TiXmlElement *ele) +{ const char *text; TiXmlElement *sub_ele; // TiXmlNode *node,*sub_node; - - text=ParseTextBlock(ele,"defaultstatus",true); - if (text) - DefaultStatus=atoi(text); - + text = ParseTextBlock(ele, "defaultstatus", true); + if (text) { + DefaultStatus = atoi(text); + } // Get the element sub_ele = ele->FirstChildElement("ports"); - if(sub_ele != nullptr) { - + if (sub_ele != nullptr) { text = sub_ele->Attribute("low"); - if (text) - ZonePortLow=atoi(text);; - + if (text) { + ZonePortLow = atoi(text); + }; text = sub_ele->Attribute("high"); - if (text) - ZonePortHigh=atoi(text); + if (text) { + ZonePortHigh = atoi(text); + } } } -void EQEmuConfig::do_files(TiXmlElement *ele) { +void EQEmuConfig::do_files(TiXmlElement *ele) +{ const char *text; - - text=ParseTextBlock(ele,"spells",true); - if (text) - SpellsFile=text; - - text=ParseTextBlock(ele,"opcodes",true); - if (text) - OpCodesFile=text; - - text=ParseTextBlock(ele,"logsettings",true); - if (text) - LogSettingsFile=text; - - text=ParseTextBlock(ele,"eqtime",true); - if (text) - EQTimeFile=text; + text = ParseTextBlock(ele, "spells", true); + if (text) { + SpellsFile = text; + } + text = ParseTextBlock(ele, "opcodes", true); + if (text) { + OpCodesFile = text; + } + text = ParseTextBlock(ele, "eqtime", true); + if (text) { + EQTimeFile = text; + } } -void EQEmuConfig::do_directories(TiXmlElement *ele) { +void EQEmuConfig::do_directories(TiXmlElement *ele) +{ const char *text; - - text=ParseTextBlock(ele,"maps",true); - if (text) - MapDir=text; - - text=ParseTextBlock(ele,"quests",true); - if (text) - QuestDir=text; - - text=ParseTextBlock(ele,"plugins",true); - if (text) - PluginDir=text; - + text = ParseTextBlock(ele, "maps", true); + if (text) { + MapDir = text; + } + text = ParseTextBlock(ele, "quests", true); + if (text) { + QuestDir = text; + } + text = ParseTextBlock(ele, "plugins", true); + if (text) { + PluginDir = text; + } } -void EQEmuConfig::do_launcher(TiXmlElement *ele) { +void EQEmuConfig::do_launcher(TiXmlElement *ele) +{ const char *text; TiXmlElement *sub_ele; - - text=ParseTextBlock(ele,"logprefix",true); - if (text) + text = ParseTextBlock(ele, "logprefix", true); + if (text) { LogPrefix = text; - - text=ParseTextBlock(ele,"logsuffix",true); - if (text) + } + text = ParseTextBlock(ele, "logsuffix", true); + if (text) { LogSuffix = text; - + } // Get the element - text = ParseTextBlock(ele,"exe",true); - if (text) + text = ParseTextBlock(ele, "exe", true); + if (text) { ZoneExe = text; - + } // Get the element sub_ele = ele->FirstChildElement("timers"); - if(sub_ele != nullptr) { + if (sub_ele != nullptr) { text = sub_ele->Attribute("restart"); - if (text) + if (text) { RestartWait = atoi(text); - + } text = sub_ele->Attribute("reterminate"); - if (text) + if (text) { TerminateWait = atoi(text); - + } text = sub_ele->Attribute("initial"); - if (text) + if (text) { InitialBootWait = atoi(text); - + } text = sub_ele->Attribute("interval"); - if (text) + if (text) { ZoneBootInterval = atoi(text); + } } } -std::string EQEmuConfig::GetByName(const std::string &var_name) const { - if(var_name == "ShortName") - return(ShortName); - if(var_name == "LongName") - return(LongName); - if(var_name == "WorldAddress") - return(WorldAddress); - if(var_name == "LoginHost") - return(LoginHost); - if(var_name == "LoginAccount") - return(LoginAccount); - if(var_name == "LoginPassword") - return(LoginPassword); - if(var_name == "LoginPort") - return(itoa(LoginPort)); - if(var_name == "Locked") - return(Locked?"true":"false"); - if(var_name == "WorldTCPPort") - return(itoa(WorldTCPPort)); - if(var_name == "WorldIP") - return(WorldIP); - if(var_name == "TelnetEnabled") - return(TelnetEnabled?"true":"false"); - if(var_name == "WorldHTTPPort") - return(itoa(WorldHTTPPort)); - if(var_name == "WorldHTTPMimeFile") - return(WorldHTTPMimeFile); - if(var_name == "WorldHTTPEnabled") - return(WorldHTTPEnabled?"true":"false"); - if(var_name == "ChatHost") - return(ChatHost); - if(var_name == "ChatPort") - return(itoa(ChatPort)); - if(var_name == "MailHost") - return(MailHost); - if(var_name == "MailPort") - return(itoa(MailPort)); - if(var_name == "DatabaseHost") - return(DatabaseHost); - if(var_name == "DatabaseUsername") - return(DatabaseUsername); - if(var_name == "DatabasePassword") - return(DatabasePassword); - if(var_name == "DatabaseDB") - return(DatabaseDB); - if(var_name == "DatabasePort") - return(itoa(DatabasePort)); - if(var_name == "QSDatabaseHost") - return(QSDatabaseHost); - if(var_name == "QSDatabaseUsername") - return(QSDatabaseUsername); - if(var_name == "QSDatabasePassword") - return(QSDatabasePassword); - if(var_name == "QSDatabaseDB") - return(QSDatabaseDB); - if(var_name == "QSDatabasePort") - return(itoa(QSDatabasePort)); - if(var_name == "SpellsFile") - return(SpellsFile); - if(var_name == "OpCodesFile") - return(OpCodesFile); - if(var_name == "EQTimeFile") - return(EQTimeFile); - if(var_name == "LogSettingsFile") - return(LogSettingsFile); - if(var_name == "MapDir") - return(MapDir); - if(var_name == "QuestDir") - return(QuestDir); - if(var_name == "PluginDir") - return(PluginDir); - if(var_name == "LogPrefix") - return(LogPrefix); - if(var_name == "LogSuffix") - return(LogSuffix); - if(var_name == "ZoneExe") - return(ZoneExe); - if(var_name == "ZonePortLow") - return(itoa(ZonePortLow)); - if(var_name == "ZonePortHigh") - return(itoa(ZonePortHigh)); - if(var_name == "DefaultStatus") - return(itoa(DefaultStatus)); +std::string EQEmuConfig::GetByName(const std::string &var_name) const +{ + if (var_name == "ShortName") { + return (ShortName); + } + if (var_name == "LongName") { + return (LongName); + } + if (var_name == "WorldAddress") { + return (WorldAddress); + } + if (var_name == "LoginHost") { + return (LoginHost); + } + if (var_name == "LoginAccount") { + return (LoginAccount); + } + if (var_name == "LoginPassword") { + return (LoginPassword); + } + if (var_name == "LoginPort") { + return (itoa(LoginPort)); + } + if (var_name == "Locked") { + return (Locked ? "true" : "false"); + } + if (var_name == "WorldTCPPort") { + return (itoa(WorldTCPPort)); + } + if (var_name == "WorldIP") { + return (WorldIP); + } + if (var_name == "TelnetEnabled") { + return (TelnetEnabled ? "true" : "false"); + } + if (var_name == "WorldHTTPPort") { + return (itoa(WorldHTTPPort)); + } + if (var_name == "WorldHTTPMimeFile") { + return (WorldHTTPMimeFile); + } + if (var_name == "WorldHTTPEnabled") { + return (WorldHTTPEnabled ? "true" : "false"); + } + if (var_name == "ChatHost") { + return (ChatHost); + } + if (var_name == "ChatPort") { + return (itoa(ChatPort)); + } + if (var_name == "MailHost") { + return (MailHost); + } + if (var_name == "MailPort") { + return (itoa(MailPort)); + } + if (var_name == "DatabaseHost") { + return (DatabaseHost); + } + if (var_name == "DatabaseUsername") { + return (DatabaseUsername); + } + if (var_name == "DatabasePassword") { + return (DatabasePassword); + } + if (var_name == "DatabaseDB") { + return (DatabaseDB); + } + if (var_name == "DatabasePort") { + return (itoa(DatabasePort)); + } + if (var_name == "QSDatabaseHost") { + return (QSDatabaseHost); + } + if (var_name == "QSDatabaseUsername") { + return (QSDatabaseUsername); + } + if (var_name == "QSDatabasePassword") { + return (QSDatabasePassword); + } + if (var_name == "QSDatabaseDB") { + return (QSDatabaseDB); + } + if (var_name == "QSDatabasePort") { + return (itoa(QSDatabasePort)); + } + if (var_name == "SpellsFile") { + return (SpellsFile); + } + if (var_name == "OpCodesFile") { + return (OpCodesFile); + } + if (var_name == "EQTimeFile") { + return (EQTimeFile); + } + if (var_name == "MapDir") { + return (MapDir); + } + if (var_name == "QuestDir") { + return (QuestDir); + } + if (var_name == "PluginDir") { + return (PluginDir); + } + if (var_name == "LogPrefix") { + return (LogPrefix); + } + if (var_name == "LogSuffix") { + return (LogSuffix); + } + if (var_name == "ZoneExe") { + return (ZoneExe); + } + if (var_name == "ZonePortLow") { + return (itoa(ZonePortLow)); + } + if (var_name == "ZonePortHigh") { + return (itoa(ZonePortHigh)); + } + if (var_name == "DefaultStatus") { + return (itoa(DefaultStatus)); + } // if(var_name == "DynamicCount") // return(itoa(DynamicCount)); - return(""); + return (""); } void EQEmuConfig::Dump() const @@ -436,7 +476,6 @@ void EQEmuConfig::Dump() const std::cout << "SpellsFile = " << SpellsFile << std::endl; std::cout << "OpCodesFile = " << OpCodesFile << std::endl; std::cout << "EQTimeFile = " << EQTimeFile << std::endl; - std::cout << "LogSettingsFile = " << LogSettingsFile << std::endl; std::cout << "MapDir = " << MapDir << std::endl; std::cout << "QuestDir = " << QuestDir << std::endl; std::cout << "PluginDir = " << PluginDir << std::endl; diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 9fa21bea6..1ad2174dc 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* EQEMu: Everquest Server Emulator Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) This program is free software; you can redistribute it and/or modify @@ -28,200 +28,190 @@ struct LoginConfig { uint16 LoginPort; }; -class EQEmuConfig : public XMLParser { -public: - virtual std::string GetByName(const std::string &var_name) const; +class EQEmuConfig : public XMLParser +{ + public: + virtual std::string GetByName(const std::string &var_name) const; - // From - std::string ShortName; - std::string LongName; - std::string WorldAddress; - std::string LocalAddress; - std::string LoginHost; - std::string LoginAccount; - std::string LoginPassword; - uint16 LoginPort; - uint32 LoginCount; - LinkedList loginlist; - bool Locked; - uint16 WorldTCPPort; - std::string WorldIP; - bool TelnetEnabled; - int32 MaxClients; - bool WorldHTTPEnabled; - uint16 WorldHTTPPort; - std::string WorldHTTPMimeFile; - std::string SharedKey; + // From + std::string ShortName; + std::string LongName; + std::string WorldAddress; + std::string LocalAddress; + std::string LoginHost; + std::string LoginAccount; + std::string LoginPassword; + uint16 LoginPort; + uint32 LoginCount; + LinkedList loginlist; + bool Locked; + uint16 WorldTCPPort; + std::string WorldIP; + bool TelnetEnabled; + int32 MaxClients; + bool WorldHTTPEnabled; + uint16 WorldHTTPPort; + std::string WorldHTTPMimeFile; + std::string SharedKey; - // From - std::string ChatHost; - uint16 ChatPort; + // From + std::string ChatHost; + uint16 ChatPort; - // From - std::string MailHost; - uint16 MailPort; + // From + std::string MailHost; + uint16 MailPort; - // From - std::string DatabaseHost; - std::string DatabaseUsername; - std::string DatabasePassword; - std::string DatabaseDB; - uint16 DatabasePort; + // From + std::string DatabaseHost; + std::string DatabaseUsername; + std::string DatabasePassword; + std::string DatabaseDB; + uint16 DatabasePort; - // From // QueryServ - std::string QSDatabaseHost; - std::string QSDatabaseUsername; - std::string QSDatabasePassword; - std::string QSDatabaseDB; - uint16 QSDatabasePort; + // From // QueryServ + std::string QSDatabaseHost; + std::string QSDatabaseUsername; + std::string QSDatabasePassword; + std::string QSDatabaseDB; + uint16 QSDatabasePort; - // From - std::string SpellsFile; - std::string OpCodesFile; - std::string EQTimeFile; - std::string LogSettingsFile; + // From + std::string SpellsFile; + std::string OpCodesFile; + std::string EQTimeFile; - // From - std::string MapDir; - std::string QuestDir; - std::string PluginDir; + // From + std::string MapDir; + std::string QuestDir; + std::string PluginDir; - // From - std::string LogPrefix; - std::string LogSuffix; - std::string ZoneExe; - uint32 RestartWait; - uint32 TerminateWait; - uint32 InitialBootWait; - uint32 ZoneBootInterval; + // From + std::string LogPrefix; + std::string LogSuffix; + std::string ZoneExe; + uint32 RestartWait; + uint32 TerminateWait; + uint32 InitialBootWait; + uint32 ZoneBootInterval; - // From - uint16 ZonePortLow; - uint16 ZonePortHigh; - uint8 DefaultStatus; + // From + uint16 ZonePortLow; + uint16 ZonePortHigh; + uint8 DefaultStatus; // uint16 DynamicCount; // map StaticZones; -protected: + protected: - static EQEmuConfig *_config; + static EQEmuConfig *_config; - static std::string ConfigFile; + static std::string ConfigFile; #define ELEMENT(name) \ void do_##name(TiXmlElement *ele); - #include "eqemu_config_elements.h" +#include "eqemu_config_elements.h" - EQEmuConfig() { - // import the needed handler prototypes + EQEmuConfig() + { + // import the needed handler prototypes #define ELEMENT(name) \ - Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name; - #include "eqemu_config_elements.h" + Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name; +#include "eqemu_config_elements.h" + // Set sane defaults + // Login server + LoginHost = "eqemulator.net"; + LoginPort = 5998; + // World + Locked = false; + WorldTCPPort = 9000; + TelnetEnabled = false; + WorldHTTPEnabled = false; + WorldHTTPPort = 9080; + WorldHTTPMimeFile = "mime.types"; + SharedKey = ""; //blank disables authentication + // Mail + ChatHost = "eqchat.eqemulator.net"; + ChatPort = 7778; + // Mail + MailHost = "eqmail.eqemulator.net"; + MailPort = 7779; + // Mysql + DatabaseHost = "localhost"; + DatabasePort = 3306; + DatabaseUsername = "eq"; + DatabasePassword = "eq"; + DatabaseDB = "eq"; + // QueryServ Database + QSDatabaseHost = "localhost"; + QSDatabasePort = 3306; + QSDatabaseUsername = "eq"; + QSDatabasePassword = "eq"; + QSDatabaseDB = "eq"; + // Files + SpellsFile = "spells_us.txt"; + OpCodesFile = "opcodes.conf"; + EQTimeFile = "eqtime.cfg"; + // Dirs + MapDir = "Maps"; + QuestDir = "quests"; + PluginDir = "plugins"; + // Launcher + LogPrefix = "logs/zone-"; + LogSuffix = ".log"; + RestartWait = 10000; //milliseconds + TerminateWait = 10000; //milliseconds + InitialBootWait = 20000; //milliseconds + ZoneBootInterval = 2000; //milliseconds + #ifdef WIN32 + ZoneExe = "zone.exe"; + #else + ZoneExe = "./zone"; + #endif + // Zones + ZonePortLow = 7000; + ZonePortHigh = 7999; + DefaultStatus = 0; + // For where zones need to connect to. + WorldIP = "127.0.0.1"; + // Dynamics to start + //DynamicCount=5; + MaxClients = -1; + LoginCount = 0; + } + virtual ~EQEmuConfig() {} - // Set sane defaults + public: - // Login server - LoginHost="eqemulator.net"; - LoginPort=5998; + // Produce a const singleton + static const EQEmuConfig *get() + { + if (_config == nullptr) { + LoadConfig(); + } + return (_config); + } - // World - Locked=false; - WorldTCPPort=9000; - TelnetEnabled=false; - WorldHTTPEnabled=false; - WorldHTTPPort=9080; - WorldHTTPMimeFile="mime.types"; - SharedKey = ""; //blank disables authentication + // Allow the use to set the conf file to be used. + static void SetConfigFile(std::string file) + { + EQEmuConfig::ConfigFile = file; + } - // Mail - ChatHost="eqchat.eqemulator.net"; - ChatPort=7778; + // Load the config + static bool LoadConfig() + { + if (_config != nullptr) { + delete _config; + } + _config = new EQEmuConfig; + return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(), "server"); + } - // Mail - MailHost="eqmail.eqemulator.net"; - MailPort=7779; - - // Mysql - DatabaseHost="localhost"; - DatabasePort=3306; - DatabaseUsername="eq"; - DatabasePassword="eq"; - DatabaseDB="eq"; - - // QueryServ Database - QSDatabaseHost="localhost"; - QSDatabasePort=3306; - QSDatabaseUsername="eq"; - QSDatabasePassword="eq"; - QSDatabaseDB="eq"; - - // Files - SpellsFile="spells_us.txt"; - OpCodesFile="opcodes.conf"; - EQTimeFile="eqtime.cfg"; - LogSettingsFile="log.ini"; - - // Dirs - MapDir="Maps"; - QuestDir="quests"; - PluginDir="plugins"; - - // Launcher - LogPrefix = "logs/zone-"; - LogSuffix = ".log"; - RestartWait = 10000; //milliseconds - TerminateWait = 10000; //milliseconds - InitialBootWait = 20000; //milliseconds - ZoneBootInterval = 2000; //milliseconds -#ifdef WIN32 - ZoneExe = "zone.exe"; -#else - ZoneExe = "./zone"; -#endif - - // Zones - ZonePortLow=7000; - ZonePortHigh=7999; - DefaultStatus=0; - - // For where zones need to connect to. - WorldIP="127.0.0.1"; - - // Dynamics to start - //DynamicCount=5; - - MaxClients=-1; - - LoginCount=0; - - } - virtual ~EQEmuConfig() {} - -public: - - // Produce a const singleton - static const EQEmuConfig *get() { - if (_config == nullptr) - LoadConfig(); - return(_config); - } - - // Allow the use to set the conf file to be used. - static void SetConfigFile(std::string file) { EQEmuConfig::ConfigFile = file; } - - // Load the config - static bool LoadConfig() { - if (_config != nullptr) - delete _config; - _config=new EQEmuConfig; - - return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); - } - - void Dump() const; + void Dump() const; }; #endif diff --git a/common/eqemu_error.cpp b/common/eqemu_error.cpp deleted file mode 100644 index ff9a7bbd6..000000000 --- a/common/eqemu_error.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 -*/ -#ifdef _WINDOWS -#include -#endif -#include "eqemu_error.h" -#include "linked_list.h" -#include "mutex.h" -#include "misc_functions.h" -#include -#include -#ifdef _WINDOWS - #include -#endif - -void UpdateWindowTitle(char* iNewTitle = 0); -void CatchSignal(int sig_num); - -const char* EQEMuErrorText[EQEMuError_MaxErrorID] = { "ErrorID# 0, No Error", - "MySQL Error #1405 or #2001 means your mysql server rejected the username and password you presented it.", - "MySQL Error #2003 means you were unable to connect to the mysql server.", - "MySQL Error #2005 means you there are too many connections on the mysql server. The server is overloaded.", - "MySQL Error #2007 means you the server is out of memory. The server is overloaded.", - }; - -LinkedList* EQEMuErrorList; -Mutex* MEQEMuErrorList; -AutoDelete< LinkedList > ADEQEMuErrorList(&EQEMuErrorList); -AutoDelete ADMEQEMuErrorList(&MEQEMuErrorList); - -const char* GetErrorText(uint32 iError) { - if (iError >= EQEMuError_MaxErrorID) - return "ErrorID# out of range"; - else - return EQEMuErrorText[iError]; -} - -void AddEQEMuError(eEQEMuError iError, bool iExitNow) { - if (!iError) - return; - if (!EQEMuErrorList) { - EQEMuErrorList = new LinkedList; - MEQEMuErrorList = new Mutex; - } - LockMutex lock(MEQEMuErrorList); - - LinkedListIterator iterator(*EQEMuErrorList); - iterator.Reset(); - while (iterator.MoreElements()) { - if (iterator.GetData()[0] == 1) { -//Umm... this gets a big WTF... -// if (*((uint32*) iterator.GetData()[1]) == iError) -//not sure whats going on, using a character as a pointer.... - if (*((eEQEMuError*) &(iterator.GetData()[1])) == iError) - return; - } - iterator.Advance(); - } - - char* tmp = new char[6]; - tmp[0] = 1; - tmp[5] = 0; - *((uint32*) &tmp[1]) = iError; - EQEMuErrorList->Append(tmp); - - if (iExitNow) - CatchSignal(2); -} - -void AddEQEMuError(char* iError, bool iExitNow) { - if (!iError) - return; - if (!EQEMuErrorList) { - EQEMuErrorList = new LinkedList; - MEQEMuErrorList = new Mutex; - } - LockMutex lock(MEQEMuErrorList); - char* tmp = strcpy(new char[strlen(iError) + 1], iError); - EQEMuErrorList->Append(tmp); - - if (iExitNow) - CatchSignal(2); -} - -uint32 CheckEQEMuError() { - if (!EQEMuErrorList) - return 0; - uint32 ret = 0; - char* tmp = 0; - bool HeaderPrinted = false; - LockMutex lock(MEQEMuErrorList); - - while ((tmp = EQEMuErrorList->Pop() )) { - if (!HeaderPrinted) { - fprintf(stdout, "===============================\nRuntime errors:\n\n"); - HeaderPrinted = true; - } - if (tmp[0] == 1) { - fprintf(stdout, "%s\n", GetErrorText(*((uint32*) &tmp[1]))); - fprintf(stdout, "For more information on this error, visit http://www.eqemu.net/eqemuerror.php?id=%u\n\n", *((uint32*) &tmp[1])); - } - else { - fprintf(stdout, "%s\n\n", tmp); - } - safe_delete(tmp); - ret++; - } - return ret; -} - -void CheckEQEMuErrorAndPause() { -#ifdef _WINDOWS - if (CheckEQEMuError()) { - fprintf(stdout, "Hit any key to exit\n"); - UpdateWindowTitle("Error"); - getch(); - } -#endif -} - diff --git a/common/eqemu_error.h b/common/eqemu_error.h deleted file mode 100644 index ffc5d69ed..000000000 --- a/common/eqemu_error.h +++ /dev/null @@ -1,36 +0,0 @@ -/* EQEMu: Everquest Server Emulator - Copyright (C) 2001-2006 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 EQEMuError_H -#define EQEMuError_H - -#include "../common/types.h" - -enum eEQEMuError { EQEMuError_NoError, - EQEMuError_Mysql_1405, - EQEMuError_Mysql_2003, - EQEMuError_Mysql_2005, - EQEMuError_Mysql_2007, - EQEMuError_MaxErrorID }; - -void AddEQEMuError(eEQEMuError iError, bool iExitNow = false); -void AddEQEMuError(char* iError, bool iExitNow = false); -uint32 CheckEQEMuError(); -void CheckEQEMuErrorAndPause(); - -#endif - diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp new file mode 100644 index 000000000..36176c399 --- /dev/null +++ b/common/eqemu_logsys.cpp @@ -0,0 +1,350 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 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 +*/ + + +#include "eqemu_logsys.h" +#include "platform.h" +#include "string_util.h" +#include "database.h" +#include "misc.h" + +#include +#include +#include +#include +#include +#include + +std::ofstream process_log; + +#ifdef _WINDOWS + #include + #include + #include + #include + #include + #include +#else + #include + #include +#endif + +/* Linux ANSI console color defines */ +#define LC_RESET "\033[0m" +#define LC_BLACK "\033[30m" /* Black */ +#define LC_RED "\033[31m" /* Red */ +#define LC_GREEN "\033[32m" /* Green */ +#define LC_YELLOW "\033[33m" /* Yellow */ +#define LC_BLUE "\033[34m" /* Blue */ +#define LC_MAGENTA "\033[35m" /* Magenta */ +#define LC_CYAN "\033[36m" /* Cyan */ +#define LC_WHITE "\033[37m" /* White */ + +namespace Console { + enum Color { + Black = 0, + Blue = 1, + Green = 2, + Cyan = 3, + Red = 4, + Magenta = 5, + Brown = 6, + LightGray = 7, + DarkGray = 8, + LightBlue = 9, + LightGreen = 10, + LightCyan = 11, + LightRed = 12, + LightMagenta = 13, + Yellow = 14, + White = 15 + }; +} + +EQEmuLogSys::EQEmuLogSys() +{ + on_log_gmsay_hook = [](uint16 log_type, const std::string&) {}; + bool file_logs_enabled = false; + int log_platform = 0; +} + +EQEmuLogSys::~EQEmuLogSys() +{ +} + +void EQEmuLogSys::LoadLogSettingsDefaults() +{ + /* Get Executable platform currently running this code (Zone/World/etc) */ + log_platform = GetExecutablePlatformInt(); + + /* Zero out Array */ + memset(log_settings, 0, sizeof(LogSettings) * Logs::LogCategory::MaxCategoryID); + + /* Set Defaults */ + log_settings[Logs::World_Server].log_to_console = Logs::General; + log_settings[Logs::Zone_Server].log_to_console = Logs::General; + log_settings[Logs::QS_Server].log_to_console = Logs::General; + log_settings[Logs::UCS_Server].log_to_console = Logs::General; + log_settings[Logs::Crash].log_to_console = Logs::General; + log_settings[Logs::MySQLError].log_to_console = Logs::General; + + /* Declare process file names for log writing + If there is no process_file_name declared, no log file will be written, simply + */ + if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld) + platform_file_name = "world"; + else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformQueryServ) + platform_file_name = "query_server"; + else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) + platform_file_name = "zone"; + else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformUCS) + platform_file_name = "ucs"; + else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) + platform_file_name = "login"; + else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin) + platform_file_name = "launcher"; +} + +std::string EQEmuLogSys::FormatOutMessageString(uint16 log_category, const std::string &in_message) +{ + std::string category_string; + if (log_category > 0 && Logs::LogCategoryName[log_category]) + category_string = StringFormat("[%s] ", Logs::LogCategoryName[log_category]); + return StringFormat("%s%s", category_string.c_str(), in_message.c_str()); +} + +void EQEmuLogSys::ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message) +{ + /* Check if category enabled for process */ + if (log_settings[log_category].log_to_gmsay == 0) + return; + + /* Enabling Netcode based GMSay output creates a feedback loop that ultimately ends in a crash */ + if (log_category == Logs::LogCategory::Netcode) + return; + + /* Make sure the message inbound is at a debug level we're set at */ + if (log_settings[log_category].log_to_gmsay < debug_level) + return; + + /* Check to see if the process that actually ran this is zone */ + if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) + on_log_gmsay_hook(log_category, message); +} + +void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message) +{ + if (log_category == Logs::Crash) { + char time_stamp[80]; + EQEmuLogSys::SetCurrentTimeStamp(time_stamp); + std::ofstream crash_log; + EQEmuLogSys::MakeDirectory("logs/crashes"); + crash_log.open(StringFormat("logs/crashes/crash_%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out); + crash_log << time_stamp << " " << message << "\n"; + crash_log.close(); + } + + /* Check if category enabled for process */ + if (log_settings[log_category].log_to_file == 0) + return; + + /* Make sure the message inbound is at a debug level we're set at */ + if (log_settings[log_category].log_to_file < debug_level) + return; + + char time_stamp[80]; + EQEmuLogSys::SetCurrentTimeStamp(time_stamp); + + if (process_log) + process_log << time_stamp << " " << message << std::endl; +} + +uint16 EQEmuLogSys::GetWindowsConsoleColorFromCategory(uint16 log_category) { + switch (log_category) { + case Logs::Status: + case Logs::Normal: + return Console::Color::Yellow; + case Logs::MySQLError: + case Logs::Error: + return Console::Color::LightRed; + case Logs::MySQLQuery: + case Logs::Debug: + return Console::Color::LightGreen; + case Logs::Quests: + return Console::Color::LightCyan; + case Logs::Commands: + case Logs::Mercenaries: + return Console::Color::LightMagenta; + case Logs::Crash: + return Console::Color::LightRed; + default: + return Console::Color::Yellow; + } +} + +std::string EQEmuLogSys::GetLinuxConsoleColorFromCategory(uint16 log_category) { + switch (log_category) { + case Logs::Status: + case Logs::Normal: + return LC_YELLOW; + case Logs::MySQLError: + case Logs::Error: + return LC_RED; + case Logs::MySQLQuery: + case Logs::Debug: + return LC_GREEN; + case Logs::Quests: + return LC_CYAN; + case Logs::Commands: + case Logs::Mercenaries: + return LC_MAGENTA; + case Logs::Crash: + return LC_RED; + default: + return LC_YELLOW; + } +} + +uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) { + switch (log_category) { + case Logs::Status: + case Logs::Normal: + return 15; /* Yellow */ + case Logs::MySQLError: + case Logs::Error: + return 13; /* Red */ + case Logs::MySQLQuery: + case Logs::Debug: + return 14; /* Light Green */ + case Logs::Quests: + return 258; /* Light Cyan */ + case Logs::Commands: + case Logs::Mercenaries: + return 5; /* Light Purple */ + case Logs::Crash: + return 13; /* Red */ + default: + return 15; /* Yellow */ + } +} + +void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message) +{ + /* Check if category enabled for process */ + if (log_settings[log_category].log_to_console == 0) + return; + + /* Make sure the message inbound is at a debug level we're set at */ + if (log_settings[log_category].log_to_console < debug_level) + return; + + #ifdef _WINDOWS + HANDLE console_handle; + console_handle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_FONT_INFOEX info = { 0 }; + info.cbSize = sizeof(info); + info.dwFontSize.Y = 12; // leave X as zero + info.FontWeight = FW_NORMAL; + wcscpy(info.FaceName, L"Lucida Console"); + SetCurrentConsoleFontEx(console_handle, NULL, &info); + SetConsoleTextAttribute(console_handle, EQEmuLogSys::GetWindowsConsoleColorFromCategory(log_category)); + std::cout << message << "\n"; + SetConsoleTextAttribute(console_handle, Console::Color::White); + #else + std::cout << EQEmuLogSys::GetLinuxConsoleColorFromCategory(log_category) << message << LC_RESET << std::endl; + #endif +} + +void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...) +{ + const bool log_to_console = log_settings[log_category].log_to_console > 0; + const bool log_to_file = log_settings[log_category].log_to_file > 0; + const bool log_to_gmsay = log_settings[log_category].log_to_gmsay > 0; + const bool nothing_to_log = !log_to_console && !log_to_file && !log_to_gmsay; + + if (nothing_to_log) return; + + va_list args; + va_start(args, message); + std::string output_message = vStringFormat(message.c_str(), args); + va_end(args); + + std::string output_debug_message = EQEmuLogSys::FormatOutMessageString(log_category, output_message); + + if (log_to_console) EQEmuLogSys::ProcessConsoleMessage(debug_level, log_category, output_debug_message); + if (log_to_gmsay) EQEmuLogSys::ProcessGMSay(debug_level, log_category, output_debug_message); + if (log_to_file) EQEmuLogSys::ProcessLogWrite(debug_level, log_category, output_debug_message); +} + +void EQEmuLogSys::SetCurrentTimeStamp(char* time_stamp) +{ + time_t raw_time; + struct tm * time_info; + time(&raw_time); + time_info = localtime(&raw_time); + strftime(time_stamp, 80, "[%m-%d-%Y :: %H:%M:%S]", time_info); +} + +void EQEmuLogSys::MakeDirectory(const std::string &directory_name) +{ +#ifdef _WINDOWS + struct _stat st; + if (_stat(directory_name.c_str(), &st) == 0) // exists + return; + _mkdir(directory_name.c_str()); +#else + struct stat st; + if (stat(directory_name.c_str(), &st) == 0) // exists + return; + mkdir(directory_name.c_str(), 0755); +#endif +} + +void EQEmuLogSys::CloseFileLogs() +{ + if (process_log.is_open()) { + process_log.close(); + } +} + +void EQEmuLogSys::StartFileLogs(const std::string &log_name) +{ + EQEmuLogSys::CloseFileLogs(); + + /* When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... */ + if (file_logs_enabled == false) + return; + + if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone) { + if (!log_name.empty()) + platform_file_name = log_name; + + if (platform_file_name.empty()) + return; + + EQEmuLogSys::Out(Logs::General, Logs::Status, "Starting File Log 'logs/%s_%i.log'", platform_file_name.c_str(), getpid()); + EQEmuLogSys::MakeDirectory("logs/zone"); + process_log.open(StringFormat("logs/zone/%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out); + } else { + if (platform_file_name.empty()) + return; + + EQEmuLogSys::Out(Logs::General, Logs::Status, "Starting File Log 'logs/%s_%i.log'", platform_file_name.c_str(), getpid()); + process_log.open(StringFormat("logs/%s_%i.log", platform_file_name.c_str(), getpid()), std::ios_base::app | std::ios_base::out); + } +} diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h new file mode 100644 index 000000000..a99b3b439 --- /dev/null +++ b/common/eqemu_logsys.h @@ -0,0 +1,204 @@ +/* EQEMu: Everquest Server Emulator + Copyright (C) 2001-2015 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 EQEMU_LOGSYS_H +#define EQEMU_LOGSYS_H + +#include +#include +#include +#include + +#include "types.h" + +namespace Logs { + enum DebugLevel { + General = 1, /* 1 - Low-Level general debugging, useful info on single line */ + Moderate, /* 2 - Informational based, used in functions, when particular things load */ + Detail /* 3 - Use this for extreme detail in logging, usually in extreme debugging in the stack or interprocess communication */ + }; + + /* + If you add to this, make sure you update LogCategoryName + NOTE: Only add to the bottom of the enum because that is the type ID assignment + */ + + enum LogCategory { + None = 0, + AA, + AI, + Aggro, + Attack, + Client_Server_Packet, + Combat, + Commands, + Crash, + Debug, + Doors, + Error, + Guilds, + Inventory, + Launcher, + Netcode, + Normal, + Object, + Pathing, + QS_Server, + Quests, + Rules, + Skills, + Spawns, + Spells, + Status, + TCP_Connection, + Tasks, + Tradeskills, + Trading, + Tribute, + UCS_Server, + WebInterface_Server, + World_Server, + Zone_Server, + MySQLError, + MySQLQuery, + Mercenaries, + QuestDebug, + Server_Client_Packet, + Client_Server_Packet_Unhandled, + Server_Client_Packet_With_Dump, + Client_Server_Packet_With_Dump, + MaxCategoryID /* Don't Remove this*/ + }; + + /* If you add to this, make sure you update LogCategory */ + static const char* LogCategoryName[LogCategory::MaxCategoryID] = { + "", + "AA", + "AI", + "Aggro", + "Attack", + "Packet :: Client -> Server", + "Combat", + "Commands", + "Crash", + "Debug", + "Doors", + "Error", + "Guilds", + "Inventory", + "Launcher", + "Netcode", + "Normal", + "Object", + "Pathing", + "QS Server", + "Quests", + "Rules", + "Skills", + "Spawns", + "Spells", + "Status", + "TCP Connection", + "Tasks", + "Tradeskills", + "Trading", + "Tribute", + "UCS Server", + "WebInterface Server", + "World Server", + "Zone Server", + "MySQL Error", + "MySQL Query", + "Mercenaries", + "Quest Debug", + "Packet :: Server -> Client", + "Packet :: Client -> Server Unhandled", + "Packet :: Server -> Client (Dump)", + "Packet :: Client -> Server (Dump)", + }; +} + +class EQEmuLogSys { +public: + EQEmuLogSys(); + ~EQEmuLogSys(); + + void CloseFileLogs(); /* Close File Logs wherever necessary, either at zone shutdown or entire process shutdown for everything else. This should be handled on deconstructor but to be safe we use it anyways. */ + void LoadLogSettingsDefaults(); /* Initializes log_settings and sets some defaults if DB is not present */ + void MakeDirectory(const std::string &directory_name); /* Platform independent way of performing a MakeDirectory based on name */ + /* + The one and only Logging function that uses a debug level as a parameter, as well as a log_category + log_category - defined in Logs::LogCategory::[] + log_category name resolution works by passing the enum int ID to Logs::LogCategoryName[category_id] + + Example: EQEmuLogSys::Out(Logs::General, Logs::Guilds, "This guild has no leader present"); + - This would pipe the same category and debug level to all output formats, but the internal memory reference of log_settings would + be checked against to see if that piped output is set to actually process it for the category and debug level + */ + void Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...); + void SetCurrentTimeStamp(char* time_stamp); /* Used in file logs to prepend a timestamp entry for logs */ + void StartFileLogs(const std::string &log_name = ""); /* Used to declare the processes file log and to keep it open for later use */ + + /* + LogSettings Struct + + This struct is the master reference for all settings for each category, and for each output + + log_to_file[category_id] = [1-3] - Sets debug level for category to output to file + log_to_console[category_id] = [1-3] - Sets debug level for category to output to console + log_to_gmsay[category_id] = [1-3] - Sets debug level for category to output to gmsay + */ + + struct LogSettings { + uint8 log_to_file; + uint8 log_to_console; + uint8 log_to_gmsay; + uint8 is_category_enabled; /* When any log output in a category > 0, set this to 1 as (Enabled) */ + }; + + /* Internally used memory reference for all log settings per category. + These are loaded via DB and have defaults loaded in LoadLogSettingsDefaults. + Database loaded via Database::LoadLogSettings(log_settings) + */ + LogSettings log_settings[Logs::LogCategory::MaxCategoryID]; + + bool file_logs_enabled; /* Set when log settings are loaded to determine if keeping a file open is necessary */ + + int log_platform; /* Sets Executable platform (Zone/World/UCS) etc. */ + + std::string platform_file_name; /* File name used in writing logs */ + + uint16 GetGMSayColorFromCategory(uint16 log_category); /* GMSay Client Message colors mapped by category */ + + void OnLogHookCallBackZone(std::function f) { on_log_gmsay_hook = f; } + +private: + std::function on_log_gmsay_hook; /* Callback pointer to zone process for hooking logs to zone using GMSay */ + std::string FormatOutMessageString(uint16 log_category, const std::string &in_message); /* Formats log messages like '[Category] This is a log message' */ + std::string GetLinuxConsoleColorFromCategory(uint16 log_category); /* Linux console color messages mapped by category */ + + uint16 GetWindowsConsoleColorFromCategory(uint16 log_category); /* Windows console color messages mapped by category */ + + void ProcessConsoleMessage(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessConsoleMessage called via Log.Out */ + void ProcessGMSay(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessGMSay called via Log.Out */ + void ProcessLogWrite(uint16 debug_level, uint16 log_category, const std::string &message); /* ProcessLogWrite called via Log.Out */ +}; + +extern EQEmuLogSys Log; + +#endif diff --git a/common/eqtime.cpp b/common/eqtime.cpp index 7e1eb9f5d..79301a28f 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -17,7 +17,8 @@ */ #include -#include "../common/debug.h" +#include "../common/global_define.h" +#include "../common/eqemu_logsys.h" #include "../common/eqtime.h" #include "../common/eq_packet_structs.h" #include @@ -140,11 +141,10 @@ bool EQTime::saveFile(const char *filename) of.open(filename); if(!of) { - LogFile->write(EQEMuLog::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename); + Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename); return false; } //Enable for debugging - //std::cout << "SAVE: day=" << (long)eqTime.start_eqtime.day << ";hour=" << (long)eqTime.start_eqtime.hour << ";min=" << (long)eqTime.start_eqtime.minute << ";mon=" << (long)eqTime.start_eqtime.month << ";yr=" << eqTime.start_eqtime.year << ";timet=" << eqTime.start_realtime << std::endl; of << EQT_VERSION << std::endl; of << (long)eqTime.start_eqtime.day << std::endl; of << (long)eqTime.start_eqtime.hour << std::endl; @@ -164,14 +164,14 @@ bool EQTime::loadFile(const char *filename) in.open(filename); if(!in) { - LogFile->write(EQEMuLog::Error, "Could not load EQTime file %s", filename); + Log.Out(Logs::General, Logs::Error, "Could not load EQTime file %s", filename); return false; } in >> version; in.ignore(80, '\n'); if(version != EQT_VERSION) { - LogFile->write(EQEMuLog::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION); + Log.Out(Logs::General, Logs::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION); return false; } //in >> eqTime.start_eqtime.day; @@ -194,7 +194,6 @@ bool EQTime::loadFile(const char *filename) in.ignore(80, '\n'); in >> eqTime.start_realtime; //Enable for debugging... - //std::cout << "LOAD: day=" << (long)eqTime.start_eqtime.day << ";hour=" << (long)eqTime.start_eqtime.hour << ";min=" << (long)eqTime.start_eqtime.minute << ";mon=" << (long)eqTime.start_eqtime.month << ";yr=" << eqTime.start_eqtime.year << ";timet=" << eqTime.start_realtime << std::endl; in.close(); return true; } diff --git a/common/extprofile.cpp b/common/extprofile.cpp index 0ea3fb7a1..f29ec1e6e 100644 --- a/common/extprofile.cpp +++ b/common/extprofile.cpp @@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" +#include "global_define.h" #include "extprofile.h" //Set defaults in the extended profile... diff --git a/common/faction.cpp b/common/faction.cpp index 7016f6547..65524f623 100644 --- a/common/faction.cpp +++ b/common/faction.cpp @@ -1,4 +1,4 @@ -/* EQEMu: Everquest Server Emulator +/* 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 @@ -15,39 +15,40 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "debug.h" + #include "faction.h" #include "races.h" -const char *FactionValueToString(FACTION_VALUE fv) { - switch(fv) { - case FACTION_ALLY: - return("Ally"); - case FACTION_WARMLY: - return("Warmly"); - case FACTION_KINDLY: - return("Kindly"); - case FACTION_AMIABLE: - return("Amiable"); - case FACTION_INDIFFERENT: - return("Indifferent"); - case FACTION_APPREHENSIVE: - return("Apprehensive"); - case FACTION_DUBIOUS: - return("Dubious"); - case FACTION_THREATENLY: - return("Threatenly"); - case FACTION_SCOWLS: - return("Scowls, ready to attack."); - default: - break; +const char *FactionValueToString(FACTION_VALUE fv) +{ + switch (fv) { + case FACTION_ALLY: + return ("Ally"); + case FACTION_WARMLY: + return ("Warmly"); + case FACTION_KINDLY: + return ("Kindly"); + case FACTION_AMIABLE: + return ("Amiable"); + case FACTION_INDIFFERENT: + return ("Indifferent"); + case FACTION_APPREHENSIVE: + return ("Apprehensive"); + case FACTION_DUBIOUS: + return ("Dubious"); + case FACTION_THREATENLY: + return ("Threatenly"); + case FACTION_SCOWLS: + return ("Scowls, ready to attack."); + default: + break; } - return("Unknown Faction Con"); + return ("Unknown Faction Con"); } //o-------------------------------------------------------------- -//| Name: CalculateFaction; rembrant, Dec. 16, 2001 +//| Name: CalculateFaction; Dec. 16, 2001 //o-------------------------------------------------------------- //| Notes: Returns the faction message value. //| Modify these values to taste. @@ -55,86 +56,112 @@ const char *FactionValueToString(FACTION_VALUE fv) { FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value) { int32 character_value = tmpCharacter_value; - if (fm) + if (fm) { character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod; - if(character_value >= 1101) return FACTION_ALLY; - if(character_value >= 701 && character_value <= 1100) return FACTION_WARMLY; - if(character_value >= 401 && character_value <= 700) return FACTION_KINDLY; - if(character_value >= 101 && character_value <= 400) return FACTION_AMIABLE; - if(character_value >= 0 && character_value <= 100) return FACTION_INDIFFERENT; - if(character_value >= -100 && character_value <= -1) return FACTION_APPREHENSIVE; - if(character_value >= -700 && character_value <= -101) return FACTION_DUBIOUS; - if(character_value >= -999 && character_value <= -701) return FACTION_THREATENLY; - if(character_value <= -1000) return FACTION_SCOWLS; + } + if (character_value >= 1101) { + return FACTION_ALLY; + } + if (character_value >= 701 && character_value <= 1100) { + return FACTION_WARMLY; + } + if (character_value >= 401 && character_value <= 700) { + return FACTION_KINDLY; + } + if (character_value >= 101 && character_value <= 400) { + return FACTION_AMIABLE; + } + if (character_value >= 0 && character_value <= 100) { + return FACTION_INDIFFERENT; + } + if (character_value >= -100 && character_value <= -1) { + return FACTION_APPREHENSIVE; + } + if (character_value >= -700 && character_value <= -101) { + return FACTION_DUBIOUS; + } + if (character_value >= -999 && character_value <= -701) { + return FACTION_THREATENLY; + } + if (character_value <= -1000) { + return FACTION_SCOWLS; + } 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) + if (r1 == r2) { return true; + } // TODO: add more values - switch(r1) - { - case DARK_ELF: - if (r2 == 77) - return true; - break; - case BARBARIAN: - if (r2 == 90) - return true; + switch (r1) { + case DARK_ELF: + if (r2 == 77) { + return true; + } + break; + case BARBARIAN: + if (r2 == 90) { + return true; + } } return false; } -// neotokyo: trolls endure ogres, dark elves, ... +// trolls endure ogres, dark elves, ... bool IsOfIndiffRace(int r1, int r2) { - if (r1 == r2) + if (r1 == r2) { return true; + } // TODO: add more values - switch(r1) - { - case DARK_ELF: - case OGRE: - case TROLL: - if (r2 == OGRE || r2 == TROLL || r2 == DARK_ELF) + switch (r1) { + case DARK_ELF: + case OGRE: + case TROLL: + if (r2 == OGRE || r2 == TROLL || r2 == DARK_ELF) { + return true; + } + break; + case HUMAN: + case BARBARIAN: + case HALF_ELF: + case GNOME: + case HALFLING: + case WOOD_ELF: + if (r2 == HUMAN || + r2 == BARBARIAN || + r2 == ERUDITE || + r2 == HALF_ELF || + r2 == GNOME || + r2 == HALFLING || + r2 == DWARF || + r2 == HIGH_ELF || + r2 == WOOD_ELF) { + return true; + } + break; + case ERUDITE: + if (r2 == HUMAN || r2 == HALF_ELF) { + return true; + } + break; + case DWARF: + if (r2 == HALFLING || r2 == GNOME) { + return true; + } + break; + case HIGH_ELF: + if (r2 == WOOD_ELF) { + return true; + } + break; + case VAHSHIR: return true; - break; - case HUMAN: - case BARBARIAN: - case HALF_ELF: - case GNOME: - case HALFLING: - case WOOD_ELF: - if (r2 == HUMAN || - r2 == BARBARIAN || - r2 == ERUDITE || - r2 == HALF_ELF || - r2 == GNOME || - r2 == HALFLING || - r2 == DWARF || - r2 == HIGH_ELF || - r2 == WOOD_ELF) - return true; - break; - case ERUDITE: - if (r2 == HUMAN || r2 == HALF_ELF) - return true; - break; - case DWARF: - if (r2 == HALFLING || r2 == GNOME) - return true; - break; - case HIGH_ELF: - if (r2 == WOOD_ELF) - return true; - break; - case VAHSHIR: - return true; - case IKSAR: - return false; + case IKSAR: + return false; } return false; } diff --git a/common/features.h b/common/features.h index 3047475e1..0860788e1 100644 --- a/common/features.h +++ b/common/features.h @@ -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) diff --git a/common/glm/glm/CMakeLists.txt b/common/glm/glm/CMakeLists.txt index 79a46074a..9dbe11cab 100644 --- a/common/glm/glm/CMakeLists.txt +++ b/common/glm/glm/CMakeLists.txt @@ -30,11 +30,13 @@ source_group("GTX Files" FILES ${GTX_HEADER}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) -add_executable(${NAME} ${ROOT_TEXT} - ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} - ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} - ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} - ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}) +if(GLM_TEST_ENABLE) + add_executable(${NAME} ${ROOT_TEXT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}) +endif(GLM_TEST_ENABLE) #add_library(glm STATIC glm.cpp) #add_library(glm_shared SHARED glm.cpp) diff --git a/common/glm/glm/common.hpp b/common/glm/glm/common.hpp index 2d787dde0..8f1c3171e 100644 --- a/common/glm/glm/common.hpp +++ b/common/glm/glm/common.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -26,9 +30,6 @@ /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -#ifndef GLM_COMMON_INCLUDED -#define GLM_COMMON_INCLUDED +#pragma once #include "detail/func_common.hpp" - -#endif//GLM_COMMON_INCLUDED diff --git a/common/glm/glm/detail/_features.hpp b/common/glm/glm/detail/_features.hpp index 1c7fe8c96..51eda577c 100644 --- a/common/glm/glm/detail/_features.hpp +++ b/common/glm/glm/detail/_features.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,13 +25,12 @@ /// THE SOFTWARE. /// /// @ref core -/// @file glm/core/_features.hpp +/// @file glm/detail/_features.hpp /// @date 2013-02-20 / 2013-02-20 /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -#ifndef glm_core_features -#define glm_core_features +#pragma once // #define GLM_CXX98_EXCEPTIONS // #define GLM_CXX98_RTTI @@ -281,7 +284,7 @@ # define GLM_CXX11_STATIC_ASSERT # endif -#elif(GLM_COMPILER & GLM_COMPILER_CLANG) +#elif(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) # if(__has_feature(cxx_exceptions)) # define GLM_CXX98_EXCEPTIONS # endif @@ -422,6 +425,4 @@ # define GLM_CXX11_VARIADIC_TEMPLATES # endif -#endif//(GLM_COMPILER & GLM_COMPILER_CLANG) - -#endif//glm_core_features +#endif//(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) diff --git a/common/glm/glm/detail/_fixes.hpp b/common/glm/glm/detail/_fixes.hpp index ce13bb1be..6185dcbb7 100644 --- a/common/glm/glm/detail/_fixes.hpp +++ b/common/glm/glm/detail/_fixes.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,7 +25,7 @@ /// THE SOFTWARE. /// /// @ref core -/// @file glm/core/_fixes.hpp +/// @file glm/detail/_fixes.hpp /// @date 2011-02-21 / 2011-11-22 /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// diff --git a/common/glm/glm/detail/_noise.hpp b/common/glm/glm/detail/_noise.hpp index e366e7c38..94c835d54 100644 --- a/common/glm/glm/detail/_noise.hpp +++ b/common/glm/glm/detail/_noise.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -26,8 +30,12 @@ /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -#ifndef GLM_DETAIL_NOISE_INCLUDED -#define GLM_DETAIL_NOISE_INCLUDED +#pragma once + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../common.hpp" namespace glm{ namespace detail @@ -75,19 +83,19 @@ namespace detail } template - GLM_FUNC_QUALIFIER detail::tvec2 taylorInvSqrt(detail::tvec2 const & r) + GLM_FUNC_QUALIFIER tvec2 taylorInvSqrt(tvec2 const & r) { return T(1.79284291400159) - T(0.85373472095314) * r; } template - GLM_FUNC_QUALIFIER detail::tvec3 taylorInvSqrt(detail::tvec3 const & r) + GLM_FUNC_QUALIFIER tvec3 taylorInvSqrt(tvec3 const & r) { return T(1.79284291400159) - T(0.85373472095314) * r; } template - GLM_FUNC_QUALIFIER detail::tvec4 taylorInvSqrt(detail::tvec4 const & r) + GLM_FUNC_QUALIFIER tvec4 taylorInvSqrt(tvec4 const & r) { return T(1.79284291400159) - T(0.85373472095314) * r; } @@ -100,19 +108,19 @@ namespace detail */ template - GLM_FUNC_QUALIFIER detail::tvec2 fade(detail::tvec2 const & t) + GLM_FUNC_QUALIFIER tvec2 fade(tvec2 const & t) { return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); } template - GLM_FUNC_QUALIFIER detail::tvec3 fade(detail::tvec3 const & t) + GLM_FUNC_QUALIFIER tvec3 fade(tvec3 const & t) { return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); } template - GLM_FUNC_QUALIFIER detail::tvec4 fade(detail::tvec4 const & t) + GLM_FUNC_QUALIFIER tvec4 fade(tvec4 const & t) { return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); } @@ -126,5 +134,3 @@ namespace detail }//namespace detail }//namespace glm -#endif//GLM_DETAIL_NOISE_INCLUDED - diff --git a/common/glm/glm/detail/_swizzle.hpp b/common/glm/glm/detail/_swizzle.hpp index 407ffb49c..3edf6cb23 100644 --- a/common/glm/glm/detail/_swizzle.hpp +++ b/common/glm/glm/detail/_swizzle.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,13 +25,12 @@ /// THE SOFTWARE. /// /// @ref core -/// @file glm/core/_swizzle.hpp +/// @file glm/detail/_swizzle.hpp /// @date 2006-04-20 / 2011-02-16 /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -#ifndef glm_core_swizzle -#define glm_core_swizzle +#pragma once namespace glm{ namespace detail @@ -139,20 +142,15 @@ namespace detail GLM_FUNC_QUALIFIER value_type& operator[] (size_t i) { -#ifndef __CUDA_ARCH__ - static -#endif - const int offset_dst[4] = { E0, E1, E2, E3 }; + const int offset_dst[4] = { E0, E1, E2, E3 }; return this->elem(offset_dst[i]); } GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const { -#ifndef __CUDA_ARCH__ - static -#endif - const int offset_dst[4] = { E0, E1, E2, E3 }; + const int offset_dst[4] = { E0, E1, E2, E3 }; return this->elem(offset_dst[i]); } + protected: template GLM_FUNC_QUALIFIER void _apply_op(const VecType& that, T op) @@ -180,16 +178,13 @@ namespace detail GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const { -#ifndef __CUDA_ARCH__ - static -#endif - const int offset_dst[4] = { E0, E1, E2, E3 }; + const int offset_dst[4] = { E0, E1, E2, E3 }; return this->elem(offset_dst[i]); } }; template - struct _swizzle : public _swizzle_base2 + struct _swizzle : public _swizzle_base2 { typedef _swizzle_base2 base_type; @@ -339,502 +334,500 @@ namespace glm } #define _GLM_SWIZZLE2_2_MEMBERS(T, P, V, E0,E1) \ - struct { _swizzle<2, T, P, V, 0,0,-1,-2> E0 ## E0; }; \ - struct { _swizzle<2, T, P, V, 0,1,-1,-2> E0 ## E1; }; \ - struct { _swizzle<2, T, P, V, 1,0,-1,-2> E1 ## E0; }; \ - struct { _swizzle<2, T, P, V, 1,1,-1,-2> E1 ## E1; }; + struct { detail::_swizzle<2, T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2, T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V, 1,1,-1,-2> E1 ## E1; }; #define _GLM_SWIZZLE2_3_MEMBERS(T, P, V, E0,E1) \ - struct { _swizzle<3,T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { _swizzle<3,T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { _swizzle<3,T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { _swizzle<3,T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { _swizzle<3,T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { _swizzle<3,T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { _swizzle<3,T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { _swizzle<3,T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; + struct { detail::_swizzle<3,T, P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V, 1,1,1,-1> E1 ## E1 ## E1; }; #define _GLM_SWIZZLE2_4_MEMBERS(T, P, V, E0,E1) \ - struct { _swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; + struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; #define _GLM_SWIZZLE3_2_MEMBERS(T, P, V, E0,E1,E2) \ - struct { _swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ - struct { _swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ - struct { _swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ - struct { _swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ - struct { _swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ - struct { _swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ - struct { _swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ - struct { _swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ - struct { _swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; + struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; #define _GLM_SWIZZLE3_3_MEMBERS(T, P, V ,E0,E1,E2) \ - struct { _swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; + struct { detail::_swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; #define _GLM_SWIZZLE3_4_MEMBERS(T, P, V, E0,E1,E2) \ - struct { _swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4,T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4,T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4,T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; + struct { detail::_swizzle<4,T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; #define _GLM_SWIZZLE4_2_MEMBERS(T, P, V, E0,E1,E2,E3) \ - struct { _swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ - struct { _swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ - struct { _swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ - struct { _swizzle<2,T, P, V, 0,3,-1,-2> E0 ## E3; }; \ - struct { _swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ - struct { _swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ - struct { _swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ - struct { _swizzle<2,T, P, V, 1,3,-1,-2> E1 ## E3; }; \ - struct { _swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ - struct { _swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ - struct { _swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; \ - struct { _swizzle<2,T, P, V, 2,3,-1,-2> E2 ## E3; }; \ - struct { _swizzle<2,T, P, V, 3,0,-1,-2> E3 ## E0; }; \ - struct { _swizzle<2,T, P, V, 3,1,-1,-2> E3 ## E1; }; \ - struct { _swizzle<2,T, P, V, 3,2,-1,-2> E3 ## E2; }; \ - struct { _swizzle<2,T, P, V, 3,3,-1,-2> E3 ## E3; }; + struct { detail::_swizzle<2,T, P, V, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 0,3,-1,-2> E0 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 1,3,-1,-2> E1 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 2,2,-1,-2> E2 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 2,3,-1,-2> E2 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V, 3,0,-1,-2> E3 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V, 3,1,-1,-2> E3 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V, 3,2,-1,-2> E3 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V, 3,3,-1,-2> E3 ## E3; }; #define _GLM_SWIZZLE4_3_MEMBERS(T,P, V, E0,E1,E2,E3) \ - struct { _swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 0,0,3,-1> E0 ## E0 ## E3; }; \ - struct { _swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 0,1,3,-1> E0 ## E1 ## E3; }; \ - struct { _swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ - struct { _swizzle<3,T,P, V, 0,2,3,-1> E0 ## E2 ## E3; }; \ - struct { _swizzle<3,T,P, V, 0,3,0,-1> E0 ## E3 ## E0; }; \ - struct { _swizzle<3,T,P, V, 0,3,1,-1> E0 ## E3 ## E1; }; \ - struct { _swizzle<3,T,P, V, 0,3,2,-1> E0 ## E3 ## E2; }; \ - struct { _swizzle<3,T,P, V, 0,3,3,-1> E0 ## E3 ## E3; }; \ - struct { _swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,0,3,-1> E1 ## E0 ## E3; }; \ - struct { _swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,1,3,-1> E1 ## E1 ## E3; }; \ - struct { _swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,2,3,-1> E1 ## E2 ## E3; }; \ - struct { _swizzle<3,T,P, V, 1,3,0,-1> E1 ## E3 ## E0; }; \ - struct { _swizzle<3,T,P, V, 1,3,1,-1> E1 ## E3 ## E1; }; \ - struct { _swizzle<3,T,P, V, 1,3,2,-1> E1 ## E3 ## E2; }; \ - struct { _swizzle<3,T,P, V, 1,3,3,-1> E1 ## E3 ## E3; }; \ - struct { _swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,0,3,-1> E2 ## E0 ## E3; }; \ - struct { _swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,1,3,-1> E2 ## E1 ## E3; }; \ - struct { _swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,2,3,-1> E2 ## E2 ## E3; }; \ - struct { _swizzle<3,T,P, V, 2,3,0,-1> E2 ## E3 ## E0; }; \ - struct { _swizzle<3,T,P, V, 2,3,1,-1> E2 ## E3 ## E1; }; \ - struct { _swizzle<3,T,P, V, 2,3,2,-1> E2 ## E3 ## E2; }; \ - struct { _swizzle<3,T,P, V, 2,3,3,-1> E2 ## E3 ## E3; }; \ - struct { _swizzle<3,T,P, V, 3,0,0,-1> E3 ## E0 ## E0; }; \ - struct { _swizzle<3,T,P, V, 3,0,1,-1> E3 ## E0 ## E1; }; \ - struct { _swizzle<3,T,P, V, 3,0,2,-1> E3 ## E0 ## E2; }; \ - struct { _swizzle<3,T,P, V, 3,0,3,-1> E3 ## E0 ## E3; }; \ - struct { _swizzle<3,T,P, V, 3,1,0,-1> E3 ## E1 ## E0; }; \ - struct { _swizzle<3,T,P, V, 3,1,1,-1> E3 ## E1 ## E1; }; \ - struct { _swizzle<3,T,P, V, 3,1,2,-1> E3 ## E1 ## E2; }; \ - struct { _swizzle<3,T,P, V, 3,1,3,-1> E3 ## E1 ## E3; }; \ - struct { _swizzle<3,T,P, V, 3,2,0,-1> E3 ## E2 ## E0; }; \ - struct { _swizzle<3,T,P, V, 3,2,1,-1> E3 ## E2 ## E1; }; \ - struct { _swizzle<3,T,P, V, 3,2,2,-1> E3 ## E2 ## E2; }; \ - struct { _swizzle<3,T,P, V, 3,2,3,-1> E3 ## E2 ## E3; }; \ - struct { _swizzle<3,T,P, V, 3,3,0,-1> E3 ## E3 ## E0; }; \ - struct { _swizzle<3,T,P, V, 3,3,1,-1> E3 ## E3 ## E1; }; \ - struct { _swizzle<3,T,P, V, 3,3,2,-1> E3 ## E3 ## E2; }; \ - struct { _swizzle<3,T,P, V, 3,3,3,-1> E3 ## E3 ## E3; }; + struct { detail::_swizzle<3,T,P, V, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,0,3,-1> E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,1,3,-1> E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,2,3,-1> E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,0,-1> E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,1,-1> E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,2,-1> E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 0,3,3,-1> E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,0,3,-1> E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,1,3,-1> E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,2,3,-1> E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,0,-1> E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,1,-1> E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,2,-1> E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 1,3,3,-1> E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,0,3,-1> E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,1,3,-1> E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,2,-1> E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,2,3,-1> E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,0,-1> E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,1,-1> E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,2,-1> E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 2,3,3,-1> E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,0,-1> E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,1,-1> E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,2,-1> E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,0,3,-1> E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,0,-1> E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,1,-1> E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,2,-1> E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,1,3,-1> E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,0,-1> E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,1,-1> E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,2,-1> E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,2,3,-1> E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,0,-1> E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,1,-1> E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,2,-1> E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V, 3,3,3,-1> E3 ## E3 ## E3; }; #define _GLM_SWIZZLE4_4_MEMBERS(T, P, V, E0,E1,E2,E3) \ - struct { _swizzle<4, T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ - struct { _swizzle<4, T, P, V, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ - struct { _swizzle<4, T, P, V, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ - struct { _swizzle<4, T, P, V, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ - struct { _swizzle<4, T, P, V, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; - -#endif//glm_core_swizzle + struct { detail::_swizzle<4, T, P, V, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; diff --git a/common/glm/glm/detail/_swizzle_func.hpp b/common/glm/glm/detail/_swizzle_func.hpp index c287bbf5b..7d725e10a 100644 --- a/common/glm/glm/detail/_swizzle_func.hpp +++ b/common/glm/glm/detail/_swizzle_func.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,13 +25,12 @@ /// THE SOFTWARE. /// /// @ref core -/// @file glm/core/_swizzle_func.hpp +/// @file glm/detail/_swizzle_func.hpp /// @date 2011-10-16 / 2011-10-16 /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -#ifndef glm_core_swizzle_func -#define glm_core_swizzle_func +#pragma once #define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ SWIZZLED_TYPE A ## B() CONST \ @@ -720,5 +723,3 @@ GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q) //GLM_SWIZZLE_GEN_VEC_FROM_VEC4(valType, detail::vec4, detail::vec2, detail::vec3, detail::vec4) - -#endif//glm_core_swizzle_func diff --git a/common/glm/glm/detail/_vectorize.hpp b/common/glm/glm/detail/_vectorize.hpp index b653fa9f3..8eea6b871 100644 --- a/common/glm/glm/detail/_vectorize.hpp +++ b/common/glm/glm/detail/_vectorize.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,197 +25,136 @@ /// THE SOFTWARE. /// /// @ref core -/// @file glm/core/_vectorize.hpp +/// @file glm/detail/_vectorize.hpp /// @date 2011-10-14 / 2011-10-14 /// @author Christophe Riccio /////////////////////////////////////////////////////////////////////////////////// -#ifndef GLM_CORE_DETAIL_INCLUDED -#define GLM_CORE_DETAIL_INCLUDED +#pragma once #include "type_vec1.hpp" #include "type_vec2.hpp" #include "type_vec3.hpp" #include "type_vec4.hpp" -#define VECTORIZE1_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec1 func( \ - detail::tvec1 const & v) \ - { \ - return detail::tvec1( \ - func(v.x)); \ - } - -#define VECTORIZE2_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec2 func( \ - detail::tvec2 const & v) \ - { \ - return detail::tvec2( \ - func(v.x), \ - func(v.y)); \ - } - -#define VECTORIZE3_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec3 func( \ - detail::tvec3 const & v) \ - { \ - return detail::tvec3( \ - func(v.x), \ - func(v.y), \ - func(v.z)); \ - } - -#define VECTORIZE4_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec4 func( \ - detail::tvec4 const & v) \ - { \ - return detail::tvec4( \ - func(v.x), \ - func(v.y), \ - func(v.z), \ - func(v.w)); \ - } - -#define VECTORIZE_VEC(func) \ - VECTORIZE1_VEC(func) \ - VECTORIZE2_VEC(func) \ - VECTORIZE3_VEC(func) \ - VECTORIZE4_VEC(func) - -#define VECTORIZE1_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec1 func \ - ( \ - detail::tvec1 const & x, \ - T const & y \ - ) \ - { \ - return detail::tvec1( \ - func(x.x, y)); \ - } - -#define VECTORIZE2_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec2 func \ - ( \ - detail::tvec2 const & x, \ - T const & y \ - ) \ - { \ - return detail::tvec2( \ - func(x.x, y), \ - func(x.y, y)); \ - } - -#define VECTORIZE3_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec3 func \ - ( \ - detail::tvec3 const & x, \ - T const & y \ - ) \ - { \ - return detail::tvec3( \ - func(x.x, y), \ - func(x.y, y), \ - func(x.z, y)); \ - } - -#define VECTORIZE4_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec4 func \ - ( \ - detail::tvec4 const & x, \ - T const & y \ - ) \ - { \ - return detail::tvec4( \ - func(x.x, y), \ - func(x.y, y), \ - func(x.z, y), \ - func(x.w, y)); \ - } - -#define VECTORIZE_VEC_SCA(func) \ - VECTORIZE1_VEC_SCA(func) \ - VECTORIZE2_VEC_SCA(func) \ - VECTORIZE3_VEC_SCA(func) \ - VECTORIZE4_VEC_SCA(func) - -#define VECTORIZE2_VEC_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec2 func \ - ( \ - detail::tvec2 const & x, \ - detail::tvec2 const & y \ - ) \ - { \ - return detail::tvec2( \ - func(x.x, y.x), \ - func(x.y, y.y)); \ - } - -#define VECTORIZE3_VEC_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec3 func \ - ( \ - detail::tvec3 const & x, \ - detail::tvec3 const & y \ - ) \ - { \ - return detail::tvec3( \ - func(x.x, y.x), \ - func(x.y, y.y), \ - func(x.z, y.z)); \ - } - -#define VECTORIZE4_VEC_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec4 func \ - ( \ - detail::tvec4 const & x, \ - detail::tvec4 const & y \ - ) \ - { \ - return detail::tvec4( \ - func(x.x, y.x), \ - func(x.y, y.y), \ - func(x.z, y.z), \ - func(x.w, y.w)); \ - } - -#define VECTORIZE_VEC_VEC(func) \ - VECTORIZE2_VEC_VEC(func) \ - VECTORIZE3_VEC_VEC(func) \ - VECTORIZE4_VEC_VEC(func) - namespace glm{ namespace detail { - template - struct If + template class vecType> + struct functor1{}; + + template + struct functor1 { - template - static GLM_FUNC_QUALIFIER T apply(F functor, const T& val) + GLM_FUNC_QUALIFIER static tvec1 call(R (*Func) (T x), tvec1 const & v) { - return functor(val); + return tvec1(Func(v.x)); } }; - template<> - struct If + template + struct functor1 { - template - static GLM_FUNC_QUALIFIER T apply(F, const T& val) + GLM_FUNC_QUALIFIER static tvec2 call(R (*Func) (T x), tvec2 const & v) { - return val; + return tvec2(Func(v.x), Func(v.y)); + } + }; + + template + struct functor1 + { + GLM_FUNC_QUALIFIER static tvec3 call(R (*Func) (T x), tvec3 const & v) + { + return tvec3(Func(v.x), Func(v.y), Func(v.z)); + } + }; + + template + struct functor1 + { + GLM_FUNC_QUALIFIER static tvec4 call(R (*Func) (T x), tvec4 const & v) + { + return tvec4(Func(v.x), Func(v.y), Func(v.z), Func(v.w)); + } + }; + + template class vecType> + struct functor2{}; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec1 call(T (*Func) (T x, T y), tvec1 const & a, tvec1 const & b) + { + return tvec1(Func(a.x, b.x)); + } + }; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec2 call(T (*Func) (T x, T y), tvec2 const & a, tvec2 const & b) + { + return tvec2(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec3 call(T (*Func) (T x, T y), tvec3 const & a, tvec3 const & b) + { + return tvec3(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template + struct functor2 + { + GLM_FUNC_QUALIFIER static tvec4 call(T (*Func) (T x, T y), tvec4 const & a, tvec4 const & b) + { + return tvec4(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; + + template class vecType> + struct functor2_vec_sca{}; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec1 call(T (*Func) (T x, T y), tvec1 const & a, T b) + { + return tvec1(Func(a.x, b)); + } + }; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec2 call(T (*Func) (T x, T y), tvec2 const & a, T b) + { + return tvec2(Func(a.x, b), Func(a.y, b)); + } + }; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec3 call(T (*Func) (T x, T y), tvec3 const & a, T b) + { + return tvec3(Func(a.x, b), Func(a.y, b), Func(a.z, b)); + } + }; + + template + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static tvec4 call(T (*Func) (T x, T y), tvec4 const & a, T b) + { + return tvec4(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b)); } }; }//namespace detail }//namespace glm - -#endif//GLM_CORE_DETAIL_INCLUDED diff --git a/common/glm/glm/detail/dummy.cpp b/common/glm/glm/detail/dummy.cpp index 26160a51a..c7ef99edb 100644 --- a/common/glm/glm/detail/dummy.cpp +++ b/common/glm/glm/detail/dummy.cpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,7 +33,6 @@ /// dummy.cpp exist only a wordaround for CMake file. /////////////////////////////////////////////////////////////////////////////////// -#define GLM_FORCE_RADIANS #define GLM_MESSAGES #include "../glm.hpp" #include @@ -42,6 +45,7 @@ struct material glm::vec4 specular; // Scm float shininess; // Srm }; + struct light { glm::vec4 ambient; // Acli @@ -60,6 +64,7 @@ struct light float quadraticAttenuation;// K2 }; + // Sample 1 #include // glm::vec3 #include // glm::cross, glm::normalize @@ -184,7 +189,34 @@ glm::vec3 lighting return Color; } */ + + +template class vecType> +T normalizeDotA(vecType const & x, vecType const & y) +{ + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); +} + +#define GLM_TEMPLATE_GENTYPE typename T, glm::precision P, template class + +template +T normalizeDotB(vecType const & x, vecType const & y) +{ + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); +} + +template +typename vecType::value_type normalizeDotC(vecType const & a, vecType const & b) +{ + return glm::dot(a, b) * glm::inversesqrt(glm::dot(a, a) * glm::dot(b, b)); +} + int main() { + glm::vec4 v(1); + float a = normalizeDotA(v, v); + float b = normalizeDotB(v, v); + float c = normalizeDotC(v, v); + return 0; } diff --git a/common/glm/glm/detail/func_common.hpp b/common/glm/glm/detail/func_common.hpp index a3e5d6338..0cea49426 100644 --- a/common/glm/glm/detail/func_common.hpp +++ b/common/glm/glm/detail/func_common.hpp @@ -12,6 +12,10 @@ /// The above copyright notice and this permission notice shall be included in /// all copies or substantial portions of the Software. /// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// /// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,7 +25,7 @@ /// THE SOFTWARE. /// /// @ref core -/// @file glm/core/func_common.hpp +/// @file glm/detail/func_common.hpp /// @date 2008-03-08 / 2010-01-26 /// @author Christophe Riccio /// @@ -33,8 +37,7 @@ /// These all operate component-wise. The description is per component. /////////////////////////////////////////////////////////////////////////////////// -#ifndef GLM_FUNC_COMMON_INCLUDED -#define GLM_FUNC_COMMON_INCLUDED +#pragma once #include "setup.hpp" #include "precision.hpp" @@ -53,7 +56,10 @@ namespace glm /// @see GLSL abs man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType abs(genType const & x); + GLM_FUNC_DECL genType abs(genType x); + + template class vecType> + GLM_FUNC_DECL vecType abs(vecType const & x); /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. /// @@ -61,17 +67,17 @@ namespace glm /// /// @see GLSL sign man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType sign(genType const & x); - + template class vecType> + GLM_FUNC_DECL vecType sign(vecType const & x); + /// Returns a value equal to the nearest integer that is less then or equal to x. /// /// @tparam genType Floating-point scalar or vector types. /// /// @see GLSL floor man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType floor(genType const & x); + template class vecType> + GLM_FUNC_DECL vecType floor(vecType const & x); /// Returns a value equal to the nearest integer to x /// whose absolute value is not larger than the absolute value of x. @@ -80,8 +86,8 @@ namespace glm /// /// @see GLSL trunc man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType trunc(genType const & x); + template class vecType> + GLM_FUNC_DECL vecType trunc(vecType const & x); /// Returns a value equal to the nearest integer to x. /// The fraction 0.5 will round in a direction chosen by the @@ -93,9 +99,9 @@ namespace glm /// /// @see GLSL round man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType round(genType const & x); - + template class vecType> + GLM_FUNC_DECL vecType round(vecType const & x); + /// Returns a value equal to the nearest integer to x. /// A fractional part of 0.5 will round toward the nearest even /// integer. (Both 3.5 and 4.5 for x will return 4.0.) @@ -105,8 +111,8 @@ namespace glm /// @see GLSL roundEven man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions /// @see New round to even technique - template - GLM_FUNC_DECL genType roundEven(genType const & x); + template class vecType> + GLM_FUNC_DECL vecType roundEven(vecType const & x); /// Returns a value equal to the nearest integer /// that is greater than or equal to x. @@ -115,8 +121,8 @@ namespace glm /// /// @see GLSL ceil man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType ceil(genType const & x); + template class vecType> + GLM_FUNC_DECL vecType ceil(vecType const & x); /// Return x - floor(x). /// @@ -125,7 +131,10 @@ namespace glm /// @see GLSL fract man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType fract(genType const & x); + GLM_FUNC_DECL genType fract(genType x); + + template class vecType> + GLM_FUNC_DECL vecType fract(vecType const & x); /// Modulus. Returns x - y * floor(x / y) /// for each component in x using the floating point value y. @@ -135,21 +144,13 @@ namespace glm /// @see GLSL mod man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType mod( - genType const & x, - genType const & y); + GLM_FUNC_DECL genType mod(genType x, genType y); - /// Modulus. Returns x - y * floor(x / y) - /// for each component in x using the floating point value y. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL mod man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType mod( - genType const & x, - typename genType::value_type const & y); + template class vecType> + GLM_FUNC_DECL vecType mod(vecType const & x, T y); + + template class vecType> + GLM_FUNC_DECL vecType mod(vecType const & x, vecType const & y); /// Returns the fractional part of x and sets i to the integer /// part (as a whole number floating point value). Both the @@ -161,25 +162,22 @@ namespace glm /// @see GLSL modf man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType modf( - genType const & x, - genType & i); + GLM_FUNC_DECL genType modf(genType x, genType & i); /// Returns y if y < x; otherwise, it returns x. /// /// @tparam genType Floating-point or integer; scalar or vector types. /// /// @see GLSL min man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions<<<<<<< HEAD + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType min( - genType const & x, - genType const & y); + GLM_FUNC_DECL genType min(genType x, genType y); - template - GLM_FUNC_DECL genType min( - genType const & x, - typename genType::value_type const & y); + template class vecType> + GLM_FUNC_DECL vecType min(vecType const & x, T y); + + template class vecType> + GLM_FUNC_DECL vecType min(vecType const & x, vecType const & y); /// Returns y if x < y; otherwise, it returns x. /// @@ -188,14 +186,13 @@ namespace glm /// @see GLSL max man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType max( - genType const & x, - genType const & y); + GLM_FUNC_DECL genType max(genType x, genType y); - template - GLM_FUNC_DECL genType max( - genType const & x, - typename genType::value_type const & y); + template class vecType> + GLM_FUNC_DECL vecType max(vecType const & x, T y); + + template class vecType> + GLM_FUNC_DECL vecType max(vecType const & x, vecType const & y); /// Returns min(max(x, minVal), maxVal) for each component in x /// using the floating-point values minVal and maxVal. @@ -205,16 +202,13 @@ namespace glm /// @see GLSL clamp man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType clamp( - genType const & x, - genType const & minVal, - genType const & maxVal); + GLM_FUNC_DECL genType clamp(genType x, genType minVal, genType maxVal); - template - GLM_FUNC_DECL genType clamp( - genType const & x, - typename genType::value_type const & minVal, - typename genType::value_type const & maxVal); + template class vecType> + GLM_FUNC_DECL vecType clamp(vecType const & x, T minVal, T maxVal); + + template class vecType> + GLM_FUNC_DECL vecType clamp(vecType const & x, vecType const & minVal, vecType const & maxVal); /// If genTypeU is a floating scalar or vector: /// Returns x * (1.0 - a) + y * a, i.e., the linear blend of @@ -259,40 +253,34 @@ namespace glm /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter. /// @endcode template class vecType> - GLM_FUNC_DECL vecType mix( - vecType const & x, - vecType const & y, - vecType const & a); + GLM_FUNC_DECL vecType mix(vecType const & x, vecType const & y, vecType const & a); template class vecType> - GLM_FUNC_DECL vecType mix( - vecType const & x, - vecType const & y, - U const & a); + GLM_FUNC_DECL vecType mix(vecType const & x, vecType const & y, U a); template - GLM_FUNC_DECL genTypeT mix( - genTypeT const & x, - genTypeT const & y, - genTypeU const & a); + GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a); /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. /// /// @see GLSL step man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template - GLM_FUNC_DECL genType step( - genType const & edge, - genType const & x); + GLM_FUNC_DECL genType step(genType edge, genType x); /// Returns 0.0 if x < edge, otherwise it returns 1.0. /// /// @see GLSL step man page /// @see GLSL 4.20.8 specification, section 8.3 Common Functions template