Merge and fix the loot update branch, ready for merge I think

This commit is contained in:
KimLS 2015-02-04 23:13:02 -08:00
commit ecd05d821e
738 changed files with 82418 additions and 58480 deletions

View File

@ -24,8 +24,8 @@
#EQEMU_DISABLE_LOGSYS #EQEMU_DISABLE_LOGSYS
#EQEMU_COMMANDS_LOGGING #EQEMU_COMMANDS_LOGGING
#EQEMU_BUILD_SERVER #EQEMU_BUILD_SERVER
#EQEMU_BUILD_LOGIN #EQEMU_BUILD_LOGIN
#EQEMU_BUILD_TESTS #EQEMU_BUILD_TESTS
#EQEMU_BUILD_PERL #EQEMU_BUILD_PERL
#EQEMU_BUILD_LUA #EQEMU_BUILD_LUA
#EQEMU_SANITIZE_LUA_LIBS #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_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /SAFESEH:NO")
SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO") SET(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /SAFESEH:NO")
ENDIF(EQEMU_DISABLE_SAFESEH) ENDIF(EQEMU_DISABLE_SAFESEH)
OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON) OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON)
IF(EQEMU_BUILD_MSVC_MP) IF(EQEMU_BUILD_MSVC_MP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
@ -115,7 +115,7 @@ IF(MSVC)
STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
ENDIF(${flag_var} MATCHES "/MD") ENDIF(${flag_var} MATCHES "/MD")
ENDFOREACH(flag_var) ENDFOREACH(flag_var)
ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DNOMINMAX)
ELSE(MSVC) ELSE(MSVC)
#Normally set by perl but we don't use the perl flags anymore so we set it. #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(UNIX)
IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
ADD_DEFINITIONS(-DFREEBSD) ADD_DEFINITIONS(-DFREEBSD)
ADD_DEFINITIONS(-D_GLIBCXX_USE_C99)
SET(FREEBSD TRUE) SET(FREEBSD TRUE)
ENDIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") ENDIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
IF(CMAKE_SYSTEM_NAME MATCHES "Darwin") 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 #C++11 stuff
IF(NOT MSVC) 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) ENDIF(NOT MSVC)
#Various definitions #Various definitions
@ -302,26 +306,26 @@ FIND_PACKAGE(ZLIB REQUIRED)
FIND_PACKAGE(MySQL REQUIRED) FIND_PACKAGE(MySQL REQUIRED)
IF(EQEMU_BUILD_PERL) IF(EQEMU_BUILD_PERL)
FIND_PACKAGE(PerlLibs REQUIRED) FIND_PACKAGE(PerlLibs REQUIRED)
INCLUDE_DIRECTORIES("${PERL_INCLUDE_PATH}") INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
ENDIF(EQEMU_BUILD_PERL) ENDIF(EQEMU_BUILD_PERL)
IF(EQEMU_BUILD_LUA) IF(EQEMU_BUILD_LUA)
FIND_PACKAGE(EQLua51 REQUIRED) FIND_PACKAGE(EQLua51 REQUIRED)
SET(Boost_USE_STATIC_LIBS OFF) SET(Boost_USE_STATIC_LIBS OFF)
SET(Boost_USE_MULTITHREADED ON) SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_RUNTIME OFF) SET(Boost_USE_STATIC_RUNTIME OFF)
SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost") SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost")
FIND_PACKAGE(Boost REQUIRED) 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) 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) IF(EQEMU_SANITIZE_LUA_LIBS)
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS) ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
ENDIF(EQEMU_SANITIZE_LUA_LIBS) ENDIF(EQEMU_SANITIZE_LUA_LIBS)
ENDIF(EQEMU_BUILD_LUA) 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) IF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(luabind) ADD_SUBDIRECTORY(luabind)

View File

@ -1,5 +1,473 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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 == == 10/01/2014 ==
Kayen: Exported to PERL $client->SendColoredText(color, msg) Kayen: Exported to PERL $client->SendColoredText(color, msg)
demonstar55: Exported SendColoredText to lua demonstar55: Exported SendColoredText to lua

View File

@ -17,7 +17,9 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "../../common/debug.h"
#include "../../common/eqemu_logsys.h"
#include "../../common/global_define.h"
#include "../../common/shareddb.h" #include "../../common/shareddb.h"
#include "../../common/eqemu_config.h" #include "../../common/eqemu_config.h"
#include "../../common/platform.h" #include "../../common/platform.h"
@ -25,47 +27,53 @@
#include "../../common/rulesys.h" #include "../../common/rulesys.h"
#include "../../common/string_util.h" #include "../../common/string_util.h"
EQEmuLogSys Log;
void ExportSpells(SharedDatabase *db); void ExportSpells(SharedDatabase *db);
void ExportSkillCaps(SharedDatabase *db); void ExportSkillCaps(SharedDatabase *db);
void ExportBaseData(SharedDatabase *db); void ExportBaseData(SharedDatabase *db);
int main(int argc, char **argv) { int main(int argc, char **argv) {
RegisterExecutablePlatform(ExePlatformClientExport); RegisterExecutablePlatform(ExePlatformClientExport);
Log.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
LogFile->write(EQEMuLog::Status, "Client Files Export Utility"); Log.Out(Logs::General, Logs::Status, "Client Files Export Utility");
if(!EQEmuConfig::LoadConfig()) { 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; return 1;
} }
const EQEmuConfig *config = EQEmuConfig::get(); 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; 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(), if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(),
config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { 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"); "database connection");
return 1; return 1;
} }
/* Register Log System and Settings */
database.LoadLogSettings(Log.log_settings);
Log.StartFileLogs();
ExportSpells(&database); ExportSpells(&database);
ExportSkillCaps(&database); ExportSkillCaps(&database);
ExportBaseData(&database); ExportBaseData(&database);
Log.CloseFileLogs();
return 0; return 0;
} }
void ExportSpells(SharedDatabase *db) { 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"); FILE *f = fopen("export/spells_us.txt", "w");
if(!f) { 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; return;
} }
@ -89,7 +97,6 @@ void ExportSpells(SharedDatabase *db) {
fprintf(f, "%s\n", line.c_str()); fprintf(f, "%s\n", line.c_str());
} }
} else { } else {
LogFile->write(EQEMuLog::Error, "Error in ExportSpells query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
} }
fclose(f); fclose(f);
@ -103,7 +110,6 @@ bool SkillUsable(SharedDatabase *db, int skill_id, int class_id) {
class_id, skill_id); class_id, skill_id);
auto results = db->QueryDatabase(query); auto results = db->QueryDatabase(query);
if(!results.Success()) { if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in skill_usable query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
return false; return false;
} }
@ -123,7 +129,6 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) {
class_id, skill_id, level); class_id, skill_id, level);
auto results = db->QueryDatabase(query); auto results = db->QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in get_skill query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
return 0; return 0;
} }
@ -135,11 +140,11 @@ int GetSkill(SharedDatabase *db, int skill_id, int class_id, int level) {
} }
void ExportSkillCaps(SharedDatabase *db) { 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"); FILE *f = fopen("export/SkillCaps.txt", "w");
if(!f) { 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; return;
} }
@ -164,11 +169,11 @@ void ExportSkillCaps(SharedDatabase *db) {
} }
void ExportBaseData(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"); FILE *f = fopen("export/BaseData.txt", "w");
if(!f) { 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; return;
} }
@ -190,7 +195,6 @@ void ExportBaseData(SharedDatabase *db) {
fprintf(f, "%s\n", line.c_str()); fprintf(f, "%s\n", line.c_str());
} }
} else { } else {
LogFile->write(EQEMuLog::Error, "Error in ExportBaseData query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
} }
fclose(f); fclose(f);

View File

@ -16,7 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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/shareddb.h"
#include "../../common/eqemu_config.h" #include "../../common/eqemu_config.h"
#include "../../common/platform.h" #include "../../common/platform.h"
@ -24,38 +25,43 @@
#include "../../common/rulesys.h" #include "../../common/rulesys.h"
#include "../../common/string_util.h" #include "../../common/string_util.h"
EQEmuLogSys Log;
void ImportSpells(SharedDatabase *db); void ImportSpells(SharedDatabase *db);
void ImportSkillCaps(SharedDatabase *db); void ImportSkillCaps(SharedDatabase *db);
void ImportBaseData(SharedDatabase *db); void ImportBaseData(SharedDatabase *db);
int main(int argc, char **argv) { int main(int argc, char **argv) {
RegisterExecutablePlatform(ExePlatformClientImport); RegisterExecutablePlatform(ExePlatformClientImport);
Log.LoadLogSettingsDefaults();
set_exception_handler(); set_exception_handler();
LogFile->write(EQEMuLog::Status, "Client Files Import Utility"); Log.Out(Logs::General, Logs::Status, "Client Files Import Utility");
if(!EQEmuConfig::LoadConfig()) { 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; return 1;
} }
const EQEmuConfig *config = EQEmuConfig::get(); 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; 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(), if(!database.Connect(config->DatabaseHost.c_str(), config->DatabaseUsername.c_str(),
config->DatabasePassword.c_str(), config->DatabaseDB.c_str(), config->DatabasePort)) { 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"); "database connection");
return 1; return 1;
} }
database.LoadLogSettings(Log.log_settings);
Log.StartFileLogs();
ImportSpells(&database); ImportSpells(&database);
ImportSkillCaps(&database); ImportSkillCaps(&database);
ImportBaseData(&database); ImportBaseData(&database);
Log.CloseFileLogs();
return 0; return 0;
} }
@ -64,7 +70,6 @@ int GetSpellColumns(SharedDatabase *db) {
const std::string query = "DESCRIBE spells_new"; const std::string query = "DESCRIBE spells_new";
auto results = db->QueryDatabase(query); auto results = db->QueryDatabase(query);
if(!results.Success()) { if(!results.Success()) {
LogFile->write(EQEMuLog::Error, "Error in GetSpellColumns query '%s' %s", query.c_str(), results.ErrorMessage().c_str());
return 0; return 0;
} }
@ -72,10 +77,10 @@ int GetSpellColumns(SharedDatabase *db) {
} }
void ImportSpells(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"); FILE *f = fopen("import/spells_us.txt", "r");
if(!f) { 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; return;
} }
@ -138,23 +143,23 @@ void ImportSpells(SharedDatabase *db) {
spells_imported++; spells_imported++;
if(spells_imported % 1000 == 0) { 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) { 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); fclose(f);
} }
void ImportSkillCaps(SharedDatabase *db) { 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"); FILE *f = fopen("import/SkillCaps.txt", "r");
if(!f) { 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; return;
} }
@ -186,11 +191,11 @@ void ImportSkillCaps(SharedDatabase *db) {
} }
void ImportBaseData(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"); FILE *f = fopen("import/BaseData.txt", "r");
if(!f) { 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; return;
} }

View File

@ -8,8 +8,9 @@ SET(common_sources
crc16.cpp crc16.cpp
crc32.cpp crc32.cpp
database.cpp database.cpp
database_conversions.cpp
database_instances.cpp
dbcore.cpp dbcore.cpp
debug.cpp
emu_opcodes.cpp emu_opcodes.cpp
emu_tcp_connection.cpp emu_tcp_connection.cpp
emu_tcp_server.cpp emu_tcp_server.cpp
@ -18,7 +19,7 @@ SET(common_sources
eqdb_res.cpp eqdb_res.cpp
eqemu_exception.cpp eqemu_exception.cpp
eqemu_config.cpp eqemu_config.cpp
eqemu_error.cpp eqemu_logsys.cpp
eq_packet.cpp eq_packet.cpp
eq_stream.cpp eq_stream.cpp
eq_stream_factory.cpp eq_stream_factory.cpp
@ -31,13 +32,10 @@ SET(common_sources
guilds.cpp guilds.cpp
ipc_mutex.cpp ipc_mutex.cpp
item.cpp item.cpp
logsys.cpp
logsys_eqemu.cpp
md5.cpp md5.cpp
memory_mapped_file.cpp memory_mapped_file.cpp
misc.cpp misc.cpp
misc_functions.cpp misc_functions.cpp
moremath.cpp
mutex.cpp mutex.cpp
mysql_request_result.cpp mysql_request_result.cpp
mysql_request_row.cpp mysql_request_row.cpp
@ -67,13 +65,13 @@ SET(common_sources
worldconn.cpp worldconn.cpp
xml_parser.cpp xml_parser.cpp
platform.cpp platform.cpp
patches/client62.cpp
patches/patches.cpp patches/patches.cpp
patches/sod.cpp patches/sod.cpp
patches/sof.cpp patches/sof.cpp
patches/rof.cpp patches/rof.cpp
patches/rof2.cpp
patches/titanium.cpp patches/titanium.cpp
patches/underfoot.cpp patches/uf.cpp
SocketLib/Base64.cpp SocketLib/Base64.cpp
SocketLib/File.cpp SocketLib/File.cpp
SocketLib/HttpdCookies.cpp SocketLib/HttpdCookies.cpp
@ -97,7 +95,6 @@ SET(common_headers
base_packet.h base_packet.h
base_data.h base_data.h
bodytypes.h bodytypes.h
breakdowns.h
classes.h classes.h
condition.h condition.h
crash.h crash.h
@ -106,7 +103,6 @@ SET(common_headers
data_verification.h data_verification.h
database.h database.h
dbcore.h dbcore.h
debug.h
deity.h deity.h
emu_opcodes.h emu_opcodes.h
emu_oplist.h emu_oplist.h
@ -120,7 +116,7 @@ SET(common_headers
eqemu_exception.h eqemu_exception.h
eqemu_config.h eqemu_config.h
eqemu_config_elements.h eqemu_config_elements.h
eqemu_error.h eqemu_logsys.h
eq_packet.h eq_packet.h
eq_stream.h eq_stream.h
eq_stream_factory.h eq_stream_factory.h
@ -136,6 +132,7 @@ SET(common_headers
features.h features.h
fixed_memory_hash_set.h fixed_memory_hash_set.h
fixed_memory_variable_hash_set.h fixed_memory_variable_hash_set.h
global_define.h
guild_base.h guild_base.h
guilds.h guilds.h
ipc_mutex.h ipc_mutex.h
@ -144,15 +141,12 @@ SET(common_headers
item_struct.h item_struct.h
languages.h languages.h
linked_list.h linked_list.h
logsys.h
logtypes.h
loottable.h loottable.h
mail_oplist.h mail_oplist.h
md5.h md5.h
memory_mapped_file.h memory_mapped_file.h
misc.h misc.h
misc_functions.h misc_functions.h
moremath.h
mutex.h mutex.h
mysql_request_result.h mysql_request_result.h
mysql_request_row.h mysql_request_row.h
@ -168,6 +162,7 @@ SET(common_headers
ptimer.h ptimer.h
queue.h queue.h
races.h races.h
random.h
rdtsc.h rdtsc.h
rulesys.h rulesys.h
ruletypes.h ruletypes.h
@ -191,11 +186,6 @@ SET(common_headers
worldconn.h worldconn.h
xml_parser.h xml_parser.h
zone_numbers.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/patches.h
patches/sod.h patches/sod.h
patches/sod_constants.h patches/sod_constants.h
@ -216,16 +206,21 @@ SET(common_headers
patches/rof_itemfields.h patches/rof_itemfields.h
patches/rof_ops.h patches/rof_ops.h
patches/rof_structs.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.h
patches/titanium_constants.h patches/titanium_constants.h
patches/titanium_itemfields.h patches/titanium_itemfields.h
patches/titanium_ops.h patches/titanium_ops.h
patches/titanium_structs.h patches/titanium_structs.h
patches/underfoot.h patches/uf.h
patches/underfoot_constants.h patches/uf_constants.h
patches/underfoot_itemfields.h patches/uf_itemfields.h
patches/underfoot_ops.h patches/uf_ops.h
patches/underfoot_structs.h patches/uf_structs.h
SocketLib/Base64.h SocketLib/Base64.h
SocketLib/File.h SocketLib/File.h
SocketLib/HttpdCookies.h SocketLib/HttpdCookies.h
@ -244,11 +239,6 @@ SET(common_headers
) )
SOURCE_GROUP(Patches FILES 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/patches.h
patches/sod.h patches/sod.h
patches/sod_itemfields.h patches/sod_itemfields.h
@ -269,23 +259,28 @@ SOURCE_GROUP(Patches FILES
patches/rof_ops.h patches/rof_ops.h
patches/rof_constants.h patches/rof_constants.h
patches/rof_structs.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.h
patches/titanium_itemfields.h patches/titanium_itemfields.h
patches/titanium_ops.h patches/titanium_ops.h
patches/titanium_constants.h patches/titanium_constants.h
patches/titanium_structs.h patches/titanium_structs.h
patches/underfoot.h patches/uf.h
patches/underfoot_itemfields.h patches/uf_itemfields.h
patches/underfoot_ops.h patches/uf_ops.h
patches/underfoot_constants.h patches/uf_constants.h
patches/underfoot_structs.h patches/uf_structs.h
patches/client62.cpp
patches/patches.cpp patches/patches.cpp
patches/sod.cpp patches/sod.cpp
patches/sof.cpp patches/sof.cpp
patches/rof.cpp patches/rof.cpp
patches/rof2.cpp
patches/titanium.cpp patches/titanium.cpp
patches/underfoot.cpp patches/uf.cpp
) )
SOURCE_GROUP(SocketLib FILES SOURCE_GROUP(SocketLib FILES
@ -334,7 +329,9 @@ ADD_LIBRARY(common ${common_sources} ${common_headers})
IF(UNIX) IF(UNIX)
ADD_DEFINITIONS(-fPIC) 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) ENDIF(UNIX)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

View File

@ -40,7 +40,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(disable:4786) #pragma warning(disable:4786)
#endif #endif
#include "../debug.h" #include "../global_define.h"
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include <stdarg.h> #include <stdarg.h>

View File

@ -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. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "../debug.h" #include "../global_define.h"
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(disable:4786) #pragma warning(disable:4786)
#endif #endif

View File

@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(disable:4786) #pragma warning(disable:4786)
#endif #endif
#include "../debug.h" #include "../global_define.h"
#include "Utility.h" #include "Utility.h"
#include "HttpdCookies.h" #include "HttpdCookies.h"
#include "HttpdForm.h" #include "HttpdForm.h"
@ -194,7 +194,6 @@ void HttpdSocket::OnHeaderComplete()
void HttpdSocket::OnData(const char *p,size_t l) void HttpdSocket::OnData(const char *p,size_t l)
{ {
//printf("Got %d bytes: %.*s\n", l, l, p);
if (m_file) if (m_file)
{ {
m_file -> fwrite(p,1,l); m_file -> fwrite(p,1,l);

View File

@ -110,7 +110,6 @@ size_t MemFile::fread(char *ptr, size_t size, size_t nmemb)
size_t sz = size * nmemb; size_t sz = size * nmemb;
if (p + sz < BLOCKSIZE) 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); memcpy(ptr, m_current_read -> data + p, sz);
m_read_ptr += 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; size_t sz = size * nmemb;
if (p + sz < BLOCKSIZE) if (p + sz < BLOCKSIZE)
{ {
//printf("Write @ %d(%d). %d bytes.\n", m_write_ptr, p, sz);
memcpy(m_current_write -> data + p, ptr, sz); memcpy(m_current_write -> data + p, ptr, sz);
m_write_ptr += sz; m_write_ptr += sz;
} }

View File

@ -1128,7 +1128,6 @@ BOOL __stdcall StackWalker::myReadProcMem(
SIZE_T st; SIZE_T st;
BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st); BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st);
*lpNumberOfBytesRead = (DWORD) 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; return bRet;
} }
else else

View File

@ -15,13 +15,12 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h"
#include "global_define.h"
#include "base_packet.h" #include "base_packet.h"
#include "misc.h" #include "misc.h"
#include "packet_dump.h" #include "packet_dump.h"
BasePacket::BasePacket(const unsigned char *buf, uint32 len) BasePacket::BasePacket(const unsigned char *buf, uint32 len)
{ {
this->pBuffer=nullptr; this->pBuffer=nullptr;

View File

@ -21,7 +21,6 @@
#include "types.h" #include "types.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <string>
#ifdef WIN32 #ifdef WIN32
#include <time.h> #include <time.h>

View File

@ -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_*/

View File

@ -14,8 +14,8 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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" #include "../common/classes.h"
const char* GetEQClassName(uint8 class_, uint8 level) { 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;
}

View File

@ -86,7 +86,5 @@
#define call_1 65536 #define call_1 65536
const char* GetEQClassName(uint8 class_, uint8 level = 0); const char* GetEQClassName(uint8 class_, uint8 level = 0);
uint32 GetArrayEQClass(uint8 eqclass);
uint8 GetEQArrayEQClass(uint8 eqclass);
#endif #endif

View File

@ -1,75 +1,76 @@
#ifndef CLIENTVERSIONS_H #ifndef CLIENTVERSIONS_H
#define CLIENTVERSIONS_H #define CLIENTVERSIONS_H
#include "types.h"
static const uint32 BIT_Client62 = 1; static const uint32 BIT_Client62 = 1;
static const uint32 BIT_Titanium = 2; static const uint32 BIT_Titanium = 2;
static const uint32 BIT_SoF = 4; static const uint32 BIT_SoF = 4;
static const uint32 BIT_SoD = 8; 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_RoF = 32;
static const uint32 BIT_RoF2 = 64; static const uint32 BIT_RoF2 = 64;
static const uint32 BIT_TitaniumAndEarlier = 0x00000003; static const uint32 BIT_TitaniumAndEarlier = 0x00000003;
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; static const uint32 BIT_SoFAndLater = 0xFFFFFFFC;
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; 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_RoFAndLater = 0xFFFFFFE0;
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
static const uint32 BIT_AllClients = 0xFFFFFFFF; static const uint32 BIT_AllClients = 0xFFFFFFFF;
typedef enum enum class ClientVersion
{ {
EQClientUnknown = 0, Unknown = 0,
EQClient62, // Build: 'Aug 4 2005 15:40:59' Client62, // Build: 'Aug 4 2005 15:40:59'
EQClientTitanium, // Build: 'Oct 31 2005 10:33:37' Titanium, // Build: 'Oct 31 2005 10:33:37'
EQClientSoF, // Build: 'Sep 7 2007 09:11:49' SoF, // Build: 'Sep 7 2007 09:11:49'
EQClientSoD, // Build: 'Dec 19 2008 15:22:49' SoD, // Build: 'Dec 19 2008 15:22:49'
EQClientUnderfoot, // Build: 'Jun 8 2010 16:44:32' UF, // Build: 'Jun 8 2010 16:44:32'
EQClientRoF, // Build: 'Dec 10 2012 17:35:44' RoF, // Build: 'Dec 10 2012 17:35:44'
EQClientRoF2, // Build: 'May 10 2013 23:30:08' 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 static const char* ClientVersionName(ClientVersion version)
} EQClientVersion;
static const char* EQClientVersionName(EQClientVersion version)
{ {
switch (version) switch (version)
{ {
case EQClientUnknown: case ClientVersion::Unknown:
return "EQClientUnknown"; return "ClientVersion::Unknown";
case EQClient62: case ClientVersion::Client62:
return "EQClient62"; return "ClientVersion::Client62";
case EQClientTitanium: case ClientVersion::Titanium:
return "EQClientTitanium"; return "ClientVersion::Titanium";
case EQClientSoF: case ClientVersion::SoF:
return "EQClientSoF"; return "ClientVersion::SoF";
case EQClientSoD: case ClientVersion::SoD:
return "EQClientSoD"; return "ClientVersion::SoD";
case EQClientUnderfoot: case ClientVersion::UF:
return "EQClientUnderfoot"; return "ClientVersion::UF";
case EQClientRoF: case ClientVersion::RoF:
return "EQClientRoF"; return "ClientVersion::RoF";
case EQClientRoF2: case ClientVersion::RoF2:
return "EQClientRoF2"; return "ClientVersion::RoF2";
case EmuNPC: case ClientVersion::MobNPC:
return "EmuNPC"; return "ClientVersion::MobNPC";
case EmuMerc: case ClientVersion::MobMerc:
return "EmuMerc"; return "ClientVersion::MobMerc";
case EmuBot: case ClientVersion::MobBot:
return "EmuBot"; return "ClientVersion::MobBot";
case EmuPet: case ClientVersion::MobPet:
return "EmuPet"; return "ClientVersion::MobPet";
default: default:
return "ERROR: Invalid EQClientVersion"; return "<ERROR> Invalid ClientVersion";
}; };
} }

View File

@ -16,7 +16,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h"
#include "condition.h" #include "condition.h"
#ifdef _WINDOWS #ifdef _WINDOWS

View File

@ -18,7 +18,8 @@
#ifndef __CONDITION_H #ifndef __CONDITION_H
#define __CONDITION_H #define __CONDITION_H
#include "debug.h" #include "global_define.h"
#include "mutex.h"
#ifndef WIN32 #ifndef WIN32
#include <pthread.h> #include <pthread.h>
#endif #endif

View File

@ -1,4 +1,5 @@
#include "debug.h" #include "global_define.h"
#include "eqemu_logsys.h"
#include "crash.h" #include "crash.h"
#if defined(_WINDOWS) && defined(CRASH_LOGGING) #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); StackWalker::OnOutput(szText);
} }
}; };
@ -34,67 +35,67 @@ LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo)
switch(ExceptionInfo->ExceptionRecord->ExceptionCode) switch(ExceptionInfo->ExceptionRecord->ExceptionCode)
{ {
case EXCEPTION_ACCESS_VIOLATION: case EXCEPTION_ACCESS_VIOLATION:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_ACCESS_VIOLATION"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_ACCESS_VIOLATION");
break; break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
break; break;
case EXCEPTION_BREAKPOINT: case EXCEPTION_BREAKPOINT:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_BREAKPOINT"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_BREAKPOINT");
break; break;
case EXCEPTION_DATATYPE_MISALIGNMENT: case EXCEPTION_DATATYPE_MISALIGNMENT:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_DATATYPE_MISALIGNMENT"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_DATATYPE_MISALIGNMENT");
break; break;
case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DENORMAL_OPERAND:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_DENORMAL_OPERAND"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_DENORMAL_OPERAND");
break; break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO: 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; break;
case EXCEPTION_FLT_INEXACT_RESULT: case EXCEPTION_FLT_INEXACT_RESULT:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_INEXACT_RESULT"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_INEXACT_RESULT");
break; break;
case EXCEPTION_FLT_INVALID_OPERATION: case EXCEPTION_FLT_INVALID_OPERATION:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_INVALID_OPERATION"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_INVALID_OPERATION");
break; break;
case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_OVERFLOW:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_OVERFLOW"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_OVERFLOW");
break; break;
case EXCEPTION_FLT_STACK_CHECK: case EXCEPTION_FLT_STACK_CHECK:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_STACK_CHECK"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_STACK_CHECK");
break; break;
case EXCEPTION_FLT_UNDERFLOW: case EXCEPTION_FLT_UNDERFLOW:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_FLT_UNDERFLOW"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_FLT_UNDERFLOW");
break; break;
case EXCEPTION_ILLEGAL_INSTRUCTION: case EXCEPTION_ILLEGAL_INSTRUCTION:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_ILLEGAL_INSTRUCTION"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_ILLEGAL_INSTRUCTION");
break; break;
case EXCEPTION_IN_PAGE_ERROR: case EXCEPTION_IN_PAGE_ERROR:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_IN_PAGE_ERROR"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_IN_PAGE_ERROR");
break; break;
case EXCEPTION_INT_DIVIDE_BY_ZERO: 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; break;
case EXCEPTION_INT_OVERFLOW: case EXCEPTION_INT_OVERFLOW:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_INT_OVERFLOW"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_INT_OVERFLOW");
break; break;
case EXCEPTION_INVALID_DISPOSITION: case EXCEPTION_INVALID_DISPOSITION:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_INVALID_DISPOSITION"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_INVALID_DISPOSITION");
break; break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION: case EXCEPTION_NONCONTINUABLE_EXCEPTION:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_NONCONTINUABLE_EXCEPTION"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_NONCONTINUABLE_EXCEPTION");
break; break;
case EXCEPTION_PRIV_INSTRUCTION: case EXCEPTION_PRIV_INSTRUCTION:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_PRIV_INSTRUCTION"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_PRIV_INSTRUCTION");
break; break;
case EXCEPTION_SINGLE_STEP: case EXCEPTION_SINGLE_STEP:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_SINGLE_STEP"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_SINGLE_STEP");
break; break;
case EXCEPTION_STACK_OVERFLOW: case EXCEPTION_STACK_OVERFLOW:
LogFile->write(EQEMuLog::Crash, "EXCEPTION_STACK_OVERFLOW"); Log.Out(Logs::General, Logs::Crash, "EXCEPTION_STACK_OVERFLOW");
break; break;
default: default:
LogFile->write(EQEMuLog::Crash, "Unknown Exception"); Log.Out(Logs::General, Logs::Crash, "Unknown Exception");
break; break;
} }

File diff suppressed because it is too large Load Diff

View File

@ -21,11 +21,14 @@
#define AUTHENTICATION_TIMEOUT 60 #define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF #define INVALID_ID 0xFFFFFFFF
#include "debug.h" #include "global_define.h"
#include "eqemu_logsys.h"
#include "types.h" #include "types.h"
#include "dbcore.h" #include "dbcore.h"
#include "linked_list.h" #include "linked_list.h"
#include "eq_packet_structs.h" #include "eq_packet_structs.h"
#include <cmath>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
@ -33,22 +36,9 @@
//atoi is not uint32 or uint32 safe!!!! //atoi is not uint32 or uint32 safe!!!!
#define atoul(str) strtoul(str, nullptr, 10) #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 Inventory;
class ItemInst; class MySQLRequestResult;
class Client;
struct EventLogDetails_Struct { struct EventLogDetails_Struct {
uint32 id; uint32 id;
@ -63,193 +53,203 @@ struct EventLogDetails_Struct {
}; };
struct CharacterEventLog_Struct { struct CharacterEventLog_Struct {
uint32 count; uint32 count;
uint8 eventid; uint8 eventid;
EventLogDetails_Struct eld[255]; 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 { struct npcDecayTimes_Struct {
uint16 minlvl; uint16 minlvl;
uint16 maxlvl; uint16 maxlvl;
uint32 seconds; uint32 seconds;
}; };
// Added By Hogie -- End
struct VarCache_Struct { struct VarCache_Struct {
char varname[26]; // varname is char(25) in database char varname[26];
char value[0]; char value[0];
}; };
struct PlayerProfile_Struct;
struct GuildRankLevel_Struct;
struct GuildRanks_Struct;
struct ExtendedProfile_Struct;
struct GuildMember_Struct;
class PTimerList; class PTimerList;
#ifdef _WINDOWS
#if _MSC_VER > 1700 // greater than 2012 (2013+)
# define _ISNAN_(a) std::isnan(a)
#else
# include <float.h>
# define _ISNAN_(a) _isnan(a)
#endif
#else
# define _ISNAN_(a) std::isnan(a)
#endif
class Database : public DBcore { class Database : public DBcore {
public: public:
Database(); Database();
Database(const char* host, const char* user, const char* passwd, const char* database,uint32 port); 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); bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
~Database(); ~Database();
bool ThrowDBError(std::string ErrorMessage, std::string query_title, std::string query);
/*
* General Character Related Stuff
*/
/* Character Creation */ /* 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);
bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid); bool MoveCharacterToZone(const char* charname, const char* zonename,uint32 zoneid);
bool MoveCharacterToZone(uint32 iCharID, const char* iZonename); 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 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 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 StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
bool DeleteCharacter(char* name); bool UpdateName(const char* oldname, const char* newname);
/* /* General Information Queries */
* General Information Getting 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 CheckNameFilter(const char* name, bool surname = false);
bool CheckUsedName(const char* name); bool CheckUsedName(const char* name);
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0); uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id); uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(const char* accname, int16* status = 0, uint32* lsid = 0); 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); uint32 GetGuildIDByCharID(uint32 char_id);
void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0); void GetAccountName(uint32 accountid, char* name, uint32* oLSAccountID = 0);
void GetCharName(uint32 char_id, char* name); 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); void LoginIP(uint32 AccountID, const char* LoginIP);
/* /* Instancing */
* 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();
bool AddClientToInstance(uint16 instance_id, uint32 char_id); 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 RemoveClientFromInstance(uint16 instance_id, uint32 char_id);
bool RemoveClientsFromInstance(uint16 instance_id); bool RemoveClientsFromInstance(uint16 instance_id);
bool CheckInstanceExists(uint16 instance_id); bool VerifyInstanceAlive(uint16 instance_id, uint32 char_id);
void BuryCorpsesInInstance(uint16 instance_id); bool VerifyZoneInstance(uint32 zone_id, uint16 instance_id);
uint16 GetInstanceVersion(uint16 instance_id);
uint16 GetInstanceID(const char* zone, uint32 charid, int16 version); uint16 GetInstanceID(const char* zone, uint32 charid, int16 version);
uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version); uint16 GetInstanceID(uint32 zone, uint32 charid, int16 version);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &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 AssignGroupToInstance(uint32 gid, uint32 instance_id);
void AssignRaidToInstance(uint32 rid, 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 FlagInstanceByGroupLeader(uint32 zone, int16 version, uint32 charid, uint32 gid);
void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid); void FlagInstanceByRaidLeader(uint32 zone, int16 version, uint32 charid, uint32 rid);
void GetCharactersInInstance(uint16 instance_id, std::list<uint32> &charid_list);
void PurgeExpiredInstances();
void SetInstanceDuration(uint16 instance_id, uint32 new_duration); 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); 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, bool GetAdventureStats(uint32 char_id, AdventureStats_Struct *as);
uint32 &guk_l, uint32 &mir_l, uint32 &mmc_l, uint32 &ruj_l, uint32 &tak_l);
/* 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 DeleteAccount(const char* name);
bool GetLiveChar(uint32 account_id, char* cname);
bool SetAccountStatus(const char* name, int16 status); bool SetAccountStatus(const char* name, int16 status);
bool SetLocalPassword(uint32 accid, const char* password); 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); uint32 GetAccountIDFromLSID(uint32 iLSID, char* oAccountName = 0, int16* oStatus = 0);
bool UpdateLiveChar(char* charname,uint32 lsaccount_id); uint32 GetMiniLoginAccount(char* ip);
bool GetLiveChar(uint32 account_id, char* cname);
uint8 GetAgreementFlag(uint32 acctid); uint8 GetAgreementFlag(uint32 acctid);
void GetAccountFromID(uint32 id, char* oAccountName, int16* oStatus);
void SetAgreementFlag(uint32 acctid); 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); /* Groups */
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);
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); 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 GetVariable(const char* varname, char* varvalue, uint16 varvalue_len);
bool SetVariable(const char* varname, const char* varvalue); bool SetVariable(const char* varname, const char* varvalue);
bool LoadVariables(); bool LoadVariables();
uint32 LoadVariables_MQ(char** query); uint32 LoadVariables_MQ(char** query);
bool LoadVariables_result(MySQLRequestResult results); bool LoadVariables_result(MySQLRequestResult results);
/* /* General Queries */
* 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();
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(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); } 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); 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);
uint8 GetRaceSkill(uint8 skillid, uint8 in_race); 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); bool LoadPTimers(uint32 charid, PTimerList &into);
void ClearPTimers(uint32 charid); bool LoadZoneNames();
void ClearMerchantTemp();
void SetLFP(uint32 CharID, bool LFP); const char* GetZoneName(uint32 zoneID, bool ErrorUnknown = false);
void SetLFG(uint32 CharID, bool LFG);
void SetFirstLogon(uint32 CharID, uint8 firstlogon); uint32 GetZoneGraveyardID(uint32 zone_id, uint32 version);
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon); 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 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: private:
void DBInitVars(); void DBInitVars();
@ -261,19 +261,14 @@ private:
VarCache_Struct** varcache_array; VarCache_Struct** varcache_array;
uint32 varcache_lastupdate; uint32 varcache_lastupdate;
/* Groups, utility methods. */
/*
* Groups, utility methods.
*/
void ClearAllGroupLeaders(); void ClearAllGroupLeaders();
void ClearAllGroups(); void ClearAllGroups();
/* Raid, utility methods. */
/*
* Raid, utility methods.
*/
void ClearAllRaids(); void ClearAllRaids();
void ClearAllRaidDetails(); void ClearAllRaidDetails();
void ClearAllRaidLeaders();
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -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 <iomanip>
#include <iostream>
// Disgrace: for windows compile
#ifdef _WINDOWS
#include <windows.h>
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include "unix.h"
#include <netinet/in.h>
#include <sys/time.h>
#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<uint32> &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);
}

View File

@ -1,17 +1,17 @@
#include "../common/debug.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#include <winsock2.h> #include <winsock2.h>
#endif #endif
#include <iostream>
#include <errmsg.h>
#include <mysqld_error.h>
#include <limits.h>
#include "dbcore.h"
#include <string.h>
#include "../common/misc_functions.h" #include "../common/misc_functions.h"
#include <cstdlib> #include "../common/eqemu_logsys.h"
#include "dbcore.h"
#include <errmsg.h>
#include <fstream>
#include <iostream>
#include <mysqld_error.h>
#include <string.h>
#ifdef _WINDOWS #ifdef _WINDOWS
#define snprintf _snprintf #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)); 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); return MySQLRequestResult(nullptr, 0, 0, 0, 0, (uint32)mysql_errno(&mysql), errorBuffer);
} }
char *errorBuffer = new char[MYSQL_ERRMSG_SIZE]; char *errorBuffer = new char[MYSQL_ERRMSG_SIZE];
snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql)); snprintf(errorBuffer, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
#ifdef _EQDEBUG /* Implement Logging at the Root */
std::cout << "DB Query Error #" << mysql_errno(&mysql) << ": " << mysql_error(&mysql) << std::endl; if (mysql_errno(&mysql) > 0 && strlen(query) > 0){
#endif 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); 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); 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)); MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
#if DEBUG_MYSQL_QUERIES >= 1 Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
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
return requestResult; 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) { void DBcore::TransactionBegin() {
if (errnum) QueryDatabase("START TRANSACTION");
*errnum = 0; }
if (errbuf)
errbuf[0] = 0;
bool ret = false;
LockMutex lock(&MDatabase);
if (pStatus != Connected)
Open();
if (mysql_real_query(&mysql, query, querylen)) { void DBcore::TransactionCommit() {
if (mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) QueryDatabase("COMMIT");
pStatus = Error; }
if (mysql_errno(&mysql) == CR_SERVER_LOST || mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) {
if (retry) { void DBcore::TransactionRollback() {
std::cout << "Database Error: Lost connection, attempting to recover...." << std::endl; QueryDatabase("ROLLBACK");
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;
} }
uint32 DBcore::DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen) { uint32 DBcore::DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen) {

View File

@ -6,15 +6,12 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include "../common/mutex.h"
#include "../common/mysql_request_result.h"
#include "../common/types.h"
#include <mysql.h> #include <mysql.h>
#include <string.h> #include <string.h>
#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 { class DBcore {
public: public:
@ -23,9 +20,11 @@ public:
DBcore(); DBcore();
~DBcore(); ~DBcore();
eStatus GetStatus() { return pStatus; } 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(const char* query, uint32 querylen, bool retryOnFailureOnce = true);
MySQLRequestResult QueryDatabase(std::string query, 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); uint32 DoEscapeString(char* tobuf, const char* frombuf, uint32 fromlen);
void ping(); void ping();
MYSQL* getMySQL(){ return &mysql; } MYSQL* getMySQL(){ return &mysql; }

View File

@ -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; i<max_door_type; i++) {
const Door* door = GetDoorDBID(i);
if(door && door->door_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

View File

@ -1,441 +0,0 @@
#include <iostream>
#include <string>
#include <cstdarg>
#include <time.h>
#ifdef _WINDOWS
#include <process.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include <sys/types.h>
#include <unistd.h>
#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; i++) {
fp[i] = 0;
logCallbackFmt[i] = nullptr;
logCallbackBuf[i] = nullptr;
logCallbackPva[i] = nullptr;
}
pLogStatus[Status] = LOG_LEVEL_STATUS;
pLogStatus[Normal] = LOG_LEVEL_NORMAL;
pLogStatus[Error] = LOG_LEVEL_ERROR;
pLogStatus[Debug] = LOG_LEVEL_DEBUG;
pLogStatus[Quest] = LOG_LEVEL_QUEST;
pLogStatus[Commands] = LOG_LEVEL_COMMANDS;
pLogStatus[Crash] = LOG_LEVEL_CRASH;
logFileValid = true;
}
EQEMuLog::~EQEMuLog() {
logFileValid = false;
for (int i=0; i<MaxLogID; i++) {
LockMutex lock(&MLog[i]); //to prevent termination race
if (fp[i])
fclose(fp[i]);
}
}
bool EQEMuLog::open(LogIDs id) {
if (!logFileValid) {
return false;
}
if (id >= MaxLogID) {
return false;
}
LockMutex lock(&MOpen);
if (pLogStatus[id] & 4) {
return false;
}
if (fp[id]) {
//cerr<<"Warning: LogFile already open"<<endl;
return true;
}
char exename[200] = "";
const EQEmuExePlatform &platform = GetExecutablePlatform();
if(platform == ExePlatformWorld) {
snprintf(exename, sizeof(exename), "_world");
} else if(platform == ExePlatformZone) {
snprintf(exename, sizeof(exename), "_zone");
} else if(platform == ExePlatformLaunch) {
snprintf(exename, sizeof(exename), "_launch");
} else if(platform == ExePlatformUCS) {
snprintf(exename, sizeof(exename), "_ucs");
} else if(platform == ExePlatformQueryServ) {
snprintf(exename, sizeof(exename), "_queryserv");
} else if(platform == ExePlatformSharedMemory) {
snprintf(exename, sizeof(exename), "_shared_memory");
} else if(platform == ExePlatformClientImport) {
snprintf(exename, sizeof(exename), "_import");
} else if(platform == ExePlatformClientExport) {
snprintf(exename, sizeof(exename), "_export");
}
char filename[200];
#ifndef NO_PIDLOG
snprintf(filename, sizeof(filename), "%s%s_%04i.log", FileNames[id], exename, getpid());
#else
snprintf(filename, sizeof(filename), "%s%s.log", FileNames[id], exename);
#endif
fp[id] = fopen(filename, "a");
if (!fp[id]) {
std::cerr << "Failed to open log file: " << filename << std::endl;
pLogStatus[id] |= 4; // set file state to error
return false;
}
fputs("---------------------------------------------\n",fp[id]);
write(id, "Starting Log: %s", filename);
return true;
}
bool EQEMuLog::write(LogIDs id, const char *fmt, ...) {
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
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<size; indexInData++) {
if ((indexInData-skip)%cols==0) {
if (indexInData != skip)
writeNTS(id, dofile, " | %s\n", asciiOutput.c_str());
writeNTS(id, dofile, "%4i: ", indexInData-skip);
asciiOutput.clear();
beginningOfLineOffset = 0;
}
else if ((indexInData-skip)%(cols/2) == 0) {
writeNTS(id, dofile, "- ");
}
writeNTS(id, dofile, "%02X ", (unsigned char)data[indexInData]);
if (data[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);
}
}

View File

@ -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 <stdlib.h>
#include <crtdbg.h>
#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 <winsock.h>
#endif
#ifdef _WINDOWS
#include <windows.h>
#include <winsock2.h>
#endif
#include "logsys.h"
#include "../common/mutex.h"
#include <stdio.h>
#include <stdarg.h>
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

View File

@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/ */
#include "debug.h" #include "global_define.h"
#include "emu_opcodes.h" #include "emu_opcodes.h"
const char *OpcodeNames[_maxEmuOpcode+1] = { const char *OpcodeNames[_maxEmuOpcode+1] = {

View File

@ -74,7 +74,9 @@ N(OP_CharacterCreateRequest),
N(OP_CharInventory), N(OP_CharInventory),
N(OP_Charm), N(OP_Charm),
N(OP_ChatMessage), N(OP_ChatMessage),
N(OP_ClearAA),
N(OP_ClearBlockedBuffs), N(OP_ClearBlockedBuffs),
N(OP_ClearLeadershipAbilities),
N(OP_ClearNPCMarks), N(OP_ClearNPCMarks),
N(OP_ClearObject), N(OP_ClearObject),
N(OP_ClearSurname), N(OP_ClearSurname),
@ -207,6 +209,7 @@ N(OP_GroupInvite2),
N(OP_GroupLeaderChange), N(OP_GroupLeaderChange),
N(OP_GroupLeadershipAAUpdate), N(OP_GroupLeadershipAAUpdate),
N(OP_GroupMakeLeader), N(OP_GroupMakeLeader),
N(OP_GroupMentor),
N(OP_GroupRoles), N(OP_GroupRoles),
N(OP_GroupUpdate), N(OP_GroupUpdate),
N(OP_GroupUpdateB), N(OP_GroupUpdateB),
@ -244,6 +247,7 @@ N(OP_IncreaseStats),
N(OP_InitialHPUpdate), N(OP_InitialHPUpdate),
N(OP_InitialMobHealth), N(OP_InitialMobHealth),
N(OP_InspectAnswer), N(OP_InspectAnswer),
N(OP_InspectBuffs),
N(OP_InspectMessageUpdate), N(OP_InspectMessageUpdate),
N(OP_InspectRequest), N(OP_InspectRequest),
N(OP_InstillDoubt), N(OP_InstillDoubt),

View File

@ -23,17 +23,14 @@ crap into its own subclass of this object, it will clean things up
tremendously. tremendously.
*/ */
#include "../common/debug.h" #include "../common/global_define.h"
#include <iostream> #include <iostream>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <iomanip>
#include "emu_tcp_connection.h" #include "emu_tcp_connection.h"
#include "emu_tcp_server.h" #include "emu_tcp_server.h"
#include "../common/servertalk.h" #include "../common/servertalk.h"
#include "../common/packet_dump.h"
#ifdef FREEBSD //Timothy Whitman - January 7, 2003 #ifdef FREEBSD //Timothy Whitman - January 7, 2003
#define MSG_NOSIGNAL 0 #define MSG_NOSIGNAL 0
@ -107,7 +104,7 @@ EmuTCPConnection::EmuTCPConnection(uint32 ID, EmuTCPServer* iServer, EmuTCPConne
RelayCount = 0; RelayCount = 0;
RemoteID = iRemoteID; RemoteID = iRemoteID;
pOldFormat = false; pOldFormat = false;
ConnectionType = Incomming; ConnectionType = Incoming;
TCPMode = modePacket; TCPMode = modePacket;
PacketMode = packetModeZone; PacketMode = packetModeZone;
#if TCPN_DEBUG_Memory >= 7 #if TCPN_DEBUG_Memory >= 7
@ -717,7 +714,7 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) {
SendNetErrorPacket("Switch to RelayServer mode by a Relay Client"); SendNetErrorPacket("Switch to RelayServer mode by a Relay Client");
break; break;
} }
if (ConnectionType != Incomming) { if (ConnectionType != Incoming) {
SendNetErrorPacket("Switch to RelayServer mode on outgoing connection"); SendNetErrorPacket("Switch to RelayServer mode on outgoing connection");
break; break;
} }
@ -738,7 +735,7 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) {
SendNetErrorPacket("New RelayClient: wrong size, expected 11"); SendNetErrorPacket("New RelayClient: wrong size, expected 11");
break; break;
} }
if (ConnectionType != Incomming) { if (ConnectionType != Incoming) {
SendNetErrorPacket("New RelayClient: illegal on outgoing connection"); SendNetErrorPacket("New RelayClient: illegal on outgoing connection");
break; break;
} }
@ -758,7 +755,7 @@ void EmuTCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) {
} }
EmuTCPConnection* con = Server->FindConnection(*((uint32*)data)); EmuTCPConnection* con = Server->FindConnection(*((uint32*)data));
if (con) { if (con) {
if (ConnectionType == Incomming) { if (ConnectionType == Incoming) {
if (con->GetRelayLink() != this) { if (con->GetRelayLink() != this) {
SendNetErrorPacket("Delete RelayClient: RelayLink != this"); SendNetErrorPacket("Delete RelayClient: RelayLink != this");
break; break;

View File

@ -26,6 +26,7 @@
struct SPackSendQueue; struct SPackSendQueue;
class EmuTCPServer; class EmuTCPServer;
class ServerPacket;
class EmuTCPConnection : public TCPConnection { class EmuTCPConnection : public TCPConnection {
public: public:

View File

@ -1,4 +1,4 @@
#include "debug.h" #include "global_define.h"
#include "emu_tcp_server.h" #include "emu_tcp_server.h"
#include "emu_tcp_connection.h" #include "emu_tcp_connection.h"

View File

@ -19,6 +19,7 @@
#define EQ_CONSTANTS_H #define EQ_CONSTANTS_H
#include "skills.h" #include "skills.h"
#include "types.h"
/* /*
** Item attributes ** Item attributes
@ -367,7 +368,7 @@ enum {
#define AT_DamageState 44 // The damage state of a destructible object (0 through 4) #define AT_DamageState 44 // The damage state of a destructible object (0 through 4)
//#define AT_Trader 300 // Bazzar Trader Mode //#define AT_Trader 300 // Bazzar Trader Mode
// solar: animations for AT_Anim // animations for AT_Anim
#define ANIM_FREEZE 102 #define ANIM_FREEZE 102
#define ANIM_STAND 0x64 #define ANIM_STAND 0x64
#define ANIM_SIT 0x6e #define ANIM_SIT 0x6e
@ -968,4 +969,6 @@ namespace legacy {
} InventorySlot; } InventorySlot;
} }
static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
#endif #endif

View File

@ -25,8 +25,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// //
// class EmuConstants // class EmuConstants
// //
uint16 EmuConstants::InventoryMapSize(int16 map) { uint16 EmuConstants::InventoryMapSize(int16 indexMap) {
switch (map) { switch (indexMap) {
case MapPossessions: case MapPossessions:
return MAP_POSSESSIONS_SIZE; return MAP_POSSESSIONS_SIZE;
case MapBank: case MapBank:
@ -91,8 +91,8 @@ std::string EmuConstants::InventoryLocationName(Location_Struct location) {
} }
*/ */
std::string EmuConstants::InventoryMapName(int16 map) { std::string EmuConstants::InventoryMapName(int16 indexMap) {
switch (map) { switch (indexMap) {
case INVALID_INDEX: case INVALID_INDEX:
return "Invalid Map"; return "Invalid Map";
case MapPossessions: case MapPossessions:
@ -150,8 +150,8 @@ std::string EmuConstants::InventoryMapName(int16 map) {
} }
} }
std::string EmuConstants::InventoryMainName(int16 main) { std::string EmuConstants::InventoryMainName(int16 indexMain) {
switch (main) { switch (indexMain) {
case INVALID_INDEX: case INVALID_INDEX:
return "Invalid Main"; return "Invalid Main";
case MainCharm: case MainCharm:
@ -229,293 +229,83 @@ std::string EmuConstants::InventoryMainName(int16 main) {
} }
} }
std::string EmuConstants::InventorySubName(int16 sub) { std::string EmuConstants::InventorySubName(int16 indexSub) {
if (sub == INVALID_INDEX) if (indexSub == INVALID_INDEX)
return "Invalid Sub"; return "Invalid Sub";
if ((uint16)sub >= ITEM_CONTAINER_SIZE) if ((uint16)indexSub >= ITEM_CONTAINER_SIZE)
return "Unknown Sub"; return "Unknown Sub";
std::string ret_str; 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; return ret_str;
} }
std::string EmuConstants::InventoryAugName(int16 aug) { std::string EmuConstants::InventoryAugName(int16 indexAug) {
if (aug == INVALID_INDEX) if (indexAug == INVALID_INDEX)
return "Invalid Aug"; return "Invalid Aug";
if ((uint16)aug >= ITEM_COMMON_SIZE) if ((uint16)indexAug >= ITEM_COMMON_SIZE)
return "Unknown Aug"; return "Unknown Aug";
std::string ret_str; 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; 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 // class EQLimits
// //
// client validation // client validation
bool EQLimits::IsValidClientVersion(uint32 version) { bool EQLimits::IsValidPCClientVersion(ClientVersion clientVersion) {
if (version < _EQClientCount) if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT)
return true; return true;
return false; return false;
} }
uint32 EQLimits::ValidateClientVersion(uint32 version) { ClientVersion EQLimits::ValidatePCClientVersion(ClientVersion clientVersion) {
if (version < _EQClientCount) if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_PC_CLIENT)
return version; return clientVersion;
return EQClientUnknown; return ClientVersion::Unknown;
}
EQClientVersion EQLimits::ValidateClientVersion(EQClientVersion version) {
if (version >= EQClientUnknown)
if (version < _EQClientCount)
return version;
return EQClientUnknown;
} }
// npc validation // npc validation
bool EQLimits::IsValidNPCVersion(uint32 version) { bool EQLimits::IsValidNPCClientVersion(ClientVersion clientVersion) {
if (version >= _EQClientCount) if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT)
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)
return true; return true;
return false; return false;
} }
uint32 EQLimits::ValidateMobVersion(uint32 version) { ClientVersion EQLimits::ValidateNPCClientVersion(ClientVersion clientVersion) {
if (version < _EmuClientCount) if (clientVersion > LAST_PC_CLIENT && clientVersion <= LAST_NPC_CLIENT)
return version; return clientVersion;
return EQClientUnknown; return ClientVersion::Unknown;
} }
EQClientVersion EQLimits::ValidateMobVersion(EQClientVersion version) { // mob validation
if (version >= EQClientUnknown) bool EQLimits::IsValidMobClientVersion(ClientVersion clientVersion) {
if (version < _EmuClientCount) if (clientVersion > ClientVersion::Unknown && clientVersion <= LAST_NPC_CLIENT)
return version; 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 // 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...) // 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 // 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 // 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::<property> or NOT_USED value to avoid unnecessary issues // when setting NPC-based values, try to adhere to an EmuConstants::<property> 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 // 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() // 'EmuConstants::MAP_POSSESSIONS_SIZE' - use/update EquipmentBitmask(), GeneralBitmask() and CursorBitmask()
// for partial range validation checks and 'EmuConstants::MAP_POSSESSIONS_SIZE' for full range iterations // 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, /*SoD*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*Underfoot*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*RoF*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*NPC*/ EmuConstants::MAP_POSSESSIONS_SIZE,
/*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE, /*Merc*/ EmuConstants::MAP_POSSESSIONS_SIZE,
@ -548,13 +338,13 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
}, },
{ // local[MapBank] { // local[MapBank]
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ Client62::consts::MAP_BANK_SIZE, /*62*/ NOT_USED,
/*Titanium*/ Titanium::consts::MAP_BANK_SIZE, /*Titanium*/ Titanium::consts::MAP_BANK_SIZE,
/*SoF*/ EmuConstants::MAP_BANK_SIZE, /*SoF*/ EmuConstants::MAP_BANK_SIZE,
/*SoD*/ EmuConstants::MAP_BANK_SIZE, /*SoD*/ EmuConstants::MAP_BANK_SIZE,
/*Underfoot*/ EmuConstants::MAP_BANK_SIZE, /*Underfoot*/ EmuConstants::MAP_BANK_SIZE,
/*RoF*/ EmuConstants::MAP_BANK_SIZE, /*RoF*/ EmuConstants::MAP_BANK_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_BANK_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -569,7 +359,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*SoD*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*Underfoot*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE, /*RoF*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_SHARED_BANK_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -584,7 +374,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_TRADE_SIZE, /*SoD*/ EmuConstants::MAP_TRADE_SIZE,
/*Underfoot*/ EmuConstants::MAP_TRADE_SIZE, /*Underfoot*/ EmuConstants::MAP_TRADE_SIZE,
/*RoF*/ EmuConstants::MAP_TRADE_SIZE, /*RoF*/ EmuConstants::MAP_TRADE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_TRADE_SIZE,
/*NPC*/ 4, /*NPC*/ 4,
/*Merc*/ 4, /*Merc*/ 4,
@ -599,7 +389,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_WORLD_SIZE, /*SoD*/ EmuConstants::MAP_WORLD_SIZE,
/*Underfoot*/ EmuConstants::MAP_WORLD_SIZE, /*Underfoot*/ EmuConstants::MAP_WORLD_SIZE,
/*RoF*/ EmuConstants::MAP_WORLD_SIZE, /*RoF*/ EmuConstants::MAP_WORLD_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_WORLD_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -614,7 +404,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_LIMBO_SIZE, /*SoD*/ EmuConstants::MAP_LIMBO_SIZE,
/*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE, /*Underfoot*/ EmuConstants::MAP_LIMBO_SIZE,
/*RoF*/ EmuConstants::MAP_LIMBO_SIZE, /*RoF*/ EmuConstants::MAP_LIMBO_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_LIMBO_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -629,7 +419,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE, /*SoD*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE, /*Underfoot*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE, /*RoF*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_TRIBUTE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -644,7 +434,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE, /*RoF*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_TROPHY_TRIBUTE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -659,7 +449,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE, /*RoF*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_GUILD_TRIBUTE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -674,7 +464,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_MERCHANT_SIZE, /*RoF*/ EmuConstants::MAP_MERCHANT_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_MERCHANT_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -689,7 +479,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_DELETED_SIZE, /*RoF*/ EmuConstants::MAP_DELETED_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_DELETED_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -698,13 +488,13 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
}, },
{ // local[MapCorpse] { // local[MapCorpse]
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ Client62::consts::MAP_CORPSE_SIZE, /*62*/ NOT_USED,
/*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE, /*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE,
/*SoF*/ SoF::consts::MAP_CORPSE_SIZE, /*SoF*/ SoF::consts::MAP_CORPSE_SIZE,
/*SoD*/ SoD::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, /*RoF*/ RoF::consts::MAP_CORPSE_SIZE,
/*RoF2*/ 0, /*RoF2*/ RoF2::consts::MAP_CORPSE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -719,7 +509,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ EmuConstants::MAP_BAZAAR_SIZE, /*SoD*/ EmuConstants::MAP_BAZAAR_SIZE,
/*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE, /*Underfoot*/ EmuConstants::MAP_BAZAAR_SIZE,
/*RoF*/ 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 /*NPC*/ 0, // this may need to be 'EmuConstants::MAP_BAZAAR_SIZE' if offline client traders respawn as an npc
/*Merc*/ 0, /*Merc*/ 0,
@ -728,13 +518,13 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
}, },
{ // local[MapInspect] { // local[MapInspect]
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ Client62::consts::MAP_INSPECT_SIZE, /*62*/ NOT_USED,
/*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE, /*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE,
/*SoF*/ SoF::consts::MAP_INSPECT_SIZE, /*SoF*/ SoF::consts::MAP_INSPECT_SIZE,
/*SoD*/ SoD::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, /*RoF*/ RoF::consts::MAP_INSPECT_SIZE,
/*RoF2*/ 0, /*RoF2*/ RoF2::consts::MAP_INSPECT_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -749,7 +539,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE, /*RoF*/ EmuConstants::MAP_REAL_ESTATE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_REAL_ESTATE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -764,7 +554,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE, /*RoF*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_VIEW_MOD_PC_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -779,7 +569,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE, /*RoF*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_VIEW_MOD_BANK_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -794,7 +584,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE, /*RoF*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_VIEW_MOD_SHARED_BANK_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -809,7 +599,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE, /*RoF*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_VIEW_MOD_LIMBO_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -824,7 +614,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE, /*RoF*/ EmuConstants::MAP_ALT_STORAGE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_ALT_STORAGE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -839,7 +629,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE, /*RoF*/ EmuConstants::MAP_ARCHIVED_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_ARCHIVED_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -854,7 +644,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_MAIL_SIZE, /*RoF*/ EmuConstants::MAP_MAIL_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_MAIL_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -869,7 +659,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE, /*RoF*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_GUILD_TROPHY_TRIBUTE_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -884,7 +674,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ NOT_USED, /*SoD*/ NOT_USED,
/*Underfoot*/ NOT_USED, /*Underfoot*/ NOT_USED,
/*RoF*/ EmuConstants::MAP_KRONO_SIZE, /*RoF*/ EmuConstants::MAP_KRONO_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_KRONO_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -899,7 +689,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
/*SoD*/ 0, /*SoD*/ 0,
/*Underfoot*/ 0, /*Underfoot*/ 0,
/*RoF*/ EmuConstants::MAP_OTHER_SIZE, /*RoF*/ EmuConstants::MAP_OTHER_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::MAP_OTHER_SIZE,
/*NPC*/ 0, /*NPC*/ 0,
/*Merc*/ 0, /*Merc*/ 0,
@ -908,19 +698,19 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
} }
}; };
if ((uint16)map < _MapCount) if ((uint16)indexMap < _MapCount)
return local[map][ValidateMobVersion(version)]; return local[indexMap][static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
return NOT_USED; 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... // these are for the new inventory system (RoF)..not the current (Ti) one...
// 0x0000000000200000 is SlotPowerSource (SoF+) // 0x0000000000200000 is SlotPowerSource (SoF+)
// 0x0000000080000000 is SlotGeneral9 (RoF+) // 0x0000000080000000 is SlotGeneral9 (RoF+)
// 0x0000000100000000 is SlotGeneral10 (RoF+) // 0x0000000100000000 is SlotGeneral10 (RoF+)
static const uint64 local[_EmuClientCount] = { static const uint64 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ 0x000000027FDFFFFF, /*62*/ 0x000000027FDFFFFF,
/*Titanium*/ 0x000000027FDFFFFF, /*Titanium*/ 0x000000027FDFFFFF,
@ -937,11 +727,11 @@ uint64 EQLimits::PossessionsBitmask(uint32 version) {
}; };
return NOT_USED; return NOT_USED;
//return local[ValidateMobVersion(version)]; //return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint64 EQLimits::EquipmentBitmask(uint32 version) { uint64 EQLimits::EquipmentBitmask(ClientVersion clientVersion) {
static const uint64 local[_EmuClientCount] = { static const uint64 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ 0x00000000005FFFFF, /*62*/ 0x00000000005FFFFF,
/*Titanium*/ 0x00000000005FFFFF, /*Titanium*/ 0x00000000005FFFFF,
@ -958,11 +748,11 @@ uint64 EQLimits::EquipmentBitmask(uint32 version) {
}; };
return NOT_USED; return NOT_USED;
//return local[ValidateMobVersion(version)]; //return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint64 EQLimits::GeneralBitmask(uint32 version) { uint64 EQLimits::GeneralBitmask(ClientVersion clientVersion) {
static const uint64 local[_EmuClientCount] = { static const uint64 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ 0x000000007F800000, /*62*/ 0x000000007F800000,
/*Titanium*/ 0x000000007F800000, /*Titanium*/ 0x000000007F800000,
@ -979,11 +769,11 @@ uint64 EQLimits::GeneralBitmask(uint32 version) {
}; };
return NOT_USED; return NOT_USED;
//return local[ValidateMobVersion(version)]; //return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint64 EQLimits::CursorBitmask(uint32 version) { uint64 EQLimits::CursorBitmask(ClientVersion clientVersion) {
static const uint64 local[_EmuClientCount] = { static const uint64 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ 0x0000000200000000, /*62*/ 0x0000000200000000,
/*Titanium*/ 0x0000000200000000, /*Titanium*/ 0x0000000200000000,
@ -1000,19 +790,19 @@ uint64 EQLimits::CursorBitmask(uint32 version) {
}; };
return NOT_USED; return NOT_USED;
//return local[ValidateMobVersion(version)]; //return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
bool EQLimits::AllowsEmptyBagInBag(uint32 version) { bool EQLimits::AllowsEmptyBagInBag(ClientVersion clientVersion) {
static const bool local[_EmuClientCount] = { static const bool local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ false, /*Unknown*/ false,
/*62*/ Client62::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*62*/ false,
/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG, /*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*SoD*/ SoD::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, /*RoF*/ RoF::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*RoF2*/ false, /*RoF2*/ RoF2::limits::ALLOWS_EMPTY_BAG_IN_BAG,
/*NPC*/ false, /*NPC*/ false,
/*Merc*/ false, /*Merc*/ false,
@ -1021,19 +811,19 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
}; };
return false; // not implemented return false; // not implemented
//return local[ValidateMobVersion(version)]; //return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
bool EQLimits::AllowsClickCastFromBag(uint32 version) { bool EQLimits::AllowsClickCastFromBag(ClientVersion clientVersion) {
static const bool local[_EmuClientCount] = { static const bool local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ false, /*Unknown*/ false,
/*62*/ Client62::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*62*/ false,
/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG, /*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*SoD*/ SoD::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, /*RoF*/ RoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*RoF2*/ false, /*RoF2*/ RoF2::limits::ALLOWS_CLICK_CAST_FROM_BAG,
/*NPC*/ false, /*NPC*/ false,
/*Merc*/ false, /*Merc*/ false,
@ -1041,12 +831,12 @@ bool EQLimits::AllowsClickCastFromBag(uint32 version) {
/*Pet*/ false /*Pet*/ false
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
// items // items
uint16 EQLimits::ItemCommonSize(uint32 version) { uint16 EQLimits::ItemCommonSize(ClientVersion clientVersion) {
static const uint16 local[_EmuClientCount] = { static const uint16 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ EmuConstants::ITEM_COMMON_SIZE, /*62*/ EmuConstants::ITEM_COMMON_SIZE,
/*Titanium*/ EmuConstants::ITEM_COMMON_SIZE, /*Titanium*/ EmuConstants::ITEM_COMMON_SIZE,
@ -1054,7 +844,7 @@ uint16 EQLimits::ItemCommonSize(uint32 version) {
/*SoD*/ EmuConstants::ITEM_COMMON_SIZE, /*SoD*/ EmuConstants::ITEM_COMMON_SIZE,
/*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE, /*Underfoot*/ EmuConstants::ITEM_COMMON_SIZE,
/*RoF*/ EmuConstants::ITEM_COMMON_SIZE, /*RoF*/ EmuConstants::ITEM_COMMON_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::ITEM_COMMON_SIZE,
/*NPC*/ EmuConstants::ITEM_COMMON_SIZE, /*NPC*/ EmuConstants::ITEM_COMMON_SIZE,
/*Merc*/ EmuConstants::ITEM_COMMON_SIZE, /*Merc*/ EmuConstants::ITEM_COMMON_SIZE,
@ -1062,11 +852,11 @@ uint16 EQLimits::ItemCommonSize(uint32 version) {
/*Pet*/ EmuConstants::ITEM_COMMON_SIZE /*Pet*/ EmuConstants::ITEM_COMMON_SIZE
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint16 EQLimits::ItemContainerSize(uint32 version) { uint16 EQLimits::ItemContainerSize(ClientVersion clientVersion) {
static const uint16 local[_EmuClientCount] = { static const uint16 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ EmuConstants::ITEM_CONTAINER_SIZE, /*62*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*Titanium*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Titanium*/ EmuConstants::ITEM_CONTAINER_SIZE,
@ -1074,7 +864,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) {
/*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE, /*SoD*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Underfoot*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE, /*RoF*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE, /*NPC*/ EmuConstants::ITEM_CONTAINER_SIZE,
/*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE, /*Merc*/ EmuConstants::ITEM_CONTAINER_SIZE,
@ -1082,19 +872,19 @@ uint16 EQLimits::ItemContainerSize(uint32 version) {
/*Pet*/ EmuConstants::ITEM_CONTAINER_SIZE /*Pet*/ EmuConstants::ITEM_CONTAINER_SIZE
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
bool EQLimits::CoinHasWeight(uint32 version) { bool EQLimits::CoinHasWeight(ClientVersion clientVersion) {
static const bool local[_EmuClientCount] = { static const bool local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ true, /*Unknown*/ true,
/*62*/ Client62::limits::COIN_HAS_WEIGHT, /*62*/ true,
/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT, /*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT,
/*SoF*/ SoF::limits::COIN_HAS_WEIGHT, /*SoF*/ SoF::limits::COIN_HAS_WEIGHT,
/*SoD*/ SoD::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, /*RoF*/ RoF::limits::COIN_HAS_WEIGHT,
/*RoF2*/ true, /*RoF2*/ RoF::limits::COIN_HAS_WEIGHT,
/*NPC*/ true, /*NPC*/ true,
/*Merc*/ true, /*Merc*/ true,
@ -1102,11 +892,11 @@ bool EQLimits::CoinHasWeight(uint32 version) {
/*Pet*/ true /*Pet*/ true
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint32 EQLimits::BandoliersCount(uint32 version) { uint32 EQLimits::BandoliersCount(ClientVersion clientVersion) {
static const uint32 local[_EmuClientCount] = { static const uint32 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ EmuConstants::BANDOLIERS_COUNT, /*62*/ EmuConstants::BANDOLIERS_COUNT,
/*Titanium*/ EmuConstants::BANDOLIERS_COUNT, /*Titanium*/ EmuConstants::BANDOLIERS_COUNT,
@ -1114,7 +904,7 @@ uint32 EQLimits::BandoliersCount(uint32 version) {
/*SoD*/ EmuConstants::BANDOLIERS_COUNT, /*SoD*/ EmuConstants::BANDOLIERS_COUNT,
/*Underfoot*/ EmuConstants::BANDOLIERS_COUNT, /*Underfoot*/ EmuConstants::BANDOLIERS_COUNT,
/*RoF*/ EmuConstants::BANDOLIERS_COUNT, /*RoF*/ EmuConstants::BANDOLIERS_COUNT,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::BANDOLIERS_COUNT,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -1122,11 +912,11 @@ uint32 EQLimits::BandoliersCount(uint32 version) {
/*Pet*/ NOT_USED /*Pet*/ NOT_USED
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint32 EQLimits::BandolierSize(uint32 version) { uint32 EQLimits::BandolierSize(ClientVersion clientVersion) {
static const uint32 local[_EmuClientCount] = { static const uint32 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ EmuConstants::BANDOLIER_SIZE, /*62*/ EmuConstants::BANDOLIER_SIZE,
/*Titanium*/ EmuConstants::BANDOLIER_SIZE, /*Titanium*/ EmuConstants::BANDOLIER_SIZE,
@ -1134,7 +924,7 @@ uint32 EQLimits::BandolierSize(uint32 version) {
/*SoD*/ EmuConstants::BANDOLIER_SIZE, /*SoD*/ EmuConstants::BANDOLIER_SIZE,
/*Underfoot*/ EmuConstants::BANDOLIER_SIZE, /*Underfoot*/ EmuConstants::BANDOLIER_SIZE,
/*RoF*/ EmuConstants::BANDOLIER_SIZE, /*RoF*/ EmuConstants::BANDOLIER_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::BANDOLIER_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -1142,11 +932,11 @@ uint32 EQLimits::BandolierSize(uint32 version) {
/*Pet*/ NOT_USED /*Pet*/ NOT_USED
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }
uint32 EQLimits::PotionBeltSize(uint32 version) { uint32 EQLimits::PotionBeltSize(ClientVersion clientVersion) {
static const uint32 local[_EmuClientCount] = { static const uint32 local[CLIENT_VERSION_COUNT] = {
/*Unknown*/ NOT_USED, /*Unknown*/ NOT_USED,
/*62*/ EmuConstants::POTION_BELT_SIZE, /*62*/ EmuConstants::POTION_BELT_SIZE,
/*Titanium*/ EmuConstants::POTION_BELT_SIZE, /*Titanium*/ EmuConstants::POTION_BELT_SIZE,
@ -1154,7 +944,7 @@ uint32 EQLimits::PotionBeltSize(uint32 version) {
/*SoD*/ EmuConstants::POTION_BELT_SIZE, /*SoD*/ EmuConstants::POTION_BELT_SIZE,
/*Underfoot*/ EmuConstants::POTION_BELT_SIZE, /*Underfoot*/ EmuConstants::POTION_BELT_SIZE,
/*RoF*/ EmuConstants::POTION_BELT_SIZE, /*RoF*/ EmuConstants::POTION_BELT_SIZE,
/*RoF2*/ 0, /*RoF2*/ EmuConstants::POTION_BELT_SIZE,
/*NPC*/ NOT_USED, /*NPC*/ NOT_USED,
/*Merc*/ NOT_USED, /*Merc*/ NOT_USED,
@ -1162,5 +952,5 @@ uint32 EQLimits::PotionBeltSize(uint32 version) {
/*Pet*/ NOT_USED /*Pet*/ NOT_USED
}; };
return local[ValidateMobVersion(version)]; return local[static_cast<unsigned int>(ValidateMobClientVersion(clientVersion))];
} }

View File

@ -26,13 +26,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "eq_constants.h" #include "eq_constants.h"
#include "clientversions.h" #include "clientversions.h"
#include <string> #include <string>
#include "../common/patches/client62_constants.h"
#include "../common/patches/titanium_constants.h" #include "../common/patches/titanium_constants.h"
#include "../common/patches/sof_constants.h" #include "../common/patches/sof_constants.h"
#include "../common/patches/sod_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/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!! *** // *** 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!! *** // *** 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 // an immutable value is required to initialize arrays, etc... use this class as a repository for those
public: public:
// database // 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 // inventory
static uint16 InventoryMapSize(int16 map); static uint16 InventoryMapSize(int16 indexMap);
//static std::string InventoryLocationName(Location_Struct location); //static std::string InventoryLocationName(Location_Struct location);
static std::string InventoryMapName(int16 map); static std::string InventoryMapName(int16 indexMap);
static std::string InventoryMainName(int16 main); static std::string InventoryMainName(int16 indexMain);
static std::string InventorySubName(int16 sub); static std::string InventorySubName(int16 indexSub);
static std::string InventoryAugName(int16 aug); 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 // 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; static const uint16 MAP_POSSESSIONS_SIZE = _MainCount;
@ -138,8 +137,8 @@ public:
// items // items
// common and container sizes will not increase until the new 'location' struct is implemented // 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_COMMON_SIZE = RoF::consts::ITEM_COMMON_SIZE;
static const uint16 ITEM_CONTAINER_SIZE = Underfoot::consts::ITEM_CONTAINER_SIZE; static const uint16 ITEM_CONTAINER_SIZE = Titanium::consts::ITEM_CONTAINER_SIZE;
// player profile // player profile
//static const uint32 CLASS_BITMASK = 0; // needs value //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 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 uint32 POTION_BELT_SIZE = Titanium::consts::POTION_BELT_SIZE;
static const size_t TEXT_LINK_BODY_LENGTH = 56;
// legacy-related functions // legacy-related functions
//static int ServerToPerlSlot(int slot); // encode //static int ServerToPerlSlot(int slot); // encode
//static int PerlToServerSlot(int slot); // decode //static int PerlToServerSlot(int slot); // decode
@ -162,44 +163,41 @@ class EQLimits {
public: public:
// client version validation (checks to avoid crashing zone server when accessing reference arrays) // client version validation (checks to avoid crashing zone server when accessing reference arrays)
// use this inside of class Client (limits to actual clients) // use this inside of class Client (limits to actual clients)
static bool IsValidClientVersion(uint32 version); static bool IsValidPCClientVersion(ClientVersion clientVersion);
static uint32 ValidateClientVersion(uint32 version); static ClientVersion ValidatePCClientVersion(ClientVersion clientVersion);
static EQClientVersion ValidateClientVersion(EQClientVersion version);
// basically..any non-client classes - do not when setting a valid client // basically..any non-client classes - do not when setting a valid client
static bool IsValidNPCVersion(uint32 version); static bool IsValidNPCClientVersion(ClientVersion clientVersion);
static uint32 ValidateNPCVersion(uint32 version); static ClientVersion ValidateNPCClientVersion(ClientVersion clientVersion);
static EQClientVersion ValidateNPCVersion(EQClientVersion version);
// these are 'universal' - do not when setting a valid client // these are 'universal' - do not when setting a valid client
static bool IsValidMobVersion(uint32 version); static bool IsValidMobClientVersion(ClientVersion clientVersion);
static uint32 ValidateMobVersion(uint32 version); static ClientVersion ValidateMobClientVersion(ClientVersion clientVersion);
static EQClientVersion ValidateMobVersion(EQClientVersion version);
// inventory // inventory
static uint16 InventoryMapSize(int16 map, uint32 version); static uint16 InventoryMapSize(int16 indexMap, ClientVersion clientVersion);
static uint64 PossessionsBitmask(uint32 version); static uint64 PossessionsBitmask(ClientVersion clientVersion);
static uint64 EquipmentBitmask(uint32 version); static uint64 EquipmentBitmask(ClientVersion clientVersion);
static uint64 GeneralBitmask(uint32 version); static uint64 GeneralBitmask(ClientVersion clientVersion);
static uint64 CursorBitmask(uint32 version); static uint64 CursorBitmask(ClientVersion clientVersion);
static bool AllowsEmptyBagInBag(uint32 version); static bool AllowsEmptyBagInBag(ClientVersion clientVersion);
static bool AllowsClickCastFromBag(uint32 version); static bool AllowsClickCastFromBag(ClientVersion clientVersion);
// items // items
static uint16 ItemCommonSize(uint32 version); static uint16 ItemCommonSize(ClientVersion clientVersion);
static uint16 ItemContainerSize(uint32 version); static uint16 ItemContainerSize(ClientVersion clientVersion);
// player profile // player profile
static bool CoinHasWeight(uint32 version); static bool CoinHasWeight(ClientVersion clientVersion);
static uint32 BandoliersCount(uint32 version); static uint32 BandoliersCount(ClientVersion clientVersion);
static uint32 BandolierSize(uint32 version); 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: Working Notes:

View File

@ -15,18 +15,22 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h"
#include <stdio.h> #include "crc16.h"
#include <iostream> #include "global_define.h"
#include <iomanip>
#include "eq_packet.h" #include "eq_packet.h"
#include "misc.h" #include "misc.h"
#include "op_codes.h" #include "op_codes.h"
#include "crc16.h"
#include "platform.h" #include "platform.h"
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stdio.h>
#ifndef STATIC_OPCODE #ifndef STATIC_OPCODE
#include "opcodemgr.h" #include "opcodemgr.h"
#endif #endif
#include "packet_dump.h" #include "packet_dump.h"
#include "packet_functions.h" #include "packet_functions.h"
#include <cstdlib> #include <cstdlib>
@ -507,3 +511,8 @@ void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) {
// DumpPacketAscii(app->pBuffer, app->size); // DumpPacketAscii(app->pBuffer, app->size);
} }
std::string DumpPacketToString(const EQApplicationPacket* app){
std::ostringstream out;
out << DumpPacketHexToString(app->pBuffer, app->size);
return out.str();
}

View File

@ -19,9 +19,8 @@
#define _EQPACKET_H #define _EQPACKET_H
#include "base_packet.h" #include "base_packet.h"
#include "eq_stream_type.h"
#include "op_codes.h"
#include "platform.h" #include "platform.h"
#include <iostream>
#ifdef STATIC_OPCODE #ifdef STATIC_OPCODE
typedef unsigned short EmuOpcode; typedef unsigned short EmuOpcode;
@ -30,9 +29,6 @@
#include "emu_opcodes.h" #include "emu_opcodes.h"
#endif #endif
class EQStream;
class EQStreamPair;
class EQPacket : public BasePacket { class EQPacket : public BasePacket {
friend class EQStream; friend class EQStream;
public: public:
@ -151,6 +147,6 @@ protected:
}; };
extern void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false); extern void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false);
extern std::string DumpPacketToString(const EQApplicationPacket* app);
#endif #endif

View File

@ -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 ** Character Selection Struct
** Length: 1704 Bytes ** Length: 1704 Bytes
@ -152,10 +174,11 @@ struct Color_Struct
*/ */
struct CharacterSelect_Struct { struct CharacterSelect_Struct {
/*0000*/ uint32 race[10]; // Characters Race /*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 /*0400*/ uint8 beardcolor[10]; // Characters beard Color
/*0410*/ uint8 hairstyle[10]; // Characters hair style /*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 /*0780*/ uint32 secondary[10]; // Characters secondary IDFile number
/*0820*/ uint32 drakkin_heritage[10]; // added for SoF /*0820*/ uint32 drakkin_heritage[10]; // added for SoF
/*0860*/ uint32 drakkin_tattoo[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 /*0193*/ uint8 guildrank; // 0=normal, 1=officer, 2=leader
/*0194*/ uint8 unknown0194[3]; /*0194*/ uint8 unknown0194[3];
/*0197*/ union /*0197*/ union
{ {
struct struct
{ {
/*0197*/ uint32 equip_helmet; // Equipment: Helmet Visual /*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual
/*0201*/ uint32 equip_chest; // Equipment: Chest Visual /*0000*/ EquipStruct equip_chest; // Equipment: Chest visual
/*0205*/ uint32 equip_arms; // Equipment: Arms Visual /*0000*/ EquipStruct equip_arms; // Equipment: Arms visual
/*0209*/ uint32 equip_bracers; // Equipment: Bracers Visual /*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual
/*0213*/ uint32 equip_hands; // Equipment: Hands Visual /*0000*/ EquipStruct equip_hands; // Equipment: Hands visual
/*0217*/ uint32 equip_legs; // Equipment: Legs Visual /*0000*/ EquipStruct equip_legs; // Equipment: Legs visual
/*0221*/ uint32 equip_feet; // Equipment: Feet Visual /*0000*/ EquipStruct equip_feet; // Equipment: Boots visual
/*0225*/ uint32 equip_primary; // Equipment: Primary Visual /*0000*/ EquipStruct equip_primary; // Equipment: Main visual
/*0229*/ uint32 equip_secondary; // Equipment: Secondary Visual /*0000*/ EquipStruct equip_secondary; // Equipment: Off visual
} equip; } equip;
/*0197*/ uint32 equipment[_MaterialCount]; // Array elements correspond to struct equipment above /*0000*/ EquipStruct equipment[_MaterialCount];
}; };
/*0233*/ float runspeed; // Speed when running /*0233*/ float runspeed; // Speed when running
/*0036*/ uint8 afk; // 0=no, 1=afk /*0036*/ uint8 afk; // 0=no, 1=afk
/*0238*/ uint32 guildID; // Current guild /*0238*/ uint32 guildID; // Current guild
/*0242*/ char title[32]; // Title /*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) /*0275*/ uint8 set_to_0xFF[8]; // ***Placeholder (all ff)
/*0283*/ uint8 helm; // Helm texture /*0283*/ uint8 helm; // Helm texture
/*0284*/ uint32 race; // Spawn race /*0284*/ uint32 race; // Spawn race
@ -340,6 +363,7 @@ union
uint32 DestructibleUnk7; uint32 DestructibleUnk7;
uint8 DestructibleUnk8; uint8 DestructibleUnk8;
uint32 DestructibleUnk9; uint32 DestructibleUnk9;
bool targetable_with_hotkey;
}; };
@ -478,7 +502,11 @@ struct CastSpell_Struct
uint32 spell_id; uint32 spell_id;
uint32 inventoryslot; // slot for clicky item, 0xFFFF = normal cast uint32 inventoryslot; // slot for clicky item, 0xFFFF = normal cast
uint32 target_id; 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 struct SpellEffect_Struct
@ -512,7 +540,7 @@ struct SpawnAppearance_Struct
}; };
// solar: this is used inside profile // this is used inside profile
struct SpellBuff_Struct struct SpellBuff_Struct
{ {
/*000*/ uint8 slotid; //badly named... seems to be 2 for a real buff, 0 otherwise /*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; /*007*/ uint8 unknown7;
/*008*/ uint32 spellid; /*008*/ uint32 spellid;
/*012*/ uint32 duration; /*012*/ uint32 duration;
/*016*/ uint32 unknown016; /*016*/ uint32 num_hits;
/*020*/ uint32 unknown020; //prolly global player ID /*020*/ uint32 unknown020; //prolly global player ID
/*024*/ uint32 slotid; /*024*/ uint32 slotid;
/*028*/ uint32 bufffade; /*028*/ uint32 bufffade;
@ -597,8 +625,8 @@ struct GMTrainee_Struct
{ {
/*000*/ uint32 npcid; /*000*/ uint32 npcid;
/*004*/ uint32 playerid; /*004*/ uint32 playerid;
/*008*/ uint32 skills[73]; /*008*/ uint32 skills[PACKET_SKILL_ARRAY_SIZE];
/*300*/ uint8 unknown300[148]; /*408*/ uint8 unknown408[40];
/*448*/ /*448*/
}; };
@ -689,7 +717,7 @@ struct CharCreate_Struct
/*0076*/ uint32 drakkin_heritage; // added for SoF /*0076*/ uint32 drakkin_heritage; // added for SoF
/*0080*/ uint32 drakkin_tattoo; // added for SoF /*0080*/ uint32 drakkin_tattoo; // added for SoF
/*0084*/ uint32 drakkin_details; // 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_GROUP_LEADERSHIP_AA_ARRAY = 16;
static const uint32 MAX_RAID_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); 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 { 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 { 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; /*008*/ float y;
/*012*/ float z; /*012*/ float z;
/*016*/ float heading; /*016*/ float heading;
/*020*/ /*020*/ uint32 instance_id;
/*024*/
}; };
struct SuspendedMinion_Struct struct SuspendedMinion_Struct
{ {
/*000*/ uint16 SpellID; /*000*/ uint16 SpellID;
/*002*/ uint32 HP; /*002*/ uint32 HP;
/*006*/ uint32 Mana; /*006*/ uint32 Mana;
/*010*/ SpellBuff_Struct Buffs[BUFF_COUNT]; /*010*/ SpellBuff_Struct Buffs[BUFF_COUNT];
/*510*/ uint32 Items[_MaterialCount]; /*510*/ uint32 Items[_MaterialCount];
/*546*/ char Name[64]; /*546*/ char Name[64];
/*610*/ /*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_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_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_PP_AA_ARRAY = 240;
static const uint32 MAX_GROUP_MEMBERS = 6; static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20; static const uint32 MAX_RECAST_TYPES = 20;
@ -1191,7 +1268,7 @@ struct Animation_Struct {
/*04*/ /*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 // get the particle effects around them when a spell is cast
// also causes a buff icon // also causes a buff icon
struct Action_Struct struct Action_Struct
@ -1215,7 +1292,7 @@ struct Action_Struct
/* 31 */ /* 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 // melee messages like You try to pierce, etc. It's basically the melee
// and spell damage message // and spell damage message
struct CombatDamage_Struct struct CombatDamage_Struct
@ -1303,19 +1380,19 @@ struct PlayerPositionUpdateServer_Struct
struct PlayerPositionUpdateClient_Struct struct PlayerPositionUpdateClient_Struct
{ {
/*0000*/ uint16 spawn_id; /*0000*/ uint16 spawn_id;
/*0022*/ uint16 sequence; //increments one each packet /*0002*/ uint16 sequence; //increments one each packet
/*0004*/ float y_pos; // y coord /*0004*/ float y_pos; // y coord
/*0008*/ float delta_z; // Change in z /*0008*/ float delta_z; // Change in z
/*0016*/ float delta_x; // Change in x /*0012*/ float delta_x; // Change in x
/*0012*/ float delta_y; // Change in y /*0016*/ float delta_y; // Change in y
/*0020*/ int32 animation:10, // animation /*0020*/ int32 animation:10, // animation
delta_heading:10, // change in heading delta_heading:10, // change in heading
padding0020:12; // ***Placeholder (mostly 1) padding0020:12; // ***Placeholder (mostly 1)
/*0024*/ float x_pos; // x coord /*0024*/ float x_pos; // x coord
/*0028*/ float z_pos; // z coord /*0028*/ float z_pos; // z coord
/*0034*/ uint16 heading:12, // Directional heading /*0032*/ uint16 heading:12, // Directional heading
padding0004:4; // ***Placeholder padding0004:4; // ***Placeholder
/*0032*/ uint8 unknown0006[2]; // ***Placeholder /*0034*/ uint8 unknown0006[2]; // ***Placeholder
/*0036*/ /*0036*/
}; };
@ -1432,7 +1509,8 @@ enum ItemPacketType
ItemPacketTributeItem = 0x6C, ItemPacketTributeItem = 0x6C,
ItemPacketMerchant = 0x64, ItemPacketMerchant = 0x64,
ItemPacketWorldContainer = 0x6B, ItemPacketWorldContainer = 0x6B,
ItemPacketCharmUpdate = 0x6E ItemPacketCharmUpdate = 0x6E,
ItemPacketInvalid = 0xFF
}; };
struct ItemPacket_Struct struct ItemPacket_Struct
{ {
@ -1449,17 +1527,18 @@ struct BulkItemPacket_Struct
struct Consume_Struct struct Consume_Struct
{ {
/*0000*/ uint32 slot; /*0000*/ uint32 slot;
/*0004*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click /*0004*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click
/*0008*/ uint8 c_unknown1[4]; /*0008*/ uint8 c_unknown1[4];
/*0012*/ uint8 type; // 0x01=Food 0x02=Water /*0012*/ uint8 type; // 0x01=Food 0x02=Water
/*0013*/ uint8 unknown13[3]; /*0013*/ uint8 unknown13[3];
}; };
struct DeleteItem_Struct { struct DeleteItem_Struct {
/*0000*/ uint32 from_slot; /*0000*/ uint32 from_slot;
/*0004*/ uint32 to_slot; /*0004*/ uint32 to_slot;
/*0008*/ uint32 number_in_stack; /*0008*/ uint32 number_in_stack;
/*0012*/
}; };
struct MoveItem_Struct struct MoveItem_Struct
@ -1467,16 +1546,18 @@ struct MoveItem_Struct
/*0000*/ uint32 from_slot; /*0000*/ uint32 from_slot;
/*0004*/ uint32 to_slot; /*0004*/ uint32 to_slot;
/*0008*/ uint32 number_in_stack; /*0008*/ uint32 number_in_stack;
/*0012*/
}; };
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will // 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 // 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 struct ClientTimeStamp_Struct
{ {
/*0000*/ uint32 from_slot; /*0000*/ uint32 from_slot;
/*0004*/ uint32 to_slot; /*0004*/ uint32 to_slot;
/*0008*/ uint32 number_in_stack; /*0008*/ uint32 number_in_stack;
/*0012*/
}; };
// //
@ -1730,7 +1811,7 @@ struct RandomReq_Struct {
uint32 high; uint32 high;
}; };
/* solar: 9/23/03 reply to /random command; struct from Zaphod */ /* 9/23/03 reply to /random command */
struct RandomReply_Struct { struct RandomReply_Struct {
/* 00 */ uint32 low; /* 00 */ uint32 low;
/* 04 */ uint32 high; /* 04 */ uint32 high;
@ -2180,6 +2261,12 @@ struct GroupLeaderChange_Struct
/*128*/ char Unknown128[20]; /*128*/ char Unknown128[20];
}; };
struct GroupMentor_Struct {
/*000*/ int percent;
/*004*/ char name[64];
/*068*/
};
struct FaceChange_Struct { struct FaceChange_Struct {
/*000*/ uint8 haircolor; /*000*/ uint8 haircolor;
/*001*/ uint8 beardcolor; /*001*/ uint8 beardcolor;
@ -2301,7 +2388,7 @@ struct AugmentItem_Struct {
// OP_Emote // OP_Emote
struct Emote_Struct { struct Emote_Struct {
/*0000*/ uint32 unknown01; /*0000*/ uint32 type; // 0 - custom, 0xffffffff - command (/dance, /flip, etc...)
/*0004*/ char message[1024]; /*0004*/ char message[1024];
/*1028*/ /*1028*/
}; };
@ -2602,6 +2689,17 @@ struct Translocate_Struct {
/*088*/ uint32 Complete; /*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 { struct Sacrifice_Struct {
/*000*/ uint32 CasterID; /*000*/ uint32 CasterID;
/*004*/ uint32 TargetID; /*004*/ uint32 TargetID;
@ -2822,7 +2920,7 @@ uint8 npccastfilters; // 0) No, 1) Ignore NPC Casts (all), 2) Ignore NPC Casts
*/ */
struct ItemViewRequest_Struct { struct ItemViewRequest_Struct {
/*000*/ uint32 item_id; /*000*/ uint32 item_id;
/*004*/ uint32 augments[5]; /*004*/ uint32 augments[6];
/*024*/ uint32 link_hash; /*024*/ uint32 link_hash;
/*028*/ uint32 unknown028; /*028*/ uint32 unknown028;
/*032*/ char unknown032[12]; //probably includes loregroup & evolving info. see Client::MakeItemLink() in zone/inventory.cpp:469 /*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 { struct Track_Struct {
uint16 entityid; uint32 entityid;
uint16 padding002;
float distance; float distance;
// Fields for SoD and later // Fields for SoD and later
uint8 level; uint8 level;
uint8 NPC; uint8 is_npc;
uint8 GroupMember;
char name[64]; char name[64];
uint8 is_pet;
uint8 is_merc;
}; };
struct Tracking_Struct { struct Tracking_Struct {
@ -3400,7 +3498,7 @@ struct Split_Struct
*/ */
struct NewCombine_Struct { struct NewCombine_Struct {
/*00*/ int16 container_slot; /*00*/ int16 container_slot;
/*02*/ char unknown02[2]; /*02*/ int16 guildtribute_slot;
/*04*/ /*04*/
}; };
@ -3911,6 +4009,11 @@ struct MarkNPC_Struct
/*08**/ char Name[64]; /*08**/ char Name[64];
}; };
struct InspectBuffs_Struct {
/*000*/ uint32 spell_id[BUFF_COUNT];
/*100*/ uint32 tics_remaining[BUFF_COUNT];
};
struct RaidGeneral_Struct { struct RaidGeneral_Struct {
/*00*/ uint32 action; //=10 /*00*/ uint32 action; //=10
/*04*/ char player_name[64]; //should both be the player's name /*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... /*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 { struct RaidAdd_Struct {
/*000*/ uint32 action; //=0 /*000*/ uint32 action; //=0
@ -4304,14 +4420,14 @@ typedef struct {
struct ControlBoat_Struct { struct ControlBoat_Struct {
/*000*/ uint32 boatId; // entitylist id of the boat /*000*/ uint32 boatId; // entitylist id of the boat
/*004*/ bool TakeControl; // 01 if taking control, 00 if releasing it /*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 struct AugmentInfo_Struct
{ {
/*000*/ uint32 itemid; // id of the solvent needed /*000*/ uint32 itemid; // id of the solvent needed
/*004*/ uint8 window; // window to display the information in /*004*/ uint32 window; // window to display the information in
/*005*/ uint8 unknown005[67]; // total packet length 72, all the rest were always 00 /*008*/ char augment_info[64]; // the reply has the text here
/*072*/ /*072*/
}; };
@ -4599,11 +4715,13 @@ struct BuffIconEntry_Struct
uint32 buff_slot; uint32 buff_slot;
uint32 spell_id; uint32 spell_id;
uint32 tics_remaining; uint32 tics_remaining;
uint32 num_hits;
}; };
struct BuffIcon_Struct struct BuffIcon_Struct
{ {
uint32 entity_id; uint32 entity_id;
uint8 all_buffs;
uint16 count; uint16 count;
BuffIconEntry_Struct entries[0]; BuffIconEntry_Struct entries[0];
}; };
@ -5116,17 +5234,19 @@ struct MercenaryMerchantResponse_Struct {
}; };
struct ServerLootItem_Struct { struct ServerLootItem_Struct {
uint32 item_id; uint32 item_id; // uint32 item_id;
int16 equipSlot; int16 equip_slot; // int16 equip_slot;
uint8 charges; uint16 charges; // uint8 charges;
uint16 lootslot; uint16 lootslot; // uint16 lootslot;
uint32 aug1; uint32 aug_1; // uint32 aug_1;
uint32 aug2; uint32 aug_2; // uint32 aug_2;
uint32 aug3; uint32 aug_3; // uint32 aug_3;
uint32 aug4; uint32 aug_4; // uint32 aug_4;
uint32 aug5; uint32 aug_5; // uint32 aug_5;
uint8 minlevel; uint32 aug_6; // uint32 aug_5;
uint8 maxlevel; uint8 attuned;
uint8 min_level;
uint8 max_level;
}; };
//Found in client near a ref to the string: //Found in client near a ref to the string:
@ -5149,6 +5269,23 @@ struct ClientMarqueeMessage_Struct {
typedef std::list<ServerLootItem_Struct*> ItemList; typedef std::list<ServerLootItem_Struct*> 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 // Restore structure packing to default
#pragma pack() #pragma pack()

View File

@ -16,18 +16,17 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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_packet.h"
#include "eq_stream.h" #include "eq_stream.h"
#include "misc.h"
#include "mutex.h"
#include "op_codes.h" #include "op_codes.h"
#include "crc16.h" #include "crc16.h"
#include "platform.h" #include "platform.h"
#include "string_util.h"
#include <string> #include <string>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
@ -50,7 +49,13 @@
uint16 EQStream::MaxWindowSize=2048; 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; active_users = 0;
Session=0; Session=0;
Key=0; Key=0;
@ -77,19 +82,19 @@ void EQStream::init() {
OpMgr = nullptr; OpMgr = nullptr;
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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 *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
{ {
EQRawApplicationPacket *ap=nullptr; EQRawApplicationPacket *ap=nullptr;
_log(NET__APP_CREATE, _L "Creating new application packet, length %d" __L, p->size); Log.Out(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, p->size);
_raw(NET__APP_CREATE_HEX, 0xFFFF, p); // _raw(NET__APP_CREATE_HEX, 0xFFFF, p);
ap = p->MakeAppPacket(); ap = p->MakeAppPacket();
return ap; return ap;
} }
@ -97,8 +102,7 @@ EQRawApplicationPacket *EQStream::MakeApplicationPacket(EQProtocolPacket *p)
EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len) EQRawApplicationPacket *EQStream::MakeApplicationPacket(const unsigned char *buf, uint32 len)
{ {
EQRawApplicationPacket *ap=nullptr; EQRawApplicationPacket *ap=nullptr;
_log(NET__APP_CREATE, _L "Creating new application packet, length %d" __L, len); Log.Out(Logs::Detail, Logs::Netcode, _L "Creating new application packet, length %d" __L, len);
_hex(NET__APP_CREATE_HEX, buf, len);
ap = new EQRawApplicationPacket(buf, len); ap = new EQRawApplicationPacket(buf, len);
return ap; return ap;
} }
@ -128,8 +132,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
} }
if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) { if (!Session && p->opcode!=OP_SessionRequest && p->opcode!=OP_SessionResponse) {
_log(NET__DEBUG, _L "Session not initialized, packet ignored" __L); Log.Out(Logs::Detail, Logs::Netcode, _L "Session not initialized, packet ignored" __L);
_raw(NET__DEBUG, 0xFFFF, p); // _raw(NET__DEBUG, 0xFFFF, p);
return; return;
} }
@ -139,8 +143,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
while(processed < p->size) { while(processed < p->size) {
subpacket_length=*(p->pBuffer+processed); subpacket_length=*(p->pBuffer+processed);
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length); EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+processed+1,subpacket_length);
_log(NET__NET_CREATE, _L "Extracting combined packet of length %d" __L, subpacket_length); Log.Out(Logs::Detail, Logs::Netcode, _L "Extracting combined packet of length %d" __L, subpacket_length);
_raw(NET__NET_CREATE_HEX, 0xFFFF, subp); // _raw(NET__NET_CREATE_HEX, 0xFFFF, subp);
subp->copyInfo(p); subp->copyInfo(p);
ProcessPacket(subp); ProcessPacket(subp);
delete subp; delete subp;
@ -154,12 +158,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
while(processed<p->size) { while(processed<p->size) {
EQRawApplicationPacket *ap=nullptr; EQRawApplicationPacket *ap=nullptr;
if ((subpacket_length=(unsigned char)*(p->pBuffer+processed))!=0xff) { 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); ap=MakeApplicationPacket(p->pBuffer+processed+1,subpacket_length);
processed+=subpacket_length+1; processed+=subpacket_length+1;
} else { } else {
subpacket_length=ntohs(*(uint16 *)(p->pBuffer+processed+1)); 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); ap=MakeApplicationPacket(p->pBuffer+processed+3,subpacket_length);
processed+=subpacket_length+3; processed+=subpacket_length+3;
} }
@ -174,29 +178,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_Packet: { case OP_Packet: {
if(!p->pBuffer || (p->Size() < 4)) 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; break;
} }
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
SeqOrder check=CompareSequence(NextInSeq,seq); SeqOrder check=CompareSequence(NextInSeq,seq);
if (check == SeqFuture) { if (check == SeqFuture) {
_log(NET__DEBUG, _L "Future OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); 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); // _raw(NET__DEBUG, seq, p);
PacketQueue[seq]=p->Copy(); 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); //SendOutOfOrderAck(seq);
} else if (check == SeqPast) { } else if (check == SeqPast) {
_log(NET__DEBUG, _L "Duplicate OP_Packet: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); 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); // _raw(NET__DEBUG, seq, p);
SendOutOfOrderAck(seq); //we already got this packet but it was out of order SendOutOfOrderAck(seq); //we already got this packet but it was out of order
} else { } else {
// In case we did queue one before as well. // In case we did queue one before as well.
EQProtocolPacket *qp=RemoveQueue(seq); EQProtocolPacket *qp=RemoveQueue(seq);
if (qp) { 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; delete qp;
} }
@ -205,8 +209,8 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
// Check for an embedded OP_AppCombinded (protocol level 0x19) // Check for an embedded OP_AppCombinded (protocol level 0x19)
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
EQProtocolPacket *subp=MakeProtocolPacket(p->pBuffer+2,p->size-2); 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); 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); // _raw(NET__NET_CREATE_HEX, seq, subp);
subp->copyInfo(p); subp->copyInfo(p);
ProcessPacket(subp); ProcessPacket(subp);
delete subp; delete subp;
@ -224,29 +228,29 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_Fragment: { case OP_Fragment: {
if(!p->pBuffer || (p->Size() < 4)) 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; break;
} }
uint16 seq=ntohs(*(uint16 *)(p->pBuffer)); uint16 seq=ntohs(*(uint16 *)(p->pBuffer));
SeqOrder check=CompareSequence(NextInSeq,seq); SeqOrder check=CompareSequence(NextInSeq,seq);
if (check == SeqFuture) { if (check == SeqFuture) {
_log(NET__DEBUG, _L "Future OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); 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); // _raw(NET__DEBUG, seq, p);
PacketQueue[seq]=p->Copy(); 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); //SendOutOfOrderAck(seq);
} else if (check == SeqPast) { } else if (check == SeqPast) {
_log(NET__DEBUG, _L "Duplicate OP_Fragment: Expecting Seq=%d, but got Seq=%d" __L, NextInSeq, seq); 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); // _raw(NET__DEBUG, seq, p);
SendOutOfOrderAck(seq); SendOutOfOrderAck(seq);
} else { } else {
// In case we did queue one before as well. // In case we did queue one before as well.
EQProtocolPacket *qp=RemoveQueue(seq); EQProtocolPacket *qp=RemoveQueue(seq);
if (qp) { 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; delete qp;
} }
SetNextAckToSend(seq); SetNextAckToSend(seq);
@ -254,18 +258,18 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
if (oversize_buffer) { if (oversize_buffer) {
memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2); memcpy(oversize_buffer+oversize_offset,p->pBuffer+2,p->size-2);
oversize_offset+=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 (oversize_offset==oversize_length) {
if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) { if (*(p->pBuffer+2)==0x00 && *(p->pBuffer+3)==0x19) {
EQProtocolPacket *subp=MakeProtocolPacket(oversize_buffer,oversize_offset); 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); 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); //// _raw(NET__NET_CREATE_HEX, subp);
subp->copyInfo(p); subp->copyInfo(p);
ProcessPacket(subp); ProcessPacket(subp);
delete subp; delete subp;
} else { } else {
EQRawApplicationPacket *ap=MakeApplicationPacket(oversize_buffer,oversize_offset); 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) { if (ap) {
ap->copyInfo(p); ap->copyInfo(p);
InboundQueuePush(ap); InboundQueuePush(ap);
@ -280,7 +284,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
oversize_buffer=new unsigned char[oversize_length]; oversize_buffer=new unsigned char[oversize_length];
memcpy(oversize_buffer,p->pBuffer+6,p->size-6); memcpy(oversize_buffer,p->pBuffer+6,p->size-6);
oversize_offset=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: { case OP_KeepAlive: {
#ifndef COLLECTOR #ifndef COLLECTOR
NonSequencedPush(new EQProtocolPacket(p->opcode,p->pBuffer,p->size)); 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 #endif
} }
break; break;
case OP_Ack: { case OP_Ack: {
if(!p->pBuffer || (p->Size() < 4)) 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; break;
} }
#ifndef COLLECTOR #ifndef COLLECTOR
@ -311,28 +315,31 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_SessionRequest: { case OP_SessionRequest: {
if(p->Size() < sizeof(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; break;
} }
#ifndef COLLECTOR #ifndef COLLECTOR
if (GetState()==ESTABLISHED) { 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(); // client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case
init(); // streamactive means we identified the opcode for the stream, we cannot re-establish this connection
State=UNESTABLISHED;*/ if ( streamactive || ( sessionAttempts > MAX_SESSION_RETRIES ) )
_SendDisconnect(); {
SetState(CLOSED); _SendDisconnect();
break; SetState(CLOSED);
break;
}
} }
#endif #endif
//std::cout << "Got OP_SessionRequest" << std::endl; sessionAttempts++;
init(); // we set established below, so statistics will not be reset for session attempts/stream active.
init(GetState()!=ESTABLISHED);
OutboundQueueClear(); OutboundQueueClear();
SessionRequest *Request=(SessionRequest *)p->pBuffer; SessionRequest *Request=(SessionRequest *)p->pBuffer;
Session=ntohl(Request->Session); Session=ntohl(Request->Session);
SetMaxLen(ntohl(Request->MaxLength)); 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); SetState(ESTABLISHED);
#ifndef COLLECTOR #ifndef COLLECTOR
Key=0x11223344; Key=0x11223344;
@ -343,7 +350,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_SessionResponse: { case OP_SessionResponse: {
if(p->Size() < sizeof(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; break;
} }
@ -359,7 +366,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
compressed=(Response->Format&FLAG_COMPRESSED); compressed=(Response->Format&FLAG_COMPRESSED);
encoded=(Response->Format&FLAG_ENCODED); 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 // Kinda kludgy, but trie for now
if (StreamType==UnknownStream) { if (StreamType==UnknownStream) {
@ -382,17 +389,17 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
EQStreamState state = GetState(); EQStreamState state = GetState();
if(state == ESTABLISHED) { if(state == ESTABLISHED) {
//client initiated disconnect? //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(); _SendDisconnect();
SetState(CLOSED); SetState(CLOSED);
} else if(state == CLOSING) { } else if(state == CLOSING) {
//we were waiting for this anyways, ignore pending messages, send the reply and be closed. //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(); _SendDisconnect();
SetState(CLOSED); SetState(CLOSED);
} else { } else {
//we are expecting this (or have already gotten it, but dont care either way) //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); SetState(CLOSED);
} }
} }
@ -400,7 +407,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_OutOfOrderAck: { case OP_OutOfOrderAck: {
if(!p->pBuffer || (p->Size() < 4)) 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; break;
} }
#ifndef COLLECTOR #ifndef COLLECTOR
@ -408,15 +415,15 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
MOutboundQueue.lock(); MOutboundQueue.lock();
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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 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) { 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); seq, SequencedBase, SequencedBase+NextSequencedSend);
bool retransmit_acked_packets = false; bool retransmit_acked_packets = false;
@ -427,7 +434,7 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
if(!retransmit_acked_packets) { if(!retransmit_acked_packets) {
uint16 sqsize = SequencedQueue.size(); uint16 sqsize = SequencedQueue.size();
uint16 index = seq - SequencedBase; 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) { if (index < sqsize) {
std::deque<EQProtocolPacket *>::iterator sitr; std::deque<EQProtocolPacket *>::iterator sitr;
sitr = SequencedQueue.begin(); sitr = SequencedQueue.begin();
@ -442,15 +449,15 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
NextSequencedSend = 0; NextSequencedSend = 0;
} else { } 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) { 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()) { 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(); MOutboundQueue.unlock();
#endif #endif
@ -459,12 +466,12 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
case OP_SessionStatRequest: { case OP_SessionStatRequest: {
if(p->Size() < sizeof(SessionStats)) 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; break;
} }
#ifndef COLLECTOR #ifndef COLLECTOR
SessionStats *Stats=(SessionStats *)p->pBuffer; 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->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->low_delta), (unsigned long)ntohl(Stats->average_delta),
(unsigned long)ntohl(Stats->high_delta), (unsigned long)ntohl(Stats->last_remote_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) if(retransmittimeout > RETRANSMIT_TIMEOUT_MAX)
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 #endif
} }
break; break;
case OP_SessionStatResponse: { 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; break;
case OP_OutOfSession: { 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; break;
default: default:
@ -527,7 +534,7 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
return; return;
if(OpMgr == nullptr || *OpMgr == nullptr) { 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; delete pack;
return; return;
} }
@ -549,12 +556,24 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p) void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
{ {
uint32 chunksize,used; uint32 chunksize, used;
uint32 length; 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 // Convert the EQApplicationPacket to 1 or more EQProtocolPackets
if (p->size>(MaxLen-8)) { // proto-op(2), seq(2), app-op(2) ... data ... crc(2) 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]; unsigned char *tmpbuff=new unsigned char[p->size+3];
length=p->serialize(opcode, tmpbuff); length=p->serialize(opcode, tmpbuff);
@ -563,7 +582,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
*(uint32 *)(out->pBuffer+2)=htonl(p->Size()); *(uint32 *)(out->pBuffer+2)=htonl(p->Size());
used=MaxLen-10; used=MaxLen-10;
memcpy(out->pBuffer+6,tmpbuff,used); 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); SequencedPush(out);
@ -574,7 +593,7 @@ void EQStream::SendPacket(uint16 opcode, EQApplicationPacket *p)
out->size=chunksize+2; out->size=chunksize+2;
SequencedPush(out); SequencedPush(out);
used+=chunksize; 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 p;
delete[] tmpbuff; delete[] tmpbuff;
@ -598,22 +617,22 @@ void EQStream::SequencedPush(EQProtocolPacket *p)
#else #else
MOutboundQueue.lock(); MOutboundQueue.lock();
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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); *(uint16 *)(p->pBuffer)=htons(NextOutSeq);
SequencedQueue.push_back(p); SequencedQueue.push_back(p);
NextOutSeq++; NextOutSeq++;
if(uint16(SequencedBase + SequencedQueue.size()) != 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()) { 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(); MOutboundQueue.unlock();
#endif #endif
@ -625,7 +644,7 @@ void EQStream::NonSequencedPush(EQProtocolPacket *p)
delete p; delete p;
#else #else
MOutboundQueue.lock(); 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); NonSequencedQueue.push(p);
MOutboundQueue.unlock(); MOutboundQueue.unlock();
#endif #endif
@ -634,14 +653,14 @@ void EQStream::NonSequencedPush(EQProtocolPacket *p)
void EQStream::SendAck(uint16 seq) void EQStream::SendAck(uint16 seq)
{ {
uint16 Seq=htons(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); SetLastAckSent(seq);
NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16))); NonSequencedPush(new EQProtocolPacket(OP_Ack,(unsigned char *)&Seq,sizeof(uint16)));
} }
void EQStream::SendOutOfOrderAck(uint16 seq) 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); uint16 Seq=htons(seq);
NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16))); NonSequencedPush(new EQProtocolPacket(OP_OutOfOrderAck,(unsigned char *)&Seq,sizeof(uint16)));
} }
@ -657,7 +676,6 @@ void EQStream::Write(int eq_fd)
int32 threshold=RateThreshold; int32 threshold=RateThreshold;
MRate.unlock(); MRate.unlock();
if (BytesWritten > threshold) { if (BytesWritten > threshold) {
//std::cout << "Over threshold: " << BytesWritten << " > " << threshold << std::endl;
return; 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 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 && if (RETRANSMIT_TIMEOUT_MULT && !SequencedQueue.empty() && NextSequencedSend &&
(GetState()==ESTABLISHED) && ((retransmittimer+retransmittimeout) < Timer::GetCurrentTime())) { (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); "buffer (seq %d, was %d)." __L, SequencedBase, SequencedBase+NextSequencedSend);
NextSequencedSend = 0; NextSequencedSend = 0;
retransmittimer = Timer::GetCurrentTime(); // don't want to endlessly retransmit the first packet 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 // If we don't have a packet to try to combine into, use this one as the base
// And remove it form the queue // And remove it form the queue
p = NonSequencedQueue.front(); 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(); NonSequencedQueue.pop();
} else if (!p->combine(NonSequencedQueue.front())) { } else if (!p->combine(NonSequencedQueue.front())) {
// Tryint to combine this packet with the base didn't work (too big maybe) // 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) // 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); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
p=nullptr; p=nullptr;
if (BytesWritten > threshold) { if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair // 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; break;
} }
} else { } else {
// Combine worked, so just remove this packet and it's spot in the queue // 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(); delete NonSequencedQueue.front();
NonSequencedQueue.pop(); NonSequencedQueue.pop();
} }
@ -726,48 +744,48 @@ void EQStream::Write(int eq_fd)
if (sitr!=SequencedQueue.end()) { if (sitr!=SequencedQueue.end()) {
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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... uint16 seq_send = SequencedBase + NextSequencedSend; //just for logging...
if(SequencedQueue.empty()) { 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; SeqEmpty=true;
continue; continue;
} }
if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) { if(GetExecutablePlatform() == ExePlatformWorld || GetExecutablePlatform() == ExePlatformZone) {
if (!RETRANSMIT_ACKED_PACKETS && (*sitr)->acked) { 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++; sitr++;
NextSequencedSend++; NextSequencedSend++;
} else if (!p) { } else if (!p) {
// If we don't have a packet to try to combine into, use this one as the base // 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 // Copy it first as it will still live until it is acked
p=(*sitr)->Copy(); 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; ++sitr;
NextSequencedSend++; NextSequencedSend++;
} else if (!p->combine(*sitr)) { } else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe) // 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) // 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); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
p=nullptr; p=nullptr;
if (BytesWritten > threshold) { if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair // 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; break;
} }
} else { } else {
// Combine worked // 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; ++sitr;
NextSequencedSend++; 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 // 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 // Copy it first as it will still live until it is acked
p=(*sitr)->Copy(); 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; ++sitr;
NextSequencedSend++; NextSequencedSend++;
} else if (!p->combine(*sitr)) { } else if (!p->combine(*sitr)) {
// Trying to combine this packet with the base didn't work (too big maybe) // 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) // 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); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
p=nullptr; p=nullptr;
if (BytesWritten > threshold) { if (BytesWritten > threshold) {
// Sent enough this round, lets stop to be fair // 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; break;
} }
} else { } else {
// Combine worked // 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; ++sitr;
NextSequencedSend++; NextSequencedSend++;
} }
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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 { } else {
// No more sequenced packets // 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 // We have a packet still, must have run out of both seq and non-seq, so send it
if (p) { 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); ReadyToSend.push(p);
BytesWritten+=p->size; BytesWritten+=p->size;
} }
@ -833,7 +851,7 @@ void EQStream::Write(int eq_fd)
if(SeqEmpty && NonSeqEmpty) { if(SeqEmpty && NonSeqEmpty) {
//no more data to send //no more data to send
if(CheckState(CLOSING)) { 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. //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(). //this packet will not actually go out until the next call to Write().
_SendDisconnect(); _SendDisconnect();
@ -896,7 +914,7 @@ EQProtocolPacket *out=new EQProtocolPacket(OP_SessionResponse,nullptr,sizeof(Ses
out->size=sizeof(SessionResponse); 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"); (unsigned long)Session, MaxLen, Key, compressed?"yes":"no", encoded?"yes":"no");
NonSequencedPush(out); NonSequencedPush(out);
@ -910,7 +928,7 @@ EQProtocolPacket *out=new EQProtocolPacket(OP_SessionRequest,nullptr,sizeof(Sess
Request->Session=htonl(time(nullptr)); Request->Session=htonl(time(nullptr));
Request->MaxLength=htonl(512); 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); NonSequencedPush(out);
} }
@ -924,7 +942,7 @@ void EQStream::_SendDisconnect()
*(uint32 *)out->pBuffer=htonl(Session); *(uint32 *)out->pBuffer=htonl(Session);
NonSequencedPush(out); 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) void EQStream::InboundQueuePush(EQRawApplicationPacket *p)
@ -946,15 +964,12 @@ EQRawApplicationPacket *p=nullptr;
} }
MInboundQueue.unlock(); MInboundQueue.unlock();
//resolve the opcode if we can. if (p) {
if(p) { if (OpMgr != nullptr && *OpMgr != nullptr) {
if(OpMgr != nullptr && *OpMgr != nullptr) {
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
#if EQDEBUG >= 4 if (emu_op == OP_Unknown) {
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());
_log(NET__ERROR, "Unable to convert EQ opcode 0x%.4x to an Application opcode.", p->opcode); }
}
#endif
p->SetOpcode(emu_op); p->SetOpcode(emu_op);
} }
} }
@ -978,11 +993,10 @@ EQRawApplicationPacket *p=nullptr;
if(p) { if(p) {
if(OpMgr != nullptr && *OpMgr != nullptr) { if(OpMgr != nullptr && *OpMgr != nullptr) {
EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode); EmuOpcode emu_op = (*OpMgr)->EQToEmu(p->opcode);
#if EQDEBUG >= 4
if(emu_op == OP_Unknown) { 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); p->SetOpcode(emu_op);
} }
} }
@ -1008,7 +1022,7 @@ void EQStream::InboundQueueClear()
{ {
EQApplicationPacket *p=nullptr; 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(); MInboundQueue.lock();
if (!InboundQueue.empty()) { if (!InboundQueue.empty()) {
@ -1051,7 +1065,7 @@ void EQStream::OutboundQueueClear()
{ {
EQProtocolPacket *p=nullptr; 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(); MOutboundQueue.lock();
while(!NonSequencedQueue.empty()) { while(!NonSequencedQueue.empty()) {
@ -1073,7 +1087,7 @@ void EQStream::PacketQueueClear()
{ {
EQProtocolPacket *p=nullptr; 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()) { if(!PacketQueue.empty()) {
std::map<unsigned short,EQProtocolPacket *>::iterator itr; std::map<unsigned short,EQProtocolPacket *>::iterator itr;
@ -1105,8 +1119,7 @@ uint32 newlength=0;
delete p; delete p;
ProcessQueue(); ProcessQueue();
} else { } else {
_log(NET__DEBUG, _L "Incoming packet failed checksum" __L); Log.Out(Logs::Detail, Logs::Netcode, _L "Incoming packet failed checksum" __L);
_hex(NET__NET_CREATE_HEX, buffer, length);
} }
} }
@ -1135,33 +1148,33 @@ std::deque<EQProtocolPacket *>::iterator itr, tmp;
MOutboundQueue.lock(); MOutboundQueue.lock();
//do a bit of sanity checking. //do a bit of sanity checking.
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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); SeqOrder ord = CompareSequence(SequencedBase, seq);
if(ord == SeqInOrder) { if(ord == SeqInOrder) {
//they are not acking anything new... //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) { } else if(ord == SeqPast) {
//they are nacking blocks going back before our buffer, wtf? //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 { } 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. //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. seq++; //we stop at the block right after their ack, counting on the wrap of both numbers.
while(SequencedBase != seq) { while(SequencedBase != seq) {
if(SequencedQueue.empty()) { 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; SequencedBase = NextOutSeq;
NextSequencedSend = 0; NextSequencedSend = 0;
break; 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 //clean out the acked packet
delete SequencedQueue.front(); delete SequencedQueue.front();
SequencedQueue.pop_front(); SequencedQueue.pop_front();
@ -1172,10 +1185,10 @@ _log(NET__ERROR, _L "OUT OF PACKETS acked packet with sequence %lu. Next send is
SequencedBase++; SequencedBase++;
} }
if(uint16(SequencedBase + SequencedQueue.size()) != NextOutSeq) { 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()) { 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) void EQStream::SetNextAckToSend(uint32 seq)
{ {
MAcks.lock(); 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; NextAckToSend=seq;
MAcks.unlock(); MAcks.unlock();
} }
@ -1193,7 +1206,7 @@ void EQStream::SetNextAckToSend(uint32 seq)
void EQStream::SetLastAckSent(uint32 seq) void EQStream::SetLastAckSent(uint32 seq)
{ {
MAcks.lock(); 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; LastAckSent=seq;
MAcks.unlock(); MAcks.unlock();
} }
@ -1206,10 +1219,10 @@ void EQStream::ProcessQueue()
EQProtocolPacket *qp=nullptr; EQProtocolPacket *qp=nullptr;
while((qp=RemoveQueue(NextInSeq))!=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); ProcessPacket(qp);
delete 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()) { if ((itr=PacketQueue.find(seq))!=PacketQueue.end()) {
qp=itr->second; qp=itr->second;
PacketQueue.erase(itr); 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; return qp;
} }
void EQStream::SetStreamType(EQStreamType type) 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; StreamType=type;
switch (StreamType) { switch (StreamType) {
case LoginStream: case LoginStream:
app_opcode_size=1; app_opcode_size=1;
compressed=false; compressed=false;
encoded=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; break;
case ChatOrMailStream: case ChatOrMailStream:
case ChatStream: case ChatStream:
@ -1242,7 +1255,7 @@ void EQStream::SetStreamType(EQStreamType type)
app_opcode_size=1; app_opcode_size=1;
compressed=false; compressed=false;
encoded=true; 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; break;
case ZoneStream: case ZoneStream:
case WorldStream: case WorldStream:
@ -1250,7 +1263,7 @@ void EQStream::SetStreamType(EQStreamType type)
app_opcode_size=2; app_opcode_size=2;
compressed=true; compressed=true;
encoded=false; 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; break;
} }
} }
@ -1300,7 +1313,7 @@ EQStream::SeqOrder EQStream::CompareSequence(uint16 expected_seq , uint16 seq)
void EQStream::SetState(EQStreamState state) { void EQStream::SetState(EQStreamState state) {
MState.lock(); 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; State=state;
MState.unlock(); MState.unlock();
} }
@ -1312,29 +1325,29 @@ void EQStream::CheckTimeout(uint32 now, uint32 timeout) {
EQStreamState orig_state = GetState(); EQStreamState orig_state = GetState();
if (orig_state == CLOSING && !outgoing_data) { 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(); _SendDisconnect();
SetState(DISCONNECTING); SetState(DISCONNECTING);
} else if (LastPacket && (now-LastPacket) > timeout) { } else if (LastPacket && (now-LastPacket) > timeout) {
switch(orig_state) { switch(orig_state) {
case CLOSING: case CLOSING:
//if we time out in the closing state, they are not acking us, just give up //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(); _SendDisconnect();
SetState(CLOSED); SetState(CLOSED);
break; break;
case DISCONNECTING: case DISCONNECTING:
//we timed out waiting for them to send us the disconnect reply, just give up. //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); SetState(CLOSED);
break; break;
case CLOSED: 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; break;
case ESTABLISHED: case ESTABLISHED:
//we timed out during normal operation. Try to be nice about it. //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. //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(); _SendDisconnect();
SetState(DISCONNECTING); SetState(DISCONNECTING);
break; break;
@ -1363,11 +1376,11 @@ void EQStream::AdjustRates(uint32 average_delta)
MRate.lock(); MRate.lock();
RateThreshold=RATEBASE/average_delta; RateThreshold=RATEBASE/average_delta;
DecayRate=DECAYBASE/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); RateThreshold, DecayRate, average_delta);
MRate.unlock(); MRate.unlock();
} else { } 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); average_delta, AVERAGE_DELTA_MAX);
} }
} else { } else {
@ -1375,7 +1388,7 @@ void EQStream::AdjustRates(uint32 average_delta)
MRate.lock(); MRate.lock();
RateThreshold=RATEBASE/average_delta; RateThreshold=RATEBASE/average_delta;
DecayRate=DECAYBASE/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); RateThreshold, DecayRate, average_delta);
MRate.unlock(); MRate.unlock();
} }
@ -1385,12 +1398,12 @@ void EQStream::AdjustRates(uint32 average_delta)
void EQStream::Close() { void EQStream::Close() {
if(HasOutgoingData()) { if(HasOutgoingData()) {
//there is pending data, wait for it to go out. //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); SetState(CLOSING);
} else { } else {
//otherwise, we are done, we can drop immediately. //otherwise, we are done, we can drop immediately.
_SendDisconnect(); _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); SetState(DISCONNECTING);
} }
} }
@ -1418,19 +1431,19 @@ EQStream::MatchState EQStream::CheckSignature(const Signature *sig) {
} else if(p->opcode == sig->first_eq_opcode) { } else if(p->opcode == sig->first_eq_opcode) {
//opcode matches, check length.. //opcode matches, check length..
if(p->size == sig->first_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; res = MatchSuccessful;
} else if(sig->first_length == 0) { } 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; res = MatchSuccessful;
} else { } else {
//opcode matched but length did not. //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; res = MatchFailed;
} }
} else { } else {
//first opcode did not match.. //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; res = MatchFailed;
} }
} }

View File

@ -1,22 +1,26 @@
#ifndef _EQSTREAM_H #ifndef _EQSTREAM_H
#define _EQSTREAM_H #define _EQSTREAM_H
#include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <queue> #include <queue>
#include <deque> #include <deque>
#ifndef WIN32 #ifndef WIN32
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#include "eq_stream_type.h"
#include "../common/misc.h"
#include "../common/opcodemgr.h"
#include "../common/timer.h"
#include "eq_packet.h" #include "eq_packet.h"
#include "eq_stream_intf.h" #include "eq_stream_intf.h"
#include "eq_stream_type.h"
#include "mutex.h" #include "mutex.h"
#include "../common/opcodemgr.h"
#include "../common/misc.h" class EQApplicationPacket;
#include "../common/condition.h" class EQProtocolPacket;
#include "../common/timer.h"
#define FLAG_COMPRESSED 0x01 #define FLAG_COMPRESSED 0x01
#define FLAG_ENCODED 0x04 #define FLAG_ENCODED 0x04
@ -45,6 +49,10 @@
#define RETRANSMIT_ACKED_PACKETS true #define RETRANSMIT_ACKED_PACKETS true
#endif #endif
#ifndef MAX_SESSION_RETRIES
#define MAX_SESSION_RETRIES 30
#endif
#pragma pack(1) #pragma pack(1)
struct SessionRequest { struct SessionRequest {
uint32 UnknownA; uint32 UnknownA;
@ -78,7 +86,6 @@ struct SessionStats {
#pragma pack() #pragma pack()
class OpcodeManager; class OpcodeManager;
class EQStreamPair;
class EQRawApplicationPacket; class EQRawApplicationPacket;
class EQStream : public EQStreamInterface { class EQStream : public EQStreamInterface {
@ -101,6 +108,9 @@ class EQStream : public EQStreamInterface {
uint32 retransmittimer; uint32 retransmittimer;
uint32 retransmittimeout; uint32 retransmittimeout;
uint16 sessionAttempts;
bool streamactive;
//uint32 buffer_len; //uint32 buffer_len;
uint32 Session, Key; uint32 Session, Key;
@ -194,10 +204,16 @@ class EQStream : public EQStreamInterface {
void _SendDisconnect(); void _SendDisconnect();
void init(); void init(bool resetSession=true);
public: 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() { init(); remote_ip = 0; remote_port = 0; State = UNESTABLISHED;
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(); } 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); } virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
void SetMaxLen(uint32 length) { MaxLen=length; } void SetMaxLen(uint32 length) { MaxLen=length; }
@ -221,6 +237,9 @@ class EQStream : public EQStreamInterface {
void SetLastPacketTime(uint32 t) {LastPacket=t;} void SetLastPacketTime(uint32 t) {LastPacket=t;}
void Write(int eq_fd); 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 bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; }
inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); } inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); }

View File

@ -1,5 +1,7 @@
#include "debug.h" #include "global_define.h"
#include "eqemu_logsys.h"
#include "eq_stream_factory.h" #include "eq_stream_factory.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#include <winsock.h> #include <winsock.h>
#include <process.h> #include <process.h>
@ -13,24 +15,24 @@
#include <netdb.h> #include <netdb.h>
#include <pthread.h> #include <pthread.h>
#endif #endif
#include <fcntl.h>
#include <iostream> #include <iostream>
#include <fcntl.h>
#include "op_codes.h" #include "op_codes.h"
#include "eq_stream.h"
#include "logsys.h"
ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs) ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs)
{ {
EQStreamFactory *fs=(EQStreamFactory *)eqfs; EQStreamFactory *fs=(EQStreamFactory *)eqfs;
#ifndef WIN32 #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 #endif
fs->ReaderLoop(); fs->ReaderLoop();
#ifndef WIN32 #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 #endif
THREAD_RETURN(nullptr); THREAD_RETURN(nullptr);
@ -41,13 +43,13 @@ ThreadReturnType EQStreamFactoryWriterLoop(void *eqfs)
EQStreamFactory *fs=(EQStreamFactory *)eqfs; EQStreamFactory *fs=(EQStreamFactory *)eqfs;
#ifndef WIN32 #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 #endif
fs->WriterLoop(); fs->WriterLoop();
#ifndef WIN32 #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 #endif
THREAD_RETURN(nullptr); THREAD_RETURN(nullptr);
@ -104,8 +106,6 @@ struct sockaddr_in address;
fcntl(sock, F_SETFL, O_NONBLOCK); fcntl(sock, F_SETFL, O_NONBLOCK);
#endif #endif
//moved these because on windows the output was delayed and causing the console window to look bad //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 #ifdef _WINDOWS
_beginthread(EQStreamFactoryReaderLoop,0, this); _beginthread(EQStreamFactoryReaderLoop,0, this);
_beginthread(EQStreamFactoryWriterLoop,0, this); _beginthread(EQStreamFactoryWriterLoop,0, this);
@ -116,44 +116,39 @@ struct sockaddr_in address;
return true; return true;
} }
EQStream *EQStreamFactory::Pop() std::shared_ptr<EQStream> EQStreamFactory::Pop()
{ {
EQStream *s=nullptr; std::shared_ptr<EQStream> s = nullptr;
//std::cout << "Pop():Locking MNewStreams" << std::endl;
MNewStreams.lock(); MNewStreams.lock();
if (NewStreams.size()) { if (NewStreams.size()) {
s=NewStreams.front(); s = NewStreams.front();
NewStreams.pop(); NewStreams.pop();
s->PutInUse(); s->PutInUse();
} }
MNewStreams.unlock(); MNewStreams.unlock();
//std::cout << "Pop(): Unlocking MNewStreams" << std::endl;
return s; return s;
} }
void EQStreamFactory::Push(EQStream *s) void EQStreamFactory::Push(std::shared_ptr<EQStream> s)
{ {
//std::cout << "Push():Locking MNewStreams" << std::endl;
MNewStreams.lock(); MNewStreams.lock();
NewStreams.push(s); NewStreams.push(s);
MNewStreams.unlock(); MNewStreams.unlock();
//std::cout << "Push(): Unlocking MNewStreams" << std::endl;
} }
void EQStreamFactory::ReaderLoop() void EQStreamFactory::ReaderLoop()
{ {
fd_set readset; fd_set readset;
std::map<std::pair<uint32, uint16>,EQStream *>::iterator stream_itr; std::map<std::pair<uint32, uint16>, std::shared_ptr<EQStream>>::iterator stream_itr;
int num; int num;
int length; int length;
unsigned char buffer[2048]; unsigned char buffer[2048];
sockaddr_in from; sockaddr_in from;
int socklen=sizeof(sockaddr_in); int socklen = sizeof(sockaddr_in);
timeval sleep_time; timeval sleep_time;
//time_t now; ReaderRunning = true;
ReaderRunning=true;
while(sock!=-1) { while(sock!=-1) {
MReaderRunning.lock(); MReaderRunning.lock();
if (!ReaderRunning) if (!ReaderRunning)
@ -184,10 +179,10 @@ timeval sleep_time;
// What do we wanna do? // What do we wanna do?
} else { } else {
MStreams.lock(); 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 (stream_itr == Streams.end()) {
if (buffer[1]==OP_SessionRequest) { if (buffer[1]==OP_SessionRequest) {
EQStream *s = new EQStream(from); std::shared_ptr<EQStream> s = std::make_shared<EQStream>(from);
s->SetStreamType(StreamType); s->SetStreamType(StreamType);
Streams[std::make_pair(from.sin_addr.s_addr, from.sin_port)]=s; Streams[std::make_pair(from.sin_addr.s_addr, from.sin_port)]=s;
WriterWork.Signal(); WriterWork.Signal();
@ -198,13 +193,13 @@ timeval sleep_time;
} }
MStreams.unlock(); MStreams.unlock();
} else { } else {
EQStream *curstream = stream_itr->second; std::shared_ptr<EQStream> curstream = stream_itr->second;
//dont bother processing incoming packets for closed connections //dont bother processing incoming packets for closed connections
if(curstream->CheckClosed()) if(curstream->CheckClosed())
curstream = nullptr; curstream = nullptr;
else else
curstream->PutInUse(); 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) { if(curstream) {
curstream->AddBytesRecv(length); curstream->AddBytesRecv(length);
@ -212,6 +207,7 @@ timeval sleep_time;
curstream->SetLastPacketTime(Timer::GetCurrentTime()); curstream->SetLastPacketTime(Timer::GetCurrentTime());
curstream->ReleaseFromUse(); curstream->ReleaseFromUse();
} }
MStreams.unlock();
} }
} }
} }
@ -224,10 +220,10 @@ void EQStreamFactory::CheckTimeout()
MStreams.lock(); MStreams.lock();
unsigned long now=Timer::GetCurrentTime(); unsigned long now=Timer::GetCurrentTime();
std::map<std::pair<uint32, uint16>,EQStream *>::iterator stream_itr; std::map<std::pair<uint32, uint16>, std::shared_ptr<EQStream>>::iterator stream_itr;
for(stream_itr=Streams.begin();stream_itr!=Streams.end();) { for(stream_itr = Streams.begin(); stream_itr != Streams.end();) {
EQStream *s = stream_itr->second; std::shared_ptr<EQStream> s = stream_itr->second;
s->CheckTimeout(now, stream_timeout); s->CheckTimeout(now, stream_timeout);
@ -239,11 +235,9 @@ void EQStreamFactory::CheckTimeout()
//give it a little time for everybody to finish with it //give it a little time for everybody to finish with it
} else { } else {
//everybody is done, we can delete it now //everybody is done, we can delete it now
//std::cout << "Removing connection" << std::endl; std::map<std::pair<uint32, uint16>, std::shared_ptr<EQStream>>::iterator temp = stream_itr;
std::map<std::pair<uint32, uint16>,EQStream *>::iterator temp=stream_itr;
++stream_itr; ++stream_itr;
//let whoever has the stream outside delete it temp->second = nullptr;
delete temp->second;
Streams.erase(temp); Streams.erase(temp);
continue; continue;
} }
@ -256,21 +250,17 @@ void EQStreamFactory::CheckTimeout()
void EQStreamFactory::WriterLoop() void EQStreamFactory::WriterLoop()
{ {
std::map<std::pair<uint32, uint16>,EQStream *>::iterator stream_itr; std::map<std::pair<uint32, uint16>, std::shared_ptr<EQStream>>::iterator stream_itr;
bool havework=true; bool havework=true;
std::vector<EQStream *> wants_write; std::vector<std::shared_ptr<EQStream>> wants_write;
std::vector<EQStream *>::iterator cur,end; std::vector<std::shared_ptr<EQStream>>::iterator cur, end;
bool decay=false; bool decay = false;
uint32 stream_count; uint32 stream_count;
Timer DecayTimer(20);
Timer DecayTimer(20); WriterRunning = true;
WriterRunning=true;
DecayTimer.Enable(); DecayTimer.Enable();
while(sock!=-1) { while(sock!=-1) {
//if (!havework) {
//WriterWork.Wait();
//}
MWriterRunning.lock(); MWriterRunning.lock();
if (!WriterRunning) if (!WriterRunning)
break; break;
@ -291,7 +281,7 @@ Timer DecayTimer(20);
//bullshit checking, to see if this is really happening, GDB seems to think so... //bullshit checking, to see if this is really happening, GDB seems to think so...
if(stream_itr->second == nullptr) { 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; continue;
} }
@ -314,12 +304,10 @@ Timer DecayTimer(20);
Sleep(10); Sleep(10);
MStreams.lock(); MStreams.lock();
stream_count=Streams.size(); stream_count = Streams.size();
MStreams.unlock(); MStreams.unlock();
if (!stream_count) { if (!stream_count) {
//std::cout << "No streams, waiting on condition" << std::endl;
WriterWork.Wait(); WriterWork.Wait();
//std::cout << "Awake from condition, must have a stream now" << std::endl;
} }
} }
} }

View File

@ -2,13 +2,16 @@
#define _EQSTREAMFACTORY_H #define _EQSTREAMFACTORY_H
#include <memory>
#include <queue> #include <queue>
#include <map> #include <map>
#include "../common/eq_stream.h" #include "../common/eq_stream.h"
#include "../common/condition.h" #include "../common/condition.h"
#include "../common/timeoutmgr.h" #include "../common/timeoutmgr.h"
#include "../common/opcodemgr.h"
#include "../common/timer.h" class EQStream;
class Timer;
class EQStreamFactory : private Timeoutable { class EQStreamFactory : private Timeoutable {
private: private:
@ -24,10 +27,10 @@ class EQStreamFactory : private Timeoutable {
EQStreamType StreamType; EQStreamType StreamType;
std::queue<EQStream *> NewStreams; std::queue<std::shared_ptr<EQStream>> NewStreams;
Mutex MNewStreams; Mutex MNewStreams;
std::map<std::pair<uint32, uint16>,EQStream *> Streams; std::map<std::pair<uint32, uint16>, std::shared_ptr<EQStream>> Streams;
Mutex MStreams; Mutex MStreams;
virtual void CheckTimeout(); 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, uint32 timeout = 135000) : Timeoutable(5000), stream_timeout(timeout) { ReaderRunning=false; WriterRunning=false; StreamType=type; sock=-1; }
EQStreamFactory(EQStreamType type, int port, uint32 timeout = 135000); EQStreamFactory(EQStreamType type, int port, uint32 timeout = 135000);
EQStream *Pop(); std::shared_ptr<EQStream> Pop();
void Push(EQStream *s); void Push(std::shared_ptr<EQStream> s);
bool Open(); bool Open();
bool Open(unsigned long port) { Port=port; return Open(); } bool Open(unsigned long port) { Port=port; return Open(); }

View File

@ -1,20 +1,20 @@
#include "debug.h" #include "global_define.h"
#include "eqemu_logsys.h"
#include "eq_stream_ident.h" #include "eq_stream_ident.h"
#include "eq_stream_proxy.h" #include "eq_stream_proxy.h"
#include "logsys.h"
EQStreamIdentifier::~EQStreamIdentifier() { EQStreamIdentifier::~EQStreamIdentifier() {
while(!m_identified.empty()) { while(!m_identified.empty()) {
m_identified.front()->ReleaseFromUse(); m_identified.front()->ReleaseFromUse();
m_identified.pop(); m_identified.pop();
} }
std::vector<Record *>::iterator cur, end; std::vector<Record>::iterator cur, end;
cur = m_streams.begin(); cur = m_streams.begin();
end = m_streams.end(); end = m_streams.end();
for(; cur != end; ++cur) { for(; cur != end; ++cur) {
Record *r = *cur; Record &r = *cur;
r->stream->ReleaseFromUse(); r.stream->ReleaseFromUse();
delete r;
} }
std::vector<Patch *>::iterator curp, endp; std::vector<Patch *>::iterator curp, endp;
curp = m_patches.begin(); curp = m_patches.begin();
@ -34,54 +34,52 @@ void EQStreamIdentifier::RegisterPatch(const EQStream::Signature &sig, const cha
} }
void EQStreamIdentifier::Process() { void EQStreamIdentifier::Process() {
std::vector<Record *>::iterator cur; std::vector<Record>::iterator cur;
std::vector<Patch *>::iterator curp, endp; std::vector<Patch *>::iterator curp, endp;
//foreach pending stream. //foreach pending stream.
cur = m_streams.begin(); cur = m_streams.begin();
while(cur != m_streams.end()) { while(cur != m_streams.end()) {
Record *r = *cur; Record &r = *cur;
//first see if this stream has expired //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. //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())); 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(); r.stream->ReleaseFromUse();
delete r;
cur = m_streams.erase(cur); cur = m_streams.erase(cur);
continue; continue;
} }
//then make sure the stream is still active //then make sure the stream is still active
//if stream hasn't finished initializing then continue; //if stream hasn't finished initializing then continue;
if(r->stream->GetState() == UNESTABLISHED) if(r.stream->GetState() == UNESTABLISHED)
{ {
++cur; ++cur;
continue; continue;
} }
if(r->stream->GetState() != ESTABLISHED) { if(r.stream->GetState() != ESTABLISHED) {
//the stream closed before it was identified. //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())); 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()) switch(r.stream->GetState())
{ {
case ESTABLISHED: case ESTABLISHED:
_log(NET__IDENTIFY, "Stream state was Established"); Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Established");
break; break;
case CLOSING: case CLOSING:
_log(NET__IDENTIFY, "Stream state was Closing"); Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closing");
break; break;
case DISCONNECTING: case DISCONNECTING:
_log(NET__IDENTIFY, "Stream state was Disconnecting"); Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Disconnecting");
break; break;
case CLOSED: case CLOSED:
_log(NET__IDENTIFY, "Stream state was Closed"); Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Closed");
break; break;
default: default:
_log(NET__IDENTIFY, "Stream state was Unestablished or unknown"); Log.Out(Logs::General, Logs::Netcode, "[IDENTIFY] Stream state was Unestablished or unknown");
break; break;
} }
r->stream->ReleaseFromUse(); r.stream->ReleaseFromUse();
delete r;
cur = m_streams.erase(cur); cur = m_streams.erase(cur);
continue; continue;
} }
@ -98,20 +96,23 @@ void EQStreamIdentifier::Process() {
Patch *p = *curp; Patch *p = *curp;
//ask the stream to see if it matches the supplied signature //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) { switch(res) {
case EQStream::MatchNotReady: case EQStream::MatchNotReady:
//the stream has not received enough packets to compare with this signature //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; all_ready = false;
break; break;
case EQStream::MatchSuccessful: { case EQStream::MatchSuccessful: {
//yay, a match. //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.. //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); m_identified.push(s);
found_one = true; found_one = true;
@ -119,7 +120,7 @@ void EQStreamIdentifier::Process() {
} }
case EQStream::MatchFailed: case EQStream::MatchFailed:
//do nothing... //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; break;
} }
} }
@ -127,14 +128,13 @@ void EQStreamIdentifier::Process() {
//if we checked all patches and did not find a match. //if we checked all patches and did not find a match.
if(all_ready && !found_one) { if(all_ready && !found_one) {
//the stream cannot be identified. //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())); 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(); r.stream->ReleaseFromUse();
} }
//if we found a match, or were not able to identify it //if we found a match, or were not able to identify it
if(found_one || all_ready) { if(found_one || all_ready) {
//cannot print ip/port here. r->stream is invalid. //cannot print ip/port here. r.stream is invalid.
delete r;
cur = m_streams.erase(cur); cur = m_streams.erase(cur);
} else { } else {
++cur; ++cur;
@ -142,8 +142,8 @@ void EQStreamIdentifier::Process() {
} //end foreach stream } //end foreach stream
} }
void EQStreamIdentifier::AddStream(EQStream *&eqs) { void EQStreamIdentifier::AddStream(std::shared_ptr<EQStream> &eqs) {
m_streams.push_back(new Record(eqs)); m_streams.push_back(Record(eqs));
eqs = nullptr; eqs = nullptr;
} }
@ -155,7 +155,7 @@ EQStreamInterface *EQStreamIdentifier::PopIdentified() {
return(res); return(res);
} }
EQStreamIdentifier::Record::Record(EQStream *s) EQStreamIdentifier::Record::Record(std::shared_ptr<EQStream> s)
: stream(s), : stream(s),
expire(STREAM_IDENT_WAIT_MS) expire(STREAM_IDENT_WAIT_MS)
{ {

View File

@ -4,13 +4,14 @@
#include "eq_stream.h" #include "eq_stream.h"
#include "timer.h" #include "timer.h"
#include <vector> #include <vector>
#include <string>
#include <queue> #include <queue>
#include <memory>
#define STREAM_IDENT_WAIT_MS 10000 #define STREAM_IDENT_WAIT_MS 10000
class OpcodeManager; class OpcodeManager;
class StructStrategy; class StructStrategy;
class EQStreamInterface;
class EQStreamIdentifier { class EQStreamIdentifier {
public: public:
@ -21,7 +22,7 @@ public:
//main processing interface //main processing interface
void Process(); void Process();
void AddStream(EQStream *& eqs); void AddStream(std::shared_ptr<EQStream> &eqs);
EQStreamInterface *PopIdentified(); EQStreamInterface *PopIdentified();
protected: protected:
@ -39,11 +40,11 @@ protected:
//pending streams.. //pending streams..
class Record { class Record {
public: public:
Record(EQStream *s); Record(std::shared_ptr<EQStream> s);
EQStream *stream; //we own this std::shared_ptr<EQStream> stream; //we own this
Timer expire; Timer expire;
}; };
std::vector<Record *> m_streams; //we own these objects, and the streams contained in them. std::vector<Record> m_streams; //we own these objects, and the streams contained in them.
std::queue<EQStreamInterface *> m_identified; //we own these objects std::queue<EQStreamInterface *> m_identified; //we own these objects
}; };

View File

@ -35,7 +35,7 @@ public:
virtual const uint32 GetBytesRecieved() const { return 0; } virtual const uint32 GetBytesRecieved() const { return 0; }
virtual const uint32 GetBytesSentPerSecond() const { return 0; } virtual const uint32 GetBytesSentPerSecond() const { return 0; }
virtual const uint32 GetBytesRecvPerSecond() 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_*/ #endif /*EQSTREAMINTF_H_*/

View File

@ -1,11 +1,11 @@
#include "debug.h" #include "global_define.h"
#include "eq_stream_proxy.h" #include "eq_stream_proxy.h"
#include "eq_stream.h" #include "eq_stream.h"
#include "struct_strategy.h" #include "struct_strategy.h"
EQStreamProxy::EQStreamProxy(EQStream *&stream, const StructStrategy *structs, OpcodeManager **opcodes) EQStreamProxy::EQStreamProxy(std::shared_ptr<EQStream> &stream, const StructStrategy *structs, OpcodeManager **opcodes)
: m_stream(stream), : m_stream(stream),
m_structs(structs), m_structs(structs),
m_opcodes(opcodes) m_opcodes(opcodes)
@ -15,16 +15,15 @@ EQStreamProxy::EQStreamProxy(EQStream *&stream, const StructStrategy *structs, O
} }
EQStreamProxy::~EQStreamProxy() { EQStreamProxy::~EQStreamProxy() {
//delete m_stream; //released by the stream factory.
} }
std::string EQStreamProxy::Describe() const { std::string EQStreamProxy::Describe() const {
return(m_structs->Describe()); 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) { void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) {
@ -85,12 +84,6 @@ const uint32 EQStreamProxy::GetBytesRecvPerSecond() const
void EQStreamProxy::ReleaseFromUse() { void EQStreamProxy::ReleaseFromUse() {
m_stream->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() { void EQStreamProxy::RemoveData() {

View File

@ -4,8 +4,9 @@
#include "types.h" #include "types.h"
#include "eq_stream_intf.h" #include "eq_stream_intf.h"
#include "eq_stream.h"
#include <memory>
class EQStream;
class StructStrategy; class StructStrategy;
class OpcodeManager; class OpcodeManager;
class EQApplicationPacket; class EQApplicationPacket;
@ -13,7 +14,7 @@ class EQApplicationPacket;
class EQStreamProxy : public EQStreamInterface { class EQStreamProxy : public EQStreamInterface {
public: public:
//takes ownership of the stream. //takes ownership of the stream.
EQStreamProxy(EQStream *&stream, const StructStrategy *structs, OpcodeManager **opcodes); EQStreamProxy(std::shared_ptr<EQStream> &stream, const StructStrategy *structs, OpcodeManager **opcodes);
virtual ~EQStreamProxy(); virtual ~EQStreamProxy();
//EQStreamInterface: //EQStreamInterface:
@ -27,7 +28,7 @@ public:
virtual void RemoveData(); virtual void RemoveData();
virtual bool CheckState(EQStreamState state); virtual bool CheckState(EQStreamState state);
virtual std::string Describe() const; virtual std::string Describe() const;
virtual const EQClientVersion ClientVersion() const; virtual const ClientVersion GetClientVersion() const;
virtual const uint32 GetBytesSent() const; virtual const uint32 GetBytesSent() const;
virtual const uint32 GetBytesRecieved() const; virtual const uint32 GetBytesRecieved() const;
@ -35,7 +36,7 @@ public:
virtual const uint32 GetBytesRecvPerSecond() const; virtual const uint32 GetBytesRecvPerSecond() const;
protected: protected:
EQStream *const m_stream; //we own this stream object. std::shared_ptr<EQStream> const m_stream; //we own this stream object.
const StructStrategy *const m_structs; //we do not own this 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 //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. //reference an invalid opcode manager when they are being reloaded.

View File

@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h" #include "global_define.h"
#include "eqdb.h" #include "eqdb.h"
#include "database.h" #include "database.h"
#include <mysql.h> #include <mysql.h>

View File

@ -15,7 +15,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h" #include "global_define.h"
#include "eqdb_res.h" #include "eqdb_res.h"
#include <mysql.h> #include <mysql.h>

View File

@ -1,4 +1,4 @@
/* EQEMu: Everquest Server Emulator /* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify 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 along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 "eqemu_config.h"
#include "misc_functions.h" #include "misc_functions.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
std::string EQEmuConfig::ConfigFile = "eqemu_config.xml"; std::string EQEmuConfig::ConfigFile = "eqemu_config.xml";
EQEmuConfig *EQEmuConfig::_config = nullptr; EQEmuConfig *EQEmuConfig::_config = nullptr;
void EQEmuConfig::do_world(TiXmlElement *ele) { void EQEmuConfig::do_world(TiXmlElement *ele)
{
const char *text; const char *text;
TiXmlElement * sub_ele;; TiXmlElement * sub_ele;;
text = ParseTextBlock(ele, "shortname");
text= ParseTextBlock(ele,"shortname"); if (text) {
if (text) ShortName = text;
ShortName=text; }
text = ParseTextBlock(ele, "longname");
text = ParseTextBlock(ele,"longname"); if (text) {
if (text) LongName = text;
LongName=text; }
text = ParseTextBlock(ele, "address", true);
text = ParseTextBlock(ele,"address",true); if (text) {
if (text) WorldAddress = text;
WorldAddress=text; }
text = ParseTextBlock(ele, "localaddress", true);
text = ParseTextBlock(ele,"localaddress",true); if (text) {
if (text) LocalAddress = text;
LocalAddress=text; }
text = ParseTextBlock(ele, "maxclients", true);
text = ParseTextBlock(ele,"maxclients",true); if (text) {
if (text) MaxClients = atoi(text);
MaxClients=atoi(text); }
// Get the <key> element // Get the <key> element
text = ParseTextBlock(ele,"key",true); text = ParseTextBlock(ele, "key", true);
if (text) if (text) {
SharedKey=text; SharedKey = text;
}
// Get the <loginserver> element // Get the <loginserver> element
sub_ele = ele->FirstChildElement("loginserver"); sub_ele = ele->FirstChildElement("loginserver");
if (sub_ele) { if (sub_ele) {
text=ParseTextBlock(sub_ele,"host",true); text = ParseTextBlock(sub_ele, "host", true);
if (text) if (text) {
LoginHost=text; LoginHost = text;
}
text=ParseTextBlock(sub_ele,"port",true); text = ParseTextBlock(sub_ele, "port", true);
if (text) if (text) {
LoginPort=atoi(text); LoginPort = atoi(text);
}
text=ParseTextBlock(sub_ele,"account",true); text = ParseTextBlock(sub_ele, "account", true);
if (text) if (text) {
LoginAccount=text; LoginAccount = text;
}
text=ParseTextBlock(sub_ele,"password",true); text = ParseTextBlock(sub_ele, "password", true);
if (text) if (text) {
LoginPassword=text; LoginPassword = text;
}
} else { } else {
char str[32]; char str[32];
do { do {
@ -78,329 +81,366 @@ void EQEmuConfig::do_world(TiXmlElement *ele) {
sub_ele = ele->FirstChildElement(str); sub_ele = ele->FirstChildElement(str);
if (sub_ele) { if (sub_ele) {
LoginConfig* loginconfig = new LoginConfig; LoginConfig* loginconfig = new LoginConfig;
text=ParseTextBlock(sub_ele,"host",true); text = ParseTextBlock(sub_ele, "host", true);
if (text) if (text) {
loginconfig->LoginHost=text; loginconfig->LoginHost = text;
}
text=ParseTextBlock(sub_ele,"port",true); text = ParseTextBlock(sub_ele, "port", true);
if (text) if (text) {
loginconfig->LoginPort=atoi(text); loginconfig->LoginPort = atoi(text);
}
text=ParseTextBlock(sub_ele,"account",true); text = ParseTextBlock(sub_ele, "account", true);
if (text) if (text) {
loginconfig->LoginAccount=text; loginconfig->LoginAccount = text;
}
text=ParseTextBlock(sub_ele,"password",true); text = ParseTextBlock(sub_ele, "password", true);
if (text) if (text) {
loginconfig->LoginPassword=text; loginconfig->LoginPassword = text;
}
loginlist.Insert(loginconfig); loginlist.Insert(loginconfig);
} }
} while(sub_ele); } while (sub_ele);
} }
// Check for locked // Check for locked
sub_ele = ele->FirstChildElement("locked"); sub_ele = ele->FirstChildElement("locked");
if (sub_ele != nullptr) if (sub_ele != nullptr) {
Locked=true; Locked = true;
}
// Get the <tcp> element // Get the <tcp> element
sub_ele = ele->FirstChildElement("tcp"); sub_ele = ele->FirstChildElement("tcp");
if(sub_ele != nullptr) { if (sub_ele != nullptr) {
text = sub_ele->Attribute("ip"); text = sub_ele->Attribute("ip");
if (text) if (text) {
WorldIP=text; WorldIP = text;
}
text = sub_ele->Attribute("port"); text = sub_ele->Attribute("port");
if (text) if (text) {
WorldTCPPort=atoi(text); WorldTCPPort = atoi(text);
}
text = sub_ele->Attribute("telnet"); text = sub_ele->Attribute("telnet");
if (text && !strcasecmp(text,"enabled")) if (text && !strcasecmp(text, "enabled")) {
TelnetEnabled=true; TelnetEnabled = true;
}
} }
// Get the <http> element // Get the <http> element
sub_ele = ele->FirstChildElement("http"); sub_ele = ele->FirstChildElement("http");
if(sub_ele != nullptr) { if (sub_ele != nullptr) {
// text = sub_ele->Attribute("ip"); // text = sub_ele->Attribute("ip");
// if (text) // if (text)
// WorldIP=text; // WorldIP=text;
text = sub_ele->Attribute("mimefile"); text = sub_ele->Attribute("mimefile");
if (text) if (text) {
WorldHTTPMimeFile=text; WorldHTTPMimeFile = text;
}
text = sub_ele->Attribute("port"); text = sub_ele->Attribute("port");
if (text) if (text) {
WorldHTTPPort=atoi(text); WorldHTTPPort = atoi(text);
}
text = sub_ele->Attribute("enabled"); text = sub_ele->Attribute("enabled");
if (text && !strcasecmp(text,"true")) if (text && !strcasecmp(text, "true")) {
WorldHTTPEnabled=true; WorldHTTPEnabled = true;
}
} }
} }
void EQEmuConfig::do_chatserver(TiXmlElement *ele) { void EQEmuConfig::do_chatserver(TiXmlElement *ele)
{
const char *text; const char *text;
text = ParseTextBlock(ele, "host", true);
text=ParseTextBlock(ele,"host",true); if (text) {
if (text) ChatHost = text;
ChatHost=text; }
text = ParseTextBlock(ele, "port", true);
text=ParseTextBlock(ele,"port",true); if (text) {
if (text) ChatPort = atoi(text);
ChatPort=atoi(text); }
} }
void EQEmuConfig::do_mailserver(TiXmlElement *ele) { void EQEmuConfig::do_mailserver(TiXmlElement *ele)
{
const char *text; const char *text;
text = ParseTextBlock(ele, "host", true);
text=ParseTextBlock(ele,"host",true); if (text) {
if (text) MailHost = text;
MailHost=text; }
text = ParseTextBlock(ele, "port", true);
text=ParseTextBlock(ele,"port",true); if (text) {
if (text) MailPort = atoi(text);
MailPort=atoi(text); }
} }
void EQEmuConfig::do_database(TiXmlElement *ele) { void EQEmuConfig::do_database(TiXmlElement *ele)
{
const char *text; const char *text;
text = ParseTextBlock(ele, "host", true);
text=ParseTextBlock(ele,"host",true); if (text) {
if (text) DatabaseHost = text;
DatabaseHost=text; }
text = ParseTextBlock(ele, "port", true);
text=ParseTextBlock(ele,"port",true); if (text) {
if (text) DatabasePort = atoi(text);
DatabasePort=atoi(text); }
text = ParseTextBlock(ele, "username", true);
text=ParseTextBlock(ele,"username",true); if (text) {
if (text) DatabaseUsername = text;
DatabaseUsername=text; }
text = ParseTextBlock(ele, "password", true);
text=ParseTextBlock(ele,"password",true); if (text) {
if (text) DatabasePassword = text;
DatabasePassword=text; }
text = ParseTextBlock(ele, "db", true);
text=ParseTextBlock(ele,"db",true); if (text) {
if (text) DatabaseDB = text;
DatabaseDB=text; }
} }
void EQEmuConfig::do_qsdatabase(TiXmlElement *ele) { void EQEmuConfig::do_qsdatabase(TiXmlElement *ele)
{
const char *text; const char *text;
text = ParseTextBlock(ele, "host", true);
text=ParseTextBlock(ele,"host",true); if (text) {
if (text) QSDatabaseHost = text;
QSDatabaseHost=text; }
text = ParseTextBlock(ele, "port", true);
text=ParseTextBlock(ele,"port",true); if (text) {
if (text) QSDatabasePort = atoi(text);
QSDatabasePort=atoi(text); }
text = ParseTextBlock(ele, "username", true);
text=ParseTextBlock(ele,"username",true); if (text) {
if (text) QSDatabaseUsername = text;
QSDatabaseUsername=text; }
text = ParseTextBlock(ele, "password", true);
text=ParseTextBlock(ele,"password",true); if (text) {
if (text) QSDatabasePassword = text;
QSDatabasePassword=text; }
text = ParseTextBlock(ele, "db", true);
text=ParseTextBlock(ele,"db",true); if (text) {
if (text) QSDatabaseDB = text;
QSDatabaseDB=text; }
} }
void EQEmuConfig::do_zones(TiXmlElement *ele) { void EQEmuConfig::do_zones(TiXmlElement *ele)
{
const char *text; const char *text;
TiXmlElement *sub_ele; TiXmlElement *sub_ele;
// TiXmlNode *node,*sub_node; // TiXmlNode *node,*sub_node;
text = ParseTextBlock(ele, "defaultstatus", true);
text=ParseTextBlock(ele,"defaultstatus",true); if (text) {
if (text) DefaultStatus = atoi(text);
DefaultStatus=atoi(text); }
// Get the <ports> element // Get the <ports> element
sub_ele = ele->FirstChildElement("ports"); sub_ele = ele->FirstChildElement("ports");
if(sub_ele != nullptr) { if (sub_ele != nullptr) {
text = sub_ele->Attribute("low"); text = sub_ele->Attribute("low");
if (text) if (text) {
ZonePortLow=atoi(text);; ZonePortLow = atoi(text);
};
text = sub_ele->Attribute("high"); text = sub_ele->Attribute("high");
if (text) if (text) {
ZonePortHigh=atoi(text); ZonePortHigh = atoi(text);
}
} }
} }
void EQEmuConfig::do_files(TiXmlElement *ele) { void EQEmuConfig::do_files(TiXmlElement *ele)
{
const char *text; const char *text;
text = ParseTextBlock(ele, "spells", true);
text=ParseTextBlock(ele,"spells",true); if (text) {
if (text) SpellsFile = text;
SpellsFile=text; }
text = ParseTextBlock(ele, "opcodes", true);
text=ParseTextBlock(ele,"opcodes",true); if (text) {
if (text) OpCodesFile = text;
OpCodesFile=text; }
text = ParseTextBlock(ele, "eqtime", true);
text=ParseTextBlock(ele,"logsettings",true); if (text) {
if (text) EQTimeFile = text;
LogSettingsFile=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; const char *text;
text = ParseTextBlock(ele, "maps", true);
text=ParseTextBlock(ele,"maps",true); if (text) {
if (text) MapDir = text;
MapDir=text; }
text = ParseTextBlock(ele, "quests", true);
text=ParseTextBlock(ele,"quests",true); if (text) {
if (text) QuestDir = text;
QuestDir=text; }
text = ParseTextBlock(ele, "plugins", true);
text=ParseTextBlock(ele,"plugins",true); if (text) {
if (text) PluginDir = text;
PluginDir=text; }
} }
void EQEmuConfig::do_launcher(TiXmlElement *ele) { void EQEmuConfig::do_launcher(TiXmlElement *ele)
{
const char *text; const char *text;
TiXmlElement *sub_ele; TiXmlElement *sub_ele;
text = ParseTextBlock(ele, "logprefix", true);
text=ParseTextBlock(ele,"logprefix",true); if (text) {
if (text)
LogPrefix = text; LogPrefix = text;
}
text=ParseTextBlock(ele,"logsuffix",true); text = ParseTextBlock(ele, "logsuffix", true);
if (text) if (text) {
LogSuffix = text; LogSuffix = text;
}
// Get the <exe> element // Get the <exe> element
text = ParseTextBlock(ele,"exe",true); text = ParseTextBlock(ele, "exe", true);
if (text) if (text) {
ZoneExe = text; ZoneExe = text;
}
// Get the <timers> element // Get the <timers> element
sub_ele = ele->FirstChildElement("timers"); sub_ele = ele->FirstChildElement("timers");
if(sub_ele != nullptr) { if (sub_ele != nullptr) {
text = sub_ele->Attribute("restart"); text = sub_ele->Attribute("restart");
if (text) if (text) {
RestartWait = atoi(text); RestartWait = atoi(text);
}
text = sub_ele->Attribute("reterminate"); text = sub_ele->Attribute("reterminate");
if (text) if (text) {
TerminateWait = atoi(text); TerminateWait = atoi(text);
}
text = sub_ele->Attribute("initial"); text = sub_ele->Attribute("initial");
if (text) if (text) {
InitialBootWait = atoi(text); InitialBootWait = atoi(text);
}
text = sub_ele->Attribute("interval"); text = sub_ele->Attribute("interval");
if (text) if (text) {
ZoneBootInterval = atoi(text); ZoneBootInterval = atoi(text);
}
} }
} }
std::string EQEmuConfig::GetByName(const std::string &var_name) const { std::string EQEmuConfig::GetByName(const std::string &var_name) const
if(var_name == "ShortName") {
return(ShortName); if (var_name == "ShortName") {
if(var_name == "LongName") return (ShortName);
return(LongName); }
if(var_name == "WorldAddress") if (var_name == "LongName") {
return(WorldAddress); return (LongName);
if(var_name == "LoginHost") }
return(LoginHost); if (var_name == "WorldAddress") {
if(var_name == "LoginAccount") return (WorldAddress);
return(LoginAccount); }
if(var_name == "LoginPassword") if (var_name == "LoginHost") {
return(LoginPassword); return (LoginHost);
if(var_name == "LoginPort") }
return(itoa(LoginPort)); if (var_name == "LoginAccount") {
if(var_name == "Locked") return (LoginAccount);
return(Locked?"true":"false"); }
if(var_name == "WorldTCPPort") if (var_name == "LoginPassword") {
return(itoa(WorldTCPPort)); return (LoginPassword);
if(var_name == "WorldIP") }
return(WorldIP); if (var_name == "LoginPort") {
if(var_name == "TelnetEnabled") return (itoa(LoginPort));
return(TelnetEnabled?"true":"false"); }
if(var_name == "WorldHTTPPort") if (var_name == "Locked") {
return(itoa(WorldHTTPPort)); return (Locked ? "true" : "false");
if(var_name == "WorldHTTPMimeFile") }
return(WorldHTTPMimeFile); if (var_name == "WorldTCPPort") {
if(var_name == "WorldHTTPEnabled") return (itoa(WorldTCPPort));
return(WorldHTTPEnabled?"true":"false"); }
if(var_name == "ChatHost") if (var_name == "WorldIP") {
return(ChatHost); return (WorldIP);
if(var_name == "ChatPort") }
return(itoa(ChatPort)); if (var_name == "TelnetEnabled") {
if(var_name == "MailHost") return (TelnetEnabled ? "true" : "false");
return(MailHost); }
if(var_name == "MailPort") if (var_name == "WorldHTTPPort") {
return(itoa(MailPort)); return (itoa(WorldHTTPPort));
if(var_name == "DatabaseHost") }
return(DatabaseHost); if (var_name == "WorldHTTPMimeFile") {
if(var_name == "DatabaseUsername") return (WorldHTTPMimeFile);
return(DatabaseUsername); }
if(var_name == "DatabasePassword") if (var_name == "WorldHTTPEnabled") {
return(DatabasePassword); return (WorldHTTPEnabled ? "true" : "false");
if(var_name == "DatabaseDB") }
return(DatabaseDB); if (var_name == "ChatHost") {
if(var_name == "DatabasePort") return (ChatHost);
return(itoa(DatabasePort)); }
if(var_name == "QSDatabaseHost") if (var_name == "ChatPort") {
return(QSDatabaseHost); return (itoa(ChatPort));
if(var_name == "QSDatabaseUsername") }
return(QSDatabaseUsername); if (var_name == "MailHost") {
if(var_name == "QSDatabasePassword") return (MailHost);
return(QSDatabasePassword); }
if(var_name == "QSDatabaseDB") if (var_name == "MailPort") {
return(QSDatabaseDB); return (itoa(MailPort));
if(var_name == "QSDatabasePort") }
return(itoa(QSDatabasePort)); if (var_name == "DatabaseHost") {
if(var_name == "SpellsFile") return (DatabaseHost);
return(SpellsFile); }
if(var_name == "OpCodesFile") if (var_name == "DatabaseUsername") {
return(OpCodesFile); return (DatabaseUsername);
if(var_name == "EQTimeFile") }
return(EQTimeFile); if (var_name == "DatabasePassword") {
if(var_name == "LogSettingsFile") return (DatabasePassword);
return(LogSettingsFile); }
if(var_name == "MapDir") if (var_name == "DatabaseDB") {
return(MapDir); return (DatabaseDB);
if(var_name == "QuestDir") }
return(QuestDir); if (var_name == "DatabasePort") {
if(var_name == "PluginDir") return (itoa(DatabasePort));
return(PluginDir); }
if(var_name == "LogPrefix") if (var_name == "QSDatabaseHost") {
return(LogPrefix); return (QSDatabaseHost);
if(var_name == "LogSuffix") }
return(LogSuffix); if (var_name == "QSDatabaseUsername") {
if(var_name == "ZoneExe") return (QSDatabaseUsername);
return(ZoneExe); }
if(var_name == "ZonePortLow") if (var_name == "QSDatabasePassword") {
return(itoa(ZonePortLow)); return (QSDatabasePassword);
if(var_name == "ZonePortHigh") }
return(itoa(ZonePortHigh)); if (var_name == "QSDatabaseDB") {
if(var_name == "DefaultStatus") return (QSDatabaseDB);
return(itoa(DefaultStatus)); }
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") // if(var_name == "DynamicCount")
// return(itoa(DynamicCount)); // return(itoa(DynamicCount));
return(""); return ("");
} }
void EQEmuConfig::Dump() const void EQEmuConfig::Dump() const
@ -436,7 +476,6 @@ void EQEmuConfig::Dump() const
std::cout << "SpellsFile = " << SpellsFile << std::endl; std::cout << "SpellsFile = " << SpellsFile << std::endl;
std::cout << "OpCodesFile = " << OpCodesFile << std::endl; std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
std::cout << "EQTimeFile = " << EQTimeFile << std::endl; std::cout << "EQTimeFile = " << EQTimeFile << std::endl;
std::cout << "LogSettingsFile = " << LogSettingsFile << std::endl;
std::cout << "MapDir = " << MapDir << std::endl; std::cout << "MapDir = " << MapDir << std::endl;
std::cout << "QuestDir = " << QuestDir << std::endl; std::cout << "QuestDir = " << QuestDir << std::endl;
std::cout << "PluginDir = " << PluginDir << std::endl; std::cout << "PluginDir = " << PluginDir << std::endl;

View File

@ -1,4 +1,4 @@
/* EQEMu: Everquest Server Emulator /* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net) Copyright (C) 2001-2006 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -28,200 +28,190 @@ struct LoginConfig {
uint16 LoginPort; uint16 LoginPort;
}; };
class EQEmuConfig : public XMLParser { class EQEmuConfig : public XMLParser
public: {
virtual std::string GetByName(const std::string &var_name) const; public:
virtual std::string GetByName(const std::string &var_name) const;
// From <world/> // From <world/>
std::string ShortName; std::string ShortName;
std::string LongName; std::string LongName;
std::string WorldAddress; std::string WorldAddress;
std::string LocalAddress; std::string LocalAddress;
std::string LoginHost; std::string LoginHost;
std::string LoginAccount; std::string LoginAccount;
std::string LoginPassword; std::string LoginPassword;
uint16 LoginPort; uint16 LoginPort;
uint32 LoginCount; uint32 LoginCount;
LinkedList<LoginConfig*> loginlist; LinkedList<LoginConfig*> loginlist;
bool Locked; bool Locked;
uint16 WorldTCPPort; uint16 WorldTCPPort;
std::string WorldIP; std::string WorldIP;
bool TelnetEnabled; bool TelnetEnabled;
int32 MaxClients; int32 MaxClients;
bool WorldHTTPEnabled; bool WorldHTTPEnabled;
uint16 WorldHTTPPort; uint16 WorldHTTPPort;
std::string WorldHTTPMimeFile; std::string WorldHTTPMimeFile;
std::string SharedKey; std::string SharedKey;
// From <chatserver/> // From <chatserver/>
std::string ChatHost; std::string ChatHost;
uint16 ChatPort; uint16 ChatPort;
// From <mailserver/> // From <mailserver/>
std::string MailHost; std::string MailHost;
uint16 MailPort; uint16 MailPort;
// From <database/> // From <database/>
std::string DatabaseHost; std::string DatabaseHost;
std::string DatabaseUsername; std::string DatabaseUsername;
std::string DatabasePassword; std::string DatabasePassword;
std::string DatabaseDB; std::string DatabaseDB;
uint16 DatabasePort; uint16 DatabasePort;
// From <qsdatabase> // QueryServ // From <qsdatabase> // QueryServ
std::string QSDatabaseHost; std::string QSDatabaseHost;
std::string QSDatabaseUsername; std::string QSDatabaseUsername;
std::string QSDatabasePassword; std::string QSDatabasePassword;
std::string QSDatabaseDB; std::string QSDatabaseDB;
uint16 QSDatabasePort; uint16 QSDatabasePort;
// From <files/> // From <files/>
std::string SpellsFile; std::string SpellsFile;
std::string OpCodesFile; std::string OpCodesFile;
std::string EQTimeFile; std::string EQTimeFile;
std::string LogSettingsFile;
// From <directories/> // From <directories/>
std::string MapDir; std::string MapDir;
std::string QuestDir; std::string QuestDir;
std::string PluginDir; std::string PluginDir;
// From <launcher/> // From <launcher/>
std::string LogPrefix; std::string LogPrefix;
std::string LogSuffix; std::string LogSuffix;
std::string ZoneExe; std::string ZoneExe;
uint32 RestartWait; uint32 RestartWait;
uint32 TerminateWait; uint32 TerminateWait;
uint32 InitialBootWait; uint32 InitialBootWait;
uint32 ZoneBootInterval; uint32 ZoneBootInterval;
// From <zones/> // From <zones/>
uint16 ZonePortLow; uint16 ZonePortLow;
uint16 ZonePortHigh; uint16 ZonePortHigh;
uint8 DefaultStatus; uint8 DefaultStatus;
// uint16 DynamicCount; // uint16 DynamicCount;
// map<string,uint16> StaticZones; // map<string,uint16> StaticZones;
protected: protected:
static EQEmuConfig *_config; static EQEmuConfig *_config;
static std::string ConfigFile; static std::string ConfigFile;
#define ELEMENT(name) \ #define ELEMENT(name) \
void do_##name(TiXmlElement *ele); void do_##name(TiXmlElement *ele);
#include "eqemu_config_elements.h" #include "eqemu_config_elements.h"
EQEmuConfig() { EQEmuConfig()
// import the needed handler prototypes {
// import the needed handler prototypes
#define ELEMENT(name) \ #define ELEMENT(name) \
Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name; Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name;
#include "eqemu_config_elements.h" #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 // Produce a const singleton
LoginHost="eqemulator.net"; static const EQEmuConfig *get()
LoginPort=5998; {
if (_config == nullptr) {
LoadConfig();
}
return (_config);
}
// World // Allow the use to set the conf file to be used.
Locked=false; static void SetConfigFile(std::string file)
WorldTCPPort=9000; {
TelnetEnabled=false; EQEmuConfig::ConfigFile = file;
WorldHTTPEnabled=false; }
WorldHTTPPort=9080;
WorldHTTPMimeFile="mime.types";
SharedKey = ""; //blank disables authentication
// Mail // Load the config
ChatHost="eqchat.eqemulator.net"; static bool LoadConfig()
ChatPort=7778; {
if (_config != nullptr) {
delete _config;
}
_config = new EQEmuConfig;
return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(), "server");
}
// Mail void Dump() const;
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;
}; };
#endif #endif

View File

@ -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 <windows.h>
#endif
#include "eqemu_error.h"
#include "linked_list.h"
#include "mutex.h"
#include "misc_functions.h"
#include <stdio.h>
#include <string.h>
#ifdef _WINDOWS
#include <conio.h>
#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<char*>* EQEMuErrorList;
Mutex* MEQEMuErrorList;
AutoDelete< LinkedList<char*> > ADEQEMuErrorList(&EQEMuErrorList);
AutoDelete<Mutex> 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<char*>;
MEQEMuErrorList = new Mutex;
}
LockMutex lock(MEQEMuErrorList);
LinkedListIterator<char*> 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<char*>;
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
}

View File

@ -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

350
common/eqemu_logsys.cpp Normal file
View File

@ -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 <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <time.h>
#include <sys/stat.h>
std::ofstream process_log;
#ifdef _WINDOWS
#include <direct.h>
#include <conio.h>
#include <iostream>
#include <dos.h>
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#include <sys/stat.h>
#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);
}
}

204
common/eqemu_logsys.h Normal file
View File

@ -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 <iostream>
#include <fstream>
#include <stdio.h>
#include <functional>
#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<void(uint16 log_type, const std::string&)> f) { on_log_gmsay_hook = f; }
private:
std::function<void(uint16 log_category, const std::string&)> 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

View File

@ -17,7 +17,8 @@
*/ */
#include <fstream> #include <fstream>
#include "../common/debug.h" #include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/eqtime.h" #include "../common/eqtime.h"
#include "../common/eq_packet_structs.h" #include "../common/eq_packet_structs.h"
#include <memory.h> #include <memory.h>
@ -140,11 +141,10 @@ bool EQTime::saveFile(const char *filename)
of.open(filename); of.open(filename);
if(!of) 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; return false;
} }
//Enable for debugging //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 << EQT_VERSION << std::endl;
of << (long)eqTime.start_eqtime.day << std::endl; of << (long)eqTime.start_eqtime.day << std::endl;
of << (long)eqTime.start_eqtime.hour << std::endl; of << (long)eqTime.start_eqtime.hour << std::endl;
@ -164,14 +164,14 @@ bool EQTime::loadFile(const char *filename)
in.open(filename); in.open(filename);
if(!in) 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; return false;
} }
in >> version; in >> version;
in.ignore(80, '\n'); in.ignore(80, '\n');
if(version != EQT_VERSION) 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; return false;
} }
//in >> eqTime.start_eqtime.day; //in >> eqTime.start_eqtime.day;
@ -194,7 +194,6 @@ bool EQTime::loadFile(const char *filename)
in.ignore(80, '\n'); in.ignore(80, '\n');
in >> eqTime.start_realtime; in >> eqTime.start_realtime;
//Enable for debugging... //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(); in.close();
return true; return true;
} }

View File

@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h" #include "global_define.h"
#include "extprofile.h" #include "extprofile.h"
//Set defaults in the extended profile... //Set defaults in the extended profile...

View File

@ -1,4 +1,4 @@
/* EQEMu: Everquest Server Emulator /* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
This program is free software; you can redistribute it and/or modify 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 along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "debug.h"
#include "faction.h" #include "faction.h"
#include "races.h" #include "races.h"
const char *FactionValueToString(FACTION_VALUE fv) { const char *FactionValueToString(FACTION_VALUE fv)
switch(fv) { {
case FACTION_ALLY: switch (fv) {
return("Ally"); case FACTION_ALLY:
case FACTION_WARMLY: return ("Ally");
return("Warmly"); case FACTION_WARMLY:
case FACTION_KINDLY: return ("Warmly");
return("Kindly"); case FACTION_KINDLY:
case FACTION_AMIABLE: return ("Kindly");
return("Amiable"); case FACTION_AMIABLE:
case FACTION_INDIFFERENT: return ("Amiable");
return("Indifferent"); case FACTION_INDIFFERENT:
case FACTION_APPREHENSIVE: return ("Indifferent");
return("Apprehensive"); case FACTION_APPREHENSIVE:
case FACTION_DUBIOUS: return ("Apprehensive");
return("Dubious"); case FACTION_DUBIOUS:
case FACTION_THREATENLY: return ("Dubious");
return("Threatenly"); case FACTION_THREATENLY:
case FACTION_SCOWLS: return ("Threatenly");
return("Scowls, ready to attack."); case FACTION_SCOWLS:
default: return ("Scowls, ready to attack.");
break; default:
break;
} }
return("Unknown Faction Con"); return ("Unknown Faction Con");
} }
//o-------------------------------------------------------------- //o--------------------------------------------------------------
//| Name: CalculateFaction; rembrant, Dec. 16, 2001 //| Name: CalculateFaction; Dec. 16, 2001
//o-------------------------------------------------------------- //o--------------------------------------------------------------
//| Notes: Returns the faction message value. //| Notes: Returns the faction message value.
//| Modify these values to taste. //| Modify these values to taste.
@ -55,86 +56,112 @@ const char *FactionValueToString(FACTION_VALUE fv) {
FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value) FACTION_VALUE CalculateFaction(FactionMods* fm, int32 tmpCharacter_value)
{ {
int32 character_value = tmpCharacter_value; int32 character_value = tmpCharacter_value;
if (fm) if (fm) {
character_value += fm->base + fm->class_mod + fm->race_mod + fm->deity_mod; 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 >= 1101) {
if(character_value >= 401 && character_value <= 700) return FACTION_KINDLY; return FACTION_ALLY;
if(character_value >= 101 && character_value <= 400) return FACTION_AMIABLE; }
if(character_value >= 0 && character_value <= 100) return FACTION_INDIFFERENT; if (character_value >= 701 && character_value <= 1100) {
if(character_value >= -100 && character_value <= -1) return FACTION_APPREHENSIVE; return FACTION_WARMLY;
if(character_value >= -700 && character_value <= -101) return FACTION_DUBIOUS; }
if(character_value >= -999 && character_value <= -701) return FACTION_THREATENLY; if (character_value >= 401 && character_value <= 700) {
if(character_value <= -1000) return FACTION_SCOWLS; 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; 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) bool IsOfEqualRace(int r1, int r2)
{ {
if (r1 == r2) if (r1 == r2) {
return true; return true;
}
// TODO: add more values // TODO: add more values
switch(r1) switch (r1) {
{ case DARK_ELF:
case DARK_ELF: if (r2 == 77) {
if (r2 == 77) return true;
return true; }
break; break;
case BARBARIAN: case BARBARIAN:
if (r2 == 90) if (r2 == 90) {
return true; return true;
}
} }
return false; return false;
} }
// neotokyo: trolls endure ogres, dark elves, ... // trolls endure ogres, dark elves, ...
bool IsOfIndiffRace(int r1, int r2) bool IsOfIndiffRace(int r1, int r2)
{ {
if (r1 == r2) if (r1 == r2) {
return true; return true;
}
// TODO: add more values // TODO: add more values
switch(r1) switch (r1) {
{ case DARK_ELF:
case DARK_ELF: case OGRE:
case OGRE: case TROLL:
case TROLL: if (r2 == OGRE || r2 == TROLL || r2 == DARK_ELF) {
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; return true;
break; case IKSAR:
case HUMAN: return false;
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;
} }
return false; return false;
} }

View File

@ -163,7 +163,7 @@ enum { //timer settings, all in milliseconds
CombatEventTimer_expire = 12000, CombatEventTimer_expire = 12000,
Tribute_duration = 600000, Tribute_duration = 600000,
ZoneTimerResolution = 3, //sleep time between zone main loop runs (milliseconds) 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, EnragedTimer = 360000,
EnragedDurationTimer = 10000 EnragedDurationTimer = 10000
}; };
@ -208,12 +208,12 @@ enum { //some random constants
//chance ratio that a //chance ratio that a
#define THREATENLY_ARRGO_CHANCE 32 // 32/128 (25%) chance that a mob will arrgo on con Threatenly #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 #define MAX_NPC_FACTIONS 20
//value caps //individual faction pool
#define MAX_FACTION 1500 #define MAX_PERSONAL_FACTION 1200
#define MIN_FACTION -1500 #define MIN_PERSONAL_FACTION -3000
//The Level Cap: //The Level Cap:
//#define LEVEL_CAP RuleI(Character, MaxLevel) //hard cap is 127 //#define LEVEL_CAP RuleI(Character, MaxLevel) //hard cap is 127
@ -261,7 +261,8 @@ enum {
commandChangeFlags = 200, //ability to set/refresh flags commandChangeFlags = 200, //ability to set/refresh flags
commandBanPlayers = 100, //can set bans on players commandBanPlayers = 100, //can set bans on players
commandChangeDatarate = 201, //edit client's data rate 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) //default states for logging flag on NPCs and clients (having NPCs on by default is prolly a bad idea)

View File

@ -30,11 +30,13 @@ source_group("GTX Files" FILES ${GTX_HEADER})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
add_executable(${NAME} ${ROOT_TEXT} if(GLM_TEST_ENABLE)
${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} add_executable(${NAME} ${ROOT_TEXT}
${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER}
${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER}
${GTX_SOURCE} ${GTX_INLINE} ${GTX_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 STATIC glm.cpp)
#add_library(glm_shared SHARED glm.cpp) #add_library(glm_shared SHARED glm.cpp)

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -26,9 +30,6 @@
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_COMMON_INCLUDED #pragma once
#define GLM_COMMON_INCLUDED
#include "detail/func_common.hpp" #include "detail/func_common.hpp"
#endif//GLM_COMMON_INCLUDED

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,13 +25,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/_features.hpp /// @file glm/detail/_features.hpp
/// @date 2013-02-20 / 2013-02-20 /// @date 2013-02-20 / 2013-02-20
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_features #pragma once
#define glm_core_features
// #define GLM_CXX98_EXCEPTIONS // #define GLM_CXX98_EXCEPTIONS
// #define GLM_CXX98_RTTI // #define GLM_CXX98_RTTI
@ -281,7 +284,7 @@
# define GLM_CXX11_STATIC_ASSERT # define GLM_CXX11_STATIC_ASSERT
# endif # endif
#elif(GLM_COMPILER & GLM_COMPILER_CLANG) #elif(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM))
# if(__has_feature(cxx_exceptions)) # if(__has_feature(cxx_exceptions))
# define GLM_CXX98_EXCEPTIONS # define GLM_CXX98_EXCEPTIONS
# endif # endif
@ -422,6 +425,4 @@
# define GLM_CXX11_VARIADIC_TEMPLATES # define GLM_CXX11_VARIADIC_TEMPLATES
# endif # endif
#endif//(GLM_COMPILER & GLM_COMPILER_CLANG) #endif//(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM))
#endif//glm_core_features

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/_fixes.hpp /// @file glm/detail/_fixes.hpp
/// @date 2011-02-21 / 2011-11-22 /// @date 2011-02-21 / 2011-11-22
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -26,8 +30,12 @@
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_DETAIL_NOISE_INCLUDED #pragma once
#define GLM_DETAIL_NOISE_INCLUDED
#include "../vec2.hpp"
#include "../vec3.hpp"
#include "../vec4.hpp"
#include "../common.hpp"
namespace glm{ namespace glm{
namespace detail namespace detail
@ -75,19 +83,19 @@ namespace detail
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> taylorInvSqrt(detail::tvec2<T, P> const & r) GLM_FUNC_QUALIFIER tvec2<T, P> taylorInvSqrt(tvec2<T, P> const & r)
{ {
return T(1.79284291400159) - T(0.85373472095314) * r; return T(1.79284291400159) - T(0.85373472095314) * r;
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> taylorInvSqrt(detail::tvec3<T, P> const & r) GLM_FUNC_QUALIFIER tvec3<T, P> taylorInvSqrt(tvec3<T, P> const & r)
{ {
return T(1.79284291400159) - T(0.85373472095314) * r; return T(1.79284291400159) - T(0.85373472095314) * r;
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> taylorInvSqrt(detail::tvec4<T, P> const & r) GLM_FUNC_QUALIFIER tvec4<T, P> taylorInvSqrt(tvec4<T, P> const & r)
{ {
return T(1.79284291400159) - T(0.85373472095314) * r; return T(1.79284291400159) - T(0.85373472095314) * r;
} }
@ -100,19 +108,19 @@ namespace detail
*/ */
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> fade(detail::tvec2<T, P> const & t) GLM_FUNC_QUALIFIER tvec2<T, P> fade(tvec2<T, P> const & t)
{ {
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> fade(detail::tvec3<T, P> const & t) GLM_FUNC_QUALIFIER tvec3<T, P> fade(tvec3<T, P> const & t)
{ {
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> fade(detail::tvec4<T, P> const & t) GLM_FUNC_QUALIFIER tvec4<T, P> fade(tvec4<T, P> const & t)
{ {
return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); return (t * t * t) * (t * (t * T(6) - T(15)) + T(10));
} }
@ -126,5 +134,3 @@ namespace detail
}//namespace detail }//namespace detail
}//namespace glm }//namespace glm
#endif//GLM_DETAIL_NOISE_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,13 +25,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/_swizzle_func.hpp /// @file glm/detail/_swizzle_func.hpp
/// @date 2011-10-16 / 2011-10-16 /// @date 2011-10-16 / 2011-10-16
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_swizzle_func #pragma once
#define glm_core_swizzle_func
#define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ #define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \
SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B() CONST \ SWIZZLED_TYPE<TMPL_TYPE, PRECISION> 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_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) //GLM_SWIZZLE_GEN_VEC_FROM_VEC4(valType, detail::vec4, detail::vec2, detail::vec3, detail::vec4)
#endif//glm_core_swizzle_func

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,197 +25,136 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/_vectorize.hpp /// @file glm/detail/_vectorize.hpp
/// @date 2011-10-14 / 2011-10-14 /// @date 2011-10-14 / 2011-10-14
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_CORE_DETAIL_INCLUDED #pragma once
#define GLM_CORE_DETAIL_INCLUDED
#include "type_vec1.hpp" #include "type_vec1.hpp"
#include "type_vec2.hpp" #include "type_vec2.hpp"
#include "type_vec3.hpp" #include "type_vec3.hpp"
#include "type_vec4.hpp" #include "type_vec4.hpp"
#define VECTORIZE1_VEC(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec1<T, P> func( \
detail::tvec1<T, P> const & v) \
{ \
return detail::tvec1<T, P>( \
func(v.x)); \
}
#define VECTORIZE2_VEC(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec2<T, P> func( \
detail::tvec2<T, P> const & v) \
{ \
return detail::tvec2<T, P>( \
func(v.x), \
func(v.y)); \
}
#define VECTORIZE3_VEC(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec3<T, P> func( \
detail::tvec3<T, P> const & v) \
{ \
return detail::tvec3<T, P>( \
func(v.x), \
func(v.y), \
func(v.z)); \
}
#define VECTORIZE4_VEC(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec4<T, P> func( \
detail::tvec4<T, P> const & v) \
{ \
return detail::tvec4<T, P>( \
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 <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec1<T, P> func \
( \
detail::tvec1<T, P> const & x, \
T const & y \
) \
{ \
return detail::tvec1<T, P>( \
func(x.x, y)); \
}
#define VECTORIZE2_VEC_SCA(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec2<T, P> func \
( \
detail::tvec2<T, P> const & x, \
T const & y \
) \
{ \
return detail::tvec2<T, P>( \
func(x.x, y), \
func(x.y, y)); \
}
#define VECTORIZE3_VEC_SCA(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec3<T, P> func \
( \
detail::tvec3<T, P> const & x, \
T const & y \
) \
{ \
return detail::tvec3<T, P>( \
func(x.x, y), \
func(x.y, y), \
func(x.z, y)); \
}
#define VECTORIZE4_VEC_SCA(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec4<T, P> func \
( \
detail::tvec4<T, P> const & x, \
T const & y \
) \
{ \
return detail::tvec4<T, P>( \
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 <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec2<T, P> func \
( \
detail::tvec2<T, P> const & x, \
detail::tvec2<T, P> const & y \
) \
{ \
return detail::tvec2<T, P>( \
func(x.x, y.x), \
func(x.y, y.y)); \
}
#define VECTORIZE3_VEC_VEC(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec3<T, P> func \
( \
detail::tvec3<T, P> const & x, \
detail::tvec3<T, P> const & y \
) \
{ \
return detail::tvec3<T, P>( \
func(x.x, y.x), \
func(x.y, y.y), \
func(x.z, y.z)); \
}
#define VECTORIZE4_VEC_VEC(func) \
template <typename T, precision P> \
GLM_FUNC_QUALIFIER detail::tvec4<T, P> func \
( \
detail::tvec4<T, P> const & x, \
detail::tvec4<T, P> const & y \
) \
{ \
return detail::tvec4<T, P>( \
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 glm{
namespace detail namespace detail
{ {
template<bool C> template <typename R, typename T, precision P, template <typename, precision> class vecType>
struct If struct functor1{};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec1>
{ {
template<typename F, typename T> GLM_FUNC_QUALIFIER static tvec1<R, P> call(R (*Func) (T x), tvec1<T, P> const & v)
static GLM_FUNC_QUALIFIER T apply(F functor, const T& val)
{ {
return functor(val); return tvec1<R, P>(Func(v.x));
} }
}; };
template<> template <typename R, typename T, precision P>
struct If<false> struct functor1<R, T, P, tvec2>
{ {
template<typename F, typename T> GLM_FUNC_QUALIFIER static tvec2<R, P> call(R (*Func) (T x), tvec2<T, P> const & v)
static GLM_FUNC_QUALIFIER T apply(F, const T& val)
{ {
return val; return tvec2<R, P>(Func(v.x), Func(v.y));
}
};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec3>
{
GLM_FUNC_QUALIFIER static tvec3<R, P> call(R (*Func) (T x), tvec3<T, P> const & v)
{
return tvec3<R, P>(Func(v.x), Func(v.y), Func(v.z));
}
};
template <typename R, typename T, precision P>
struct functor1<R, T, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<R, P> call(R (*Func) (T x), tvec4<T, P> const & v)
{
return tvec4<R, P>(Func(v.x), Func(v.y), Func(v.z), Func(v.w));
}
};
template <typename T, precision P, template <typename, precision> class vecType>
struct functor2{};
template <typename T, precision P>
struct functor2<T, P, tvec1>
{
GLM_FUNC_QUALIFIER static tvec1<T, P> call(T (*Func) (T x, T y), tvec1<T, P> const & a, tvec1<T, P> const & b)
{
return tvec1<T, P>(Func(a.x, b.x));
}
};
template <typename T, precision P>
struct functor2<T, P, tvec2>
{
GLM_FUNC_QUALIFIER static tvec2<T, P> call(T (*Func) (T x, T y), tvec2<T, P> const & a, tvec2<T, P> const & b)
{
return tvec2<T, P>(Func(a.x, b.x), Func(a.y, b.y));
}
};
template <typename T, precision P>
struct functor2<T, P, tvec3>
{
GLM_FUNC_QUALIFIER static tvec3<T, P> call(T (*Func) (T x, T y), tvec3<T, P> const & a, tvec3<T, P> const & b)
{
return tvec3<T, P>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z));
}
};
template <typename T, precision P>
struct functor2<T, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<T, P> call(T (*Func) (T x, T y), tvec4<T, P> const & a, tvec4<T, P> const & b)
{
return tvec4<T, P>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w));
}
};
template <typename T, precision P, template <typename, precision> class vecType>
struct functor2_vec_sca{};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec1>
{
GLM_FUNC_QUALIFIER static tvec1<T, P> call(T (*Func) (T x, T y), tvec1<T, P> const & a, T b)
{
return tvec1<T, P>(Func(a.x, b));
}
};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec2>
{
GLM_FUNC_QUALIFIER static tvec2<T, P> call(T (*Func) (T x, T y), tvec2<T, P> const & a, T b)
{
return tvec2<T, P>(Func(a.x, b), Func(a.y, b));
}
};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec3>
{
GLM_FUNC_QUALIFIER static tvec3<T, P> call(T (*Func) (T x, T y), tvec3<T, P> const & a, T b)
{
return tvec3<T, P>(Func(a.x, b), Func(a.y, b), Func(a.z, b));
}
};
template <typename T, precision P>
struct functor2_vec_sca<T, P, tvec4>
{
GLM_FUNC_QUALIFIER static tvec4<T, P> call(T (*Func) (T x, T y), tvec4<T, P> const & a, T b)
{
return tvec4<T, P>(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b));
} }
}; };
}//namespace detail }//namespace detail
}//namespace glm }//namespace glm
#endif//GLM_CORE_DETAIL_INCLUDED

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// 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. /// dummy.cpp exist only a wordaround for CMake file.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#define GLM_FORCE_RADIANS
#define GLM_MESSAGES #define GLM_MESSAGES
#include "../glm.hpp" #include "../glm.hpp"
#include <limits> #include <limits>
@ -42,6 +45,7 @@ struct material
glm::vec4 specular; // Scm glm::vec4 specular; // Scm
float shininess; // Srm float shininess; // Srm
}; };
struct light struct light
{ {
glm::vec4 ambient; // Acli glm::vec4 ambient; // Acli
@ -60,6 +64,7 @@ struct light
float quadraticAttenuation;// K2 float quadraticAttenuation;// K2
}; };
// Sample 1 // Sample 1
#include <glm/vec3.hpp>// glm::vec3 #include <glm/vec3.hpp>// glm::vec3
#include <glm/geometric.hpp>// glm::cross, glm::normalize #include <glm/geometric.hpp>// glm::cross, glm::normalize
@ -184,7 +189,34 @@ glm::vec3 lighting
return Color; return Color;
} }
*/ */
template <typename T, glm::precision P, template<typename, glm::precision> class vecType>
T normalizeDotA(vecType<T, P> const & x, vecType<T, P> 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<typename, glm::precision> class
template <GLM_TEMPLATE_GENTYPE vecType>
T normalizeDotB(vecType<T, P> const & x, vecType<T, P> const & y)
{
return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y));
}
template <typename vecType>
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() int main()
{ {
glm::vec4 v(1);
float a = normalizeDotA(v, v);
float b = normalizeDotB(v, v);
float c = normalizeDotC(v, v);
return 0; return 0;
} }

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_common.hpp /// @file glm/detail/func_common.hpp
/// @date 2008-03-08 / 2010-01-26 /// @date 2008-03-08 / 2010-01-26
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -33,8 +37,7 @@
/// These all operate component-wise. The description is per component. /// These all operate component-wise. The description is per component.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_FUNC_COMMON_INCLUDED #pragma once
#define GLM_FUNC_COMMON_INCLUDED
#include "setup.hpp" #include "setup.hpp"
#include "precision.hpp" #include "precision.hpp"
@ -53,7 +56,10 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType abs(genType const & x); GLM_FUNC_DECL genType abs(genType x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> abs(vecType<T, P> const & x);
/// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0.
/// ///
@ -61,17 +67,17 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sign.xml">GLSL sign man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sign.xml">GLSL sign man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType sign(genType const & x); GLM_FUNC_DECL vecType<T, P> sign(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer that is less then or equal to 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. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floor.xml">GLSL floor man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floor.xml">GLSL floor man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType floor(genType const & x); GLM_FUNC_DECL vecType<T, P> floor(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer to x /// Returns a value equal to the nearest integer to x
/// whose absolute value is not larger than the absolute value of x. /// whose absolute value is not larger than the absolute value of x.
@ -80,8 +86,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/trunc.xml">GLSL trunc man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/trunc.xml">GLSL trunc man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType trunc(genType const & x); GLM_FUNC_DECL vecType<T, P> trunc(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer to x. /// Returns a value equal to the nearest integer to x.
/// The fraction 0.5 will round in a direction chosen by the /// The fraction 0.5 will round in a direction chosen by the
@ -93,9 +99,9 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType round(genType const & x); GLM_FUNC_DECL vecType<T, P> round(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer to x. /// Returns a value equal to the nearest integer to x.
/// A fractional part of 0.5 will round toward the nearest even /// 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.) /// integer. (Both 3.5 and 4.5 for x will return 4.0.)
@ -105,8 +111,8 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/roundEven.xml">GLSL roundEven man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/roundEven.xml">GLSL roundEven man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
/// @see <a href="http://developer.amd.com/documentation/articles/pages/New-Round-to-Even-Technique.aspx">New round to even technique</a> /// @see <a href="http://developer.amd.com/documentation/articles/pages/New-Round-to-Even-Technique.aspx">New round to even technique</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType roundEven(genType const & x); GLM_FUNC_DECL vecType<T, P> roundEven(vecType<T, P> const & x);
/// Returns a value equal to the nearest integer /// Returns a value equal to the nearest integer
/// that is greater than or equal to x. /// that is greater than or equal to x.
@ -115,8 +121,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ceil.xml">GLSL ceil man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ceil.xml">GLSL ceil man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType ceil(genType const & x); GLM_FUNC_DECL vecType<T, P> ceil(vecType<T, P> const & x);
/// Return x - floor(x). /// Return x - floor(x).
/// ///
@ -125,7 +131,10 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fract.xml">GLSL fract man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fract.xml">GLSL fract man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType fract(genType const & x); GLM_FUNC_DECL genType fract(genType x);
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> fract(vecType<T, P> const & x);
/// Modulus. Returns x - y * floor(x / y) /// Modulus. Returns x - y * floor(x / y)
/// for each component in x using the floating point value y. /// for each component in x using the floating point value y.
@ -135,21 +144,13 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType mod( GLM_FUNC_DECL genType mod(genType x, genType y);
genType const & x,
genType const & y);
/// Modulus. Returns x - y * floor(x / y) template <typename T, precision P, template <typename, precision> class vecType>
/// for each component in x using the floating point value y. GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, T y);
///
/// @tparam genType Floating-point scalar or vector types. template <typename T, precision P, template <typename, precision> class vecType>
/// GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y);
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType>
GLM_FUNC_DECL genType mod(
genType const & x,
typename genType::value_type const & y);
/// Returns the fractional part of x and sets i to the integer /// Returns the fractional part of x and sets i to the integer
/// part (as a whole number floating point value). Both the /// part (as a whole number floating point value). Both the
@ -161,25 +162,22 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/modf.xml">GLSL modf man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/modf.xml">GLSL modf man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType modf( GLM_FUNC_DECL genType modf(genType x, genType & i);
genType const & x,
genType & i);
/// Returns y if y < x; otherwise, it returns x. /// Returns y if y < x; otherwise, it returns x.
/// ///
/// @tparam genType Floating-point or integer; scalar or vector types. /// @tparam genType Floating-point or integer; scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a><<<<<<< HEAD /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType min( GLM_FUNC_DECL genType min(genType x, genType y);
genType const & x,
genType const & y);
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType min( GLM_FUNC_DECL vecType<T, P> min(vecType<T, P> const & x, T y);
genType const & x,
typename genType::value_type const & y); template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> min(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns y if x < y; otherwise, it returns x. /// Returns y if x < y; otherwise, it returns x.
/// ///
@ -188,14 +186,13 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType max( GLM_FUNC_DECL genType max(genType x, genType y);
genType const & x,
genType const & y);
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType max( GLM_FUNC_DECL vecType<T, P> max(vecType<T, P> const & x, T y);
genType const & x,
typename genType::value_type const & y); template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> max(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns min(max(x, minVal), maxVal) for each component in x /// Returns min(max(x, minVal), maxVal) for each component in x
/// using the floating-point values minVal and maxVal. /// using the floating-point values minVal and maxVal.
@ -205,16 +202,13 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType clamp( GLM_FUNC_DECL genType clamp(genType x, genType minVal, genType maxVal);
genType const & x,
genType const & minVal,
genType const & maxVal);
template <typename genType, precision P> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType clamp( GLM_FUNC_DECL vecType<T, P> clamp(vecType<T, P> const & x, T minVal, T maxVal);
genType const & x,
typename genType::value_type const & minVal, template <typename T, precision P, template <typename, precision> class vecType>
typename genType::value_type const & maxVal); GLM_FUNC_DECL vecType<T, P> clamp(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal);
/// If genTypeU is a floating scalar or vector: /// If genTypeU is a floating scalar or vector:
/// Returns x * (1.0 - a) + y * a, i.e., the linear blend of /// 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. /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter.
/// @endcode /// @endcode
template <typename T, typename U, precision P, template <typename, precision> class vecType> template <typename T, typename U, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> mix( GLM_FUNC_DECL vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a);
vecType<T, P> const & x,
vecType<T, P> const & y,
vecType<U, P> const & a);
template <typename T, typename U, precision P, template <typename, precision> class vecType> template <typename T, typename U, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> mix( GLM_FUNC_DECL vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, U a);
vecType<T, P> const & x,
vecType<T, P> const & y,
U const & a);
template <typename genTypeT, typename genTypeU> template <typename genTypeT, typename genTypeU>
GLM_FUNC_DECL genTypeT mix( GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a);
genTypeT const & x,
genTypeT const & y,
genTypeU const & a);
/// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType step( GLM_FUNC_DECL genType step(genType edge, genType x);
genType const & edge,
genType const & x);
/// Returns 0.0 if x < edge, otherwise it returns 1.0. /// Returns 0.0 if x < edge, otherwise it returns 1.0.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, typename T, precision P> template <template <typename, precision> class vecType, typename T, precision P>
GLM_FUNC_DECL vecType<T, P> step( GLM_FUNC_DECL vecType<T, P> step(T edge, vecType<T, P> const & x);
T const & edge,
vecType<T, P> const & x); /// Returns 0.0 if x < edge, otherwise it returns 1.0.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <template <typename, precision> class vecType, typename T, precision P>
GLM_FUNC_DECL vecType<T, P> step(vecType<T, P> const & edge, vecType<T, P> const & x);
/// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and /// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and
/// performs smooth Hermite interpolation between 0 and 1 /// performs smooth Hermite interpolation between 0 and 1
@ -309,16 +297,13 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/smoothstep.xml">GLSL smoothstep man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/smoothstep.xml">GLSL smoothstep man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL genType smoothstep( GLM_FUNC_DECL genType smoothstep(genType edge0, genType edge1, genType x);
genType const & edge0,
genType const & edge1,
genType const & x);
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType smoothstep( GLM_FUNC_DECL vecType<T, P> smoothstep(T edge0, T edge1, vecType<T, P> const & x);
typename genType::value_type const & edge0,
typename genType::value_type const & edge1, template <typename T, precision P, template <typename, precision> class vecType>
genType const & x); GLM_FUNC_DECL vecType<T, P> smoothstep(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x);
/// Returns true if x holds a NaN (not a number) /// Returns true if x holds a NaN (not a number)
/// representation in the underlying implementation's set of /// representation in the underlying implementation's set of
@ -332,8 +317,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename genType::bool_type isnan(genType const & x); GLM_FUNC_DECL vecType<bool, P> isnan(vecType<T, P> const & x);
/// Returns true if x holds a positive infinity or negative /// Returns true if x holds a positive infinity or negative
/// infinity representation in the underlying implementation's /// infinity representation in the underlying implementation's
@ -345,8 +330,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isinf.xml">GLSL isinf man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isinf.xml">GLSL isinf man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename genType::bool_type isinf(genType const & x); GLM_FUNC_DECL vecType<bool, P> isinf(vecType<T, P> const & x);
/// Returns a signed integer value representing /// Returns a signed integer value representing
/// the encoding of a floating-point value. The floating-point /// the encoding of a floating-point value. The floating-point
@ -469,4 +454,3 @@ namespace glm
#include "func_common.inl" #include "func_common.inl"
#endif//GLM_FUNC_COMMON_INCLUDED

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_exponential.hpp /// @file glm/detail/func_exponential.hpp
/// @date 2008-08-08 / 2011-06-14 /// @date 2008-08-08 / 2011-06-14
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -33,8 +37,7 @@
/// These all operate component-wise. The description is per component. /// These all operate component-wise. The description is per component.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_func_exponential #pragma once
#define glm_core_func_exponential
#include "type_vec1.hpp" #include "type_vec1.hpp"
#include "type_vec2.hpp" #include "type_vec2.hpp"
@ -49,84 +52,81 @@ namespace glm
/// Returns 'base' raised to the power 'exponent'. /// Returns 'base' raised to the power 'exponent'.
/// ///
/// @param base Floating point value. pow function is defined for input values of x defined in the range (inf-, inf+) in the limit of the type precision. /// @param base Floating point value. pow function is defined for input values of 'base' defined in the range (inf-, inf+) in the limit of the type precision.
/// @param exponent Floating point value representing the 'exponent'. /// @param exponent Floating point value representing the 'exponent'.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/pow.xml">GLSL pow man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/pow.xml">GLSL pow man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType pow(genType const & base, genType const & exponent); GLM_FUNC_DECL vecType<T, P> pow(vecType<T, P> const & base, vecType<T, P> const & exponent);
/// Returns the natural exponentiation of x, i.e., e^x. /// Returns the natural exponentiation of x, i.e., e^x.
/// ///
/// @param x exp function is defined for input values of x defined in the range (inf-, inf+) in the limit of the type precision. /// @param v exp function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp.xml">GLSL exp man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp.xml">GLSL exp man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType exp(genType const & x); GLM_FUNC_DECL vecType<T, P> exp(vecType<T, P> const & v);
/// Returns the natural logarithm of x, i.e., /// Returns the natural logarithm of v, i.e.,
/// returns the value y which satisfies the equation x = e^y. /// returns the value y which satisfies the equation x = e^y.
/// Results are undefined if x <= 0. /// Results are undefined if v <= 0.
/// ///
/// @param x log function is defined for input values of x defined in the range (0, inf+) in the limit of the type precision. /// @param v log function is defined for input values of v defined in the range (0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log.xml">GLSL log man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log.xml">GLSL log man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType log(genType const & x); GLM_FUNC_DECL vecType<T, P> log(vecType<T, P> const & v);
/// Returns 2 raised to the x power. /// Returns 2 raised to the v power.
/// ///
/// @param x exp2 function is defined for input values of x defined in the range (inf-, inf+) in the limit of the type precision. /// @param v exp2 function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp2.xml">GLSL exp2 man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp2.xml">GLSL exp2 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType exp2(genType const & x); GLM_FUNC_DECL vecType<T, P> exp2(vecType<T, P> const & v);
/// Returns the base 2 log of x, i.e., returns the value y, /// Returns the base 2 log of x, i.e., returns the value y,
/// which satisfies the equation x = 2 ^ y. /// which satisfies the equation x = 2 ^ y.
/// ///
/// @param x log2 function is defined for input values of x defined in the range (0, inf+) in the limit of the type precision. /// @param v log2 function is defined for input values of v defined in the range (0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log2.xml">GLSL log2 man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log2.xml">GLSL log2 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType log2(genType x); GLM_FUNC_DECL vecType<T, P> log2(vecType<T, P> const & v);
/// Returns the positive square root of x. /// Returns the positive square root of v.
/// ///
/// @param x sqrt function is defined for input values of x defined in the range [0, inf+) in the limit of the type precision. /// @param v sqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sqrt.xml">GLSL sqrt man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sqrt.xml">GLSL sqrt man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
//template <typename genType> //template <typename genType>
//GLM_FUNC_DECL genType sqrt(genType const & x); //GLM_FUNC_DECL genType sqrt(genType const & x);
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<T, P> sqrt(vecType<T, P> const & x); GLM_FUNC_DECL vecType<T, P> sqrt(vecType<T, P> const & v);
/// Returns the reciprocal of the positive square root of x. /// Returns the reciprocal of the positive square root of v.
/// ///
/// @param x inversesqrt function is defined for input values of x defined in the range [0, inf+) in the limit of the type precision. /// @param v inversesqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type precision.
/// @tparam genType Floating-point scalar or vector types. /// @tparam genType Floating-point scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inversesqrt.xml">GLSL inversesqrt man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inversesqrt.xml">GLSL inversesqrt man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType inversesqrt(genType const & x); GLM_FUNC_DECL vecType<T, P> inversesqrt(vecType<T, P> const & v);
/// @} /// @}
}//namespace glm }//namespace glm
#include "func_exponential.inl" #include "func_exponential.inl"
#endif//glm_core_func_exponential

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_exponential.inl /// @file glm/detail/func_exponential.inl
/// @date 2008-08-03 / 2011-06-15 /// @date 2008-08-03 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -29,25 +33,28 @@
#include "func_vector_relational.hpp" #include "func_vector_relational.hpp"
#include "_vectorize.hpp" #include "_vectorize.hpp"
#include <limits> #include <limits>
#include <cmath>
#include <cassert> #include <cassert>
namespace glm{ namespace glm{
namespace detail namespace detail
{ {
template <bool isFloat> # if GLM_HAS_CXX11_STL
using std::log2;
# else
template <typename genType>
genType log2(genType Value)
{
return std::log(Value) * static_cast<genType>(1.4426950408889634073599246810019);
}
# endif
template <typename T, precision P, template <class, precision> class vecType, bool isFloat = true>
struct compute_log2 struct compute_log2
{ {
template <typename T> GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & vec)
T operator() (T const & Value) const;
};
template <>
struct compute_log2<true>
{
template <typename T>
GLM_FUNC_QUALIFIER T operator() (T const & Value) const
{ {
return static_cast<T>(::std::log(Value)) * static_cast<T>(1.4426950408889634073599246810019); return detail::functor1<T, T, P, vecType>::call(log2, vec);
} }
}; };
@ -78,170 +85,77 @@ namespace detail
}//namespace detail }//namespace detail
// pow // pow
template <typename genType> using std::pow;
GLM_FUNC_QUALIFIER genType pow template <typename T, precision P, template <typename, precision> class vecType>
( GLM_FUNC_QUALIFIER vecType<T, P> pow(vecType<T, P> const & base, vecType<T, P> const & exponent)
genType const & x,
genType const & y
)
{ {
GLM_STATIC_ASSERT( return detail::functor2<T, P, vecType>::call(pow, base, exponent);
std::numeric_limits<genType>::is_iec559,
"'pow' only accept floating-point inputs");
return std::pow(x, y);
} }
VECTORIZE_VEC_VEC(pow)
// exp // exp
template <typename genType> using std::exp;
GLM_FUNC_QUALIFIER genType exp template <typename T, precision P, template <typename, precision> class vecType>
( GLM_FUNC_QUALIFIER vecType<T, P> exp(vecType<T, P> const & x)
genType const & x
)
{ {
GLM_STATIC_ASSERT( return detail::functor1<T, T, P, vecType>::call(exp, x);
std::numeric_limits<genType>::is_iec559,
"'exp' only accept floating-point inputs");
return std::exp(x);
} }
VECTORIZE_VEC(exp)
// log // log
template <typename genType> using std::log;
GLM_FUNC_QUALIFIER genType log template <typename T, precision P, template <typename, precision> class vecType>
( GLM_FUNC_QUALIFIER vecType<T, P> log(vecType<T, P> const & x)
genType const & x
)
{ {
GLM_STATIC_ASSERT( return detail::functor1<T, T, P, vecType>::call(log, x);
std::numeric_limits<genType>::is_iec559,
"'log' only accept floating-point inputs");
return std::log(x);
} }
VECTORIZE_VEC(log)
//exp2, ln2 = 0.69314718055994530941723212145818f //exp2, ln2 = 0.69314718055994530941723212145818f
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType exp2(genType const & x) GLM_FUNC_QUALIFIER genType exp2(genType x)
{ {
GLM_STATIC_ASSERT( GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'exp2' only accept floating-point inputs");
std::numeric_limits<genType>::is_iec559,
"'exp2' only accept floating-point inputs");
return std::exp(static_cast<genType>(0.69314718055994530941723212145818) * x); return std::exp(static_cast<genType>(0.69314718055994530941723212145818) * x);
} }
VECTORIZE_VEC(exp2) template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> exp2(vecType<T, P> const & x)
{
return detail::functor1<T, T, P, vecType>::call(exp2, x);
}
// log2, ln2 = 0.69314718055994530941723212145818f // log2, ln2 = 0.69314718055994530941723212145818f
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType log2(genType x) GLM_FUNC_QUALIFIER genType log2(genType x)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, return log2(tvec1<genType>(x)).x;
"GLM core 'log2' only accept floating-point inputs. Include <glm/gtx/integer.hpp> for additional integer support.");
assert(x > genType(0)); // log2 is only defined on the range (0, inf]
return detail::compute_log2<std::numeric_limits<genType>::is_iec559>()(x);
} }
VECTORIZE_VEC(log2) template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> log2(vecType<T, P> const & x)
namespace detail
{ {
template <template <class, precision> class vecType, typename T, precision P> return detail::compute_log2<T, P, vecType, std::numeric_limits<T>::is_iec559>::call(x);
struct compute_sqrt{}; }
template <typename T, precision P>
struct compute_sqrt<detail::tvec1, T, P>
{
GLM_FUNC_QUALIFIER static detail::tvec1<T, P> call(detail::tvec1<T, P> const & x)
{
return detail::tvec1<T, P>(std::sqrt(x.x));
}
};
template <typename T, precision P>
struct compute_sqrt<detail::tvec2, T, P>
{
GLM_FUNC_QUALIFIER static detail::tvec2<T, P> call(detail::tvec2<T, P> const & x)
{
return detail::tvec2<T, P>(std::sqrt(x.x), std::sqrt(x.y));
}
};
template <typename T, precision P>
struct compute_sqrt<detail::tvec3, T, P>
{
GLM_FUNC_QUALIFIER static detail::tvec3<T, P> call(detail::tvec3<T, P> const & x)
{
return detail::tvec3<T, P>(std::sqrt(x.x), std::sqrt(x.y), std::sqrt(x.z));
}
};
template <typename T, precision P>
struct compute_sqrt<detail::tvec4, T, P>
{
GLM_FUNC_QUALIFIER static detail::tvec4<T, P> call(detail::tvec4<T, P> const & x)
{
return detail::tvec4<T, P>(std::sqrt(x.x), std::sqrt(x.y), std::sqrt(x.z), std::sqrt(x.w));
}
};
}//namespace detail
// sqrt // sqrt
GLM_FUNC_QUALIFIER float sqrt(float x) using std::sqrt;
{
# ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6
detail::tvec1<float, highp> tmp(detail::compute_sqrt<detail::tvec1, float, highp>::call(x));
return tmp.x;
# else
return detail::compute_sqrt<detail::tvec1, float, highp>::call(x).x;
# endif
}
GLM_FUNC_QUALIFIER double sqrt(double x)
{
# ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6
detail::tvec1<double, highp> tmp(detail::compute_sqrt<detail::tvec1, double, highp>::call(x));
return tmp.x;
# else
return detail::compute_sqrt<detail::tvec1, double, highp>::call(x).x;
# endif
}
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> sqrt(vecType<T, P> const & x) GLM_FUNC_QUALIFIER vecType<T, P> sqrt(vecType<T, P> const & x)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sqrt' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sqrt' only accept floating-point inputs");
return detail::compute_sqrt<vecType, T, P>::call(x); return detail::functor1<T, T, P, vecType>::call(sqrt, x);
} }
// inversesqrt // inversesqrt
GLM_FUNC_QUALIFIER float inversesqrt(float const & x) template <typename genType>
GLM_FUNC_QUALIFIER genType inversesqrt(genType x)
{ {
return 1.0f / sqrt(x); return static_cast<genType>(1) / sqrt(x);
} }
GLM_FUNC_QUALIFIER double inversesqrt(double const & x) template <typename T, precision P, template <typename, precision> class vecType>
{ GLM_FUNC_QUALIFIER vecType<T, P> inversesqrt(vecType<T, P> const & x)
return 1.0 / sqrt(x);
}
template <template <class, precision> class vecType, typename T, precision P>
GLM_FUNC_QUALIFIER vecType<T, P> inversesqrt
(
vecType<T, P> const & x
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inversesqrt' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inversesqrt' only accept floating-point inputs");
return detail::compute_inversesqrt<vecType, T, P>::call(x); return detail::compute_inversesqrt<vecType, T, P>::call(x);
} }
VECTORIZE_VEC(inversesqrt)
}//namespace glm }//namespace glm

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_geometric.hpp /// @file glm/detail/func_geometric.hpp
/// @date 2008-08-03 / 2011-06-14 /// @date 2008-08-03 / 2011-06-14
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -33,8 +37,7 @@
/// These operate on vectors as vectors, not component-wise. /// These operate on vectors as vectors, not component-wise.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_func_geometric #pragma once
#define glm_core_func_geometric
#include "type_vec3.hpp" #include "type_vec3.hpp"
@ -49,9 +52,9 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/length.xml">GLSL length man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/length.xml">GLSL length man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename genType::value_type length( GLM_FUNC_DECL T length(
genType const & x); vecType<T, P> const & x);
/// Returns the distance betwwen p0 and p1, i.e., length(p0 - p1). /// Returns the distance betwwen p0 and p1, i.e., length(p0 - p1).
/// ///
@ -59,10 +62,10 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/distance.xml">GLSL distance man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/distance.xml">GLSL distance man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename genType::value_type distance( GLM_FUNC_DECL T distance(
genType const & p0, vecType<T, P> const & p0,
genType const & p1); vecType<T, P> const & p1);
/// Returns the dot product of x and y, i.e., result = x * y. /// Returns the dot product of x and y, i.e., result = x * y.
/// ///
@ -75,17 +78,6 @@ namespace glm
vecType<T, P> const & x, vecType<T, P> const & x,
vecType<T, P> const & y); vecType<T, P> const & y);
/// Returns the dot product of x and y, i.e., result = x * y.
///
/// @tparam genType Floating-point vector types.
///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/dot.xml">GLSL dot man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename genType>
GLM_FUNC_DECL genType dot(
genType const & x,
genType const & y);
/// Returns the cross product of x and y. /// Returns the cross product of x and y.
/// ///
/// @tparam valType Floating-point scalar types. /// @tparam valType Floating-point scalar types.
@ -93,17 +85,18 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cross.xml">GLSL cross man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cross.xml">GLSL cross man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_DECL detail::tvec3<T, P> cross( GLM_FUNC_DECL tvec3<T, P> cross(
detail::tvec3<T, P> const & x, tvec3<T, P> const & x,
detail::tvec3<T, P> const & y); tvec3<T, P> const & y);
/// Returns a vector in the same direction as x but with length of 1. /// Returns a vector in the same direction as x but with length of 1.
/// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefined and generate an error.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/normalize.xml">GLSL normalize man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/normalize.xml">GLSL normalize man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType normalize( GLM_FUNC_DECL vecType<T, P> normalize(
genType const & x); vecType<T, P> const & x);
/// If dot(Nref, I) < 0.0, return N, otherwise, return -N. /// If dot(Nref, I) < 0.0, return N, otherwise, return -N.
/// ///
@ -141,11 +134,9 @@ namespace glm
GLM_FUNC_DECL vecType<T, P> refract( GLM_FUNC_DECL vecType<T, P> refract(
vecType<T, P> const & I, vecType<T, P> const & I,
vecType<T, P> const & N, vecType<T, P> const & N,
T const & eta); T eta);
/// @} /// @}
}//namespace glm }//namespace glm
#include "func_geometric.inl" #include "func_geometric.inl"
#endif//glm_core_func_geometric

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_geometric.inl /// @file glm/detail/func_geometric.inl
/// @date 2008-08-03 / 2011-06-15 /// @date 2008-08-03 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -39,45 +43,40 @@ namespace detail
struct compute_dot{}; struct compute_dot{};
template <typename T, precision P> template <typename T, precision P>
struct compute_dot<detail::tvec1, T, P> struct compute_dot<tvec1, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tvec1<T, P> const & x, detail::tvec1<T, P> const & y) GLM_FUNC_QUALIFIER static T call(tvec1<T, P> const & a, tvec1<T, P> const & b)
{ {
# ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6 return a.x * b.x;
detail::tvec1<T, P> tmp(x * y);
return tmp.x;
# else
return detail::tvec1<T, P>(x * y).x;
# endif
} }
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_dot<detail::tvec2, T, P> struct compute_dot<tvec2, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tvec2<T, P> const & x, detail::tvec2<T, P> const & y) GLM_FUNC_QUALIFIER static T call(tvec2<T, P> const & x, tvec2<T, P> const & y)
{ {
detail::tvec2<T, P> tmp(x * y); tvec2<T, P> tmp(x * y);
return tmp.x + tmp.y; return tmp.x + tmp.y;
} }
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_dot<detail::tvec3, T, P> struct compute_dot<tvec3, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tvec3<T, P> const & x, detail::tvec3<T, P> const & y) GLM_FUNC_QUALIFIER static T call(tvec3<T, P> const & x, tvec3<T, P> const & y)
{ {
detail::tvec3<T, P> tmp(x * y); tvec3<T, P> tmp(x * y);
return tmp.x + tmp.y + tmp.z; return tmp.x + tmp.y + tmp.z;
} }
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_dot<detail::tvec4, T, P> struct compute_dot<tvec4, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tvec4<T, P> const & x, detail::tvec4<T, P> const & y) GLM_FUNC_QUALIFIER static T call(tvec4<T, P> const & x, tvec4<T, P> const & y)
{ {
detail::tvec4<T, P> tmp(x * y); tvec4<T, P> tmp(x * y);
return (tmp.x + tmp.y) + (tmp.z + tmp.w); return (tmp.x + tmp.y) + (tmp.z + tmp.w);
} }
}; };
@ -85,144 +84,58 @@ namespace detail
// length // length
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType length GLM_FUNC_QUALIFIER genType length(genType x)
(
genType const & x
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' only accept floating-point inputs");
genType sqr = x * x; return abs(x);
return sqrt(sqr);
} }
template <typename T, precision P> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER T length(detail::tvec2<T, P> const & v) GLM_FUNC_QUALIFIER T length(vecType<T, P> const & v)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs");
T sqr = v.x * v.x + v.y * v.y; return sqrt(dot(v, v));
return sqrt(sqr);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER T length(detail::tvec3<T, P> const & v)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs");
T sqr = v.x * v.x + v.y * v.y + v.z * v.z;
return sqrt(sqr);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER T length(detail::tvec4<T, P> const & v)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs");
T sqr = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
return sqrt(sqr);
} }
// distance // distance
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType distance GLM_FUNC_QUALIFIER genType distance(genType const & p0, genType const & p1)
(
genType const & p0,
genType const & p1
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' only accept floating-point inputs");
return length(p1 - p0); return length(p1 - p0);
} }
template <typename T, precision P> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER T distance GLM_FUNC_QUALIFIER T distance(vecType<T, P> const & p0, vecType<T, P> const & p1)
(
detail::tvec2<T, P> const & p0,
detail::tvec2<T, P> const & p1
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs");
return length(p1 - p0);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER T distance
(
detail::tvec3<T, P> const & p0,
detail::tvec3<T, P> const & p1
)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs");
return length(p1 - p0);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER T distance
(
detail::tvec4<T, P> const & p0,
detail::tvec4<T, P> const & p1
)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs");
return length(p1 - p0); return length(p1 - p0);
} }
// dot // dot
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER T dot GLM_FUNC_QUALIFIER T dot(T x, T y)
(
T const & x,
T const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs");
return detail::compute_dot<detail::tvec1, T, highp>::call(x, y); return x * y;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER T dot GLM_FUNC_QUALIFIER T dot(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs");
return detail::compute_dot<vecType, T, P>::call(x, y); return detail::compute_dot<vecType, T, P>::call(x, y);
} }
/* // SSE3
GLM_FUNC_QUALIFIER float dot(const tvec4<float>& x, const tvec4<float>& y)
{
float Result;
__asm
{
mov esi, x
mov edi, y
movaps xmm0, [esi]
mulps xmm0, [edi]
haddps( _xmm0, _xmm0 )
haddps( _xmm0, _xmm0 )
movss Result, xmm0
}
return Result;
}
*/
// cross // cross
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> cross GLM_FUNC_QUALIFIER tvec3<T, P> cross(tvec3<T, P> const & x, tvec3<T, P> const & y)
(
detail::tvec3<T, P> const & x,
detail::tvec3<T, P> const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' only accept floating-point inputs");
return detail::tvec3<T, P>( return tvec3<T, P>(
x.y * y.z - y.y * x.z, x.y * y.z - y.y * x.z,
x.z * y.x - y.z * x.x, x.z * y.x - y.z * x.x,
x.x * y.y - y.x * x.y); x.x * y.y - y.x * x.y);
@ -230,111 +143,53 @@ namespace detail
// normalize // normalize
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType normalize GLM_FUNC_QUALIFIER genType normalize(genType const & x)
(
genType const & x
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' only accept floating-point inputs");
return x < genType(0) ? genType(-1) : genType(1); return x < genType(0) ? genType(-1) : genType(1);
} }
// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefine and generate an error template <typename T, precision P, template <typename, precision> class vecType>
template <typename T, precision P> GLM_FUNC_QUALIFIER vecType<T, P> normalize(vecType<T, P> const & x)
GLM_FUNC_QUALIFIER detail::tvec2<T, P> normalize
(
detail::tvec2<T, P> const & x
)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs");
T sqr = x.x * x.x + x.y * x.y;
return x * inversesqrt(sqr);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> normalize
(
detail::tvec3<T, P> const & x
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs");
T sqr = x.x * x.x + x.y * x.y + x.z * x.z; return x * inversesqrt(dot(x, x));
return x * inversesqrt(sqr);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> normalize
(
detail::tvec4<T, P> const & x
)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs");
T sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w;
return x * inversesqrt(sqr);
} }
// faceforward // faceforward
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType faceforward GLM_FUNC_QUALIFIER genType faceforward(genType const & N, genType const & I, genType const & Nref)
(
genType const & N,
genType const & I,
genType const & Nref
)
{ {
return dot(Nref, I) < 0 ? N : -N; return dot(Nref, I) < static_cast<genType>(0) ? N : -N;
} }
// reflect // reflect
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType reflect GLM_FUNC_QUALIFIER genType reflect(genType const & I, genType const & N)
(
genType const & I,
genType const & N
)
{ {
return I - N * dot(N, I) * genType(2); return I - N * dot(N, I) * static_cast<genType>(2);
} }
// refract // refract
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType refract GLM_FUNC_QUALIFIER genType refract(genType const & I, genType const & N, genType const & eta)
(
genType const & I,
genType const & N,
genType const & eta
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' only accept floating-point inputs");
genType dotValue = dot(N, I); genType const dotValue(dot(N, I));
genType k = genType(1) - eta * eta * (genType(1) - dotValue * dotValue); genType const k(static_cast<genType>(1) - eta * eta * (static_cast<genType>(1) - dotValue * dotValue));
if(k < genType(0)) return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast<genType>(k >= static_cast<genType>(0));
return genType(0);
else
return eta * I - (eta * dotValue + sqrt(k)) * N;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> refract GLM_FUNC_QUALIFIER vecType<T, P> refract(vecType<T, P> const & I, vecType<T, P> const & N, T eta)
(
vecType<T, P> const & I,
vecType<T, P> const & N,
T const & eta
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' only accept floating-point inputs");
T dotValue = dot(N, I); T const dotValue(dot(N, I));
T k = T(1) - eta * eta * (T(1) - dotValue * dotValue); T const k(static_cast<T>(1) - eta * eta * (static_cast<T>(1) - dotValue * dotValue));
if(k < T(0)) return (eta * I - (eta * dotValue + std::sqrt(k)) * N) * static_cast<T>(k >= static_cast<T>(0));
return vecType<T, P>(0);
else
return eta * I - (eta * dotValue + std::sqrt(k)) * N;
} }
}//namespace glm }//namespace glm

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_integer.hpp /// @file glm/detail/func_integer.hpp
/// @date 2010-03-17 / 2011-06-18 /// @date 2010-03-17 / 2011-06-18
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -35,10 +39,12 @@
/// b, inclusive. The lowest-order bit is bit 0. /// b, inclusive. The lowest-order bit is bit 0.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_func_integer #pragma once
#define glm_core_func_integer
#include "setup.hpp" #include "setup.hpp"
#include "precision.hpp"
#include "func_common.hpp"
#include "func_vector_relational.hpp"
namespace glm namespace glm
{ {
@ -53,11 +59,11 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uaddCarry.xml">GLSL uaddCarry man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uaddCarry.xml">GLSL uaddCarry man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genUType> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genUType uaddCarry( GLM_FUNC_DECL vecType<uint, P> uaddCarry(
genUType const & x, vecType<uint, P> const & x,
genUType const & y, vecType<uint, P> const & y,
genUType & carry); vecType<uint, P> & carry);
/// Subtracts the 32-bit unsigned integer y from x, returning /// Subtracts the 32-bit unsigned integer y from x, returning
/// the difference if non-negative, or pow(2, 32) plus the difference /// the difference if non-negative, or pow(2, 32) plus the difference
@ -67,12 +73,12 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/usubBorrow.xml">GLSL usubBorrow man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/usubBorrow.xml">GLSL usubBorrow man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genUType> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genUType usubBorrow( GLM_FUNC_DECL vecType<uint, P> usubBorrow(
genUType const & x, vecType<uint, P> const & x,
genUType const & y, vecType<uint, P> const & y,
genUType & borrow); vecType<uint, P> & borrow);
/// Multiplies 32-bit integers x and y, producing a 64-bit /// Multiplies 32-bit integers x and y, producing a 64-bit
/// result. The 32 least-significant bits are returned in lsb. /// result. The 32 least-significant bits are returned in lsb.
/// The 32 most-significant bits are returned in msb. /// The 32 most-significant bits are returned in msb.
@ -81,12 +87,12 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/umulExtended.xml">GLSL umulExtended man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/umulExtended.xml">GLSL umulExtended man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genUType> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL void umulExtended( GLM_FUNC_DECL void umulExtended(
genUType const & x, vecType<uint, P> const & x,
genUType const & y, vecType<uint, P> const & y,
genUType & msb, vecType<uint, P> & msb,
genUType & lsb); vecType<uint, P> & lsb);
/// Multiplies 32-bit integers x and y, producing a 64-bit /// Multiplies 32-bit integers x and y, producing a 64-bit
/// result. The 32 least-significant bits are returned in lsb. /// result. The 32 least-significant bits are returned in lsb.
@ -96,12 +102,12 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/imulExtended.xml">GLSL imulExtended man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/imulExtended.xml">GLSL imulExtended man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIType> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL void imulExtended( GLM_FUNC_DECL void imulExtended(
genIType const & x, vecType<int, P> const & x,
genIType const & y, vecType<int, P> const & y,
genIType & msb, vecType<int, P> & msb,
genIType & lsb); vecType<int, P> & lsb);
/// Extracts bits [offset, offset + bits - 1] from value, /// Extracts bits [offset, offset + bits - 1] from value,
/// returning them in the least significant bits of the result. /// returning them in the least significant bits of the result.
@ -114,15 +120,15 @@ namespace glm
/// offset and bits is greater than the number of bits used /// offset and bits is greater than the number of bits used
/// to store the operand. /// to store the operand.
/// ///
/// @tparam genIUType Signed or unsigned integer scalar or vector types. /// @tparam T Signed or unsigned integer scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldExtract.xml">GLSL bitfieldExtract man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldExtract.xml">GLSL bitfieldExtract man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genIUType bitfieldExtract( GLM_FUNC_DECL vecType<T, P> bitfieldExtract(
genIUType const & Value, vecType<T, P> const & Value,
int const & Offset, int Offset,
int const & Bits); int Bits);
/// Returns the insertion the bits least-significant bits of insert into base. /// Returns the insertion the bits least-significant bits of insert into base.
/// ///
@ -134,70 +140,93 @@ namespace glm
/// offset and bits is greater than the number of bits used to /// offset and bits is greater than the number of bits used to
/// store the operand. /// store the operand.
/// ///
/// @tparam genIUType Signed or unsigned integer scalar or vector types. /// @tparam T Signed or unsigned integer scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldInsert.xml">GLSL bitfieldInsert man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldInsert.xml">GLSL bitfieldInsert man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genIUType bitfieldInsert( GLM_FUNC_DECL vecType<T, P> bitfieldInsert(
genIUType const & Base, vecType<T, P> const & Base,
genIUType const & Insert, vecType<T, P> const & Insert,
int const & Offset, int Offset,
int const & Bits); int Bits);
/// Returns the reversal of the bits of value. /// Returns the reversal of the bits of value.
/// The bit numbered n of the result will be taken from bit (bits - 1) - n of value, /// The bit numbered n of the result will be taken from bit (bits - 1) - n of value,
/// where bits is the total number of bits used to represent value. /// where bits is the total number of bits used to represent value.
/// ///
/// @tparam genIUType Signed or unsigned integer scalar or vector types. /// @tparam T Signed or unsigned integer scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldReverse.xml">GLSL bitfieldReverse man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldReverse.xml">GLSL bitfieldReverse man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genIUType bitfieldReverse(genIUType const & Value); GLM_FUNC_DECL vecType<T, P> bitfieldReverse(vecType<T, P> const & v);
/// Returns the number of bits set to 1 in the binary representation of value. /// Returns the number of bits set to 1 in the binary representation of value.
/// ///
/// @tparam genIUType Signed or unsigned integer scalar or vector types. /// @tparam T Signed or unsigned integer scalar or vector types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genType>
GLM_FUNC_DECL int bitCount(genType v);
/// Returns the number of bits set to 1 in the binary representation of value.
/// ///
/// @todo Clarify the declaration to specify that scalars are suported. /// @tparam T Signed or unsigned integer scalar or vector types.
template <typename T, template <typename> class genIUType> ///
GLM_FUNC_DECL typename genIUType<T>::signed_type bitCount(genIUType<T> const & Value); /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<int, P> bitCount(vecType<T, P> const & v);
/// Returns the bit number of the least significant bit set to /// Returns the bit number of the least significant bit set to
/// 1 in the binary representation of value. /// 1 in the binary representation of value.
/// If value is zero, -1 will be returned. /// If value is zero, -1 will be returned.
/// ///
/// @tparam genIUType Signed or unsigned integer scalar or vector types. /// @tparam T Signed or unsigned integer scalar types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType>
GLM_FUNC_DECL int findLSB(genIUType x);
/// Returns the bit number of the least significant bit set to
/// 1 in the binary representation of value.
/// If value is zero, -1 will be returned.
/// ///
/// @todo Clarify the declaration to specify that scalars are suported. /// @tparam T Signed or unsigned integer scalar types.
template <typename T, template <typename> class genIUType> ///
GLM_FUNC_DECL typename genIUType<T>::signed_type findLSB(genIUType<T> const & Value); /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<int, P> findLSB(vecType<T, P> const & v);
/// Returns the bit number of the most significant bit in the binary representation of value. /// Returns the bit number of the most significant bit in the binary representation of value.
/// For positive integers, the result will be the bit number of the most significant bit set to 1. /// For positive integers, the result will be the bit number of the most significant bit set to 1.
/// For negative integers, the result will be the bit number of the most significant /// For negative integers, the result will be the bit number of the most significant
/// bit set to 0. For a value of zero or negative one, -1 will be returned. /// bit set to 0. For a value of zero or negative one, -1 will be returned.
/// ///
/// @tparam genIUType Signed or unsigned integer scalar or vector types. /// @tparam T Signed or unsigned integer scalar types.
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename genIUType>
GLM_FUNC_DECL int findMSB(genIUType x);
/// Returns the bit number of the most significant bit in the binary representation of value.
/// For positive integers, the result will be the bit number of the most significant bit set to 1.
/// For negative integers, the result will be the bit number of the most significant
/// bit set to 0. For a value of zero or negative one, -1 will be returned.
/// ///
/// @todo Clarify the declaration to specify that scalars are suported. /// @tparam T Signed or unsigned integer scalar types.
template <typename T, template <typename> class genIUType> ///
GLM_FUNC_DECL typename genIUType<T>::signed_type findMSB(genIUType<T> const & Value); /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a>
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL vecType<int, P> findMSB(vecType<T, P> const & v);
/// @} /// @}
}//namespace glm }//namespace glm
#include "func_integer.inl" #include "func_integer.inl"
#endif//glm_core_func_integer

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_integer.inl /// @file glm/detail/func_integer.inl
/// @date 2010-03-17 / 2011-06-15 /// @date 2010-03-17 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -39,73 +43,186 @@
#endif//(GLM_ARCH != GLM_ARCH_PURE) #endif//(GLM_ARCH != GLM_ARCH_PURE)
#include <limits> #include <limits>
namespace glm namespace glm{
namespace detail
{ {
template <typename T>
GLM_FUNC_QUALIFIER T mask(T Bits)
{
return Bits >= sizeof(T) * 8 ? ~static_cast<T>(0) : (static_cast<T>(1) << Bits) - static_cast<T>(1);
}
template <bool EXEC = false>
struct compute_bitfieldReverseStep
{
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T, T)
{
return v;
}
};
template <>
struct compute_bitfieldReverseStep<true>
{
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Mask, T Shift)
{
return (v & Mask) << Shift | (v & (~Mask)) >> Shift;
}
};
template <bool EXEC = false>
struct compute_bitfieldBitCountStep
{
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T, T)
{
return v;
}
};
template <>
struct compute_bitfieldBitCountStep<true>
{
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Mask, T Shift)
{
return (v & Mask) + ((v >> Shift) & Mask);
}
};
template <typename genIUType, size_t Bits>
struct compute_findLSB
{
GLM_FUNC_QUALIFIER static int call(genIUType Value)
{
if(Value == 0)
return -1;
return glm::bitCount(~Value & (Value - static_cast<genIUType>(1)));
}
};
# if GLM_HAS_BITSCAN_WINDOWS
template <typename genIUType>
struct compute_findLSB<genIUType, 32>
{
GLM_FUNC_QUALIFIER static int call(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanForward(&Result, *reinterpret_cast<unsigned long*>(&Value));
return IsNotNull ? int(Result) : -1;
}
};
# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32))
template <typename genIUType>
struct compute_findLSB<genIUType, 64>
{
GLM_FUNC_QUALIFIER static int call(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanForward64(&Result, *reinterpret_cast<unsigned __int64*>(&Value));
return IsNotNull ? int(Result) : -1;
}
};
# endif
# endif//GLM_HAS_BITSCAN_WINDOWS
template <typename T, glm::precision P, template <class, glm::precision> class vecType, bool EXEC = true>
struct compute_findMSB_step_vec
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, T Shift)
{
return x | (x >> Shift);
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType>
struct compute_findMSB_step_vec<T, P, vecType, false>
{
GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, T)
{
return x;
}
};
template <typename T, glm::precision P, template <typename, glm::precision> class vecType, int>
struct compute_findMSB_vec
{
GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & vec)
{
vecType<T, P> x(vec);
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 1));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 2));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 4));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 16>::call(x, static_cast<T>( 8));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 32>::call(x, static_cast<T>(16));
x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 64>::call(x, static_cast<T>(32));
return vecType<int, P>(sizeof(T) * 8 - 1) - glm::bitCount(~x);
}
};
# if GLM_HAS_BITSCAN_WINDOWS
template <typename genIUType>
GLM_FUNC_QUALIFIER int compute_findMSB_32(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanReverse(&Result, *reinterpret_cast<unsigned long*>(&Value));
return IsNotNull ? int(Result) : -1;
}
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
struct compute_findMSB_vec<T, P, vecType, 32>
{
GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & x)
{
return detail::functor1<int, T, P, vecType>::call(compute_findMSB_32, x);
}
};
# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32))
template <typename genIUType>
GLM_FUNC_QUALIFIER int compute_findMSB_64(genIUType Value)
{
unsigned long Result(0);
unsigned char IsNotNull = _BitScanReverse64(&Result, *reinterpret_cast<unsigned __int64*>(&Value));
return IsNotNull ? int(Result) : -1;
}
template <typename T, glm::precision P, template <class, glm::precision> class vecType>
struct compute_findMSB_vec<T, P, vecType, 64>
{
GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & x)
{
return detail::functor1<int, T, P, vecType>::call(compute_findMSB_64, x);
}
};
# endif
# endif//GLM_HAS_BITSCAN_WINDOWS
}//namespace detail
// uaddCarry // uaddCarry
template <> GLM_FUNC_QUALIFIER uint uaddCarry(uint const & x, uint const & y, uint & Carry)
GLM_FUNC_QUALIFIER uint uaddCarry
(
uint const & x,
uint const & y,
uint & Carry
)
{ {
uint64 Value64 = static_cast<uint64>(x) + static_cast<uint64>(y); uint64 const Value64(static_cast<uint64>(x) + static_cast<uint64>(y));
uint32 Result = static_cast<uint32>(Value64 % (static_cast<uint64>(1) << static_cast<uint64>(32))); uint64 const Max32((static_cast<uint64>(1) << static_cast<uint64>(32)) - static_cast<uint64>(1));
Carry = (Value64 % (static_cast<uint64>(1) << static_cast<uint64>(32))) > 1 ? static_cast<uint32>(1) : static_cast<uint32>(0); Carry = Value64 > Max32 ? 1 : 0;
return Result; return static_cast<uint32>(Value64 % (Max32 + static_cast<uint64>(1)));
} }
template <> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER uvec2 uaddCarry GLM_FUNC_QUALIFIER vecType<uint, P> uaddCarry(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & Carry)
(
uvec2 const & x,
uvec2 const & y,
uvec2 & Carry
)
{ {
return uvec2( vecType<uint64, P> Value64(vecType<uint64, P>(x) + vecType<uint64, P>(y));
uaddCarry(x[0], y[0], Carry[0]), vecType<uint64, P> Max32((static_cast<uint64>(1) << static_cast<uint64>(32)) - static_cast<uint64>(1));
uaddCarry(x[1], y[1], Carry[1])); Carry = mix(vecType<uint32, P>(0), vecType<uint32, P>(1), greaterThan(Value64, Max32));
} return vecType<uint32,P>(Value64 % (Max32 + static_cast<uint64>(1)));
template <>
GLM_FUNC_QUALIFIER uvec3 uaddCarry
(
uvec3 const & x,
uvec3 const & y,
uvec3 & Carry
)
{
return uvec3(
uaddCarry(x[0], y[0], Carry[0]),
uaddCarry(x[1], y[1], Carry[1]),
uaddCarry(x[2], y[2], Carry[2]));
}
template <>
GLM_FUNC_QUALIFIER uvec4 uaddCarry
(
uvec4 const & x,
uvec4 const & y,
uvec4 & Carry
)
{
return uvec4(
uaddCarry(x[0], y[0], Carry[0]),
uaddCarry(x[1], y[1], Carry[1]),
uaddCarry(x[2], y[2], Carry[2]),
uaddCarry(x[3], y[3], Carry[3]));
} }
// usubBorrow // usubBorrow
template <> GLM_FUNC_QUALIFIER uint usubBorrow(uint const & x, uint const & y, uint & Borrow)
GLM_FUNC_QUALIFIER uint usubBorrow
(
uint const & x,
uint const & y,
uint & Borrow
)
{ {
GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch"); GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
@ -116,57 +233,17 @@ namespace glm
return static_cast<uint32>((static_cast<int64>(1) << static_cast<int64>(32)) + (static_cast<int64>(y) - static_cast<int64>(x))); return static_cast<uint32>((static_cast<int64>(1) << static_cast<int64>(32)) + (static_cast<int64>(y) - static_cast<int64>(x)));
} }
template <> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER uvec2 usubBorrow GLM_FUNC_QUALIFIER vecType<uint, P> usubBorrow(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & Borrow)
(
uvec2 const & x,
uvec2 const & y,
uvec2 & Borrow
)
{ {
return uvec2( Borrow = mix(vecType<uint, P>(1), vecType<uint, P>(0), greaterThanEqual(x, y));
usubBorrow(x[0], y[0], Borrow[0]), vecType<uint, P> const YgeX(y - x);
usubBorrow(x[1], y[1], Borrow[1])); vecType<uint, P> const XgeY(vecType<uint32, P>((static_cast<int64>(1) << static_cast<int64>(32)) + (vecType<int64, P>(y) - vecType<int64, P>(x))));
} return mix(XgeY, YgeX, greaterThanEqual(y, x));
template <>
GLM_FUNC_QUALIFIER uvec3 usubBorrow
(
uvec3 const & x,
uvec3 const & y,
uvec3 & Borrow
)
{
return uvec3(
usubBorrow(x[0], y[0], Borrow[0]),
usubBorrow(x[1], y[1], Borrow[1]),
usubBorrow(x[2], y[2], Borrow[2]));
}
template <>
GLM_FUNC_QUALIFIER uvec4 usubBorrow
(
uvec4 const & x,
uvec4 const & y,
uvec4 & Borrow
)
{
return uvec4(
usubBorrow(x[0], y[0], Borrow[0]),
usubBorrow(x[1], y[1], Borrow[1]),
usubBorrow(x[2], y[2], Borrow[2]),
usubBorrow(x[3], y[3], Borrow[3]));
} }
// umulExtended // umulExtended
template <> GLM_FUNC_QUALIFIER void umulExtended(uint const & x, uint const & y, uint & msb, uint & lsb)
GLM_FUNC_QUALIFIER void umulExtended
(
uint const & x,
uint const & y,
uint & msb,
uint & lsb
)
{ {
GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch"); GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
@ -177,57 +254,18 @@ namespace glm
lsb = *PointerLSB; lsb = *PointerLSB;
} }
template <> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER void umulExtended GLM_FUNC_QUALIFIER void umulExtended(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & msb, vecType<uint, P> & lsb)
(
uvec2 const & x,
uvec2 const & y,
uvec2 & msb,
uvec2 & lsb
)
{ {
umulExtended(x[0], y[0], msb[0], lsb[0]); GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch");
umulExtended(x[1], y[1], msb[1], lsb[1]);
}
template <> vecType<uint64, P> Value64(vecType<uint64, P>(x) * vecType<uint64, P>(y));
GLM_FUNC_QUALIFIER void umulExtended msb = vecType<uint32, P>(Value64 >> static_cast<uint64>(32));
( lsb = vecType<uint32, P>(Value64);
uvec3 const & x,
uvec3 const & y,
uvec3 & msb,
uvec3 & lsb
)
{
umulExtended(x[0], y[0], msb[0], lsb[0]);
umulExtended(x[1], y[1], msb[1], lsb[1]);
umulExtended(x[2], y[2], msb[2], lsb[2]);
}
template <>
GLM_FUNC_QUALIFIER void umulExtended
(
uvec4 const & x,
uvec4 const & y,
uvec4 & msb,
uvec4 & lsb
)
{
umulExtended(x[0], y[0], msb[0], lsb[0]);
umulExtended(x[1], y[1], msb[1], lsb[1]);
umulExtended(x[2], y[2], msb[2], lsb[2]);
umulExtended(x[3], y[3], msb[3], lsb[3]);
} }
// imulExtended // imulExtended
template <> GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int & msb, int & lsb)
GLM_FUNC_QUALIFIER void imulExtended
(
int const & x,
int const & y,
int & msb,
int & lsb
)
{ {
GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch"); GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
@ -238,417 +276,118 @@ namespace glm
lsb = *PointerLSB; lsb = *PointerLSB;
} }
template <> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER void imulExtended GLM_FUNC_QUALIFIER void imulExtended(vecType<int, P> const & x, vecType<int, P> const & y, vecType<int, P> & msb, vecType<int, P> & lsb)
(
ivec2 const & x,
ivec2 const & y,
ivec2 & msb,
ivec2 & lsb
)
{ {
imulExtended(x[0], y[0], msb[0], lsb[0]), GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch");
imulExtended(x[1], y[1], msb[1], lsb[1]);
}
template <> vecType<int64, P> Value64(vecType<int64, P>(x) * vecType<int64, P>(y));
GLM_FUNC_QUALIFIER void imulExtended lsb = vecType<int32, P>(Value64 & static_cast<int64>(0xFFFFFFFF));
( msb = vecType<int32, P>((Value64 >> static_cast<int64>(32)) & static_cast<int64>(0xFFFFFFFF));
ivec3 const & x,
ivec3 const & y,
ivec3 & msb,
ivec3 & lsb
)
{
imulExtended(x[0], y[0], msb[0], lsb[0]),
imulExtended(x[1], y[1], msb[1], lsb[1]);
imulExtended(x[2], y[2], msb[2], lsb[2]);
}
template <>
GLM_FUNC_QUALIFIER void imulExtended
(
ivec4 const & x,
ivec4 const & y,
ivec4 & msb,
ivec4 & lsb
)
{
imulExtended(x[0], y[0], msb[0], lsb[0]),
imulExtended(x[1], y[1], msb[1], lsb[1]);
imulExtended(x[2], y[2], msb[2], lsb[2]);
imulExtended(x[3], y[3], msb[3], lsb[3]);
} }
// bitfieldExtract // bitfieldExtract
template <typename genIUType> template <typename genIUType>
GLM_FUNC_QUALIFIER genIUType bitfieldExtract GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits)
(
genIUType const & Value,
int const & Offset,
int const & Bits
)
{ {
int GenSize = int(sizeof(genIUType)) << int(3); return bitfieldExtract(tvec1<genIUType>(Value), Offset, Bits).x;
assert(Offset + Bits <= GenSize);
genIUType ShiftLeft = Bits ? Value << (GenSize - (Bits + Offset)) : genIUType(0);
genIUType ShiftBack = ShiftLeft >> genIUType(GenSize - Bits);
return ShiftBack;
} }
template <typename T, precision P> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> bitfieldExtract GLM_FUNC_QUALIFIER vecType<T, P> bitfieldExtract(vecType<T, P> const & Value, int Offset, int Bits)
(
detail::tvec2<T, P> const & Value,
int const & Offset,
int const & Bits
)
{ {
return detail::tvec2<T, P>( GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldExtract' only accept integer inputs");
bitfieldExtract(Value[0], Offset, Bits),
bitfieldExtract(Value[1], Offset, Bits));
}
template <typename T, precision P> return (Value >> static_cast<T>(Offset)) & static_cast<T>(detail::mask(Bits));
GLM_FUNC_QUALIFIER detail::tvec3<T, P> bitfieldExtract
(
detail::tvec3<T, P> const & Value,
int const & Offset,
int const & Bits
)
{
return detail::tvec3<T, P>(
bitfieldExtract(Value[0], Offset, Bits),
bitfieldExtract(Value[1], Offset, Bits),
bitfieldExtract(Value[2], Offset, Bits));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> bitfieldExtract
(
detail::tvec4<T, P> const & Value,
int const & Offset,
int const & Bits
)
{
return detail::tvec4<T, P>(
bitfieldExtract(Value[0], Offset, Bits),
bitfieldExtract(Value[1], Offset, Bits),
bitfieldExtract(Value[2], Offset, Bits),
bitfieldExtract(Value[3], Offset, Bits));
} }
// bitfieldInsert // bitfieldInsert
template <typename genIUType> template <typename genIUType>
GLM_FUNC_QUALIFIER genIUType bitfieldInsert GLM_FUNC_QUALIFIER genIUType bitfieldInsert(genIUType const & Base, genIUType const & Insert, int Offset, int Bits)
(
genIUType const & Base,
genIUType const & Insert,
int const & Offset,
int const & Bits
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitfieldInsert' only accept integer values"); return bitfieldInsert(tvec1<genIUType>(Base), tvec1<genIUType>(Insert), Offset, Bits).x;
assert(Offset + Bits <= sizeof(genIUType)); }
if(Bits == 0) template <typename T, precision P, template <typename, precision> class vecType>
return Base; GLM_FUNC_QUALIFIER vecType<T, P> bitfieldInsert(vecType<T, P> const & Base, vecType<T, P> const & Insert, int Offset, int Bits)
{
genIUType Mask = 0; GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldInsert' only accept integer values");
for(int Bit = Offset; Bit < Offset + Bits; ++Bit)
Mask |= (1 << Bit);
T const Mask = static_cast<T>(detail::mask(Bits) << Offset);
return (Base & ~Mask) | (Insert & Mask); return (Base & ~Mask) | (Insert & Mask);
} }
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> bitfieldInsert
(
detail::tvec2<T, P> const & Base,
detail::tvec2<T, P> const & Insert,
int const & Offset,
int const & Bits
)
{
return detail::tvec2<T, P>(
bitfieldInsert(Base[0], Insert[0], Offset, Bits),
bitfieldInsert(Base[1], Insert[1], Offset, Bits));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> bitfieldInsert
(
detail::tvec3<T, P> const & Base,
detail::tvec3<T, P> const & Insert,
int const & Offset,
int const & Bits
)
{
return detail::tvec3<T, P>(
bitfieldInsert(Base[0], Insert[0], Offset, Bits),
bitfieldInsert(Base[1], Insert[1], Offset, Bits),
bitfieldInsert(Base[2], Insert[2], Offset, Bits));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> bitfieldInsert
(
detail::tvec4<T, P> const & Base,
detail::tvec4<T, P> const & Insert,
int const & Offset,
int const & Bits
)
{
return detail::tvec4<T, P>(
bitfieldInsert(Base[0], Insert[0], Offset, Bits),
bitfieldInsert(Base[1], Insert[1], Offset, Bits),
bitfieldInsert(Base[2], Insert[2], Offset, Bits),
bitfieldInsert(Base[3], Insert[3], Offset, Bits));
}
// bitfieldReverse // bitfieldReverse
template <typename genIUType> template <typename genType>
GLM_FUNC_QUALIFIER genIUType bitfieldReverse(genIUType const & Value) GLM_FUNC_QUALIFIER genType bitfieldReverse(genType x)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitfieldReverse' only accept integer values"); return bitfieldReverse(glm::tvec1<genType, glm::defaultp>(x)).x;
}
genIUType Out = 0; template <typename T, glm::precision P, template <typename, glm::precision> class vecType>
std::size_t BitSize = sizeof(genIUType) * 8; GLM_FUNC_QUALIFIER vecType<T, P> bitfieldReverse(vecType<T, P> const & v)
for(std::size_t i = 0; i < BitSize; ++i) {
if(Value & (genIUType(1) << i)) vecType<T, P> x(v);
Out |= genIUType(1) << (BitSize - 1 - i); x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 2>::call(x, T(0x5555555555555555ull), static_cast<T>( 1));
return Out; x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 4>::call(x, T(0x3333333333333333ull), static_cast<T>( 2));
} x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 8>::call(x, T(0x0F0F0F0F0F0F0F0Full), static_cast<T>( 4));
x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 16>::call(x, T(0x00FF00FF00FF00FFull), static_cast<T>( 8));
VECTORIZE_VEC(bitfieldReverse) x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 32>::call(x, T(0x0000FFFF0000FFFFull), static_cast<T>(16));
x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 64>::call(x, T(0x00000000FFFFFFFFull), static_cast<T>(32));
return x;
}
// bitCount // bitCount
template <typename genIUType> template <typename genType>
GLM_FUNC_QUALIFIER int bitCount(genIUType const & Value) GLM_FUNC_QUALIFIER int bitCount(genType x)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'bitCount' only accept integer values"); return bitCount(glm::tvec1<genType, glm::defaultp>(x)).x;
int Count = 0;
for(std::size_t i = 0; i < sizeof(genIUType) * std::size_t(8); ++i)
{
if(Value & (1 << i))
++Count;
}
return Count;
} }
template <typename T, precision P> template <typename T, glm::precision P, template <typename, glm::precision> class vecType>
GLM_FUNC_QUALIFIER detail::tvec2<int, P> bitCount GLM_FUNC_QUALIFIER vecType<int, P> bitCount(vecType<T, P> const & v)
(
detail::tvec2<T, P> const & value
)
{ {
return detail::tvec2<int, P>( vecType<typename detail::make_unsigned<T>::type, P> x(*reinterpret_cast<vecType<typename detail::make_unsigned<T>::type, P> const *>(&v));
bitCount(value[0]), x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 2>::call(x, typename detail::make_unsigned<T>::type(0x5555555555555555ull), typename detail::make_unsigned<T>::type( 1));
bitCount(value[1])); x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 4>::call(x, typename detail::make_unsigned<T>::type(0x3333333333333333ull), typename detail::make_unsigned<T>::type( 2));
} x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 8>::call(x, typename detail::make_unsigned<T>::type(0x0F0F0F0F0F0F0F0Full), typename detail::make_unsigned<T>::type( 4));
x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 16>::call(x, typename detail::make_unsigned<T>::type(0x00FF00FF00FF00FFull), typename detail::make_unsigned<T>::type( 8));
template <typename T, precision P> x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 32>::call(x, typename detail::make_unsigned<T>::type(0x0000FFFF0000FFFFull), typename detail::make_unsigned<T>::type(16));
GLM_FUNC_QUALIFIER detail::tvec3<int, P> bitCount x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 64>::call(x, typename detail::make_unsigned<T>::type(0x00000000FFFFFFFFull), typename detail::make_unsigned<T>::type(32));
( return vecType<int, P>(x);
detail::tvec3<T, P> const & value
)
{
return detail::tvec3<int, P>(
bitCount(value[0]),
bitCount(value[1]),
bitCount(value[2]));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<int, P> bitCount
(
detail::tvec4<T, P> const & value
)
{
return detail::tvec4<int, P>(
bitCount(value[0]),
bitCount(value[1]),
bitCount(value[2]),
bitCount(value[3]));
} }
// findLSB // findLSB
template <typename genIUType> template <typename genIUType>
GLM_FUNC_QUALIFIER int findLSB GLM_FUNC_QUALIFIER int findLSB(genIUType Value)
(
genIUType const & Value
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findLSB' only accept integer values"); GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findLSB' only accept integer values");
if(Value == 0)
return -1;
genIUType Bit; return detail::compute_findLSB<genIUType, sizeof(genIUType) * 8>::call(Value);
for(Bit = genIUType(0); !(Value & (1 << Bit)); ++Bit){}
return Bit;
} }
template <typename T, precision P> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER detail::tvec2<int, P> findLSB GLM_FUNC_QUALIFIER vecType<int, P> findLSB(vecType<T, P> const & x)
(
detail::tvec2<T, P> const & value
)
{ {
return detail::tvec2<int, P>( GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findLSB' only accept integer values");
findLSB(value[0]),
findLSB(value[1]));
}
template <typename T, precision P> return detail::functor1<int, T, P, vecType>::call(findLSB, x);
GLM_FUNC_QUALIFIER detail::tvec3<int, P> findLSB
(
detail::tvec3<T, P> const & value
)
{
return detail::tvec3<int, P>(
findLSB(value[0]),
findLSB(value[1]),
findLSB(value[2]));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<int, P> findLSB
(
detail::tvec4<T, P> const & value
)
{
return detail::tvec4<int, P>(
findLSB(value[0]),
findLSB(value[1]),
findLSB(value[2]),
findLSB(value[3]));
} }
// findMSB // findMSB
#if((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_VC))
template <typename genIUType> template <typename genIUType>
GLM_FUNC_QUALIFIER int findMSB GLM_FUNC_QUALIFIER int findMSB(genIUType x)
(
genIUType const & Value
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values"); GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
if(Value == 0)
return -1;
unsigned long Result(0); return findMSB(tvec1<genIUType>(x)).x;
_BitScanReverse(&Result, Value);
return int(Result);
}
/*
// __builtin_clz seems to be buggy as it crasks for some values, from 0x00200000 to 80000000
#elif((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC40))
template <typename genIUType>
GLM_FUNC_QUALIFIER int findMSB
(
genIUType const & Value
)
{
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
if(Value == 0)
return -1;
// clz returns the number or trailing 0-bits; see
// http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Other-Builtins.html
//
// NoteBecause __builtin_clz only works for unsigned ints, this
// implementation will not work for 64-bit integers.
//
return 31 - __builtin_clzl(Value);
}
*/
#else
/* SSE implementation idea
__m128i const Zero = _mm_set_epi32( 0, 0, 0, 0);
__m128i const One = _mm_set_epi32( 1, 1, 1, 1);
__m128i Bit = _mm_set_epi32(-1, -1, -1, -1);
__m128i Tmp = _mm_set_epi32(Value, Value, Value, Value);
__m128i Mmi = Zero;
for(int i = 0; i < 32; ++i)
{
__m128i Shilt = _mm_and_si128(_mm_cmpgt_epi32(Tmp, One), One);
Tmp = _mm_srai_epi32(Tmp, One);
Bit = _mm_add_epi32(Bit, _mm_and_si128(Shilt, i));
Mmi = _mm_and_si128(Mmi, One);
}
return Bit;
*/
template <typename genIUType>
GLM_FUNC_QUALIFIER int findMSB
(
genIUType const & Value
)
{
GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values");
if(Value == genIUType(0) || Value == genIUType(-1))
return -1;
else if(Value > 0)
{
genIUType Bit = genIUType(-1);
for(genIUType tmp = Value; tmp > 0; tmp >>= 1, ++Bit){}
return Bit;
}
else //if(Value < 0)
{
int const BitCount(sizeof(genIUType) * 8);
int MostSignificantBit(-1);
for(int BitIndex(0); BitIndex < BitCount; ++BitIndex)
MostSignificantBit = (Value & (1 << BitIndex)) ? MostSignificantBit : BitIndex;
assert(MostSignificantBit >= 0);
return MostSignificantBit;
}
}
#endif//(GLM_COMPILER)
template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<int, P> findMSB
(
detail::tvec2<T, P> const & value
)
{
return detail::tvec2<int, P>(
findMSB(value[0]),
findMSB(value[1]));
} }
template <typename T, precision P> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER detail::tvec3<int, P> findMSB GLM_FUNC_QUALIFIER vecType<int, P> findMSB(vecType<T, P> const & x)
(
detail::tvec3<T, P> const & value
)
{ {
return detail::tvec3<int, P>( GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findMSB' only accept integer values");
findMSB(value[0]),
findMSB(value[1]),
findMSB(value[2]));
}
template <typename T, precision P> return detail::compute_findMSB_vec<T, P, vecType, sizeof(T) * 8>::call(x);
GLM_FUNC_QUALIFIER detail::tvec4<int, P> findMSB
(
detail::tvec4<T, P> const & value
)
{
return detail::tvec4<int, P>(
findMSB(value[0]),
findMSB(value[1]),
findMSB(value[2]),
findMSB(value[3]));
} }
}//namespace glm }//namespace glm

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_matrix.hpp /// @file glm/detail/func_matrix.hpp
/// @date 2008-08-03 / 2011-06-15 /// @date 2008-08-03 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -37,8 +41,7 @@
/// floating point version is shown. /// floating point version is shown.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_CORE_func_matrix #pragma once
#define GLM_CORE_func_matrix
// Dependencies // Dependencies
#include "../detail/precision.hpp" #include "../detail/precision.hpp"
@ -137,8 +140,6 @@ namespace detail
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/outerProduct.xml">GLSL outerProduct man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/outerProduct.xml">GLSL outerProduct man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
///
/// @todo Clarify the declaration to specify that matType doesn't have to be provided when used.
template <typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB> template <typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB>
GLM_FUNC_DECL typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r); GLM_FUNC_DECL typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r);
@ -148,7 +149,7 @@ namespace detail
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/transpose.xml">GLSL transpose man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/transpose.xml">GLSL transpose man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a>
# if((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC11)) # if((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2012))
template <typename T, precision P, template <typename, precision> class matType> template <typename T, precision P, template <typename, precision> class matType>
GLM_FUNC_DECL typename matType<T, P>::transpose_type transpose(matType<T, P> const & x); GLM_FUNC_DECL typename matType<T, P>::transpose_type transpose(matType<T, P> const & x);
# endif # endif
@ -175,5 +176,3 @@ namespace detail
}//namespace glm }//namespace glm
#include "func_matrix.inl" #include "func_matrix.inl"
#endif//GLM_CORE_func_matrix

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_matrix.inl /// @file glm/detail/func_matrix.inl
/// @date 2008-03-08 / 2011-06-15 /// @date 2008-03-08 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -32,173 +36,15 @@
namespace glm{ namespace glm{
namespace detail namespace detail
{ {
template
<
template <class, precision> class vecTypeA,
template <class, precision> class vecTypeB,
typename T, precision P
>
struct compute_outerProduct{};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec2, detail::tvec2, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec2, detail::tvec2>::type call(detail::tvec2<T, P> const & c, detail::tvec2<T, P> const & r)
{
detail::tmat2x2<T, P> m(detail::tmat2x2<T, P>::_null);
m[0][0] = c[0] * r[0];
m[0][1] = c[1] * r[0];
m[1][0] = c[0] * r[1];
m[1][1] = c[1] * r[1];
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec3, detail::tvec3, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec3, detail::tvec3>::type call(detail::tvec3<T, P> const & c, detail::tvec3<T, P> const & r)
{
detail::tmat3x3<T, P> m(detail::tmat3x3<T, P>::_null);
for(length_t i(0); i < m.length(); ++i)
m[i] = c * r[i];
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec4, detail::tvec4, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec4, detail::tvec4>::type call(detail::tvec4<T, P> const & c, detail::tvec4<T, P> const & r)
{
detail::tmat4x4<T, P> m(detail::tmat4x4<T, P>::_null);
for(length_t i(0); i < m.length(); ++i)
m[i] = c * r[i];
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec3, detail::tvec2, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec3, detail::tvec2>::type call(detail::tvec3<T, P> const & c, detail::tvec2<T, P> const & r)
{
detail::tmat2x3<T, P> m(detail::tmat2x3<T, P>::_null);
m[0][0] = c.x * r.x;
m[0][1] = c.y * r.x;
m[0][2] = c.z * r.x;
m[1][0] = c.x * r.y;
m[1][1] = c.y * r.y;
m[1][2] = c.z * r.y;
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec2, detail::tvec3, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec2, detail::tvec3>::type call(detail::tvec2<T, P> const & c, detail::tvec3<T, P> const & r)
{
detail::tmat3x2<T, P> m(detail::tmat3x2<T, P>::_null);
m[0][0] = c.x * r.x;
m[0][1] = c.y * r.x;
m[1][0] = c.x * r.y;
m[1][1] = c.y * r.y;
m[2][0] = c.x * r.z;
m[2][1] = c.y * r.z;
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec4, detail::tvec2, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec4, detail::tvec2>::type call(detail::tvec4<T, P> const & c, detail::tvec2<T, P> const & r)
{
detail::tmat2x4<T, P> m(detail::tmat2x4<T, P>::_null);
m[0][0] = c.x * r.x;
m[0][1] = c.y * r.x;
m[0][2] = c.z * r.x;
m[0][3] = c.w * r.x;
m[1][0] = c.x * r.y;
m[1][1] = c.y * r.y;
m[1][2] = c.z * r.y;
m[1][3] = c.w * r.y;
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec2, detail::tvec4, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec2, detail::tvec4>::type call(detail::tvec2<T, P> const & c, detail::tvec4<T, P> const & r)
{
detail::tmat4x2<T, P> m(detail::tmat4x2<T, P>::_null);
m[0][0] = c.x * r.x;
m[0][1] = c.y * r.x;
m[1][0] = c.x * r.y;
m[1][1] = c.y * r.y;
m[2][0] = c.x * r.z;
m[2][1] = c.y * r.z;
m[3][0] = c.x * r.w;
m[3][1] = c.y * r.w;
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec4, detail::tvec3, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec4, detail::tvec3>::type call(detail::tvec4<T, P> const & c, detail::tvec3<T, P> const & r)
{
detail::tmat3x4<T, P> m(detail::tmat3x4<T, P>::_null);
m[0][0] = c.x * r.x;
m[0][1] = c.y * r.x;
m[0][2] = c.z * r.x;
m[0][3] = c.w * r.x;
m[1][0] = c.x * r.y;
m[1][1] = c.y * r.y;
m[1][2] = c.z * r.y;
m[1][3] = c.w * r.y;
m[2][0] = c.x * r.z;
m[2][1] = c.y * r.z;
m[2][2] = c.z * r.z;
m[2][3] = c.w * r.z;
return m;
}
};
template <typename T, precision P>
struct compute_outerProduct<detail::tvec3, detail::tvec4, T, P>
{
GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec3, detail::tvec4>::type call(detail::tvec3<T, P> const & c, detail::tvec4<T, P> const & r)
{
detail::tmat4x3<T, P> m(detail::tmat4x3<T, P>::_null);
m[0][0] = c.x * r.x;
m[0][1] = c.y * r.x;
m[0][2] = c.z * r.x;
m[1][0] = c.x * r.y;
m[1][1] = c.y * r.y;
m[1][2] = c.z * r.y;
m[2][0] = c.x * r.z;
m[2][1] = c.y * r.z;
m[2][2] = c.z * r.z;
m[3][0] = c.x * r.w;
m[3][1] = c.y * r.w;
m[3][2] = c.z * r.w;
return m;
}
};
template <template <class, precision> class matType, typename T, precision P> template <template <class, precision> class matType, typename T, precision P>
struct compute_transpose{}; struct compute_transpose{};
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat2x2, T, P> struct compute_transpose<tmat2x2, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat2x2<T, P> call(detail::tmat2x2<T, P> const & m) GLM_FUNC_QUALIFIER static tmat2x2<T, P> call(tmat2x2<T, P> const & m)
{ {
detail::tmat2x2<T, P> result(detail::tmat2x2<T, P>::_null); tmat2x2<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[1][0] = m[0][1]; result[1][0] = m[0][1];
@ -208,11 +54,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat2x3, T, P> struct compute_transpose<tmat2x3, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat3x2<T, P> call(detail::tmat2x3<T, P> const & m) GLM_FUNC_QUALIFIER static tmat3x2<T, P> call(tmat2x3<T, P> const & m)
{ {
detail::tmat3x2<T, P> result(detail::tmat3x2<T, P>::_null); tmat3x2<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[1][0] = m[0][1]; result[1][0] = m[0][1];
@ -224,11 +70,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat2x4, T, P> struct compute_transpose<tmat2x4, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat4x2<T, P> call(detail::tmat2x4<T, P> const & m) GLM_FUNC_QUALIFIER static tmat4x2<T, P> call(tmat2x4<T, P> const & m)
{ {
detail::tmat4x2<T, P> result(detail::tmat4x2<T, P>::_null); tmat4x2<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[1][0] = m[0][1]; result[1][0] = m[0][1];
@ -242,11 +88,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat3x2, T, P> struct compute_transpose<tmat3x2, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat2x3<T, P> call(detail::tmat3x2<T, P> const & m) GLM_FUNC_QUALIFIER static tmat2x3<T, P> call(tmat3x2<T, P> const & m)
{ {
detail::tmat2x3<T, P> result(detail::tmat2x3<T, P>::_null); tmat2x3<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[0][2] = m[2][0]; result[0][2] = m[2][0];
@ -258,11 +104,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat3x3, T, P> struct compute_transpose<tmat3x3, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat3x3<T, P> call(detail::tmat3x3<T, P> const & m) GLM_FUNC_QUALIFIER static tmat3x3<T, P> call(tmat3x3<T, P> const & m)
{ {
detail::tmat3x3<T, P> result(detail::tmat3x3<T, P>::_null); tmat3x3<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[0][2] = m[2][0]; result[0][2] = m[2][0];
@ -279,11 +125,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat3x4, T, P> struct compute_transpose<tmat3x4, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat4x3<T, P> call(detail::tmat3x4<T, P> const & m) GLM_FUNC_QUALIFIER static tmat4x3<T, P> call(tmat3x4<T, P> const & m)
{ {
detail::tmat4x3<T, P> result(detail::tmat4x3<T, P>::_null); tmat4x3<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[0][2] = m[2][0]; result[0][2] = m[2][0];
@ -301,11 +147,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat4x2, T, P> struct compute_transpose<tmat4x2, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat2x4<T, P> call(detail::tmat4x2<T, P> const & m) GLM_FUNC_QUALIFIER static tmat2x4<T, P> call(tmat4x2<T, P> const & m)
{ {
detail::tmat2x4<T, P> result(detail::tmat2x4<T, P>::_null); tmat2x4<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[0][2] = m[2][0]; result[0][2] = m[2][0];
@ -319,11 +165,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat4x3, T, P> struct compute_transpose<tmat4x3, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat3x4<T, P> call(detail::tmat4x3<T, P> const & m) GLM_FUNC_QUALIFIER static tmat3x4<T, P> call(tmat4x3<T, P> const & m)
{ {
detail::tmat3x4<T, P> result(detail::tmat3x4<T, P>::_null); tmat3x4<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[0][2] = m[2][0]; result[0][2] = m[2][0];
@ -341,11 +187,11 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_transpose<detail::tmat4x4, T, P> struct compute_transpose<tmat4x4, T, P>
{ {
GLM_FUNC_QUALIFIER static detail::tmat4x4<T, P> call(detail::tmat4x4<T, P> const & m) GLM_FUNC_QUALIFIER static tmat4x4<T, P> call(tmat4x4<T, P> const & m)
{ {
detail::tmat4x4<T, P> result(detail::tmat4x4<T, P>::_null); tmat4x4<T, P> result(uninitialize);
result[0][0] = m[0][0]; result[0][0] = m[0][0];
result[0][1] = m[1][0]; result[0][1] = m[1][0];
result[0][2] = m[2][0]; result[0][2] = m[2][0];
@ -373,18 +219,18 @@ namespace detail
struct compute_determinant{}; struct compute_determinant{};
template <typename T, precision P> template <typename T, precision P>
struct compute_determinant<detail::tmat2x2, T, P> struct compute_determinant<tmat2x2, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tmat2x2<T, P> const & m) GLM_FUNC_QUALIFIER static T call(tmat2x2<T, P> const & m)
{ {
return m[0][0] * m[1][1] - m[1][0] * m[0][1]; return m[0][0] * m[1][1] - m[1][0] * m[0][1];
} }
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_determinant<detail::tmat3x3, T, P> struct compute_determinant<tmat3x3, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tmat3x3<T, P> const & m) GLM_FUNC_QUALIFIER static T call(tmat3x3<T, P> const & m)
{ {
return return
+ m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
@ -394,9 +240,9 @@ namespace detail
}; };
template <typename T, precision P> template <typename T, precision P>
struct compute_determinant<detail::tmat4x4, T, P> struct compute_determinant<tmat4x4, T, P>
{ {
GLM_FUNC_QUALIFIER static T call(detail::tmat4x4<T, P> const & m) GLM_FUNC_QUALIFIER static T call(tmat4x4<T, P> const & m)
{ {
T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
@ -405,7 +251,7 @@ namespace detail
T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
detail::tvec4<T, P> DetCof( tvec4<T, P> DetCof(
+ (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
- (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
+ (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
@ -423,8 +269,8 @@ namespace detail
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'matrixCompMult' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'matrixCompMult' only accept floating-point inputs");
matType<T, P> result(matType<T, P>::_null); matType<T, P> result(uninitialize);
for(length_t i = 0; i < result.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(result); ++i)
result[i] = x[i] * y[i]; result[i] = x[i] * y[i];
return result; return result;
} }
@ -433,7 +279,11 @@ namespace detail
GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r) GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'outerProduct' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'outerProduct' only accept floating-point inputs");
return detail::compute_outerProduct<vecTypeA, vecTypeB, T, P>::call(c, r);
typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type m(uninitialize);
for(detail::component_count_t i = 0; i < detail::component_count(m); ++i)
m[i] = c * r[i];
return m;
} }
template <typename T, precision P, template <typename, precision> class matType> template <typename T, precision P, template <typename, precision> class matType>
@ -454,7 +304,7 @@ namespace detail
GLM_FUNC_QUALIFIER matType<T, P> inverse(matType<T, P> const & m) GLM_FUNC_QUALIFIER matType<T, P> inverse(matType<T, P> const & m)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inverse' only accept floating-point inputs"); GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inverse' only accept floating-point inputs");
return detail::compute_inverse<matType, T, P>::call(m); return detail::compute_inverse(m);
} }
}//namespace glm }//namespace glm

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_noise.hpp /// @file glm/detail/func_noise.hpp
/// @date 2008-08-01 / 2011-06-18 /// @date 2008-08-01 / 2011-06-18
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -35,8 +39,7 @@
/// appearance of randomness, but are not truly random. /// appearance of randomness, but are not truly random.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_func_noise #pragma once
#define glm_core_func_noise
#include "type_vec1.hpp" #include "type_vec1.hpp"
#include "type_vec2.hpp" #include "type_vec2.hpp"
@ -64,7 +67,7 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise2.xml">GLSL noise2 man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise2.xml">GLSL noise2 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL detail::tvec2<typename genType::value_type, defaultp> noise2(genType const & x); GLM_FUNC_DECL tvec2<typename genType::value_type, defaultp> noise2(genType const & x);
/// Returns a 3D noise value based on the input value x. /// Returns a 3D noise value based on the input value x.
/// ///
@ -73,7 +76,7 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise3.xml">GLSL noise3 man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise3.xml">GLSL noise3 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL detail::tvec3<typename genType::value_type, defaultp> noise3(genType const & x); GLM_FUNC_DECL tvec3<typename genType::value_type, defaultp> noise3(genType const & x);
/// Returns a 4D noise value based on the input value x. /// Returns a 4D noise value based on the input value x.
/// ///
@ -82,11 +85,9 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise4.xml">GLSL noise4 man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise4.xml">GLSL noise4 man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a>
template <typename genType> template <typename genType>
GLM_FUNC_DECL detail::tvec4<typename genType::value_type, defaultp> noise4(genType const & x); GLM_FUNC_DECL tvec4<typename genType::value_type, defaultp> noise4(genType const & x);
/// @} /// @}
}//namespace glm }//namespace glm
#include "func_noise.inl" #include "func_noise.inl"
#endif//glm_core_func_noise

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_noise.inl /// @file glm/detail/func_noise.inl
/// @date 2008-08-01 / 2011-09-27 /// @date 2008-08-01 / 2011-09-27
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -33,43 +37,43 @@ namespace glm{
namespace detail namespace detail
{ {
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> grad4(T const & j, detail::tvec4<T, P> const & ip) GLM_FUNC_QUALIFIER tvec4<T, P> grad4(T const & j, tvec4<T, P> const & ip)
{ {
detail::tvec3<T, P> pXYZ = floor(fract(detail::tvec3<T, P>(j) * detail::tvec3<T, P>(ip)) * T(7)) * ip[2] - T(1); tvec3<T, P> pXYZ = floor(fract(tvec3<T, P>(j) * tvec3<T, P>(ip)) * T(7)) * ip[2] - T(1);
T pW = static_cast<T>(1.5) - dot(abs(pXYZ), detail::tvec3<T, P>(1)); T pW = static_cast<T>(1.5) - dot(abs(pXYZ), tvec3<T, P>(1));
detail::tvec4<T, P> s = detail::tvec4<T, P>(lessThan(detail::tvec4<T, P>(pXYZ, pW), detail::tvec4<T, P>(0.0))); tvec4<T, P> s = tvec4<T, P>(lessThan(tvec4<T, P>(pXYZ, pW), tvec4<T, P>(0.0)));
pXYZ = pXYZ + (detail::tvec3<T, P>(s) * T(2) - T(1)) * s.w; pXYZ = pXYZ + (tvec3<T, P>(s) * T(2) - T(1)) * s.w;
return detail::tvec4<T, P>(pXYZ, pW); return tvec4<T, P>(pXYZ, pW);
} }
}//namespace detail }//namespace detail
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER T noise1(T const & x) GLM_FUNC_QUALIFIER T noise1(T const & x)
{ {
return noise1(detail::tvec2<T, defaultp>(x, T(0))); return noise1(tvec2<T, defaultp>(x, T(0)));
} }
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER detail::tvec2<T, defaultp> noise2(T const & x) GLM_FUNC_QUALIFIER tvec2<T, defaultp> noise2(T const & x)
{ {
return detail::tvec2<T, defaultp>( return tvec2<T, defaultp>(
noise1(x + T(0.0)), noise1(x + T(0.0)),
noise1(x + T(1.0))); noise1(x + T(1.0)));
} }
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER detail::tvec3<T, defaultp> noise3(T const & x) GLM_FUNC_QUALIFIER tvec3<T, defaultp> noise3(T const & x)
{ {
return detail::tvec3<T, defaultp>( return tvec3<T, defaultp>(
noise1(x - T(1.0)), noise1(x - T(1.0)),
noise1(x + T(0.0)), noise1(x + T(0.0)),
noise1(x + T(1.0))); noise1(x + T(1.0)));
} }
template <typename T> template <typename T>
GLM_FUNC_QUALIFIER detail::tvec4<T, defaultp> noise4(T const & x) GLM_FUNC_QUALIFIER tvec4<T, defaultp> noise4(T const & x)
{ {
return detail::tvec4<T, defaultp>( return tvec4<T, defaultp>(
noise1(x - T(1.0)), noise1(x - T(1.0)),
noise1(x + T(0.0)), noise1(x + T(0.0)),
noise1(x + T(1.0)), noise1(x + T(1.0)),
@ -77,38 +81,38 @@ namespace detail
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER T noise1(detail::tvec2<T, P> const & v) GLM_FUNC_QUALIFIER T noise1(tvec2<T, P> const & v)
{ {
detail::tvec4<T, P> const C = detail::tvec4<T, P>( tvec4<T, P> const C = tvec4<T, P>(
T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0 T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0
T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0) T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0)
T(-0.577350269189626), // -1.0 + 2.0 * C.x T(-0.577350269189626), // -1.0 + 2.0 * C.x
T( 0.024390243902439)); // 1.0 / 41.0 T( 0.024390243902439)); // 1.0 / 41.0
// First corner // First corner
detail::tvec2<T, P> i = floor(v + dot(v, detail::tvec2<T, P>(C[1]))); tvec2<T, P> i = floor(v + dot(v, tvec2<T, P>(C[1])));
detail::tvec2<T, P> x0 = v - i + dot(i, detail::tvec2<T, P>(C[0])); tvec2<T, P> x0 = v - i + dot(i, tvec2<T, P>(C[0]));
// Other corners // Other corners
//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//i1.y = 1.0 - i1.x; //i1.y = 1.0 - i1.x;
detail::tvec2<T, P> i1 = (x0.x > x0.y) ? detail::tvec2<T, P>(1, 0) : detail::tvec2<T, P>(0, 1); tvec2<T, P> i1 = (x0.x > x0.y) ? tvec2<T, P>(1, 0) : tvec2<T, P>(0, 1);
// x0 = x0 - 0.0 + 0.0 * C.xx ; // x0 = x0 - 0.0 + 0.0 * C.xx ;
// x1 = x0 - i1 + 1.0 * C.xx ; // x1 = x0 - i1 + 1.0 * C.xx ;
// x2 = x0 - 1.0 + 2.0 * C.xx ; // x2 = x0 - 1.0 + 2.0 * C.xx ;
detail::tvec4<T, P> x12 = detail::tvec4<T, P>(x0.x, x0.y, x0.x, x0.y) + detail::tvec4<T, P>(C.x, C.x, C.z, C.z); tvec4<T, P> x12 = tvec4<T, P>(x0.x, x0.y, x0.x, x0.y) + tvec4<T, P>(C.x, C.x, C.z, C.z);
x12 = detail::tvec4<T, P>(detail::tvec2<T, P>(x12) - i1, x12.z, x12.w); x12 = tvec4<T, P>(tvec2<T, P>(x12) - i1, x12.z, x12.w);
// Permutations // Permutations
i = mod(i, T(289)); // Avoid truncation effects in permutation i = mod(i, T(289)); // Avoid truncation effects in permutation
detail::tvec3<T, P> p = detail::permute( tvec3<T, P> p = detail::permute(
detail::permute(i.y + detail::tvec3<T, P>(T(0), i1.y, T(1))) + i.x + detail::tvec3<T, P>(T(0), i1.x, T(1))); detail::permute(i.y + tvec3<T, P>(T(0), i1.y, T(1))) + i.x + tvec3<T, P>(T(0), i1.x, T(1)));
detail::tvec3<T, P> m = max(T(0.5) - detail::tvec3<T, P>( tvec3<T, P> m = max(T(0.5) - tvec3<T, P>(
dot(x0, x0), dot(x0, x0),
dot(detail::tvec2<T, P>(x12.x, x12.y), detail::tvec2<T, P>(x12.x, x12.y)), dot(tvec2<T, P>(x12.x, x12.y), tvec2<T, P>(x12.x, x12.y)),
dot(detail::tvec2<T, P>(x12.z, x12.w), detail::tvec2<T, P>(x12.z, x12.w))), T(0)); dot(tvec2<T, P>(x12.z, x12.w), tvec2<T, P>(x12.z, x12.w))), T(0));
m = m * m; m = m * m;
m = m * m; m = m * m;
@ -116,17 +120,17 @@ namespace detail
// Gradients: 41 points uniformly over a line, mapped onto a diamond. // Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
detail::tvec3<T, P> x = static_cast<T>(2) * fract(p * C.w) - T(1); tvec3<T, P> x = static_cast<T>(2) * fract(p * C.w) - T(1);
detail::tvec3<T, P> h = abs(x) - T(0.5); tvec3<T, P> h = abs(x) - T(0.5);
detail::tvec3<T, P> ox = floor(x + T(0.5)); tvec3<T, P> ox = floor(x + T(0.5));
detail::tvec3<T, P> a0 = x - ox; tvec3<T, P> a0 = x - ox;
// Normalise gradients implicitly by scaling m // Normalise gradients implicitly by scaling m
// Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h );
m *= static_cast<T>(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h); m *= static_cast<T>(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h);
// Compute final noise value at P // Compute final noise value at P
detail::tvec3<T, P> g; tvec3<T, P> g;
g.x = a0.x * x0.x + h.x * x0.y; g.x = a0.x * x0.x + h.x * x0.y;
//g.yz = a0.yz * x12.xz + h.yz * x12.yw; //g.yz = a0.yz * x12.xz + h.yz * x12.yw;
g.y = a0.y * x12.x + h.y * x12.y; g.y = a0.y * x12.x + h.y * x12.y;
@ -135,84 +139,84 @@ namespace detail
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER T noise1(detail::tvec3<T, P> const & v) GLM_FUNC_QUALIFIER T noise1(tvec3<T, P> const & v)
{ {
detail::tvec2<T, P> const C(1.0 / 6.0, 1.0 / 3.0); tvec2<T, P> const C(1.0 / 6.0, 1.0 / 3.0);
detail::tvec4<T, P> const D(0.0, 0.5, 1.0, 2.0); tvec4<T, P> const D(0.0, 0.5, 1.0, 2.0);
// First corner // First corner
detail::tvec3<T, P> i(floor(v + dot(v, detail::tvec3<T, P>(C.y)))); tvec3<T, P> i(floor(v + dot(v, tvec3<T, P>(C.y))));
detail::tvec3<T, P> x0(v - i + dot(i, detail::tvec3<T, P>(C.x))); tvec3<T, P> x0(v - i + dot(i, tvec3<T, P>(C.x)));
// Other corners // Other corners
detail::tvec3<T, P> g(step(detail::tvec3<T, P>(x0.y, x0.z, x0.x), x0)); tvec3<T, P> g(step(tvec3<T, P>(x0.y, x0.z, x0.x), x0));
detail::tvec3<T, P> l(T(1) - g); tvec3<T, P> l(T(1) - g);
detail::tvec3<T, P> i1(min(g, detail::tvec3<T, P>(l.z, l.x, l.y))); tvec3<T, P> i1(min(g, tvec3<T, P>(l.z, l.x, l.y)));
detail::tvec3<T, P> i2(max(g, detail::tvec3<T, P>(l.z, l.x, l.y))); tvec3<T, P> i2(max(g, tvec3<T, P>(l.z, l.x, l.y)));
// x0 = x0 - 0.0 + 0.0 * C.xxx; // x0 = x0 - 0.0 + 0.0 * C.xxx;
// x1 = x0 - i1 + 1.0 * C.xxx; // x1 = x0 - i1 + 1.0 * C.xxx;
// x2 = x0 - i2 + 2.0 * C.xxx; // x2 = x0 - i2 + 2.0 * C.xxx;
// x3 = x0 - 1.0 + 3.0 * C.xxx; // x3 = x0 - 1.0 + 3.0 * C.xxx;
detail::tvec3<T, P> x1(x0 - i1 + C.x); tvec3<T, P> x1(x0 - i1 + C.x);
detail::tvec3<T, P> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y tvec3<T, P> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y
detail::tvec3<T, P> x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y tvec3<T, P> x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations // Permutations
i = mod289(i); i = mod289(i);
detail::tvec4<T, P> p(detail::permute(detail::permute(detail::permute( tvec4<T, P> p(detail::permute(detail::permute(detail::permute(
i.z + detail::tvec4<T, P>(T(0), i1.z, i2.z, T(1))) + i.z + tvec4<T, P>(T(0), i1.z, i2.z, T(1))) +
i.y + detail::tvec4<T, P>(T(0), i1.y, i2.y, T(1))) + i.y + tvec4<T, P>(T(0), i1.y, i2.y, T(1))) +
i.x + detail::tvec4<T, P>(T(0), i1.x, i2.x, T(1)))); i.x + tvec4<T, P>(T(0), i1.x, i2.x, T(1))));
// Gradients: 7x7 points over a square, mapped onto an octahedron. // Gradients: 7x7 points over a square, mapped onto an octahedron.
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
T n_ = static_cast<T>(0.142857142857); // 1.0/7.0 T n_ = static_cast<T>(0.142857142857); // 1.0/7.0
detail::tvec3<T, P> ns(n_ * detail::tvec3<T, P>(D.w, D.y, D.z) - detail::tvec3<T, P>(D.x, D.z, D.x)); tvec3<T, P> ns(n_ * tvec3<T, P>(D.w, D.y, D.z) - tvec3<T, P>(D.x, D.z, D.x));
detail::tvec4<T, P> j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7) tvec4<T, P> j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7)
detail::tvec4<T, P> x_(floor(j * ns.z)); tvec4<T, P> x_(floor(j * ns.z));
detail::tvec4<T, P> y_(floor(j - T(7) * x_)); // mod(j,N) tvec4<T, P> y_(floor(j - T(7) * x_)); // mod(j,N)
detail::tvec4<T, P> x(x_ * ns.x + ns.y); tvec4<T, P> x(x_ * ns.x + ns.y);
detail::tvec4<T, P> y(y_ * ns.x + ns.y); tvec4<T, P> y(y_ * ns.x + ns.y);
detail::tvec4<T, P> h(T(1) - abs(x) - abs(y)); tvec4<T, P> h(T(1) - abs(x) - abs(y));
detail::tvec4<T, P> b0(x.x, x.y, y.x, y.y); tvec4<T, P> b0(x.x, x.y, y.x, y.y);
detail::tvec4<T, P> b1(x.z, x.w, y.z, y.w); tvec4<T, P> b1(x.z, x.w, y.z, y.w);
// vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
// vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
detail::tvec4<T, P> s0(floor(b0) * T(2) + T(1)); tvec4<T, P> s0(floor(b0) * T(2) + T(1));
detail::tvec4<T, P> s1(floor(b1) * T(2) + T(1)); tvec4<T, P> s1(floor(b1) * T(2) + T(1));
detail::tvec4<T, P> sh(-step(h, detail::tvec4<T, P>(0.0))); tvec4<T, P> sh(-step(h, tvec4<T, P>(0.0)));
detail::tvec4<T, P> a0 = detail::tvec4<T, P>(b0.x, b0.z, b0.y, b0.w) + detail::tvec4<T, P>(s0.x, s0.z, s0.y, s0.w) * detail::tvec4<T, P>(sh.x, sh.x, sh.y, sh.y); tvec4<T, P> a0 = tvec4<T, P>(b0.x, b0.z, b0.y, b0.w) + tvec4<T, P>(s0.x, s0.z, s0.y, s0.w) * tvec4<T, P>(sh.x, sh.x, sh.y, sh.y);
detail::tvec4<T, P> a1 = detail::tvec4<T, P>(b1.x, b1.z, b1.y, b1.w) + detail::tvec4<T, P>(s1.x, s1.z, s1.y, s1.w) * detail::tvec4<T, P>(sh.z, sh.z, sh.w, sh.w); tvec4<T, P> a1 = tvec4<T, P>(b1.x, b1.z, b1.y, b1.w) + tvec4<T, P>(s1.x, s1.z, s1.y, s1.w) * tvec4<T, P>(sh.z, sh.z, sh.w, sh.w);
detail::tvec3<T, P> p0(a0.x, a0.y, h.x); tvec3<T, P> p0(a0.x, a0.y, h.x);
detail::tvec3<T, P> p1(a0.z, a0.w, h.y); tvec3<T, P> p1(a0.z, a0.w, h.y);
detail::tvec3<T, P> p2(a1.x, a1.y, h.z); tvec3<T, P> p2(a1.x, a1.y, h.z);
detail::tvec3<T, P> p3(a1.z, a1.w, h.w); tvec3<T, P> p3(a1.z, a1.w, h.w);
// Normalise gradients // Normalise gradients
detail::tvec4<T, P> norm = taylorInvSqrt(detail::tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); tvec4<T, P> norm = taylorInvSqrt(tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
p0 *= norm.x; p0 *= norm.x;
p1 *= norm.y; p1 *= norm.y;
p2 *= norm.z; p2 *= norm.z;
p3 *= norm.w; p3 *= norm.w;
// Mix final noise value // Mix final noise value
detail::tvec4<T, P> m = max(T(0.6) - detail::tvec4<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), T(0)); tvec4<T, P> m = max(T(0.6) - tvec4<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), T(0));
m = m * m; m = m * m;
return T(42) * dot(m * m, detail::tvec4<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); return T(42) * dot(m * m, tvec4<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER T noise1(detail::tvec4<T, P> const & v) GLM_FUNC_QUALIFIER T noise1(tvec4<T, P> const & v)
{ {
detail::tvec4<T, P> const C( tvec4<T, P> const C(
0.138196601125011, // (5 - sqrt(5))/20 G4 0.138196601125011, // (5 - sqrt(5))/20 G4
0.276393202250021, // 2 * G4 0.276393202250021, // 2 * G4
0.414589803375032, // 3 * G4 0.414589803375032, // 3 * G4
@ -222,66 +226,66 @@ namespace detail
T const F4 = static_cast<T>(0.309016994374947451); T const F4 = static_cast<T>(0.309016994374947451);
// First corner // First corner
detail::tvec4<T, P> i = floor(v + dot(v, detail::tvec4<T, P>(F4))); tvec4<T, P> i = floor(v + dot(v, tvec4<T, P>(F4)));
detail::tvec4<T, P> x0 = v - i + dot(i, detail::tvec4<T, P>(C.x)); tvec4<T, P> x0 = v - i + dot(i, tvec4<T, P>(C.x));
// Other corners // Other corners
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
detail::tvec4<T, P> i0; tvec4<T, P> i0;
detail::tvec3<T, P> isX = step(detail::tvec3<T, P>(x0.y, x0.z, x0.w), detail::tvec3<T, P>(x0.x)); tvec3<T, P> isX = step(tvec3<T, P>(x0.y, x0.z, x0.w), tvec3<T, P>(x0.x));
detail::tvec3<T, P> isYZ = step(detail::tvec3<T, P>(x0.z, x0.w, x0.w), detail::tvec3<T, P>(x0.y, x0.y, x0.z)); tvec3<T, P> isYZ = step(tvec3<T, P>(x0.z, x0.w, x0.w), tvec3<T, P>(x0.y, x0.y, x0.z));
// i0.x = dot(isX, vec3(1.0)); // i0.x = dot(isX, vec3(1.0));
//i0.x = isX.x + isX.y + isX.z; //i0.x = isX.x + isX.y + isX.z;
//i0.yzw = static_cast<T>(1) - isX; //i0.yzw = static_cast<T>(1) - isX;
i0 = detail::tvec4<T, P>(isX.x + isX.y + isX.z, T(1) - isX); i0 = tvec4<T, P>(isX.x + isX.y + isX.z, T(1) - isX);
// i0.y += dot(isYZ.xy, vec2(1.0)); // i0.y += dot(isYZ.xy, vec2(1.0));
i0.y += isYZ.x + isYZ.y; i0.y += isYZ.x + isYZ.y;
//i0.zw += 1.0 - detail::tvec2<T, P>(isYZ.x, isYZ.y); //i0.zw += 1.0 - tvec2<T, P>(isYZ.x, isYZ.y);
i0.z += static_cast<T>(1) - isYZ.x; i0.z += static_cast<T>(1) - isYZ.x;
i0.w += static_cast<T>(1) - isYZ.y; i0.w += static_cast<T>(1) - isYZ.y;
i0.z += isYZ.z; i0.z += isYZ.z;
i0.w += static_cast<T>(1) - isYZ.z; i0.w += static_cast<T>(1) - isYZ.z;
// i0 now contains the unique values 0,1,2,3 in each channel // i0 now contains the unique values 0,1,2,3 in each channel
detail::tvec4<T, P> i3 = clamp(i0, T(0), T(1)); tvec4<T, P> i3 = clamp(i0, T(0), T(1));
detail::tvec4<T, P> i2 = clamp(i0 - T(1), T(0), T(1)); tvec4<T, P> i2 = clamp(i0 - T(1), T(0), T(1));
detail::tvec4<T, P> i1 = clamp(i0 - T(2), T(0), T(1)); tvec4<T, P> i1 = clamp(i0 - T(2), T(0), T(1));
// x0 = x0 - 0.0 + 0.0 * C.xxxx // x0 = x0 - 0.0 + 0.0 * C.xxxx
// x1 = x0 - i1 + 0.0 * C.xxxx // x1 = x0 - i1 + 0.0 * C.xxxx
// x2 = x0 - i2 + 0.0 * C.xxxx // x2 = x0 - i2 + 0.0 * C.xxxx
// x3 = x0 - i3 + 0.0 * C.xxxx // x3 = x0 - i3 + 0.0 * C.xxxx
// x4 = x0 - 1.0 + 4.0 * C.xxxx // x4 = x0 - 1.0 + 4.0 * C.xxxx
detail::tvec4<T, P> x1 = x0 - i1 + C.x; tvec4<T, P> x1 = x0 - i1 + C.x;
detail::tvec4<T, P> x2 = x0 - i2 + C.y; tvec4<T, P> x2 = x0 - i2 + C.y;
detail::tvec4<T, P> x3 = x0 - i3 + C.z; tvec4<T, P> x3 = x0 - i3 + C.z;
detail::tvec4<T, P> x4 = x0 + C.w; tvec4<T, P> x4 = x0 + C.w;
// Permutations // Permutations
i = mod(i, T(289)); i = mod(i, T(289));
T j0 = detail::permute(detail::permute(detail::permute(detail::permute(i.w) + i.z) + i.y) + i.x); T j0 = detail::permute(detail::permute(detail::permute(detail::permute(i.w) + i.z) + i.y) + i.x);
detail::tvec4<T, P> j1 = detail::permute(detail::permute(detail::permute(detail::permute( tvec4<T, P> j1 = detail::permute(detail::permute(detail::permute(detail::permute(
i.w + detail::tvec4<T, P>(i1.w, i2.w, i3.w, T(1))) + i.w + tvec4<T, P>(i1.w, i2.w, i3.w, T(1))) +
i.z + detail::tvec4<T, P>(i1.z, i2.z, i3.z, T(1))) + i.z + tvec4<T, P>(i1.z, i2.z, i3.z, T(1))) +
i.y + detail::tvec4<T, P>(i1.y, i2.y, i3.y, T(1))) + i.y + tvec4<T, P>(i1.y, i2.y, i3.y, T(1))) +
i.x + detail::tvec4<T, P>(i1.x, i2.x, i3.x, T(1))); i.x + tvec4<T, P>(i1.x, i2.x, i3.x, T(1)));
// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
// 7*7*6 = 294, which is close to the ring size 17*17 = 289. // 7*7*6 = 294, which is close to the ring size 17*17 = 289.
detail::tvec4<T, P> ip = detail::tvec4<T, P>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0)); tvec4<T, P> ip = tvec4<T, P>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0));
detail::tvec4<T, P> p0 = detail::grad4(j0, ip); tvec4<T, P> p0 = detail::grad4(j0, ip);
detail::tvec4<T, P> p1 = detail::grad4(j1.x, ip); tvec4<T, P> p1 = detail::grad4(j1.x, ip);
detail::tvec4<T, P> p2 = detail::grad4(j1.y, ip); tvec4<T, P> p2 = detail::grad4(j1.y, ip);
detail::tvec4<T, P> p3 = detail::grad4(j1.z, ip); tvec4<T, P> p3 = detail::grad4(j1.z, ip);
detail::tvec4<T, P> p4 = detail::grad4(j1.w, ip); tvec4<T, P> p4 = detail::grad4(j1.w, ip);
// Normalise gradients // Normalise gradients
detail::tvec4<T, P> norm = detail::taylorInvSqrt(detail::tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); tvec4<T, P> norm = detail::taylorInvSqrt(tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
p0 *= norm.x; p0 *= norm.x;
p1 *= norm.y; p1 *= norm.y;
p2 *= norm.z; p2 *= norm.z;
@ -289,96 +293,96 @@ namespace detail
p4 *= taylorInvSqrt(dot(p4, p4)); p4 *= taylorInvSqrt(dot(p4, p4));
// Mix contributions from the five corners // Mix contributions from the five corners
detail::tvec3<T, P> m0 = max(T(0.6) - detail::tvec3<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), T(0)); tvec3<T, P> m0 = max(T(0.6) - tvec3<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), T(0));
detail::tvec2<T, P> m1 = max(T(0.6) - detail::tvec2<T, P>(dot(x3, x3), dot(x4, x4) ), T(0)); tvec2<T, P> m1 = max(T(0.6) - tvec2<T, P>(dot(x3, x3), dot(x4, x4) ), T(0));
m0 = m0 * m0; m0 = m0 * m0;
m1 = m1 * m1; m1 = m1 * m1;
return T(49) * ( return T(49) * (
dot(m0 * m0, detail::tvec3<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + dot(m0 * m0, tvec3<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) +
dot(m1 * m1, detail::tvec2<T, P>(dot(p3, x3), dot(p4, x4)))); dot(m1 * m1, tvec2<T, P>(dot(p3, x3), dot(p4, x4))));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> noise2(detail::tvec2<T, P> const & x) GLM_FUNC_QUALIFIER tvec2<T, P> noise2(tvec2<T, P> const & x)
{ {
return detail::tvec2<T, P>( return tvec2<T, P>(
noise1(x + detail::tvec2<T, P>(0.0)), noise1(x + tvec2<T, P>(0.0)),
noise1(detail::tvec2<T, P>(0.0) - x)); noise1(tvec2<T, P>(0.0) - x));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> noise2(detail::tvec3<T, P> const & x) GLM_FUNC_QUALIFIER tvec2<T, P> noise2(tvec3<T, P> const & x)
{ {
return detail::tvec2<T, P>( return tvec2<T, P>(
noise1(x + detail::tvec3<T, P>(0.0)), noise1(x + tvec3<T, P>(0.0)),
noise1(detail::tvec3<T, P>(0.0) - x)); noise1(tvec3<T, P>(0.0) - x));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec2<T, P> noise2(detail::tvec4<T, P> const & x) GLM_FUNC_QUALIFIER tvec2<T, P> noise2(tvec4<T, P> const & x)
{ {
return detail::tvec2<T, P>( return tvec2<T, P>(
noise1(x + detail::tvec4<T, P>(0)), noise1(x + tvec4<T, P>(0)),
noise1(detail::tvec4<T, P>(0) - x)); noise1(tvec4<T, P>(0) - x));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> noise3(detail::tvec2<T, P> const & x) GLM_FUNC_QUALIFIER tvec3<T, P> noise3(tvec2<T, P> const & x)
{ {
return detail::tvec3<T, P>( return tvec3<T, P>(
noise1(x - detail::tvec2<T, P>(1.0)), noise1(x - tvec2<T, P>(1.0)),
noise1(x + detail::tvec2<T, P>(0.0)), noise1(x + tvec2<T, P>(0.0)),
noise1(x + detail::tvec2<T, P>(1.0))); noise1(x + tvec2<T, P>(1.0)));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> noise3(detail::tvec3<T, P> const & x) GLM_FUNC_QUALIFIER tvec3<T, P> noise3(tvec3<T, P> const & x)
{ {
return detail::tvec3<T, P>( return tvec3<T, P>(
noise1(x - detail::tvec3<T, P>(1.0)), noise1(x - tvec3<T, P>(1.0)),
noise1(x + detail::tvec3<T, P>(0.0)), noise1(x + tvec3<T, P>(0.0)),
noise1(x + detail::tvec3<T, P>(1.0))); noise1(x + tvec3<T, P>(1.0)));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec3<T, P> noise3(detail::tvec4<T, P> const & x) GLM_FUNC_QUALIFIER tvec3<T, P> noise3(tvec4<T, P> const & x)
{ {
return detail::tvec3<T, P>( return tvec3<T, P>(
noise1(x - detail::tvec4<T, P>(1)), noise1(x - tvec4<T, P>(1)),
noise1(x + detail::tvec4<T, P>(0)), noise1(x + tvec4<T, P>(0)),
noise1(x + detail::tvec4<T, P>(1))); noise1(x + tvec4<T, P>(1)));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> noise4(detail::tvec2<T, P> const & x) GLM_FUNC_QUALIFIER tvec4<T, P> noise4(tvec2<T, P> const & x)
{ {
return detail::tvec4<T, P>( return tvec4<T, P>(
noise1(x - detail::tvec2<T, P>(1)), noise1(x - tvec2<T, P>(1)),
noise1(x + detail::tvec2<T, P>(0)), noise1(x + tvec2<T, P>(0)),
noise1(x + detail::tvec2<T, P>(1)), noise1(x + tvec2<T, P>(1)),
noise1(x + detail::tvec2<T, P>(2))); noise1(x + tvec2<T, P>(2)));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> noise4(detail::tvec3<T, P> const & x) GLM_FUNC_QUALIFIER tvec4<T, P> noise4(tvec3<T, P> const & x)
{ {
return detail::tvec4<T, P>( return tvec4<T, P>(
noise1(x - detail::tvec3<T, P>(1)), noise1(x - tvec3<T, P>(1)),
noise1(x + detail::tvec3<T, P>(0)), noise1(x + tvec3<T, P>(0)),
noise1(x + detail::tvec3<T, P>(1)), noise1(x + tvec3<T, P>(1)),
noise1(x + detail::tvec3<T, P>(2))); noise1(x + tvec3<T, P>(2)));
} }
template <typename T, precision P> template <typename T, precision P>
GLM_FUNC_QUALIFIER detail::tvec4<T, P> noise4(detail::tvec4<T, P> const & x) GLM_FUNC_QUALIFIER tvec4<T, P> noise4(tvec4<T, P> const & x)
{ {
return detail::tvec4<T, P>( return tvec4<T, P>(
noise1(x - detail::tvec4<T, P>(1)), noise1(x - tvec4<T, P>(1)),
noise1(x + detail::tvec4<T, P>(0)), noise1(x + tvec4<T, P>(0)),
noise1(x + detail::tvec4<T, P>(1)), noise1(x + tvec4<T, P>(1)),
noise1(x + detail::tvec4<T, P>(2))); noise1(x + tvec4<T, P>(2)));
} }
}//namespace glm }//namespace glm

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,11 +25,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_packing.hpp /// @file glm/detail/func_packing.hpp
/// @date 2010-03-17 / 2011-06-15 /// @date 2010-03-17 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a>
/// @see gtc_packing
/// ///
/// @defgroup core_func_packing Floating-Point Pack and Unpack Functions /// @defgroup core_func_packing Floating-Point Pack and Unpack Functions
/// @ingroup core /// @ingroup core
@ -33,8 +38,7 @@
/// These functions do not operate component-wise, rather as described in each case. /// These functions do not operate component-wise, rather as described in each case.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_CORE_func_packing #pragma once
#define GLM_CORE_func_packing
#include "type_vec2.hpp" #include "type_vec2.hpp"
#include "type_vec4.hpp" #include "type_vec4.hpp"
@ -191,5 +195,3 @@ namespace glm
}//namespace glm }//namespace glm
#include "func_packing.inl" #include "func_packing.inl"
#endif//GLM_CORE_func_packing

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_packing.inl /// @file glm/detail/func_packing.inl
/// @date 2010-03-17 / 2011-06-15 /// @date 2010-03-17 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -35,7 +39,9 @@ namespace glm
GLM_FUNC_QUALIFIER uint packUnorm2x16(vec2 const & v) GLM_FUNC_QUALIFIER uint packUnorm2x16(vec2 const & v)
{ {
u16vec2 Topack(round(clamp(v, 0.0f, 1.0f) * 65535.0f)); u16vec2 Topack(round(clamp(v, 0.0f, 1.0f) * 65535.0f));
return reinterpret_cast<uint&>(Topack); // return reinterpret_cast<uint&>(Topack);
uint* ptr(reinterpret_cast<uint*>(&Topack));
return *ptr;
} }
GLM_FUNC_QUALIFIER vec2 unpackUnorm2x16(uint const & p) GLM_FUNC_QUALIFIER vec2 unpackUnorm2x16(uint const & p)
@ -47,7 +53,9 @@ namespace glm
GLM_FUNC_QUALIFIER uint packSnorm2x16(vec2 const & v) GLM_FUNC_QUALIFIER uint packSnorm2x16(vec2 const & v)
{ {
i16vec2 Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); i16vec2 Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f));
return reinterpret_cast<uint32&>(Topack); // return reinterpret_cast<uint32&>(Topack);
uint* ptr(reinterpret_cast<uint*>(&Topack));
return *ptr;
} }
GLM_FUNC_QUALIFIER vec2 unpackSnorm2x16(uint const & p) GLM_FUNC_QUALIFIER vec2 unpackSnorm2x16(uint const & p)

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_trigonometric.hpp /// @file glm/detail/func_trigonometric.hpp
/// @date 2008-08-01 / 2011-06-15 /// @date 2008-08-01 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -37,8 +41,10 @@
/// These all operate component-wise. The description is per component. /// These all operate component-wise. The description is per component.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_CORE_func_trigonometric #pragma once
#define GLM_CORE_func_trigonometric
#include "setup.hpp"
#include "precision.hpp"
namespace glm namespace glm
{ {
@ -51,8 +57,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/radians.xml">GLSL radians man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/radians.xml">GLSL radians man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType radians(genType const & degrees); GLM_FUNC_DECL vecType<T, P> radians(vecType<T, P> const & degrees);
/// Converts radians to degrees and returns the result. /// Converts radians to degrees and returns the result.
/// ///
@ -60,8 +66,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/degrees.xml">GLSL degrees man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/degrees.xml">GLSL degrees man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType degrees(genType const & radians); GLM_FUNC_DECL vecType<T, P> degrees(vecType<T, P> const & radians);
/// The standard trigonometric sine function. /// The standard trigonometric sine function.
/// The values returned by this function will range from [-1, 1]. /// The values returned by this function will range from [-1, 1].
@ -70,8 +76,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sin.xml">GLSL sin man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sin.xml">GLSL sin man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType sin(genType const & angle); GLM_FUNC_DECL vecType<T, P> sin(vecType<T, P> const & angle);
/// The standard trigonometric cosine function. /// The standard trigonometric cosine function.
/// The values returned by this function will range from [-1, 1]. /// The values returned by this function will range from [-1, 1].
@ -80,8 +86,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cos.xml">GLSL cos man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cos.xml">GLSL cos man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType cos(genType const & angle); GLM_FUNC_DECL vecType<T, P> cos(vecType<T, P> const & angle);
/// The standard trigonometric tangent function. /// The standard trigonometric tangent function.
/// ///
@ -89,8 +95,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tan.xml">GLSL tan man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tan.xml">GLSL tan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType tan(genType const & angle); GLM_FUNC_DECL vecType<T, P> tan(vecType<T, P> const & angle);
/// Arc sine. Returns an angle whose sine is x. /// Arc sine. Returns an angle whose sine is x.
/// The range of values returned by this function is [-PI/2, PI/2]. /// The range of values returned by this function is [-PI/2, PI/2].
@ -100,8 +106,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asin.xml">GLSL asin man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asin.xml">GLSL asin man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType asin(genType const & x); GLM_FUNC_DECL vecType<T, P> asin(vecType<T, P> const & x);
/// Arc cosine. Returns an angle whose sine is x. /// Arc cosine. Returns an angle whose sine is x.
/// The range of values returned by this function is [0, PI]. /// The range of values returned by this function is [0, PI].
@ -111,8 +117,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acos.xml">GLSL acos man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acos.xml">GLSL acos man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType acos(genType const & x); GLM_FUNC_DECL vecType<T, P> acos(vecType<T, P> const & x);
/// Arc tangent. Returns an angle whose tangent is y/x. /// Arc tangent. Returns an angle whose tangent is y/x.
/// The signs of x and y are used to determine what /// The signs of x and y are used to determine what
@ -124,8 +130,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType atan(genType const & y, genType const & x); GLM_FUNC_DECL vecType<T, P> atan(vecType<T, P> const & y, vecType<T, P> const & x);
/// Arc tangent. Returns an angle whose tangent is y_over_x. /// Arc tangent. Returns an angle whose tangent is y_over_x.
/// The range of values returned by this function is [-PI/2, PI/2]. /// The range of values returned by this function is [-PI/2, PI/2].
@ -134,8 +140,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType atan(genType const & y_over_x); GLM_FUNC_DECL vecType<T, P> atan(vecType<T, P> const & y_over_x);
/// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2 /// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2
/// ///
@ -143,8 +149,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sinh.xml">GLSL sinh man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sinh.xml">GLSL sinh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType sinh(genType const & angle); GLM_FUNC_DECL vecType<T, P> sinh(vecType<T, P> const & angle);
/// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2 /// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2
/// ///
@ -152,8 +158,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cosh.xml">GLSL cosh man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cosh.xml">GLSL cosh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType cosh(genType const & angle); GLM_FUNC_DECL vecType<T, P> cosh(vecType<T, P> const & angle);
/// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle) /// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle)
/// ///
@ -161,8 +167,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tanh.xml">GLSL tanh man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tanh.xml">GLSL tanh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType tanh(genType const & angle); GLM_FUNC_DECL vecType<T, P> tanh(vecType<T, P> const & angle);
/// Arc hyperbolic sine; returns the inverse of sinh. /// Arc hyperbolic sine; returns the inverse of sinh.
/// ///
@ -170,8 +176,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asinh.xml">GLSL asinh man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asinh.xml">GLSL asinh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType asinh(genType const & x); GLM_FUNC_DECL vecType<T, P> asinh(vecType<T, P> const & x);
/// Arc hyperbolic cosine; returns the non-negative inverse /// Arc hyperbolic cosine; returns the non-negative inverse
/// of cosh. Results are undefined if x < 1. /// of cosh. Results are undefined if x < 1.
@ -180,8 +186,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acosh.xml">GLSL acosh man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acosh.xml">GLSL acosh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType acosh(genType const & x); GLM_FUNC_DECL vecType<T, P> acosh(vecType<T, P> const & x);
/// Arc hyperbolic tangent; returns the inverse of tanh. /// Arc hyperbolic tangent; returns the inverse of tanh.
/// Results are undefined if abs(x) >= 1. /// Results are undefined if abs(x) >= 1.
@ -190,14 +196,10 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atanh.xml">GLSL atanh man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atanh.xml">GLSL atanh man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a>
template <typename genType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL genType atanh(genType const & x); GLM_FUNC_DECL vecType<T, P> atanh(vecType<T, P> const & x);
/// @} /// @}
}//namespace glm }//namespace glm
#include "func_trigonometric.inl" #include "func_trigonometric.inl"
#endif//GLM_CORE_func_trigonometric

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_trigonometric.inl /// @file glm/detail/func_trigonometric.inl
/// @date 2008-08-03 / 2011-06-15 /// @date 2008-08-03 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -34,213 +38,187 @@ namespace glm
{ {
// radians // radians
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType radians GLM_FUNC_QUALIFIER genType radians(genType degrees)
(
genType const & degrees
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'radians' only accept floating-point input"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'radians' only accept floating-point input");
return degrees * genType(0.01745329251994329576923690768489); return degrees * static_cast<genType>(0.01745329251994329576923690768489);
} }
VECTORIZE_VEC(radians) template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> radians(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(radians, v);
}
// degrees // degrees
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType degrees GLM_FUNC_QUALIFIER genType degrees(genType radians)
(
genType const & radians
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'degrees' only accept floating-point input"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'degrees' only accept floating-point input");
return radians * genType(57.295779513082320876798154814105); return radians * static_cast<genType>(57.295779513082320876798154814105);
} }
VECTORIZE_VEC(degrees) template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> degrees(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(degrees, v);
}
// sin // sin
template <typename genType> using ::std::sin;
GLM_FUNC_QUALIFIER genType sin
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & angle GLM_FUNC_QUALIFIER vecType<T, P> sin(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'sin' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(sin, v);
return genType(::std::sin(angle));
} }
VECTORIZE_VEC(sin)
// cos // cos
template <typename genType> using std::cos;
GLM_FUNC_QUALIFIER genType cos(genType const & angle)
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> cos(vecType<T, P> const & v)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'cos' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(cos, v);
return genType(::std::cos(angle));
} }
VECTORIZE_VEC(cos)
// tan // tan
template <typename genType> using std::tan;
GLM_FUNC_QUALIFIER genType tan
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & angle GLM_FUNC_QUALIFIER vecType<T, P> tan(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'tan' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(tan, v);
return genType(::std::tan(angle));
} }
VECTORIZE_VEC(tan)
// asin // asin
template <typename genType> using std::asin;
GLM_FUNC_QUALIFIER genType asin
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & x GLM_FUNC_QUALIFIER vecType<T, P> asin(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asin' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(asin, v);
return genType(::std::asin(x));
} }
VECTORIZE_VEC(asin)
// acos // acos
template <typename genType> using std::acos;
GLM_FUNC_QUALIFIER genType acos
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & x GLM_FUNC_QUALIFIER vecType<T, P> acos(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acos' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(acos, v);
return genType(::std::acos(x));
} }
VECTORIZE_VEC(acos)
// atan // atan
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER genType atan GLM_FUNC_QUALIFIER genType atan(genType const & y, genType const & x)
(
genType const & y,
genType const & x
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atan' only accept floating-point input"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atan' only accept floating-point input");
return genType(::std::atan2(y, x)); return ::std::atan2(y, x);
} }
VECTORIZE_VEC_VEC(atan) template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> atan(vecType<T, P> const & a, vecType<T, P> const & b)
template <typename genType>
GLM_FUNC_QUALIFIER genType atan
(
genType const & x
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atan' only accept floating-point input"); return detail::functor2<T, P, vecType>::call(atan2, a, b);
return genType(::std::atan(x));
} }
VECTORIZE_VEC(atan) using std::atan;
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> atan(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(atan, v);
}
// sinh // sinh
template <typename genType> using std::sinh;
GLM_FUNC_QUALIFIER genType sinh
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & angle GLM_FUNC_QUALIFIER vecType<T, P> sinh(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'sinh' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(sinh, v);
return genType(std::sinh(angle));
} }
VECTORIZE_VEC(sinh)
// cosh // cosh
template <typename genType> using std::cosh;
GLM_FUNC_QUALIFIER genType cosh
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & angle GLM_FUNC_QUALIFIER vecType<T, P> cosh(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'cosh' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(cosh, v);
return genType(std::cosh(angle));
} }
VECTORIZE_VEC(cosh)
// tanh // tanh
template <typename genType> using std::tanh;
GLM_FUNC_QUALIFIER genType tanh
( template <typename T, precision P, template <typename, precision> class vecType>
genType const & angle GLM_FUNC_QUALIFIER vecType<T, P> tanh(vecType<T, P> const & v)
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'tanh' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(tanh, v);
return genType(std::tanh(angle));
} }
VECTORIZE_VEC(tanh)
// asinh // asinh
template <typename genType> # if GLM_HAS_CXX11_STL
GLM_FUNC_QUALIFIER genType asinh using std::asinh;
( # else
genType const & x template <typename genType>
) GLM_FUNC_QUALIFIER genType asinh(genType const & x)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asinh' only accept floating-point input"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asinh' only accept floating-point input");
return (x < genType(0) ? genType(-1) : (x > genType(0) ? genType(1) : genType(0))) * log(abs(x) + sqrt(genType(1) + x * x));
}
VECTORIZE_VEC(asinh) return (x < static_cast<genType>(0) ? static_cast<genType>(-1) : (x > static_cast<genType>(0) ? static_cast<genType>(1) : static_cast<genType>(0))) * log(abs(x) + sqrt(static_cast<genType>(1) + x * x));
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> asinh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(asinh, v);
}
// acosh // acosh
template <typename genType> # if GLM_HAS_CXX11_STL
GLM_FUNC_QUALIFIER genType acosh using std::acosh;
( # else
genType const & x template <typename genType>
) GLM_FUNC_QUALIFIER genType acosh(genType const & x)
{
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acosh' only accept floating-point input");
if(x < static_cast<genType>(1))
return static_cast<genType>(0);
return log(x + sqrt(x * x - static_cast<genType>(1)));
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> acosh(vecType<T, P> const & v)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acosh' only accept floating-point input"); return detail::functor1<T, T, P, vecType>::call(acosh, v);
if(x < genType(1))
return genType(0);
return log(x + sqrt(x * x - genType(1)));
} }
VECTORIZE_VEC(acosh)
// atanh // atanh
template <typename genType> # if GLM_HAS_CXX11_STL
GLM_FUNC_QUALIFIER genType atanh using std::atanh;
( # else
genType const & x template <typename genType>
) GLM_FUNC_QUALIFIER genType atanh(genType const & x)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atanh' only accept floating-point input"); GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atanh' only accept floating-point input");
if(abs(x) >= genType(1)) if(abs(x) >= static_cast<genType>(1))
return 0; return 0;
return genType(0.5) * log((genType(1) + x) / (genType(1) - x)); return static_cast<genType>(0.5) * log((static_cast<genType>(1) + x) / (static_cast<genType>(1) - x));
}
# endif
template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<T, P> atanh(vecType<T, P> const & v)
{
return detail::functor1<T, T, P, vecType>::call(atanh, v);
} }
VECTORIZE_VEC(atanh)
}//namespace glm }//namespace glm

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_vector_relational.hpp /// @file glm/detail/func_vector_relational.hpp
/// @date 2008-08-03 / 2011-06-15 /// @date 2008-08-03 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/// ///
@ -38,14 +42,11 @@
/// call must match. /// call must match.
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef GLM_CORE_func_vector_relational #pragma once
#define GLM_CORE_func_vector_relational
#include "precision.hpp" #include "precision.hpp"
#include "setup.hpp" #include "setup.hpp"
#if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER <= GLM_COMPILER_VC10)) // Workaround a Visual C++ bug
namespace glm namespace glm
{ {
/// @addtogroup core_func_vector_relational /// @addtogroup core_func_vector_relational
@ -57,9 +58,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThan.xml">GLSL lessThan man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThan.xml">GLSL lessThan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
// TODO: Mismatched template <typename T, precision P, template <typename, precision> class vecType>
//template <typename T, precision P, template <typename, precision> class vecType> GLM_FUNC_DECL vecType<bool, P> lessThan(vecType<T, P> const & x, vecType<T, P> const & y);
//GLM_FUNC_DECL typename vecType<T, P>::bool_type lessThan(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x <= y. /// Returns the component-wise comparison of result x <= y.
/// ///
@ -68,7 +68,7 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThanEqual.xml">GLSL lessThanEqual man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThanEqual.xml">GLSL lessThanEqual man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename vecType<T, P>::bool_type lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y); GLM_FUNC_DECL vecType<bool, P> lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x > y. /// Returns the component-wise comparison of result x > y.
/// ///
@ -77,7 +77,7 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThan.xml">GLSL greaterThan man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThan.xml">GLSL greaterThan man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename vecType<T, P>::bool_type greaterThan(vecType<T, P> const & x, vecType<T, P> const & y); GLM_FUNC_DECL vecType<bool, P> greaterThan(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x >= y. /// Returns the component-wise comparison of result x >= y.
/// ///
@ -86,7 +86,7 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThanEqual.xml">GLSL greaterThanEqual man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThanEqual.xml">GLSL greaterThanEqual man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename vecType<T, P>::bool_type greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y); GLM_FUNC_DECL vecType<bool, P> greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x == y. /// Returns the component-wise comparison of result x == y.
/// ///
@ -94,9 +94,8 @@ namespace glm
/// ///
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/equal.xml">GLSL equal man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/equal.xml">GLSL equal man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
//TODO: conflicts with definision template <typename T, precision P, template <typename, precision> class vecType>
//template <typename T, precision P, template <typename, precision> class vecType> GLM_FUNC_DECL vecType<bool, P> equal(vecType<T, P> const & x, vecType<T, P> const & y);
//GLM_FUNC_DECL typename vecType<T, P>::bool_type equal(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns the component-wise comparison of result x != y. /// Returns the component-wise comparison of result x != y.
/// ///
@ -105,7 +104,7 @@ namespace glm
/// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/notEqual.xml">GLSL notEqual man page</a> /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/notEqual.xml">GLSL notEqual man page</a>
/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a>
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL typename vecType<T, P>::bool_type notEqual(vecType<T, P> const & x, vecType<T, P> const & y); GLM_FUNC_DECL vecType<bool, P> notEqual(vecType<T, P> const & x, vecType<T, P> const & y);
/// Returns true if any component of x is true. /// Returns true if any component of x is true.
/// ///
@ -138,8 +137,4 @@ namespace glm
/// @} /// @}
}//namespace glm }//namespace glm
#endif
#include "func_vector_relational.inl" #include "func_vector_relational.inl"
#endif//GLM_CORE_func_vector_relational

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -21,7 +25,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/func_vector_relational.inl /// @file glm/detail/func_vector_relational.inl
/// @date 2008-08-03 / 2011-09-09 /// @date 2008-08-03 / 2011-09-09
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -31,100 +35,68 @@
namespace glm namespace glm
{ {
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER typename vecType<T, P>::bool_type lessThan GLM_FUNC_QUALIFIER vecType<bool, P> lessThan(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, assert(detail::component_count(x) == detail::component_count(y));
"Invalid template instantiation of 'lessThan', GLM vector types required floating-point or integer value types vectors");
assert(x.length() == y.length());
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < x.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(x); ++i)
Result[i] = x[i] < y[i]; Result[i] = x[i] < y[i];
return Result; return Result;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER typename vecType<T, P>::bool_type lessThanEqual GLM_FUNC_QUALIFIER vecType<bool, P> lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, assert(detail::component_count(x) == detail::component_count(y));
"Invalid template instantiation of 'lessThanEqual', GLM vector types required floating-point or integer value types vectors");
assert(x.length() == y.length());
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < x.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(x); ++i)
Result[i] = x[i] <= y[i]; Result[i] = x[i] <= y[i];
return Result; return Result;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER typename vecType<T, P>::bool_type greaterThan GLM_FUNC_QUALIFIER vecType<bool, P> greaterThan(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, assert(detail::component_count(x) == detail::component_count(y));
"Invalid template instantiation of 'greaterThan', GLM vector types required floating-point or integer value types vectors");
assert(x.length() == y.length());
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < x.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(x); ++i)
Result[i] = x[i] > y[i]; Result[i] = x[i] > y[i];
return Result; return Result;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER typename vecType<T, P>::bool_type greaterThanEqual GLM_FUNC_QUALIFIER vecType<bool, P> greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, assert(detail::component_count(x) == detail::component_count(y));
"Invalid template instantiation of 'greaterThanEqual', GLM vector types required floating-point or integer value types vectors");
assert(x.length() == y.length());
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < x.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(x); ++i)
Result[i] = x[i] >= y[i]; Result[i] = x[i] >= y[i];
return Result; return Result;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER typename vecType<T, P>::bool_type equal GLM_FUNC_QUALIFIER vecType<bool, P> equal(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
assert(x.length() == y.length()); assert(detail::component_count(x) == detail::component_count(y));
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < x.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(x); ++i)
Result[i] = x[i] == y[i]; Result[i] = x[i] == y[i];
return Result; return Result;
} }
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER typename vecType<T, P>::bool_type notEqual GLM_FUNC_QUALIFIER vecType<bool, P> notEqual(vecType<T, P> const & x, vecType<T, P> const & y)
(
vecType<T, P> const & x,
vecType<T, P> const & y
)
{ {
assert(x.length() == y.length()); assert(detail::component_count(x) == detail::component_count(y));
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < x.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(x); ++i)
Result[i] = x[i] != y[i]; Result[i] = x[i] != y[i];
return Result; return Result;
} }
@ -133,7 +105,7 @@ namespace glm
GLM_FUNC_QUALIFIER bool any(vecType<bool, P> const & v) GLM_FUNC_QUALIFIER bool any(vecType<bool, P> const & v)
{ {
bool Result = false; bool Result = false;
for(int i = 0; i < v.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(v); ++i)
Result = Result || v[i]; Result = Result || v[i];
return Result; return Result;
} }
@ -142,7 +114,7 @@ namespace glm
GLM_FUNC_QUALIFIER bool all(vecType<bool, P> const & v) GLM_FUNC_QUALIFIER bool all(vecType<bool, P> const & v)
{ {
bool Result = true; bool Result = true;
for(int i = 0; i < v.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(v); ++i)
Result = Result && v[i]; Result = Result && v[i];
return Result; return Result;
} }
@ -150,8 +122,8 @@ namespace glm
template <precision P, template <typename, precision> class vecType> template <precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER vecType<bool, P> not_(vecType<bool, P> const & v) GLM_FUNC_QUALIFIER vecType<bool, P> not_(vecType<bool, P> const & v)
{ {
typename vecType<bool, P>::bool_type Result(vecType<bool, P>::_null); vecType<bool, P> Result(uninitialize);
for(int i = 0; i < v.length(); ++i) for(detail::component_count_t i = 0; i < detail::component_count(v); ++i)
Result[i] = !v[i]; Result[i] = !v[i];
return Result; return Result;
} }

View File

@ -12,6 +12,10 @@
/// The above copyright notice and this permission notice shall be included in /// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software. /// 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 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -30,11 +34,9 @@
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <glm/gtx/dual_quaternion.hpp> #include <glm/gtx/dual_quaternion.hpp>
namespace glm{ namespace glm
namespace detail
{ {
// tvec1 type explicit instantiation // tvec1 type explicit instantiation
/*
template struct tvec1<uint8, lowp>; template struct tvec1<uint8, lowp>;
template struct tvec1<uint16, lowp>; template struct tvec1<uint16, lowp>;
template struct tvec1<uint32, lowp>; template struct tvec1<uint32, lowp>;
@ -43,7 +45,6 @@ template struct tvec1<int8, lowp>;
template struct tvec1<int16, lowp>; template struct tvec1<int16, lowp>;
template struct tvec1<int32, lowp>; template struct tvec1<int32, lowp>;
template struct tvec1<int64, lowp>; template struct tvec1<int64, lowp>;
template struct tvec1<float16, lowp>;
template struct tvec1<float32, lowp>; template struct tvec1<float32, lowp>;
template struct tvec1<float64, lowp>; template struct tvec1<float64, lowp>;
@ -55,7 +56,6 @@ template struct tvec1<int8, mediump>;
template struct tvec1<int16, mediump>; template struct tvec1<int16, mediump>;
template struct tvec1<int32, mediump>; template struct tvec1<int32, mediump>;
template struct tvec1<int64, mediump>; template struct tvec1<int64, mediump>;
template struct tvec1<float16, mediump>;
template struct tvec1<float32, mediump>; template struct tvec1<float32, mediump>;
template struct tvec1<float64, mediump>; template struct tvec1<float64, mediump>;
@ -67,10 +67,9 @@ template struct tvec1<int8, highp>;
template struct tvec1<int16, highp>; template struct tvec1<int16, highp>;
template struct tvec1<int32, highp>; template struct tvec1<int32, highp>;
template struct tvec1<int64, highp>; template struct tvec1<int64, highp>;
template struct tvec1<float16, highp>;
template struct tvec1<float32, highp>; template struct tvec1<float32, highp>;
template struct tvec1<float64, highp>; template struct tvec1<float64, highp>;
*/
// tvec2 type explicit instantiation // tvec2 type explicit instantiation
template struct tvec2<uint8, lowp>; template struct tvec2<uint8, lowp>;
template struct tvec2<uint16, lowp>; template struct tvec2<uint16, lowp>;
@ -283,6 +282,5 @@ template struct tdualquat<float64, mediump>;
template struct tdualquat<float32, highp>; template struct tdualquat<float32, highp>;
template struct tdualquat<float64, highp>; template struct tdualquat<float64, highp>;
}//namespace detail
}//namespace glm }//namespace glm

View File

@ -21,13 +21,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_common.hpp /// @file glm/detail/intrinsic_common.hpp
/// @date 2009-05-11 / 2011-06-15 /// @date 2009-05-11 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_detail_intrinsic_common #pragma once
#define glm_detail_intrinsic_common
#include "setup.hpp" #include "setup.hpp"
@ -86,4 +85,3 @@ namespace detail
#include "intrinsic_common.inl" #include "intrinsic_common.inl"
#endif//GLM_ARCH #endif//GLM_ARCH
#endif//glm_detail_intrinsic_common

View File

@ -21,7 +21,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_common.inl /// @file glm/detail/intrinsic_common.inl
/// @date 2009-05-08 / 2011-06-15 /// @date 2009-05-08 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -21,13 +21,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_exponential.hpp /// @file glm/detail/intrinsic_exponential.hpp
/// @date 2009-05-11 / 2011-06-15 /// @date 2009-05-11 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_detail_intrinsic_exponential #pragma once
#define glm_detail_intrinsic_exponential
#include "setup.hpp" #include "setup.hpp"
@ -76,4 +75,3 @@ GLM_FUNC_QUALIFIER __m128 sse_normalize_fast_ps( float * RESTRICT vOut, float *
}//namespace glm }//namespace glm
#endif//GLM_ARCH #endif//GLM_ARCH
#endif//glm_detail_intrinsic_exponential

View File

@ -21,7 +21,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_exponential.inl /// @file glm/detail/intrinsic_exponential.inl
/// @date 2011-06-15 / 2011-06-15 /// @date 2011-06-15 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -21,13 +21,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_geometric.hpp /// @file glm/detail/intrinsic_geometric.hpp
/// @date 2009-05-08 / 2011-06-15 /// @date 2009-05-08 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_core_intrinsic_geometric #pragma once
#define glm_core_intrinsic_geometric
#include "setup.hpp" #include "setup.hpp"
@ -73,4 +72,3 @@ namespace detail
#include "intrinsic_geometric.inl" #include "intrinsic_geometric.inl"
#endif//GLM_ARCH #endif//GLM_ARCH
#endif//glm_core_intrinsic_geometric

View File

@ -21,7 +21,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_geometric.inl /// @file glm/detail/intrinsic_geometric.inl
/// @date 2009-05-08 / 2011-06-15 /// @date 2009-05-08 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -32,32 +32,33 @@ namespace detail{
//length //length
GLM_FUNC_QUALIFIER __m128 sse_len_ps(__m128 x) GLM_FUNC_QUALIFIER __m128 sse_len_ps(__m128 x)
{ {
__m128 dot0 = sse_dot_ps(x, x); __m128 dot0 = sse_dot_ps(x, x);
__m128 sqt0 = _mm_sqrt_ps(dot0); __m128 sqt0 = _mm_sqrt_ps(dot0);
return sqt0; return sqt0;
} }
//distance //distance
GLM_FUNC_QUALIFIER __m128 sse_dst_ps(__m128 p0, __m128 p1) GLM_FUNC_QUALIFIER __m128 sse_dst_ps(__m128 p0, __m128 p1)
{ {
__m128 sub0 = _mm_sub_ps(p0, p1); __m128 sub0 = _mm_sub_ps(p0, p1);
__m128 len0 = sse_len_ps(sub0); __m128 len0 = sse_len_ps(sub0);
return len0; return len0;
} }
//dot //dot
GLM_FUNC_QUALIFIER __m128 sse_dot_ps(__m128 v1, __m128 v2) GLM_FUNC_QUALIFIER __m128 sse_dot_ps(__m128 v1, __m128 v2)
{ {
# if((GLM_ARCH & GLM_ARCH_AVX) == GLM_ARCH_AVX)
return _mm_dp_ps(v1, v2, 0xff); # if(GLM_ARCH & GLM_ARCH_AVX)
# else return _mm_dp_ps(v1, v2, 0xff);
__m128 mul0 = _mm_mul_ps(v1, v2); # else
__m128 swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1)); __m128 mul0 = _mm_mul_ps(v1, v2);
__m128 add0 = _mm_add_ps(mul0, swp0); __m128 swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1));
__m128 swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3)); __m128 add0 = _mm_add_ps(mul0, swp0);
__m128 add1 = _mm_add_ps(add0, swp1); __m128 swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3));
return add1; __m128 add1 = _mm_add_ps(add0, swp1);
# endif return add1;
# endif
} }
// SSE1 // SSE1

View File

@ -21,13 +21,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_integer.hpp /// @file glm/detail/intrinsic_integer.hpp
/// @date 2009-05-11 / 2011-06-15 /// @date 2009-05-11 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_detail_intrinsic_integer #pragma once
#define glm_detail_intrinsic_integer
#include "glm/glm.hpp" #include "glm/glm.hpp"
@ -47,4 +46,3 @@ namespace detail
#include "intrinsic_integer.inl" #include "intrinsic_integer.inl"
#endif//GLM_ARCH #endif//GLM_ARCH
#endif//glm_detail_intrinsic_integer

View File

@ -21,7 +21,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_integer.inl /// @file glm/detail/intrinsic_integer.inl
/// @date 2009-05-08 / 2011-06-15 /// @date 2009-05-08 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -21,13 +21,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_common.hpp /// @file glm/detail/intrinsic_common.hpp
/// @date 2009-06-05 / 2011-06-15 /// @date 2009-06-05 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_detail_intrinsic_matrix #pragma once
#define glm_detail_intrinsic_matrix
#include "setup.hpp" #include "setup.hpp"
@ -66,4 +65,3 @@ namespace detail
#include "intrinsic_matrix.inl" #include "intrinsic_matrix.inl"
#endif//GLM_ARCH #endif//GLM_ARCH
#endif//glm_detail_intrinsic_matrix

View File

@ -21,7 +21,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_common.inl /// @file glm/detail/intrinsic_common.inl
/// @date 2009-06-05 / 2011-06-15 /// @date 2009-06-05 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -448,7 +448,7 @@ GLM_FUNC_QUALIFIER __m128 sse_detd_ps
__m128 MulC = _mm_mul_ps(Swp2C, Swp3C); __m128 MulC = _mm_mul_ps(Swp2C, Swp3C);
__m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC);
//detail::tvec4<T, P> DetCof( //tvec4<T, P> DetCof(
// + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
// - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
// + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
@ -514,7 +514,7 @@ GLM_FUNC_QUALIFIER __m128 sse_det_ps
__m128 MulC = _mm_mul_ps(Swp2C, Swp3C); __m128 MulC = _mm_mul_ps(Swp2C, Swp3C);
__m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC);
//detail::tvec4<T, P> DetCof( //tvec4<T, P> DetCof(
// + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
// - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
// + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
@ -1003,7 +1003,7 @@ GLM_FUNC_QUALIFIER void sse_rotate_ps(__m128 const in[4], float Angle, float con
__m128 Sin0 = _mm_set_ss(s); __m128 Sin0 = _mm_set_ss(s);
__m128 SinA = _mm_shuffle_ps(Sin0, Sin0, _MM_SHUFFLE(0, 0, 0, 0)); __m128 SinA = _mm_shuffle_ps(Sin0, Sin0, _MM_SHUFFLE(0, 0, 0, 0));
// detail::tvec3<T, P> temp = (valType(1) - c) * axis; // tvec3<T, P> temp = (valType(1) - c) * axis;
__m128 Temp0 = _mm_sub_ps(one, CosA); __m128 Temp0 = _mm_sub_ps(one, CosA);
__m128 Temp1 = _mm_mul_ps(Temp0, AxisC); __m128 Temp1 = _mm_mul_ps(Temp0, AxisC);
@ -1049,7 +1049,7 @@ GLM_FUNC_QUALIFIER void sse_rotate_ps(__m128 const in[4], float Angle, float con
Result[2] = TmpC4; Result[2] = TmpC4;
Result[3] = _mm_set_ps(1, 0, 0, 0); Result[3] = _mm_set_ps(1, 0, 0, 0);
//detail::tmat4x4<valType> Result(detail::tmat4x4<valType>::_null); //tmat4x4<valType> Result(uninitialize);
//Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; //Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2];
//Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; //Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2];
//Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; //Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2];

View File

@ -21,13 +21,12 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_trigonometric.hpp /// @file glm/detail/intrinsic_trigonometric.hpp
/// @date 2009-06-09 / 2011-06-15 /// @date 2009-06-09 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
#ifndef glm_detail_intrinsic_trigonometric #pragma once
#define glm_detail_intrinsic_trigonometric
#include "setup.hpp" #include "setup.hpp"
@ -45,4 +44,3 @@ namespace detail
#include "intrinsic_trigonometric.inl" #include "intrinsic_trigonometric.inl"
#endif//GLM_ARCH #endif//GLM_ARCH
#endif//glm_detail_intrinsic_trigonometric

View File

@ -21,7 +21,7 @@
/// THE SOFTWARE. /// THE SOFTWARE.
/// ///
/// @ref core /// @ref core
/// @file glm/core/intrinsic_trigonometric.inl /// @file glm/detail/intrinsic_trigonometric.inl
/// @date 2011-06-15 / 2011-06-15 /// @date 2011-06-15 / 2011-06-15
/// @author Christophe Riccio /// @author Christophe Riccio
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

Some files were not shown because too many files have changed in this diff Show More