Compare commits

..

36 Commits

Author SHA1 Message Date
KimLS 46cb96a026 Merchant buying in flux but it works better now 2015-06-22 23:50:39 -07:00
KimLS bbc3733c3a Compiles again, had to disable a new piece of code though 2015-06-21 01:45:42 -07:00
KimLS 5995afa1b8 Merge from master, probably wont compile but will fix that soon 2015-06-21 01:38:19 -07:00
KimLS ff3cb9fc54 Merge branch 'master' into inv2 2015-04-07 16:29:07 -07:00
KimLS 56e7d1b0dc Okay finally merchant buying works -.- 2015-04-07 16:28:28 -07:00
KimLS 7341ecc185 Some work on implementing slot selection 2015-04-06 16:53:12 -07:00
KimLS 279ed8d86c Merge branch 'master' into inv2 2015-03-25 15:55:16 -07:00
KimLS 21ce5c6daa Merge plus some work on fixing stacking for merchants. 2015-03-15 14:02:13 -07:00
KimLS 00af95502e Wip merchant stuff, summoning should work now. 2015-03-06 15:53:15 -08:00
KimLS dda8ae4803 Basic item summoning, fix for saving not working 100 pct, deletion works, cursor queue should work too. 2015-03-05 18:03:37 -08:00
KimLS 316aa5ef73 Added current table to utils sql, though not formatted correctly yet since it's heavily wip 2015-03-04 19:35:10 -08:00
KimLS 9fcdf5367e Swap saving now works correctly except for cursor items which wont be reloaded correctly as we don't send cursor on login yet. Also added check for bag into another bag src bag needs to have nothing in it first. 2015-03-04 19:33:01 -08:00
KimLS 972d3d8874 Fix for swapping a stack with another item that is not of the same stack size. Added some console visualization for testing and added basics of data modeling for inventory, saving soon. 2015-03-02 19:38:57 -08:00
KimLS abc5ddc5f8 Inventory Swap implemented and passes tests, though still want to verify it a bit more also does not yet save but that's next. Fixed a crash in memory buffer too. 2015-03-02 00:44:28 -08:00
KimLS 14b5a8d817 Merge from master 2015-02-28 17:59:32 -08:00
KimLS 20cbe4af44 More work on swapping, almost there just need to write code for stack split/move/combining 2015-02-28 17:56:01 -08:00
KimLS 7870bf103a Working on can equip, putting it in the general inventory class. 2015-02-27 02:40:44 -08:00
KimLS 18b4d068ea Early stages of swapping requirements in, should check for basic validity and equipable status 2015-02-26 22:09:29 -08:00
KimLS 568938d003 Merge from master 2015-02-25 19:39:48 -08:00
KimLS 215861dd86 Added serialization differentiation 2015-02-25 19:36:10 -08:00
KimLS c62cff1ce7 Fixed test again. 2015-02-24 00:38:49 -08:00
KimLS 69612b44d4 OP_MoveItem encode/decode for RoF2, disabled other patches for now (until i get rof2 packets and mechanics working well enough to go back and fix those) 2015-02-23 22:45:50 -08:00
KimLS 8bce7893ed BulkSendItems now works on RoF2 2015-02-23 17:33:21 -08:00
KimLS 4e4168852b Going to start work on SerializingItems for bulk inv sends 2015-02-23 01:50:50 -08:00
KimLS ca278d029e Fix for Memory Buffer stuff, have yet to compile so not sure if that's enough. Partial work on RoF inventory bulk send 2015-02-22 19:38:44 -08:00
KimLS 273574d4db Added memory buffer plus tests to project, going to use it for item serialization 2015-02-22 15:37:11 -08:00
KimLS c71a5888ff Merge branch 'master' into inv2 2015-02-22 14:27:49 -08:00
KimLS b3c53e5907 Merge master, fix conflicts 2015-02-21 15:30:15 -08:00
KimLS f511862004 Working working working on getting the basics setup 2015-02-21 15:21:45 -08:00
KimLS a90e9cf4c6 Refactoring 2015-02-20 20:15:58 -08:00
KimLS 2d617f0ea7 Get/Put item implementation + tests 2015-02-20 16:24:32 -08:00
KimLS 551c0ef368 Basic arch work, doesn't make a ton of sense yet but it will 2015-02-19 23:34:43 -08:00
KimLS a5274b9b6e InventoryOld in client has been unhooked from loading/saving 2015-02-18 20:29:58 -08:00
KimLS fc2492a859 Merge from master, fixed conflicts 2015-02-18 13:18:21 -08:00
KimLS 701e194ece Renamed Item_Struct to ItemData 2015-02-17 18:06:22 -08:00
KimLS b75e6308dd Renamed Inventory to InventoryOld 2015-02-17 13:42:21 -08:00
325 changed files with 21177 additions and 88983 deletions
+8 -10
View File
@@ -1,18 +1,16 @@
language: cpp
compiler: gcc
sudo: false
addons:
apt:
packages:
- libmysqlclient-dev
- libperl-dev
- libboost-dev
- liblua5.1-0-dev
- zlib1g-dev
before_install:
- sudo apt-get update -qq
- sudo apt-get install -y libmysqlclient-dev libperl-dev libboost-dev liblua5.1-0-dev zlib1g-dev
script:
- cmake -G "Unix Makefiles" -DEQEMU_BUILD_TESTS=ON -DEQEMU_ENABLE_BOTS=ON
- make -j8
- make
- ./bin/tests
branches:
only:
- master
- stable
notifications:
email: false
irc:
-6
View File
@@ -331,14 +331,8 @@ IF(EQEMU_BUILD_LUA)
ADD_SUBDIRECTORY(luabind)
ENDIF(EQEMU_BUILD_LUA)
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/debug_utils/include")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/detour/include")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/detour_tile_cache/include")
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/recast/recast/include")
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(recast)
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
IF(EQEMU_BUILD_SERVER)
ADD_SUBDIRECTORY(shared_memory)
-251
View File
@@ -1,256 +1,5 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 01/13/2016 ==
Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog.
- Just target the person whose flag you want to refresh and type #flag.
Uleat: Added itemlink functionality to the #summonitem command. Current use is limited to extracting the item id from the link.
- Invoking by item link '#summonitem Arrow' produces the same result as by item id '#summonitem 8005'
== 01/12/2016 ==
Athrogate: Adding ClearCompassMark() to Lua.
- Lua didn't have ClearCompassMark(). Perl already had this.
== 01/12/2016 ==
Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player (thanks Natedog!)
== 12/29/2015 ==
Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true
- When a zone boots, it will spawn an invisible npc by the name of zone_controller
- Lua and Perl scripts can be represented with this npc as zone_controller.pl/lua
- This NPC's ID is ruled be define ZONE_CONTROLLER_NPC_ID 10
- Two EVENT's uniquely are handled with this NPC/controller (They only work with the zone_controller NPC)
- EVENT_SPAWN_ZONE :: All NPC spawns in the zone trigger the controller and pass the following variables:
$spawned_entity_id
$spawned_npc_id
- EVENT_DEATH_ZONE :: All NPC deaths in the zone trigger the controller event and pass the following variables:
$killer_id
$killer_damage
$killer_spell
$killer_skill
$killed_npc_id
== 12/28/2015 ==
Kinglykrab: Added GetInstanceTimer() to Perl and Lua.
- Added GetInstanceTimerByID(instance_id) to Perl and Lua.
- Note: If you do not provide an instance id in the method it defaults to instance id 0 and returns 0 for time remaining.
- Added UpdateZoneHeader(type, value) to Perl and Lua.
- Note: UpdateZoneHeader allows you to manipulate fog color, fog density, and many other zone header settings on the fly in Perl and Lua.
== 12/21/2015 ==
Natedog: Updated item table fields and added a few missing fields for evolving items
-DO NOT implement Heirloom items till the inventory code is fixed to allow placing NO DROP
items in your shared bank. (but item field located on items table)
-NYI - SkillModMax: Max skill point modification from the percent mods. EX:
100% 2HSlashing (Max 50) - can only increase 2hslash by 50 MAX! (item field located though)
Kinglykrab: Added GetMeleeMitigation() for NPCs and Clients in Perl and Lua.
- This allows you to check total item, spell, and AA melee mitigation contribution.
== 12/19/2015 ==
Kinglykrab: Added many methods to Perl and Lua, list below:
- SeeInvisible()
- SeeInvisibleUndead()
- SeeHide()
- SeeImprovedHide()
- GetNimbusEffect1() - returns first nimbus effect
- GetNimbusEffect2() - returns second nimbus effect
- GetNimbusEffect3() - returns third nimbus effect
- IsTargetable()
- HasShieldEquiped()
- HasTwoHandBluntEquiped()
- HasTwoHanderEquiped()
- GetHerosForgeModel() - returns int32 Hero's Forge model
- IsEliteMaterialItem() - returns uint32 Hero's Forge Model
- GetBaseSize() - returns Mob's base size
- HasOwner()
- IsPet()
- HasPet()
- IsSilenced()
- IsAmnesiad()
== 12/16/2015 ==
Noudess: Repaired issue with Bind Wounds on someone else. Message was not coming out on client (hold still) and a bind wounds on someone already binding their wounds would interrupt their bind and make them stand. Also removed some duplicate messaging.
== 12/14/2015 ==
Kinglykrab: Added IsBlind() and IsFeared() functionality to Perl and Lua.
- Note: Both methods are Mob methods and may be used on NPCs or PCs.
Natedog: Added Discipline functions, UpdateInstanceTimer function, and UnmemSpellBySpellID to lua and perl
-Examples: http://wiki.eqemulator.org/i?M=Pastebin&Paste=BJ0ygmNM
== 12/07/2015 ==
Uleat: Command aliases are no longer handled through the command_add() function.
- To add a command alias, edit the database table `command_settings` - here, you will find three columns: `command`, `access` and `aliases`
- Adding command aliases require that the command contain an entry in `command_settings`.`command`
- Only 'real' commands go inside of the command_init() function in command.cpp .. if you wish to add aliases, you must enter them into the database
- 'Real' commands are loaded first .. then any access/alias data is loaded and applied afterwards
- Duplicate aliases will be ignored .. only the first encountered occurrence will be honored - if it does not conflict with an existing command name
- Aliases should not contain whitespace and should be '|' (pipe) delimited
- The restriction on the number of aliases has been removed .. though each alias will still be limited to the access level of the parent command
- If you need need more name space for aliases, simply edit the `command_settings` table and increase the size of the `aliases` column
- The old `commands` table has been renamed to `commands_old` for reference
- All of the current 'standard' commands have been added to the new `command_settings` table
- YOU WILL NEED TO VERIFY/IMPORT OLD ACCESS VALUES AS THIS CHANGE REVERTS ALL COMMAND ACCESS VALUES TO THEIR PEQDB DEFAULTS
== 11/30/2015 ==
Uleat: Changed criteria for a few bots scripts from count to null/not null in hopes of fixing special case failures
== 11/22/2015 ==
Uleat: Fix for loginserver project compile failure
== 11/7/2015 ==
Akkadius: Implemented #repopclose [distance in units] - Used for development purposes, defaults to 500 units
- Real case use: Large zones with 700 NPC's and you are making fast quick tweaks to nearby NPC's you can refresh just the NPC's around you instead of all in the zone
- This can be quite the time saver
- This command will depop all NPC's and only respawn the NPC's that are 500 units around you or unless you specify otherwise
== 11/2/2015 ==
Akkadius: Performance boost (exponential) - Adjusted default idle cast check timers in rules
- Spells:AI_IdleNoSpellMinRecast 500 (Now 6000) 6 seconds
- Spells:AI_IdleNoSpellMaxRecast 2000 (Now 60000) 60 seconds
- Database version 9089 will take care of this update automatically only if you used the default values
- The CPU cost of NPC's checking the entire entity list to cast beneficial spells (Heals/Buffs) becomes extremely high when higher NPC count zones exist (Based off of process profiling)
- Distance checks for every single NPC to every single other NPC who are casting beneficial spells occur every .5 - 2 seconds unless npc_spells dictates other values, which most of the time it does not
- Zones that once fluctuated from 1-8% CPU with no activity (Idle but players present) now idle at .5% based on my testings due
to this change in conjunction with the past few performance commits, these are zones that have 600-800 NPC's in them
- These values normally are overidden by the spells table (npc_spells), fields (idle_no_sp_recast_min, idle_no_sp_recast_max)
== 11/1/2015 ==
Akkadius: Made many performance optimizing oriented code changes in the source
- Added Rate limit the rate in which signals are processed for NPC's (.5 seconds instead of .01 seconds)
Akkadius: Added Perl Export Settings which should heavily reduce the Perl footprint
- Normally when any sub EVENT_ gets triggered, all kinds of variables have to get exported every single time an event is triggered and
this can make Perl very slow when events are triggered constantly
- The two most taxing variable exports are the item variables ($itemcount{} $hasitem{} $oncursor{}) and qglobals ($qglobals{})
- qglobals can pose to be an issue quickly when global qglobals build up, it is highly recommend to use the GetGlobal() and SetGlobal()
methods instead as they don't reference the hashmap $qglobals{} that is rebuilt every single time a sub event is triggered
- A stress test conducted with 10,000 samples shows an excess of time taken to export variables: http://i.imgur.com/NEpW1tS.png
- After the Perl Export Settings table is implemented, and all exports are shut off you see the following test result:
http://i.imgur.com/Du5hth9.png
- The difference of eliminating uneeded exports brings the overhead and footprint of 10,000 triggers from 54 seconds to 2 seconds
- In a 10,000 sample test (10,000 sub event triggers), exporting item variables adds 12 seconds alone, when item variables are only needed in
EVENT_ITEM and EVENT_SAY a majority of the time if at all
- In a 10,000 sample test (10,000 sub event triggers), exporting qglobals with approximately 1,000 global qglobals in the database creates
about 11-20 seconds of delay on its own (Depending on hardware of course)
- I've written a parser that has determined which of these exports are needed in which sub routines and have turned off all of the unneeded
exports in sub routines that do not need them and used it to create the default table that will be installed in the database.
- The export table is called 'perl_event_export_settings' and it resembles the following structure and contains all current 81 EVENTS
- If an entry doesn't exist in this table and a new subroutine is added to the source, all exports will be on by default for that routine
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
| event_id | event_description | export_qglobals | export_mob | export_zone | export_item | export_event |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
| 0 | EVENT_SAY | 1 | 1 | 1 | 1 | 1 |
| 1 | EVENT_ITEM | 1 | 1 | 1 | 0 | 1 |
| 2 | EVENT_DEATH | 1 | 1 | 1 | 0 | 1 |
| 3 | EVENT_SPAWN | 1 | 1 | 1 | 0 | 1 |
| 4 | EVENT_ATTACK | 0 | 1 | 1 | 0 | 1 |
| 5 | EVENT_COMBAT | 1 | 1 | 1 | 0 | 1 |
+----------+-----------------------------------------+-----------------+------------+-------------+-------------+--------------+
- If a change is made to this table while the server is live and running, you can hot reload all zone process settings via:
#reloadperlexportsettings
- For those who wonder what "exports" are, they are reference to variables that are made available at runtime of the sub event, such as:
(export_qglobals) (Heavy) : $qglobals https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L916
(export_item) (Heavy) : $itemcount{} $hasitem{} $oncursor{} https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1103
(export_zone) : $zoneid, $instanceid, $zoneln etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1083
(export_mob) : $x, $y, $z, $h, $hpratio etc. https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1032
(export_event) : (event specific) IE: EVENT_SAY ($text) https://github.com/EQEmu/Server/blob/master/zone/embparser.cpp#L1141
== 10/16/2015 ==
Uleat: Added command '#bot clearfollowdistance [ <target> | spawned | all ]' to coincide with the activation of the load/save feature for follow_distance
== 10/13/2015 ==
Uleat: Important update to 2015_09_30_bots.sql - fix for orphaned entries causing crashes during the conversion process
Note: Please visit the thread below if you encounter issues during the conversion process
== 10/12/2015 ==
Uleat: Implemented 'bots' database versioning
Note: See thread for more information: http://www.eqemulator.org/forums/showthread.php?t=40091
Kayen: Feign death will now break when hit by casted spells, consisted with live.
Implemented suport for AA/spell effect which provides a chance to avoid FD breaking from spells.
== 10/10/2015 ==
Kayen: Updated mechanics to be consistent with live regarding how invisible breaks when the client is the target of a spell.
Invisible will drop whenever a client is hit with a detrimental spell, regardless of if resisted, if it does damage or AOE.
Hide skill now also follows the same rules as above.
Implemented support for Rogue AA - Nerves of Steel which gives a chance for hide NOT to break
when client is hit with an AOE spell.
== 09/25/2015 ==
Uleat: Implemented 'Inventory Snapshot' feature to track online player inventories at timed intervals.
rules:
'Character:ActiveInvSnapshots' - active (true) or inactive (false - default)
'Character:InvSnapshotMinIntervalM' - minimum time between snapshots (in minutes)
'Character:InvSnapshotMinRetryM' - minimum time to attempt a retry after a failed snapshot (in minutes)
'Character:InvSnapshotHistoryD' - minimum time to keep snapshot entries (in days)
commands:
'#invsnapshot' - Takes a snapshot of target client's inventory (feature active or inactive)
'#clearinvsnapshots [use rule]' - Clears snapshot entries based on bool argument ([true] - honors the 'InvSnapshotHistoryD' rule, [false] - erases all)
== 08/02/2015 ==
Shendare: VS2013 query StringFormat glitches when "%f" is passed for the int GetRunSpeed().
Shendare: In CreateNewNPCCommand(), the npc_type_id and spawngroupid are created in the database, but never set in the spawn class, so later it can't delete them with #npcspawn remove or #npcspawn delete.
== 07/27/2015 ==
Uleat: Reworked the QS Audit code in Handle_OP_ShopPlayerBuy (\zone\client_packet.cpp) to help eliminate potential for exception errors
== 07/22/2015 ==
mackal: Corrected some hate value calcs based on updated http://www.eqemulator.org/forums/showthread.php?t=39819
Rule Aggro:MaxStunProcAggro to Aggro:MaxScalingProcAggro since the cap applies to more than stuns
== 07/16/2015 ==
mackal: Rework spell aggro based on http://www.eqemulator.org/forums/showthread.php?t=39819
== 07/15/2015 ==
Hateborne: Added optional ability to enforce task level requirements in perl and lua via an added, optional parameter to $client->AssignTask and quest::assigntask.
Use cases:
quest::assigntask(703); # this still assigns the task as normal, no functional change
quest::assigntask(703, 1); # this will assign the task, provided the character meets the db-stored level requirements
$client->AssignTask(703, $npc->GetID()); # still assigns the task as normal, no functional change
$client->AssignTask(703, $npc->GetID(), 1); # this will assign the task, provided the character meets the db-stored level requirements
== 07/06/2015 ==
mackal: Implement Triple Attack Skill
Parses showed about rand(1000) for the chance, may need more investigating
Corrected Double Attack chances as well
Running optional 2015_07_06_TripleAttack.sql will set current toons to their max skill
This is optional because the admins might want to go a different route.
== 07/05/2015 ==
mackal: Rewrite NPC combat attack round logic
An NPC "quading" is really just an NPC with innate dual wield that doubles on both hands
The old rules allowed NPCs to hit 6 times in one round
NPCs also seem to have their own skill progression for DW/DA
See: http://www.eqemulator.org/forums/showthread.php?t=38708
You can set Combat:UseLiveCombatRounds to false to use the old rules
PC Double Attack rates kind of follow the same thing but still needs to be implemented
Kinglykrab: WARNING: summonburriedplayercorpse is now summonburiedplayercorpse, getplayerburriedcorpsecount is now getplayerburiedcorpsecount, summon_burried_player_corpse is now summon_buried_player_corpse, and get_player_burried_corpse_count is now get_player_buried_corpse_count FIX THESE IN YOUR SCRIPTS OR THEY WILL NOT WORK!!!!
Added bot saylinks (thanks Uleat!)
Command aliases for #augmentitem (#aug), #findnpctype (#fn), #findspell (#fs)
Bot command changes: #bot sow -> #bot speed, #bot magepet -> #bot setpet, #bot resurrectme -> #bot resurrect
Changed all occurrences of burried to buried in the code.
client_packet.cpp was referencing old columns in character_corpses, not sure how we didn't already see this before.
== 7/4/2015 ==
mackal: Reworked the activated avoidace skills (riposte, dodge, etc) based on dev quotes
This also fixes the order things are checked (avoidance skills, THEN hit/miss)
Also riposte immunity from the increase riposte chance spell effect.
== 7/2/2015 ==
KLS/Demonstar55: AA system has been rewritten fixing a ton of bugs and extending functionality while making it easier to create new AA points.
KLS/Demonstar55: New tables are needed and so older data will need to be migrated to the new system.
KLS/Demonstar55: The SQL saves the old aa points spent/avail/character_alt_abilities data if any server ops want to do something different than PEQ did with it.
KLS/Demonstar55: Will try to get a wiki entry written up next week some time explaining the system but it's really not hard to follow the db tables in the meantime.
== 7/1/2015 ==
Akkadius: Fix an issue where emote messages would overflow the buffer of 256 by increasing the size and changing some of the initialization
Akkadius: Added a custom Health Update message that will display in the middle of the players screen, to enable this server wide you must enable rule 'Character:MarqueeHPUpdates'
Example: https://www.youtube.com/watch?v=KUVdbPxLIn0
Akkadius: (Haynar) Fixed some runspeed issues with Perl and LUA scripts
Akkadius: (Haynar) Updated #showstats and #npcstats for new speed calcs to display speeds again in familiar float format.
Akkadius: (Haynar) Improved client movement while AI Controlled, such as feared and charmed. Movement will be much smoother from clients perspective.
== 06/12/2015 ==
Uleat: Adjusted SessionStats to better reflect a sister implementation
+20 -23
View File
@@ -21,12 +21,6 @@ IF(MYSQL_ROOT)
NAMES mysql.h
PATHS ${MYSQL_ROOT}/include
PATH_SUFFIXES mysql
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_PATH(MySQL_INCLUDE_DIR
NAMES mysql.h
PATH_SUFFIXES mysql
)
ELSE(MYSQL_ROOT)
FIND_PATH(MySQL_INCLUDE_DIR
@@ -36,46 +30,49 @@ ELSE(MYSQL_ROOT)
ENDIF(MYSQL_ROOT)
# Library
SET(MySQL_NAMES libmysql)
SET(MySQL_NAMES mysqlclient_r mysqlclient)
IF(MYSQL_ROOT)
FIND_LIBRARY(MySQL_LIBRARY
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
NAMES ${MySQL_NAMES}
PATHS ${MYSQL_ROOT}/lib
PATHS ${MYSQL_ROOT}/lib/debug /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_LIBRARY(MySQL_LIBRARY
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
NAMES ${MySQL_NAMES}
PATHS ${MYSQL_ROOT}/lib /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
ELSE(MYSQL_ROOT)
FIND_LIBRARY(MySQL_LIBRARY
NAMES ${MySQL_NAMES} mysqlclient_r mysqlclient
FIND_LIBRARY(MySQL_LIBRARY_DEBUG
NAMES ${MySQL_NAMES}
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
FIND_LIBRARY(MySQL_LIBRARY_RELEASE
NAMES ${MySQL_NAMES}
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql
)
ENDIF(MYSQL_ROOT)
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
IF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
SET(MySQL_FOUND TRUE)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY} )
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
ELSE (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
SET(MySQL_FOUND FALSE)
SET( MySQL_LIBRARIES )
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY)
ENDIF (MySQL_INCLUDE_DIR AND MySQL_LIBRARY_DEBUG AND MySQL_LIBRARY_RELEASE)
# handle the QUIETLY and REQUIRED arguments and set MySQL_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MySQL DEFAULT_MSG MySQL_LIBRARY_DEBUG MySQL_LIBRARY_RELEASE MySQL_INCLUDE_DIR)
IF(MySQL_FOUND)
SET( MySQL_LIBRARY_RELEASE ${MySQL_LIBRARY} )
SET( MySQL_LIBRARY_DEBUG ${MySQL_LIBRARY} )
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_RELEASE} ${MySQL_LIBRARY_DEBUG} )
SET( MySQL_LIBRARIES ${MySQL_LIBRARY_DEBUG} ${MySQL_LIBRARY_RELEASE} )
ELSE(MySQL_FOUND)
SET( MySQL_LIBRARIES )
ENDIF(MySQL_FOUND)
+18 -3
View File
@@ -30,9 +30,16 @@ SET(common_sources
faction.cpp
guild_base.cpp
guilds.cpp
inventory.cpp
inventory_db_data_model.cpp
ipc_mutex.cpp
item.cpp
item_container.cpp
item_container_default_serialization.cpp
item_container_personal_serialization.cpp
item_instance.cpp
md5.cpp
memory_buffer.cpp
memory_mapped_file.cpp
misc.cpp
misc_functions.cpp
@@ -64,7 +71,6 @@ SET(common_sources
unix.cpp
worldconn.cpp
xml_parser.cpp
pathfind.cpp
platform.cpp
patches/patches.cpp
patches/sod.cpp
@@ -136,15 +142,25 @@ SET(common_headers
global_define.h
guild_base.h
guilds.h
inventory.h
inventory_data_model.h
inventory_db_data_model.h
inventory_null_data_model.h
ipc_mutex.h
item.h
item_container.h
item_container_default_serialization.h
item_container_personal_serialization.h
item_container_serialization_strategy.h
item_data.h
item_fieldlist.h
item_struct.h
item_instance.h
languages.h
linked_list.h
loottable.h
mail_oplist.h
md5.h
memory_buffer.h
memory_mapped_file.h
misc.h
misc_functions.h
@@ -157,7 +173,6 @@ SET(common_headers
packet_dump.h
packet_dump_file.h
packet_functions.h
pathfind.h
platform.h
proc_launcher.h
profiler.h
+1 -3
View File
@@ -63,12 +63,10 @@ public:
void WriteFloat(float value) { *(float *)(pBuffer + _wpos) = value; _wpos += sizeof(float); }
void WriteDouble(double value) { *(double *)(pBuffer + _wpos) = value; _wpos += sizeof(double); }
void WriteString(const char * str) { uint32 len = static_cast<uint32>(strlen(str)) + 1; memcpy(pBuffer + _wpos, str, len); _wpos += len; }
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += (uint32)n; }
void WriteData(const void *ptr, size_t n) { memcpy(pBuffer + _wpos, ptr, n); _wpos += n; }
uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; }
uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; }
uint16 ReadUInt16() { uint16 value = *(uint16 *)(pBuffer + _rpos); _rpos += sizeof(uint16); return value; }
uint16 ReadUInt16(uint32 Offset) const { uint16 value = *(uint16 *)(pBuffer + Offset); return value; }
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
+13 -42
View File
@@ -24,27 +24,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "types.h"
static const uint32 BIT_Client62 = 0x00000001; // 1 (unsupported - placeholder for scripts)
static const uint32 BIT_Titanium = 0x00000002; // 2
static const uint32 BIT_SoF = 0x00000004; // 4
static const uint32 BIT_SoD = 0x00000008; // 8
static const uint32 BIT_UF = 0x00000010; // 16
static const uint32 BIT_RoF = 0x00000020; // 32
static const uint32 BIT_RoF2 = 0x00000040; // 64
static const uint32 BIT_TitaniumAndEarlier = 0x00000003; // 3
static const uint32 BIT_SoFAndEarlier = 0x00000007; // 7
static const uint32 BIT_SoDAndEarlier = 0x0000000F; // 15
static const uint32 BIT_UFAndEarlier = 0x0000001F; // 31
static const uint32 BIT_RoFAndEarlier = 0x0000003F; // 63
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC; // 4294967292
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8; // 4294967288
static const uint32 BIT_UFAndLater = 0xFFFFFFF0; // 4294967280
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0; // 4294967264
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0; // 4294967232
static const uint32 BIT_Client62 = 1;
static const uint32 BIT_Titanium = 2;
static const uint32 BIT_SoF = 4;
static const uint32 BIT_SoD = 8;
static const uint32 BIT_UF = 16;
static const uint32 BIT_RoF = 32;
static const uint32 BIT_RoF2 = 64;
static const uint32 BIT_TitaniumAndEarlier = 0x00000003;
static const uint32 BIT_SoFAndLater = 0xFFFFFFFC;
static const uint32 BIT_SoDAndLater = 0xFFFFFFF8;
static const uint32 BIT_UFAndLater = 0xFFFFFFF0;
static const uint32 BIT_RoFAndLater = 0xFFFFFFE0;
static const uint32 BIT_RoF2AndLater = 0xFFFFFFC0;
static const uint32 BIT_AllClients = 0xFFFFFFFF;
enum class ClientVersion
@@ -157,26 +150,4 @@ static ClientVersion ClientVersionFromBit(uint32 clientVersionBit)
}
}
static uint32 ExpansionFromClientVersion(ClientVersion clientVersion)
{
switch(clientVersion)
{
case ClientVersion::Unknown:
case ClientVersion::Client62:
case ClientVersion::Titanium:
return 0x000007FFU;
case ClientVersion::SoF:
return 0x00007FFFU;
case ClientVersion::SoD:
return 0x0000FFFFU;
case ClientVersion::UF:
return 0x0001FFFFU;
case ClientVersion::RoF:
case ClientVersion::RoF2:
return 0x000FFFFFU;
default:
return 0;
}
}
#endif /* CLIENTVERSIONS_H */
+11 -11
View File
@@ -23,23 +23,23 @@
namespace EQEmu
{
template <typename T>
T Clamp(const T& value, const T& lower, const T& upper) {
return std::max(lower, std::min(value, upper));
template <typename T, typename U, typename V>
T Clamp(const T& value, const U& lower, const V& upper) {
return std::max(static_cast<T>(lower), std::min(value, static_cast<T>(upper)));
}
template <typename T>
T ClampLower(const T& value, const T& lower) {
return std::max(lower, value);
template <typename T, typename U>
T ClampLower(const T& value, const U& lower) {
return std::max(static_cast<T>(lower), value);
}
template <typename T>
T ClampUpper(const T& value, const T& upper) {
return std::min(value, upper);
template <typename T, typename U>
T ClampUpper(const T& value, const U& upper) {
return std::min(value, static_cast<T>(upper));
}
template <typename T>
bool ValueWithin(const T& value, const T& lower, const T& upper) {
template <typename T, typename U, typename V>
bool ValueWithin(const T& value, const U& lower, const V& upper) {
return value >= lower && value <= upper;
}
+19 -62
View File
@@ -348,11 +348,11 @@ bool Database::DeleteCharacter(char *name) {
query = StringFormat("DELETE FROM `character_inspect_messages` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_leadership_abilities` WHERE `id` = %u", charid); QueryDatabase(query);
query = StringFormat("DELETE FROM `character_alt_currency` WHERE `char_id` = '%d'", charid); QueryDatabase(query);
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid); // note: only use of GetMobTypeById()
#else
#ifdef BOTS
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d' AND GetMobTypeById(%i) = 'C'", charid);
#else
query = StringFormat("DELETE FROM `guild_members` WHERE `char_id` = '%d'", charid);
#endif
#endif
QueryDatabase(query);
return true;
@@ -677,7 +677,7 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe
}
/* This only for new Character creation storing */
bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv) {
bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv) {
uint32 charid = 0;
char zone[50];
float x, y, z;
@@ -1183,16 +1183,21 @@ bool Database::CheckNameFilter(const char* name, bool surname)
{
std::string str_name = name;
// the minimum 4 is enforced by the client too
if (!name || strlen(name) < 4)
if(surname)
{
return false;
// the minimum 4 is enforced by the client too
if(!name || strlen(name) < 3)
{
return false;
}
}
// Given name length is enforced by the client too
if (!surname && strlen(name) > 15)
else
{
return false;
// the minimum 4 is enforced by the client too
if(!name || strlen(name) < 4 || strlen(name) > 15)
{
return false;
}
}
for (size_t i = 0; i < str_name.size(); i++)
@@ -1379,7 +1384,7 @@ bool Database::MoveCharacterToZone(const char* charname, const char* zonename) {
}
bool Database::MoveCharacterToZone(uint32 iCharID, const char* iZonename) {
std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", GetZoneID(iZonename), iCharID);
std::string query = StringFormat("UPDATE `character_data` SET `zone_id` = %i, `x` = -1, `y` = -1, `z` = -1 WHERE `id` = %i", iZonename, GetZoneID(iZonename), iCharID);
auto results = QueryDatabase(query);
if (!results.Success()) {
@@ -1559,7 +1564,7 @@ void Database::AddReport(std::string who, std::string against, std::string lines
char *escape_str = new char[lines.size()*2+1];
DoEscapeString(escape_str, lines.c_str(), lines.size());
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", EscapeString(who).c_str(), EscapeString(against).c_str(), escape_str);
std::string query = StringFormat("INSERT INTO reports (name, reported, reported_text) VALUES('%s', '%s', '%s')", who.c_str(), against.c_str(), escape_str);
QueryDatabase(query);
safe_delete_array(escape_str);
}
@@ -2168,51 +2173,3 @@ void Database::LoadLogSettings(EQEmuLogSys::LogSettings* log_settings)
}
}
}
void Database::ClearInvSnapshots(bool use_rule)
{
uint32 del_time = time(nullptr);
if (use_rule) { del_time -= RuleI(Character, InvSnapshotHistoryD) * 86400; }
std::string query = StringFormat("DELETE FROM inventory_snapshots WHERE time_index <= %lu", (unsigned long)del_time);
QueryDatabase(query);
}
struct TimeOfDay_Struct Database::LoadTime(time_t &realtime)
{
TimeOfDay_Struct eqTime;
std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1");
auto results = QueryDatabase(query);
if (!results.Success() || results.RowCount() == 0){
Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults.");
eqTime.minute = 0;
eqTime.hour = 9;
eqTime.day = 1;
eqTime.month = 1;
eqTime.year = 3100;
realtime = time(0);
}
else{
auto row = results.begin();
eqTime.minute = atoi(row[0]);
eqTime.hour = atoi(row[1]);
eqTime.day = atoi(row[2]);
eqTime.month = atoi(row[3]);
eqTime.year = atoi(row[4]);
realtime = atoi(row[5]);
}
return eqTime;
}
bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year)
{
std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0));
auto results = QueryDatabase(query);
return results.Success();
}
+4 -7
View File
@@ -23,11 +23,11 @@
#include "global_define.h"
#include "eqemu_logsys.h"
#include "types.h"
#include "dbcore.h"
#include "linked_list.h"
#include "eq_packet_structs.h"
#include "inventory.h"
#include <cmath>
#include <string>
@@ -37,7 +37,7 @@
//atoi is not uint32 or uint32 safe!!!!
#define atoul(str) strtoul(str, nullptr, 10)
class Inventory;
class InventoryOld;
class MySQLRequestResult;
class Client;
@@ -103,7 +103,7 @@ public:
bool SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp);
bool SetHackerFlag(const char* accountname, const char* charactername, const char* hacked);
bool SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone);
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inventory* inv);
bool StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, InventoryOld* inv);
bool UpdateName(const char* oldname, const char* newname);
/* General Information Queries */
@@ -210,6 +210,7 @@ public:
/* Database Conversions 'database_conversions.cpp' */
bool CheckDatabaseConversions();
bool CheckDatabaseConvertBotsPostPPDeblob();
bool CheckDatabaseConvertCorpseDeblob();
bool CheckDatabaseConvertPPDeblob();
@@ -241,8 +242,6 @@ public:
uint8 GetSkillCap(uint8 skillid, uint8 in_race, uint8 in_class, uint16 in_level);
void AddReport(std::string who, std::string against, std::string lines);
struct TimeOfDay_Struct LoadTime(time_t &realtime);
bool SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year);
void ClearMerchantTemp();
void ClearPTimers(uint32 charid);
void SetFirstLogon(uint32 CharID, uint8 firstlogon);
@@ -250,8 +249,6 @@ public:
void SetLFP(uint32 CharID, bool LFP);
void SetLoginFlags(uint32 CharID, bool LFP, bool LFG, uint8 firstlogon);
void ClearInvSnapshots(bool use_rule = true);
/* EQEmuLogSys */
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
+159 -1
View File
@@ -470,6 +470,7 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50)
bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertBotsPostPPDeblob();
CheckDatabaseConvertCorpseDeblob();
/* Fetch Automatic Upgrade Script */
@@ -493,7 +494,7 @@ bool Database::CheckDatabaseConversions() {
/* Check for a new version of this script, the arg passed
would have to be higher than the copy they have downloaded
locally and they will re fetch */
system("perl eqemu_update.pl V 14");
system("perl eqemu_update.pl V 7");
/* Run Automatic Database Upgrade Script */
system("perl eqemu_update.pl ran_from_world");
@@ -1490,6 +1491,163 @@ bool Database::CheckDatabaseConvertPPDeblob(){
return true;
}
bool Database::CheckDatabaseConvertBotsPostPPDeblob(){
#ifdef BOTS
int runbotsconvert = 0;
/* Check For Legacy Bot References */
std::string rquery = StringFormat("SHOW CREATE VIEW `vwBotCharacterMobs`");
auto results = QueryDatabase(rquery);
if (results.RowCount() == 1){
auto row = results.begin();
std::string table_check = row[1];
if (table_check.find("character_data") == -1){
runbotsconvert = 1;
printf("\n\n::: Legacy Bot Views and Function Detected... \n");
printf("----------------------------------------------------------\n\n");
printf(" Database currently has bot view/function linkage to obselete \n");
printf(" table references and will now be converted...\n\n");
printf(" It is recommended that you backup your database \n");
printf(" before continuing the automatic conversion process...\n\n");
printf("----------------------------------------------------------\n\n");
std::cout << "Press ENTER to continue....." << std::endl << std::endl;
std::cin.ignore(1);
}
}
if (runbotsconvert == 1){
printf("Running bot views/function database conversion... \n");
/* Update view `vwbotcharactermobs` */
rquery = StringFormat("DROP VIEW `vwBotCharacterMobs`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwBotCharacterMobs` AS\n"
"SELECT _utf8'C' AS mobtype,\n" // Natedog: '_utf8'
"c.`id`,\n"
"c.`name`,\n"
"c.`class`,\n"
"c.`level`,\n"
"c.`last_login`,\n"
"c.`zone_id`\n"
"FROM `character_data` AS c\n"
"UNION ALL\n"
"SELECT _utf8'B' AS mobtype,\n" // Natedog: '_utf8'
"b.`BotID` AS id,\n"
"b.`Name` AS name,\n"
"b.`Class` AS class,\n"
"b.`BotLevel` AS level,\n"
"0 AS timelaston,\n"
"0 AS zoneid\n"
"FROM bots AS b;"
);
results = QueryDatabase(rquery);
/* Update function `GetMobType` */
rquery = StringFormat("DROP FUNCTION IF EXISTS `GetMobType`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE FUNCTION `GetMobType` (mobname VARCHAR(64)) RETURNS CHAR(1)\n"
"BEGIN\n"
" DECLARE Result CHAR(1);\n"
"\n"
" SET Result = NULL;\n"
"\n"
" IF (SELECT COUNT(*) FROM `character_data` WHERE `name` = mobname) > 0 THEN\n"
" SET Result = 'C';\n"
" ELSEIF (SELECT COUNT(*) FROM `bots` WHERE `Name` = mobname) > 0 THEN\n"
" SET Result = 'B';\n"
" END IF;\n "
"\n"
" RETURN Result;\n"
"END"
);
results = QueryDatabase(rquery);
/* Update view `vwgroups` */
rquery = StringFormat("DROP VIEW IF EXISTS `vwGroups`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwGroups` AS\n"
"SELECT g.`groupid` AS groupid,\n"
"GetMobType(g.`name`) AS mobtype,\n"
"g.`name` AS name,\n"
"g.`charid` AS mobid,\n"
"IFNULL(c.`level`, b.`BotLevel`) AS level\n"
"FROM `group_id` AS g\n"
"LEFT JOIN `character_data` AS c ON g.`name` = c.`name`\n"
"LEFT JOIN `bots` AS b ON g.`name` = b.`Name`;"
);
results = QueryDatabase(rquery);
/* Update view `vwbotgroups` */
rquery = StringFormat("DROP VIEW IF EXISTS `vwBotGroups`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwBotGroups` AS\n"
"SELECT g.`BotGroupId`,\n"
"g.`BotGroupName`,\n"
"g.`BotGroupLeaderBotId`,\n"
"b.`Name` AS BotGroupLeaderName,\n"
"b.`BotOwnerCharacterId`,\n"
"c.`name` AS BotOwnerCharacterName\n"
"FROM `botgroup` AS g\n"
"JOIN `bots` AS b ON g.`BotGroupLeaderBotId` = b.`BotID`\n"
"JOIN `character_data` AS c ON b.`BotOwnerCharacterID` = c.`id`\n"
"ORDER BY b.`BotOwnerCharacterId`, g.`BotGroupName`;"
);
results = QueryDatabase(rquery);
/* Update view `vwguildmembers` */
rquery = StringFormat("DROP VIEW IF EXISTS `vwGuildMembers`;");
results = QueryDatabase(rquery);
rquery = StringFormat(
"CREATE VIEW `vwGuildMembers` AS\n"
"SELECT 'C' AS mobtype,\n"
"cm.`char_id`,\n"
"cm.`guild_id`,\n"
"cm.`rank`,\n"
"cm.`tribute_enable`,\n"
"cm.`total_tribute`,\n"
"cm.`last_tribute`,\n"
"cm.`banker`,\n"
"cm.`public_note`,\n"
"cm.`alt`\n"
"FROM `guild_members` AS cm\n"
"UNION ALL\n"
"SELECT 'B' AS mobtype,\n"
"bm.`char_id`,\n"
"bm.`guild_id`,\n"
"bm.`rank`,\n"
"bm.`tribute_enable`,\n"
"bm.`total_tribute`,\n"
"bm.`last_tribute`,\n"
"bm.`banker`,\n"
"bm.`public_note`,\n"
"bm.`alt`\n"
"FROM `botguildmembers` AS bm;"
);
results = QueryDatabase(rquery);
}
if (runbotsconvert == 1){
printf("\n\nBot views/function conversion complete, continuing world bootup...\n");
}
#endif
return true;
}
bool Database::CheckDatabaseConvertCorpseDeblob(){
Convert::DBPlayerCorpse_Struct_temp* dbpc;
Convert::classic_db_temp::DBPlayerCorpse_Struct_temp* dbpc_c;
+1 -6
View File
@@ -128,12 +128,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char* query, uint32 querylen, boo
MySQLRequestResult requestResult(res, (uint32)mysql_affected_rows(&mysql), rowCount, (uint32)mysql_field_count(&mysql), (uint32)mysql_insert_id(&mysql));
if (Log.log_settings[Logs::MySQLQuery].is_category_enabled == 1)
{
if ((strncasecmp(query, "select", 6) == 0))
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s returned)", query, requestResult.RowCount(), requestResult.RowCount() == 1 ? "" : "s");
else
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u row%s affected)", query, requestResult.RowsAffected(), requestResult.RowsAffected() == 1 ? "" : "s");
}
Log.Out(Logs::General, Logs::MySQLQuery, "%s (%u rows returned)", query, rowCount, requestResult.RowCount());
return requestResult;
}
-4
View File
@@ -215,7 +215,6 @@ N(OP_GroupUpdate),
N(OP_GroupUpdateB),
N(OP_GroupUpdateLeaderAA),
N(OP_GuildBank),
N(OP_GuildBankItemList),
N(OP_GuildCreate),
N(OP_GuildDelete),
N(OP_GuildDemote),
@@ -536,8 +535,6 @@ N(OP_WorldLogout),
N(OP_WorldObjectsSent),
N(OP_WorldUnknown001),
N(OP_XTargetAutoAddHaters),
N(OP_XTargetOpen),
N(OP_XTargetOpenResponse),
N(OP_XTargetRequest),
N(OP_XTargetResponse),
N(OP_YellForHelp),
@@ -551,5 +548,4 @@ N(OP_ZoneServerInfo),
N(OP_ZoneServerReady),
N(OP_ZoneSpawns),
N(OP_ZoneUnavail),
N(OP_ResetAA),
// mail and chat opcodes located in ../mail_oplist.h
+1 -1
View File
@@ -306,7 +306,7 @@ enum AugmentationRestrictionTypes : uint8 {
/*
** Container use types
**
** This correlates to world 'object.type' (object.h/Object.cpp) as well as Item_Struct.BagType
** This correlates to world 'object.type' (object.h/Object.cpp) as well as ItemData.BagType
**
** (ref: database, web forums and eqstr_us.txt)
*/
+31 -75
View File
@@ -25,7 +25,7 @@
#include <list>
#include <time.h>
#include "../common/version.h"
//#include "../common/item_struct.h"
//#include "../common/item_data.h"
static const uint32 BUFF_COUNT = 25;
static const uint32 MAX_MERC = 100;
@@ -126,6 +126,14 @@ struct LDoNTrapTemplate
// All clients translate the character select information to some degree
struct Inventory_Slot_Struct
{
int16 type;
int16 slot;
int16 bag;
int16 aug;
};
struct Color_Struct
{
union {
@@ -1322,7 +1330,7 @@ struct CombatDamage_Struct
/* 11 */ float force;
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 23 */
};
/*
@@ -1558,7 +1566,7 @@ struct DeleteItem_Struct {
/*0012*/
};
struct MoveItem_Struct
struct MoveItemOld_Struct
{
/*0000*/ uint32 from_slot;
/*0004*/ uint32 to_slot;
@@ -1566,6 +1574,19 @@ struct MoveItem_Struct
/*0012*/
};
struct MoveItem_Struct
{
int16 from_type;
int16 from_slot;
int16 from_bag_slot;
int16 from_aug_slot;
int16 to_type;
int16 to_slot;
int16 to_bag_slot;
int16 to_aug_slot;
uint32 number_in_stack;
};
// both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will
// be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this
// info at the moment..but, it is forwarded on to the server for handling/future use)
@@ -1957,13 +1978,11 @@ Unknowns:
struct Merchant_Sell_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
/*004*/ uint32 playerid; // Player's entity id
/*008*/ uint32 itemslot;
uint32 unknown12;
/*016*/ uint8 quantity; // Already sold
/*017*/ uint8 Unknown016[3];
/*020*/ uint32 price;
uint32 npcid;
uint32 playerid;
uint32 itemslot;
int32 quantity;
uint32 price;
};
struct Merchant_Purchase_Struct {
/*000*/ uint32 npcid; // Merchant NPC's entity id
@@ -2099,7 +2118,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -4219,52 +4238,6 @@ struct UseAA_Struct {
uint32 end;
};
//new AA stuff
//reference only
struct AARankInfo_Struct
{
uint32 id;
int32 upper_hotkey_sid;
int32 lower_hotkey_sid;
int32 title_sid;
int32 desc_sid;
int32 level_req;
int32 cost;
uint32 seq;
uint32 current_level;
uint32 type;
int32 spell;
int32 spell_type;
int32 spell_refresh;
int32 classes;
int32 max_level;
int32 prev_id;
int32 next_id;
int32 total_cost;
int32 expansion;
int32 category;
uint32 charges;
uint8 grant_only;
uint32 total_effects;
uint32 total_prereqs;
};
struct AARankPrereq_Struct
{
int32 aa_id;
int32 points;
};
struct AARankEffect_Struct
{
int32 effect_id;
int32 base1;
int32 base2;
int32 slot;
};
//old AA stuff
struct AA_Ability {
/*00*/ uint32 skill_id;
/*04*/ uint32 base1;
@@ -4319,7 +4292,7 @@ struct SendAA_Struct {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
};
@@ -4724,22 +4697,6 @@ struct GuildBankItemUpdate_Struct
/*226*/ uint16 Unknown226;
};
// newer clients (RoF+) send a list that contains 240 entries
// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these
struct GuildBankItemListEntry_Struct
{
uint8 vaild;
uint32 permissions;
char whofor[64];
char donator[64];
uint32 item_id;
uint32 item_icon;
uint32 quantity;
uint8 allow_merge; // 1 here for non-full stacks
uint8 usable;
char item_name[64];
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
@@ -4796,7 +4753,6 @@ struct BuffIcon_Struct
uint8 all_buffs;
uint16 count;
uint8 type; // 0 = self buff window, 1 = self target window, 4 = group, 5 = PC, 7 = NPC
int32 tic_timer;
BuffIconEntry_Struct entries[0];
};
+8
View File
@@ -254,6 +254,10 @@ void EQEmuConfig::do_files(TiXmlElement *ele)
if (text) {
OpCodesFile = text;
}
text = ParseTextBlock(ele, "eqtime", true);
if (text) {
EQTimeFile = text;
}
}
void EQEmuConfig::do_directories(TiXmlElement *ele)
@@ -404,6 +408,9 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
if (var_name == "OpCodesFile") {
return (OpCodesFile);
}
if (var_name == "EQTimeFile") {
return (EQTimeFile);
}
if (var_name == "MapDir") {
return (MapDir);
}
@@ -468,6 +475,7 @@ void EQEmuConfig::Dump() const
std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl;
std::cout << "SpellsFile = " << SpellsFile << std::endl;
std::cout << "OpCodesFile = " << OpCodesFile << std::endl;
std::cout << "EQTimeFile = " << EQTimeFile << std::endl;
std::cout << "MapDir = " << MapDir << std::endl;
std::cout << "QuestDir = " << QuestDir << std::endl;
std::cout << "PluginDir = " << PluginDir << std::endl;
+2
View File
@@ -79,6 +79,7 @@ class EQEmuConfig : public XMLParser
// From <files/>
std::string SpellsFile;
std::string OpCodesFile;
std::string EQTimeFile;
// From <directories/>
std::string MapDir;
@@ -153,6 +154,7 @@ class EQEmuConfig : public XMLParser
// Files
SpellsFile = "spells_us.txt";
OpCodesFile = "opcodes.conf";
EQTimeFile = "eqtime.cfg";
// Dirs
MapDir = "Maps";
QuestDir = "quests";
+35 -28
View File
@@ -102,7 +102,6 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
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;
log_settings[Logs::Login_Server].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
@@ -117,27 +116,32 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
platform_file_name = "ucs";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLogin)
platform_file_name = "login";
else if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformLaunch)
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 ret;
ret.push_back('[');
ret.append(Logs::LogCategoryName[log_category]);
ret.push_back(']');
ret.push_back(' ');
ret.append(in_message);
return ret;
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);
@@ -155,6 +159,14 @@ void EQEmuLogSys::ProcessLogWrite(uint16 debug_level, uint16 log_category, const
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);
@@ -233,6 +245,13 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category) {
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;
@@ -253,32 +272,20 @@ void EQEmuLogSys::ProcessConsoleMessage(uint16 debug_level, uint16 log_category,
void EQEmuLogSys::Out(Logs::DebugLevel debug_level, uint16 log_category, std::string message, ...)
{
bool log_to_console = true;
if (log_settings[log_category].log_to_console < debug_level) {
log_to_console = false;
}
bool log_to_file = true;
if (log_settings[log_category].log_to_file < debug_level) {
log_to_file = false;
}
bool log_to_gmsay = true;
if (log_settings[log_category].log_to_gmsay < debug_level) {
log_to_gmsay = false;
}
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;
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);
-2
View File
@@ -82,7 +82,6 @@ namespace Logs {
Client_Server_Packet_Unhandled,
Server_Client_Packet_With_Dump,
Client_Server_Packet_With_Dump,
Login_Server,
MaxCategoryID /* Don't Remove this*/
};
@@ -131,7 +130,6 @@ namespace Logs {
"Packet :: Client -> Server Unhandled",
"Packet :: Server -> Client (Dump)",
"Packet :: Client -> Server (Dump)",
"Login Server"
};
}
+66
View File
@@ -133,6 +133,72 @@ int EQTime::SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real)
return 1;
}
//saveFile and loadFile need to use long for the save datatype...
//For some reason, ifstream/ofstream have problems with EQEmu datatypes in files.
bool EQTime::saveFile(const char *filename)
{
std::ofstream of;
of.open(filename);
if (!of)
{
Log.Out(Logs::General, Logs::Error, "EQTime::saveFile failed: Unable to open file '%s'", filename);
return false;
}
//Enable for debugging
of << EQT_VERSION << std::endl;
of << (long)eqTime.start_eqtime.day << std::endl;
of << (long)eqTime.start_eqtime.hour << std::endl;
of << (long)eqTime.start_eqtime.minute << std::endl;
of << (long)eqTime.start_eqtime.month << std::endl;
of << eqTime.start_eqtime.year << std::endl;
of << eqTime.start_realtime << std::endl;
of.close();
return true;
}
bool EQTime::loadFile(const char *filename)
{
int version=0;
long in_data=0;
std::ifstream in;
in.open(filename);
if(!in)
{
Log.Out(Logs::General, Logs::Error, "Could not load EQTime file %s", filename);
return false;
}
in >> version;
in.ignore(80, '\n');
if(version != EQT_VERSION)
{
Log.Out(Logs::General, Logs::Error, "'%s' is NOT a valid EQTime file. File version is %i, EQTime version is %i", filename, version, EQT_VERSION);
return false;
}
//in >> eqTime.start_eqtime.day;
in >> in_data;
in.ignore(80, '\n');
eqTime.start_eqtime.day = in_data;
//in >> eqTime.start_eqtime.hour;
in >> in_data;
eqTime.start_eqtime.hour = in_data;
in.ignore(80, '\n');
//in >> eqTime.start_eqtime.minute;
in >> in_data;
in.ignore(80, '\n');
eqTime.start_eqtime.minute = in_data;
//in >> eqTime.start_eqtime.month;
in >> in_data;
in.ignore(80, '\n');
eqTime.start_eqtime.month = in_data;
in >> eqTime.start_eqtime.year;
in.ignore(80, '\n');
in >> eqTime.start_realtime;
//Enable for debugging...
in.close();
return true;
}
bool EQTime::IsTimeBefore(TimeOfDay_Struct *base, TimeOfDay_Struct *test) {
if (base->year > test->year)
return(true);
+6
View File
@@ -39,6 +39,12 @@ public:
static void ToString(TimeOfDay_Struct *t, std::string &str);
//Database functions
//bool loadDB(Database q);
//bool setDB(Database q);
bool loadFile(const char *filename);
bool saveFile(const char *filename);
private:
//This is our reference clock.
eqTimeOfDay eqTime;
-2
View File
@@ -54,8 +54,6 @@ struct ExtendedProfile_Struct {
uint32 mercTimerRemaining; /* Not Used */
uint8 mercGender; /* Not Used */
int32 mercState; /* Not Used */
uint32 last_invsnapshot_time; /* Used */
uint32 next_invsnapshot_time; /* Used */
};
#pragma pack()
+1 -7
View File
@@ -154,12 +154,11 @@ enum { //reuse times
enum { //timer settings, all in milliseconds
AImovement_duration = 100,
AIthink_duration = 150,
AIscanarea_delay = 6000,
AIscanarea_delay = 500,
AIfeignremember_delay = 500,
AItarget_check_duration = 500,
AIClientScanarea_delay = 750, //used in REVERSE_AGGRO
AIassistcheck_delay = 3000, //now often a fighting NPC will yell for help
AI_check_signal_timer_delay = 500, // How often EVENT_SIGNAL checks are processed
ClientProximity_interval = 150,
CombatEventTimer_expire = 12000,
Tribute_duration = 600000,
@@ -233,8 +232,6 @@ enum { //some random constants
#define GROUP_EXP_PER_POINT 1000
#define RAID_EXP_PER_POINT 2000
#define ZONE_CONTROLLER_NPC_ID 10
//Some hard coded statuses from commands and other places:
enum {
minStatusToBeGM = 40,
@@ -273,9 +270,6 @@ enum {
#define NPC_DEFAULT_LOGGING_ENABLED false
// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars
#define SAYLINK_ITEM_ID 0xFFFFF
/*
+9 -9
View File
@@ -867,16 +867,16 @@ bool BaseGuildManager::QueryWithLogging(std::string query, const char *errmsg) {
//factored out so I dont have to copy this crap.
#ifdef BOTS
#define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt`" \
" FROM `vw_bot_character_mobs` AS c LEFT JOIN `vw_guild_members` AS g ON c.`id` = g.`char_id` AND c.`mob_type` = g.`mob_type` "
"SELECT c.id,c.name,c.class,c.level,c.timelaston,c.zoneid," \
" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \
" g.banker,g.public_note,g.alt" \
" FROM vwBotCharacterMobs AS c LEFT JOIN vwGuildMembers AS g ON c.id=g.char_id AND c.mobtype = g.mobtype "
#else
#define GuildMemberBaseQuery \
"SELECT c.`id`, c.`name`, c.`class`, c.`level`, c.`last_login`, c.`zone_id`," \
" g.`guild_id`, g.`rank`, g.`tribute_enable`, g.`total_tribute`, g.`last_tribute`," \
" g.`banker`, g.`public_note`, g.`alt` " \
" FROM `character_data` AS c LEFT JOIN `guild_members` AS g ON c.`id` = g.`char_id` "
"SELECT c.id,c.name,c.class,c.level,c.last_login,c.zone_id," \
" g.guild_id,g.rank,g.tribute_enable,g.total_tribute,g.last_tribute," \
" g.banker,g.public_note,g.alt " \
" FROM `character_data` AS c LEFT JOIN guild_members AS g ON c.id=g.char_id "
#endif
static void ProcessGuildMember(MySQLRequestRow row, CharGuildInfo &into) {
//fields from `characer_`
@@ -969,7 +969,7 @@ bool BaseGuildManager::GetCharInfo(uint32 char_id, CharGuildInfo &into) {
//load up the rank info for each guild.
std::string query;
#ifdef BOTS
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mob_type = 'C'", char_id);
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d AND c.mobtype = 'C'", char_id);
#else
query = StringFormat(GuildMemberBaseQuery " WHERE c.id=%d", char_id);
#endif
+782
View File
@@ -0,0 +1,782 @@
/* 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 "inventory.h"
#include "inventory_null_data_model.h"
#include "item_container_personal_serialization.h"
#include "data_verification.h"
#include "string_util.h"
#include <map>
bool EQEmu::InventorySlot::IsValid() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotCursor)) {
return true;
}
if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) {
return true;
}
if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) {
return true;
}
if(type_ == InvTypeTribute && EQEmu::ValueWithin(slot_, 0, 4)) {
return true;
}
if(type_ == InvTypeTrade && EQEmu::ValueWithin(slot_, 0, 7)) {
return true;
}
if(type_ == InvTypeWorld && EQEmu::ValueWithin(slot_, 0, 255)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsDelete() const {
return type_ == -1 && slot_ == -1 && bag_index_ == -1 && aug_index_ == -1;
}
bool EQEmu::InventorySlot::IsBank() const {
if(type_ == InvTypeBank && EQEmu::ValueWithin(slot_, 0, 23)) {
return true;
}
if(type_ == InvTypeSharedBank && EQEmu::ValueWithin(slot_, 0, 1)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsCursor() const {
if(type_ == InvTypePersonal && slot_ == PersonalSlotCursor) {
return true;
}
if(type_ == InvTypeCursorBuffer) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsEquipment() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotAmmo)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsGeneral() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotGeneral1, PersonalSlotGeneral10)) {
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsWeapon() const {
if(type_ == InvTypePersonal &&
(EQEmu::ValueWithin(slot_, PersonalSlotPrimary, PersonalSlotSecondary) || slot_ == PersonalSlotRange))
{
return true;
}
return false;
}
bool EQEmu::InventorySlot::IsTrade() const {
if(type_ == InvTypeTrade) {
return true;
}
return false;
}
const std::string EQEmu::InventorySlot::ToString() const {
return StringFormat("(%i, %i, %i, %i)", type_, slot_, bag_index_, aug_index_);
}
struct EQEmu::Inventory::impl
{
std::map<int, ItemContainer> containers_;
int race_;
int class_;
int deity_;
std::unique_ptr<InventoryDataModel> data_model_;
};
EQEmu::Inventory::Inventory(int race, int class_, int deity) {
impl_ = new impl;
impl_->race_ = race;
impl_->class_ = class_;
impl_->deity_ = deity;
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(new InventoryNullDataModel());
}
EQEmu::Inventory::~Inventory() {
delete impl_;
}
void EQEmu::Inventory::SetRace(int race) {
impl_->race_ = race;
}
void EQEmu::Inventory::SetClass(int class_) {
impl_->class_ = class_;
}
void EQEmu::Inventory::SetDeity(int deity) {
impl_->deity_ = deity;
}
void EQEmu::Inventory::SetDataModel(InventoryDataModel *dm) {
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(dm);
}
EQEmu::ItemInstance::pointer EQEmu::Inventory::Get(const InventorySlot &slot) {
auto iter = impl_->containers_.find(slot.Type());
if(iter != impl_->containers_.end()) {
auto item = iter->second.Get(slot.Slot());
if(item) {
if(slot.BagIndex() > -1) {
auto sub_item = item->Get(slot.BagIndex());
if(sub_item) {
if(slot.AugIndex() > -1) {
return sub_item->Get(slot.AugIndex());
} else {
return sub_item;
}
}
} else {
return item;
}
}
}
return ItemInstance::pointer(nullptr);
}
bool EQEmu::Inventory::Put(const InventorySlot &slot, ItemInstance::pointer &inst) {
if(impl_->containers_.count(slot.Type()) == 0) {
if(slot.Type() == 0) {
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.Type(), ItemContainer(new ItemContainerPersonalSerialization())));
} else {
impl_->containers_.insert(std::pair<int, ItemContainer>(slot.Type(), ItemContainer()));
}
}
//Verify item can be put into the slot requested
auto &container = impl_->containers_[slot.Type()];
if(slot.BagIndex() > -1) {
auto item = container.Get(slot.Slot());
if(!item)
return false;
if(slot.AugIndex() > -1) {
auto bag_item = item->Get(slot.BagIndex());
if(!bag_item) {
return false;
}
return bag_item->Put(slot.AugIndex(), inst);
} else {
return item->Put(slot.BagIndex(), inst);
}
} else {
if(slot.AugIndex() > -1) {
auto item = container.Get(slot.Slot());
if(!item)
return false;
return item->Put(slot.AugIndex(), inst);
}
return container.Put(slot.Slot(), inst);
}
return false;
}
bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest, int charges) {
if(src == dest) {
return true;
}
if(!src.IsValid()) {
return false;
}
if(src.Type() == InvTypeCursorBuffer || dest.Type() == InvTypeCursorBuffer) {
return true;
}
if(dest.IsDelete()) {
impl_->data_model_->Begin();
bool v = _destroy(src);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
if(!dest.IsValid()) {
return false;
}
auto i_src = Get(src);
auto i_dest = Get(dest);
if(!i_src) {
return false;
}
if(i_src->GetBaseItem()->ItemClass == ItemClassContainer && dest.BagIndex() > -1) {
if(i_src->GetContainer()->Size() > 0) {
return false;
}
}
if(dest.IsEquipment() && !CanEquip(i_src, dest)) {
return false;
}
//Check this -> trade no drop
if(dest.IsTrade() && i_src->IsNoDrop()) {
return false;
}
impl_->data_model_->Begin();
if(i_src->IsStackable()) {
//move # charges from src to dest
//0 means *all* the charges
if(charges == 0) {
charges = i_src->GetCharges();
}
//src needs to have that many charges
if(i_src->GetCharges() < charges) {
impl_->data_model_->Rollback();
return false;
}
//if dest exists it needs to not only be the same item id but also be able to hold enough charges to combine
//we can also swap if src id != dest id
if(i_dest) {
uint32 src_id = i_src->GetBaseItem()->ID;
uint32 dest_id = i_dest->GetBaseItem()->ID;
if(src_id != dest_id) {
bool v = _swap(src, dest);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
int charges_avail = i_dest->GetBaseItem()->StackSize - i_dest->GetCharges();
if(charges_avail < charges) {
impl_->data_model_->Rollback();
return false;
}
if(i_src->GetCharges() == charges) {
if(!_destroy(src)) {
impl_->data_model_->Rollback();
return false;
}
} else {
i_src->SetCharges(i_src->GetCharges() - charges);
impl_->data_model_->Insert(src, i_src);
}
i_dest->SetCharges(i_dest->GetCharges() + charges);
impl_->data_model_->Delete(dest);
impl_->data_model_->Insert(dest, i_dest);
impl_->data_model_->Commit();
return true;
} else {
//if dest does not exist and src charges > # charges then we need to create a new item with # charges in dest
//if dest does not exist and src charges == # charges then we need to swap src to dest
if(i_src->GetCharges() > charges) {
auto split = i_src->Split(charges);
if(!split) {
impl_->data_model_->Rollback();
return false;
}
Put(dest, split);
impl_->data_model_->Delete(src);
impl_->data_model_->Delete(dest);
impl_->data_model_->Insert(src, i_src);
impl_->data_model_->Insert(dest, split);
impl_->data_model_->Commit();
return true;
} else {
bool v = _swap(src, dest);
if(v) {
impl_->data_model_->Commit();
} else {
impl_->data_model_->Rollback();
}
return v;
}
}
} else {
bool v = _swap(src, dest);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
impl_->data_model_->Commit();
return true;
}
bool EQEmu::Inventory::Summon(const InventorySlot &slot, ItemInstance::pointer &inst) {
if(!inst)
return false;
if(CheckLoreConflict(inst->GetBaseItem())) {
return false;
}
auto cur = Get(slot);
if(cur) {
if(slot.IsCursor()) {
PushToCursorBuffer(inst);
}
return false;
}
impl_->data_model_->Begin();
bool v = Put(slot, inst);
if(v) {
impl_->data_model_->Insert(slot, inst);
impl_->data_model_->Commit();
} else {
impl_->data_model_->Rollback();
}
return v;
}
bool EQEmu::Inventory::PushToCursorBuffer(ItemInstance::pointer &inst) {
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
impl_->containers_.insert(std::pair<int, ItemContainer>(InvTypeCursorBuffer, ItemContainer()));
}
int32 top = 0;
auto &container = impl_->containers_[InvTypeCursorBuffer];
auto iter = container.Begin();
while(iter != container.End()) {
top = iter->first;
++iter;
}
InventorySlot slot(InvTypeCursorBuffer, top + 1);
impl_->data_model_->Begin();
bool v = Put(slot, inst);
if(v) {
impl_->data_model_->Insert(slot, inst);
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
bool EQEmu::Inventory::PopFromCursorBuffer() {
InventorySlot cursor(InvTypePersonal, PersonalSlotCursor);
auto inst = Get(cursor);
if(inst) {
return false;
}
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
return false;
}
int32 top = 0;
auto &container = impl_->containers_[InvTypeCursorBuffer];
auto iter = container.Begin();
while(iter != container.End()) {
top = iter->first;
++iter;
}
InventorySlot slot(InvTypeCursorBuffer, top);
inst = Get(slot);
if(inst) {
impl_->data_model_->Begin();
bool v = _destroy(slot);
impl_->data_model_->Delete(slot);
if(!v) {
impl_->data_model_->Rollback();
return false;
}
v = Put(cursor, inst);
impl_->data_model_->Insert(cursor, inst);
if(!v) {
impl_->data_model_->Rollback();
return false;
}
impl_->data_model_->Commit();
return true;
}
return false;
}
EQEmu::InventorySlot EQEmu::Inventory::FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) {
bool for_bag = inst->GetItem()->ItemClass == ItemClassContainer;
int min_size = inst->GetItem()->Size;
bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow;
//check upper level inventory
for(int i = slot_id_start; i <= slot_id_end; ++i) {
EQEmu::InventorySlot slot(container_id, i);
if(!Get(slot)) {
return slot;
}
}
//if not for a bag then check inside bags
if (!for_bag) {
for(int i = slot_id_start; i <= slot_id_end; ++i) {
EQEmu::InventorySlot slot(container_id, i);
auto inst = Get(slot);
if(inst && inst->GetBaseItem()->ItemClass == ItemClassContainer && inst->GetBaseItem()->BagSize >= min_size)
{
if(inst->GetBaseItem()->BagType == BagTypeQuiver && !is_arrow)
{
continue;
}
int slots = inst->GetBaseItem()->BagSlots;
for(int b_i = 0; b_i < slots; ++b_i) {
EQEmu::InventorySlot bag_slot(container_id, i, b_i);
if(!Get(bag_slot)) {
return bag_slot;
}
}
}
}
}
return EQEmu::InventorySlot();
}
int EQEmu::Inventory::FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end) {
if(!inst->IsStackable()) {
return 0;
}
bool is_arrow = inst->GetItem()->ItemType == ItemTypeArrow;
int item_id = inst->GetItem()->ID;
int charges_to_check = inst->GetCharges();
int charges = 0;
auto iter = impl_->containers_.find(container_id);
if(iter == impl_->containers_.end()) {
return 0;
}
auto &container = iter->second;
for(int i = slot_id_start; i <= slot_id_end; ++i) {
auto current = container.Get(i);
if(!current) {
continue;
}
if(current->GetItem()->ID == item_id) {
int free_charges = current->GetItem()->StackSize - current->GetCharges();
if(free_charges)
charges += free_charges;
if(charges >= charges_to_check) {
return charges_to_check;
}
} else if(current->GetItem()->ItemClass == ItemClassContainer) {
int sz = current->GetItem()->BagSlots;
for(int i = 0; i < sz; ++i) {
auto sub_item = current->Get(i);
if(!sub_item) {
continue;
}
if(sub_item->GetItem()->ID == item_id) {
int free_charges = sub_item->GetItem()->StackSize - sub_item->GetCharges();
if(free_charges)
charges += free_charges;
if(charges >= charges_to_check) {
return charges_to_check;
}
}
}
}
}
if(charges >= charges_to_check) {
return charges_to_check;
}
return charges;
}
void EQEmu::Inventory::UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst) {
impl_->data_model_->Begin();
impl_->data_model_->Delete(slot);
if(inst) {
impl_->data_model_->Insert(slot, inst);
}
impl_->data_model_->Commit();
}
int EQEmu::Inventory::CalcMaterialFromSlot(const InventorySlot &slot) {
if(slot.Type() != 0)
return _MaterialInvalid;
switch(slot.Slot()) {
case PersonalSlotHead:
return MaterialHead;
case PersonalSlotChest:
return MaterialChest;
case PersonalSlotArms:
return MaterialArms;
case PersonalSlotWrist1:
return MaterialWrist;
case PersonalSlotHands:
return MaterialHands;
case PersonalSlotLegs:
return MaterialLegs;
case PersonalSlotFeet:
return MaterialFeet;
case PersonalSlotPrimary:
return MaterialPrimary;
case PersonalSlotSecondary:
return MaterialSecondary;
default:
return _MaterialInvalid;
}
}
EQEmu::InventorySlot EQEmu::Inventory::CalcSlotFromMaterial(int material) {
switch(material)
{
case MaterialHead:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHead);
case MaterialChest:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotChest);
case MaterialArms:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotArms);
case MaterialWrist:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotWrist1);
case MaterialHands:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotHands);
case MaterialLegs:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotLegs);
case MaterialFeet:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotFeet);
case MaterialPrimary:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotPrimary);
case MaterialSecondary:
return EQEmu::InventorySlot(InvTypePersonal, PersonalSlotSecondary);
default:
return EQEmu::InventorySlot(-1, -1);
}
}
bool EQEmu::Inventory::CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot) {
if(!inst) {
return false;
}
if(slot.Type() != 0) {
return false;
}
if(!EQEmu::ValueWithin(slot.Slot(), EQEmu::PersonalSlotCharm, EQEmu::PersonalSlotAmmo)) {
return false;
}
auto item = inst->GetItem();
//check slot
int use_slot = -1;
if(slot.Slot() == EQEmu::PersonalSlotPowerSource) {
use_slot = EQEmu::PersonalSlotAmmo;
}
else if(slot.Slot() == EQEmu::PersonalSlotAmmo) {
use_slot = EQEmu::PersonalSlotPowerSource;
}
else {
use_slot = slot.Slot();
}
if(!(item->Slots & (1 << use_slot))) {
return false;
}
//todo: check deity
if(!item->IsEquipable(impl_->race_, impl_->class_)) {
return false;
}
//Checking augments
auto iter = inst->GetContainer()->Begin();
auto end = inst->GetContainer()->End();
while(iter != end) {
EQEmu::ItemInstance::pointer itm = iter->second;
if(!CanEquip(itm, InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first))) {
return false;
}
++iter;
}
return true;
}
bool EQEmu::Inventory::CheckLoreConflict(const ItemData *item) {
if(!item)
return false;
if(!item->LoreFlag)
return false;
if(item->LoreGroup == 0)
return false;
if(item->LoreGroup == 0xFFFFFFFF) {
//look everywhere except shared bank
for(auto &container : impl_->containers_) {
if(container.first != InvTypeSharedBank && container.second.HasItem(item->ID)) {
return true;
}
}
}
else {
//look everywhere except shared bank
for(auto &container : impl_->containers_) {
if(container.first != InvTypeSharedBank && container.second.HasItemByLoreGroup(item->LoreGroup)) {
return true;
}
}
}
return false;
}
bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) {
buf.SetWritePosition(0);
buf.SetReadPosition(0);
buf.Resize(0);
buf.Write<int32>(105);
bool value = false;
for(auto &iter : impl_->containers_) {
bool v = iter.second.Serialize(buf, iter.first);
if(v && !value) {
value = true;
}
}
return value;
}
void EQEmu::Inventory::Interrogate() {
printf("Inventory:\n");
printf("Class: %u, Race: %u, Deity: %u\n", impl_->class_, impl_->race_, impl_->deity_);
for(auto &iter : impl_->containers_) {
printf("Container: %u\n", iter.first);
iter.second.Interrogate(1);
}
printf("\n");
}
bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest) {
auto src_i = Get(src);
auto dest_i = Get(dest);
if(src_i) {
if(!_destroy(src)) {
return false;
}
}
if(dest_i) {
if(!_destroy(dest)) {
return false;
}
impl_->data_model_->Insert(src, dest_i);
if(!Put(src, dest_i)) {
return false;
}
}
if(src_i) {
impl_->data_model_->Insert(dest, src_i);
if(!Put(dest, src_i)) {
return false;
}
}
return true;
}
bool EQEmu::Inventory::_destroy(const InventorySlot &slot) {
bool v = Put(slot, EQEmu::ItemInstance::pointer(nullptr));
impl_->data_model_->Delete(slot);
return v;
}
+165
View File
@@ -0,0 +1,165 @@
/* 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 COMMON_INVENTORY_H
#define COMMON_INVENTORY_H
#include "item_container.h"
#include <string>
namespace EQEmu
{
enum InventoryType : int
{
InvTypePersonal = 0,
InvTypeBank,
InvTypeSharedBank,
InvTypeTrade,
InvTypeWorld,
InvTypeCursorBuffer,
InvTypeTribute,
InvTypeTrophyTribute,
InvTypeGuildTribute,
InvTypeMerchant
};
enum PersonaInventorySlot : int
{
PersonalSlotCharm = 0,
PersonalSlotEar1,
PersonalSlotHead,
PersonalSlotFace,
PersonalSlotEar2,
PersonalSlotNeck,
PersonalSlotShoulders,
PersonalSlotArms,
PersonalSlotBack,
PersonalSlotWrist1,
PersonalSlotWrist2,
PersonalSlotRange,
PersonalSlotHands,
PersonalSlotPrimary,
PersonalSlotSecondary,
PersonalSlotFinger1,
PersonalSlotFinger2,
PersonalSlotChest,
PersonalSlotLegs,
PersonalSlotFeet,
PersonalSlotWaist,
PersonalSlotPowerSource,
PersonalSlotAmmo,
PersonalSlotGeneral1,
PersonalSlotGeneral2,
PersonalSlotGeneral3,
PersonalSlotGeneral4,
PersonalSlotGeneral5,
PersonalSlotGeneral6,
PersonalSlotGeneral7,
PersonalSlotGeneral8,
PersonalSlotGeneral9,
PersonalSlotGeneral10,
PersonalSlotCursor
};
class InventorySlot
{
public:
InventorySlot() : type_(-1), slot_(-1), bag_index_(-1), aug_index_(-1) { }
InventorySlot(int type, int slot)
: type_(type), slot_(slot), bag_index_(-1), aug_index_(-1) { }
InventorySlot(int type, int slot, int bag_index)
: type_(type), slot_(slot), bag_index_(bag_index), aug_index_(-1) { }
InventorySlot(int type, int slot, int bag_index, int aug_index)
: type_(type), slot_(slot), bag_index_(bag_index), aug_index_(aug_index) { }
bool IsValid() const;
bool IsDelete() const;
bool IsBank() const;
bool IsCursor() const;
bool IsEquipment() const;
bool IsGeneral() const;
bool IsWeapon() const;
bool IsTrade() const;
const std::string ToString() const;
inline int Type() { return type_; }
inline int Type() const { return type_; }
inline int Slot() { return slot_; }
inline int Slot() const { return slot_; }
inline int BagIndex() { return bag_index_; }
inline int BagIndex() const { return bag_index_; }
inline int AugIndex() { return aug_index_; }
inline int AugIndex() const { return aug_index_; }
private:
int type_;
int slot_;
int bag_index_;
int aug_index_;
};
inline bool operator==(const InventorySlot &lhs, const InventorySlot &rhs) {
return lhs.Type() == rhs.Type() &&
lhs.Slot() == rhs.Slot() &&
lhs.BagIndex() == rhs.BagIndex() &&
lhs.AugIndex() == rhs.AugIndex(); }
inline bool operator!=(const InventorySlot &lhs, const InventorySlot &rhs) { return !(lhs == rhs); }
class InventoryDataModel;
class Inventory
{
public:
Inventory(int race, int class_, int deity);
~Inventory();
void SetRace(int race);
void SetClass(int class_);
void SetDeity(int deity);
void SetDataModel(InventoryDataModel *dm);
ItemInstance::pointer Get(const InventorySlot &slot);
bool Put(const InventorySlot &slot, ItemInstance::pointer &inst);
bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges);
bool Summon(const InventorySlot &slot, ItemInstance::pointer &inst);
bool PushToCursorBuffer(ItemInstance::pointer &inst);
bool PopFromCursorBuffer();
InventorySlot FindFreeSlot(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end);
int FindFreeStackSlots(ItemInstance::pointer &inst, int container_id, int slot_id_start, int slot_id_end);
void UpdateSlot(const InventorySlot &slot, ItemInstance::pointer &inst);
//utility
static int CalcMaterialFromSlot(const InventorySlot &slot);
static InventorySlot CalcSlotFromMaterial(int material);
bool CanEquip(EQEmu::ItemInstance::pointer &inst, const EQEmu::InventorySlot &slot);
bool CheckLoreConflict(const ItemData *item);
bool Serialize(MemoryBuffer &buf);
//testing
void Interrogate();
private:
bool _swap(const InventorySlot &src, const InventorySlot &dest);
bool _destroy(const InventorySlot &slot);
struct impl;
impl *impl_;
};
} // EQEmu
#endif
@@ -16,23 +16,25 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_RANK_EFFECTS_H
#define EQEMU_ZONE_AA_RANK_EFFECTS_H
#ifndef COMMON_INVENTORY_DATA_MODEL_H
#define COMMON_INVENTORY_DATA_MODEL_H
#include "../common/global_define.h"
#include <string>
#include "inventory.h"
namespace AA
namespace EQEmu
{
struct RankEffect
{
int slot;
int effect_id;
int base1;
int base2;
};
}
class InventoryDataModel
{
public:
InventoryDataModel() { }
virtual ~InventoryDataModel() { }
virtual void Begin() = 0;
virtual bool Commit() = 0;
virtual void Rollback() = 0;
virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst) = 0;
virtual void Delete(const InventorySlot &slot) = 0;
};
} // EQEmu
#endif
+212
View File
@@ -0,0 +1,212 @@
#include "inventory_db_data_model.h"
#include "shareddb.h"
#include "string_util.h"
#include <list>
#include <string>
enum DataEventTypes
{
DB_Insert,
DB_Delete
};
struct DataEvent
{
DataEventTypes evt;
EQEmu::InventorySlot slot;
EQEmu::ItemInstance::pointer inst;
};
struct EQEmu::InventoryDatabaseDataModel::impl {
SharedDatabase *db_;
std::list<DataEvent> events_;
uint32 char_id_;
};
EQEmu::InventoryDatabaseDataModel::InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id) {
impl_ = new impl;
impl_->db_ = db;
impl_->char_id_ = char_id;
}
EQEmu::InventoryDatabaseDataModel::~InventoryDatabaseDataModel() {
delete impl_;
}
void EQEmu::InventoryDatabaseDataModel::Begin() {
impl_->db_->TransactionBegin();
impl_->events_.clear();
}
bool EQEmu::InventoryDatabaseDataModel::Commit() {
std::string base_insert = "INSERT INTO character_inventory(id, type, slot, bag_index, aug_index, "
"item_id, charges, color, attuned, custom_data, ornament_icon, ornament_idfile, ornament_hero_model"
", tracking_id) VALUES";
std::string current_insert = base_insert;
bool insert = false;
for(auto iter : impl_->events_) {
if(iter.evt == DB_Delete) {
if(insert) {
insert = false;
//commit the current_insert
auto res = impl_->db_->QueryDatabase(current_insert);
if(!res.Success()) {
Rollback();
return false;
}
current_insert = base_insert;
}
std::string current_delete;
if(iter.slot.BagIndex() > -1) {
if(iter.slot.AugIndex() > -1) {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u AND aug_index=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex(), iter.slot.AugIndex());
}
else {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex());
}
}
else if(iter.slot.AugIndex() > -1) {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND aug_index=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.AugIndex());
}
else {
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u",
impl_->char_id_, iter.slot.Type(), iter.slot.Slot());
}
auto res = impl_->db_->QueryDatabase(current_delete);
if(!res.Success()) {
Rollback();
return false;
}
} else {
//insert
if(!insert) {
insert = true;
} else {
current_insert += ",";
}
current_insert += StringFormat("(%u, %i, %i, %i, %i, %u, %i, %u, %u, '%s', %u, %u, %u, %llu)",
impl_->char_id_,
iter.slot.Type(),
iter.slot.Slot(),
iter.slot.BagIndex(),
iter.slot.AugIndex(),
iter.inst->GetBaseItem()->ID,
iter.inst->GetCharges(),
iter.inst->GetColor(),
iter.inst->GetAttuned(),
EscapeString(iter.inst->GetCustomData()).c_str(),
iter.inst->GetOrnamentIcon(),
iter.inst->GetOrnamentIDFile(),
iter.inst->GetOrnamentHeroModel(),
iter.inst->GetTrackingID());
}
}
if(insert) {
insert = false;
//commit the current_insert
auto res = impl_->db_->QueryDatabase(current_insert);
if(!res.Success()) {
Rollback();
return false;
}
current_insert = base_insert;
}
impl_->db_->TransactionCommit();
impl_->events_.clear();
return true;
}
void EQEmu::InventoryDatabaseDataModel::Rollback() {
impl_->db_->TransactionRollback();
impl_->events_.clear();
}
void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, ItemInstance::pointer &inst) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = inst;
evt.slot = slot;
impl_->events_.push_back(evt);
//insert current item
if(slot.BagIndex() < 0 && slot.AugIndex() < 0) {
//if bag put all bag contents in
//if common put all augment contents in
if(inst->GetBaseItem()->ItemClass == ItemClassContainer) {
auto container = inst->GetContainer();
auto iter = container->Begin();
while(iter != container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, -1);
impl_->events_.push_back(evt);
//do augments here
if(evt.inst->GetBaseItem()->ItemClass == ItemClassCommon) {
auto inst_container = evt.inst->GetContainer();
auto inst_iter = inst_container->Begin();
while(inst_iter != inst_container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = inst_iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, inst_iter->first);
impl_->events_.push_back(evt);
++inst_iter;
}
}
++iter;
}
}
else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) {
auto container = inst->GetContainer();
auto iter = container->Begin();
while(iter != container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first);
impl_->events_.push_back(evt);
++iter;
}
}
}
else if(slot.AugIndex() < 0 && inst->GetBaseItem()->ItemClass == ItemClassCommon) {
//bag item that can have augs
//if common put all augment contents in
auto container = inst->GetContainer();
auto iter = container->Begin();
while(iter != container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first);
impl_->events_.push_back(evt);
++iter;
}
}
}
void EQEmu::InventoryDatabaseDataModel::Delete(const InventorySlot &slot) {
DataEvent evt;
evt.evt = DB_Delete;
evt.slot = slot;
impl_->events_.push_back(evt);
}
@@ -16,46 +16,30 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_ABILITY_H
#define EQEMU_ZONE_AA_ABILITY_H
#ifndef COMMON_INVENTORY_DB_DATA_MODEL_H
#define COMMON_INVENTORY_DB_DATA_MODEL_H
#include "../common/global_define.h"
#include <unordered_map>
#include <vector>
#include <memory>
#include "aa_rank_effects.h"
#include "aa_rank.h"
#include "inventory_data_model.h"
class Mob;
class SharedDatabase;
namespace AA
namespace EQEmu
{
class Ability
{
public:
Ability() { }
~Ability() { }
Rank *GetMaxRank();
Rank *GetRankByPointsSpent(int current_level);
int GetMaxLevel(Mob *who);
int id;
std::string name;
int category;
int classes;
int races;
int deities;
int drakkin_heritage;
int status;
bool grant_only;
int type;
int charges;
int first_rank_id;
Rank *first;
};
}
class InventoryDatabaseDataModel : public InventoryDataModel
{
public:
InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id);
virtual ~InventoryDatabaseDataModel();
virtual void Begin();
virtual bool Commit();
virtual void Rollback();
virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst);
virtual void Delete(const InventorySlot &slot);
private:
struct impl;
impl *impl_;
};
} // EQEmu
#endif
@@ -16,41 +16,25 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_RANK_H
#define EQEMU_ZONE_AA_RANK_H
#ifndef COMMON_INVENTORY_NULL_DATA_MODEL_H
#define COMMON_INVENTORY_NULL_DATA_MODEL_H
namespace AA
#include "inventory_data_model.h"
namespace EQEmu
{
class Ability;
class Rank
{
public:
Rank() { }
~Rank() { }
int id;
int upper_hotkey_sid;
int lower_hotkey_sid;
int title_sid;
int desc_sid;
int cost;
int level_req;
int spell;
int spell_type;
int recast_time;
int prev_id;
Rank *prev;
int next_id;
Rank *next;
int current_value;
int expansion;
int total_cost;
Ability *base_ability;
std::vector<RankEffect> effects;
std::map<int, int> prereqs;
};
}
class InventoryNullDataModel : public InventoryDataModel
{
public:
InventoryNullDataModel() { }
virtual ~InventoryNullDataModel() { }
virtual void Begin() { }
virtual bool Commit() { return true; }
virtual void Rollback() { }
virtual void Insert(const InventorySlot &slot, ItemInstance::pointer &inst) { }
virtual void Delete(const InventorySlot &slot) { }
};
} // EQEmu
#endif
+102 -820
View File
File diff suppressed because it is too large Load Diff
+15 -68
View File
@@ -27,9 +27,8 @@ class ItemParse; // Parses item packets
class EvolveInfo; // Stores information about an evolving item family
#include "../common/eq_constants.h"
#include "../common/item_struct.h"
#include "../common/item_data.h"
#include "../common/timer.h"
#include "../common/bodytypes.h"
#include <list>
#include <map>
@@ -105,9 +104,9 @@ protected:
};
// ########################################
// Class: Inventory
// Class: InventoryOld
// Character inventory
class Inventory
class InventoryOld
{
friend class ItemInst;
public:
@@ -115,8 +114,8 @@ public:
// Public Methods
///////////////////////////////
Inventory() { m_version = ClientVersion::Unknown; m_versionset = false; }
~Inventory();
InventoryOld() { m_version = ClientVersion::Unknown; m_versionset = false; }
~InventoryOld();
// Inventory v2 creep
bool SetInventoryVersion(ClientVersion version) {
@@ -169,7 +168,7 @@ public:
ItemInst* PopItem(int16 slot_id);
// Check whether there is space for the specified number of the specified item.
bool HasSpaceForItem(const Item_Struct *ItemToTry, int16 Quantity);
bool HasSpaceForItem(const ItemData *ItemToTry, int16 Quantity);
// Check whether item exists in inventory
// where argument specifies OR'd list of invWhere constants to look
@@ -194,7 +193,7 @@ public:
static int16 CalcSlotFromMaterial(uint8 material);
static uint8 CalcMaterialFromSlot(int16 equipslot);
static bool CanItemFitInContainer(const Item_Struct *ItemToTry, const Item_Struct *Container);
static bool CanItemFitInContainer(const ItemData *ItemToTry, const ItemData *Container);
// Test for valid inventory casting slot
bool SupportsClickCasting(int16 slot_id);
@@ -271,7 +270,7 @@ public:
/////////////////////////
// Constructors/Destructor
ItemInst(const Item_Struct* item = nullptr, int16 charges = 0);
ItemInst(const ItemData* item = nullptr, int16 charges = 0);
ItemInst(SharedDatabase *db, uint32 item_id, int16 charges = 0);
@@ -332,7 +331,7 @@ public:
bool IsAugmented();
ItemInst* GetOrnamentationAug(int32 ornamentationAugtype) const;
bool UpdateOrnamentationInfo();
static bool CanTransform(const Item_Struct *ItemToTry, const Item_Struct *Container, bool AllowAll = false);
static bool CanTransform(const ItemData *ItemToTry, const ItemData *Container, bool AllowAll = false);
// Has attack/delay?
bool IsWeapon() const;
@@ -341,8 +340,8 @@ public:
// Accessors
const uint32 GetID() const { return ((m_item) ? m_item->ID : NO_ITEM); }
const uint32 GetItemScriptID() const { return ((m_item) ? m_item->ScriptFileID : NO_ITEM); }
const Item_Struct* GetItem() const;
const Item_Struct* GetUnscaledItem() const;
const ItemData* GetItem() const;
const ItemData* GetUnscaledItem() const;
int16 GetCharges() const { return m_charges; }
void SetCharges(int16 charges) { m_charges = charges; }
@@ -377,7 +376,7 @@ public:
// Allows treatment of this object as though it were a pointer to m_item
operator bool() const { return (m_item != nullptr); }
// Compare inner Item_Struct of two ItemInst objects
// Compare inner ItemData of two ItemInst objects
bool operator==(const ItemInst& right) const { return (this->m_item == right.m_item); }
bool operator!=(const ItemInst& right) const { return (this->m_item != right.m_item); }
@@ -419,58 +418,6 @@ public:
void StopTimer(std::string name);
void ClearTimers();
// Get a total of a stat, including augs
// These functions should be used in place of other code manually totaling
// to centralize where it is done to make future changes easier (ex. whenever powersources come around)
// and to minimize errors. CalcItemBonuses however doesn't use these in interest of performance
// by default these do not recurse into augs
int GetItemArmorClass(bool augments = false) const;
int GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments = false) const;
// These two differ in the fact that they're quick checks (they are checked BEFORE the one above
int GetItemElementalFlag(bool augments = false) const;
int GetItemElementalDamage(bool augments = false) const;
int GetItemRecommendedLevel(bool augments = false) const;
int GetItemRequiredLevel(bool augments = false) const;
int GetItemWeaponDamage(bool augments = false) const;
int GetItemBackstabDamage(bool augments = false) const;
// these two are just quick checks
int GetItemBaneDamageBody(bool augments = false) const;
int GetItemBaneDamageRace(bool augments = false) const;
int GetItemBaneDamageBody(bodyType against, bool augments = false) const;
int GetItemBaneDamageRace(uint16 against, bool augments = false) const;
int GetItemMagical(bool augments = false) const;
int GetItemHP(bool augments = false) const;
int GetItemMana(bool augments = false) const;
int GetItemEndur(bool augments = false) const;
int GetItemAttack(bool augments = false) const;
int GetItemStr(bool augments = false) const;
int GetItemSta(bool augments = false) const;
int GetItemDex(bool augments = false) const;
int GetItemAgi(bool augments = false) const;
int GetItemInt(bool augments = false) const;
int GetItemWis(bool augments = false) const;
int GetItemCha(bool augments = false) const;
int GetItemMR(bool augments = false) const;
int GetItemFR(bool augments = false) const;
int GetItemCR(bool augments = false) const;
int GetItemPR(bool augments = false) const;
int GetItemDR(bool augments = false) const;
int GetItemCorrup(bool augments = false) const;
int GetItemHeroicStr(bool augments = false) const;
int GetItemHeroicSta(bool augments = false) const;
int GetItemHeroicDex(bool augments = false) const;
int GetItemHeroicAgi(bool augments = false) const;
int GetItemHeroicInt(bool augments = false) const;
int GetItemHeroicWis(bool augments = false) const;
int GetItemHeroicCha(bool augments = false) const;
int GetItemHeroicMR(bool augments = false) const;
int GetItemHeroicFR(bool augments = false) const;
int GetItemHeroicCR(bool augments = false) const;
int GetItemHeroicPR(bool augments = false) const;
int GetItemHeroicDR(bool augments = false) const;
int GetItemHeroicCorrup(bool augments = false) const;
int GetItemHaste(bool augments = false) const;
protected:
//////////////////////////
// Protected Members
@@ -478,13 +425,13 @@ protected:
std::map<uint8, ItemInst*>::const_iterator _cbegin() { return m_contents.cbegin(); }
std::map<uint8, ItemInst*>::const_iterator _cend() { return m_contents.cend(); }
friend class Inventory;
friend class InventoryOld;
void _PutItem(uint8 index, ItemInst* inst) { m_contents[index] = inst; }
ItemInstTypes m_use_type; // Usage type for item
const Item_Struct* m_item; // Ptr to item data
const ItemData* m_item; // Ptr to item data
int16 m_charges; // # of charges for chargeable items
uint32 m_price; // Bazaar /trader price
uint32 m_color;
@@ -496,7 +443,7 @@ protected:
uint32 m_exp;
int8 m_evolveLvl;
bool m_activated;
Item_Struct* m_scaledItem;
ItemData* m_scaledItem;
EvolveInfo* m_evolveInfo;
bool m_scaling;
uint32 m_ornamenticon;
+135
View File
@@ -0,0 +1,135 @@
#include "item_container.h"
#include "item_container_default_serialization.h"
#include <utility>
struct EQEmu::ItemContainer::impl
{
std::map<int, ItemInstance::pointer> items_;
ItemContainerSerializationStrategy *serialize_strat_;
};
EQEmu::ItemContainer::ItemContainer()
{
impl_ = new impl();
impl_->serialize_strat_ = new ItemContainerDefaultSerialization();
}
EQEmu::ItemContainer::ItemContainer(ItemContainerSerializationStrategy *strategy) {
impl_ = new impl();
impl_->serialize_strat_ = strategy;
}
EQEmu::ItemContainer::~ItemContainer()
{
if(impl_) {
delete impl_->serialize_strat_;
delete impl_;
}
}
EQEmu::ItemContainer::ItemContainer(ItemContainer &&other) {
impl_ = other.impl_;
other.impl_ = nullptr;
}
EQEmu::ItemContainer& EQEmu::ItemContainer::operator=(ItemContainer &&other) {
if(this == &other)
return *this;
impl_ = other.impl_;
other.impl_ = nullptr;
return *this;
}
EQEmu::ItemInstance::pointer EQEmu::ItemContainer::Get(const int slot_id) {
auto iter = impl_->items_.find(slot_id);
if(iter != impl_->items_.end()) {
return iter->second;
}
return EQEmu::ItemInstance::pointer(nullptr);
}
bool EQEmu::ItemContainer::Put(const int slot_id, ItemInstance::pointer &inst) {
if(!inst) {
impl_->items_.erase(slot_id);
return true;
} else {
auto iter = impl_->items_.find(slot_id);
if(iter == impl_->items_.end()) {
impl_->items_[slot_id] = inst;
return true;
}
}
return false;
}
bool EQEmu::ItemContainer::HasItem(uint32 item_id) {
for(auto &item : impl_->items_) {
if(item.second->GetBaseItem()->ID == item_id) {
return true;
}
}
return false;
}
bool EQEmu::ItemContainer::HasItemByLoreGroup(uint32 loregroup) {
if(loregroup == 0xFFFFFFFF)
return false;
for(auto &item : impl_->items_) {
if(item.second->GetBaseItem()->LoreGroup == loregroup) {
return true;
}
}
return false;
}
uint32 EQEmu::ItemContainer::Size() {
return (uint32)impl_->items_.size();
}
uint32 EQEmu::ItemContainer::Size() const {
return (uint32)impl_->items_.size();
}
bool EQEmu::ItemContainer::Delete(const int slot_id) {
auto iter = impl_->items_.find(slot_id);
if(iter == impl_->items_.end()) {
return false;
} else {
impl_->items_.erase(iter);
return true;
}
}
bool EQEmu::ItemContainer::Serialize(MemoryBuffer &buf, int container_number) {
if(impl_->serialize_strat_) {
return impl_->serialize_strat_->Serialize(buf, container_number, impl_->items_);
}
return false;
}
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::Begin() {
return impl_->items_.begin();
}
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::End() {
return impl_->items_.end();
}
void EQEmu::ItemContainer::Interrogate(int level) {
char buffer[16] = { 0 };
for(int i = 0; i < level; ++i) {
buffer[i] = '\t';
}
for(auto &iter : impl_->items_) {
printf("%s%u: (%u)%s (%u)\n", buffer, iter.first, iter.second->GetBaseItem()->ID, iter.second->GetBaseItem()->Name, iter.second->GetCharges());
iter.second->Interrogate(level + 1);
}
}
+70
View File
@@ -0,0 +1,70 @@
/* 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 COMMON_ITEM_CONTAINER_H
#define COMMON_ITEM_CONTAINER_H
#include "item_instance.h"
#include "item_container_serialization_strategy.h"
#include "memory_buffer.h"
#include <memory>
#include <map>
namespace EQEmu
{
class ItemContainerSerializationStrategy;
class ItemContainer
{
public:
typedef std::map<int, ItemInstance::pointer>::const_iterator ItemContainerIter;
ItemContainer();
ItemContainer(ItemContainerSerializationStrategy *strategy);
~ItemContainer();
ItemContainer(ItemContainer &&other);
ItemContainer& operator=(ItemContainer &&other);
ItemInstance::pointer Get(const int slot_id);
bool Put(const int slot_id, ItemInstance::pointer &inst);
bool Delete(const int slot_id);
//Utility
bool HasItem(uint32 item_id);
bool HasItemByLoreGroup(uint32 loregroup);
uint32 Size();
uint32 Size() const;
//Low level interface for encode/decode
bool Serialize(MemoryBuffer &buf, int container_number);
ItemContainerIter Begin();
ItemContainerIter End();
//testing
void Interrogate(int level);
protected:
struct impl;
impl *impl_;
private:
ItemContainer(const ItemContainer &other);
ItemContainer& operator=(const ItemContainer &other);
};
} // EQEmu
#endif
@@ -0,0 +1,19 @@
#include "item_container_default_serialization.h"
bool EQEmu::ItemContainerDefaultSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) {
if(items.size() == 0) {
return false;
}
bool ret = false;
for(auto &iter : items) {
buf.Write<int32>(container_number);
buf.Write<int32>(iter.first);
buf.Write<int32>(-1);
buf.Write<int32>(-1);
buf.Write<void*>(iter.second.get());
ret = true;
}
return ret;
}
@@ -0,0 +1,35 @@
/* 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 COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H
#define COMMON_ITEM_CONTAINER_DEFAULT_SERIALIZATION_H
#include "item_container_serialization_strategy.h"
namespace EQEmu
{
class ItemContainerDefaultSerialization : public ItemContainerSerializationStrategy
{
public:
ItemContainerDefaultSerialization() { }
virtual ~ItemContainerDefaultSerialization() { }
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items);
};
} // EQEmu
#endif
@@ -0,0 +1,21 @@
#include "item_container_personal_serialization.h"
bool EQEmu::ItemContainerPersonalSerialization::Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) {
if(items.size() == 0) {
return false;
}
bool ret = false;
for(auto &iter : items) {
if(iter.first < 33) {
buf.Write<int32>(container_number);
buf.Write<int32>(iter.first);
buf.Write<int32>(-1);
buf.Write<int32>(-1);
buf.Write<void*>(iter.second.get());
ret = true;
}
}
return ret;
}
@@ -0,0 +1,35 @@
/* 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 COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H
#define COMMON_ITEM_CONTAINER_PERSONAL_SERIALIZATION_H
#include "item_container_serialization_strategy.h"
namespace EQEmu
{
class ItemContainerPersonalSerialization : public ItemContainerSerializationStrategy
{
public:
ItemContainerPersonalSerialization() { }
virtual ~ItemContainerPersonalSerialization() { }
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items);
};
} // EQEmu
#endif
@@ -0,0 +1,37 @@
/* 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 COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H
#define COMMON_ITEM_CONTAINER_SERIALIZATION_STRATEGY_H
#include "item_container.h"
#include "memory_buffer.h"
#include <map>
namespace EQEmu
{
class ItemContainerSerializationStrategy
{
public:
ItemContainerSerializationStrategy() { }
virtual ~ItemContainerSerializationStrategy() { }
virtual bool Serialize(MemoryBuffer &buf, const int container_number, const std::map<int, ItemInstance::pointer>& items) = 0;
};
} // EQEmu
#endif
+20 -27
View File
@@ -16,8 +16,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 04111-1307 USA
*/
#ifndef ITEM_STRUCT_H
#define ITEM_STRUCT_H
#ifndef COMMON_ITEM_DATA_H
#define COMMON_ITEM_DATA_H
/*
* Note: (Doodman)
@@ -35,7 +35,7 @@
*
* Note #3: (Doodman)
* Please take care when adding new found data fields to add them
* to the appropriate structure. Item_Struct has elements that are
* to the appropriate structure. ItemData has elements that are
* global to all types of items only.
*
* Note #4: (Doodman)
@@ -46,12 +46,12 @@
#include "eq_dictionary.h"
/*
** Child struct of Item_Struct:
** Child struct of ItemData:
** Effect data: Click, Proc, Focus, Worn, Scroll
**
*/
struct ItemEffect_Struct {
int32 Effect;
int16 Effect;
uint8 Type;
uint8 Level;
uint8 Level2;
@@ -69,10 +69,18 @@ struct InternalSerializedItem_Struct {
const void * inst;
};
struct SerializedItemInstance_Struct {
int32 container_id;
int32 slot_id;
int32 bag_id;
int32 aug_id;
void *inst;
};
// use EmuConstants::ITEM_COMMON_SIZE
//#define MAX_AUGMENT_SLOTS 5
struct Item_Struct {
struct ItemData {
bool IsEquipable(uint16 Race, uint16 Class) const;
// Non packet based fields
uint8 MinStatus;
@@ -99,17 +107,10 @@ struct Item_Struct {
uint32 Favor; // Individual favor
uint32 GuildFavor; // Guild favor
uint32 PointType;
//uint32 Unk117;
//uint32 Unk118;
//uint32 Unk121;
//uint32 Unk124;
uint8 BagType; // 0:Small Bag, 1:Large Bag, 2:Quiver, 3:Belt Pouch ... there are 50 types
uint8 BagSlots; // Number of slots: can only be 2, 4, 6, 8, or 10
uint8 BagSlots; // Number of slots
uint8 BagSize; // 0:TINY, 1:SMALL, 2:MEDIUM, 3:LARGE, 4:GIANT
uint8 BagWR; // 0->100
bool BenefitFlag;
bool Tradeskills; // Is this a tradeskill item?
int8 CR; // Save vs Cold
@@ -128,9 +129,7 @@ struct Item_Struct {
int32 Mana; // Mana
int32 AC; // AC
uint32 Deity; // Bitmask of Deities that can equip this item
//uint32 Unk033
int32 SkillModValue; // % Mod to skill specified in SkillModType
int32 SkillModMax; // Max skill point modification
uint32 SkillModType; // Type of skill for SkillModValue to apply to
uint32 BaneDmgRace; // Bane Damage Race
int8 BaneDmgAmt; // Bane Damage Body Amount
@@ -151,13 +150,11 @@ struct Item_Struct {
uint32 Color; // RR GG BB 00 <-- as it appears in pc
uint32 Classes; // Bitfield of classes that can equip item (1 << class#)
uint32 Races; // Bitfield of races that can equip item (1 << race#)
//uint32 Unk054;
int16 MaxCharges; // Maximum charges items can hold: -1 if not a chargeable item
uint8 ItemType; // Item Type/Skill (itemClass* from above)
uint8 Material; // Item material type
uint32 HerosForgeModel;// Hero's Forge Armor Model Type (2-13?)
float SellRate; // Sell rate
//uint32 Unk059;
union {
uint32 Fulfilment; // Food fulfilment (How long it lasts)
int16 CastTime; // Cast Time for clicky effects, in milliseconds
@@ -212,17 +209,13 @@ struct Item_Struct {
int16 StackSize;
uint8 PotionBeltSlots;
ItemEffect_Struct Click, Proc, Worn, Focus, Scroll, Bard;
uint8 Book; // 0=Not book, 1=Book
uint32 BookType;
char Filename[33]; // Filename for book data
// Begin SoF Fields
int32 SVCorruption;
uint32 Purity;
uint8 EvolvingItem;
uint32 EvolvingID;
uint8 EvolvingLevel;
uint8 EvolvingMax;
uint32 BackstabDmg;
uint32 DSMitigation;
int32 HeroicStr;
@@ -244,11 +237,11 @@ struct Item_Struct {
uint32 ScriptFileID;
uint16 ExpendableArrow;
uint32 Clairvoyance;
char ClickName[65];
char ProcName[65];
char WornName[65];
char FocusName[65];
char ScrollName[65];
char ClickName[65];
char ProcName[65];
char WornName[65];
char FocusName[65];
char ScrollName[65];
};
-4
View File
@@ -41,7 +41,6 @@ F(ac)
F(deity)
F(skillmodvalue)
F(UNK033)
F(skillmodmax)
F(skillmodtype)
F(banedmgrace)
F(banedmgamt)
@@ -173,10 +172,7 @@ F(bardlevel)
F(questitemflag)
F(svcorruption)
F(purity)
F(evoitem)
F(evoid)
F(evolvinglevel)
F(evomax)
F(backstabdmg)
F(dsmitigation)
F(heroic_str)
+389
View File
@@ -0,0 +1,389 @@
/* 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 "item_instance.h"
#include "data_verification.h"
#include "item_container.h"
uint32 ItemInstanceSerial = 1;
uint32 EQEmu::GetNextItemInstanceSerial() {
ItemInstanceSerial++;
return ItemInstanceSerial;
}
struct EQEmu::ItemInstance::impl {
const ItemData *base_item_;
ItemData *modified_item_;
int16 charges_;
uint32 color_;
bool attuned_;
std::string custom_data_;
uint32 ornament_idfile_;
uint32 ornament_icon_;
uint32 ornament_hero_model_;
char tracking_id_[17];
uint32 serial_id_;
uint32 recast_timestamp_;
uint32 merchant_slot_;
uint32 merchant_count_;
uint32 price_;
ItemContainer contents_;
};
EQEmu::ItemInstance::ItemInstance(const ItemData* idata) {
impl_ = new impl;
impl_->base_item_ = idata;
impl_->modified_item_ = nullptr;
impl_->charges_ = -1;
impl_->color_ = 0;
impl_->attuned_ = false;
impl_->ornament_idfile_ = 0;
impl_->ornament_icon_ = 0;
impl_->ornament_hero_model_ = 0;
impl_->serial_id_ = 0;
impl_->recast_timestamp_ = 0;
impl_->merchant_slot_ = 0;
impl_->merchant_count_ = 0;
impl_->price_ = 0;
memset(impl_->tracking_id_, 0, 17);
}
EQEmu::ItemInstance::ItemInstance(const ItemData* idata, int16 charges) {
impl_ = new impl;
impl_->base_item_ = idata;
impl_->modified_item_ = nullptr;
impl_->charges_ = charges;
impl_->color_ = 0;
impl_->attuned_ = false;
impl_->ornament_idfile_ = 0;
impl_->ornament_icon_ = 0;
impl_->ornament_hero_model_ = 0;
impl_->recast_timestamp_ = 0;
impl_->serial_id_ = 0;
impl_->merchant_slot_ = 0;
impl_->merchant_count_ = 0;
impl_->price_ = 0;
memset(impl_->tracking_id_, 0, 17);
}
EQEmu::ItemInstance::~ItemInstance() {
delete impl_;
}
EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Split(int charges) {
if(!IsStackable()) {
//Can't split non stackable items!
return pointer(nullptr);
}
if(charges >= GetCharges()) {
return pointer(nullptr);
}
if(impl_->contents_.Size() > 0) {
return pointer(nullptr);
}
pointer split = pointer(new EQEmu::ItemInstance(impl_->base_item_, charges));
split->SetSerialNumber(EQEmu::GetNextItemInstanceSerial());
//Set Tracking here
split->impl_->attuned_ = impl_->attuned_;
split->impl_->custom_data_ = impl_->custom_data_;
split->impl_->recast_timestamp_ = impl_->recast_timestamp_;
split->impl_->price_ = impl_->price_;
split->impl_->color_ = impl_->color_;
split->impl_->merchant_count_ = impl_->merchant_count_;
split->impl_->merchant_slot_ = impl_->merchant_slot_;
split->impl_->ornament_hero_model_ = impl_->ornament_hero_model_;
split->impl_->ornament_icon_ = impl_->ornament_icon_;
split->impl_->ornament_idfile_ = impl_->ornament_idfile_;
SetCharges(GetCharges() - charges);
return split;
}
const ItemData *EQEmu::ItemInstance::GetItem() {
return impl_->modified_item_ ? impl_->modified_item_ : impl_->base_item_;
}
const ItemData *EQEmu::ItemInstance::GetBaseItem() {
return impl_->base_item_;
}
const ItemData *EQEmu::ItemInstance::GetBaseItem() const {
return impl_->base_item_;
}
EQEmu::ItemInstance::pointer EQEmu::ItemInstance::Get(const int index) {
if(EQEmu::ValueWithin(index, 0, 255)) {
return impl_->contents_.Get(index);
}
return pointer(nullptr);
}
bool EQEmu::ItemInstance::Put(const int index, pointer &inst) {
if(!impl_->base_item_) {
return false;
}
auto item = impl_->base_item_;
if(item->ItemClass == ItemClassContainer) { // Bag
if(!EQEmu::ValueWithin(index, 0, item->BagSlots)) {
return false;
}
return impl_->contents_.Put(index, inst);
}
else if(item->ItemClass == ItemClassCommon) { // Augment
if(!EQEmu::ValueWithin(index, 0, EmuConstants::ITEM_COMMON_SIZE)) {
return false;
}
if(!item->AugSlotVisible[index]) {
return false;
}
if(inst) {
auto *aug_item = inst->GetItem();
int aug_type = aug_item->AugType;
if(aug_type == -1 || (1 << (item->AugSlotType[index] - 1)) & aug_type) {
return impl_->contents_.Put(index, inst);
}
} else {
return impl_->contents_.Put(index, inst);
}
return false;
}
return false;
}
int16 EQEmu::ItemInstance::GetCharges() {
return impl_->charges_;
}
int16 EQEmu::ItemInstance::GetCharges() const {
return impl_->charges_;
}
void EQEmu::ItemInstance::SetCharges(const int16 charges) {
impl_->charges_ = charges;
}
uint32 EQEmu::ItemInstance::GetColor() {
return impl_->color_;
}
uint32 EQEmu::ItemInstance::GetColor() const {
return impl_->color_;
}
void EQEmu::ItemInstance::SetColor(const uint32 color) {
impl_->color_ = color;
}
bool EQEmu::ItemInstance::GetAttuned() {
return impl_->attuned_;
}
bool EQEmu::ItemInstance::GetAttuned() const {
return impl_->attuned_;
}
void EQEmu::ItemInstance::SetAttuned(const bool attuned) {
impl_->attuned_ = attuned;
}
std::string EQEmu::ItemInstance::GetCustomData() {
return impl_->custom_data_;
}
std::string EQEmu::ItemInstance::GetCustomData() const {
return impl_->custom_data_;
}
void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) {
//We need to actually set the custom data stuff based on this string
impl_->custom_data_ = custom_data;
}
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() {
return impl_->ornament_idfile_;
}
uint32 EQEmu::ItemInstance::GetOrnamentIDFile() const {
return impl_->ornament_idfile_;
}
void EQEmu::ItemInstance::SetOrnamentIDFile(const uint32 ornament_idfile) {
impl_->ornament_idfile_ = ornament_idfile;
}
uint32 EQEmu::ItemInstance::GetOrnamentIcon() {
return impl_->ornament_icon_;
}
uint32 EQEmu::ItemInstance::GetOrnamentIcon() const {
return impl_->ornament_icon_;
}
void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) {
impl_->ornament_icon_ = ornament_icon;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() {
return impl_->ornament_hero_model_;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() const {
return impl_->ornament_hero_model_;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) {
uint32 hero_model = 0;
if(impl_->ornament_hero_model_ > 0)
{
hero_model = impl_->ornament_hero_model_;
if(material_slot >= 0)
{
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
}
}
return hero_model;
}
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) const {
uint32 hero_model = 0;
if(impl_->ornament_hero_model_ > 0)
{
hero_model = impl_->ornament_hero_model_;
if(material_slot >= 0)
{
hero_model = (impl_->ornament_hero_model_ * 100) + material_slot;
}
}
return hero_model;
}
void EQEmu::ItemInstance::SetOrnamentHeroModel(const uint32 ornament_hero_model) {
impl_->ornament_hero_model_ = ornament_hero_model;
}
const char* EQEmu::ItemInstance::GetTrackingID() {
return impl_->tracking_id_;
}
const char* EQEmu::ItemInstance::GetTrackingID() const {
return impl_->tracking_id_;
}
void EQEmu::ItemInstance::SetTrackingID(const char *tracking_id) {
size_t len = strlen(tracking_id);
if(len > 16) {
return;
}
strncpy(impl_->tracking_id_, tracking_id, 16);
}
uint32 EQEmu::ItemInstance::GetRecastTimestamp() {
return impl_->recast_timestamp_;
}
uint32 EQEmu::ItemInstance::GetRecastTimestamp() const {
return impl_->recast_timestamp_;
}
void EQEmu::ItemInstance::SetRecastTimestamp(const uint32 recast_timestamp) {
impl_->recast_timestamp_ = recast_timestamp;
}
uint32 EQEmu::ItemInstance::GetMerchantSlot() {
return impl_->merchant_slot_;
}
uint32 EQEmu::ItemInstance::GetMerchantSlot() const {
return impl_->merchant_slot_;
}
void EQEmu::ItemInstance::SetMerchantSlot(uint32 slot) {
impl_->merchant_slot_ = slot;
}
uint32 EQEmu::ItemInstance::GetMerchantCount() {
return impl_->merchant_count_;
}
uint32 EQEmu::ItemInstance::GetMerchantCount() const {
return impl_->merchant_count_;
}
void EQEmu::ItemInstance::SetMerchantCount(const uint32 cnt) {
impl_->merchant_count_ = cnt;
}
uint32 EQEmu::ItemInstance::GetPrice() {
return impl_->price_;
}
uint32 EQEmu::ItemInstance::GetPrice() const {
return impl_->price_;
}
void EQEmu::ItemInstance::SetPrice(const uint32 p) {
impl_->price_ = p;
}
uint32 EQEmu::ItemInstance::GetSerialNumber() {
return impl_->serial_id_;
}
uint32 EQEmu::ItemInstance::GetSerialNumber() const {
return impl_->serial_id_;
}
void EQEmu::ItemInstance::SetSerialNumber(const uint32 sn) {
impl_->serial_id_ = sn;
}
bool EQEmu::ItemInstance::IsStackable() {
return impl_->base_item_->Stackable;
}
bool EQEmu::ItemInstance::IsStackable() const {
return impl_->base_item_->Stackable;
}
bool EQEmu::ItemInstance::IsNoDrop() {
return GetAttuned() || GetBaseItem()->NoDrop == 0;
}
bool EQEmu::ItemInstance::IsNoDrop() const {
return GetAttuned() || GetBaseItem()->NoDrop == 0;
}
EQEmu::ItemContainer *EQEmu::ItemInstance::GetContainer() {
return &(impl_->contents_);
}
void EQEmu::ItemInstance::Interrogate(int level) {
impl_->contents_.Interrogate(level);
}
+126
View File
@@ -0,0 +1,126 @@
/* 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 COMMON_ITEM_INSTANCE_H
#define COMMON_ITEM_INSTANCE_H
#include "item_data.h"
#include <memory>
namespace EQEmu
{
uint32 GetNextItemInstanceSerial();
class ItemContainer;
class ItemInstance
{
public:
typedef std::shared_ptr<ItemInstance> pointer;
ItemInstance(const ItemData* idata);
ItemInstance(const ItemData* idata, const int16 charges);
~ItemInstance();
const ItemData *GetItem();
const ItemData *GetBaseItem();
const ItemData *GetBaseItem() const;
pointer Split(int charges);
//Container
pointer Get(const int index);
bool Put(const int index, pointer &inst);
//Persistent State
int16 GetCharges();
int16 GetCharges() const;
void SetCharges(const int16 charges);
uint32 GetColor();
uint32 GetColor() const;
void SetColor(const uint32 color);
bool GetAttuned();
bool GetAttuned() const;
void SetAttuned(const bool attuned);
std::string GetCustomData();
std::string GetCustomData() const;
void SetCustomData(const std::string &custom_data);
uint32 GetOrnamentIDFile();
uint32 GetOrnamentIDFile() const;
void SetOrnamentIDFile(const uint32 ornament_idfile);
uint32 GetOrnamentIcon();
uint32 GetOrnamentIcon() const;
void SetOrnamentIcon(const uint32 ornament_icon);
uint32 GetOrnamentHeroModel();
uint32 GetOrnamentHeroModel() const;
uint32 GetOrnamentHeroModel(int material_slot);
uint32 GetOrnamentHeroModel(int material_slot) const;
void SetOrnamentHeroModel(const uint32 ornament_hero_model);
const char* GetTrackingID();
const char* GetTrackingID() const;
void SetTrackingID(const char *tracking_id);
uint32 GetRecastTimestamp();
uint32 GetRecastTimestamp() const;
void SetRecastTimestamp(const uint32 recast_timestamp);
//Merchant
uint32 GetMerchantSlot();
uint32 GetMerchantSlot() const;
void SetMerchantSlot(const uint32 slot);
uint32 GetMerchantCount();
uint32 GetMerchantCount() const;
void SetMerchantCount(const uint32 cnt);
uint32 GetPrice();
uint32 GetPrice() const;
void SetPrice(const uint32 p);
//Serial Number
uint32 GetSerialNumber();
uint32 GetSerialNumber() const;
void SetSerialNumber(uint32 sn);
//Basic Stats
bool IsStackable();
bool IsStackable() const;
bool IsNoDrop();
bool IsNoDrop() const;
void CheckStackRemaining(pointer &insert, int &charges);
//Internal state
//Used for low level operations such as encode/decode
ItemContainer *GetContainer();
void Interrogate(int level);
private:
struct impl;
impl *impl_;
};
} // EQEmu
#endif
+212
View File
@@ -0,0 +1,212 @@
#include "memory_buffer.h"
EQEmu::MemoryBuffer::MemoryBuffer() {
buffer_ = nullptr;
size_ = 0;
capacity_ = 0;
read_pos_ = 0;
write_pos_ = 0;
}
EQEmu::MemoryBuffer::MemoryBuffer(size_t sz) {
buffer_ = nullptr;
size_ = 0;
capacity_ = 0;
read_pos_ = 0;
write_pos_ = 0;
Resize(sz);
}
EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) {
if(other.capacity_) {
buffer_ = new uchar[other.capacity_];
memcpy(buffer_, other.buffer_, other.capacity_);
} else {
buffer_ = nullptr;
}
size_ = other.size_;
capacity_ = other.capacity_;
write_pos_ = other.write_pos_;
read_pos_ = other.read_pos_;
}
EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) {
uchar *tbuf = other.buffer_;
size_t tsz = other.size_;
size_t tcapacity = other.capacity_;
size_t twrite_pos = other.write_pos_;
size_t tread_pos = other.read_pos_;
other.buffer_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
other.read_pos_ = 0;
other.write_pos_ = 0;
buffer_ = tbuf;
size_ = tsz;
capacity_ = tcapacity;
write_pos_ = twrite_pos;
read_pos_ = tread_pos;
}
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) {
if(this == &other) {
return *this;
}
if(buffer_) {
delete[] buffer_;
}
if(other.capacity_) {
buffer_ = new uchar[other.capacity_];
memcpy(buffer_, other.buffer_, other.capacity_);
}
else {
buffer_ = nullptr;
}
size_ = other.size_;
capacity_ = other.capacity_;
write_pos_ = other.write_pos_;
read_pos_ = other.read_pos_;
return *this;
}
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) {
uchar *tbuf = other.buffer_;
size_t tsz = other.size_;
size_t tcapacity = other.capacity_;
size_t twrite_pos = other.write_pos_;
size_t tread_pos = other.read_pos_;
other.buffer_ = nullptr;
other.size_ = 0;
other.capacity_ = 0;
other.read_pos_ = 0;
other.write_pos_ = 0;
buffer_ = tbuf;
size_ = tsz;
capacity_ = tcapacity;
write_pos_ = twrite_pos;
read_pos_ = tread_pos;
return *this;
}
EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator+=(const MemoryBuffer &rhs) {
if(!rhs.buffer_) {
return *this;
}
if(buffer_) {
size_t old_size = size_;
Resize(size_ + rhs.size_);
memcpy(&buffer_[old_size], rhs.buffer_, rhs.size_);
} else {
buffer_ = new uchar[rhs.capacity_];
memcpy(buffer_, rhs.buffer_, rhs.capacity_);
size_ = rhs.size_;
capacity_ = rhs.capacity_;
}
return *this;
}
EQEmu::MemoryBuffer::~MemoryBuffer() { Clear(); }
uchar& EQEmu::MemoryBuffer::operator[](size_t pos) {
return buffer_[pos];
}
const uchar& EQEmu::MemoryBuffer::operator[](size_t pos) const {
return buffer_[pos];
}
bool EQEmu::MemoryBuffer::Empty() {
return size_ == 0;
}
bool EQEmu::MemoryBuffer::Empty() const {
return size_ == 0;
}
size_t EQEmu::MemoryBuffer::Size() {
return size_;
}
size_t EQEmu::MemoryBuffer::Size() const {
return size_;
}
size_t EQEmu::MemoryBuffer::Capacity() {
return capacity_;
}
size_t EQEmu::MemoryBuffer::Capacity() const {
return capacity_;
}
void EQEmu::MemoryBuffer::Resize(size_t sz) {
if(!buffer_) {
size_t new_size = sz + 64;
buffer_ = new uchar[new_size];
capacity_ = new_size;
size_ = sz;
memset(buffer_, 0, capacity_);
return;
}
if(sz > capacity_) {
size_t new_size = sz + 32;
uchar *temp = new uchar[new_size];
memcpy(temp, buffer_, capacity_);
delete[] buffer_;
buffer_ = temp;
capacity_ = new_size;
size_ = sz;
}
else {
size_ = sz;
}
}
void EQEmu::MemoryBuffer::Clear() {
if(buffer_) {
delete[] buffer_;
buffer_ = nullptr;
}
size_ = 0;
capacity_ = 0;
write_pos_ = 0;
read_pos_ = 0;
}
void EQEmu::MemoryBuffer::Zero() {
if(buffer_) {
memset(buffer_, 0, capacity_);
}
}
void EQEmu::MemoryBuffer::Write(const char *val, size_t len) {
size_t size_needed = write_pos_ + len;
Resize(size_needed);
memcpy(&buffer_[write_pos_], val, len);
write_pos_ += len;
}
void EQEmu::MemoryBuffer::Read(uchar *buf, size_t len) {
memcpy(buf, &buffer_[read_pos_], len);
read_pos_ += len;
}
void EQEmu::MemoryBuffer::Read(char *str) {
size_t len = strlen((const char*)&buffer_[read_pos_]);
memcpy(str, &buffer_[read_pos_], len);
read_pos_ += len;
}
+124
View File
@@ -0,0 +1,124 @@
/* 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 COMMON_MEMORY_BUFFER_H
#define COMMON_MEMORY_BUFFER_H
#include "types.h"
#include <type_traits>
#include <string.h>
#include <string>
namespace EQEmu
{
class MemoryBuffer
{
public:
MemoryBuffer();
MemoryBuffer(size_t sz);
MemoryBuffer(const MemoryBuffer &other);
MemoryBuffer(MemoryBuffer &&other);
MemoryBuffer& operator=(const MemoryBuffer &other);
MemoryBuffer& operator=(MemoryBuffer &&other);
MemoryBuffer& operator+=(const MemoryBuffer &rhs);
friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; }
~MemoryBuffer();
uchar& operator[](size_t pos);
const uchar& operator[](size_t pos) const;
template<typename T>
operator T*() {
return reinterpret_cast<T*>(buffer_);
}
template<typename T>
operator T*() const {
return reinterpret_cast<T*>(buffer_);
}
operator bool() { return buffer_ != nullptr; }
operator bool() const { return buffer_ != nullptr; }
bool Empty();
bool Empty() const;
size_t Size();
size_t Size() const;
size_t Capacity();
size_t Capacity() const;
void Resize(size_t sz);
void Clear();
void Zero();
template<typename T>
void Write(T val) {
static_assert(std::is_pod<T>::value, "MemoryBuffer::Write<T>(T val) only works on pod and string types.");
Write((const char*)&val, sizeof(T));
}
template<typename T>
T Read() {
static_assert(std::is_pod<T>::value, "MemoryBuffer::Read<T>() only works on pod and string types.");
T temp;
Read((uchar*)&temp, sizeof(T));
return temp;
}
void Write(const std::string &val) {
Write(val.c_str(), val.length());
Write((uint8)0);
}
void Write(const char *val) {
size_t len = strlen(val);
Write(val, len);
Write((uint8)0);
}
std::string ReadString() {
std::string ret;
size_t len = strlen((const char*)&buffer_[read_pos_]);
ret.resize(len);
memcpy(&ret[0], &buffer_[read_pos_], len);
read_pos_ += len + 1;
return ret;
}
void Write(const char *val, size_t len);
void Read(uchar *buf, size_t len);
void Read(char *str);
inline size_t GetWritePosition() { return write_pos_; }
inline void SetWritePosition(size_t wp) { write_pos_ = wp; }
inline void WriteSkipBytes(size_t skip) { write_pos_ += skip; }
inline size_t GetReadPosition() { return read_pos_; }
inline void SetReadPosition(size_t wp) { read_pos_ = wp; }
inline void ReadSkipBytes(size_t skip) { read_pos_ += skip; }
private:
uchar *buffer_;
size_t size_;
size_t capacity_;
size_t write_pos_;
size_t read_pos_;
};
} // EQEmu
#endif
-1
View File
@@ -146,7 +146,6 @@ INr(OP_GuildDelete); //?
IN(OP_GuildPublicNote, GuildUpdate_PublicNote);
INz(OP_GetGuildsList); //?
IN(OP_SetGuildMOTD, GuildMOTD_Struct);
IN(OP_SetRunMode, SetRunMode_Struct);
INz(OP_GuildPeace); //?
INz(OP_GuildWar); //?
IN(OP_GuildLeader, GuildMakeLeader);
+10 -10
View File
@@ -10,19 +10,19 @@
#include "rof2.h"
void RegisterAllPatches(EQStreamIdentifier &into) {
Titanium::Register(into);
SoF::Register(into);
SoD::Register(into);
UF::Register(into);
RoF::Register(into);
//Titanium::Register(into);
//SoF::Register(into);
//SoD::Register(into);
//UF::Register(into);
//RoF::Register(into);
RoF2::Register(into);
}
void ReloadAllPatches() {
Titanium::Reload();
SoF::Reload();
SoD::Reload();
UF::Reload();
RoF::Reload();
//Titanium::Reload();
//SoF::Reload();
//SoD::Reload();
//UF::Reload();
//RoF::Reload();
RoF2::Reload();
}
+155 -313
View File
@@ -435,7 +435,7 @@ namespace RoF
memset(__packet->pBuffer, 0, sz);
__packet->WriteUInt32(emu->entity_id);
__packet->WriteUInt32(emu->tic_timer);
__packet->WriteUInt32(0); // PlayerID ?
__packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff)
__packet->WriteUInt16(emu->count);
@@ -532,71 +532,72 @@ namespace RoF
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
//*p = nullptr;
//
//if (in->size == 0) {
//
// in->size = 4;
// in->pBuffer = new uchar[in->size];
//
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
//
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
//
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
//
// uchar *OldBuffer = in->pBuffer;
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClickObjectAction)
@@ -658,10 +659,9 @@ namespace RoF
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force);
OUT(force)
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
OUT(meleepush_z)
FINISH_ENCODE();
}
@@ -1179,54 +1179,6 @@ namespace RoF
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildBank)
{
auto in = *p;
*p = nullptr;
auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger
// The first action in the enum was removed, everything 1 less
// Normally we cast them to their structs, but there are so many here! will only do when it's easier
switch (in->ReadUInt32()) {
case 10: // GuildBankAcknowledge
outapp->WriteUInt32(9);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
break;
case 5: // GuildBankDeposit (ack)
outapp->WriteUInt32(4);
outapp->WriteUInt32(in->ReadUInt32());
outapp->WriteUInt32(0);
outapp->WriteUInt32(in->ReadUInt32());
break;
case 1: { // GuildBankItemUpdate
auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer;
auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer;
eq->Action = 0;
OUT(Unknown004);
eq->Unknown08 = 0;
OUT(SlotID);
OUT(Area);
OUT(Unknown012);
OUT(ItemID);
OUT(Icon);
OUT(Quantity);
OUT(Permissions);
OUT(AllowMerge);
OUT(Useable);
OUT_str(ItemName);
OUT_str(Donator);
OUT_str(WhoFor);
OUT(Unknown226);
break;
}
default:
break;
}
delete in;
dest->FastQueuePacket(&outapp);
}
ENCODE(OP_GuildMemberList)
{
//consume the packet
@@ -1757,14 +1709,14 @@ namespace RoF
ENCODE(OP_MoveItem)
{
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToRoFSlot(emu->from_slot);
eq->to_slot = ServerToRoFSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToRoFSlot(emu->from_slot);
//eq->to_slot = ServerToRoFSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -2392,14 +2344,13 @@ namespace RoF
outapp->WriteSInt32(234); // Endurance Total ?
outapp->WriteSInt32(345); // Mana Total ?
// these are needed to fix display bugs
outapp->WriteUInt32(0x19); // base CR
outapp->WriteUInt32(0x19); // base FR
outapp->WriteUInt32(0x19); // base MR
outapp->WriteUInt32(0xf); // base DR
outapp->WriteUInt32(0xf); // base PR
outapp->WriteUInt32(0xf); // base PhR?
outapp->WriteUInt32(0xf); // base Corrup
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
outapp->WriteUInt32(0); // Unknown
@@ -2860,7 +2811,7 @@ namespace RoF
eq->aa_spent = emu->aa_spent;
// These fields may need to be correctly populated at some point
eq->aapoints_assigned = emu->aa_spent;
eq->aapoints_assigned = emu->aa_spent + 1;
eq->aa_spent_general = 0;
eq->aa_spent_archetype = 0;
eq->aa_spent_class = 0;
@@ -2896,81 +2847,58 @@ namespace RoF
ENCODE(OP_SendAATable)
{
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
// the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs
auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0;
auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size);
inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct));
std::vector<int32> skill;
std::vector<int32> points;
for(auto i = 0; i < emu->total_prereqs; ++i) {
skill.push_back(inapp->ReadUInt32());
points.push_back(inapp->ReadUInt32());
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for Live
if (emu->clientver <= 7)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
eq->prereq_skill_count = 1; // min 1
OUT(prereq_skill);
eq->prereq_minpoints_count = 1; // min 1
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
eq->unknown057 = 1; // Introduced during HoT
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
}
outapp->WriteUInt32(emu->id);
outapp->WriteUInt8(1);
outapp->WriteSInt32(emu->upper_hotkey_sid);
outapp->WriteSInt32(emu->lower_hotkey_sid);
outapp->WriteSInt32(emu->title_sid);
outapp->WriteSInt32(emu->desc_sid);
outapp->WriteSInt32(emu->level_req);
outapp->WriteSInt32(emu->cost);
outapp->WriteUInt32(emu->seq);
outapp->WriteUInt32(emu->current_level);
if(emu->total_prereqs) {
outapp->WriteUInt32(emu->total_prereqs);
for(auto &e : skill)
outapp->WriteSInt32(e);
outapp->WriteUInt32(emu->total_prereqs);
for(auto &e : points)
outapp->WriteSInt32(e);
}
else {
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
}
outapp->WriteSInt32(emu->type);
outapp->WriteSInt32(emu->spell);
outapp->WriteSInt32(1);
outapp->WriteSInt32(emu->spell_type);
outapp->WriteSInt32(emu->spell_refresh);
outapp->WriteSInt32(emu->classes);
outapp->WriteSInt32(emu->max_level);
outapp->WriteSInt32(emu->prev_id);
outapp->WriteSInt32(emu->next_id);
outapp->WriteSInt32(emu->total_cost);
outapp->WriteUInt8(0);
outapp->WriteUInt8(emu->grant_only);
outapp->WriteUInt8(0);
outapp->WriteUInt32(emu->charges);
outapp->WriteSInt32(emu->expansion);
outapp->WriteSInt32(emu->category);
outapp->WriteUInt8(0); // shroud
outapp->WriteUInt8(0); // unknown109
outapp->WriteUInt8(0); // loh
outapp->WriteUInt8(0); // unknown111
outapp->WriteUInt32(emu->total_effects);
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
for(auto i = 0; i < emu->total_effects; ++i) {
outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id
outapp->WriteUInt32(inapp->ReadUInt32()); // base1
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
outapp->WriteUInt32(inapp->ReadUInt32()); // slot
}
dest->FastQueuePacket(&outapp);
delete inapp;
FINISH_ENCODE();
}
ENCODE(OP_SendCharInfo)
@@ -3138,13 +3066,13 @@ namespace RoF
{
ENCODE_LENGTH_EXACT(Merchant_Sell_Struct);
SETUP_DIRECT_ENCODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct);
OUT(npcid);
OUT(playerid);
OUT(itemslot);
OUT(quantity);
OUT(price);
FINISH_ENCODE();
}
@@ -4639,92 +4567,6 @@ namespace RoF
DECODE_FORWARD(OP_GroupInvite);
}
DECODE(OP_GuildBank)
{
// all actions are 1 off due to the removal of one of enums
switch (__packet->ReadUInt32()) {
case 2: {// GuildBankPromote
DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct);
SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct);
emu->Action = 3;
IN(Unknown04);
IN(Slot);
IN(Slot2);
FINISH_DIRECT_DECODE();
return;
}
case 3: { // GuildBankViewItem
DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct);
SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct);
emu->Action = 4;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Unknown16);
FINISH_DIRECT_DECODE();
return;
}
case 4: { // GuildBankDeposit
__packet->WriteUInt32(5);
return;
}
case 5: { // GuildBankPermissions
DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct);
SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct);
emu->Action = 6;
IN(Unknown04);
IN(SlotID);
IN(Unknown10);
IN(ItemID);
IN(Permissions);
strn0cpy(emu->MemberName, eq->MemberName, 64);
FINISH_DIRECT_DECODE();
return;
}
case 6: { // GuildBankWithdraw
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 7;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 7: { // GuildBankSplitStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 8;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
case 8: { // GuildBankMergeStacks
DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct);
SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct);
emu->Action = 9;
IN(Unknown04);
IN(SlotID);
IN(Area);
IN(Unknown12);
IN(Quantity);
FINISH_DIRECT_DECODE();
return;
}
default:
Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action");
__packet->SetOpcode(OP_Unknown); /* invalidate the packet */
return;
}
}
DECODE(OP_GuildDemote)
{
DECODE_LENGTH_EXACT(structs::GuildDemoteStruct);
@@ -4862,16 +4704,16 @@ namespace RoF
DECODE(OP_MoveItem)
{
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
emu->from_slot = RoFToServerSlot(eq->from_slot);
emu->to_slot = RoFToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot);
//Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack);
//emu->from_slot = RoFToServerSlot(eq->from_slot);
//emu->to_slot = RoFToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -4999,13 +4841,13 @@ namespace RoF
{
DECODE_LENGTH_EXACT(structs::Merchant_Sell_Struct);
SETUP_DIRECT_DECODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct);
IN(npcid);
IN(playerid);
IN(itemslot);
IN(quantity);
IN(price);
FINISH_DIRECT_DECODE();
}
@@ -5202,7 +5044,7 @@ namespace RoF
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const Item_Struct *item = inst->GetUnscaledItem();
const ItemData *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
RoF::structs::ItemSerializationHeader hdr;
@@ -5232,19 +5074,19 @@ namespace RoF
hdr.unknown044 = 0;
hdr.unknown048 = 0;
hdr.unknown052 = 0;
hdr.isEvolving = item->EvolvingItem;
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader));
if (item->EvolvingItem > 0) {
if (item->EvolvingLevel > 0) {
RoF::structs::EvolvingItem evotop;
evotop.unknown001 = 0;
evotop.unknown002 = 0;
evotop.unknown003 = 0;
evotop.unknown004 = 0;
evotop.evoLevel = item->EvolvingLevel;
evotop.progress = 0;
evotop.progress = 95.512;
evotop.Activated = 1;
evotop.evomaxlevel = item->EvolvingMax;
evotop.evomaxlevel = 7;
ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem));
}
//ORNAMENT IDFILE / ICON
@@ -5261,7 +5103,7 @@ namespace RoF
ss.write(tmp, strlen(tmp));
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = inst->GetOrnamentationIcon();
heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in));
heroModel = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in));
}
else
{
@@ -5354,7 +5196,7 @@ namespace RoF
ibs.Races = item->Races;
ibs.Deity = item->Deity;
ibs.SkillModValue = item->SkillModValue;
ibs.SkillModMax = item->SkillModMax;
ibs.SkillModMax = 0xffffffff;
ibs.SkillModType = (int8)(item->SkillModType);
ibs.SkillModExtra = 0;
ibs.BaneDmgRace = item->BaneDmgRace;
@@ -5704,7 +5546,7 @@ namespace RoF
/*
// TEST CODE: <watch>
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+242 -468
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -57,7 +57,6 @@ E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
@@ -153,7 +152,6 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)
+6 -115
View File
@@ -1487,8 +1487,7 @@ struct CombatDamage_Struct
/* 13 */ float force; // cd cc cc 3d
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
/* 21 */ float meleepush_z;
/* 25 */ uint8 unknown25; // was [9]
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 25 */ uint8 unknown25[5]; // was [9]
/* 30 */
};
@@ -1859,114 +1858,6 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildBankAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
};
struct GuildBankDepositAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
};
struct GuildBankPromote_Struct
{
/*00*/ uint32 Action; // 3
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 Slot;
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
/*20*/ uint32 unknown20;
};
struct GuildBankPermissions_Struct
{
/*00*/ uint32 Action; // 6
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
/*12*/ uint32 ItemID;
/*16*/ uint32 Permissions;
/*20*/ char MemberName[64];
};
struct GuildBankViewItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Unknown16;
};
struct GuildBankWithdrawItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Quantity;
/*20*/
};
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 DepositAreaCount;
/*16*/ uint32 MainAreaCount;
};
/*
** Money Loot
** Length: 22 Bytes
@@ -2419,7 +2310,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -4398,7 +4289,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
/*16*/
};
@@ -4515,7 +4406,7 @@ struct RoF2SlotStruct
struct ItemSerializationHeader
{
/*000*/ char unknown000[17]; // New for HoT. Looks like a string.
/*000*/ char tracking_id[17]; // New for HoT. Looks like a string.
/*017*/ uint32 stacksize;
/*021*/ uint32 unknown004;
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
@@ -4732,7 +4623,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4747,7 +4638,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
-2
View File
@@ -42,7 +42,6 @@ E(OP_GroupFollow)
E(OP_GroupFollow2)
E(OP_GroupInvite)
E(OP_GroupUpdate)
E(OP_GuildBank)
E(OP_GuildMemberList)
E(OP_GuildMemberUpdate)
E(OP_GuildsList)
@@ -138,7 +137,6 @@ D(OP_GroupFollow)
D(OP_GroupFollow2)
D(OP_GroupInvite)
D(OP_GroupInvite2)
D(OP_GuildBank)
D(OP_GuildDemote)
D(OP_GuildRemove)
D(OP_GuildStatus)
+5 -114
View File
@@ -1517,8 +1517,7 @@ struct CombatDamage_Struct
/* 13 */ float force; // cd cc cc 3d
/* 17 */ float meleepush_xy; // see above notes in Action_Struct
/* 21 */ float meleepush_z;
/* 25 */ uint8 unknown25; // was [9]
/* 26 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 25 */ uint8 unknown25[5]; // was [9]
/* 30 */
};
@@ -1889,114 +1888,6 @@ struct GuildUpdate_Struct {
GuildsListEntry_Struct entry;
};
struct GuildBankAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
};
struct GuildBankDepositAck_Struct
{
/*00*/ uint32 Action; // 10
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint32 Fail; //1 = Fail, 0 = Success
};
struct GuildBankPromote_Struct
{
/*00*/ uint32 Action; // 3
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 Slot;
/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
/*20*/ uint32 unknown20;
};
struct GuildBankPermissions_Struct
{
/*00*/ uint32 Action; // 6
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits
/*12*/ uint32 ItemID;
/*16*/ uint32 Permissions;
/*20*/ char MemberName[64];
};
struct GuildBankViewItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Unknown16;
};
struct GuildBankWithdrawItem_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*08*/ uint16 SlotID;
/*10*/ uint16 Area;
/*12*/ uint32 Unknown12;
/*16*/ uint32 Quantity;
/*20*/
};
struct GuildBankItemUpdate_Struct
{
void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity,
uint32 inPermissions, uint32 inAllowMerge, bool inUseable)
{
Action = inAction;
Unknown004 = inUnknown004;
SlotID = inSlotID;
Area = inArea;
Unknown012 = inUnknown012;
ItemID = inItemID;
Icon = inIcon;
Quantity = inQuantity;
Permissions = inPermissions;
AllowMerge = inAllowMerge;
Useable = inUseable;
ItemName[0] = '\0';
Donator[0] = '\0';
WhoFor[0] = '\0';
};
/*000*/ uint32 Action;
/*004*/ uint32 Unknown004;
/*008*/ uint32 Unknown08;
/*012*/ uint16 SlotID;
/*014*/ uint16 Area;
/*016*/ uint32 Unknown012;
/*020*/ uint32 ItemID;
/*024*/ uint32 Icon;
/*028*/ uint32 Quantity;
/*032*/ uint32 Permissions;
/*036*/ uint8 AllowMerge;
/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission.
/*038*/ char ItemName[64];
/*102*/ char Donator[64];
/*166*/ char WhoFor[64];
/*230*/ uint16 Unknown226;
};
struct GuildBankClear_Struct
{
/*00*/ uint32 Action;
/*04*/ uint32 Unknown04;
/*08*/ uint32 Unknown08;
/*12*/ uint32 DepositAreaCount;
/*16*/ uint32 MainAreaCount;
};
/*
** Money Loot
** Length: 22 Bytes
@@ -2447,7 +2338,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -4397,7 +4288,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
/*16*/
};
@@ -4731,7 +4622,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4746,7 +4637,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
+154 -136
View File
@@ -336,71 +336,72 @@ namespace SoD
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
//*p = nullptr;
//
//if (in->size == 0) {
//
// in->size = 4;
//
// in->pBuffer = new uchar[in->size];
//
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
//
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
//
// uchar *OldBuffer = in->pBuffer;
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
//
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClientUpdate)
@@ -446,10 +447,9 @@ namespace SoD
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force);
OUT(force)
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
OUT(meleepush_z)
FINISH_ENCODE();
}
@@ -1267,14 +1267,14 @@ namespace SoD
ENCODE(OP_MoveItem)
{
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToSoDSlot(emu->from_slot);
eq->to_slot = ServerToSoDSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToSoDSlot(emu->from_slot);
//eq->to_slot = ServerToSoDSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1678,8 +1678,8 @@ namespace SoD
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
OUT(expansions);
//eq->expansions = 16383;
//OUT(expansions);
eq->expansions = 16383;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@@ -1863,56 +1863,55 @@ namespace SoD
ENCODE(OP_SendAATable)
{
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for SoD
if (emu->clientver <= 5)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
}
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
FINISH_ENCODE();
}
ENCODE(OP_SendCharInfo)
@@ -2207,6 +2206,25 @@ namespace SoD
ptr += sizeof(uint32);
ptr += 1;
}
/*std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
uint8 write_var8 = 1;
ss.write((const char*)&emu->entity_id, sizeof(uint32));
ss.write((const char*)&emu->count, sizeof(uint16));
write_var8 = 0;
for(uint16 i = 0; i < emu->count; ++i)
{
ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32));
ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32));
ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32));
ss.write((const char*)&write_var8, sizeof(uint8));
}
__packet->size = ss.str().length();
__packet->pBuffer = new unsigned char[__packet->size];
memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size);
*/
FINISH_ENCODE();
}
@@ -3247,16 +3265,16 @@ namespace SoD
DECODE(OP_MoveItem)
{
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = SoDToServerSlot(eq->from_slot);
emu->to_slot = SoDToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = SoDToServerSlot(eq->from_slot);
//emu->to_slot = SoDToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -3542,7 +3560,7 @@ namespace SoD
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const Item_Struct *item = inst->GetUnscaledItem();
const ItemData *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
SoD::structs::ItemSerializationHeader hdr;
hdr.stacksize = stackable ? charges : 1;
@@ -3940,7 +3958,7 @@ namespace SoD
/*
// TEST CODE: <watch>
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+7 -7
View File
@@ -1275,8 +1275,7 @@ struct CombatDamage_Struct
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23; // was [9]
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 23 */ uint8 unknown23[5]; // was [9]
/* 28 */
};
@@ -1974,7 +1973,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -3814,7 +3813,8 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint32 classes;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@@ -3840,7 +3840,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
};
@@ -4111,7 +4111,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4126,7 +4126,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
+133 -132
View File
@@ -318,69 +318,70 @@ namespace SoF
{
//consume the packet
EQApplicationPacket *in = *p;
delete in;
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
//*p = nullptr;
//
//if (in->size == 0) {
// in->size = 4;
// in->pBuffer = new uchar[in->size];
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
//
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
// uchar *OldBuffer = in->pBuffer;
//
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
//
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClientUpdate)
@@ -426,9 +427,9 @@ namespace SoF
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force);
OUT(force)
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(meleepush_z)
FINISH_ENCODE();
}
@@ -931,14 +932,14 @@ namespace SoF
ENCODE(OP_MoveItem)
{
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToSoFSlot(emu->from_slot);
eq->to_slot = ServerToSoFSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToSoFSlot(emu->from_slot);
//eq->to_slot = ServerToSoFSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1335,8 +1336,8 @@ namespace SoF
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
OUT(expansions);
//eq->expansions = 16383;
//OUT(expansions);
eq->expansions = 16383;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@@ -1520,56 +1521,56 @@ namespace SoF
ENCODE(OP_SendAATable)
{
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 4 is for SoF
if (emu->clientver <= 4)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
}
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
FINISH_ENCODE();
}
ENCODE(OP_SendCharInfo)
@@ -2603,16 +2604,16 @@ namespace SoF
DECODE(OP_MoveItem)
{
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = SoFToServerSlot(eq->from_slot);
emu->to_slot = SoFToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = SoFToServerSlot(eq->from_slot);
//emu->to_slot = SoFToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -2884,7 +2885,7 @@ namespace SoF
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const Item_Struct *item = inst->GetUnscaledItem();
const ItemData *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
SoF::structs::ItemSerializationHeader hdr;
hdr.stacksize = stackable ? charges : 1;
@@ -3280,7 +3281,7 @@ namespace SoF
/*
// TEST CODE: <watch>
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+7 -6
View File
@@ -1253,7 +1253,7 @@ struct CombatDamage_Struct
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23[5]; // was [9] this appears unrelated to the stuff the other clients do here?
/* 23 */ uint8 unknown23[5]; // was [9]
/* 28 */
};
@@ -1948,7 +1948,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -3677,7 +3677,8 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint32 classes;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@@ -3701,7 +3702,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
};
@@ -3965,7 +3966,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -3980,7 +3981,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
+94 -111
View File
@@ -263,57 +263,42 @@ namespace Titanium
EQApplicationPacket *in = *p;
*p = nullptr;
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
delete in;
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//do the transform...
int r;
std::string serial_string;
for (r = 0; r < itemcount; r++, eq++) {
uint32 length;
char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0);
if (serialized) {
serial_string.append(serialized, length + 1);
safe_delete_array(serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
in->size = serial_string.length();
in->pBuffer = new unsigned char[in->size];
memcpy(in->pBuffer, serial_string.c_str(), serial_string.length());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_Damage)
{
ENCODE_LENGTH_EXACT(CombatDamage_Struct);
SETUP_DIRECT_ENCODE(CombatDamage_Struct, structs::CombatDamage_Struct);
OUT(target);
OUT(source);
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force);
OUT(meleepush_xy);
OUT(meleepush_z);
FINISH_ENCODE();
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
//if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
// delete in;
// return;
//}
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
////do the transform...
//int r;
//std::string serial_string;
//for (r = 0; r < itemcount; r++, eq++) {
// uint32 length;
// char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0);
// if (serialized) {
// serial_string.append(serialized, length + 1);
// safe_delete_array(serialized);
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//
//}
//
//in->size = serial_string.length();
//in->pBuffer = new unsigned char[in->size];
//memcpy(in->pBuffer, serial_string.c_str(), serial_string.length());
//
//delete[] __emu_buffer;
//
//dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); }
@@ -793,14 +778,14 @@ namespace Titanium
ENCODE(OP_MoveItem)
{
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToTitaniumSlot(emu->from_slot);
//eq->to_slot = ServerToTitaniumSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1124,52 +1109,50 @@ namespace Titanium
ENCODE(OP_SendAATable)
{
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
// Check clientver field to verify this AA should be sent for Titanium
// clientver 1 is for all clients and 3 is for Titanium
if (emu->clientver <= 3)
{
OUT(id);
eq->unknown004 = 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
eq->title_sid = emu->id - emu->current_level + 1;
eq->desc_sid = emu->id - emu->current_level + 1;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
OUT(type);
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
OUT(unknown80[0]);
OUT(unknown80[1]);
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
}
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
FINISH_ENCODE();
}
ENCODE(OP_SendCharInfo)
@@ -1871,16 +1854,16 @@ namespace Titanium
DECODE(OP_MoveItem)
{
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = TitaniumToServerSlot(eq->from_slot);
emu->to_slot = TitaniumToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = TitaniumToServerSlot(eq->from_slot);
//emu->to_slot = TitaniumToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -2089,7 +2072,7 @@ namespace Titanium
int16 slot_id = ServerToTitaniumSlot(slot_id_in);
uint32 merchant_slot = inst->GetMerchantSlot();
int16 charges = inst->GetCharges();
const Item_Struct *item = inst->GetUnscaledItem();
const ItemData *item = inst->GetUnscaledItem();
int i;
uint32 sub_length;
-1
View File
@@ -6,7 +6,6 @@ E(OP_BazaarSearch)
E(OP_BecomeTrader)
E(OP_ChannelMessage)
E(OP_CharInventory)
E(OP_Damage)
E(OP_DeleteCharge)
E(OP_DeleteItem)
E(OP_DeleteSpawn)
+4 -3
View File
@@ -1700,7 +1700,7 @@ struct AdventureRequestResponse_Struct{
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -3157,7 +3157,8 @@ struct SendAA_Struct {
/*0052*/ uint32 spellid;
/*0056*/ uint32 spell_type;
/*0060*/ uint32 spell_refresh;
/*0064*/ uint32 classes;
/*0064*/ uint16 classes;
/*0066*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0068*/ uint32 max_level;
/*0072*/ uint32 last_id;
/*0076*/ uint32 next_id;
@@ -3174,7 +3175,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
};
+147 -164
View File
@@ -365,7 +365,7 @@ namespace UF
memset(__packet->pBuffer, 0, sz);
__packet->WriteUInt32(emu->entity_id);
__packet->WriteUInt32(emu->tic_timer);
__packet->WriteUInt32(0);
__packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff
__packet->WriteUInt16(emu->count);
@@ -474,68 +474,69 @@ namespace UF
{
//consume the packet
EQApplicationPacket *in = *p;
*p = nullptr;
if (in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *)in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
in->pBuffer = new uchar[4];
*(uint32 *)in->pBuffer = ItemCount;
in->size = 4;
for (int r = 0; r < ItemCount; r++, eq++) {
uint32 Length = 0;
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
if (Serialized) {
uchar *OldBuffer = in->pBuffer;
in->pBuffer = new uchar[in->size + Length];
memcpy(in->pBuffer, OldBuffer, in->size);
safe_delete_array(OldBuffer);
memcpy(in->pBuffer + in->size, Serialized, Length);
in->size += Length;
safe_delete_array(Serialized);
}
else {
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
}
}
delete[] __emu_buffer;
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
delete in;
//*p = nullptr;
//
//if (in->size == 0) {
//
// in->size = 4;
// in->pBuffer = new uchar[in->size];
// *((uint32 *)in->pBuffer) = 0;
//
// dest->FastQueuePacket(&in, ack_req);
// return;
//}
//
////store away the emu struct
//unsigned char *__emu_buffer = in->pBuffer;
//
//int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
//
//if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
//
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
// opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
//
// delete in;
// return;
//}
//
//InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
//
//in->pBuffer = new uchar[4];
//*(uint32 *)in->pBuffer = ItemCount;
//in->size = 4;
//
//for (int r = 0; r < ItemCount; r++, eq++) {
//
// uint32 Length = 0;
// char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
//
// if (Serialized) {
//
// uchar *OldBuffer = in->pBuffer;
// in->pBuffer = new uchar[in->size + Length];
// memcpy(in->pBuffer, OldBuffer, in->size);
//
// safe_delete_array(OldBuffer);
//
// memcpy(in->pBuffer + in->size, Serialized, Length);
// in->size += Length;
//
// safe_delete_array(Serialized);
// }
// else {
// Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
// }
//}
//
//delete[] __emu_buffer;
//
////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
////Log.Hex(Logs::Netcode, in->pBuffer, in->size);
//
//dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ClientUpdate)
@@ -581,10 +582,9 @@ namespace UF
OUT(type);
OUT(spellid);
OUT(damage);
OUT(force);
OUT(force)
OUT(meleepush_xy);
OUT(meleepush_z);
OUT(special);
OUT(meleepush_z)
FINISH_ENCODE();
}
@@ -1506,14 +1506,14 @@ namespace UF
ENCODE(OP_MoveItem)
{
ENCODE_LENGTH_EXACT(MoveItem_Struct);
SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
eq->from_slot = ServerToUFSlot(emu->from_slot);
eq->to_slot = ServerToUFSlot(emu->to_slot);
OUT(number_in_stack);
FINISH_ENCODE();
//ENCODE_LENGTH_EXACT(MoveItem_Struct);
//SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//eq->from_slot = ServerToUFSlot(emu->from_slot);
//eq->to_slot = ServerToUFSlot(emu->to_slot);
//OUT(number_in_stack);
//
//FINISH_ENCODE();
}
ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); }
@@ -1806,13 +1806,11 @@ namespace UF
//NOTE: new client supports 300 AAs, our internal rep/PP
//only supports 240..
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
eq->aa_array[r].AA = emu->aa_array[r].AA;
eq->aa_array[r].value = emu->aa_array[r].value;
eq->aa_array[r].charges = emu->aa_array[r].charges;
OUT(aa_array[r].AA);
OUT(aa_array[r].value);
OUT(aa_array[r].charges);
}
// OUT(unknown02220[4]);
OUT(mana);
OUT(cur_hp);
OUT(STR);
@@ -1942,8 +1940,8 @@ namespace UF
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
OUT(expansions);
//eq->expansions = 0x1ffff;
//OUT(expansions);
eq->expansions = 0xffff;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@@ -2131,7 +2129,7 @@ namespace UF
eq->aa_spent = emu->aa_spent;
eq->aa_assigned = emu->aa_spent;
eq->aa_spent3 = 0;
eq->aa_spent3 = emu->aa_spent;
eq->unknown012 = 0;
eq->unknown016 = 0;
eq->unknown020 = 0;
@@ -2148,56 +2146,55 @@ namespace UF
ENCODE(OP_SendAATable)
{
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 6 is for Underfoot
if (emu->clientver <= 6)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
}
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
FINISH_ENCODE();
}
ENCODE(OP_SendCharInfo)
@@ -3048,21 +3045,11 @@ namespace UF
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
if (emu->equipment[MaterialPrimary].Material > 99999) {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63);
} else {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
}
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
if (emu->equipment[MaterialSecondary].Material > 99999) {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63);
} else {
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
}
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0);
}
@@ -3072,11 +3059,7 @@ namespace UF
structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer;
for (k = 0; k < 9; k++) {
if (emu->equipment[k].Material > 99999) {
Equipment[k].Material = 63;
} else {
Equipment[k].Material = emu->equipment[k].Material;
}
Equipment[k].Material = emu->equipment[k].Material;
Equipment[k].Unknown1 = emu->equipment[k].Unknown1;
Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial;
}
@@ -3604,16 +3587,16 @@ namespace UF
DECODE(OP_MoveItem)
{
DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
emu->from_slot = UFToServerSlot(eq->from_slot);
emu->to_slot = UFToServerSlot(eq->to_slot);
IN(number_in_stack);
FINISH_DIRECT_DECODE();
//DECODE_LENGTH_EXACT(structs::MoveItem_Struct);
//SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct);
//
//Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot);
//
//emu->from_slot = UFToServerSlot(eq->from_slot);
//emu->to_slot = UFToServerSlot(eq->to_slot);
//IN(number_in_stack);
//
//FINISH_DIRECT_DECODE();
}
DECODE(OP_PetCommands)
@@ -3829,7 +3812,7 @@ namespace UF
std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary);
const Item_Struct *item = inst->GetUnscaledItem();
const ItemData *item = inst->GetUnscaledItem();
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
UF::structs::ItemSerializationHeader hdr;
hdr.stacksize = stackable ? charges : 1;
@@ -3849,25 +3832,25 @@ namespace UF
hdr.unknown044 = 0;
hdr.unknown048 = 0;
hdr.unknown052 = 0;
hdr.isEvolving = item->EvolvingItem;
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader));
if (item->EvolvingItem > 0) {
if (item->EvolvingLevel > 0) {
UF::structs::EvolvingItem evotop;
evotop.unknown001 = 0;
evotop.unknown002 = 0;
evotop.unknown003 = 0;
evotop.unknown004 = 0;
evotop.evoLevel = item->EvolvingLevel;
evotop.progress = 0;
evotop.progress = 95.512;
evotop.Activated = 1;
evotop.evomaxlevel = item->EvolvingMax;
evotop.evomaxlevel = 7;
ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
}
//ORNAMENT IDFILE / ICON -
uint16 ornaIcon = 0;
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
const ItemData *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
ss.write((const char*)&null_term, sizeof(uint8));
ornaIcon = aug_weap->Icon;
@@ -3961,7 +3944,7 @@ namespace UF
ibs.Races = item->Races;
ibs.Deity = item->Deity;
ibs.SkillModValue = item->SkillModValue;
ibs.SkillModMax = item->SkillModMax;
ibs.unknown5 = 0;
ibs.SkillModType = item->SkillModType;
ibs.BaneDmgRace = item->BaneDmgRace;
ibs.BaneDmgBody = item->BaneDmgBody;
@@ -4283,7 +4266,7 @@ namespace UF
/*
// TEST CODE: <watch>
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x);
*/
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
+8 -8
View File
@@ -1333,8 +1333,7 @@ struct CombatDamage_Struct
/* 11 */ float force; // cd cc cc 3d
/* 15 */ float meleepush_xy; // see above notes in Action_Struct
/* 19 */ float meleepush_z;
/* 23 */ uint8 unknown23; // was [9]
/* 24 */ uint32 special; // 2 = Rampage, 1 = Wild Rampage
/* 23 */ uint8 unknown23[5]; // was [9]
/* 28 */
};
@@ -2033,7 +2032,7 @@ struct AdventureLeaderboard_Struct
/*struct Item_Shop_Struct {
uint16 merchantid;
uint8 itemtype;
Item_Struct item;
ItemData item;
uint8 iss_unknown001[6];
};*/
@@ -3887,7 +3886,8 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint32 classes;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@@ -3913,7 +3913,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 target_id;
/*08*/ uint32 unknown08;
/*12*/ uint32 exp_value;
};
@@ -4103,7 +4103,7 @@ struct ItemBodyStruct
uint32 Races;
uint32 Deity;
int32 SkillModValue;
uint32 SkillModMax;
uint32 unknown5;
uint32 SkillModType;
uint32 BaneDmgRace;
uint32 BaneDmgBody;
@@ -4206,7 +4206,7 @@ struct ClickEffectStruct
struct ProcEffectStruct
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
@@ -4221,7 +4221,7 @@ struct ProcEffectStruct
struct WornEffectStruct //worn, focus and scroll effect
{
int32 effect;
uint32 effect;
uint8 level2;
uint32 type;
uint8 level;
-363
View File
@@ -1,363 +0,0 @@
#include "pathfind.h"
#include "random.h"
#include <stdio.h>
#include <string.h>
#include <zlib.h>
namespace Pathfind
{
uint32_t InflateData(const char* buffer, uint32_t len, char* out_buffer, uint32_t out_len_max) {
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(buffer));
zstream.avail_in = len;
zstream.next_out = reinterpret_cast<unsigned char*>(out_buffer);;
zstream.avail_out = out_len_max;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
i = inflateInit2(&zstream, 15);
if (i != Z_OK) {
return 0;
}
zerror = inflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END) {
inflateEnd(&zstream);
return zstream.total_out;
}
else {
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd(&zstream);
return 0;
}
}
}
const uint32_t nav_mesh_file_version = 2;
const float max_dest_drift = 10.0f;
const float at_waypoint_eps = 1.0f;
EQEmu::Random path_rng;
float vec_dist(const glm::vec3 &a, const glm::vec3 &b) {
float dist_x = a.x - b.x;
float dist_y = a.y - b.y;
float dist_z = a.z - b.z;
return sqrt((dist_x * dist_x) + (dist_y * dist_y) + (dist_z * dist_z));
}
PathfindingManager::PathfindingManager()
{
m_nav_mesh = nullptr;
m_nav_query = nullptr;
m_filter.setIncludeFlags(NavigationPolyFlagAll);
m_filter.setAreaCost(NavigationAreaFlagNormal, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagWater, 2.5f);
m_filter.setAreaCost(NavigationAreaFlagLava, 2.5f);
m_filter.setAreaCost(NavigationAreaFlagPvP, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagSlime, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagIce, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagVWater, 2.5f);
m_filter.setAreaCost(NavigationAreaFlagGeneralArea, 1.0f);
m_filter.setAreaCost(NavigationAreaFlagPortal, 1.0f);
}
PathfindingManager::~PathfindingManager()
{
Clear();
}
void PathfindingManager::Load(const std::string &zone_name)
{
Clear();
std::string filename = MAP_DIR + std::string("/") + zone_name + ".nav";
FILE *f = fopen(filename.c_str(), "rb");
if (f) {
char magic[9] = { 0 };
if (fread(magic, 9, 1, f) != 1) {
fclose(f);
return;
}
if (strncmp(magic, "EQNAVMESH", 9) != 0)
{
fclose(f);
return;
}
uint32_t version = 0;
if (fread(&version, sizeof(uint32_t), 1, f) != 1) {
fclose(f);
return;
}
if (version != nav_mesh_file_version) {
fclose(f);
return;
}
uint32_t data_size;
if (fread(&data_size, sizeof(data_size), 1, f) != 1) {
fclose(f);
return;
}
uint32_t buffer_size;
if (fread(&buffer_size, sizeof(buffer_size), 1, f) != 1) {
fclose(f);
return;
}
std::vector<char> data;
data.resize(data_size);
if (fread(&data[0], data_size, 1, f) != 1) {
fclose(f);
return;
}
std::vector<char> buffer;
buffer.resize(buffer_size);
uint32_t v = Pathfind::InflateData(&data[0], data_size, &buffer[0], buffer_size);
fclose(f);
char *buf = &buffer[0];
m_nav_mesh = dtAllocNavMesh();
uint32_t number_of_tiles = *(uint32_t*)buf;
buf += sizeof(uint32_t);
dtNavMeshParams params = *(dtNavMeshParams*)buf;
buf += sizeof(dtNavMeshParams);
dtStatus status = m_nav_mesh->init(&params);
if (dtStatusFailed(status))
{
dtFreeNavMesh(m_nav_mesh);
m_nav_mesh = nullptr;
return;
}
for (unsigned int i = 0; i < number_of_tiles; ++i)
{
uint32_t tile_ref = *(uint32_t*)buf;
buf += sizeof(uint32_t);
int32_t data_size = *(uint32_t*)buf;
buf += sizeof(uint32_t);
if (!tile_ref || !data_size) {
dtFreeNavMesh(m_nav_mesh);
m_nav_mesh = nullptr;
return;
}
unsigned char* data = (unsigned char*)dtAlloc(data_size, DT_ALLOC_PERM);
memcpy(data, buf, data_size);
buf += data_size;
m_nav_mesh->addTile(data, data_size, DT_TILE_FREE_DATA, tile_ref, 0);
}
}
}
void PathfindingManager::Clear()
{
if (m_nav_mesh) {
dtFreeNavMesh(m_nav_mesh);
m_nav_mesh = nullptr;
}
if (m_nav_query) {
dtFreeNavMeshQuery(m_nav_query);
m_nav_query = nullptr;
}
}
PathfindingRoute PathfindingManager::FindRoute(const glm::vec3 &src_loc, const glm::vec3 &dest_loc)
{
glm::vec3 current_location(src_loc.x, src_loc.z, src_loc.y);
glm::vec3 dest_location(dest_loc.x, dest_loc.z, dest_loc.y);
PathfindingRoute ret;
ret.m_status = PathComplete;
ret.m_dest = dest_loc;
ret.m_current_node = 0;
ret.m_active = true;
if (!m_nav_mesh) {
PathfindingNode dest;
dest.flag = NavigationPolyFlagNormal;
dest.position = dest_loc;
ret.m_nodes.push_back(dest);
return ret;
}
if (!m_nav_query) {
m_nav_query = dtAllocNavMeshQuery();
m_nav_query->init(m_nav_mesh, 4092);
}
dtPolyRef start_ref;
dtPolyRef end_ref;
glm::vec3 ext(15.0f, 15.0f, 15.0f);
m_nav_query->findNearestPoly(&current_location[0], &ext[0], &m_filter, &start_ref, 0);
m_nav_query->findNearestPoly(&dest_location[0], &ext[0], &m_filter, &end_ref, 0);
if (!start_ref || !end_ref) {
PathfindingNode dest;
dest.flag = NavigationPolyFlagNormal;
dest.position = dest_loc;
ret.m_nodes.push_back(dest);
return ret;
}
int npoly = 0;
dtPolyRef path[256] = { 0 };
auto status = m_nav_query->findPath(start_ref, end_ref, &current_location[0], &dest_location[0], &m_filter, path, &npoly, 256);
if (status & DT_OUT_OF_NODES || status & DT_BUFFER_TOO_SMALL) {
ret.m_status = PathPartial;
}
else if (status & DT_PARTIAL_RESULT) {
ret.m_status = PathBroken;
}
if (npoly) {
glm::vec3 epos = dest_location;
if (path[npoly - 1] != end_ref)
m_nav_query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
float straight_path[512 * 3];
unsigned char straight_path_flags[512];
int n_straight_polys;
dtPolyRef straight_path_polys[512];
status = m_nav_query->findStraightPath(&current_location[0], &epos[0], path, npoly,
straight_path, straight_path_flags,
straight_path_polys, &n_straight_polys, 512, DT_STRAIGHTPATH_ALL_CROSSINGS);
if (ret.m_status == PathComplete && status & DT_OUT_OF_NODES || status & DT_BUFFER_TOO_SMALL) {
ret.m_status = PathPartial;
}
else if (ret.m_status == PathComplete && status & DT_PARTIAL_RESULT) {
ret.m_status = PathBroken;
}
if (n_straight_polys) {
ret.m_nodes.reserve(n_straight_polys);
for (int i = 0; i < n_straight_polys; ++i)
{
PathfindingNode node;
node.position.x = straight_path[i * 3];
node.position.z = straight_path[i * 3 + 1];
node.position.y = straight_path[i * 3 + 2];
if (!dtStatusSucceed(m_nav_mesh->getPolyFlags(straight_path_polys[i], &node.flag))) {
node.flag = 0;
}
ret.m_nodes.push_back(node);
}
}
}
else {
PathfindingNode dest;
dest.flag = NavigationPolyFlagNormal;
dest.position = dest_loc;
ret.m_nodes.push_back(dest);
}
return ret;
}
bool PathfindingManager::GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos)
{
if(!m_nav_mesh)
return false;
if (!m_nav_query) {
m_nav_query = dtAllocNavMeshQuery();
m_nav_query->init(m_nav_mesh, 4092);
}
glm::vec3 ext(10.0f, 10.0f, 10.0f);
dtPolyRef start_ref;
m_nav_query->findNearestPoly(&start[0], &ext[0], &m_filter, &start_ref, 0);
if (!start_ref) {
return false;
}
dtPolyRef random_ref;
glm::vec3 pt;
dtStatus status = m_nav_query->findRandomPointAroundCircle(start_ref, &start[0], radius,
&m_filter, []() -> float { return (float)path_rng.Real(0.0, 1.0); }, &random_ref, &pt[0]);
if (dtStatusSucceed(status))
{
pos.x = pt.x;
pos.z = pt.y;
pos.y = pt.z;
return true;
}
return false;
}
PathfindingRoute::PathfindingRoute()
{
m_active = false;
}
PathfindingRoute::~PathfindingRoute()
{
}
bool PathfindingRoute::DestinationValid(const glm::vec3 &dest)
{
if (m_status == PathPartial && m_current_node + 1 == m_nodes.size()) {
return false;
}
auto dist = vec_dist(dest, m_dest);
if (dist <= max_dest_drift) {
return true;
}
return false;
}
void PathfindingRoute::CalcCurrentNode(const glm::vec3 &current_pos, bool &wp_changed)
{
wp_changed = false;
if (m_active) {
//if we're at last node then we dont need to do anything.
if (m_nodes.size() - 1 == m_current_node) {
return;
}
auto &current = GetCurrentNode();
auto dist = vec_dist(current.position, current_pos);
if (dist < at_waypoint_eps) {
m_current_node++;
wp_changed = true;
}
}
}
unsigned short PathfindingRoute::GetPreviousNodeFlag()
{
if(m_current_node == 0)
return 0;
return m_nodes[m_current_node - 1].flag;
}
-94
View File
@@ -1,94 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <DetourNavMesh.h>
#include <DetourNavMeshQuery.h>
#include <glm/vec3.hpp>
enum NavigationAreaFlags
{
NavigationAreaFlagNormal,
NavigationAreaFlagWater,
NavigationAreaFlagLava,
NavigationAreaFlagZoneLine,
NavigationAreaFlagPvP,
NavigationAreaFlagSlime,
NavigationAreaFlagIce,
NavigationAreaFlagVWater,
NavigationAreaFlagGeneralArea,
NavigationAreaFlagPortal,
NavigationAreaFlagDisabled,
};
enum NavigationPolyFlags
{
NavigationPolyFlagNormal = 1,
NavigationPolyFlagWater = 2,
NavigationPolyFlagLava = 4,
NavigationPolyFlagZoneLine = 8,
NavigationPolyFlagPvP = 16,
NavigationPolyFlagSlime = 32,
NavigationPolyFlagIce = 64,
NavigationPolyFlagVWater = 128,
NavigationPolyFlagGeneralArea = 256,
NavigationPolyFlagPortal = 512,
NavigationPolyFlagDisabled = 1024,
NavigationPolyFlagAll = 0xFFFF
};
struct PathfindingNode
{
glm::vec3 position;
unsigned short flag;
};
enum PathfindingRouteStatus
{
PathComplete,
PathPartial,
PathBroken
};
class PathfindingRoute
{
public:
PathfindingRoute();
~PathfindingRoute();
bool Active() const { return m_active; }
bool DestinationValid(const glm::vec3 &dest);
void CalcCurrentNode(const glm::vec3 &current_pos, bool &wp_changed);
const PathfindingNode& GetCurrentNode() { return m_nodes[m_current_node]; }
unsigned short GetPreviousNodeFlag();
const std::vector<PathfindingNode>& GetNodes() const { return m_nodes; }
std::vector<PathfindingNode>& GetNodesEdit() { return m_nodes; }
PathfindingRouteStatus GetStatus() { return m_status; }
private:
glm::vec3 m_dest;
std::vector<PathfindingNode> m_nodes;
int m_current_node;
bool m_active;
PathfindingRouteStatus m_status;
friend class PathfindingManager;
};
class PathfindingManager
{
public:
PathfindingManager();
~PathfindingManager();
void Load(const std::string &filename);
void Clear();
//Expects locations in EQEmu internal format eg what #loc returns not what /loc returns.
PathfindingRoute FindRoute(const glm::vec3 &current_location, const glm::vec3 &dest_location);
bool GetRandomPoint(const glm::vec3 &start, float radius, glm::vec3 &pos);
bool Loaded() const { return m_nav_mesh != nullptr; }
private:
dtNavMesh *m_nav_mesh;
dtNavMeshQuery *m_nav_query;
dtQueryFilter m_filter;
};
+4
View File
@@ -139,4 +139,8 @@ protected:
std::map<pTimerType, PersistentTimer *> _list;
};
//code prettying macros
#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3))
#define AA_Choose5(val, v1, v2, v3, v4, v5) (val==1?v1:(val==2?v2:(val==3?v3:(val==4?v4:v5))))
#endif
+172 -149
View File
@@ -17,14 +17,43 @@
*/
#include "rulesys.h"
#include "database.h"
#include "string_util.h"
#include <cstdlib>
#include <cstring>
/*
Commands:
#rules:
FatherNitwit: Added new rules subsystem to allow game rules to be changed
at runtime. more about this will come as time goes on.
FatherNitwit: Added #rules command to manage rules data from in game.
FatherNitwit: Renamed old #rules to #serverrules
FatherNitwit: Moved max level into the rules system (Character:MaxLevel)
Requred SQL:
CREATE TABLE rule_sets (
ruleset_id TINYINT UNSIGNED NOT NULL auto_increment,
name VARCHAR(255) NOT NULL,
PRIMARY KEY(ruleset_id)
);
INSERT INTO rule_sets VALUES(0, "default");
UPDATE rule_sets SET ruleset_id=0;
CREATE TABLE rule_values (
ruleset_id TINYINT UNSIGNED NOT NULL,
rule_name VARCHAR(64) NOT NULL,
rule_value VARCHAR(10) NOT NULL,
INDEX(ruleset_id),
PRIMARY KEY(ruleset_id,rule_name)
);
Commands:
#rules:
current -> lists current set name
switch (set name) -> change set in the DB, but dont reload
load (set name) -> load set into this zone without changing the world
@@ -65,28 +94,28 @@ RuleManager::RuleManager()
}
RuleManager::CategoryType RuleManager::FindCategory(const char *catname) {
int i;
for (i = 0; i < _CatCount; i++) {
if (strcasecmp(catname, s_categoryNames[i]) == 0)
return((CategoryType)i);
int r;
for(r = 0; r < _CatCount; r++) {
if(strcasecmp(catname, s_categoryNames[r]) == 0)
return((CategoryType) r);
}
return(InvalidCategory);
}
bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into) {
CategoryType cat = InvalidCategory;
if (catname != nullptr) {
if(catname != nullptr) {
cat = FindCategory(catname);
if (cat == InvalidCategory) {
if(cat == InvalidCategory) {
Log.Out(Logs::Detail, Logs::Rules, "Unable to find category '%s'", catname);
return(false);
}
}
int i;
int rule_count = CountRules();
for (i = 0; i < rule_count; i++) {
const RuleInfo &rule = s_RuleInfo[i];
if (catname == nullptr || cat == rule.category) {
int r;
int rcount = CountRules();
for(r = 0; r < rcount; r++) {
const RuleInfo &rule = s_RuleInfo[r];
if(catname == nullptr || cat == rule.category) {
into.push_back(rule.name);
}
}
@@ -94,14 +123,15 @@ bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into
}
bool RuleManager::ListCategories(std::vector<const char *> &into) {
int i;
for (i = 0; i < _CatCount; i++) {
into.push_back(s_categoryNames[i]);
int r;
for(r = 0; r < _CatCount; r++) {
into.push_back(s_categoryNames[r]);
}
return(true);
}
bool RuleManager::GetRule(const char *rule_name, std::string &return_value) {
bool RuleManager::GetRule(const char *rule_name, std::string &ret_val) {
RuleType type;
uint16 index;
if (!_FindRule(rule_name, type, index))
@@ -121,12 +151,12 @@ bool RuleManager::GetRule(const char *rule_name, std::string &return_value) {
break;
}
return_value = tmp;
ret_val = tmp;
return true;
}
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save) {
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *db, bool db_save) {
if(rule_name == nullptr || rule_value == nullptr)
return(false);
@@ -136,26 +166,25 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas
return(false);
switch(type) {
case IntRule:
m_RuleIntValues[index] = atoi(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
break;
case RealRule:
m_RuleRealValues[index] = atof(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
break;
case BoolRule:
uint32 val = 0;
if (!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
val = 1;
m_RuleBoolValues[index] = val;
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
break;
case IntRule:
m_RuleIntValues [index] = atoi(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %d", rule_name, m_RuleIntValues[index]);
break;
case RealRule:
m_RuleRealValues[index] = atof(rule_value);
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
break;
case BoolRule:
uint32 val = 0;
if(!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
val = 1;
m_RuleBoolValues[index] = val;
Log.Out(Logs::Detail, Logs::Rules, "Set rule %s to value %s", rule_name, m_RuleBoolValues[index] == 1 ?"true":"false");
break;
}
if(db_save)
_SaveRule(database, type, index);
_SaveRule(db, type, index);
return(true);
}
@@ -172,14 +201,14 @@ void RuleManager::ResetRules() {
}
bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) {
if (rule_name == nullptr)
if(rule_name == nullptr)
return(false);
int i;
int rule_count = CountRules();
for (i = 0; i < rule_count; i++) {
const RuleInfo &rule = s_RuleInfo[i];
if (strcmp(rule_name, rule.name) == 0) {
int r;
int rcount = CountRules();
for(r = 0; r < rcount; r++) {
const RuleInfo &rule = s_RuleInfo[r];
if(strcmp(rule_name, rule.name) == 0) {
type_into = rule.type;
index_into = rule.rule_index;
return(true);
@@ -191,197 +220,191 @@ bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &
//assumes index is valid!
const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
switch (type) {
case IntRule:
return(s_RuleInfo[index].name);
case RealRule:
return(s_RuleInfo[index + _IntRuleCount].name);
case BoolRule:
return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name);
switch(type) {
case IntRule:
return(s_RuleInfo[index].name);
case RealRule:
return(s_RuleInfo[index+_IntRuleCount].name);
case BoolRule:
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
}
//should never happen
return("InvalidRule??");
}
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
void RuleManager::SaveRules(Database *db, const char *ruleset) {
if (ruleset_name != nullptr) {
if(ruleset != nullptr) {
//saving to a specific name
if (m_activeName != ruleset_name) {
if(m_activeName != ruleset) {
//a new name...
m_activeRuleset = _FindOrCreateRuleset(database, ruleset_name);
if (m_activeRuleset == -1) {
Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset_name);
m_activeRuleset = _FindOrCreateRuleset(db, ruleset);
if(m_activeRuleset == -1) {
Log.Out(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset);
return;
}
m_activeName = ruleset_name;
m_activeName = ruleset;
}
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset_name, m_activeRuleset);
}
else {
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset, m_activeRuleset);
} else {
Log.Out(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset);
}
int i;
for (i = 0; i < _IntRuleCount; i++) {
_SaveRule(database, IntRule, i);
int r;
for(r = 0; r < _IntRuleCount; r++) {
_SaveRule(db, IntRule, r);
}
for (i = 0; i < _RealRuleCount; i++) {
_SaveRule(database, RealRule, i);
for(r = 0; r < _RealRuleCount; r++) {
_SaveRule(db, RealRule, r);
}
for (i = 0; i < _BoolRuleCount; i++) {
_SaveRule(database, BoolRule, i);
for(r = 0; r < _BoolRuleCount; r++) {
_SaveRule(db, BoolRule, r);
}
}
bool RuleManager::LoadRules(Database *database, const char *ruleset_name) {
int ruleset_id = GetRulesetID(database, ruleset_name);
if (ruleset_id < 0) {
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
bool RuleManager::LoadRules(Database *db, const char *ruleset) {
int rsid = GetRulesetID(db, ruleset);
if(rsid < 0) {
Log.Out(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset);
return(false);
}
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id);
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset, rsid);
m_activeRuleset = ruleset_id;
m_activeName = ruleset_name;
m_activeRuleset = rsid;
m_activeName = ruleset;
/* Load default ruleset values first if we're loading something other than default */
if (strcasecmp(ruleset_name, "default") != 0){
std::string default_ruleset_name = "default";
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
if (default_ruleset_id < 0) {
Log.Out(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.", default_ruleset_name.c_str());
return(false);
}
Log.Out(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d", default_ruleset_id);
auto results = database->QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row)
if (!SetRule(row[0], row[1], nullptr, false))
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", rsid);
auto results = db->QueryDatabase(query);
if (!results.Success())
{
return false;
}
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
auto results = database->QueryDatabase(query);
if (!results.Success())
return false;
for (auto row = results.begin(); row != results.end(); ++row)
if (!SetRule(row[0], row[1], nullptr, false))
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
for(auto row = results.begin(); row != results.end(); ++row)
if(!SetRule(row[0], row[1], nullptr, false))
Log.Out(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
return true;
}
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
char value_string[100];
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
char vstr[100];
switch(type) {
case IntRule:
sprintf(value_string, "%d", m_RuleIntValues[index]);
break;
case RealRule:
sprintf(value_string, "%.13f", m_RuleRealValues[index]);
break;
case BoolRule:
sprintf(value_string, "%s", m_RuleBoolValues[index]?"true":"false");
break;
case IntRule:
sprintf(vstr, "%d", m_RuleIntValues[index]);
break;
case RealRule:
sprintf(vstr, "%.13f", m_RuleRealValues[index]);
break;
case BoolRule:
sprintf(vstr, "%s", m_RuleBoolValues[index]?"true":"false");
break;
}
std::string query = StringFormat("REPLACE INTO rule_values "
"(ruleset_id, rule_name, rule_value) "
" VALUES(%d, '%s', '%s')",
m_activeRuleset, _GetRuleName(type, index), value_string);
auto results = database->QueryDatabase(query);
m_activeRuleset, _GetRuleName(type, index), vstr);
auto results = db->QueryDatabase(query);
}
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
int RuleManager::GetRulesetID(Database *db, const char *rulesetname) {
uint32 len = strlen(ruleset_name);
char* rst = new char[2 * len + 1];
database->DoEscapeString(rst, ruleset_name, len);
uint32 len = strlen(rulesetname);
char* rst = new char[2*len+1];
db->DoEscapeString(rst, rulesetname, len);
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
safe_delete_array(rst);
auto results = database->QueryDatabase(query);
if (!results.Success())
return -1;
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
safe_delete_array(rst);
auto results = db->QueryDatabase(query);
if (!results.Success()) {
return -1;
}
if (results.RowCount() == 0)
return -1;
if (results.RowCount() == 0)
return -1;
auto row = results.begin();
auto row = results.begin();
return atoi(row[0]);
}
int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset_name) {
int RuleManager::_FindOrCreateRuleset(Database *db, const char *ruleset) {
int ruleset_id = GetRulesetID(database, in_ruleset_name);
if (ruleset_id >= 0)
return ruleset_id; //found and existing one...
int res = GetRulesetID(db, ruleset);
if(res >= 0)
return res; //found and existing one...
uint32 len = strlen(in_ruleset_name);
char* ruleset_name = new char[2 * len + 1];
database->DoEscapeString(ruleset_name, in_ruleset_name, len);
uint32 len = strlen(ruleset);
char* rst = new char[2*len+1];
db->DoEscapeString(rst, ruleset, len);
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name);
safe_delete_array(ruleset_name);
auto results = database->QueryDatabase(query);
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", rst);
safe_delete_array(rst);
auto results = db->QueryDatabase(query);
if (!results.Success())
{
return -1;
}
return results.LastInsertedID();
return results.LastInsertedID();
}
std::string RuleManager::GetRulesetName(Database *database, int ruleset_id) {
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", ruleset_id);
auto results = database->QueryDatabase(query);
std::string RuleManager::GetRulesetName(Database *db, int id) {
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", id);
auto results = db->QueryDatabase(query);
if (!results.Success())
return "";
{
return "";
}
if (results.RowCount() == 0)
return "";
return "";
auto row = results.begin();
auto row = results.begin();
return row[0];
}
bool RuleManager::ListRulesets(Database *database, std::map<int, std::string> &into) {
bool RuleManager::ListRulesets(Database *db, std::map<int, std::string> &into) {
//start out with the default set which is always present.
into[0] = "default";
std::string query = "SELECT ruleset_id, name FROM rule_sets";
auto results = database->QueryDatabase(query);
std::string query = "SELECT ruleset_id, name FROM rule_sets";
auto results = db->QueryDatabase(query);
if (results.Success())
{
return false;
}
for (auto row = results.begin(); row != results.end(); ++row)
into[atoi(row[0])] = row[1];
into[ atoi(row[0]) ] = row[1];
return true;
}
int32 RuleManager::GetIntRule(RuleManager::IntType t) const{
int32 RuleManager::GetIntRule(RuleManager::IntType t) const
{
return(m_RuleIntValues[t]);
}
float RuleManager::GetRealRule(RuleManager::RealType t) const{
float RuleManager::GetRealRule(RuleManager::RealType t) const
{
return(m_RuleRealValues[t]);
}
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const{
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
{
return (m_RuleBoolValues[t] == 1);
}
+13 -58
View File
@@ -85,8 +85,6 @@ RULE_INT(Character, MaxCharmDurationForPlayerCharacter, 15)
RULE_INT(Character, BaseHPRegenBonusRaces, 4352) //a bitmask of race(s) that receive the regen bonus. Iksar (4096) & Troll (256) = 4352. see common/races.h for the bitmask values
RULE_BOOL(Character, SoDClientUseSoDHPManaEnd, false) // Setting this to true will allow SoD clients to use the SoD HP/Mana/End formulas and previous clients will use the old formulas
RULE_BOOL(Character, UseRaceClassExpBonuses, true) // Setting this to true will enable Class and Racial experience rate bonuses
RULE_BOOL(Character, UseOldRaceExpPenalties, false) // Setting this to true will enable racial exp penalties for Iksar, Troll, Ogre, and Barbarian, as well as the bonus for Halflings
RULE_BOOL(Character, UseOldClassExpPenalties, false) // Setting this to true will enable old class exp penalties for Paladin, SK, Ranger, Bard, Monk, Wizard, Enchanter, Magician, and Necromancer, as well as the bonus for Rogues and Warriors
RULE_BOOL(Character, RespawnFromHover, false) // Use Respawn window, or not.
RULE_INT(Character, RespawnFromHoverTimer, 300) // Respawn Window countdown timer, in SECONDS
RULE_BOOL(Character, UseNewStatsWindow, true) // New stats window shows everything
@@ -101,7 +99,6 @@ RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Wind
RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap
RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update
RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well.
RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field
RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225.
RULE_INT(Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type
RULE_REAL(Character, EnvironmentDamageMulipliter, 1)
@@ -116,16 +113,6 @@ RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjus
RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster.
RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster.
RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster.
RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on!
RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100%
RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?)
RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?)
RULE_INT(Character, TrollCommonTongue, 95) // 95 By default (live-like?)
RULE_BOOL(Character, ActiveInvSnapshots, false) // Takes a periodic snapshot of inventory contents from online players
RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) between inventory snapshots
RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure
RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries
RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing to allowable races/classes of spell scroll, if true
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@@ -196,7 +183,6 @@ RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against Ant
RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)
RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method.
RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS.
RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using
RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules.
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
@@ -233,7 +219,6 @@ RULE_BOOL(Zone, LevelBasedEXPMods, false) // Allows you to use the level_exp_mod
RULE_INT(Zone, WeatherTimer, 600) // Weather timer when no duration is available
RULE_BOOL(Zone, EnableLoggedOffReplenishments, true)
RULE_INT(Zone, MinOfflineTimeToReplenishments, 21600) // 21600 seconds is 6 Hours
RULE_BOOL(Zone, UseZoneController, true) // Enables the ability to use persistent quest based zone controllers (zone_controller.pl/lua)
RULE_CATEGORY_END()
RULE_CATEGORY(Map)
@@ -351,8 +336,8 @@ RULE_INT(Spells, AI_EngagedDetrimentalChance, 20) // Chance during third AI Cast
RULE_INT(Spells, AI_PursueNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while chasing target. (min time in random)
RULE_INT(Spells, AI_PursueNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing target to cast a detrimental spell.
RULE_INT(Spells, AI_IdleNoSpellMinRecast, 6000) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 60000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
RULE_INT(Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
RULE_INT(Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others.
RULE_BOOL(Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false)
RULE_BOOL(Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014
@@ -450,7 +435,7 @@ RULE_REAL (Combat,TauntSkillFalloff, 0.33)//For every taunt skill point that's n
RULE_BOOL (Combat,EXPFromDmgShield, false) //Determine if damage from a damage shield counts for EXP gain.
RULE_INT(Combat, MonkACBonusWeight, 15)
RULE_INT(Combat, ClientStunLevel, 55) //This is the level where client kicks and bashes can stun the target
RULE_INT(Combat, QuiverHasteCap, 1000) //Quiver haste cap 1000 on live for a while, currently 700 on live
RULE_INT(Combat, QuiverWRHasteDiv, 3) //Weight Reduction is divided by this to get haste contribution for quivers
RULE_BOOL(Combat, UseArcheryBonusRoll, false) //Make the 51+ archery bonus require an actual roll
RULE_INT(Combat, ArcheryBonusChance, 50)
RULE_INT(Combat, BerserkerFrenzyStart, 35)
@@ -459,10 +444,6 @@ RULE_BOOL(Combat, OneProcPerWeapon, true) //If enabled, One proc per weapon per
RULE_BOOL(Combat, ProjectileDmgOnImpact, true) //If enabled, projectiles (ie arrows) will hit on impact, instead of instantly.
RULE_BOOL(Combat, MeleePush, true) // enable melee push
RULE_INT(Combat, MeleePushChance, 50) // (NPCs) chance the target will be pushed. Made up, 100 actually isn't that bad
RULE_BOOL(Combat, UseLiveCombatRounds, true) // turn this false if you don't want to worry about fixing up combat rounds for NPCs
RULE_INT(Combat, NPCAssistCap, 5) // Maxiumium number of NPCs that will assist another NPC at once
RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will take to clear assist aggro cap space
RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF
RULE_CATEGORY_END()
RULE_CATEGORY(NPC)
@@ -482,8 +463,6 @@ RULE_BOOL(NPC, ReturnNonQuestNoDropItems, false) // Returns NO DROP items on NPC
RULE_INT(NPC, StartEnrageValue, 9) // % HP that an NPC will begin to enrage
RULE_BOOL(NPC, LiveLikeEnrage, false) // If set to true then only player controlled pets will enrage
RULE_BOOL(NPC, EnableMeritBasedFaction, false) // If set to true, faction will given in the same way as experience (solo/group/raid)
RULE_INT(NPC, NPCToNPCAggroTimerMin, 500)
RULE_INT(NPC, NPCToNPCAggroTimerMax, 6000)
RULE_CATEGORY_END()
RULE_CATEGORY(Aggro)
@@ -496,9 +475,8 @@ RULE_INT(Aggro, SpellAggroMod, 100)
RULE_INT(Aggro, SongAggroMod, 33)
RULE_INT(Aggro, PetSpellAggroMod, 10)
RULE_REAL(Aggro, TunnelVisionAggroMod, 0.75) //people not currently the top hate generate this much hate on a Tunnel Vision mob
RULE_INT(Aggro, MaxScalingProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that HP scaling SPA effect in a proc will add.
RULE_INT(Aggro, MaxStunProcAggro, 400) // Set to -1 for no limit. Maxmimum amount of aggro that a stun based proc will add.
RULE_INT(Aggro, IntAggroThreshold, 75) // Int <= this will aggro regardless of level difference.
RULE_BOOL(Aggro, AllowTickPulling, false) // tick pulling is an exploit in an NPC's call for help fixed sometime in 2006 on live
RULE_CATEGORY_END()
RULE_CATEGORY(TaskSystem)
@@ -512,19 +490,17 @@ RULE_CATEGORY_END()
#ifdef BOTS
RULE_CATEGORY(Bots)
RULE_INT(Bots, AAExpansion, 8) // Bots get AAs through this expansion
RULE_INT(Bots, CreationLimit, 150) // Number of bots that each account can create
RULE_BOOL(Bots, FinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.
RULE_BOOL(Bots, GroupBuffing, false) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.
RULE_REAL(Bots, ManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.
RULE_BOOL(Bots, QuestableSpawnLimit, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl
RULE_BOOL(Bots, QuestableSpells, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests.
RULE_INT(Bots, SpawnLimit, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid
RULE_REAL(Bots, BotManaRegen, 2.0) // Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.
RULE_BOOL(Bots, BotFinishBuffing, false) // Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.
RULE_INT(Bots, CreateBotCount, 150) // Number of bots that each account can create
RULE_INT(Bots, SpawnBotCount, 71) // Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid
RULE_BOOL(Bots, BotQuest, false) // Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl
RULE_BOOL(Bots, BotGroupBuffing, false) // Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.
RULE_BOOL(Bots, BotSpellQuest, false) // Anita Thrall's (Anita_Thrall.pl) Bot Spell Scriber quests.
RULE_INT(Bots, BotAAExpansion, 8) // Bots get AAs through this expansion
RULE_BOOL(Bots, BotGroupXP, false) // Determines whether client gets xp for bots outside their group.
RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs (optional script)
RULE_BOOL(Bots, BotBardUseOutOfCombatSongs, true) // Determines whether bard bots use additional out of combat songs.
RULE_BOOL(Bots, BotLevelsWithOwner, false) // Auto-updates spawned bots as owner levels/de-levels (false is original behavior)
RULE_BOOL(Bots, BotCharacterLevelEnabled, false) // Enables required level to spawn bots
RULE_INT(Bots, BotCharacterLevel, 0) // 0 as default (if level > this value you can spawn bots if BotCharacterLevelEnabled is true)
RULE_CATEGORY_END()
#endif
@@ -608,27 +584,6 @@ RULE_CATEGORY_END()
RULE_CATEGORY(QueryServ)
RULE_BOOL(QueryServ, PlayerLogChat, false) // Logs Player Chat
RULE_BOOL(QueryServ, PlayerLogTrades, false) // Logs Player Trades
RULE_BOOL(QueryServ, PlayerLogHandins, false) // Logs Player Handins
RULE_BOOL(QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills
RULE_BOOL(QueryServ, PlayerLogDeletes, false) // Logs Player Deletes
RULE_BOOL(QueryServ, PlayerLogMoves, false) // Logs Player Moves
RULE_BOOL(QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions
RULE_BOOL(QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events
RULE_BOOL(QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item
RULE_BOOL(QueryServ, PlayerLogZone, false) // Logs Player Zone Events
RULE_BOOL(QueryServ, PlayerLogDeaths, false) // Logs Player Deaths
RULE_BOOL(QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State
RULE_BOOL(QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling
RULE_BOOL(QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates
RULE_BOOL(QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates
RULE_BOOL(QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates
RULE_BOOL(QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions
RULE_BOOL(QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases
RULE_BOOL(QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions
RULE_BOOL(QueryServ, PlayerLogIssuedCommandes, false) // Log Player Issued Commands
RULE_BOOL(QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits
RULE_BOOL(QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions
RULE_CATEGORY_END()
RULE_CATEGORY(Inventory)
+2 -140
View File
@@ -84,7 +84,6 @@
#define ServerOP_QGlobalDelete 0x0064
#define ServerOP_DepopPlayerCorpse 0x0065
#define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues
#define ServerOP_ChangeSharedMem 0x0067
#define ServerOP_RaidAdd 0x0100 //in use
#define ServerOP_RaidRemove 0x0101 //in use
@@ -182,15 +181,7 @@
#define ServerOP_CZMessagePlayer 0x4008
#define ServerOP_ReloadWorld 0x4009
#define ServerOP_ReloadLogs 0x4010
#define ServerOP_ReloadPerlExportSettings 0x4011
/* Query Server OP Codes */
#define ServerOP_QSPlayerLogTrades 0x5010
#define ServerOP_QSPlayerLogHandins 0x5011
#define ServerOP_QSPlayerLogNPCKills 0x5012
#define ServerOP_QSPlayerLogDeletes 0x5013
#define ServerOP_QSPlayerLogMoves 0x5014
#define ServerOP_QSPlayerLogMerchantTransactions 0x5015
#define ServerOP_QSSendQuery 0x5016
#define ServerOP_QSSendQuery 0x5000
#define ServerOP_CZSignalNPC 0x5017
#define ServerOP_CZSetEntityVariableByNPCTypeID 0x5018
@@ -523,7 +514,7 @@ struct ServerLSPlayerZoneChange_Struct {
uint32 from; // 0 = world
uint32 to; // 0 = world
};
struct ClientAuth_Struct {
struct ServerLSClientAuth {
uint32 lsaccount_id; // ID# in login server's db
char name[30]; // username in login server's db
char key[30]; // the Key the client will present
@@ -547,9 +538,7 @@ struct ServerLSPeerConnect {
struct ServerConnectInfo {
char address[250];
char local_address[250];
uint16 port;
uint32 process_id;
};
struct ServerGMGoto_Struct {
@@ -764,7 +753,6 @@ typedef enum {
struct LauncherZoneRequest {
uint8 command;
char short_name[33];
uint16 port;
};
struct LauncherZoneStatus {
@@ -1118,132 +1106,6 @@ struct CZClientSignalByName_Struct {
uint32 data;
};
struct QSTradeItems_Struct {
uint32 from_id;
uint16 from_slot;
uint32 to_id;
uint16 to_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogTrade_Struct {
uint32 char1_id;
MoneyUpdate_Struct char1_money;
uint16 char1_count;
uint32 char2_id;
MoneyUpdate_Struct char2_money;
uint16 char2_count;
uint16 _detail_count;
QSTradeItems_Struct items[0];
};
struct QSHandinItems_Struct {
char action_type[7]; // handin, return or reward
uint16 char_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogHandin_Struct {
uint32 quest_id;
uint32 char_id;
MoneyUpdate_Struct char_money;
uint16 char_count;
uint32 npc_id;
MoneyUpdate_Struct npc_money;
uint16 npc_count;
uint16 _detail_count;
QSHandinItems_Struct items[0];
};
struct QSPlayerLogNPCKillSub_Struct{
uint32 NPCID;
uint32 ZoneID;
uint32 Type;
};
struct QSPlayerLogNPCKillsPlayers_Struct{
uint32 char_id;
};
struct QSPlayerLogNPCKill_Struct{
QSPlayerLogNPCKillSub_Struct s1;
QSPlayerLogNPCKillsPlayers_Struct Chars[0];
};
struct QSDeleteItems_Struct {
uint16 char_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogDelete_Struct {
uint32 char_id;
uint16 stack_size; // '0' indicates full stack or non-stackable item move
uint16 char_count;
QSDeleteItems_Struct items[0];
};
struct QSMoveItems_Struct {
uint16 from_slot;
uint16 to_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSPlayerLogMove_Struct {
uint32 char_id;
uint16 from_slot;
uint16 to_slot;
uint16 stack_size; // '0' indicates full stack or non-stackable item move
uint16 char_count;
bool postaction;
QSMoveItems_Struct items[0];
};
struct QSTransactionItems_Struct {
uint16 char_slot;
uint32 item_id;
uint16 charges;
uint32 aug_1;
uint32 aug_2;
uint32 aug_3;
uint32 aug_4;
uint32 aug_5;
};
struct QSMerchantLogTransaction_Struct {
uint32 zone_id;
uint32 merchant_id;
MoneyUpdate_Struct merchant_money;
uint16 merchant_count;
uint32 char_id;
MoneyUpdate_Struct char_money;
uint16 char_count;
QSTransactionItems_Struct items[0];
};
struct QSGeneralQuery_Struct {
char QueryString[0];
};
+478 -529
View File
File diff suppressed because it is too large Load Diff
+31 -35
View File
@@ -9,19 +9,19 @@
#include "base_data.h"
#include "fixed_memory_hash_set.h"
#include "fixed_memory_variable_hash_set.h"
#include "inventory.h"
#include <list>
#include <map>
#include <memory>
class EvolveInfo;
class Inventory;
class InventoryOld;
class ItemInst;
struct BaseDataStruct;
struct InspectMessage_Struct;
struct PlayerProfile_Struct;
struct SPDat_Spell_Struct;
struct Item_Struct;
struct ItemData;
struct NPCFactionList;
struct LootTable_Struct;
struct LootDrop_Struct;
@@ -51,7 +51,9 @@ class SharedDatabase : public Database
int32 DeleteStalePlayerCorpses();
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message);
void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message);
bool GetCommandSettings(std::map<std::string, uint8> &commands);
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
/*
@@ -64,15 +66,15 @@ class SharedDatabase : public Database
bool UpdateInventorySlot(uint32 char_id, const ItemInst* inst, int16 slot_id);
bool UpdateSharedBankSlot(uint32 char_id, const ItemInst* inst, int16 slot_id);
bool VerifyInventory(uint32 account_id, int16 slot_id, const ItemInst* inst);
bool GetSharedBank(uint32 id, Inventory* inv, bool is_charid);
bool GetSharedBank(uint32 id, InventoryOld* inv, bool is_charid);
int32 GetSharedPlatinum(uint32 account_id);
bool SetSharedPlatinum(uint32 account_id, int32 amount_to_add);
bool GetInventory(uint32 char_id, Inventory* inv);
bool GetInventory(uint32 account_id, char* name, Inventory* inv);
bool GetInventory(uint32 char_id, EQEmu::Inventory* inv);
bool GetInventory(uint32 account_id, char* name, InventoryOld* inv);
std::map<uint32, uint32> GetItemRecastTimestamps(uint32 char_id);
uint32 GetItemRecastTimestamp(uint32 char_id, uint32 recast_type);
void ClearOldRecastTimestamps(uint32 char_id);
bool SetStartingItems(PlayerProfile_Struct* pp, Inventory* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
bool SetStartingItems(PlayerProfile_Struct* pp, InventoryOld* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin);
std::string GetBook(const char *txtfile);
@@ -80,9 +82,10 @@ class SharedDatabase : public Database
/*
Item Methods
*/
ItemInst* CreateItem(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateItem(const Item_Struct* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateBaseItem(const Item_Struct* item, int16 charges = 0);
ItemInst* CreateItemOld(uint32 item_id, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateItemOld(const ItemData* item, int16 charges = 0, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, uint8 attuned = 0);
ItemInst* CreateBaseItemOld(const ItemData* item, int16 charges = 0);
EQEmu::ItemInstance::pointer CreateItem(uint32 item_id, int16 charges = 0, bool unique = true);
/*
Shared Memory crap
@@ -91,59 +94,52 @@ class SharedDatabase : public Database
//items
void GetItemsCount(int32 &item_count, uint32 &max_id);
void LoadItems(void *data, uint32 size, int32 items, uint32 max_item_id);
bool LoadItems(const std::string &prefix);
const Item_Struct* IterateItems(uint32* id);
const Item_Struct* GetItem(uint32 id);
bool LoadItems();
const ItemData* IterateItems(uint32* id);
const ItemData* GetItem(uint32 id);
const EvolveInfo* GetEvolveInfo(uint32 loregroup);
//faction lists
void GetFactionListInfo(uint32 &list_count, uint32 &max_lists);
const NPCFactionList* GetNPCFactionEntry(uint32 id);
void LoadNPCFactionLists(void *data, uint32 size, uint32 list_count, uint32 max_lists);
bool LoadNPCFactionLists(const std::string &prefix);
bool LoadNPCFactionLists();
//loot
void GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot_table, uint32 &loot_table_entries);
void GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_drop, uint32 &loot_drop_entries);
void LoadLootTables(void *data, uint32 size);
void LoadLootDrops(void *data, uint32 size);
bool LoadLoot(const std::string &prefix);
bool LoadLoot();
const LootTable_Struct* GetLootTable(uint32 loottable_id);
const LootDrop_Struct* GetLootDrop(uint32 lootdrop_id);
void LoadSkillCaps(void *data);
bool LoadSkillCaps(const std::string &prefix);
bool LoadSkillCaps();
uint16 GetSkillCap(uint8 Class_, SkillUseTypes Skill, uint8 Level);
uint8 GetTrainLevel(uint8 Class_, SkillUseTypes Skill, uint8 Level);
int GetMaxSpellID();
bool LoadSpells(const std::string &prefix, int32 *records, const SPDat_Spell_Struct **sp);
void LoadSpells(void *data, int max_spells);
void LoadDamageShieldTypes(SPDat_Spell_Struct* sp, int32 iMaxSpellID);
int GetMaxBaseDataLevel();
bool LoadBaseData(const std::string &prefix);
bool LoadBaseData();
void LoadBaseData(void *data, int max_level);
const BaseDataStruct* GetBaseData(int lvl, int cl);
#ifdef BOTS
void GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message);
void SetBotInspectMessage(uint32 botid, const InspectMessage_Struct* message);
#endif
protected:
std::unique_ptr<EQEmu::MemoryMappedFile> skill_caps_mmf;
std::unique_ptr<EQEmu::MemoryMappedFile> items_mmf;
std::unique_ptr<EQEmu::FixedMemoryHashSet<Item_Struct>> items_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> faction_mmf;
std::unique_ptr<EQEmu::FixedMemoryHashSet<NPCFactionList>> faction_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> loot_table_mmf;
std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootTable_Struct>> loot_table_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> loot_drop_mmf;
std::unique_ptr<EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct>> loot_drop_hash;
std::unique_ptr<EQEmu::MemoryMappedFile> base_data_mmf;
std::unique_ptr<EQEmu::MemoryMappedFile> spells_mmf;
EQEmu::MemoryMappedFile *skill_caps_mmf;
EQEmu::MemoryMappedFile *items_mmf;
EQEmu::FixedMemoryHashSet<ItemData> *items_hash;
EQEmu::MemoryMappedFile *faction_mmf;
EQEmu::FixedMemoryHashSet<NPCFactionList> *faction_hash;
EQEmu::MemoryMappedFile *loot_table_mmf;
EQEmu::FixedMemoryVariableHashSet<LootTable_Struct> *loot_table_hash;
EQEmu::MemoryMappedFile *loot_drop_mmf;
EQEmu::FixedMemoryVariableHashSet<LootDrop_Struct> *loot_drop_hash;
EQEmu::MemoryMappedFile *base_data_mmf;
};
#endif /*SHAREDDB_H_*/
+4 -5
View File
@@ -108,17 +108,16 @@ enum SkillUseTypes
/*13869*/ SkillBerserking,
/*13902*/ SkillTaunt,
/*05837*/ SkillFrenzy, // This appears to be the only listed one not grouped with the others
/*00000*/ _EmuSkillCount // move to last position of active enumeration labels
// SoF+ specific skills
/*03670*/ SkillRemoveTraps,
/*13049*/ SkillTripleAttack,
// /*03670*/ SkillRemoveTraps,
// /*13049*/ SkillTripleAttack,
// RoF2+ specific skills
// /*00789*/ Skill2HPiercing,
// /*01216*/ SkillNone, // This needs to move down as new skills are added
/*00000*/ _EmuSkillCount // move to last position of active enumeration labels
// Skill Counts
// /*-----*/ _SkillCount_62 = 75, // use for Ti and earlier max skill checks
// /*-----*/ _SkillCount_SoF = 77, // use for SoF thru RoF1 max skill checks
@@ -171,7 +170,7 @@ enum SkillUseTypes
};
// temporary until it can be sorted out...
#define HIGHEST_SKILL SkillTripleAttack
#define HIGHEST_SKILL SkillFrenzy
// Spell Effects use this value to determine if an effect applies to all skills.
#define ALL_SKILLS -1
+1 -9
View File
@@ -447,7 +447,7 @@ bool IsTGBCompatibleSpell(uint16 spell_id)
bool IsBardSong(uint16 spell_id)
{
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 255 && !spells[spell_id].IsDisciplineBuff)
if (IsValidSpell(spell_id) && spells[spell_id].classes[BARD - 1] < 127 && !spells[spell_id].IsDisciplineBuff)
return true;
return false;
@@ -1092,14 +1092,6 @@ bool DetrimentalSpellAllowsRest(uint16 spell_id)
return false;
}
bool NoDetrimentalSpellAggro(uint16 spell_id)
{
if (IsValidSpell(spell_id))
return spells[spell_id].no_detrimental_spell_aggro;
return false;
}
uint32 GetNimbusEffect(uint16 spell_id)
{
if (IsValidSpell(spell_id))
+32 -49
View File
@@ -381,47 +381,47 @@ typedef enum {
#define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance.
#define SE_TwoHandBash 226 // *not implemented as bonus
#define SE_ReduceSkillTimer 227 // implemented
#define SE_ReduceFallDamage 228 // implented - reduce the damage that you take from falling
//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
#define SE_PersistantCasting 229 // implemented
#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
//#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
//#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
//#define SE_FreePet 236 // not used
#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity)
#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
#define SE_FeignedCastOnChance 239 // implemented - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
#define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr
#define SE_CharmBreakChance 243 // implemented - Total Domination
#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break.
#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
//#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
#define SE_SetBreathLevel 246 // *not implemented as bonus
#define SE_RaiseSkillCap 247 // implemented[AA] - adds skill over the skill cap.
#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
#define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap.
//#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
#define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes)
#define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther)
#define SE_ConsumeProjectile 251 // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100)
#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front.
#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage.
#define SE_Blank 254 // implemented
#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
#define SE_ShroudofStealth 256 // implemented
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
//#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
//#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs
//#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
#define SE_CombatStability 259 // implemented[AA] - damage mitigation
#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType
#define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live)
#define SE_RaiseStatCap 262 // implemented
#define SE_TradeSkillMastery 263 // implemented - lets you raise more than one tradeskill above master.
#define SE_HastenedAASkill 264 // implemented
//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master.
//#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect
#define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled
#define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon.
#define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast
#define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance
//#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance
#define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound.
#define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo)
#define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods
@@ -434,14 +434,14 @@ typedef enum {
#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage)
#define SE_Flurry 279 // implemented
#define SE_PetFlurry 280 // implemented[AA]
#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
//#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent.
#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk
//#define SE_LoHSetHeal 284 // not used
#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
//#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
#define SE_FcDamageAmt 286 // implemented - adds direct spell damage
#define SE_SpellDurationIncByTic 287 // implemented
#define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch)
#define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch].
#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration.
#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap
#define SE_Purify 291 // implemented - Removes determental effects
@@ -478,7 +478,7 @@ typedef enum {
#define SE_GateToHomeCity 322 // implemented
#define SE_DefensiveProc 323 // implemented
#define SE_HPToMana 324 // implemented
#define SE_NoBreakAESneak 325 // implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
//#define SE_ChanceInvsBreakToAoE 325 // *not implemented[AA] - [AA Nerves of Steel] increasing chance to remain hidden when they are an indirect target of an AoE spell.
#define SE_SpellSlotIncrease 326 // *not implemented as bonus - increases your spell slot availability
#define SE_MysticalAttune 327 // implemented - increases amount of buffs that a player can have
#define SE_DelayDeath 328 // implemented - increases how far you can fall below 0 hp before you die
@@ -486,7 +486,7 @@ typedef enum {
#define SE_CriticalDamageMob 330 // implemented
#define SE_Salvage 331 // implemented - chance to recover items that would be destroyed in failed tradeskill combine
//#define SE_SummonToCorpse 332 // *not implemented AA - Call of the Wild (Druid/Shaman Res spell with no exp)
#define SE_CastOnRuneFadeEffect 333 // implemented
#define SE_CastOnRuneFadeEffect 333 // implemented
#define SE_BardAEDot 334 // implemented
#define SE_BlockNextSpellFocus 335 // implemented - base1 chance to block next spell ie Puratus (8494)
//#define SE_IllusionaryTarget 336 // not used
@@ -515,8 +515,8 @@ typedef enum {
//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing)
#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level
#define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed
#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
//#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
//#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
#define SE_TripleAttackChance 364 // implemented
#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin)
#define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA
@@ -525,7 +525,7 @@ typedef enum {
#define SE_CorruptionCounter 369 // implemented
#define SE_ResistCorruption 370 // implemented
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
//#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
#define SE_ApplyEffect 374 // implemented
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
@@ -544,7 +544,7 @@ typedef enum {
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
#define SE_LimitManaMax 391 // implemented
#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used]
#define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells
#define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions.
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
@@ -579,7 +579,7 @@ typedef enum {
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires.
@@ -613,25 +613,12 @@ typedef enum {
#define SE_ResourceTap 457 // implemented Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
#define SE_FactionModPct 458 // implemented Modifies faction gains and losses by percent.
#define SE_DamageModifier2 459 // implemented - Modifies melee damage by skill type
//#define SE_Ff_Override_NotFocusable 460 //
#define SE_ImprovedDamage2 461 // implemented - Increase spell damage by percent (SE_Fc_Damage_%2)
#define SE_FcDamageAmt2 462 // implemented - Increase spell damage by flat amount (SE_Fc_Damage_Amt2)
//#define SE_Shield_Target 463 //
#define SE_PC_Pet_Rampage 464 // implemented - Base1 % chance to do rampage for base2 % of damage each melee round
//#define SE_PC_Pet_AE_Rampage 465 // Would assume as above but need to confirm.
#define SE_PC_Pet_Flurry_Chance 466 // implemented - Base1 % chance to do flurry from double attack hit.
//#define SE_DS_Mitigation_Amount 467 //
//#define SE_DS_Mitigation_Percentage 468 //
//#define SE_Chance_Best_in_Spell_Grp 469 //
//#define SE_Trigger_Best_in_Spell Grp 470 //
//#define SE_Double_Melee_Round 471 //
// LAST
#define DF_Permanent 50
#define DF_Aura 51
#define DF_Aura 51
// note this struct is historical, we don't actually need it to be
// aligned to anything, but for maintaining it it is kept in the order that
@@ -744,28 +731,26 @@ struct SPDat_Spell_Struct
/* 194 */ float directional_start; //Cone Start Angle:
/* 195 */ float directional_end; // Cone End Angle:
/* 196 */ bool sneak; // effect can only be used if sneaking (rogue 'Daggerfall' ect)
/* 197 */ bool not_focusable; //prevents focus effects from being applied to spell
/* 198 */ bool no_detrimental_spell_aggro;
/* 199 */
/* 197 */ bool not_extendable;
/* 198- 199 */
/* 200 */ bool suspendable; // buff is suspended in suspended buff zones
/* 201 */ int viral_range;
/* 202 */ int songcap; // individual song cap
/* 203 */
/* 202 */
/* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented)
/* 204 */
/* 205 */ bool no_block;
/* 206 */
/* 207 */ int spellgroup;
/* 208 */ int rank; //increments AA effects with same name
/* 209 */ int no_resist; //makes spells unresistable, which makes charms unbreakable as well.
/* 209 */ int powerful_flag; // Need more investigation to figure out what to call this, for now we know -1 makes charm spells not break before their duration is complete, it does alot more though
/* 210 */ // bool DurationFrozen; ???
/* 211 */ int CastRestriction; //Various restriction categories for spells most seem targetable race related but have also seen others for instance only castable if target hp 20% or lower or only if target out of combat
/* 212 */ bool AllowRest;
/* 213 */ bool InCombat; //Allow spell if target is in combat
/* 214 */ bool OutofCombat; //Allow spell if target is out of combat
/* 215 - 216 */
/* 217 */ int override_crit_chance; //Places a cap on the max chance to critical
/* 215 - 217 */
/* 218 */ int aemaxtargets; //Is used for various AE effects
/* 219 */ int no_heal_damage_item_mod;
/* 219 */ int maxtargets; //Is used for beam and ring spells for target # limits (not implemented)
/* 220 - 223 */
/* 224 */ bool persistdeath; // buff doesn't get stripped on death
/* 225 - 226 */
@@ -774,8 +759,7 @@ struct SPDat_Spell_Struct
/* 229 */ float max_dist; //spell power modified by distance from caster (Max Distance)
/* 230 */ float max_dist_mod; //spell power modified by distance from caster (Modifier at Max Distance)
/* 231 */ float min_range; //Min casting range
/* 232 */ bool no_remove; //prevents buff from being removed by click
/* 233 - 236 */
/* 232 - 236 */
uint8 DamageShieldType; // This field does not exist in spells_us.txt
};
@@ -881,7 +865,6 @@ uint32 GetPartialMeleeRuneReduction(uint32 spell_id);
uint32 GetPartialMagicRuneReduction(uint32 spell_id);
uint32 GetPartialMeleeRuneAmount(uint32 spell_id);
uint32 GetPartialMagicRuneAmount(uint32 spell_id);
bool NoDetrimentalSpellAggro(uint16 spell_id);
int CalcPetHp(int levelb, int classb, int STA = 75);
const char *GetRandPetName();
+1 -3
View File
@@ -23,9 +23,7 @@
*/
#ifdef _WINDOWS
#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900))
#define snprintf _snprintf
#endif
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
+1 -3
View File
@@ -43,9 +43,7 @@ typedef unsigned char uchar;
typedef const char Const_char; //for perl XS
#ifdef _WINDOWS
#if (!defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER < 1900))
#define snprintf _snprintf
#endif
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
typedef void ThreadReturnType;
+1 -6
View File
@@ -30,12 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9095
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000
#else
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0
#endif
#define CURRENT_BINARY_DATABASE_VERSION 9083
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
#ifndef WIN32
+2
View File
@@ -102,6 +102,8 @@ int main(int argc, char *argv[]) {
Log.Out(Logs::Detail, Logs::Launcher, "Starting main loop...");
// zones["test"] = new ZoneLaunch(&world, "./zone", "dynamic_1");
ProcLauncher *launch = ProcLauncher::get();
RunLoops = true;
while(RunLoops) {
+2 -1
View File
@@ -86,13 +86,14 @@ void WorldServer::Process() {
}
const LauncherZoneRequest *lzr = (const LauncherZoneRequest *) pack->pBuffer;
switch(ZoneRequestCommands(lzr->command)) {
case ZR_Start: {
if(m_zones.find(lzr->short_name) != m_zones.end()) {
Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s, but it is already running.", lzr->short_name);
} else {
Log.Out(Logs::Detail, Logs::Launcher, "World told us to start zone %s.", lzr->short_name);
ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, lzr->port, m_config);
ZoneLaunch *l = new ZoneLaunch(this, m_name, lzr->short_name, m_config);
m_zones[lzr->short_name] = l;
}
break;
+5 -10
View File
@@ -34,11 +34,10 @@ void ZoneLaunch::InitStartTimer() {
}
ZoneLaunch::ZoneLaunch(WorldServer *world, const char *launcher_name,
const char *zone_name, uint16 port, const EQEmuConfig *config)
const char *zone_name, const EQEmuConfig *config)
: m_state(StateStartPending),
m_world(world),
m_zone(zone_name),
m_port(port),
m_launcherName(launcher_name),
m_config(config),
m_timer(config->RestartWait),
@@ -62,14 +61,10 @@ void ZoneLaunch::SendStatus() const {
void ZoneLaunch::Start() {
ProcLauncher::Spec *spec = new ProcLauncher::Spec();
spec->program = m_config->ZoneExe;
if(m_port) {
std::string arg = m_zone + std::string(":") + std::to_string(m_port);
spec->args.push_back(arg);
} else {
spec->args.push_back(m_zone);
}
// if(m_zone.substr(0,7) == "dynamic")
// spec->args.push_back(".");
// else
spec->args.push_back(m_zone);
spec->args.push_back(m_launcherName);
spec->handler = this;
spec->logFile = m_config->LogPrefix + m_zone + m_config->LogSuffix;
+1 -2
View File
@@ -28,7 +28,7 @@ class EQEmuConfig;
class ZoneLaunch : protected ProcLauncher::EventHandler {
public:
ZoneLaunch(WorldServer *world, const char *launcher_name,
const char *zone_name, uint16 port, const EQEmuConfig *config);
const char *zone_name, const EQEmuConfig *config);
virtual ~ZoneLaunch();
void Stop(bool graceful = true);
@@ -63,7 +63,6 @@ protected:
const std::string m_zone;
const char *const m_launcherName;
const EQEmuConfig *const m_config;
const uint16 m_port;
Timer m_timer;
ProcLauncher::ProcRef m_ref;
+3 -1
View File
@@ -6,6 +6,7 @@ SET(eqlogin_sources
config.cpp
database_mysql.cpp
database_postgresql.cpp
error_log.cpp
main.cpp
server_manager.cpp
world_server.cpp
@@ -25,6 +26,7 @@ SET(eqlogin_headers
database_postgresql.h
encryption.h
eq_crypto_api.h
error_log.h
login_server.h
login_structures.h
options.h
@@ -41,7 +43,7 @@ ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers})
INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE})
IF(MSVC)
SET_TARGET_PROPERTIES(loginserver PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
+101 -106
View File
@@ -16,12 +16,12 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client.h"
#include "error_log.h"
#include "login_server.h"
#include "login_structures.h"
#include "../common/misc_functions.h"
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern ErrorLog *server_log;
extern LoginServer server;
Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
@@ -41,7 +41,7 @@ bool Client::Process()
{
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Login_Server, "Application packet received from client (size %u)", app->Size());
server_log->Log(log_network, "Application packet received from client (size %u)", app->Size());
}
if(server.options.IsDumpInPacketsOn())
@@ -55,7 +55,7 @@ bool Client::Process()
{
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Login_Server, "Session ready received from client.");
server_log->Log(log_network, "Session ready received from client.");
}
Handle_SessionReady((const char*)app->pBuffer, app->Size());
break;
@@ -64,13 +64,13 @@ bool Client::Process()
{
if(app->Size() < 20)
{
Log.Out(Logs::General, Logs::Error, "Login received but it is too small, discarding.");
server_log->Log(log_network_error, "Login received but it is too small, discarding.");
break;
}
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Login_Server, "Login received from client.");
server_log->Log(log_network, "Login received from client.");
}
Handle_Login((const char*)app->pBuffer, app->Size());
@@ -80,7 +80,7 @@ bool Client::Process()
{
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Login_Server, "Server list request received from client.");
server_log->Log(log_network, "Server list request received from client.");
}
SendServerListPacket();
@@ -90,7 +90,7 @@ bool Client::Process()
{
if(app->Size() < sizeof(PlayEverquestRequest_Struct))
{
Log.Out(Logs::General, Logs::Error, "Play received but it is too small, discarding.");
server_log->Log(log_network_error, "Play received but it is too small, discarding.");
break;
}
@@ -101,7 +101,7 @@ bool Client::Process()
{
char dump[64];
app->build_header_dump(dump);
Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump);
server_log->Log(log_network_error, "Recieved unhandled application packet from the client: %s.", dump);
}
}
@@ -116,20 +116,20 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
{
if(status != cs_not_sent_session_ready)
{
Log.Out(Logs::General, Logs::Error, "Session ready received again after already being received.");
server_log->Log(log_network_error, "Session ready received again after already being received.");
return;
}
if(size < sizeof(unsigned int))
{
Log.Out(Logs::General, Logs::Error, "Session ready was too small.");
server_log->Log(log_network_error, "Session ready was too small.");
return;
}
unsigned int mode = *((unsigned int*)data);
if(mode == (unsigned int)lm_from_world)
{
Log.Out(Logs::General, Logs::Login_Server, "Session ready indicated logged in from world(unsupported feature), disconnecting.");
server_log->Log(log_network, "Session ready indicated logged in from world(unsupported feature), disconnecting.");
connection->Close();
return;
}
@@ -175,144 +175,138 @@ void Client::Handle_SessionReady(const char* data, unsigned int size)
void Client::Handle_Login(const char* data, unsigned int size)
{
if(status != cs_waiting_for_login) {
Log.Out(Logs::General, Logs::Error, "Login received after already having logged in.");
if(status != cs_waiting_for_login)
{
server_log->Log(log_network_error, "Login received after already having logged in.");
return;
}
if((size - 12) % 8 != 0) {
Log.Out(Logs::General, Logs::Error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size);
if((size - 12) % 8 != 0)
{
server_log->Log(log_network_error, "Login received packet of size: %u, this would cause a block corruption, discarding.", size);
return;
}
status = cs_logged_in;
string entered_username;
string entered_password_hash_result;
char *login_packet_buffer = nullptr;
unsigned int db_account_id = 0;
string db_account_password_hash;
string e_user;
string e_hash;
char *e_buffer = nullptr;
unsigned int d_account_id = 0;
string d_pass_hash;
#ifdef WIN32
login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
e_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
int login_packet_buffer_length = strlen(login_packet_buffer);
entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length);
entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1));
int buffer_len = strlen(e_buffer);
e_hash.assign(e_buffer, buffer_len);
e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1));
if(server.options.IsTraceOn()) {
Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str());
Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str());
if(server.options.IsTraceOn())
{
server_log->Log(log_client, "User: %s", e_user.c_str());
server_log->Log(log_client, "Hash: %s", e_hash.c_str());
}
server.eq_crypto->DeleteHeap(login_packet_buffer);
server.eq_crypto->DeleteHeap(e_buffer);
#else
login_packet_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
e_buffer = DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
int login_packet_buffer_length = strlen(login_packet_buffer);
entered_password_hash_result.assign(login_packet_buffer, login_packet_buffer_length);
entered_username.assign((login_packet_buffer + login_packet_buffer_length + 1), strlen(login_packet_buffer + login_packet_buffer_length + 1));
int buffer_len = strlen(e_buffer);
e_hash.assign(e_buffer, buffer_len);
e_user.assign((e_buffer + buffer_len + 1), strlen(e_buffer + buffer_len + 1));
if(server.options.IsTraceOn()) {
Log.Out(Logs::General, Logs::Debug, "User: %s", entered_username.c_str());
Log.Out(Logs::General, Logs::Debug, "Hash: %s", entered_password_hash_result.c_str());
if(server.options.IsTraceOn())
{
server_log->Log(log_client, "User: %s", e_user.c_str());
server_log->Log(log_client, "Hash: %s", e_hash.c_str());
}
_HeapDeleteCharBuffer(login_packet_buffer);
_HeapDeleteCharBuffer(e_buffer);
#endif
bool result;
if(server.db->GetLoginDataFromAccountName(entered_username, db_account_password_hash, db_account_id) == false) {
/* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/
if (
server.config->GetVariable("options", "auto_create_accounts").compare("TRUE") == 0 &&
server.db->CreateLoginData(entered_username, entered_password_hash_result, db_account_id) == true
){
Log.Out(Logs::General, Logs::Error, "User %s does not exist in the database, so we created it...", entered_username.c_str());
result = true;
}
else{
Log.Out(Logs::General, Logs::Error, "Error logging in, user %s does not exist in the database.", entered_username.c_str());
result = false;
}
if(server.db->GetLoginDataFromAccountName(e_user, d_pass_hash, d_account_id) == false)
{
server_log->Log(log_client_error, "Error logging in, user %s does not exist in the database.", e_user.c_str());
result = false;
}
else {
if(db_account_password_hash.compare(entered_password_hash_result) == 0) {
else
{
if(d_pass_hash.compare(e_hash) == 0)
{
result = true;
}
else {
else
{
result = false;
}
}
/* Login Accepted */
if(result) {
server.client_manager->RemoveExistingClient(db_account_id);
if(result)
{
server.CM->RemoveExistingClient(d_account_id);
in_addr in;
in.s_addr = connection->GetRemoteIP();
server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in)));
server.db->UpdateLSAccountData(d_account_id, string(inet_ntoa(in)));
GenerateKey();
account_id = db_account_id;
account_name = entered_username;
account_id = d_account_id;
account_name = e_user;
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80);
const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data;
LoginAccepted_Struct* login_accepted = (LoginAccepted_Struct *)outapp->pBuffer;
login_accepted->unknown1 = llrs->unknown1;
login_accepted->unknown2 = llrs->unknown2;
login_accepted->unknown3 = llrs->unknown3;
login_accepted->unknown4 = llrs->unknown4;
login_accepted->unknown5 = llrs->unknown5;
LoginLoginAccepted_Struct* llas = (LoginLoginAccepted_Struct *)outapp->pBuffer;
llas->unknown1 = llrs->unknown1;
llas->unknown2 = llrs->unknown2;
llas->unknown3 = llrs->unknown3;
llas->unknown4 = llrs->unknown4;
llas->unknown5 = llrs->unknown5;
LoginFailedAttempts_Struct * login_failed_attempts = new LoginFailedAttempts_Struct;
memset(login_failed_attempts, 0, sizeof(LoginFailedAttempts_Struct));
Login_ReplyBlock_Struct * lrbs = new Login_ReplyBlock_Struct;
memset(lrbs, 0, sizeof(Login_ReplyBlock_Struct));
login_failed_attempts->failed_attempts = 0;
login_failed_attempts->message = 0x01;
login_failed_attempts->lsid = db_account_id;
login_failed_attempts->unknown3[3] = 0x03;
login_failed_attempts->unknown4[3] = 0x02;
login_failed_attempts->unknown5[0] = 0xe7;
login_failed_attempts->unknown5[1] = 0x03;
login_failed_attempts->unknown6[0] = 0xff;
login_failed_attempts->unknown6[1] = 0xff;
login_failed_attempts->unknown6[2] = 0xff;
login_failed_attempts->unknown6[3] = 0xff;
login_failed_attempts->unknown7[0] = 0xa0;
login_failed_attempts->unknown7[1] = 0x05;
login_failed_attempts->unknown8[3] = 0x02;
login_failed_attempts->unknown9[0] = 0xff;
login_failed_attempts->unknown9[1] = 0x03;
login_failed_attempts->unknown11[0] = 0x63;
login_failed_attempts->unknown12[0] = 0x01;
memcpy(login_failed_attempts->key, key.c_str(), key.size());
lrbs->failed_attempts = 0;
lrbs->message = 0x01;
lrbs->lsid = d_account_id;
lrbs->unknown3[3] = 0x03;
lrbs->unknown4[3] = 0x02;
lrbs->unknown5[0] = 0xe7;
lrbs->unknown5[1] = 0x03;
lrbs->unknown6[0] = 0xff;
lrbs->unknown6[1] = 0xff;
lrbs->unknown6[2] = 0xff;
lrbs->unknown6[3] = 0xff;
lrbs->unknown7[0] = 0xa0;
lrbs->unknown7[1] = 0x05;
lrbs->unknown8[3] = 0x02;
lrbs->unknown9[0] = 0xff;
lrbs->unknown9[1] = 0x03;
lrbs->unknown11[0] = 0x63;
lrbs->unknown12[0] = 0x01;
memcpy(lrbs->key, key.c_str(), key.size());
#ifdef WIN32
unsigned int e_size;
char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)login_failed_attempts, 75, e_size);
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
char *encrypted_buffer = server.eq_crypto->Encrypt((const char*)lrbs, 75, e_size);
memcpy(llas->encrypt, encrypted_buffer, 80);
server.eq_crypto->DeleteHeap(encrypted_buffer);
#else
unsigned int e_size;
char *encrypted_buffer = Encrypt((const char*)login_failed_attempts, 75, e_size);
memcpy(login_accepted->encrypt, encrypted_buffer, 80);
char *encrypted_buffer = Encrypt((const char*)lrbs, 75, e_size);
memcpy(llas->encrypt, encrypted_buffer, 80);
_HeapDeleteCharBuffer(encrypted_buffer);
#endif
if(server.options.IsDumpOutPacketsOn()) {
if(server.options.IsDumpOutPacketsOn())
{
DumpPacket(outapp);
}
connection->QueuePacket(outapp);
delete outapp;
}
else {
else
{
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, sizeof(LoginLoginFailed_Struct));
const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data;
LoginLoginFailed_Struct* llas = (LoginLoginFailed_Struct *)outapp->pBuffer;
@@ -323,7 +317,8 @@ void Client::Handle_Login(const char* data, unsigned int size)
llas->unknown5 = llrs->unknown5;
memcpy(llas->unknown6, FailedLoginResponseData, sizeof(FailedLoginResponseData));
if(server.options.IsDumpOutPacketsOn()) {
if(server.options.IsDumpOutPacketsOn())
{
DumpPacket(outapp);
}
@@ -336,7 +331,7 @@ void Client::Handle_Play(const char* data)
{
if(status != cs_logged_in)
{
Log.Out(Logs::General, Logs::Error, "Client sent a play request when they either were not logged in, discarding.");
server_log->Log(log_client_error, "Client sent a play request when they either were not logged in, discarding.");
return;
}
@@ -346,18 +341,18 @@ void Client::Handle_Play(const char* data)
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Login_Server, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in);
server_log->Log(log_network, "Play received from client, server number %u sequence %u.", server_id_in, sequence_in);
}
this->play_server_id = (unsigned int)play->ServerNumber;
play_sequence_id = sequence_in;
play_server_id = server_id_in;
server.server_manager->SendUserToWorldRequest(server_id_in, account_id);
server.SM->SendUserToWorldRequest(server_id_in, account_id);
}
void Client::SendServerListPacket()
{
EQApplicationPacket *outapp = server.server_manager->CreateServerListPacket(this);
EQApplicationPacket *outapp = server.SM->CreateServerListPacket(this);
if(server.options.IsDumpOutPacketsOn())
{
@@ -372,8 +367,8 @@ void Client::SendPlayResponse(EQApplicationPacket *outapp)
{
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Sending play response for %s.", GetAccountName().c_str());
// server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
server_log->Log(log_network_trace, "Sending play response for %s.", GetAccountName().c_str());
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
}
connection->QueuePacket(outapp);
status = cs_logged_in;
@@ -383,7 +378,7 @@ void Client::GenerateKey()
{
key.clear();
int count = 0;
while (count < 10)
while(count < 10)
{
static const char key_selection[] =
{
+14 -15
View File
@@ -16,14 +16,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "client_manager.h"
#include "error_log.h"
#include "login_server.h"
extern ErrorLog *server_log;
extern LoginServer server;
extern bool run_server;
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
ClientManager::ClientManager()
{
int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str());
@@ -31,18 +30,18 @@ ClientManager::ClientManager()
titanium_ops = new RegularOpcodeManager;
if(!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str()))
{
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
server.config->GetVariable("Titanium", "opcodes").c_str());
run_server = false;
}
if(titanium_stream->Open())
{
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on Titanium stream.");
server_log->Log(log_network, "ClientManager listening on Titanium stream.");
}
else
{
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open Titanium stream.");
server_log->Log(log_error, "ClientManager fatal error: couldn't open Titanium stream.");
run_server = false;
}
@@ -51,18 +50,18 @@ ClientManager::ClientManager()
sod_ops = new RegularOpcodeManager;
if(!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str()))
{
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
server_log->Log(log_error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
server.config->GetVariable("SoD", "opcodes").c_str());
run_server = false;
}
if(sod_stream->Open())
{
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on SoD stream.");
server_log->Log(log_network, "ClientManager listening on SoD stream.");
}
else
{
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open SoD stream.");
server_log->Log(log_error, "ClientManager fatal error: couldn't open SoD stream.");
run_server = false;
}
}
@@ -100,7 +99,7 @@ void ClientManager::Process()
{
struct in_addr in;
in.s_addr = cur->GetRemoteIP();
Log.Out(Logs::General, Logs::Login_Server, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
server_log->Log(log_network, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
cur->SetOpcodeManager(&titanium_ops);
Client *c = new Client(cur, cv_titanium);
@@ -113,7 +112,7 @@ void ClientManager::Process()
{
struct in_addr in;
in.s_addr = cur->GetRemoteIP();
Log.Out(Logs::General, Logs::Login_Server, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
server_log->Log(log_network, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
cur->SetOpcodeManager(&sod_ops);
Client *c = new Client(cur, cv_sod);
@@ -126,7 +125,7 @@ void ClientManager::Process()
{
if((*iter)->Process() == false)
{
Log.Out(Logs::General, Logs::Debug, "Client had a fatal error and had to be removed from the login.");
server_log->Log(log_client, "Client had a fatal error and had to be removed from the login.");
delete (*iter);
iter = clients.erase(iter);
}
@@ -145,7 +144,7 @@ void ClientManager::ProcessDisconnect()
std::shared_ptr<EQStream> c = (*iter)->GetConnection();
if(c->CheckClosed())
{
Log.Out(Logs::General, Logs::Login_Server, "Client disconnected from the server, removing client.");
server_log->Log(log_network, "Client disconnected from the server, removing client.");
delete (*iter);
iter = clients.erase(iter);
}
@@ -173,7 +172,7 @@ void ClientManager::RemoveExistingClient(unsigned int account_id)
{
if((*iter)->GetAccountID() == account_id)
{
Log.Out(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client.");
server_log->Log(log_network, "Client attempting to log in and existing client already logged in, removing existing client.");
delete (*iter);
iter = clients.erase(iter);
}
@@ -201,7 +200,7 @@ Client *ClientManager::GetClient(unsigned int account_id)
if(count > 1)
{
Log.Out(Logs::General, Logs::Error, "More than one client with a given account_id existed in the client list.");
server_log->Log(log_client_error, "More than one client with a given account_id existed in the client list.");
}
return cur;
}
+6 -6
View File
@@ -16,10 +16,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "config.h"
#include "error_log.h"
extern EQEmuLogSys Log;
extern ErrorLog *server_log;
/**
* Retrieves the variable we want from our title or theme
* First gets the map from the title
@@ -48,7 +48,7 @@ void Config::Parse(const char *file_name)
{
if(file_name == nullptr)
{
Log.Out(Logs::General, Logs::Error, "Config::Parse(), file_name passed was null.");
server_log->Log(log_error, "Config::Parse(), file_name passed was null.");
return;
}
@@ -71,7 +71,7 @@ void Config::Parse(const char *file_name)
++iter;
if(iter == tokens.end())
{
Log.Out(Logs::General, Logs::Error, "Config::Parse(), EOF before title done parsing.");
server_log->Log(log_error, "Config::Parse(), EOF before title done parsing.");
fclose(input);
vars.clear();
return;
@@ -104,7 +104,7 @@ void Config::Parse(const char *file_name)
mode++;
if((*iter).compare("=") != 0)
{
Log.Out(Logs::General, Logs::Error, "Config::Parse(), invalid parse token where = should be.");
server_log->Log(log_error, "Config::Parse(), invalid parse token where = should be.");
fclose(input);
vars.clear();
return;
@@ -133,7 +133,7 @@ void Config::Parse(const char *file_name)
}
else
{
Log.Out(Logs::General, Logs::Error, "Config::Parse(), file was unable to be opened for parsing.");
server_log->Log(log_error, "Config::Parse(), file was unable to be opened for parsing.");
}
}
-2
View File
@@ -44,8 +44,6 @@ public:
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id) { return false; }
virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id) { return false; }
/**
* Retrieves the world registration from the long and short names provided.
* Needed for world login procedure.
+61 -86
View File
@@ -20,12 +20,14 @@
#ifdef EQEMU_MYSQL_ENABLED
#include "database_mysql.h"
#include "error_log.h"
#include "login_server.h"
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern ErrorLog *server_log;
extern LoginServer server;
#pragma comment(lib, "mysqlclient.lib")
DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name)
{
this->user = user;
@@ -33,35 +35,35 @@ DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port,
this->host = host;
this->name = name;
database = mysql_init(nullptr);
if(database)
db = mysql_init(nullptr);
if(db)
{
my_bool r = 1;
mysql_options(database, MYSQL_OPT_RECONNECT, &r);
if(!mysql_real_connect(database, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0))
mysql_options(db, MYSQL_OPT_RECONNECT, &r);
if(!mysql_real_connect(db, host.c_str(), user.c_str(), pass.c_str(), name.c_str(), atoi(port.c_str()), nullptr, 0))
{
mysql_close(database);
Log.Out(Logs::General, Logs::Error, "Failed to connect to MySQL database. Error: %s", mysql_error(database));
mysql_close(db);
server_log->Log(log_database, "Failed to connect to MySQL database. Error: %s", mysql_error(db));
exit(1);
}
}
else
{
Log.Out(Logs::General, Logs::Error, "Failed to create db object in MySQL database.");
server_log->Log(log_database, "Failed to create db object in MySQL database.");
}
}
DatabaseMySQL::~DatabaseMySQL()
{
if(database)
if(db)
{
mysql_close(database);
mysql_close(db);
}
}
bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
{
if (!database)
if(!db)
{
return false;
}
@@ -73,17 +75,17 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
query << name;
query << "'";
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(database);
res = mysql_use_result(db);
if (res)
if(res)
{
while ((row = mysql_fetch_row(res)) != nullptr)
while((row = mysql_fetch_row(res)) != nullptr)
{
id = atoi(row[0]);
password = row[1];
@@ -92,41 +94,14 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
}
}
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id)
{
if (!database) {
return false;
}
MYSQL_RES *result;
MYSQL_ROW row;
stringstream query(stringstream::in | stringstream::out);
query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) ";
query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); ";
if (mysql_query(database, query.str().c_str()) != 0) {
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
return false;
}
else{
id = mysql_insert_id(database);
return true;
}
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id,
unsigned int &trusted, string &list_desc, string &account, string &password)
unsigned int &trusted, string &list_desc, string &account, string &password)
{
if (!database)
if(!db)
{
return false;
}
@@ -135,8 +110,8 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
MYSQL_ROW row;
char escaped_short_name[101];
unsigned long length;
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length + 1] = 0;
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length+1] = 0;
stringstream query(stringstream::in | stringstream::out);
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
@@ -145,16 +120,16 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
query << escaped_short_name;
query << "'";
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(database);
if (res)
res = mysql_use_result(db);
if(res)
{
if ((row = mysql_fetch_row(res)) != nullptr)
if((row = mysql_fetch_row(res)) != nullptr)
{
id = atoi(row[0]);
desc = row[1];
@@ -164,22 +139,22 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
int db_account_id = atoi(row[5]);
mysql_free_result(res);
if (db_account_id > 0)
if(db_account_id > 0)
{
stringstream query(stringstream::in | stringstream::out);
query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable();
query << " WHERE ServerAdminID = " << db_account_id;
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(database);
if (res)
res = mysql_use_result(db);
if(res)
{
if ((row = mysql_fetch_row(res)) != nullptr)
if((row = mysql_fetch_row(res)) != nullptr)
{
account = row[0];
password = row[1];
@@ -188,20 +163,20 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
}
}
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
return true;
}
}
Log.Out(Logs::General, Logs::Error, "Mysql query returned no result: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query returned no result: %s", query.str().c_str());
return false;
}
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
{
if (!database)
if(!db)
{
return;
}
@@ -212,15 +187,15 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
query << "', LastLoginDate = now() where LoginServerID = ";
query << id;
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
}
}
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email)
{
if (!database)
if(!db)
{
return;
}
@@ -231,23 +206,23 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas
query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email;
query << "', LastIPAddress = '0.0.0.0', LastLoginDate = now()";
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
}
}
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address)
{
if (!database)
if(!db)
{
return;
}
char escaped_long_name[101];
unsigned long length;
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length + 1] = 0;
length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length+1] = 0;
stringstream query(stringstream::in | stringstream::out);
query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '";
query << ip_address;
@@ -256,15 +231,15 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
query << "' WHERE ServerID = ";
query << id;
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
}
}
bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id)
{
if (!database)
if(!db)
{
return false;
}
@@ -274,23 +249,23 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
char escaped_long_name[201];
char escaped_short_name[101];
unsigned long length;
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length + 1] = 0;
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length + 1] = 0;
length = mysql_real_escape_string(db, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
escaped_long_name[length+1] = 0;
length = mysql_real_escape_string(db, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
escaped_short_name[length+1] = 0;
stringstream query(stringstream::in | stringstream::out);
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
return false;
}
res = mysql_use_result(database);
if (res)
res = mysql_use_result(db);
if(res)
{
if ((row = mysql_fetch_row(res)) != nullptr)
if((row = mysql_fetch_row(res)) != nullptr)
{
id = atoi(row[0]) + 1;
mysql_free_result(res);
@@ -300,15 +275,15 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name;
query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''";
if (mysql_query(database, query.str().c_str()) != 0)
if(mysql_query(db, query.str().c_str()) != 0)
{
Log.Out(Logs::General, Logs::Error, "Mysql query failed: %s", query.str().c_str());
server_log->Log(log_database, "Mysql query failed: %s", query.str().c_str());
return false;
}
return true;
}
}
Log.Out(Logs::General, Logs::Error, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str());
server_log->Log(log_database, "World registration did not exist in the database for %s %s", long_name.c_str(), short_name.c_str());
return false;
}
+3 -5
View File
@@ -35,7 +35,7 @@ public:
/**
* Constructor, sets our database to null.
*/
DatabaseMySQL() { database = nullptr; }
DatabaseMySQL() { db = nullptr; }
/**
* Constructor, tries to set our database to connect to the supplied options.
@@ -50,7 +50,7 @@ public:
/**
* @return Returns true if the database successfully connected.
*/
virtual bool IsConnected() { return (database != nullptr); }
virtual bool IsConnected() { return (db != nullptr); }
/**
* Retrieves the login data (password hash and account id) from the account name provided
@@ -59,8 +59,6 @@ public:
*/
virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id);
virtual bool CreateLoginData(std::string name, std::string &password, unsigned int &id);
/**
* Retrieves the world registration from the long and short names provided.
* Needed for world login procedure.
@@ -90,7 +88,7 @@ public:
virtual bool CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id);
protected:
std::string user, pass, host, port, name;
MYSQL *database;
MYSQL *db;
};
#endif
+7 -7
View File
@@ -23,7 +23,7 @@
#include "error_log.h"
#include "login_server.h"
extern ErrorLog *server_log;
extern LoginServer server;
#pragma comment(lib, "libpq.lib")
@@ -34,12 +34,12 @@ DatabasePostgreSQL::DatabasePostgreSQL(string user, string pass, string host, st
db = PQsetdbLogin(host.c_str(), port.c_str(), nullptr, nullptr, name.c_str(), user.c_str(), pass.c_str());
if(!db)
{
Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database.");
server_log->Log(log_database, "Failed to connect to PostgreSQL Database.");
}
if(PQstatus(db) != CONNECTION_OK)
{
Log.Out(Logs::General, Logs::Error, "Failed to connect to PostgreSQL Database.");
server_log->Log(log_database, "Failed to connect to PostgreSQL Database.");
PQfinish(db);
db = nullptr;
}
@@ -83,7 +83,7 @@ bool DatabasePostgreSQL::GetLoginDataFromAccountName(string name, string &passwo
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
PQclear(res);
return false;
}
@@ -135,7 +135,7 @@ bool DatabasePostgreSQL::GetWorldRegistration(string long_name, string short_nam
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error);
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetWorldRegistration(): %s", error);
PQclear(res);
return false;
}
@@ -188,7 +188,7 @@ void DatabasePostgreSQL::UpdateLSAccountData(unsigned int id, string ip_address)
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
}
PQclear(res);
}
@@ -225,7 +225,7 @@ void DatabasePostgreSQL::UpdateWorldRegistration(unsigned int id, string long_na
char *error = PQresultErrorMessage(res);
if(strlen(error) > 0)
{
Log.Out(Logs::General, Logs::Error, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
server_log->Log(log_database, "Database error in DatabasePostgreSQL::GetLoginDataFromAccountName(): %s", error);
}
PQclear(res);
}
+6 -6
View File
@@ -17,16 +17,16 @@
*/
#include "../common/global_define.h"
#include "encryption.h"
#include "error_log.h"
#include <string>
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern ErrorLog *server_log;
bool Encryption::LoadCrypto(std::string name)
{
if(!Load(name.c_str()))
{
Log.Out(Logs::General, Logs::Error, "Failed to load %s from the operating system.", name.c_str());
server_log->Log(log_error, "Failed to load %s from the operating system.", name.c_str());
return false;
}
else
@@ -34,21 +34,21 @@ bool Encryption::LoadCrypto(std::string name)
encrypt_func = (DLLFUNC_Encrypt)GetSym("Encrypt");
if(encrypt_func == NULL)
{
Log.Out(Logs::General, Logs::Error, "Failed to attach Encrypt.");
server_log->Log(log_error, "Failed to attach Encrypt.");
Unload();
return false;
}
decrypt_func = (DLLFUNC_DecryptUsernamePassword)GetSym("DecryptUsernamePassword");
if(decrypt_func == NULL)
{
Log.Out(Logs::General, Logs::Error, "Failed to attach DecryptUsernamePassword.");
server_log->Log(log_error, "Failed to attach DecryptUsernamePassword.");
Unload();
return false;
}
delete_func = (DLLFUNC_HeapDelete)GetSym("_HeapDeleteCharBuffer");
if(delete_func == NULL)
{
Log.Out(Logs::General, Logs::Error, "Failed to attach _HeapDeleteCharBuffer.");
server_log->Log(log_error, "Failed to attach _HeapDeleteCharBuffer.");
Unload();
return false;
}
+210
View File
@@ -0,0 +1,210 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2010 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 <string.h>
#include "error_log.h"
const char *eqLogTypes[_log_largest_type] =
{
"Debug",
"Error",
"Database",
"Network",
"Network Trace",
"Network Error",
"World",
"World Error",
"Client",
"Client Error"
};
ErrorLog::ErrorLog(const char* file_name)
{
log_mutex = new Mutex();
error_log = fopen(file_name, "w");
}
ErrorLog::~ErrorLog()
{
log_mutex->lock();
if(error_log)
{
fclose(error_log);
}
log_mutex->unlock();
delete log_mutex;
}
void ErrorLog::Log(eqLogType type, const char *message, ...)
{
if(type >= _log_largest_type)
{
return;
}
va_list argptr;
char *buffer = new char[4096];
va_start(argptr, message);
vsnprintf(buffer, 4096, message, argptr);
va_end(argptr);
time_t m_clock;
struct tm *m_time;
time(&m_clock);
m_time = localtime(&m_clock);
log_mutex->lock();
printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
buffer);
if(error_log)
{
fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] %s\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
buffer);
fflush(error_log);
}
log_mutex->unlock();
delete[] buffer;
}
void ErrorLog::LogPacket(eqLogType type, const char *data, size_t size)
{
if(type >= _log_largest_type)
{
return;
}
log_mutex->lock();
time_t m_clock;
struct tm *m_time;
time(&m_clock);
m_time = localtime(&m_clock);
log_mutex->lock();
printf("[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u:\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
(unsigned int)size);
if(error_log)
{
fprintf(error_log, "[%s] [%02d.%02d.%02d - %02d:%02d:%02d] dumping packet of size %u\n",
eqLogTypes[type],
m_time->tm_mon+1,
m_time->tm_mday,
m_time->tm_year%100,
m_time->tm_hour,
m_time->tm_min,
m_time->tm_sec,
(unsigned int)size);
}
char ascii[17]; //16 columns + 1 null term
memset(ascii, 0, 17);
size_t j = 0;
size_t i = 0;
for(; i < size; ++i)
{
if(i % 16 == 0)
{
if(i != 0)
{
printf(" | %s\n", ascii);
if(error_log)
{
fprintf(error_log, " | %s\n", ascii);
}
}
printf("%.4u: ", (unsigned int)i);
memset(ascii, 0, 17);
j = 0;
}
else if(i % 8 == 0)
{
printf("- ");
if(error_log)
{
fprintf(error_log, "- ");
}
}
printf("%02X ", (unsigned int)data[i]);
if(error_log)
{
fprintf(error_log, "%02X ", (unsigned int)data[i]);
}
if(data[i] >= 32 && data[i] < 127)
{
ascii[j++] = data[i];
}
else
{
ascii[j++] = '.';
}
}
size_t k = (i - 1) % 16;
if(k < 8)
{
printf(" ");
if(error_log)
{
fprintf(error_log, " ");
}
}
for(size_t h = k + 1; h < 16; ++h)
{
printf(" ");
if(error_log)
{
fprintf(error_log, " ");
}
}
printf(" | %s\n", ascii);
if(error_log)
{
fprintf(error_log, " | %s\n", ascii);
fflush(error_log);
}
log_mutex->unlock();
}
+79
View File
@@ -0,0 +1,79 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2010 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_ERROR_LOG_H
#define EQEMU_ERROR_LOG_H
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string>
#include "../common/mutex.h"
/**
* Dictates the log type specified in ErrorLog for Log(...)
*/
enum eqLogType
{
log_debug,
log_error,
log_database,
log_network,
log_network_trace,
log_network_error,
log_world,
log_world_error,
log_client,
log_client_error,
_log_largest_type
};
/**
* Basic error logging class.
* Thread safe logging class that records time and date to both a file and to console(if exists).
*/
class ErrorLog
{
public:
/**
* Constructor: opens the log file for writing and creates our mutex for writing to the log.
*/
ErrorLog(const char* file_name);
/**
* Closes the file and destroys the mutex.
*/
~ErrorLog();
/**
* Writes to the log system a variable message.
*/
void Log(eqLogType type, const char *message, ...);
/**
* Writes to the log system a packet.
*/
void LogPacket(eqLogType type, const char *data, size_t size);
protected:
Mutex *log_mutex;
FILE* error_log;
};
#endif
+4 -3
View File
@@ -18,6 +18,7 @@
#ifndef EQEMU_LOGINSERVER_H
#define EQEMU_LOGINSERVER_H
#include "error_log.h"
#include "config.h"
#include "database.h"
#include "database_mysql.h"
@@ -39,7 +40,7 @@ public:
* but it's the most trivial way to do this.
*/
#ifdef WIN32
LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), server_manager(nullptr) { }
LoginServer() : config(nullptr), db(nullptr), eq_crypto(nullptr), SM(nullptr) { }
#else
LoginServer() : config(nullptr), db(nullptr) { }
#endif
@@ -47,8 +48,8 @@ public:
Config *config;
Database *db;
Options options;
ServerManager *server_manager;
ClientManager *client_manager;
ServerManager *SM;
ClientManager *CM;
#ifdef WIN32
Encryption *eq_crypto;
+2 -2
View File
@@ -38,7 +38,7 @@ struct LoginLoginRequest_Struct {
char unknown6[16];
};
struct LoginAccepted_Struct {
struct LoginLoginAccepted_Struct {
short unknown1;
short unknown2;
short unknown3;
@@ -47,7 +47,7 @@ struct LoginAccepted_Struct {
char encrypt[80];
};
struct LoginFailedAttempts_Struct
struct Login_ReplyBlock_Struct
{
char message; //0x01
char unknown2[7]; //0x00
+133 -79
View File
@@ -32,6 +32,7 @@
TimeoutManager timeout_manager;
LoginServer server;
EQEmuLogSys Log;
ErrorLog *server_log;
bool run_server = true;
void CatchSignal(int sig_num)
@@ -42,63 +43,106 @@ int main()
{
RegisterExecutablePlatform(ExePlatformLogin);
set_exception_handler();
Log.LoadLogSettingsDefaults();
Log.log_settings[Logs::Error].log_to_console = Logs::General;
//Create our error log, is of format login_<number>.log
time_t current_time = time(nullptr);
std::stringstream log_name(std::stringstream::in | std::stringstream::out);
#ifdef WIN32
log_name << ".\\logs\\login_" << (unsigned int)current_time << ".log";
#else
log_name << "./logs/login_" << (unsigned int)current_time << ".log";
#endif
server_log = new ErrorLog(log_name.str().c_str());
server_log->Log(log_debug, "Logging System Init.");
Log.Out(Logs::General, Logs::Login_Server, "Logging System Init.");
/* Parse out login.ini */
//Create our subsystem and parse the ini file.
server.config = new Config();
Log.Out(Logs::General, Logs::Login_Server, "Config System Init.");
server_log->Log(log_debug, "Config System Init.");
server.config->Parse("login.ini");
if (server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0)
//Parse unregistered allowed option.
if(server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0)
{
server.options.AllowUnregistered(false);
}
if (server.config->GetVariable("options", "trace").compare("TRUE") == 0)
//Parse trace option.
if(server.config->GetVariable("options", "trace").compare("TRUE") == 0)
{
server.options.Trace(true);
}
if (server.config->GetVariable("options", "world_trace").compare("TRUE") == 0)
//Parse trace option.
if(server.config->GetVariable("options", "world_trace").compare("TRUE") == 0)
{
server.options.WorldTrace(true);
}
if (server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0)
//Parse packet inc dump option.
if(server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0)
{
server.options.DumpInPackets(true);
}
if (server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0)
//Parse packet out dump option.
if(server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0)
{
server.options.DumpOutPackets(true);
}
//Parse encryption mode option.
std::string mode = server.config->GetVariable("security", "mode");
if (mode.size() > 0)
if(mode.size() > 0)
{
server.options.EncryptionMode(atoi(mode.c_str()));
}
std::string local_network = server.config->GetVariable("options", "local_network");
if (local_network.size() > 0)
server.options.LocalNetwork(local_network);
//Parse local network option.
std::string ln = server.config->GetVariable("options", "local_network");
if(ln.size() > 0)
{
server.options.LocalNetwork(ln);
}
if (server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0)
//Parse reject duplicate servers option.
if(server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0)
{
server.options.RejectDuplicateServers(true);
}
local_network = server.config->GetVariable("schema", "account_table");
if (local_network.size() > 0)
server.options.AccountTable(local_network);
//Parse account table option.
ln = server.config->GetVariable("schema", "account_table");
if(ln.size() > 0)
{
server.options.AccountTable(ln);
}
local_network = server.config->GetVariable("schema", "world_registration_table");
if (local_network.size() > 0)
server.options.WorldRegistrationTable(local_network);
//Parse world account table option.
ln = server.config->GetVariable("schema", "world_registration_table");
if(ln.size() > 0)
{
server.options.WorldRegistrationTable(ln);
}
local_network = server.config->GetVariable("schema", "world_admin_registration_table");
if (local_network.size() > 0)
server.options.WorldAdminRegistrationTable(local_network);
//Parse admin world account table option.
ln = server.config->GetVariable("schema", "world_admin_registration_table");
if(ln.size() > 0)
{
server.options.WorldAdminRegistrationTable(ln);
}
local_network = server.config->GetVariable("schema", "world_server_type_table");
if (local_network.size() > 0)
server.options.WorldServerTypeTable(local_network);
//Parse world type table option.
ln = server.config->GetVariable("schema", "world_server_type_table");
if(ln.size() > 0)
{
server.options.WorldServerTypeTable(ln);
}
/* Create database connection */
if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) {
//Create our DB from options.
if(server.config->GetVariable("database", "subsystem").compare("MySQL") == 0)
{
#ifdef EQEMU_MYSQL_ENABLED
Log.Out(Logs::General, Logs::Login_Server, "MySQL Database Init.");
server_log->Log(log_debug, "MySQL Database Init.");
server.db = (Database*)new DatabaseMySQL(
server.config->GetVariable("database", "user"),
server.config->GetVariable("database", "password"),
@@ -107,9 +151,10 @@ int main()
server.config->GetVariable("database", "db"));
#endif
}
else if (server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0) {
else if(server.config->GetVariable("database", "subsystem").compare("PostgreSQL") == 0)
{
#ifdef EQEMU_POSTGRESQL_ENABLED
Log.Out(Logs::General, Logs::Login_Server, "PostgreSQL Database Init.");
server_log->Log(log_debug, "PostgreSQL Database Init.");
server.db = (Database*)new DatabasePostgreSQL(
server.config->GetVariable("database", "user"),
server.config->GetVariable("database", "password"),
@@ -119,70 +164,78 @@ int main()
#endif
}
/* Make sure our database got created okay, otherwise cleanup and exit. */
if (!server.db) {
Log.Out(Logs::General, Logs::Error, "Database Initialization Failure.");
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
//Make sure our database got created okay, otherwise cleanup and exit.
if(!server.db)
{
server_log->Log(log_error, "Database Initialization Failure.");
server_log->Log(log_debug, "Config System Shutdown.");
delete server.config;
Log.Out(Logs::General, Logs::Login_Server, "Log System Shutdown.");
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
#if WIN32
//initialize our encryption.
Log.Out(Logs::General, Logs::Login_Server, "Encryption Initialize.");
server_log->Log(log_debug, "Encryption Initialize.");
server.eq_crypto = new Encryption();
if (server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin"))) {
Log.Out(Logs::General, Logs::Login_Server, "Encryption Loaded Successfully.");
if(server.eq_crypto->LoadCrypto(server.config->GetVariable("security", "plugin")))
{
server_log->Log(log_debug, "Encryption Loaded Successfully.");
}
else {
else
{
//We can't run without encryption, cleanup and exit.
Log.Out(Logs::General, Logs::Error, "Encryption Failed to Load.");
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
server_log->Log(log_error, "Encryption Failed to Load.");
server_log->Log(log_debug, "Database System Shutdown.");
delete server.db;
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
server_log->Log(log_debug, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
#endif
//create our server manager.
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Initialize.");
server.server_manager = new ServerManager();
if (!server.server_manager) {
server_log->Log(log_debug, "Server Manager Initialize.");
server.SM = new ServerManager();
if(!server.SM)
{
//We can't run without a server manager, cleanup and exit.
Log.Out(Logs::General, Logs::Error, "Server Manager Failed to Start.");
server_log->Log(log_error, "Server Manager Failed to Start.");
#ifdef WIN32
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
server_log->Log(log_debug, "Encryption System Shutdown.");
delete server.eq_crypto;
#endif
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
server_log->Log(log_debug, "Database System Shutdown.");
delete server.db;
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
server_log->Log(log_debug, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
//create our client manager.
Log.Out(Logs::General, Logs::Login_Server, "Client Manager Initialize.");
server.client_manager = new ClientManager();
if (!server.client_manager) {
server_log->Log(log_debug, "Client Manager Initialize.");
server.CM = new ClientManager();
if(!server.CM)
{
//We can't run without a client manager, cleanup and exit.
Log.Out(Logs::General, Logs::Error, "Client Manager Failed to Start.");
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown.");
delete server.server_manager;
server_log->Log(log_error, "Client Manager Failed to Start.");
server_log->Log(log_debug, "Server Manager Shutdown.");
delete server.SM;
#ifdef WIN32
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
server_log->Log(log_debug, "Encryption System Shutdown.");
delete server.eq_crypto;
#endif
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
server_log->Log(log_debug, "Database System Shutdown.");
delete server.db;
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
server_log->Log(log_debug, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 1;
}
@@ -194,29 +247,30 @@ int main()
#endif
#endif
Log.Out(Logs::General, Logs::Login_Server, "Server Started.");
while (run_server) {
server_log->Log(log_debug, "Server Started.");
while(run_server)
{
Timer::SetCurrentTime();
server.client_manager->Process();
server.server_manager->Process();
server.CM->Process();
server.SM->Process();
Sleep(100);
}
Log.Out(Logs::General, Logs::Login_Server, "Server Shutdown.");
Log.Out(Logs::General, Logs::Login_Server, "Client Manager Shutdown.");
delete server.client_manager;
Log.Out(Logs::General, Logs::Login_Server, "Server Manager Shutdown.");
delete server.server_manager;
server_log->Log(log_debug, "Server Shutdown.");
server_log->Log(log_debug, "Client Manager Shutdown.");
delete server.CM;
server_log->Log(log_debug, "Server Manager Shutdown.");
delete server.SM;
#ifdef WIN32
Log.Out(Logs::General, Logs::Login_Server, "Encryption System Shutdown.");
server_log->Log(log_debug, "Encryption System Shutdown.");
delete server.eq_crypto;
#endif
Log.Out(Logs::General, Logs::Login_Server, "Database System Shutdown.");
server_log->Log(log_debug, "Database System Shutdown.");
delete server.db;
Log.Out(Logs::General, Logs::Login_Server, "Config System Shutdown.");
server_log->Log(log_debug, "Config System Shutdown.");
delete server.config;
server_log->Log(log_debug, "Log System Shutdown.");
delete server_log;
return 0;
}
+138 -97
View File
@@ -17,12 +17,11 @@
*/
#include "server_manager.h"
#include "login_server.h"
#include "error_log.h"
#include "login_structures.h"
#include <stdlib.h>
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern ErrorLog *server_log;
extern LoginServer server;
extern bool run_server;
@@ -32,18 +31,21 @@ ServerManager::ServerManager()
int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str());
tcps = new EmuTCPServer(listen_port, true);
if(tcps->Open(listen_port, error_buffer)) {
Log.Out(Logs::General, Logs::Login_Server, "ServerManager listening on port %u", listen_port);
if(tcps->Open(listen_port, error_buffer))
{
server_log->Log(log_network, "ServerManager listening on port %u", listen_port);
}
else {
Log.Out(Logs::General, Logs::Error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer);
else
{
server_log->Log(log_error, "ServerManager fatal error opening port on %u: %s", listen_port, error_buffer);
run_server = false;
}
}
ServerManager::~ServerManager()
{
if (tcps) {
if(tcps)
{
tcps->Close();
delete tcps;
}
@@ -53,32 +55,38 @@ void ServerManager::Process()
{
ProcessDisconnect();
EmuTCPConnection *tcp_c = nullptr;
while (tcp_c = tcps->NewQueuePop()) {
while(tcp_c = tcps->NewQueuePop())
{
in_addr tmp;
tmp.s_addr = tcp_c->GetrIP();
Log.Out(Logs::General, Logs::Login_Server, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort());
server_log->Log(log_network, "New world server connection from %s:%d", inet_ntoa(tmp), tcp_c->GetrPort());
WorldServer *server_entity = GetServerByAddress(tcp_c->GetrIP());
if (server_entity) {
Log.Out(Logs::General, Logs::Login_Server, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp));
server_entity->GetConnection()->Free();
server_entity->SetConnection(tcp_c);
server_entity->Reset();
WorldServer *cur = GetServerByAddress(tcp_c->GetrIP());
if(cur)
{
server_log->Log(log_network, "World server already existed for %s, removing existing connection and updating current.", inet_ntoa(tmp));
cur->GetConnection()->Free();
cur->SetConnection(tcp_c);
cur->Reset();
}
else {
else
{
WorldServer *w = new WorldServer(tcp_c);
world_servers.push_back(w);
}
}
list<WorldServer*>::iterator iter = world_servers.begin();
while (iter != world_servers.end()) {
if ((*iter)->Process() == false) {
Log.Out(Logs::General, Logs::World_Server, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
while(iter != world_servers.end())
{
if((*iter)->Process() == false)
{
server_log->Log(log_world, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
delete (*iter);
iter = world_servers.erase(iter);
}
else {
else
{
++iter;
}
}
@@ -87,17 +95,20 @@ void ServerManager::Process()
void ServerManager::ProcessDisconnect()
{
list<WorldServer*>::iterator iter = world_servers.begin();
while (iter != world_servers.end()) {
EmuTCPConnection *connection = (*iter)->GetConnection();
if (!connection->Connected()) {
while(iter != world_servers.end())
{
EmuTCPConnection *c = (*iter)->GetConnection();
if(!c->Connected())
{
in_addr tmp;
tmp.s_addr = connection->GetrIP();
Log.Out(Logs::General, Logs::Login_Server, "World server disconnected from the server, removing server and freeing connection.");
connection->Free();
tmp.s_addr = c->GetrIP();
server_log->Log(log_network, "World server disconnected from the server, removing server and freeing connection.");
c->Free();
delete (*iter);
iter = world_servers.erase(iter);
}
else {
else
{
++iter;
}
}
@@ -106,8 +117,10 @@ void ServerManager::ProcessDisconnect()
WorldServer* ServerManager::GetServerByAddress(unsigned int address)
{
list<WorldServer*>::iterator iter = world_servers.begin();
while (iter != world_servers.end()) {
if ((*iter)->GetConnection()->GetrIP() == address) {
while(iter != world_servers.end())
{
if((*iter)->GetConnection()->GetrIP() == address)
{
return (*iter);
}
++iter;
@@ -125,8 +138,10 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
string client_ip = inet_ntoa(in);
list<WorldServer*>::iterator iter = world_servers.begin();
while (iter != world_servers.end()) {
if ((*iter)->IsAuthorized() == false) {
while(iter != world_servers.end())
{
if((*iter)->IsAuthorized() == false)
{
++iter;
continue;
}
@@ -134,13 +149,16 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
in.s_addr = (*iter)->GetConnection()->GetrIP();
string world_ip = inet_ntoa(in);
if (world_ip.compare(client_ip) == 0) {
if(world_ip.compare(client_ip) == 0)
{
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
}
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos)
{
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
}
else {
else
{
packet_size += (*iter)->GetLongName().size() + (*iter)->GetRemoteIP().size() + 24;
}
@@ -149,87 +167,98 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
}
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ServerListResponse, packet_size);
ServerListHeader_Struct *server_list = (ServerListHeader_Struct*)outapp->pBuffer;
server_list->Unknown1 = 0x00000004;
server_list->Unknown2 = 0x00000000;
server_list->Unknown3 = 0x01650000;
ServerListHeader_Struct *sl = (ServerListHeader_Struct*)outapp->pBuffer;
sl->Unknown1 = 0x00000004;
sl->Unknown2 = 0x00000000;
sl->Unknown3 = 0x01650000;
/**
* Not sure what this is but it should be noted setting it to
* 0xFFFFFFFF crashes the client so: don't do that.
* Not sure what this is but it should be noted setting it to
* 0xFFFFFFFF crashes the client so: don't do that.
*/
server_list->Unknown4 = 0x00000000;
server_list->NumberOfServers = server_count;
sl->Unknown4 = 0x00000000;
sl->NumberOfServers = server_count;
unsigned char *data_pointer = outapp->pBuffer;
data_pointer += sizeof(ServerListHeader_Struct);
unsigned char *data_ptr = outapp->pBuffer;
data_ptr += sizeof(ServerListHeader_Struct);
iter = world_servers.begin();
while (iter != world_servers.end()) {
if ((*iter)->IsAuthorized() == false) {
while(iter != world_servers.end())
{
if((*iter)->IsAuthorized() == false)
{
++iter;
continue;
}
in.s_addr = (*iter)->GetConnection()->GetrIP();
string world_ip = inet_ntoa(in);
if (world_ip.compare(client_ip) == 0) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1);
if(world_ip.compare(client_ip) == 0)
{
memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_ptr += ((*iter)->GetLocalIP().size() + 1);
}
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1);
else if(client_ip.find(server.options.GetLocalNetwork()) != string::npos)
{
memcpy(data_ptr, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_ptr += ((*iter)->GetLocalIP().size() + 1);
}
else {
memcpy(data_pointer, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
data_pointer += ((*iter)->GetRemoteIP().size() + 1);
else
{
memcpy(data_ptr, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
data_ptr += ((*iter)->GetRemoteIP().size() + 1);
}
switch ((*iter)->GetServerListID()) {
case 1: {
*(unsigned int*)data_pointer = 0x00000030;
switch((*iter)->GetServerListID())
{
case 1:
{
*(unsigned int*)data_ptr = 0x00000030;
break;
}
case 2: {
*(unsigned int*)data_pointer = 0x00000009;
case 2:
{
*(unsigned int*)data_ptr = 0x00000009;
break;
}
default: {
*(unsigned int*)data_pointer = 0x00000001;
default:
{
*(unsigned int*)data_ptr = 0x00000001;
}
}
data_ptr += 4;
data_pointer += 4;
*(unsigned int*)data_ptr = (*iter)->GetRuntimeID();
data_ptr += 4;
*(unsigned int*)data_pointer = (*iter)->GetRuntimeID();
data_pointer += 4;
memcpy(data_ptr, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size());
data_ptr += ((*iter)->GetLongName().size() + 1);
memcpy(data_pointer, (*iter)->GetLongName().c_str(), (*iter)->GetLongName().size());
data_pointer += ((*iter)->GetLongName().size() + 1);
memcpy(data_ptr, "EN", 2);
data_ptr += 3;
memcpy(data_pointer, "EN", 2);
data_pointer += 3;
memcpy(data_pointer, "US", 2);
data_pointer += 3;
memcpy(data_ptr, "US", 2);
data_ptr += 3;
// 0 = Up, 1 = Down, 2 = Up, 3 = down, 4 = locked, 5 = locked(down)
if ((*iter)->GetStatus() < 0) {
if ((*iter)->GetZonesBooted() == 0) {
*(uint32*)data_pointer = 0x01;
if((*iter)->GetStatus() < 0)
{
if((*iter)->GetZonesBooted() == 0)
{
*(uint32*)data_ptr = 0x01;
}
else {
*(uint32*)data_pointer = 0x04;
else
{
*(uint32*)data_ptr = 0x04;
}
}
else {
*(uint32*)data_pointer = 0x02;
else
{
*(uint32*)data_ptr = 0x02;
}
data_pointer += 4;
data_ptr += 4;
*(uint32*)data_pointer = (*iter)->GetPlayersOnline();
data_pointer += 4;
*(uint32*)data_ptr = (*iter)->GetPlayersOnline();
data_ptr += 4;
++iter;
}
@@ -241,8 +270,10 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
{
list<WorldServer*>::iterator iter = world_servers.begin();
bool found = false;
while (iter != world_servers.end()) {
if ((*iter)->GetRuntimeID() == server_id) {
while(iter != world_servers.end())
{
if((*iter)->GetRuntimeID() == server_id)
{
ServerPacket *outapp = new ServerPacket(ServerOP_UsertoWorldReq, sizeof(UsertoWorldRequest_Struct));
UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp->pBuffer;
utwr->worldid = server_id;
@@ -250,7 +281,8 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
(*iter)->GetConnection()->SendPacket(outapp);
found = true;
if (server.options.IsDumpInPacketsOn()) {
if(server.options.IsDumpInPacketsOn())
{
DumpPacket(outapp);
}
delete outapp;
@@ -258,21 +290,25 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
++iter;
}
if (!found && server.options.IsTraceOn()) {
Log.Out(Logs::General, Logs::Error, "Client requested a user to world but supplied an invalid id of %u.", server_id);
if(!found && server.options.IsTraceOn())
{
server_log->Log(log_client_error, "Client requested a user to world but supplied an invalid id of %u.", server_id);
}
}
bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore)
{
list<WorldServer*>::iterator iter = world_servers.begin();
while (iter != world_servers.end()) {
if ((*iter) == ignore) {
while(iter != world_servers.end())
{
if((*iter) == ignore)
{
++iter;
continue;
}
if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) {
if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0)
{
return true;
}
@@ -284,14 +320,18 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno
void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore)
{
list<WorldServer*>::iterator iter = world_servers.begin();
while (iter != world_servers.end()) {
if ((*iter) == ignore) {
while(iter != world_servers.end())
{
if((*iter) == ignore)
{
++iter;
}
if ((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0) {
if((*iter)->GetLongName().compare(l_name) == 0 && (*iter)->GetShortName().compare(s_name) == 0)
{
EmuTCPConnection *c = (*iter)->GetConnection();
if (c->Connected()) {
if(c->Connected())
{
c->Disconnect();
}
c->Free();
@@ -301,4 +341,5 @@ void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServe
++iter;
}
}
}
+129 -128
View File
@@ -16,13 +16,11 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "world_server.h"
#include "error_log.h"
#include "login_server.h"
#include "login_structures.h"
#include "config.h"
#include "../common/eqemu_logsys.h"
extern EQEmuLogSys Log;
extern ErrorLog *server_log;
extern LoginServer server;
WorldServer::WorldServer(EmuTCPConnection *c)
@@ -30,18 +28,19 @@ WorldServer::WorldServer(EmuTCPConnection *c)
connection = c;
zones_booted = 0;
players_online = 0;
server_status = 0;
status = 0;
runtime_id = 0;
server_list_id = 0;
server_type = 0;
is_server_authorized = false;
is_server_trusted = false;
is_server_logged_in = false;
authorized = false;
trusted = false;
logged_in = false;
}
WorldServer::~WorldServer()
{
if(connection) {
if(connection)
{
connection->Free();
}
}
@@ -50,12 +49,12 @@ void WorldServer::Reset()
{
zones_booted = 0;
players_online = 0;
server_status = 0;
status = 0;
runtime_id;
server_list_id = 0;
server_type = 0;
is_server_authorized = false;
is_server_logged_in = false;
authorized = false;
logged_in = false;
}
bool WorldServer::Process()
@@ -65,7 +64,7 @@ bool WorldServer::Process()
{
if(server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);
server_log->Log(log_network_trace, "Application packet received from server: 0x%.4X, (size %u)", app->opcode, app->size);
}
if(server.options.IsDumpInPacketsOn())
@@ -79,14 +78,14 @@ bool WorldServer::Process()
{
if(app->size < sizeof(ServerNewLSInfo_Struct))
{
Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
server_log->Log(log_network_error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved.");
server_log->Log(log_network_trace, "New Login Info Recieved.");
}
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)app->pBuffer;
@@ -97,14 +96,14 @@ bool WorldServer::Process()
{
if(app->size < sizeof(ServerLSStatus_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
server_log->Log(log_network_trace, "World Server Status Recieved.");
}
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)app->pBuffer;
@@ -128,7 +127,7 @@ bool WorldServer::Process()
{
if(app->size < sizeof(UsertoWorldResponse_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
@@ -138,22 +137,21 @@ bool WorldServer::Process()
//While keeping world server spam with multiple servers connected almost impossible.
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
server_log->Log(log_network_trace, "User-To-World Response received.");
}
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)app->pBuffer;
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
server_log->Log(log_client, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.CM->GetClient(utwr->lsaccountid);
if(c)
{
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
server_log->Log(log_client, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
server_log->Log(log_client, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
if(utwr->response > 0)
{
@@ -182,9 +180,9 @@ bool WorldServer::Process()
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
server_log->Log(log_network_trace, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
server_log->LogPacket(log_network_trace, (const char*)outapp->pBuffer, outapp->size);
}
if(server.options.IsDumpOutPacketsOn())
@@ -197,7 +195,7 @@ bool WorldServer::Process()
}
else
{
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
server_log->Log(log_client_error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
break;
}
@@ -205,16 +203,16 @@ bool WorldServer::Process()
{
if(app->size < sizeof(ServerLSAccountUpdate_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
server_log->Log(log_network_error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)app->pBuffer;
if(is_server_trusted)
if(trusted)
{
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
string name;
string password;
string email;
@@ -227,7 +225,7 @@ bool WorldServer::Process()
}
default:
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
server_log->Log(log_network_error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", app->opcode);
}
}
@@ -239,9 +237,9 @@ bool WorldServer::Process()
void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(is_server_logged_in)
if(logged_in)
{
Log.Out(Logs::General, Logs::Error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
server_log->Log(log_network_error, "WorldServer::Handle_NewLSInfo called but the login server was already marked as logged in, aborting.");
return;
}
@@ -251,7 +249,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account name was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, account name was too long.");
return;
}
@@ -261,7 +259,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, account password was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, account password was too long.");
return;
}
@@ -271,7 +269,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, long name was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, long name was too long.");
return;
}
@@ -281,7 +279,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, short name was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, short name was too long.");
return;
}
@@ -289,7 +287,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(strlen(i->local_address) == 0)
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was null, defaulting to localhost");
server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was null, defaulting to localhost");
local_ip = "127.0.0.1";
}
else
@@ -299,7 +297,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, local address was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, local address was too long.");
return;
}
@@ -310,7 +308,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
in_addr in;
in.s_addr = GetConnection()->GetrIP();
remote_ip = inet_ntoa(in);
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
}
else
{
@@ -322,7 +320,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
in_addr in;
in.s_addr = GetConnection()->GetrIP();
remote_ip = inet_ntoa(in);
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
server_log->Log(log_network_error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
}
if(strlen(i->serverversion) <= 64)
@@ -331,7 +329,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, server version was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, server version was too long.");
return;
}
@@ -341,27 +339,27 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, protocol version was too long.");
server_log->Log(log_network_error, "Handle_NewLSInfo error, protocol version was too long.");
return;
}
server_type = i->servertype;
is_server_logged_in = true;
logged_in = true;
if(server.options.IsRejectingDuplicateServers())
{
if(server.server_manager->ServerExists(long_name, short_name, this))
if(server.SM->ServerExists(long_name, short_name, this))
{
Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name.");
server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name.");
return;
}
}
else
{
if(server.server_manager->ServerExists(long_name, short_name, this))
if(server.SM->ServerExists(long_name, short_name, this))
{
Log.Out(Logs::General, Logs::Error, "World tried to login but there already exists a server that has that name.");
server.server_manager->DestroyServerByName(long_name, short_name, this);
server_log->Log(log_world_error, "World tried to login but there already exists a server that has that name.");
server.SM->DestroyServerByName(long_name, short_name, this);
}
}
@@ -380,112 +378,112 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
{
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged into account that had no user/password requirement.",
server_log->Log(log_world, "Server %s(%s) successfully logged into account that had no user/password requirement.",
long_name.c_str(), short_name.c_str());
is_server_authorized = true;
authorized = true;
SetRuntimeID(s_id);
server_list_id = s_list_type;
desc = s_desc;
}
else if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0)
{
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.",
server_log->Log(log_world, "Server %s(%s) successfully logged in.",
long_name.c_str(), short_name.c_str());
is_server_authorized = true;
authorized = true;
SetRuntimeID(s_id);
server_list_id = s_list_type;
desc = s_desc;
if(s_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true;
if(s_trusted)
{
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world");
trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp);
}
}
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only"
else
{
server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database, and only"
" registered servers are allowed.", long_name.c_str(), short_name.c_str());
return;
}
}
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.",
else
{
server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry and only registered servers are allowed.",
long_name.c_str(), short_name.c_str());
return;
}
}
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but only registered servers are allowed.",
else
{
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but only registered servers are allowed.",
long_name.c_str(), short_name.c_str());
return;
}
}
else {
unsigned int server_id = 0;
unsigned int server_list_type = 0;
unsigned int is_server_trusted = 0;
string server_description;
string server_list_description;
string server_account_name;
string server_account_password;
if(server.db->GetWorldRegistration(
long_name,
short_name,
server_id,
server_description,
server_list_type,
is_server_trusted,
server_list_description,
server_account_name,
server_account_password))
else
{
unsigned int s_id = 0;
unsigned int s_list_type = 0;
unsigned int s_trusted = 0;
string s_desc;
string s_list_desc;
string s_acct_name;
string s_acct_pass;
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
{
if(account_name.size() > 0 && account_password.size() > 0) {
if(server_account_name.compare(account_name) == 0 && server_account_password.compare(account_password) == 0) {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) successfully logged in.",
if(account_name.size() > 0 && account_password.size() > 0)
{
if(s_acct_name.compare(account_name) == 0 && s_acct_pass.compare(account_password) == 0)
{
server_log->Log(log_world, "Server %s(%s) successfully logged in.",
long_name.c_str(), short_name.c_str());
is_server_authorized = true;
SetRuntimeID(server_id);
server_list_id = server_list_type;
desc = server_description;
if(is_server_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true;
authorized = true;
SetRuntimeID(s_id);
server_list_id = s_list_type;
desc = s_desc;
if(s_trusted)
{
server_log->Log(log_network_trace, "ServerOP_LSAccountUpdate sent to world");
trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp);
}
}
else {
else
{
// this is the first of two cases where we should deny access even if unregistered is allowed
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.",
server_log->Log(log_world, "Server %s(%s) attempted to log in but account and password did not match the entry in the database.",
long_name.c_str(), short_name.c_str());
}
}
else {
if(server_account_name.size() > 0 || server_account_password.size() > 0) {
else
{
if(s_acct_name.size() > 0 || s_acct_pass.size() > 0)
{
// this is the second of two cases where we should deny access even if unregistered is allowed
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but this server requires a password.",
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but this server requires a password.",
long_name.c_str(), short_name.c_str());
}
else {
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.",
else
{
server_log->Log(log_world, "Server %s(%s) did not attempt to log in but unregistered servers are allowed.",
long_name.c_str(), short_name.c_str());
is_server_authorized = true;
SetRuntimeID(server_id);
authorized = true;
SetRuntimeID(s_id);
server_list_id = 3;
}
}
}
else
{
Log.Out(Logs::General, Logs::World_Server, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.",
server_log->Log(log_world, "Server %s(%s) attempted to log in but database couldn't find an entry but unregistered servers are allowed.",
long_name.c_str(), short_name.c_str());
if(server.db->CreateWorldRegistration(long_name, short_name, server_id)) {
is_server_authorized = true;
SetRuntimeID(server_id);
if(server.db->CreateWorldRegistration(long_name, short_name, s_id))
{
authorized = true;
SetRuntimeID(s_id);
server_list_id = 3;
}
}
@@ -495,9 +493,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
in.s_addr = connection->GetrIP();
server.db->UpdateWorldRegistration(GetRuntimeID(), long_name, string(inet_ntoa(in)));
if(is_server_authorized)
if(authorized)
{
server.client_manager->UpdateServerList();
server.CM->UpdateServerList();
}
}
@@ -505,40 +503,43 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
{
players_online = s->num_players;
zones_booted = s->num_zones;
server_status = s->status;
status = s->status;
}
void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id)
{
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct));
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer;
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ServerLSClientAuth));
ServerLSClientAuth* slsca = (ServerLSClientAuth*)outapp->pBuffer;
client_auth->lsaccount_id = account_id;
strncpy(client_auth->name, account.c_str(), account.size() > 30 ? 30 : account.size());
strncpy(client_auth->key, key.c_str(), 10);
client_auth->lsadmin = 0;
client_auth->worldadmin = 0;
client_auth->ip = ip;
slsca->lsaccount_id = account_id;
strncpy(slsca->name, account.c_str(), account.size() > 30 ? 30 : account.size());
strncpy(slsca->key, key.c_str(), 10);
slsca->lsadmin = 0;
slsca->worldadmin = 0;
slsca->ip = ip;
in_addr in;
in.s_addr = ip; connection->GetrIP();
in.s_addr = ip;connection->GetrIP();
string client_address(inet_ntoa(in));
in.s_addr = connection->GetrIP();
string world_address(inet_ntoa(in));
if (client_address.compare(world_address) == 0) {
client_auth->local = 1;
if(client_address.compare(world_address) == 0)
{
slsca->local = 1;
}
else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) {
client_auth->local = 1;
else if(client_address.find(server.options.GetLocalNetwork()) != string::npos)
{
slsca->local = 1;
}
else {
client_auth->local = 0;
else
{
slsca->local = 0;
}
connection->SendPacket(outapp);
if (server.options.IsDumpInPacketsOn())
if(server.options.IsDumpInPacketsOn())
{
DumpPacket(outapp);
}
+6 -6
View File
@@ -86,7 +86,7 @@ public:
/**
* Gets whether the server is authorized to show up on the server list or not.
*/
bool IsAuthorized() const { return is_server_authorized; }
bool IsAuthorized() const { return authorized; }
/**
* Gets the local ip of the server.
@@ -106,7 +106,7 @@ public:
/**
* Gets the status of the server.
*/
int GetStatus() const { return server_status; }
int GetStatus() const { return status; }
/**
* Gets the number of zones online on the server.
@@ -138,7 +138,7 @@ private:
EmuTCPConnection *connection;
unsigned int zones_booted;
unsigned int players_online;
int server_status;
int status;
unsigned int runtime_id;
unsigned int server_list_id;
unsigned int server_type;
@@ -151,9 +151,9 @@ private:
std::string local_ip;
std::string protocol;
std::string version;
bool is_server_authorized;
bool is_server_logged_in;
bool is_server_trusted;
bool authorized;
bool logged_in;
bool trusted;
};
#endif
-223
View File
@@ -123,229 +123,6 @@ void Database::AddSpeech(const char* from, const char* to, const char* message,
}
void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 detailCount) {
std::string query = StringFormat("INSERT INTO `qs_player_trade_record` SET `time` = NOW(), "
"`char1_id` = '%i', `char1_pp` = '%i', `char1_gp` = '%i', "
"`char1_sp` = '%i', `char1_cp` = '%i', `char1_items` = '%i', "
"`char2_id` = '%i', `char2_pp` = '%i', `char2_gp` = '%i', "
"`char2_sp` = '%i', `char2_cp` = '%i', `char2_items` = '%i'",
QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold,
QS->char1_money.silver, QS->char1_money.copper, QS->char1_count,
QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold,
QS->char2_money.silver, QS->char2_money.copper, QS->char2_count);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
if(detailCount == 0)
return;
int lastIndex = results.LastInsertedID();
for(int i = 0; i < detailCount; i++) {
query = StringFormat("INSERT INTO `qs_player_trade_record_entries` SET `event_id` = '%i', "
"`from_id` = '%i', `from_slot` = '%i', `to_id` = '%i', `to_slot` = '%i', "
"`item_id` = '%i', `charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', "
"`aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
lastIndex, QS->items[i].from_id, QS->items[i].from_slot,
QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id,
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Trade Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 detailCount) {
std::string query = StringFormat("INSERT INTO `qs_player_handin_record` SET `time` = NOW(), "
"`quest_id` = '%i', `char_id` = '%i', `char_pp` = '%i', "
"`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', "
"`char_items` = '%i', `npc_id` = '%i', `npc_pp` = '%i', "
"`npc_gp` = '%i', `npc_sp` = '%i', `npc_cp` = '%i', "
"`npc_items`='%i'",
QS->quest_id, QS->char_id, QS->char_money.platinum,
QS->char_money.gold, QS->char_money.silver, QS->char_money.copper,
QS->char_count, QS->npc_id, QS->npc_money.platinum,
QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper,
QS->npc_count);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
if(detailCount == 0)
return;
int lastIndex = results.LastInsertedID();
for(int i = 0; i < detailCount; i++) {
query = StringFormat("INSERT INTO `qs_player_handin_record_entries` SET `event_id` = '%i', "
"`action_type` = '%s', `char_slot` = '%i', `item_id` = '%i', "
"`charges` = '%i', `aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', "
"`aug_4` = '%i', `aug_5` = '%i'",
lastIndex, QS->items[i].action_type, QS->items[i].char_slot,
QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
QS->items[i].aug_5);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Handin Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 members){
std::string query = StringFormat("INSERT INTO `qs_player_npc_kill_record` "
"SET `npc_id` = '%i', `type` = '%i', "
"`zone_id` = '%i', `time` = NOW()",
QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
if(members == 0)
return;
int lastIndex = results.LastInsertedID();
for (int i = 0; i < members; i++) {
query = StringFormat("INSERT INTO `qs_player_npc_kill_record_entries` "
"SET `event_id` = '%i', `char_id` = '%i'",
lastIndex, QS->Chars[i].char_id);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed NPC Kill Log Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 items) {
std::string query = StringFormat("INSERT INTO `qs_player_delete_record` SET `time` = NOW(), "
"`char_id` = '%i', `stack_size` = '%i', `char_items` = '%i'",
QS->char_id, QS->stack_size, QS->char_count, QS->char_count);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
if(items == 0)
return;
int lastIndex = results.LastInsertedID();
for(int i = 0; i < items; i++) {
query = StringFormat("INSERT INTO `qs_player_delete_record_entries` SET `event_id` = '%i', "
"`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', "
"`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
QS->items[i].aug_5);
results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Delete Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 items) {
/* These are item moves */
std::string query = StringFormat("INSERT INTO `qs_player_move_record` SET `time` = NOW(), "
"`char_id` = '%i', `from_slot` = '%i', `to_slot` = '%i', "
"`stack_size` = '%i', `char_items` = '%i', `postaction` = '%i'",
QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size,
QS->char_count, QS->postaction);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
if(items == 0)
return;
int lastIndex = results.LastInsertedID();
for(int i = 0; i < items; i++) {
query = StringFormat("INSERT INTO `qs_player_move_record_entries` SET `event_id` = '%i', "
"`from_slot` = '%i', `to_slot` = '%i', `item_id` = '%i', `charges` = '%i', "
"`aug_1` = '%i', `aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
lastIndex, QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id,
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2,
QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5);
results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Move Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 items) {
/* Merchant transactions are from the perspective of the merchant, not the player */
std::string query = StringFormat("INSERT INTO `qs_merchant_transaction_record` SET `time` = NOW(), "
"`zone_id` = '%i', `merchant_id` = '%i', `merchant_pp` = '%i', "
"`merchant_gp` = '%i', `merchant_sp` = '%i', `merchant_cp` = '%i', "
"`merchant_items` = '%i', `char_id` = '%i', `char_pp` = '%i', "
"`char_gp` = '%i', `char_sp` = '%i', `char_cp` = '%i', "
"`char_items` = '%i'",
QS->zone_id, QS->merchant_id, QS->merchant_money.platinum,
QS->merchant_money.gold, QS->merchant_money.silver,
QS->merchant_money.copper, QS->merchant_count, QS->char_id,
QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver,
QS->char_money.copper, QS->char_count);
auto results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
if(items == 0)
return;
int lastIndex = results.LastInsertedID();
for(int i = 0; i < items; i++) {
query = StringFormat("INSERT INTO `qs_merchant_transaction_record_entries` SET `event_id` = '%i', "
"`char_slot` = '%i', `item_id` = '%i', `charges` = '%i', `aug_1` = '%i', "
"`aug_2` = '%i', `aug_3` = '%i', `aug_4` = '%i', `aug_5` = '%i'",
lastIndex, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4,
QS->items[i].aug_5);
results = QueryDatabase(query);
if(!results.Success()) {
Log.Out(Logs::Detail, Logs::QS_Server, "Failed Transaction Log Record Entry Insert: %s", results.ErrorMessage().c_str());
Log.Out(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
}
}
}
void Database::GeneralQueryReceive(ServerPacket *pack) {
/*
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
-6
View File
@@ -44,12 +44,6 @@ public:
~Database();
void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type);
void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 DetailCount);
void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 DetailCount);
void LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members);
void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items);
void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items);
void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items);
void GeneralQueryReceive(ServerPacket *pack);
void LoadLogSettings(EQEmuLogSys::LogSettings* log_settings);
-35
View File
@@ -81,41 +81,6 @@ void WorldServer::Process()
database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type);
break;
}
case ServerOP_QSPlayerLogTrades: {
QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct*)pack->pBuffer;
database.LogPlayerTrade(QS, QS->_detail_count);
break;
}
case ServerOP_QSPlayerLogHandins: {
QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)pack->pBuffer;
database.LogPlayerHandin(QS, QS->_detail_count);
break;
}
case ServerOP_QSPlayerLogNPCKills: {
QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
uint32 Members = pack->size - sizeof(QSPlayerLogNPCKill_Struct);
if (Members > 0) Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct);
database.LogPlayerNPCKill(QS, Members);
break;
}
case ServerOP_QSPlayerLogDeletes: {
QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct*)pack->pBuffer;
uint32 Items = QS->char_count;
database.LogPlayerDelete(QS, Items);
break;
}
case ServerOP_QSPlayerLogMoves: {
QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct*)pack->pBuffer;
uint32 Items = QS->char_count;
database.LogPlayerMove(QS, Items);
break;
}
case ServerOP_QSPlayerLogMerchantTransactions: {
QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct*)pack->pBuffer;
uint32 Items = QS->char_count + QS->merchant_count;
database.LogMerchantTransaction(QS, Items);
break;
}
case ServerOP_QueryServGeneric: {
/*
The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets

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