mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-23 00:42:27 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 46cb96a026 | |||
| bbc3733c3a | |||
| 5995afa1b8 | |||
| ff3cb9fc54 | |||
| 56e7d1b0dc | |||
| 7341ecc185 | |||
| 279ed8d86c | |||
| 21ce5c6daa | |||
| 00af95502e | |||
| dda8ae4803 | |||
| 316aa5ef73 | |||
| 9fcdf5367e | |||
| 972d3d8874 | |||
| abc5ddc5f8 | |||
| 14b5a8d817 | |||
| 20cbe4af44 | |||
| 7870bf103a | |||
| 18b4d068ea | |||
| 568938d003 | |||
| 215861dd86 | |||
| c62cff1ce7 | |||
| 69612b44d4 | |||
| 8bce7893ed | |||
| 4e4168852b | |||
| ca278d029e | |||
| 273574d4db | |||
| c71a5888ff | |||
| b3c53e5907 | |||
| f511862004 | |||
| a90e9cf4c6 | |||
| 2d617f0ea7 | |||
| 551c0ef368 | |||
| a5274b9b6e | |||
| fc2492a859 | |||
| 701e194ece | |||
| b75e6308dd |
+8
-10
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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];
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+15
-68
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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];
|
||||
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(¶ms);
|
||||
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(¤t_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, ¤t_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(¤t_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 ¤t_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 ¤t = 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;
|
||||
}
|
||||
|
||||
@@ -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 ¤t_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 ¤t_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;
|
||||
};
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+31
-35
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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[] =
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user