diff options
| -rw-r--r-- | sql/updates/world/2014_08_10_02_world_misc.sql | 238 | ||||
| -rw-r--r-- | src/server/authserver/Server/AuthSession.cpp | 81 | ||||
| -rw-r--r-- | src/server/authserver/Server/AuthSession.h | 4 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 109 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.h | 4 | ||||
| -rw-r--r-- | src/server/shared/Common.h | 40 | ||||
| -rw-r--r-- | src/server/shared/Database/DatabaseWorkerPool.h | 95 | ||||
| -rw-r--r-- | src/server/shared/Database/MySQLConnection.cpp | 8 | ||||
| -rw-r--r-- | src/server/shared/Networking/MessageBuffer.h | 93 | ||||
| -rw-r--r-- | src/server/shared/Networking/Socket.h | 129 | ||||
| -rw-r--r-- | src/server/shared/Packets/ByteBuffer.cpp | 5 | ||||
| -rw-r--r-- | src/server/shared/Packets/ByteBuffer.h | 12 | ||||
| -rw-r--r-- | src/server/shared/Packets/WorldPacket.h | 2 | ||||
| -rw-r--r-- | src/server/worldserver/Main.cpp | 57 | ||||
| -rw-r--r-- | src/tools/mmaps_generator/PathGenerator.cpp | 2 |
15 files changed, 612 insertions, 267 deletions
diff --git a/sql/updates/world/2014_08_10_02_world_misc.sql b/sql/updates/world/2014_08_10_02_world_misc.sql new file mode 100644 index 00000000000..b07b6a3632d --- /dev/null +++ b/sql/updates/world/2014_08_10_02_world_misc.sql @@ -0,0 +1,238 @@ +DELETE FROM `creature_text` WHERE `entry` IN(19270,19228,18756,19271); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`, `BroadcastTextID`) VALUES +(19270, 0, 0, 'If you are ready to laugh, head over to the World''s End Tavern!', 14, 0, 100, 0, 0, 0, 'Shattrath Saul',16380), +(18756, 0, 0, 'I, like, so don''t get it...', 12, 0, 100, 1, 0, 0, 'Haris Pilton',16888), +(18756, 0, 1, 'Psshh... whatever.', 12, 0, 100, 1, 0, 0, 'Haris Pilton',16882), +(18756, 0, 2, 'That''s hot.', 12, 0, 100, 1, 0, 0, 'Haris Pilton',16881), +(18756, 0, 3, 'That joke''s hot.', 12, 0, 100, 1, 0, 0, 'Haris Pilton',16887), +(19228, 0, 0, 'Hey all! So how long until the jokes spawn?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16382), +(19228, 0, 1, 'I just flew in from Ironforge and, Boy!, are my mount''s wings tired!', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16649), +(19228, 0, 2, 'Hey folks, go easy on me... it''s my first time.', 12, 0, 100, 24, 0, 0, 'Perry Gatner',16328), +(19228, 0, 3, 'Thanks for coming out to see me! I hope you are ready for a good time, because I am.', 12, 0, 100, 21, 0, 0, 'Perry Gatner',16327), + + + +(19228, 1, 0, 'I never met a tauren I didn''t like...', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16378), +(19228, 2, 0, 'To eat!!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16379), +(19228, 3, 0, 'Last week I was in Goldshire. Have you been there?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16651), +(19228, 4, 0, 'That town''s so small, I asked a kid to draw me a map. He drew it on the back of a Defias wanted poster...', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16652), +(19228, 5, 0, 'to scale!!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16653), +(19228, 6, 0, 'Impersonation time!! I call this, "The Silly Tauren."', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16337), +(19228, 7, 0, 'The comedian clears his throat.', 16, 0, 100, 0, 0, 0, 'Perry Gatner',16338), +(19228, 8, 0, 'The comedian impersonates a tauren.', 16, 0, 100, 5, 0, 6386, 'Perry Gatner',16580), +(19228, 9, 0, 'Here''s a good one, why do watermelons have water in them? ', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16333), +(19228, 10, 0, 'Because they are planted in the spring!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16336), +(19228, 11, 0, 'What''s the deal with women? I mean they are always like...', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16339), +(19228, 12, 0, 'The comedian impersonates a human female.', 16, 0, 100, 5, 0, 6143, 'Perry Gatner',16583), +(19228, 13, 0, 'And then gnomes are even worse! They are always saying stuff like...', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16340), +(19228, 14, 0, 'The comedian impersonates a gnome.', 16, 0, 100, 5, 0, 6133, 'Perry Gatner',16581), +(19228, 15, 0, 'What time is it when an elekk sits on your fence?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16368), +(19228, 16, 0, 'Time to get a new fence!!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16369), +(19228, 17, 0, 'If I knew it was going to be like this, I''d have worn my Greater Boots of Laughter.', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16388), +(19228, 17, 1, 'Apparently my reputation with you people is hostile.', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16385), +(19228, 17, 2, 'Wow! The laughs don''t drop very often here, do they?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16389), +(19228, 18, 0, 'Hey! Hey! Hey! It''s Raliq the drunk... His momma''s so fat she didn''t just make the front cover of Ogre Today...', 12, 0, 100, 25, 0, 0, 'Perry Gatner',16667), +(19228, 19, 0, 'She made the back cover too!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16668), +(19228, 20, 0, 'The gnomes used to be a nice respectful people...', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16669), +(19228, 21, 0, 'The other day I saw one walking down the street shouting, "Once you go gnome, you never go home!"', 12, 0, 100, 1, 0, 4415, 'Perry Gatner',16670), +(19228, 22, 0, 'I love blood elf women. Especially when they say stuff like this...', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16374), +(19228, 23, 0, 'The comedian impersonates a blood elf.', 16, 0, 100, 5, 0, 9643, 'Perry Gatner',16582), +(19228, 24, 0, 'So the blood elves think they''re just one step away from ruling the world...', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16682), +(19228, 25, 0, 'Twelve steps is more like it!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16683), +(19228, 26, 0, 'One last impersonation. It''s tough, but let''s see if you can guess who it is...', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16351), +(19228, 27, 0, 'The comedian impersonates an orc.', 16, 0, 100, 5, 0, 7195, 'Perry Gatner',16584), +(19228, 28, 0, 'Now that the show''s done, can someone run me through Scarlet Monestary?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16381), +(19228, 28, 1, 'Thank you! Don''t forget to tip your waiters! Good night folks.', 12, 0, 100, 0, 0, 0, 'Perry Gatner',16341), +(19228, 28, 2, 'Well, it''s time to take these comedic muscles elsewhere. Have a good night all!', 12, 0, 100, 23, 0, 0, 'Perry Gatner',16348), +(19228, 28, 3, 'Is it over already? You''ve been great folks. Walk safely and have a good night.', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16343), +(19228, 29, 0, 'How many kobolds does it take to change a lantern wick?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16657), +(19228, 30, 0, 'You no take candle!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16658), +(19228, 31, 0, 'Goldshire''s inn advertises a lakeside view...', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16655), +(19228, 32, 0, 'I saw a murloc swim by my window.', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16656), +(19228, 33, 0, 'Have you ever noticed that all those cute, orc kids look the same?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16331), +(19228, 34, 0, 'It''s too bad they don''t stay cute. There must be some rite of passage in the Barrens called, "Climb ugly tree and fall out."', 12, 0, 100, 0, 0, 0, 'Perry Gatner',16334), +(19228, 35, 0, 'I''ve heard that gnomes can grant wishes...', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16375), +(19228, 36, 0, 'Well I wish they''d go away!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16376), +(19228, 37, 0, 'Look who''s here, it''s Raliq the drunk... His momma''s so fat dragons won''t eat her...', 12, 0, 100, 25, 0, 0, 'Perry Gatner',16665), +(19228, 38, 0, 'They don''t know where to store the leftovers!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16666), +(19228, 39, 0, 'My wife and I were happy for 23 years...', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16370), +(19228, 40, 0, 'And then we met!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16371), +(19228, 41, 0, 'What do you call a broken boomerang?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16372), +(19228, 42, 0, 'A stick!', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16373), +(19228, 43, 0, 'So this gnome tells a tauren that he''s been to Molten Core.', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16332), +(19228, 44, 0, 'The tauren says, "That''s a load of bull."', 12, 0, 100, 5, 0, 0, 'Perry Gatner',16335), +(19228, 45, 0, 'How desperate do you have to be for allies that you recruit your livestock?', 12, 0, 100, 6, 0, 0, 'Perry Gatner',16680), +(19228, 46, 0, 'I own a dog, but I''m not giving him a sword.', 12, 0, 100, 1, 0, 0, 'Perry Gatner',16681), +(19271, 0, 0, 'Thank you all for coming tonight. Now put your hands together to welcome Shattrath''s best, Perry Gatner!', 12, 0, 100, 21, 0, 0, 'Albert Quarksprocket',16383), +(19271, 1, 0, 'Perry Gatner! What an act! The cantina is open all night long, so please, stay and enjoy yourselves!', 12, 0, 100, 21, 0, 0, 'Albert Quarksprocket',16384); +-- Delete the permament spawn of Perry Gatner +DELETE FROM `creature` WHERE `guid`=6747; + +DELETE FROM `waypoints` WHERE `entry` IN(19228,19271,1927100); +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(19228,1,-1748.807, 5131.199, -35.77385,'Perry Gatner WP1'), +(19228,2,-1749.057, 5132.199, -36.02385,'Perry Gatner WP2'), +(19228,3,-1750.557, 5137.449, -36.02385,'Perry Gatner WP3'), -- Stage +(19228,4,-1748.807, 5131.199, -35.77385,'Perry Gatner WP4'), +(19228,5,-1749.029, 5132.317, -36.02094,'Perry Gatner WP5'), +(19228,6,-1748.779, 5131.067, -36.02094,'Perry Gatner WP6'), -- back + + +(19271,1,-1740.421, 5139.315, -37.04716,'Albert Quarksprocket WP1'), +(19271,2,-1741.421, 5139.315, -36.54716,'Albert Quarksprocket WP2'), +(19271,3,-1745.072, 5139.196, -36.11526,'Albert Quarksprocket WP3'), +(19271,4,-1749.072, 5140.196, -36.11526,'Albert Quarksprocket WP4'), +(19271,5,-1750.931, 5143.452, -35.98227,'Albert Quarksprocket WP5'), -- Intro +(19271,6,-1749.931, 5144.202, -36.48227,'Albert Quarksprocket WP6'), +(19271,7,-1749.181, 5144.952, -36.73227,'Albert Quarksprocket WP7'), +(19271,8,-1748.681, 5145.452, -36.73227,'Albert Quarksprocket WP8'), +(19271,9,-1747.681, 5144.952, -36.73227,'Albert Quarksprocket WP9'), +(19271,10,-1740.931, 5142.721, -37.01586,'Albert Quarksprocket WP10'), -- end +(19271,11,-1739.931, 5141.971, -37.01586,'Albert Quarksprocket WP11'), +(19271,12,-1740.726, 5142.045, -37.01049,'Albert Quarksprocket WP12'), +(19271,13,-1741.726, 5142.545, -37.01049,'Albert Quarksprocket WP13'), +(19271,14,-1747.726, 5145.545, -37.01049,'Albert Quarksprocket WP14'), +(19271,15,-1748.1, 5145.452, -36.73235,'Albert Quarksprocket WP15'), +(19271,16,-1748.6, 5145.952, -36.73235,'Albert Quarksprocket WP16'), +(19271,17,-1749.35, 5144.952, -36.73235,'Albert Quarksprocket WP17'), +(19271,18,-1749.85, 5143.702, -36.23235,'Albert Quarksprocket WP18'), -- Outro +(19271,19,-1749.56, 5143.69, -35.98226,'Albert Quarksprocket WP19'), +(19271,20,-1748.56, 5143.94, -36.48226,'Albert Quarksprocket WP20'), +(19271,21,-1747.31, 5144.44, -36.73226,'Albert Quarksprocket WP21'), +(19271,22,-1748.287, 5144.005, -36.37066,'Albert Quarksprocket WP22'), +(19271,23,-1747.037, 5144.505, -36.87066,'Albert Quarksprocket WP23'), +(19271,24,-1745.287, 5145.255, -36.87066,'Albert Quarksprocket WP24'), +(19271,25,-1741.787, 5142.005, -36.87066,'Albert Quarksprocket WP25'), +(19271,26,-1737.287, 5138.584, -37.30579,'Albert Quarksprocket WP26');-- end + +DELETE FROM `game_event` WHERE `eventEntry` IN(65,66); +INSERT INTO `game_event` (`eventEntry`, `start_time`, `end_time`, `occurence`, `length`, `holiday`, `description`, `world_event`, `announce`) VALUES +(65, '2008-01-02 15:55:00', '2020-12-31 06:00:00', 1440, 15, 0, 'Perry Gatner 4pm', 0, 2), +(66, '2008-01-02 19:55:00', '2020-12-31 06:00:00', 1440, 15, 0, 'Perry Gatner 8pm', 0, 2); + +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry` IN(19270,19228,19271,15106,14990,22015,30567,15105,34949); + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(19270,19228,19271,15106,14990,22015,30567,15105,34949) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(1922800,1922801,1922802,1927000,1927100,1927101,1927102,1927103,1927104,1927105,1927106,1927107,1927108,1927109,1927110,1927111,1927112,1927113,1927114) AND `source_type`=9; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(19270, 0, 0, 0, 68, 0, 100, 0, 65, 0, 0, 0, 80, 1927000, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shattrath Saul - On Event Start Run Timed action list'), +(19270, 0, 1, 0, 68, 0, 100, 0, 66, 0, 0, 0, 80, 1927000, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shattrath Saul - On Event Start Run Timed action list'), +(1927000, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shattrath Saul - Script - Say'), +(1927000, 9, 1, 0, 0, 0, 100, 0, 120000, 120000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shattrath Saul - Script - Say'), +(1927000, 9, 2, 0, 0, 0, 100, 0, 120000, 120000, 0, 0, 12, 19228, 1, 900000, 0, 0, 0, 8, 0, 0, 0, -1747.617, 5126.938, -35.78802, 1.867502, 'Shattrath Saul - Script - Spawn Perry Gatner'), +(1927000, 9, 3, 0, 0, 0, 100, 0, 60000, 60000, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 19271, 0, 0, 0, 0, 0, 0, 'Shattrath Saul - Script - Set Data 1 1 on Albert Quarksprocket'), +(19271, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 53, 0, 19271, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Data 11 - Start WP'), +(19271, 0, 1, 2, 40, 0, 100, 0, 5, 19271, 0, 0, 54, 13000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Reached WP5 - Pause WP'), +(19271, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1.867502, 'Albert Quarksprocket - On Reached WP5 - Set Orientation'), +(19271, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 5000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Reached WP5 - Say line 1'), +(19271, 0, 4, 0, 52, 0, 100, 0, 0, 19271, 0, 0, 80, 1927104, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Text over line 1 - Run Script '), +(19271, 0, 5, 6, 40, 0, 100, 0, 10, 19271, 0, 0, 54, 229000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Reached WP10 - Stop WP'), +(19271, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Reached WP10 - Set Orientation'), +(19271, 0, 7, 0, 38, 0, 100, 0, 2, 2, 0, 0, 87, 1927102, 1927103, 1927113, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2.03774, 'Albert Quarksprocket - On Reached WP26 - Set Orientation'), +(19271, 0, 8, 9, 40, 0, 100, 0, 18, 19271, 0, 0, 54, 15000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Reached WP18 - Pause WP'), +(19271, 0, 9, 10, 61, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1.867502, 'Albert Quarksprocket - On Reached WP18 - Set Orientation'), +(19271, 0, 10, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 1, 14000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Reached WP18 - Say line 2'), +(19271, 0, 11, 0, 40, 0, 100, 0, 26, 19271, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 2.03774, 'Albert Quarksprocket - On Reached WP26 - Set Orientation'), +(19271, 0, 12, 0, 38, 0, 100, 0, 3, 3, 0, 0, 87, 1927100, 1927101, 1927111, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Data set 3 3 - Run Random script'), +(19271, 0, 13, 0, 38, 0, 100, 0, 4, 4, 0, 0, 87, 1927105, 1927106, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Data set 4 4 - Run Random script'), +(19271, 0, 14, 0, 38, 0, 100, 0, 5, 5, 0, 0, 87, 1927107, 1927108, 1927114, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Data set 5 5 - Run Random script'), +(19271, 0, 15, 0, 38, 0, 100, 0, 6, 6, 0, 0, 87, 1927109, 1927110, 1927112, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - On Data set 5 5 - Run Random script'), +(1927100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 15, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 1 - Say Line 15 (Perry Gatner'), +(1927100, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 16, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 1 - Say Line 16 (Perry Gatner'), +(1927101, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 29, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 2 - Say Line 29 (Perry Gatner'), +(1927101, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 30, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 2 - Say Line 30 (Perry Gatner'), +(1927102, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 3 - Say Line 15 (Perry Gatner'), +(1927102, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 10, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 3 - Say Line 16 (Perry Gatner'), +(1927103, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 31, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 3 - Say Line 31 (Perry Gatner'), +(1927103, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 32, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 3 - Say Line 32 (Perry Gatner'), +(1927104, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 4 - Set Orientation'), +(1927104, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 4 - Play emote Oneshot_applause'), +(1927104, 9, 2, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 5, 25, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 4 - Play emote Oneshot_point'), +(1927104, 9, 3, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 5, 21, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 4 - Play emote Oneshot_applause'), +(1927104, 9, 4, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 4 - Set Data 1 1 on Perry Gatner'), +(1927105, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 5 - Say Line 1 (Perry Gatner'), +(1927105, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 2, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 5 - Say Line 2 (Perry Gatner'), +(1927106, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 33, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 6 - Say Line 33 (Perry Gatner'), +(1927106, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 34, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 6 - Say Line 34 (Perry Gatner'), +(1927107, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 24, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 7 - Say Line 24 (Perry Gatner'), +(1927107, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 25, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 7 - Say Line 25 (Perry Gatner'), +(1927108, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 35, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 8 - Say Line 35 (Perry Gatner'), +(1927108, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 36, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 8 - Say Line 36 (Perry Gatner'), +(1927109, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 18, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 9 - Say Line 24 (Perry Gatner'), +(1927109, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 19, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 9 - Say Line 25 (Perry Gatner'), +(1927110, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 10 - Say Line 35 (Perry Gatner'), +(1927110, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 38, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 10 - Say Line 36 (Perry Gatner'), +(1927111, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 39, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 11 - Say Line 39 (Perry Gatner'), +(1927111, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 40, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 11 - Say Line 40 (Perry Gatner'), +(1927112, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 41, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 12 - Say Line 41 (Perry Gatner'), +(1927112, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 42, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 12 - Say Line 42 (Perry Gatner'), +(1927113, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 43, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 13 - Say Line 42 (Perry Gatner'), +(1927113, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 44, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 13 - Say Line 43 (Perry Gatner'), +(1927114, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 45, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 14 - Say Line 44 (Perry Gatner'), +(1927114, 9, 1, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 46, 0, 0, 0, 0, 0, 19, 19228, 0, 0, 0, 0, 0, 0, 'Albert Quarksprocket - - Script 14 - Say Line 45 (Perry Gatner'), +(19228, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 53, 0, 19228, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - On Data Set 1 1 - Start WP'), +(19228, 0, 1, 2, 40, 0, 100, 0, 3, 19228, 0, 0, 54, 220000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - On Reached WP3 - Pause WP'), +(19228, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 80, 1922800, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - On Reached WP3 - Run Script 1'), +(19228, 0, 3, 0, 40, 0, 100, 0, 6, 19228, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - On Reached WP6 - Despawn'), +(19228, 0, 4, 0, 40, 0, 100, 0, 2, 19228, 0, 0, 80, 1922801, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - On Reached WP2 - Run Script 2'), +(19228, 0, 5, 0, 40, 0, 100, 0, 4, 19228, 0, 0, 80, 1922802, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - On Reached WP6 - Run Script 3'), +(1922800, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 1, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 45, 4, 4, 0, 0, 0, 0, 19, 19271, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Set Data 4 4 on Albert Quarksprocket'), +(1922800, 9, 2, 0, 0, 0, 100, 0, 14000, 14000, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 3, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 4, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 5, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 6, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 7, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 8, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 19271, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Set Data 2 2 on Albert Quarksprocket'), +(1922800, 9, 9, 0, 0, 0, 100, 0, 14000, 14000, 0, 0, 1, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 10, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 11, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 12, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 12, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 13, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 13, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 14, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 14, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 15, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 45, 3, 3, 0, 0, 0, 0, 19, 19271, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Set Data 3 3 on Albert Quarksprocket'), +(1922800, 9, 16, 0, 0, 0, 100, 0, 12000, 12000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 19, 18756, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line 1 on Hilton Paris'), +(1922800, 9, 17, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 1, 17, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 18, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 45, 6, 6, 0, 0, 0, 0, 19, 19271, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Set Data 6 6 on Albert Quarksprocket'), +(1922800, 9, 19, 0, 0, 0, 100, 0, 14000, 14000, 0, 0, 1, 20, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 20, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 21, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 21, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 22, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 22, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 23, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 23, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 24, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 45, 5, 5, 0, 0, 0, 0, 19, 19271, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Set Data 5 5 on Albert Quarksprocket'), +(1922800, 9, 25, 0, 0, 0, 100, 0, 14000, 14000, 0, 0, 1, 26, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 26, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 27, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 27, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922800, 9, 38, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script - Say Line'), +(1922801, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 15106, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 2 - Set Data 1 1 on Frostwolf Emissary'), +(1922801, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 14990, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 2 - Set Data 1 1 on Defilers Emissary'), +(1922801, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 22015, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 2 - Set Data 1 1 on Eye of the Storm Envoy'), +(1922801, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 30567, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 2 - Set Data 1 1 on Strand of the Ancients Envoy'), +(1922801, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 15105, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 2 - Set Data 1 1 on Warsong Emissary'), +(1922801, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 34949, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 2 - Set Data 1 1 on Isle of Conquest Envoy'), +(1922802, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 15106, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 3 - Set Data 2 2 on Frostwolf Emissary'), +(1922802, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 14990, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 3 - Set Data 2 2 on Defilers Emissary'), +(1922802, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 22015, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 3 - Set Data 2 2 on Eye of the Storm Envoy'), +(1922802, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 30567, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 3 - Set Data 2 2 on Strand of the Ancients Envoy'), +(1922802, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 15105, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 3 - Set Data 2 2 on Warsong Emissary'), +(1922802, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 34949, 0, 0, 0, 0, 0, 0, 'Perry Gatner - Script 3 - Set Data 2 2 on Isle of Conquest Envoy'), +(15106, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostwolf Emissary - On Data Set 1 1 - Set Phase 2'), +(15106, 0, 1, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostwolf Emissary - On Data Set 2 2 - Set Phase 1'), +(15106, 0, 2, 0, 1, 2, 100, 0, 14000, 21000, 7000, 21000, 5, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frostwolf Emissary - OOC (Phase 2) - Play emote oneshot laugh'), +(14990, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Defilers Emissary - On Data Set 1 1 - Set Phase 2'), +(14990, 0, 1, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Defilers Emissary - On Data Set 2 2 - Set Phase 1'), +(14990, 0, 2, 0, 1, 2, 100, 0, 14000, 21000, 7000, 21000, 5, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Defilers Emissary - OOC (Phase 2) - Play emote oneshot laugh'), +(22015, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eye of the Storm Envoy - On Data Set 1 1 - Set Phase 2'), +(22015, 0, 1, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eye of the Storm Envoy - On Data Set 2 2 - Set Phase 1'), +(22015, 0, 2, 0, 1, 2, 100, 0, 14000, 21000, 7000, 21000, 5, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Eye of the Storm Envoy - OOC (Phase 2) - Play emote oneshot laugh'), +(30567, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Strand of the Ancients Envoy - On Data Set 1 1 - Set Phase 2'), +(30567, 0, 1, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Strand of the Ancients Envoy - On Data Set 2 2 - Set Phase 1'), +(30567, 0, 2, 0, 1, 2, 100, 0, 14000, 21000, 7000, 21000, 5, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Strand of the Ancients Envoy - OOC (Phase 2) - Play emote oneshot laugh'), +(15105, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Warsong Emissary - On Data Set 1 1 - Set Phase 2'), +(15105, 0, 1, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Warsong Emissary - On Data Set 2 2 - Set Phase 1'), +(15105, 0, 2, 0, 1, 2, 100, 0, 14000, 21000, 7000, 21000, 5, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Warsong Emissary - OOC (Phase 2) - Play emote oneshot laugh'), +(34949, 0, 0, 0, 38, 0, 100, 0, 1, 1, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Isle of Conquest Envoy - On Data Set 1 1 - Set Phase 2'), +(34949, 0, 1, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Isle of Conquest Envoy - On Data Set 2 2 - Set Phase 1'), +(34949, 0, 2, 0, 1, 2, 100, 0, 14000, 21000, 7000, 21000, 5, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Isle of Conquest Envoy - OOC (Phase 2) - Play emote oneshot laugh'); diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index cdd8298174f..76f8b8c27b0 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -21,6 +21,7 @@ #include "AuthCodes.h" #include "Database/DatabaseEnv.h" #include "SHA1.h" +#include "TOTP.h" #include "openssl/crypto.h" #include "Configuration/Config.h" #include "RealmList.h" @@ -52,7 +53,6 @@ enum eStatus typedef struct AUTH_LOGON_CHALLENGE_C { - uint8 cmd; uint8 error; uint16 size; uint8 gamename[4]; @@ -71,7 +71,6 @@ typedef struct AUTH_LOGON_CHALLENGE_C typedef struct AUTH_LOGON_PROOF_C { - uint8 cmd; uint8 A[32]; uint8 M1[20]; uint8 crc_hash[20]; @@ -99,7 +98,6 @@ typedef struct AUTH_LOGON_PROOF_S_OLD typedef struct AUTH_RECONNECT_PROOF_C { - uint8 cmd; uint8 R1[16]; uint8 R2[20]; uint8 R3[20]; @@ -114,10 +112,10 @@ enum class BufferSizes : uint32 SRP_6_S = 0x20, }; -#define REALM_LIST_PACKET_SIZE 5 -#define XFER_ACCEPT_SIZE 1 -#define XFER_RESUME_SIZE 9 -#define XFER_CANCEL_SIZE 1 +#define REALM_LIST_PACKET_SIZE 4 +#define XFER_ACCEPT_SIZE 0 +#define XFER_RESUME_SIZE 8 +#define XFER_CANCEL_SIZE 0 std::unordered_map<uint8, AuthHandler> AuthSession::InitHandlers() { @@ -137,44 +135,36 @@ std::unordered_map<uint8, AuthHandler> AuthSession::InitHandlers() std::unordered_map<uint8, AuthHandler> const Handlers = AuthSession::InitHandlers(); -void AuthSession::ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) +void AuthSession::ReadHeaderHandler() { - if (!error && transferedBytes == 1) + uint8 cmd = GetHeaderBuffer()[0]; + auto itr = Handlers.find(cmd); + if (itr != Handlers.end()) { - uint8 cmd = GetReadBuffer()[0]; - auto itr = Handlers.find(cmd); - if (itr != Handlers.end()) + // Handle dynamic size packet + if (cmd == AUTH_LOGON_CHALLENGE || cmd == AUTH_RECONNECT_CHALLENGE) { - // Handle dynamic size packet - if (cmd == AUTH_LOGON_CHALLENGE || cmd == AUTH_RECONNECT_CHALLENGE) - { - ReadData(sizeof(uint8) + sizeof(uint16), sizeof(cmd)); //error + size - sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer()); + ReadData(sizeof(uint8) + sizeof(uint16)); //error + size + sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetDataBuffer()); - AsyncReadData(challenge->size, sizeof(uint8) + sizeof(uint8) + sizeof(uint16)); // cmd + error + size - } - else - AsyncReadData(itr->second.packetSize, sizeof(uint8)); + AsyncReadData(challenge->size); } + else + AsyncReadData(itr->second.packetSize); } else CloseSocket(); } -void AuthSession::ReadDataHandler(boost::system::error_code error, size_t transferedBytes) +void AuthSession::ReadDataHandler() { - if (!error && transferedBytes > 0) + if (!(*this.*Handlers.at(GetHeaderBuffer()[0]).handler)()) { - if (!(*this.*Handlers.at(GetReadBuffer()[0]).handler)()) - { - CloseSocket(); - return; - } - - AsyncReadHeader(); - } - else CloseSocket(); + return; + } + + AsyncReadHeader(); } void AuthSession::AsyncWrite(ByteBuffer& packet) @@ -191,7 +181,7 @@ void AuthSession::AsyncWrite(ByteBuffer& packet) bool AuthSession::HandleLogonChallenge() { - sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer()); + sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetDataBuffer()); //TC_LOG_DEBUG("server.authserver", "[AuthChallenge] got full packet, %#04x bytes", challenge->size); TC_LOG_DEBUG("server.authserver", "[AuthChallenge] name(%d): '%s'", challenge->I_len, challenge->I); @@ -410,7 +400,7 @@ bool AuthSession::HandleLogonProof() TC_LOG_DEBUG("server.authserver", "Entering _HandleLogonProof"); // Read the packet - sAuthLogonProof_C *logonProof = reinterpret_cast<sAuthLogonProof_C*>(GetReadBuffer()); + sAuthLogonProof_C *logonProof = reinterpret_cast<sAuthLogonProof_C*>(GetDataBuffer()); // If the client has no valid version if (_expversion == NO_VALID_EXP_FLAG) @@ -522,17 +512,12 @@ bool AuthSession::HandleLogonProof() // Check auth token if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty()) { - // TODO To be fixed - - /* - uint8 size; - socket().recv((char*)&size, 1); - char* token = new char[size + 1]; - token[size] = '\0'; - socket().recv(token, size); - unsigned int validToken = TOTP::GenerateToken(_tokenKey.c_str()); - unsigned int incomingToken = atoi(token); - delete[] token; + ReadData(1); + uint8 size = *(GetDataBuffer() + sizeof(sAuthLogonProof_C)); + ReadData(size); + std::string token(reinterpret_cast<char*>(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)), size); + uint32 validToken = TOTP::GenerateToken(_tokenKey.c_str()); + uint32 incomingToken = atoi(token.c_str()); if (validToken != incomingToken) { ByteBuffer packet; @@ -542,7 +527,7 @@ bool AuthSession::HandleLogonProof() packet << uint8(0); AsyncWrite(packet); return false; - }*/ + } } ByteBuffer packet; @@ -650,7 +635,7 @@ bool AuthSession::HandleLogonProof() bool AuthSession::HandleReconnectChallenge() { TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectChallenge"); - sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetReadBuffer()); + sAuthLogonChallenge_C* challenge = reinterpret_cast<sAuthLogonChallenge_C*>(GetDataBuffer()); //TC_LOG_DEBUG("server.authserver", "[AuthChallenge] got full packet, %#04x bytes", challenge->size); TC_LOG_DEBUG("server.authserver", "[AuthChallenge] name(%d): '%s'", challenge->I_len, challenge->I); @@ -701,7 +686,7 @@ bool AuthSession::HandleReconnectChallenge() bool AuthSession::HandleReconnectProof() { TC_LOG_DEBUG("server.authserver", "Entering _HandleReconnectProof"); - sAuthReconnectProof_C *reconnectProof = reinterpret_cast<sAuthReconnectProof_C*>(GetReadBuffer()); + sAuthReconnectProof_C *reconnectProof = reinterpret_cast<sAuthReconnectProof_C*>(GetDataBuffer()); if (_login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) return false; diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index 5a05ee6f8e9..3497e3a030c 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -53,8 +53,8 @@ public: void AsyncWrite(ByteBuffer& packet); protected: - void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) override; - void ReadDataHandler(boost::system::error_code error, size_t transferedBytes) override; + void ReadHeaderHandler() override; + void ReadDataHandler() override; private: bool HandleLogonChallenge(); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 65a424d5d75..046cdc0acd3 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -54,89 +54,72 @@ void WorldSocket::HandleSendAuthSession() AsyncWrite(packet); } -void WorldSocket::ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) +void WorldSocket::ReadHeaderHandler() { - if (!error && transferedBytes == sizeof(ClientPktHeader)) - { - _authCrypt.DecryptRecv(GetReadBuffer(), sizeof(ClientPktHeader)); + _authCrypt.DecryptRecv(GetHeaderBuffer(), sizeof(ClientPktHeader)); - ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetReadBuffer()); - EndianConvertReverse(header->size); - EndianConvert(header->cmd); + ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetHeaderBuffer()); + EndianConvertReverse(header->size); + EndianConvert(header->cmd); - AsyncReadData(header->size - sizeof(header->cmd), sizeof(ClientPktHeader)); - } - else - CloseSocket(); + AsyncReadData(header->size - sizeof(header->cmd)); } -void WorldSocket::ReadDataHandler(boost::system::error_code error, size_t transferedBytes) +void WorldSocket::ReadDataHandler() { - ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetReadBuffer()); + ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(GetHeaderBuffer()); - if (!error && transferedBytes == (header->size - sizeof(header->cmd))) - { - header->size -= sizeof(header->cmd); - - uint16 opcode = uint16(header->cmd); + header->size -= sizeof(header->cmd); - std::string opcodeName = GetOpcodeNameForLogging(opcode); + uint16 opcode = uint16(header->cmd); - WorldPacket packet(opcode, header->size); + std::string opcodeName = GetOpcodeNameForLogging(opcode); - if (header->size > 0) - { - packet.resize(header->size); + WorldPacket packet(opcode, MoveData()); - std::memcpy(packet.contents(), &(GetReadBuffer()[sizeof(ClientPktHeader)]), header->size); - } - - if (sPacketLog->CanLogPacket()) - sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort()); + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort()); - TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(opcode).c_str()); + TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), opcodeName.c_str()); - switch (opcode) - { - case CMSG_PING: - HandlePing(packet); + switch (opcode) + { + case CMSG_PING: + HandlePing(packet); + break; + case CMSG_AUTH_SESSION: + if (_worldSession) + { + TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); break; - case CMSG_AUTH_SESSION: - if (_worldSession) - { - TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); - break; - } + } - sScriptMgr->OnPacketReceive(shared_from_this(), packet); - HandleAuthSession(packet); - break; - case CMSG_KEEP_ALIVE: - TC_LOG_DEBUG("network", "%s", opcodeName.c_str()); - sScriptMgr->OnPacketReceive(shared_from_this(), packet); - break; - default: + sScriptMgr->OnPacketReceive(shared_from_this(), packet); + HandleAuthSession(packet); + break; + case CMSG_KEEP_ALIVE: + TC_LOG_DEBUG("network", "%s", opcodeName.c_str()); + sScriptMgr->OnPacketReceive(shared_from_this(), packet); + break; + default: + { + if (!_worldSession) { - if (!_worldSession) - { - TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); - break; - } - - // Our Idle timer will reset on any non PING opcodes. - // Catches people idling on the login screen and any lingering ingame connections. - _worldSession->ResetTimeOutTime(); - - // Copy the packet to the heap before enqueuing - _worldSession->QueuePacket(new WorldPacket(packet)); + TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); break; } - } - AsyncReadHeader(); + // Our Idle timer will reset on any non PING opcodes. + // Catches people idling on the login screen and any lingering ingame connections. + _worldSession->ResetTimeOutTime(); + + // Copy the packet to the heap before enqueuing + _worldSession->QueuePacket(new WorldPacket(std::move(packet))); + break; + } } - else - CloseSocket(); + + AsyncReadHeader(); } void WorldSocket::AsyncWrite(WorldPacket& packet) diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 7275da5ff29..8d452677650 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -108,8 +108,8 @@ public: void AsyncWrite(WorldPacket& packet); protected: - void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) override; - void ReadDataHandler(boost::system::error_code error, size_t transferedBytes) override; + void ReadHeaderHandler() override; + void ReadDataHandler() override; private: void HandleSendAuthSession(); diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index 0a1389c1f38..ab268835046 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -19,46 +19,6 @@ #ifndef TRINITYCORE_COMMON_H #define TRINITYCORE_COMMON_H -// config.h needs to be included 1st -/// @todo this thingy looks like hack, but its not, need to -// make separate header however, because It makes mess here. -#ifdef HAVE_CONFIG_H -// Remove Some things that we will define -// This is in case including another config.h -// before trinity config.h -#ifdef PACKAGE -#undef PACKAGE -#endif //PACKAGE -#ifdef PACKAGE_BUGREPORT -#undef PACKAGE_BUGREPORT -#endif //PACKAGE_BUGREPORT -#ifdef PACKAGE_NAME -#undef PACKAGE_NAME -#endif //PACKAGE_NAME -#ifdef PACKAGE_STRING -#undef PACKAGE_STRING -#endif //PACKAGE_STRING -#ifdef PACKAGE_TARNAME -#undef PACKAGE_TARNAME -#endif //PACKAGE_TARNAME -#ifdef PACKAGE_VERSION -#undef PACKAGE_VERSION -#endif //PACKAGE_VERSION -#ifdef VERSION -#undef VERSION -#endif //VERSION - -# include "Config.h" - -#undef PACKAGE -#undef PACKAGE_BUGREPORT -#undef PACKAGE_NAME -#undef PACKAGE_STRING -#undef PACKAGE_TARNAME -#undef PACKAGE_VERSION -#undef VERSION -#endif //HAVE_CONFIG_H - #include "Define.h" #include <unordered_map> diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 39f1a8da3c2..e95dfc1e484 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -45,6 +45,14 @@ class PingOperation : public SQLOperation template <class T> class DatabaseWorkerPool { + private: + enum InternalIndex + { + IDX_ASYNC, + IDX_SYNCH, + IDX_SIZE + }; + public: /* Activity state */ DatabaseWorkerPool() : _connectionInfo(NULL) @@ -74,34 +82,17 @@ class DatabaseWorkerPool TC_LOG_INFO("sql.driver", "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.", GetDatabaseName(), async_threads, synch_threads); - //! Open asynchronous connections (delayed operations) - _connections[IDX_ASYNC].resize(async_threads); - for (uint8 i = 0; i < async_threads; ++i) - { - T* t = new T(_queue, *_connectionInfo); - res &= t->Open(); - if (res) // only check mysql version if connection is valid - WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "TrinityCore does not support MySQL versions below 5.1"); - _connections[IDX_ASYNC][i] = t; - ++_connectionCount[IDX_ASYNC]; - } + res = OpenConnections(IDX_ASYNC, async_threads); - //! Open synchronous connections (direct, blocking operations) - _connections[IDX_SYNCH].resize(synch_threads); - for (uint8 i = 0; i < synch_threads; ++i) - { - T* t = new T(*_connectionInfo); - res &= t->Open(); - _connections[IDX_SYNCH][i] = t; - ++_connectionCount[IDX_SYNCH]; - } + if (!res) + return res; + + res = OpenConnections(IDX_SYNCH, synch_threads); if (res) TC_LOG_INFO("sql.driver", "DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(), (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC])); - else - TC_LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " - "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName()); + return res; } @@ -112,8 +103,6 @@ class DatabaseWorkerPool for (uint8 i = 0; i < _connectionCount[IDX_ASYNC]; ++i) { T* t = _connections[IDX_ASYNC][i]; - DatabaseWorker* worker = t->m_worker; - delete worker; t->Close(); //! Closes the actualy MySQL connection. } @@ -442,7 +431,7 @@ class DatabaseWorkerPool if (str.empty()) return; - char* buf = new char[str.size()*2+1]; + char* buf = new char[str.size() * 2 + 1]; EscapeString(buf, str.c_str(), str.size()); str = buf; delete[] buf; @@ -470,6 +459,52 @@ class DatabaseWorkerPool } private: + bool OpenConnections(InternalIndex type, uint8 numConnections) + { + _connections[type].resize(numConnections); + for (uint8 i = 0; i < numConnections; ++i) + { + T* t; + + if (type == IDX_ASYNC) + t = new T(_queue, *_connectionInfo); + else if (type == IDX_SYNCH) + t = new T(*_connectionInfo); + + _connections[type][i] = t; + ++_connectionCount[type]; + + bool res = t->Open(); + + if (res) + { + if (mysql_get_server_version(t->GetHandle()) < MIN_MYSQL_SERVER_VERSION) + { + TC_LOG_ERROR("sql.driver", "TrinityCore does not support MySQL versions below 5.1"); + res = false; + } + } + + // Failed to open a connection or invalid version, abort and cleanup + if (!res) + { + TC_LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " + "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName()); + + while (_connectionCount[type] != 0) + { + T* t = _connections[type][i--]; + delete t; + --_connectionCount[type]; + } + + return false; + } + } + + return true; + } + unsigned long EscapeString(char *to, const char *from, unsigned long length) { if (!to || !from || !length) @@ -507,14 +542,6 @@ class DatabaseWorkerPool return _connectionInfo->database.c_str(); } - private: - enum _internalIndex - { - IDX_ASYNC, - IDX_SYNCH, - IDX_SIZE - }; - ProducerConsumerQueue<SQLOperation*>* _queue; //! Queue shared by async worker threads. std::vector< std::vector<T*> > _connections; uint32 _connectionCount[2]; //! Counter of MySQL connections; diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/shared/Database/MySQLConnection.cpp index e9fc20aef82..4e46ff0e3a1 100644 --- a/src/server/shared/Database/MySQLConnection.cpp +++ b/src/server/shared/Database/MySQLConnection.cpp @@ -57,12 +57,14 @@ m_connectionFlags(CONNECTION_ASYNC) MySQLConnection::~MySQLConnection() { - ASSERT (m_Mysql); /// MySQL context must be present at this point - for (size_t i = 0; i < m_stmts.size(); ++i) delete m_stmts[i]; - mysql_close(m_Mysql); + if (m_Mysql) + mysql_close(m_Mysql); + + if (m_worker) + delete m_worker; } void MySQLConnection::Close() diff --git a/src/server/shared/Networking/MessageBuffer.h b/src/server/shared/Networking/MessageBuffer.h new file mode 100644 index 00000000000..fff94b86c1e --- /dev/null +++ b/src/server/shared/Networking/MessageBuffer.h @@ -0,0 +1,93 @@ +/* +* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; 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, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __MESSAGEBUFFER_H_ +#define __MESSAGEBUFFER_H_ + +#include "Define.h" +#include <vector> + +class MessageBuffer +{ + typedef std::vector<uint8>::size_type size_type; + +public: + MessageBuffer() : _wpos(0), _storage() { } + + MessageBuffer(MessageBuffer const& right) : _wpos(right._wpos), _storage(right._storage) { } + + MessageBuffer(MessageBuffer&& right) : _wpos(right._wpos), _storage(right.Move()) { } + + void Reset() + { + _storage.clear(); + _wpos = 0; + } + + bool IsMessageReady() const { return _wpos == _storage.size(); } + + size_type GetMissingSize() const { return _storage.size() - _wpos; } + + uint8* Data() { return _storage.data(); } + + void Grow(size_type bytes) + { + _storage.resize(_storage.size() + bytes); + } + + uint8* GetWritePointer() { return &_storage[_wpos]; } + + void WriteCompleted(size_type bytes) { _wpos += bytes; } + + void ResetWritePointer() { _wpos = 0; } + + size_type GetSize() { return _storage.size(); } + + std::vector<uint8>&& Move() + { + _wpos = 0; + return std::move(_storage); + } + + MessageBuffer& operator=(MessageBuffer& right) + { + if (this != &right) + { + _wpos = right._wpos; + _storage = right._storage; + } + + return *this; + } + + MessageBuffer& operator=(MessageBuffer&& right) + { + if (this != &right) + { + _wpos = right._wpos; + _storage = right.Move(); + } + + return *this; + } + +private: + size_type _wpos; + std::vector<uint8> _storage; +}; + +#endif /* __MESSAGEBUFFER_H_ */ diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index 6bf67e06d9c..f86890ed7ef 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -18,8 +18,9 @@ #ifndef __SOCKET_H__ #define __SOCKET_H__ -#include "Define.h" +#include "MessageBuffer.h" #include "Log.h" +#include <atomic> #include <vector> #include <mutex> #include <queue> @@ -28,19 +29,22 @@ #include <type_traits> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/write.hpp> +#include <boost/asio/read.hpp> using boost::asio::ip::tcp; +#define READ_BLOCK_SIZE 4096 + template<class T, class PacketType> class Socket : public std::enable_shared_from_this<T> { typedef typename std::conditional<std::is_pointer<PacketType>::value, PacketType, PacketType const&>::type WritePacketType; public: - Socket(tcp::socket&& socket, std::size_t headerSize) : _socket(std::move(socket)), _headerSize(headerSize) + Socket(tcp::socket&& socket, std::size_t headerSize) : _socket(std::move(socket)), _remoteAddress(_socket.remote_endpoint().address()), + _remotePort(_socket.remote_endpoint().port()), _readHeaderBuffer(), _readDataBuffer(), _closed(false) { - _remotePort = _socket.remote_endpoint().port(); - _remoteAddress = _socket.remote_endpoint().address(); + _readHeaderBuffer.Grow(headerSize); } virtual void Start() = 0; @@ -57,25 +61,39 @@ public: void AsyncReadHeader() { - _socket.async_read_some(boost::asio::buffer(_readBuffer, _headerSize), std::bind(&Socket<T, PacketType>::ReadHeaderHandlerInternal, this->shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + _readHeaderBuffer.ResetWritePointer(); + _readDataBuffer.Reset(); + + AsyncReadMissingHeaderData(); } - void AsyncReadData(std::size_t size, std::size_t bufferOffset) + void AsyncReadData(std::size_t size) { - _socket.async_read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size), std::bind(&Socket<T, PacketType>::ReadDataHandlerInternal, this->shared_from_this(), - std::placeholders::_1, std::placeholders::_2)); + if (!size) + { + // if this is a packet with 0 length body just invoke handler directly + ReadDataHandler(); + return; + } + + _readDataBuffer.Grow(size); + AsyncReadMissingData(); } - void ReadData(std::size_t size, std::size_t bufferOffset) + void ReadData(std::size_t size) { boost::system::error_code error; - _socket.read_some(boost::asio::buffer(&_readBuffer[bufferOffset], size), error); + _readDataBuffer.Grow(size); - if (error) + std::size_t bytesRead = boost::asio::read(_socket, boost::asio::buffer(_readDataBuffer.GetWritePointer(), size), error); + + _readDataBuffer.WriteCompleted(bytesRead); + + if (error || !_readDataBuffer.IsMessageReady()) { - TC_LOG_DEBUG("network", "Socket::ReadData: %s errored with: %i (%s)", GetRemoteIpAddress().to_string().c_str(), error.value(), error.message().c_str()); + TC_LOG_DEBUG("network", "Socket::ReadData: %s errored with: %i (%s)", GetRemoteIpAddress().to_string().c_str(), error.value(), + error.message().c_str()); CloseSocket(); } @@ -83,18 +101,22 @@ public: void AsyncWrite(WritePacketType data) { - boost::asio::async_write(_socket, boost::asio::buffer(data), std::bind(&Socket<T, PacketType>::WriteHandler, this->shared_from_this(), std::placeholders::_1, - std::placeholders::_2)); + boost::asio::async_write(_socket, boost::asio::buffer(data), std::bind(&Socket<T, PacketType>::WriteHandler, this->shared_from_this(), + std::placeholders::_1, std::placeholders::_2)); } - bool IsOpen() const { return _socket.is_open(); } + bool IsOpen() const { return !_closed; } + void CloseSocket() { + if (_closed.exchange(true)) + return; + boost::system::error_code shutdownError; _socket.shutdown(boost::asio::socket_base::shutdown_both, shutdownError); if (shutdownError) TC_LOG_DEBUG("network", "Socket::CloseSocket: %s errored when shutting down socket: %i (%s)", GetRemoteIpAddress().to_string().c_str(), - shutdownError.value(), shutdownError.message().c_str()); + shutdownError.value(), shutdownError.message().c_str()); boost::system::error_code error; _socket.close(error); @@ -103,18 +125,72 @@ public: error.value(), error.message().c_str()); } - uint8* GetReadBuffer() { return _readBuffer; } + virtual bool IsHeaderReady() const { return _readHeaderBuffer.IsMessageReady(); } + virtual bool IsDataReady() const { return _readDataBuffer.IsMessageReady(); } + + uint8* GetHeaderBuffer() { return _readHeaderBuffer.Data(); } + uint8* GetDataBuffer() { return _readDataBuffer.Data(); } + + MessageBuffer&& MoveHeader() { return std::move(_readHeaderBuffer); } + MessageBuffer&& MoveData() { return std::move(_readDataBuffer); } protected: - virtual void ReadHeaderHandler(boost::system::error_code error, size_t transferedBytes) = 0; - virtual void ReadDataHandler(boost::system::error_code error, size_t transferedBytes) = 0; + virtual void ReadHeaderHandler() = 0; + virtual void ReadDataHandler() = 0; std::mutex _writeLock; std::queue<PacketType> _writeQueue; private: - void ReadHeaderHandlerInternal(boost::system::error_code error, size_t transferedBytes) { ReadHeaderHandler(error, transferedBytes); } - void ReadDataHandlerInternal(boost::system::error_code error, size_t transferedBytes) { ReadDataHandler(error, transferedBytes); } + void AsyncReadMissingHeaderData() + { + _socket.async_read_some(boost::asio::buffer(_readHeaderBuffer.GetWritePointer(), std::min<std::size_t>(READ_BLOCK_SIZE, _readHeaderBuffer.GetMissingSize())), + std::bind(&Socket<T, PacketType>::ReadHeaderHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + } + + void AsyncReadMissingData() + { + _socket.async_read_some(boost::asio::buffer(_readDataBuffer.GetWritePointer(), std::min<std::size_t>(READ_BLOCK_SIZE, _readDataBuffer.GetMissingSize())), + std::bind(&Socket<T, PacketType>::ReadDataHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + } + + void ReadHeaderHandlerInternal(boost::system::error_code error, size_t transferredBytes) + { + if (error) + { + CloseSocket(); + return; + } + + _readHeaderBuffer.WriteCompleted(transferredBytes); + if (!IsHeaderReady()) + { + // incomplete, read more + AsyncReadMissingHeaderData(); + return; + } + + ReadHeaderHandler(); + } + + void ReadDataHandlerInternal(boost::system::error_code error, size_t transferredBytes) + { + if (error) + { + CloseSocket(); + return; + } + + _readDataBuffer.WriteCompleted(transferredBytes); + if (!IsDataReady()) + { + // incomplete, read more + AsyncReadMissingData(); + return; + } + + ReadDataHandler(); + } void WriteHandler(boost::system::error_code error, size_t /*transferedBytes*/) { @@ -140,12 +216,13 @@ private: tcp::socket _socket; - uint8 _readBuffer[4096]; - - uint16 _remotePort; boost::asio::ip::address _remoteAddress; + uint16 _remotePort; + + MessageBuffer _readHeaderBuffer; + MessageBuffer _readDataBuffer; - std::size_t _headerSize; + std::atomic<bool> _closed; }; #endif // __SOCKET_H__ diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp index 86234039a4a..3785d1c29fa 100644 --- a/src/server/shared/Packets/ByteBuffer.cpp +++ b/src/server/shared/Packets/ByteBuffer.cpp @@ -17,11 +17,16 @@ */ #include "ByteBuffer.h" +#include "MessageBuffer.h" #include "Common.h" #include "Log.h" #include <sstream> +ByteBuffer::ByteBuffer(MessageBuffer&& buffer) : _rpos(0), _wpos(0), _storage(buffer.Move()) +{ +} + ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize) { diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index c678e9dce06..456223d744d 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -34,6 +34,8 @@ #include <math.h> #include <boost/asio/buffer.hpp> +class MessageBuffer; + // Root of ByteBuffer exception hierarchy class ByteBufferException : public std::exception { @@ -82,14 +84,12 @@ class ByteBuffer } ByteBuffer(ByteBuffer&& buf) : _rpos(buf._rpos), _wpos(buf._wpos), - _storage(std::move(buf._storage)) - { - } + _storage(std::move(buf._storage)) { } ByteBuffer(ByteBuffer const& right) : _rpos(right._rpos), _wpos(right._wpos), - _storage(right._storage) - { - } + _storage(right._storage) { } + + ByteBuffer(MessageBuffer&& buffer); ByteBuffer& operator=(ByteBuffer const& right) { diff --git a/src/server/shared/Packets/WorldPacket.h b/src/server/shared/Packets/WorldPacket.h index 8851b9f3e45..848a00739fe 100644 --- a/src/server/shared/Packets/WorldPacket.h +++ b/src/server/shared/Packets/WorldPacket.h @@ -51,6 +51,8 @@ class WorldPacket : public ByteBuffer return *this; } + WorldPacket(uint16 opcode, MessageBuffer&& buffer) : ByteBuffer(std::move(buffer)), m_opcode(opcode) { } + void Initialize(uint16 opcode, size_t newres=200) { clear(); diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 3afa9e84e8b..2c393215f7d 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -87,6 +87,7 @@ bool StartDB(); void StopDB(); void WorldUpdateLoop(); void ClearOnlineAccounts(); +void ShutdownThreadPool(std::vector<std::thread>& threadPool); variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service); /// Launch the Trinity server @@ -179,7 +180,10 @@ extern int main(int argc, char** argv) // Start the databases if (!StartDB()) + { + ShutdownThreadPool(threadPool); return 1; + } // Set server offline (not connectable) LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmID); @@ -236,13 +240,7 @@ extern int main(int argc, char** argv) WorldUpdateLoop(); // Shutdown starts here - - _ioService.stop(); - - for (auto& thread : threadPool) - { - thread.join(); - } + ShutdownThreadPool(threadPool); sScriptMgr->OnShutdown(); @@ -281,41 +279,7 @@ extern int main(int argc, char** argv) if (cliThread != nullptr) { #ifdef _WIN32 - - // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API) - //_exit(1); - // send keyboard input to safely unblock the CLI thread - INPUT_RECORD b[4]; - HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); - b[0].EventType = KEY_EVENT; - b[0].Event.KeyEvent.bKeyDown = TRUE; - b[0].Event.KeyEvent.uChar.AsciiChar = 'X'; - b[0].Event.KeyEvent.wVirtualKeyCode = 'X'; - b[0].Event.KeyEvent.wRepeatCount = 1; - - b[1].EventType = KEY_EVENT; - b[1].Event.KeyEvent.bKeyDown = FALSE; - b[1].Event.KeyEvent.uChar.AsciiChar = 'X'; - b[1].Event.KeyEvent.wVirtualKeyCode = 'X'; - b[1].Event.KeyEvent.wRepeatCount = 1; - - b[2].EventType = KEY_EVENT; - b[2].Event.KeyEvent.bKeyDown = TRUE; - b[2].Event.KeyEvent.dwControlKeyState = 0; - b[2].Event.KeyEvent.uChar.AsciiChar = '\r'; - b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; - b[2].Event.KeyEvent.wRepeatCount = 1; - b[2].Event.KeyEvent.wVirtualScanCode = 0x1c; - - b[3].EventType = KEY_EVENT; - b[3].Event.KeyEvent.bKeyDown = FALSE; - b[3].Event.KeyEvent.dwControlKeyState = 0; - b[3].Event.KeyEvent.uChar.AsciiChar = '\r'; - b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; - b[3].Event.KeyEvent.wVirtualScanCode = 0x1c; - b[3].Event.KeyEvent.wRepeatCount = 1; - DWORD numb; - WriteConsoleInput(hStdIn, b, 4, &numb); + CancelSynchronousIo(cliThread->native_handle()); #endif cliThread->join(); delete cliThread; @@ -330,6 +294,15 @@ extern int main(int argc, char** argv) return World::GetExitCode(); } +void ShutdownThreadPool(std::vector<std::thread>& threadPool) +{ + _ioService.stop(); + + for (auto& thread : threadPool) + { + thread.join(); + } +} void WorldUpdateLoop() { diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 3e2025dace8..c2ca184905e 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -276,7 +276,7 @@ int main(int argc, char** argv) } if (!checkDirectories(debugOutput)) - return silent ? -3 : finish("Press any key to close...", -3); + return silent ? -3 : finish("Press ENTER to close...", -3); MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, debugOutput, bigBaseUnit, offMeshInputPath); |
