diff options
445 files changed, 48697 insertions, 14936 deletions
diff --git a/apps/db_pendings/import.sh b/apps/db_pendings/import.sh index 970d762838..ebbff1bbca 100644 --- a/apps/db_pendings/import.sh +++ b/apps/db_pendings/import.sh @@ -79,9 +79,11 @@ function import() { echo "--" >> "$newFile"; echo "-- START UPDATING QUERIES" >> "$newFile"; echo "--" >> "$newFile"; + echo "" >> "$newFile"; cat $entry >> "$newFile"; + echo "" >> "$newFile"; echo "--" >> "$newFile"; echo "-- END UPDATING QUERIES" >> "$newFile"; echo "--" >> "$newFile"; @@ -89,8 +91,7 @@ function import() { echo "$endTransaction" >> "$newFile"; if [[ $isRev -eq 1 ]]; then - echo "END;" >> "$newFile"; - echo "//" >> "$newFile"; + echo "END //" >> "$newFile"; echo "DELIMITER ;" >> "$newFile"; echo "CALL updateDb();" >> "$newFile"; echo "DROP PROCEDURE IF EXISTS \`updateDb\`;" >> "$newFile"; diff --git a/data/sql/updates/db_auth/2016_11_18_00.sql b/data/sql/updates/db_auth/2016_11_18_00.sql index 86c8463975..4db79713b5 100644 --- a/data/sql/updates/db_auth/2016_11_18_00.sql +++ b/data/sql/updates/db_auth/2016_11_18_00.sql @@ -15,8 +15,7 @@ ALTER TABLE version_db_auth CHANGE COLUMN 2016_09_04_00 2016_11_18_00 bit; -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_auth/2016_11_19_00.sql b/data/sql/updates/db_auth/2016_11_19_00.sql index fb61724774..ce1003ba62 100644 --- a/data/sql/updates/db_auth/2016_11_19_00.sql +++ b/data/sql/updates/db_auth/2016_11_19_00.sql @@ -26,8 +26,7 @@ ALTER TABLE `account` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_auth/2017_08_19_00.sql b/data/sql/updates/db_auth/2017_08_19_00.sql index 82afc22384..7ec7a62520 100644 --- a/data/sql/updates/db_auth/2017_08_19_00.sql +++ b/data/sql/updates/db_auth/2017_08_19_00.sql @@ -22,8 +22,7 @@ ALTER TABLE `account` CHANGE `expansion` `expansion` TINYINT(3) UNSIGNED DEFAULT -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_auth/2017_08_20_01.sql b/data/sql/updates/db_auth/2017_08_20_01.sql index 84597197a6..12b09a746c 100644 --- a/data/sql/updates/db_auth/2017_08_20_01.sql +++ b/data/sql/updates/db_auth/2017_08_20_01.sql @@ -38,8 +38,7 @@ CREATE TABLE `ip2nationCountries` ( -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_auth/2017_12_05_00.sql b/data/sql/updates/db_auth/2017_12_05_00.sql new file mode 100644 index 0000000000..6fd5b75ac9 --- /dev/null +++ b/data/sql/updates/db_auth/2017_12_05_00.sql @@ -0,0 +1,35 @@ +-- DB update 2017_08_20_01 -> 2017_12_05_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_auth' AND COLUMN_NAME = '2017_08_20_01'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_auth CHANGE COLUMN 2017_08_20_01 2017_12_05_00 bit; +SELECT sql_rev INTO OK FROM version_db_auth WHERE sql_rev = '1511238042597856200'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- + +INSERT INTO version_db_auth (`sql_rev`) VALUES ('1511238042597856200'); +DROP TABLE IF EXISTS `uptime`; + +CREATE TABLE `uptime` ( + `realmid` int(10) unsigned NOT NULL, + `starttime` int(10) unsigned NOT NULL DEFAULT '0', + `uptime` int(10) unsigned NOT NULL DEFAULT '0', + `maxplayers` smallint(5) unsigned NOT NULL DEFAULT '0', + `revision` varchar(255) NOT NULL DEFAULT 'AzerothCore', + PRIMARY KEY (`realmid`,`starttime`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Uptime system'; +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_characters/2016_11_18_00.sql b/data/sql/updates/db_characters/2016_11_18_00.sql index 587cd291db..306aab53ce 100644 --- a/data/sql/updates/db_characters/2016_11_18_00.sql +++ b/data/sql/updates/db_characters/2016_11_18_00.sql @@ -15,8 +15,7 @@ ALTER TABLE version_db_characters CHANGE COLUMN 2016_08_25_00 2016_11_18_00 bit; -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_characters/2016_11_19_00.sql b/data/sql/updates/db_characters/2016_11_19_00.sql index dc9722fc99..d4d082b00c 100644 --- a/data/sql/updates/db_characters/2016_11_19_00.sql +++ b/data/sql/updates/db_characters/2016_11_19_00.sql @@ -22,8 +22,7 @@ ALTER TABLE `arena_team_member` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_characters/2017_09_18_00.sql b/data/sql/updates/db_characters/2017_09_18_00.sql index 19b71d4fd5..c25a8537ba 100644 --- a/data/sql/updates/db_characters/2017_09_18_00.sql +++ b/data/sql/updates/db_characters/2017_09_18_00.sql @@ -41,8 +41,7 @@ CREATE TABLE `banned_addons` ( -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2016_11_18_00.sql b/data/sql/updates/db_world/2016_11_18_00.sql index 6e3b5091dd..ae80b7e0ad 100644 --- a/data/sql/updates/db_world/2016_11_18_00.sql +++ b/data/sql/updates/db_world/2016_11_18_00.sql @@ -16,8 +16,7 @@ ALTER TABLE version_db_world CHANGE COLUMN 2016_11_06_02 2016_11_18_00 bit; -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2016_11_19_00.sql b/data/sql/updates/db_world/2016_11_19_00.sql index 614bca34dc..4b41d548be 100644 --- a/data/sql/updates/db_world/2016_11_19_00.sql +++ b/data/sql/updates/db_world/2016_11_19_00.sql @@ -20,8 +20,7 @@ UPDATE `quest_template` SET `SpecialFlags` = "0", `RequiredItemId1` = "31811", ` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2016_11_26_00.sql b/data/sql/updates/db_world/2016_11_26_00.sql index ec0eb6c22f..afa22b78be 100644 --- a/data/sql/updates/db_world/2016_11_26_00.sql +++ b/data/sql/updates/db_world/2016_11_26_00.sql @@ -23,8 +23,7 @@ INSERT INTO trinity_string(`entry`,`content_default`,`content_loc6`,`content_loc -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2016_11_26_01.sql b/data/sql/updates/db_world/2016_11_26_01.sql index 5dfc29629c..d903dea906 100644 --- a/data/sql/updates/db_world/2016_11_26_01.sql +++ b/data/sql/updates/db_world/2016_11_26_01.sql @@ -63,8 +63,7 @@ ALTER TABLE `gameobject_template` DROP `questItem1`, DROP `questItem2`, DROP `qu -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2016_12_02_00.sql b/data/sql/updates/db_world/2016_12_02_00.sql index 1ffbc6b981..2e87b2c407 100644 --- a/data/sql/updates/db_world/2016_12_02_00.sql +++ b/data/sql/updates/db_world/2016_12_02_00.sql @@ -12398,8 +12398,7 @@ UPDATE `creature_text` SET `BroadcastTextID`='8388' WHERE `entry`=4489 AND `grou UPDATE `creature_text` SET `BroadcastTextID`='8393' WHERE `entry`=4489 AND `groupid`=4 AND `id`=0; COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_00.sql b/data/sql/updates/db_world/2017_01_24_00.sql index 6abae0204e..42ff301ed5 100644 --- a/data/sql/updates/db_world/2017_01_24_00.sql +++ b/data/sql/updates/db_world/2017_01_24_00.sql @@ -20,8 +20,7 @@ UPDATE `creature_text` SET `text` = "$N! I'm watching you!" WHERE `entry` = "113 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_01.sql b/data/sql/updates/db_world/2017_01_24_01.sql index e036ec3cb6..8f0ee91453 100644 --- a/data/sql/updates/db_world/2017_01_24_01.sql +++ b/data/sql/updates/db_world/2017_01_24_01.sql @@ -25,8 +25,7 @@ INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_ -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_02.sql b/data/sql/updates/db_world/2017_01_24_02.sql index ce3f960848..bc8a7d46ed 100644 --- a/data/sql/updates/db_world/2017_01_24_02.sql +++ b/data/sql/updates/db_world/2017_01_24_02.sql @@ -72,8 +72,7 @@ ALTER TABLE `quest_template` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_03.sql b/data/sql/updates/db_world/2017_01_24_03.sql index c10cf59416..2e98dda4bc 100644 --- a/data/sql/updates/db_world/2017_01_24_03.sql +++ b/data/sql/updates/db_world/2017_01_24_03.sql @@ -19,8 +19,7 @@ DELETE FROM `disables` WHERE `entry` = "532";-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_04.sql b/data/sql/updates/db_world/2017_01_24_04.sql index fb44848f7e..d23749d4ce 100644 --- a/data/sql/updates/db_world/2017_01_24_04.sql +++ b/data/sql/updates/db_world/2017_01_24_04.sql @@ -51,8 +51,7 @@ ALTER TABLE `quest_template` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_05.sql b/data/sql/updates/db_world/2017_01_24_05.sql index d3d8560a17..cd071978ad 100644 --- a/data/sql/updates/db_world/2017_01_24_05.sql +++ b/data/sql/updates/db_world/2017_01_24_05.sql @@ -29,8 +29,7 @@ INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `modelid` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_01_24_06.sql b/data/sql/updates/db_world/2017_01_24_06.sql index 26f5f639df..7cdbdc449a 100644 --- a/data/sql/updates/db_world/2017_01_24_06.sql +++ b/data/sql/updates/db_world/2017_01_24_06.sql @@ -82,8 +82,7 @@ INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_00.sql b/data/sql/updates/db_world/2017_02_03_00.sql index 4cbcd6ba5a..2b5da6dfc5 100644 --- a/data/sql/updates/db_world/2017_02_03_00.sql +++ b/data/sql/updates/db_world/2017_02_03_00.sql @@ -19,8 +19,7 @@ UPDATE `creature` SET `MovementType` = 1, `spawndist` = 10 WHERE `guid` IN (197 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_01.sql b/data/sql/updates/db_world/2017_02_03_01.sql index 411cabea89..12ec44437c 100644 --- a/data/sql/updates/db_world/2017_02_03_01.sql +++ b/data/sql/updates/db_world/2017_02_03_01.sql @@ -21,8 +21,7 @@ INSERT INTO `disables` (`sourceType`,`entry`,`flags`,`params_0`,`params_1`,`comm -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_02.sql b/data/sql/updates/db_world/2017_02_03_02.sql index f0ddc25ded..d505d2bf17 100644 --- a/data/sql/updates/db_world/2017_02_03_02.sql +++ b/data/sql/updates/db_world/2017_02_03_02.sql @@ -29,8 +29,7 @@ INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_03.sql b/data/sql/updates/db_world/2017_02_03_03.sql index fe44fb5ec0..e70ca064f9 100644 --- a/data/sql/updates/db_world/2017_02_03_03.sql +++ b/data/sql/updates/db_world/2017_02_03_03.sql @@ -77,8 +77,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_04.sql b/data/sql/updates/db_world/2017_02_03_04.sql index 410167122b..74f174262a 100644 --- a/data/sql/updates/db_world/2017_02_03_04.sql +++ b/data/sql/updates/db_world/2017_02_03_04.sql @@ -149,8 +149,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_05.sql b/data/sql/updates/db_world/2017_02_03_05.sql index b0f2452fb1..5bda6976bf 100644 --- a/data/sql/updates/db_world/2017_02_03_05.sql +++ b/data/sql/updates/db_world/2017_02_03_05.sql @@ -130,8 +130,7 @@ UPDATE `waypoint_data` SET `action_chance`=100 WHERE `action` IN (@SCRIPTID); -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_06.sql b/data/sql/updates/db_world/2017_02_03_06.sql index a3b20e0b1d..dd4d3072bb 100644 --- a/data/sql/updates/db_world/2017_02_03_06.sql +++ b/data/sql/updates/db_world/2017_02_03_06.sql @@ -24,8 +24,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_07.sql b/data/sql/updates/db_world/2017_02_03_07.sql index 5b6c524542..c5d36ef27c 100644 --- a/data/sql/updates/db_world/2017_02_03_07.sql +++ b/data/sql/updates/db_world/2017_02_03_07.sql @@ -58,8 +58,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_08.sql b/data/sql/updates/db_world/2017_02_03_08.sql index 99ca6a503c..208a3ceb2e 100644 --- a/data/sql/updates/db_world/2017_02_03_08.sql +++ b/data/sql/updates/db_world/2017_02_03_08.sql @@ -45,8 +45,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_09.sql b/data/sql/updates/db_world/2017_02_03_09.sql index 7cddaa255b..935ca7ff82 100644 --- a/data/sql/updates/db_world/2017_02_03_09.sql +++ b/data/sql/updates/db_world/2017_02_03_09.sql @@ -116,8 +116,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_10.sql b/data/sql/updates/db_world/2017_02_03_10.sql index 9598c821c3..06721f3977 100644 --- a/data/sql/updates/db_world/2017_02_03_10.sql +++ b/data/sql/updates/db_world/2017_02_03_10.sql @@ -53,8 +53,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_11.sql b/data/sql/updates/db_world/2017_02_03_11.sql index 73291503db..f5cec8fa6f 100644 --- a/data/sql/updates/db_world/2017_02_03_11.sql +++ b/data/sql/updates/db_world/2017_02_03_11.sql @@ -46,8 +46,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_12.sql b/data/sql/updates/db_world/2017_02_03_12.sql index 394bbed7ab..1858d6dbf1 100644 --- a/data/sql/updates/db_world/2017_02_03_12.sql +++ b/data/sql/updates/db_world/2017_02_03_12.sql @@ -59,8 +59,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_13.sql b/data/sql/updates/db_world/2017_02_03_13.sql index ace4105ede..a90f8ce0f6 100644 --- a/data/sql/updates/db_world/2017_02_03_13.sql +++ b/data/sql/updates/db_world/2017_02_03_13.sql @@ -143,8 +143,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_14.sql b/data/sql/updates/db_world/2017_02_03_14.sql index e2987251da..8f0a0c785c 100644 --- a/data/sql/updates/db_world/2017_02_03_14.sql +++ b/data/sql/updates/db_world/2017_02_03_14.sql @@ -78,8 +78,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_15.sql b/data/sql/updates/db_world/2017_02_03_15.sql index 91b8be674e..2d32baff30 100644 --- a/data/sql/updates/db_world/2017_02_03_15.sql +++ b/data/sql/updates/db_world/2017_02_03_15.sql @@ -184,8 +184,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_16.sql b/data/sql/updates/db_world/2017_02_03_16.sql index 7d11ce0eaf..c162f7c782 100644 --- a/data/sql/updates/db_world/2017_02_03_16.sql +++ b/data/sql/updates/db_world/2017_02_03_16.sql @@ -109,8 +109,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_17.sql b/data/sql/updates/db_world/2017_02_03_17.sql index 8ddb4c9514..54238647ee 100644 --- a/data/sql/updates/db_world/2017_02_03_17.sql +++ b/data/sql/updates/db_world/2017_02_03_17.sql @@ -143,8 +143,7 @@ UPDATE `waypoint_data` SET `action_chance`=100 WHERE `action` BETWEEN @SCTIPT_ID -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_18.sql b/data/sql/updates/db_world/2017_02_03_18.sql index f2fa2e3d7a..cc98fc5a73 100644 --- a/data/sql/updates/db_world/2017_02_03_18.sql +++ b/data/sql/updates/db_world/2017_02_03_18.sql @@ -102,8 +102,7 @@ UPDATE `waypoint_data` SET `move_type`=1 WHERE `id`=@PATH;-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_19.sql b/data/sql/updates/db_world/2017_02_03_19.sql index ca71ab29e9..03a131e3f4 100644 --- a/data/sql/updates/db_world/2017_02_03_19.sql +++ b/data/sql/updates/db_world/2017_02_03_19.sql @@ -135,8 +135,7 @@ UPDATE `waypoint_data` SET `action_chance`=100 WHERE `action` BETWEEN @SCRIPTID+ -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_20.sql b/data/sql/updates/db_world/2017_02_03_20.sql index b34cb9da60..8db2b86db6 100644 --- a/data/sql/updates/db_world/2017_02_03_20.sql +++ b/data/sql/updates/db_world/2017_02_03_20.sql @@ -165,8 +165,7 @@ UPDATE `waypoint_data` SET `action_chance`=100 WHERE `action` IN (@SCRIPTID);-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_21.sql b/data/sql/updates/db_world/2017_02_03_21.sql index af771deb97..ff45269ace 100644 --- a/data/sql/updates/db_world/2017_02_03_21.sql +++ b/data/sql/updates/db_world/2017_02_03_21.sql @@ -159,8 +159,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_22.sql b/data/sql/updates/db_world/2017_02_03_22.sql index 0ef4ab7bad..ac148ef114 100644 --- a/data/sql/updates/db_world/2017_02_03_22.sql +++ b/data/sql/updates/db_world/2017_02_03_22.sql @@ -73,8 +73,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_23.sql b/data/sql/updates/db_world/2017_02_03_23.sql index 3b5006e6f5..e98dcda9a1 100644 --- a/data/sql/updates/db_world/2017_02_03_23.sql +++ b/data/sql/updates/db_world/2017_02_03_23.sql @@ -185,8 +185,7 @@ INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_24.sql b/data/sql/updates/db_world/2017_02_03_24.sql index 52c2fb7eac..b8699a2d17 100644 --- a/data/sql/updates/db_world/2017_02_03_24.sql +++ b/data/sql/updates/db_world/2017_02_03_24.sql @@ -108,8 +108,7 @@ INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`pr -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_25.sql b/data/sql/updates/db_world/2017_02_03_25.sql index d1e3f812d5..a585700d7f 100644 --- a/data/sql/updates/db_world/2017_02_03_25.sql +++ b/data/sql/updates/db_world/2017_02_03_25.sql @@ -59,8 +59,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_26.sql b/data/sql/updates/db_world/2017_02_03_26.sql index 7c3f6ffb31..136684a565 100644 --- a/data/sql/updates/db_world/2017_02_03_26.sql +++ b/data/sql/updates/db_world/2017_02_03_26.sql @@ -53,8 +53,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_27.sql b/data/sql/updates/db_world/2017_02_03_27.sql index 4af6377086..11a747016a 100644 --- a/data/sql/updates/db_world/2017_02_03_27.sql +++ b/data/sql/updates/db_world/2017_02_03_27.sql @@ -45,8 +45,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_28.sql b/data/sql/updates/db_world/2017_02_03_28.sql index cad87486c3..27d6594baf 100644 --- a/data/sql/updates/db_world/2017_02_03_28.sql +++ b/data/sql/updates/db_world/2017_02_03_28.sql @@ -51,8 +51,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_29.sql b/data/sql/updates/db_world/2017_02_03_29.sql index c5cf0f67cc..7313d8e79a 100644 --- a/data/sql/updates/db_world/2017_02_03_29.sql +++ b/data/sql/updates/db_world/2017_02_03_29.sql @@ -54,8 +54,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_30.sql b/data/sql/updates/db_world/2017_02_03_30.sql index ba443c88a5..4e38c33e5e 100644 --- a/data/sql/updates/db_world/2017_02_03_30.sql +++ b/data/sql/updates/db_world/2017_02_03_30.sql @@ -49,8 +49,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_31.sql b/data/sql/updates/db_world/2017_02_03_31.sql index 50505cadc3..baf0954ea9 100644 --- a/data/sql/updates/db_world/2017_02_03_31.sql +++ b/data/sql/updates/db_world/2017_02_03_31.sql @@ -92,8 +92,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_32.sql b/data/sql/updates/db_world/2017_02_03_32.sql index cde3f5176e..f8832565e8 100644 --- a/data/sql/updates/db_world/2017_02_03_32.sql +++ b/data/sql/updates/db_world/2017_02_03_32.sql @@ -89,8 +89,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_33.sql b/data/sql/updates/db_world/2017_02_03_33.sql index 70c9bfe2f2..f7507a7af4 100644 --- a/data/sql/updates/db_world/2017_02_03_33.sql +++ b/data/sql/updates/db_world/2017_02_03_33.sql @@ -65,8 +65,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_34.sql b/data/sql/updates/db_world/2017_02_03_34.sql index 3a06493522..fdaf66d2d2 100644 --- a/data/sql/updates/db_world/2017_02_03_34.sql +++ b/data/sql/updates/db_world/2017_02_03_34.sql @@ -172,8 +172,7 @@ INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_35.sql b/data/sql/updates/db_world/2017_02_03_35.sql index 6ffcf8e168..5ef6f5800b 100644 --- a/data/sql/updates/db_world/2017_02_03_35.sql +++ b/data/sql/updates/db_world/2017_02_03_35.sql @@ -81,8 +81,7 @@ UPDATE `waypoint_data` SET `action_chance`=100 WHERE `action` IN (@SCRIPTID);-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_36.sql b/data/sql/updates/db_world/2017_02_03_36.sql index b6467efc9a..9d41ab7fd6 100644 --- a/data/sql/updates/db_world/2017_02_03_36.sql +++ b/data/sql/updates/db_world/2017_02_03_36.sql @@ -23,8 +23,7 @@ INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spe -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_37.sql b/data/sql/updates/db_world/2017_02_03_37.sql index 9b65040c16..3b97a93638 100644 --- a/data/sql/updates/db_world/2017_02_03_37.sql +++ b/data/sql/updates/db_world/2017_02_03_37.sql @@ -30,8 +30,7 @@ INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spe -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_38.sql b/data/sql/updates/db_world/2017_02_03_38.sql index 97d5079127..8c994ffb9b 100644 --- a/data/sql/updates/db_world/2017_02_03_38.sql +++ b/data/sql/updates/db_world/2017_02_03_38.sql @@ -18,8 +18,7 @@ DELETE FROM `creature_loot_template` WHERE `item` = 23612 AND `entry` IN (21060, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_39.sql b/data/sql/updates/db_world/2017_02_03_39.sql index 1447ba9846..03b7932448 100644 --- a/data/sql/updates/db_world/2017_02_03_39.sql +++ b/data/sql/updates/db_world/2017_02_03_39.sql @@ -151,8 +151,7 @@ UPDATE `creature` SET `SpawnDist` = 0, `MovementType` = 0 WHERE `guid` IN (79369 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_40.sql b/data/sql/updates/db_world/2017_02_03_40.sql index de109344fe..fa51248d17 100644 --- a/data/sql/updates/db_world/2017_02_03_40.sql +++ b/data/sql/updates/db_world/2017_02_03_40.sql @@ -1879,8 +1879,7 @@ UPDATE `creature` SET `SpawnTimeSecs` = 180 WHERE `map` IN (560) AND id IN (2350 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_41.sql b/data/sql/updates/db_world/2017_02_03_41.sql index 9b0b2ceed3..31e717685d 100644 --- a/data/sql/updates/db_world/2017_02_03_41.sql +++ b/data/sql/updates/db_world/2017_02_03_41.sql @@ -146,8 +146,7 @@ UPDATE `gameobject` SET `spawntimesecs` = 10800 WHERE `guid` = 12029; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_42.sql b/data/sql/updates/db_world/2017_02_03_42.sql index 97e124c521..ee64bb6f8e 100644 --- a/data/sql/updates/db_world/2017_02_03_42.sql +++ b/data/sql/updates/db_world/2017_02_03_42.sql @@ -20,8 +20,7 @@ UPDATE `creature_template` SET `VehicleId`=244 WHERE `entry`=30236;-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_43.sql b/data/sql/updates/db_world/2017_02_03_43.sql index e06bc63dce..fe05901f00 100644 --- a/data/sql/updates/db_world/2017_02_03_43.sql +++ b/data/sql/updates/db_world/2017_02_03_43.sql @@ -23,8 +23,7 @@ UPDATE `creature_template` SET `speed_run` = 1.14286 WHERE `entry` IN (34657, 3 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_44.sql b/data/sql/updates/db_world/2017_02_03_44.sql index 3a8f46c113..c634f833eb 100644 --- a/data/sql/updates/db_world/2017_02_03_44.sql +++ b/data/sql/updates/db_world/2017_02_03_44.sql @@ -34,8 +34,7 @@ INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entr -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_45.sql b/data/sql/updates/db_world/2017_02_03_45.sql index fa170ce721..77f92100cb 100644 --- a/data/sql/updates/db_world/2017_02_03_45.sql +++ b/data/sql/updates/db_world/2017_02_03_45.sql @@ -20,8 +20,7 @@ UPDATE `creature_text` SET `emote` = "398", `duration` = "3000" WHERE `entry` = -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_46.sql b/data/sql/updates/db_world/2017_02_03_46.sql index 8b2e44eda8..dbb5d24570 100644 --- a/data/sql/updates/db_world/2017_02_03_46.sql +++ b/data/sql/updates/db_world/2017_02_03_46.sql @@ -21,8 +21,7 @@ INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_02_03_47.sql b/data/sql/updates/db_world/2017_02_03_47.sql index 117e84a0a0..5b5af06758 100644 --- a/data/sql/updates/db_world/2017_02_03_47.sql +++ b/data/sql/updates/db_world/2017_02_03_47.sql @@ -29,8 +29,7 @@ UPDATE `quest_template_addon` SET `SpecialFlags` = "2" WHERE `ID` = "10409";-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_00.sql b/data/sql/updates/db_world/2017_03_04_00.sql index 0ca83b078d..b0b395329b 100644 --- a/data/sql/updates/db_world/2017_03_04_00.sql +++ b/data/sql/updates/db_world/2017_03_04_00.sql @@ -29,8 +29,7 @@ INSERT INTO `creature_loot_template` (`entry`, `item`, `ChanceOrQuestChance`, `l -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_01.sql b/data/sql/updates/db_world/2017_03_04_01.sql index 2ca5a2c6eb..c06970b99f 100644 --- a/data/sql/updates/db_world/2017_03_04_01.sql +++ b/data/sql/updates/db_world/2017_03_04_01.sql @@ -20,8 +20,7 @@ UPDATE `creature` SET `modelid` = 24818 WHERE `guid` IN (117789);-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_02.sql b/data/sql/updates/db_world/2017_03_04_02.sql index 686c3250f6..a3cf9290e9 100644 --- a/data/sql/updates/db_world/2017_03_04_02.sql +++ b/data/sql/updates/db_world/2017_03_04_02.sql @@ -166,8 +166,7 @@ INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_03.sql b/data/sql/updates/db_world/2017_03_04_03.sql index fb9479b75e..e01067316e 100644 --- a/data/sql/updates/db_world/2017_03_04_03.sql +++ b/data/sql/updates/db_world/2017_03_04_03.sql @@ -40,8 +40,7 @@ INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_04.sql b/data/sql/updates/db_world/2017_03_04_04.sql index d16d150bb6..14c7b872aa 100644 --- a/data/sql/updates/db_world/2017_03_04_04.sql +++ b/data/sql/updates/db_world/2017_03_04_04.sql @@ -18,8 +18,7 @@ UPDATE `creature_addon` SET `bytes1`=0, `auras`=45787 WHERE `guid`=97150;-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_05.sql b/data/sql/updates/db_world/2017_03_04_05.sql index 6e81dd5dbe..f110eaa81a 100644 --- a/data/sql/updates/db_world/2017_03_04_05.sql +++ b/data/sql/updates/db_world/2017_03_04_05.sql @@ -21,8 +21,7 @@ INSERT INTO `spell_linked_spell` (`spell_trigger` ,`spell_effect`, `type`, `comm -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_06.sql b/data/sql/updates/db_world/2017_03_04_06.sql index 43e5433c54..14a411a77f 100644 --- a/data/sql/updates/db_world/2017_03_04_06.sql +++ b/data/sql/updates/db_world/2017_03_04_06.sql @@ -18,8 +18,7 @@ UPDATE `creature_addon` SET `auras`=55701 WHERE `guid`=100071;-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_07.sql b/data/sql/updates/db_world/2017_03_04_07.sql index 6eb20f0d7a..fabe9d3a63 100644 --- a/data/sql/updates/db_world/2017_03_04_07.sql +++ b/data/sql/updates/db_world/2017_03_04_07.sql @@ -20,8 +20,7 @@ UPDATE `creature_template` SET `flags_extra`=32768 WHERE `entry`=7980;-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_08.sql b/data/sql/updates/db_world/2017_03_04_08.sql index 66449f0a58..80309d44c4 100644 --- a/data/sql/updates/db_world/2017_03_04_08.sql +++ b/data/sql/updates/db_world/2017_03_04_08.sql @@ -59,8 +59,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_09.sql b/data/sql/updates/db_world/2017_03_04_09.sql index d8859cb073..1232392da5 100644 --- a/data/sql/updates/db_world/2017_03_04_09.sql +++ b/data/sql/updates/db_world/2017_03_04_09.sql @@ -20,8 +20,7 @@ UPDATE `item_template` SET `spellcooldown_1` = 30000 WHERE `entry` IN (44010); -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_10.sql b/data/sql/updates/db_world/2017_03_04_10.sql index 5525cf3815..d4c15f8d44 100644 --- a/data/sql/updates/db_world/2017_03_04_10.sql +++ b/data/sql/updates/db_world/2017_03_04_10.sql @@ -24,8 +24,7 @@ INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spe -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_11.sql b/data/sql/updates/db_world/2017_03_04_11.sql index c84ff8b6d8..6d7d8647ed 100644 --- a/data/sql/updates/db_world/2017_03_04_11.sql +++ b/data/sql/updates/db_world/2017_03_04_11.sql @@ -54,8 +54,7 @@ INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_12.sql b/data/sql/updates/db_world/2017_03_04_12.sql index 579defc725..675504e5f1 100644 --- a/data/sql/updates/db_world/2017_03_04_12.sql +++ b/data/sql/updates/db_world/2017_03_04_12.sql @@ -19,8 +19,7 @@ UPDATE `quest_template` SET `TimeAllowed` = 0 WHERE `id` IN(3364); -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_13.sql b/data/sql/updates/db_world/2017_03_04_13.sql index 03588bcd30..efe2c87789 100644 --- a/data/sql/updates/db_world/2017_03_04_13.sql +++ b/data/sql/updates/db_world/2017_03_04_13.sql @@ -63,8 +63,7 @@ INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_14.sql b/data/sql/updates/db_world/2017_03_04_14.sql index 9a20addd60..24e4222511 100644 --- a/data/sql/updates/db_world/2017_03_04_14.sql +++ b/data/sql/updates/db_world/2017_03_04_14.sql @@ -66,8 +66,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_15.sql b/data/sql/updates/db_world/2017_03_04_15.sql index 62fc9c6a73..bc34fc0d82 100644 --- a/data/sql/updates/db_world/2017_03_04_15.sql +++ b/data/sql/updates/db_world/2017_03_04_15.sql @@ -66,8 +66,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_16.sql b/data/sql/updates/db_world/2017_03_04_16.sql index 57ead3cb0b..b7da2a3d8a 100644 --- a/data/sql/updates/db_world/2017_03_04_16.sql +++ b/data/sql/updates/db_world/2017_03_04_16.sql @@ -20,8 +20,7 @@ UPDATE `creature` SET `map` = 47 WHERE `guid` = 84369 AND `id` = 4512; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_17.sql b/data/sql/updates/db_world/2017_03_04_17.sql index 47a935c746..e54c71418c 100644 --- a/data/sql/updates/db_world/2017_03_04_17.sql +++ b/data/sql/updates/db_world/2017_03_04_17.sql @@ -57,8 +57,7 @@ INSERT INTO `waypoint_data`(`id`,`point`,`position_x`,`position_y`,`position_z`, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_18.sql b/data/sql/updates/db_world/2017_03_04_18.sql index a65bfa7167..52afd91589 100644 --- a/data/sql/updates/db_world/2017_03_04_18.sql +++ b/data/sql/updates/db_world/2017_03_04_18.sql @@ -25,8 +25,7 @@ INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_19.sql b/data/sql/updates/db_world/2017_03_04_19.sql index 321c3efe54..ea6bff49ca 100644 --- a/data/sql/updates/db_world/2017_03_04_19.sql +++ b/data/sql/updates/db_world/2017_03_04_19.sql @@ -22,8 +22,7 @@ INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `modelid` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_03_04_20.sql b/data/sql/updates/db_world/2017_03_04_20.sql index 2d0dfc8227..5d434b678b 100644 --- a/data/sql/updates/db_world/2017_03_04_20.sql +++ b/data/sql/updates/db_world/2017_03_04_20.sql @@ -22,8 +22,7 @@ IF OK <> 'FALSE' THEN LEAVE proc; END IF; INSERT INTO version_db_world (`sql_rev`) VALUES ('1488633880780960000'); COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_00.sql b/data/sql/updates/db_world/2017_05_01_00.sql index 9cc13140c0..4ed2c1f4e2 100644 --- a/data/sql/updates/db_world/2017_05_01_00.sql +++ b/data/sql/updates/db_world/2017_05_01_00.sql @@ -166,8 +166,7 @@ INSERT INTO `npc_text` (`ID`, `text0_0`) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_01.sql b/data/sql/updates/db_world/2017_05_01_01.sql index 89f956e949..953c644ebc 100644 --- a/data/sql/updates/db_world/2017_05_01_01.sql +++ b/data/sql/updates/db_world/2017_05_01_01.sql @@ -37,8 +37,7 @@ INSERT INTO `command` (`name`,`security`,`help`) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_02.sql b/data/sql/updates/db_world/2017_05_01_02.sql index ec0a818882..a9f49e6282 100644 --- a/data/sql/updates/db_world/2017_05_01_02.sql +++ b/data/sql/updates/db_world/2017_05_01_02.sql @@ -35,8 +35,7 @@ INSERT INTO `item_loot_template` (`Entry`,`Item`,`ChanceOrQuestChance`,`LootMode -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_03.sql b/data/sql/updates/db_world/2017_05_01_03.sql index 84222f0150..e64a882304 100644 --- a/data/sql/updates/db_world/2017_05_01_03.sql +++ b/data/sql/updates/db_world/2017_05_01_03.sql @@ -29,8 +29,7 @@ DELETE FROM `gameobject` WHERE (id = 73941) AND (guid IN (14685)); -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_04.sql b/data/sql/updates/db_world/2017_05_01_04.sql index 7e84f2f201..1f8e3cc585 100644 --- a/data/sql/updates/db_world/2017_05_01_04.sql +++ b/data/sql/updates/db_world/2017_05_01_04.sql @@ -24,8 +24,7 @@ UPDATE `spell_proc` SET `Cooldown`=0 WHERE `SpellId`=64440; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_05.sql b/data/sql/updates/db_world/2017_05_01_05.sql index b22bb3ce6d..3f366d2fbe 100644 --- a/data/sql/updates/db_world/2017_05_01_05.sql +++ b/data/sql/updates/db_world/2017_05_01_05.sql @@ -82,8 +82,7 @@ INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_ -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_06.sql b/data/sql/updates/db_world/2017_05_01_06.sql index 407cbbd5ee..b5a1d92735 100644 --- a/data/sql/updates/db_world/2017_05_01_06.sql +++ b/data/sql/updates/db_world/2017_05_01_06.sql @@ -32,8 +32,7 @@ INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_01_07.sql b/data/sql/updates/db_world/2017_05_01_07.sql index 3b6406b963..63b88b6d25 100644 --- a/data/sql/updates/db_world/2017_05_01_07.sql +++ b/data/sql/updates/db_world/2017_05_01_07.sql @@ -28,8 +28,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_05_28_00.sql b/data/sql/updates/db_world/2017_05_28_00.sql index 2f1d3f2361..df44cc7c45 100644 --- a/data/sql/updates/db_world/2017_05_28_00.sql +++ b/data/sql/updates/db_world/2017_05_28_00.sql @@ -325,8 +325,7 @@ UPDATE `pet_levelstats` SET `str`=314, `agi`= 90, `sta`=328, `inte`=150, `spi`=2 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_06_12_00.sql b/data/sql/updates/db_world/2017_06_12_00.sql index 03fde39023..073d88fc88 100644 --- a/data/sql/updates/db_world/2017_06_12_00.sql +++ b/data/sql/updates/db_world/2017_06_12_00.sql @@ -25,8 +25,7 @@ INSERT INTO command (name, security, help) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_06_14_00.sql b/data/sql/updates/db_world/2017_06_14_00.sql index cc1db6857a..98f023b74d 100644 --- a/data/sql/updates/db_world/2017_06_14_00.sql +++ b/data/sql/updates/db_world/2017_06_14_00.sql @@ -30,8 +30,7 @@ INSERT INTO `creature_text` VALUES (4967, 0, 0, 'Go with grace, and may the Lady -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_06_23_00.sql b/data/sql/updates/db_world/2017_06_23_00.sql index 536d598f1a..91732a59b0 100644 --- a/data/sql/updates/db_world/2017_06_23_00.sql +++ b/data/sql/updates/db_world/2017_06_23_00.sql @@ -26,8 +26,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_06_27_00.sql b/data/sql/updates/db_world/2017_06_27_00.sql index 2588476362..db2e605ec4 100644 --- a/data/sql/updates/db_world/2017_06_27_00.sql +++ b/data/sql/updates/db_world/2017_06_27_00.sql @@ -27,8 +27,7 @@ UPDATE `creature_template_addon` SET `auras`='48602' WHERE `entry`=27292; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_06_29_00.sql b/data/sql/updates/db_world/2017_06_29_00.sql index 1d00520bd6..cbb8634d03 100644 --- a/data/sql/updates/db_world/2017_06_29_00.sql +++ b/data/sql/updates/db_world/2017_06_29_00.sql @@ -24,8 +24,7 @@ INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comm -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_18_00.sql b/data/sql/updates/db_world/2017_08_18_00.sql index bee4471ca1..78fffe40c6 100644 --- a/data/sql/updates/db_world/2017_08_18_00.sql +++ b/data/sql/updates/db_world/2017_08_18_00.sql @@ -20,8 +20,7 @@ UPDATE `creature_template` SET `modelid1` = '6485' WHERE `entry` = '7780'; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_18_01.sql b/data/sql/updates/db_world/2017_08_18_01.sql index e2479f25f4..2b5b09a827 100644 --- a/data/sql/updates/db_world/2017_08_18_01.sql +++ b/data/sql/updates/db_world/2017_08_18_01.sql @@ -27,8 +27,7 @@ INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_ -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_18_02.sql b/data/sql/updates/db_world/2017_08_18_02.sql index 6dea4971f9..0fdde66f99 100644 --- a/data/sql/updates/db_world/2017_08_18_02.sql +++ b/data/sql/updates/db_world/2017_08_18_02.sql @@ -23,8 +23,7 @@ UPDATE `quest_template_addon` SET `SpecialFlags` = '0' WHERE `ID` = '342';-- -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_18_03.sql b/data/sql/updates/db_world/2017_08_18_03.sql index 01aa65afdd..1cc14942ee 100644 --- a/data/sql/updates/db_world/2017_08_18_03.sql +++ b/data/sql/updates/db_world/2017_08_18_03.sql @@ -128,8 +128,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_00.sql b/data/sql/updates/db_world/2017_08_19_00.sql index d171c2fe26..0bf643d980 100644 --- a/data/sql/updates/db_world/2017_08_19_00.sql +++ b/data/sql/updates/db_world/2017_08_19_00.sql @@ -30,8 +30,7 @@ UPDATE `quest_template` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_01.sql b/data/sql/updates/db_world/2017_08_19_01.sql index 7ded5a4442..057b03f477 100644 --- a/data/sql/updates/db_world/2017_08_19_01.sql +++ b/data/sql/updates/db_world/2017_08_19_01.sql @@ -22,8 +22,7 @@ UPDATE `creature_template` SET `AIName`= 'PetAI', `mindmg`=1360, `maxdmg`=1840, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_02.sql b/data/sql/updates/db_world/2017_08_19_02.sql index a3e5ae1846..436a53f043 100644 --- a/data/sql/updates/db_world/2017_08_19_02.sql +++ b/data/sql/updates/db_world/2017_08_19_02.sql @@ -207,8 +207,7 @@ INSERT INTO `game_event_gameobject` (`guid`, `eventEntry`) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_03.sql b/data/sql/updates/db_world/2017_08_19_03.sql index 2e5df34ea1..0bc83b3988 100644 --- a/data/sql/updates/db_world/2017_08_19_03.sql +++ b/data/sql/updates/db_world/2017_08_19_03.sql @@ -32,8 +32,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_04.sql b/data/sql/updates/db_world/2017_08_19_04.sql index 97256b2455..b58f1167af 100644 --- a/data/sql/updates/db_world/2017_08_19_04.sql +++ b/data/sql/updates/db_world/2017_08_19_04.sql @@ -32,8 +32,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_05.sql b/data/sql/updates/db_world/2017_08_19_05.sql index 22288d84d7..c641dbf161 100644 --- a/data/sql/updates/db_world/2017_08_19_05.sql +++ b/data/sql/updates/db_world/2017_08_19_05.sql @@ -41,8 +41,7 @@ INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_06.sql b/data/sql/updates/db_world/2017_08_19_06.sql index 18cdb92dfb..e7a1dad920 100644 --- a/data/sql/updates/db_world/2017_08_19_06.sql +++ b/data/sql/updates/db_world/2017_08_19_06.sql @@ -115,8 +115,7 @@ INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`pr -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_07.sql b/data/sql/updates/db_world/2017_08_19_07.sql index e8a0e22f98..ef2dc707dd 100644 --- a/data/sql/updates/db_world/2017_08_19_07.sql +++ b/data/sql/updates/db_world/2017_08_19_07.sql @@ -246,8 +246,7 @@ INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `positi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_08.sql b/data/sql/updates/db_world/2017_08_19_08.sql index bd5c05c96e..274fbb2f03 100644 --- a/data/sql/updates/db_world/2017_08_19_08.sql +++ b/data/sql/updates/db_world/2017_08_19_08.sql @@ -23,8 +23,7 @@ WHERE `ID`= 5064; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_09.sql b/data/sql/updates/db_world/2017_08_19_09.sql index 2650ba0ff5..d029590dad 100644 --- a/data/sql/updates/db_world/2017_08_19_09.sql +++ b/data/sql/updates/db_world/2017_08_19_09.sql @@ -19,8 +19,7 @@ UPDATE `spell_dbc` SET `RangeIndex`=4 WHERE `Id`=61698; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_10.sql b/data/sql/updates/db_world/2017_08_19_10.sql index 918ed81123..45b18a5939 100644 --- a/data/sql/updates/db_world/2017_08_19_10.sql +++ b/data/sql/updates/db_world/2017_08_19_10.sql @@ -19,8 +19,7 @@ UPDATE `creature_template` SET `faction` = 1873 WHERE `entry` = 16927; -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_11.sql b/data/sql/updates/db_world/2017_08_19_11.sql index a2488b627c..6416bcee55 100644 --- a/data/sql/updates/db_world/2017_08_19_11.sql +++ b/data/sql/updates/db_world/2017_08_19_11.sql @@ -62,8 +62,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_12.sql b/data/sql/updates/db_world/2017_08_19_12.sql index 0ae38e1d48..1fd5b1b450 100644 --- a/data/sql/updates/db_world/2017_08_19_12.sql +++ b/data/sql/updates/db_world/2017_08_19_12.sql @@ -24,8 +24,7 @@ INSERT INTO `creature_onkill_reputation` (`creature_id`,`RewOnKillRepFaction1`,` -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_13.sql b/data/sql/updates/db_world/2017_08_19_13.sql index ce8e5b1ed6..2e250ba350 100644 --- a/data/sql/updates/db_world/2017_08_19_13.sql +++ b/data/sql/updates/db_world/2017_08_19_13.sql @@ -41,8 +41,7 @@ UPDATE `creature` SET `position_x`=4402.431152, `position_y`=4554.557129, `posit -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_14.sql b/data/sql/updates/db_world/2017_08_19_14.sql index a2042bb155..76b2c3a4fb 100644 --- a/data/sql/updates/db_world/2017_08_19_14.sql +++ b/data/sql/updates/db_world/2017_08_19_14.sql @@ -42,8 +42,7 @@ UPDATE `quest_template` SET RewardXPDifficulty = 0, RewardBonusMoney = 0 WHER -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_15.sql b/data/sql/updates/db_world/2017_08_19_15.sql index 7f933125e5..638bbf683e 100644 --- a/data/sql/updates/db_world/2017_08_19_15.sql +++ b/data/sql/updates/db_world/2017_08_19_15.sql @@ -166,8 +166,7 @@ UPDATE `item_loot_template` SET `ChanceOrQuestChance` = 100 WHERE `entry` = 1056 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_16.sql b/data/sql/updates/db_world/2017_08_19_16.sql index 73d1ba7d90..5a35ef619c 100644 --- a/data/sql/updates/db_world/2017_08_19_16.sql +++ b/data/sql/updates/db_world/2017_08_19_16.sql @@ -97,8 +97,7 @@ UPDATE `creature_loot_template` SET `ChanceOrQuestChance` = 15 WHERE `item` = 24 -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_17.sql b/data/sql/updates/db_world/2017_08_19_17.sql index 75e791cb54..4d04398a07 100644 --- a/data/sql/updates/db_world/2017_08_19_17.sql +++ b/data/sql/updates/db_world/2017_08_19_17.sql @@ -298,8 +298,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_18.sql b/data/sql/updates/db_world/2017_08_19_18.sql index e17f62ffdc..9585764d6c 100644 --- a/data/sql/updates/db_world/2017_08_19_18.sql +++ b/data/sql/updates/db_world/2017_08_19_18.sql @@ -22,8 +22,7 @@ UPDATE creature_equip_template SET ItemID1= 38723, ItemID2= 12932 WHERE Creature -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_19_19.sql b/data/sql/updates/db_world/2017_08_19_19.sql index ac2056bd8f..5371e951f1 100644 --- a/data/sql/updates/db_world/2017_08_19_19.sql +++ b/data/sql/updates/db_world/2017_08_19_19.sql @@ -298,8 +298,7 @@ INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_20_00.sql b/data/sql/updates/db_world/2017_08_20_00.sql index ad1bd8c627..9174e6f5e6 100644 --- a/data/sql/updates/db_world/2017_08_20_00.sql +++ b/data/sql/updates/db_world/2017_08_20_00.sql @@ -26,8 +26,7 @@ INSERT INTO `command` (`name`,`security`,`help`) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_20_01.sql b/data/sql/updates/db_world/2017_08_20_01.sql index 31c12794cd..492779b4f5 100644 --- a/data/sql/updates/db_world/2017_08_20_01.sql +++ b/data/sql/updates/db_world/2017_08_20_01.sql @@ -26,8 +26,7 @@ INSERT INTO `command` (`name`,`security`,`help`) VALUES -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_22_00.sql b/data/sql/updates/db_world/2017_08_22_00.sql index 241b29a813..79e931126d 100644 --- a/data/sql/updates/db_world/2017_08_22_00.sql +++ b/data/sql/updates/db_world/2017_08_22_00.sql @@ -23,8 +23,7 @@ UPDATE `creature_template_addon` SET `auras`=10848 WHERE `entry` IN (8888); -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_22_01.sql b/data/sql/updates/db_world/2017_08_22_01.sql index 4673f4e03a..d2d38f1036 100644 --- a/data/sql/updates/db_world/2017_08_22_01.sql +++ b/data/sql/updates/db_world/2017_08_22_01.sql @@ -32,8 +32,7 @@ INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`, -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_08_25_00.sql b/data/sql/updates/db_world/2017_08_25_00.sql index 87cb39f24f..136d4ad4c4 100644 --- a/data/sql/updates/db_world/2017_08_25_00.sql +++ b/data/sql/updates/db_world/2017_08_25_00.sql @@ -38,8 +38,7 @@ UPDATE `creature_text` SET `sound` = '10159' WHERE `entry` = '17461' AND `groupi -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_09_26_00.sql b/data/sql/updates/db_world/2017_09_26_00.sql index 2427091d4c..f93e472d5c 100644 --- a/data/sql/updates/db_world/2017_09_26_00.sql +++ b/data/sql/updates/db_world/2017_09_26_00.sql @@ -28,8 +28,7 @@ UPDATE `creature_template` SET `AIName`='', `ScriptName`='boss_high_inquisitor_w -- END UPDATING QUERIES -- COMMIT; -END; -// +END // DELIMITER ; CALL updateDb(); DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_14_00.sql b/data/sql/updates/db_world/2017_10_14_00.sql new file mode 100644 index 0000000000..840175104a --- /dev/null +++ b/data/sql/updates/db_world/2017_10_14_00.sql @@ -0,0 +1,23 @@ +-- DB update World of Warcraft/_World of Warcraft/ -> 2017_10_14_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_09_26_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_09_26_00 2017_10_14_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1504044222560696700'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_14_01.sql b/data/sql/updates/db_world/2017_10_14_01.sql new file mode 100644 index 0000000000..04cc398884 --- /dev/null +++ b/data/sql/updates/db_world/2017_10_14_01.sql @@ -0,0 +1,23 @@ +-- DB update 2017_10_14_00 -> 2017_10_14_01 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_14_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_14_00 2017_10_14_01 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1504704582101308200'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_14_02.sql b/data/sql/updates/db_world/2017_10_14_02.sql new file mode 100644 index 0000000000..039eac6352 --- /dev/null +++ b/data/sql/updates/db_world/2017_10_14_02.sql @@ -0,0 +1,23 @@ +-- DB update 2017_10_14_01 -> 2017_10_14_02 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_14_01'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_14_01 2017_10_14_02 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1506719089670151700'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_15_00.sql b/data/sql/updates/db_world/2017_10_15_00.sql new file mode 100644 index 0000000000..b0f9d5f6e3 --- /dev/null +++ b/data/sql/updates/db_world/2017_10_15_00.sql @@ -0,0 +1,179 @@ +DROP FUNCTION IF EXISTS packDate; +CREATE FUNCTION packDate (yy TINYINT UNSIGNED, mm TINYINT UNSIGNED, dd TINYINT UNSIGNED) +RETURNS INT UNSIGNED DETERMINISTIC +RETURN (yy << 24) | ((mm - 1) << 20) | ((dd - 1) << 14); + +-- DB update 2017_09_26_00 -> 2017_10_15_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_14_02'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_14_02 2017_10_15_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1504044222560696700'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1504044222560696700'); + +-- fix NO_ZERO_DATE error on mysql 5.7 (for latest linux platforms) +-- please use 5.6 on windows +SET SESSION sql_mode = "ONLY_FULL_GROUP_BY,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES"; + +DROP TABLE IF EXISTS holiday_dates; +CREATE TABLE holiday_dates ( + id INT UNSIGNED NOT NULL, + date_id TINYINT UNSIGNED NOT NULL, + date_value INT UNSIGNED NOT NULL, + PRIMARY KEY (id, date_id) +); + +INSERT INTO holiday_dates VALUES +(181, 6, 220692480 + (1 << 14)), -- rescheduled +(181, 7, 238338048 + (1 << 14)), +(181, 8, 254869504 + (1 << 14)), +(181, 9, 270958592 + (1 << 14)), +(181, 10, 288635520), -- 7.2 (PTR) dbc +(181, 11, 305166976), +(181, 12, 322271872), +(201, 9, 221723264), +(201, 10, 238484096), +(201, 11, 255244928), +(201, 12, 272661120), +(201, 13, 289421952), +(201, 14, 305625728), +(201, 15, 322386560), +(321, 7, 210106368), +(321, 8, 226704000), +(321, 9, 243300992), +(321, 10, 260389504), +(321, 11, 276970112), +(321, 12, 294075008), +(321, 13, 310672000), +(327, 7, 218429440 + (7 << 14)), +(327, 8, 235207296), +(327, 9, 252967552), +(327, 10, 269499008), +(327, 11, 285555328), +(327, 12, 303184512), +(327, 13, 319224448), +(404, 4, 228997760), +(404, 5, 245758592), +(404, 6, 262519424), +(404, 7, 279263872), +(404, 8, 296024704), +(404, 9, 312785536), +(404, 10, 329661056), +(423, 3, 219185152 + (7 << 14)), +(423, 4, 236092032), +(423, 5, 252738176), +(423, 6, 269728384), +(423, 7, 286374528), +(423, 8, 303184512), +(423, 9, 319881856), + +(374, 0, packDate(16, 12, 02)), +(375, 0, packDate(16, 12, 30)), +(376, 0, packDate(17, 02, 03)), +(374, 1, packDate(17, 03, 03)), +(375, 1, packDate(17, 03, 31)), +(376, 1, packDate(17, 04, 28)), +(374, 2, packDate(17, 06, 02)), +(375, 2, packDate(17, 06, 30)), +(376, 2, packDate(17, 08, 04)), +(374, 3, packDate(17, 09, 01)), +(375, 3, packDate(17, 09, 29)), +(376, 3, packDate(17, 11, 03)), +(374, 4, packDate(17, 12, 01)), +(375, 4, packDate(17, 12, 29)), +(376, 4, packDate(18, 02, 02)), +(374, 5, packDate(18, 03, 02)), +(375, 5, packDate(18, 03, 30)), +(376, 5, packDate(18, 05, 04)), +(374, 6, packDate(18, 06, 01)), +(375, 6, packDate(18, 06, 29)), +(376, 6, packDate(18, 08, 03)), +(374, 7, packDate(18, 08, 31)), +(375, 7, packDate(18, 09, 28)), +(376, 7, packDate(18, 11, 02)), +(374, 8, packDate(18, 11, 30)), +(375, 8, packDate(19, 01, 04)), +(376, 8, packDate(19, 02, 01)), +(374, 9, packDate(19, 03, 01)), +(375, 9, packDate(19, 03, 29)), +(376, 9, packDate(19, 05, 03)), +(374, 10, packDate(19, 05, 31)), +(375, 10, packDate(19, 06, 28)), +(376, 10, packDate(19, 08, 02)), +(374, 11, packDate(19, 08, 30)), +(375, 11, packDate(19, 10, 04)), +(376, 11, packDate(19, 11, 01)), +(374, 12, packDate(19, 11, 29)), +(375, 12, packDate(20, 01, 03)), +(376, 12, packDate(20, 01, 31)), +(374, 13, packDate(20, 02, 28)), +(375, 13, packDate(20, 04, 03)), +(376, 13, packDate(20, 05, 01)), +(374, 14, packDate(20, 05, 29)), +(375, 14, packDate(20, 07, 03)), +(376, 14, packDate(20, 07, 31)), +(374, 15, packDate(20, 09, 04)), +(375, 15, packDate(20, 10, 02)), +(376, 15, packDate(20, 10, 30)), +(374, 16, packDate(20, 12, 04)), +(375, 16, packDate(21, 01, 01)), +(376, 16, packDate(21, 01, 29)), +(374, 17, packDate(21, 02, 26)), +(375, 17, packDate(21, 04, 02)), +(376, 17, packDate(21, 04, 30)), +(374, 18, packDate(21, 06, 04)), +(375, 18, packDate(21, 07, 02)), +(376, 18, packDate(21, 07, 30)), +(374, 19, packDate(21, 09, 03)), +(375, 19, packDate(21, 10, 01)), +(376, 19, packDate(21, 10, 29)), +(374, 20, packDate(21, 12, 03)), +(375, 20, packDate(21, 12, 31)), +(376, 20, packDate(22, 02, 04)), +(374, 21, packDate(22, 03, 04)), +(375, 21, packDate(22, 04, 01)), +(376, 21, packDate(22, 04, 29)), +(374, 22, packDate(22, 06, 03)), +(375, 22, packDate(22, 07, 01)), +(376, 22, packDate(22, 07, 29)), +(374, 23, packDate(22, 09, 02)), +(375, 23, packDate(22, 09, 30)), +(376, 23, packDate(22, 11, 04)), +(374, 24, packDate(22, 12, 02)), +(375, 24, packDate(22, 12, 30)), +(376, 24, packDate(23, 02, 03)), +(374, 25, packDate(23, 03, 03)), +(375, 25, packDate(23, 03, 31)), +(376, 25, packDate(23, 04, 28)); + +UPDATE holiday_dates SET date_value = date_value & ~0x3FFF; + +ALTER TABLE game_event ADD COLUMN holidayStage TINYINT UNSIGNED NOT NULL DEFAULT 0 AFTER holiday; + +UPDATE game_event SET holiday = 424 WHERE eventEntry = 64; +UPDATE game_event SET holiday = 0 WHERE eventEntry = 63; +UPDATE game_event SET holiday = 374 WHERE eventEntry = 23; +UPDATE game_event SET holiday = 375 WHERE eventEntry = 110; +UPDATE game_event SET holiday = 376 WHERE eventEntry = 62; +UPDATE game_event SET holidayStage = 1 WHERE eventEntry IN (1, 2, 7, 8, 9, 10, 11, 12, 18, 19, 20, 21, 23, 24, 26, 50, 51, 53, 54, 62, 110); +UPDATE game_event SET holidayStage = 2 WHERE eventEntry IN (3, 4, 5); +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; + +DROP FUNCTION packDate; + diff --git a/data/sql/updates/db_world/2017_10_15_01.sql b/data/sql/updates/db_world/2017_10_15_01.sql new file mode 100644 index 0000000000..010f1aa1f5 --- /dev/null +++ b/data/sql/updates/db_world/2017_10_15_01.sql @@ -0,0 +1,58 @@ +-- DB update 2017_10_15_00 -> 2017_10_15_01 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_15_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_15_00 2017_10_15_01 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1504704582101308200'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1504704582101308200'); + +-- Editing the SmartAI script of [Creature] ENTRY 11663 (name: Flamewaker Healer) + +-- Table creature_template +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 11663; + +-- Table smart_scripts +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = 11663); +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 +(11663, 0, 0, 0, 0, 0, 100, 2, 9000, 9000, 9000, 9000, 11, 20603, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Healer - In Combat - Cast \'Shadow Shock\' (Normal Dungeon)'), +(11663, 0, 1, 0, 0, 0, 100, 2, 2000, 2000, 2000, 2000, 11, 22677, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Healer - In Combat - Cast \'Shadow Bolt\' (Normal Dungeon)'), +(11663, 0, 2, 0, 4, 0, 100, 0, 0, 0, 0, 0, 39, 20, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Healer - On Aggro - Call For Help'); + + +-- Editing the SmartAI script of [Creature] ENTRY 11664 (name: Flamewaker Elite) + +-- Table creature_template +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 11664; + +-- Table smart_scripts +DELETE FROM `smart_scripts` WHERE (source_type = 0 AND entryorguid = 11664); +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 +(11664, 0, 0, 0, 0, 0, 85, 2, 1000, 1000, 8000, 8000, 11, 36711, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Elite - In Combat - Cast \'Fireball\' (Normal Dungeon)'), +(11664, 0, 1, 0, 0, 0, 100, 2, 12000, 12000, 12000, 12000, 11, 20229, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Elite - In Combat - Cast \'Blast Wave\' (Normal Dungeon)'), +(11664, 0, 2, 0, 0, 0, 80, 2, 5000, 5000, 15000, 15000, 11, 20623, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Elite - In Combat - Cast \'Fire Blast\' (Normal Dungeon)'), +(11664, 0, 3, 0, 4, 0, 100, 0, 0, 0, 0, 0, 39, 20, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamewaker Elite - On Aggro - Call For Help'); + +-- Core Hound scriptname +UPDATE `creature_template` SET `scriptname` = 'npc_magmadar_core_hound' WHERE `entry` = 11671; + +-- Core Hound texts +DELETE FROM `creature_text` WHERE entry = 11671; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `textrange`) VALUES +(11671, 0, 0, "%s collapses and begins to smolder.", 16, 0, 100, 0, 2000, 0), +(11671, 1, 0, "%s reignites from the heat of another Core Hound!", 16, 0, 100, 0, 2000, 0);-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_15_02.sql b/data/sql/updates/db_world/2017_10_15_02.sql new file mode 100644 index 0000000000..f9ea98278b --- /dev/null +++ b/data/sql/updates/db_world/2017_10_15_02.sql @@ -0,0 +1,26 @@ +-- DB update 2017_10_15_01 -> 2017_10_15_02 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_15_01'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_15_01 2017_10_15_02 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1506719089670151700'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1506719089670151700'); + +UPDATE creature_template SET flags_extra =+ 2 WHERE entry IN (69,299); +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_17_00.sql b/data/sql/updates/db_world/2017_10_17_00.sql new file mode 100644 index 0000000000..b34c1a3a8d --- /dev/null +++ b/data/sql/updates/db_world/2017_10_17_00.sql @@ -0,0 +1,38 @@ +-- DB update 2017_10_15_02 -> 2017_10_17_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_15_02'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_15_02 2017_10_17_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1508171605836767200'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1508171605836767200'); + +-- Lord Thorval +SET @ENTRY := 28472; +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`, `BroadcastTextId`) VALUES +(@ENTRY, 0, 0, 'As disciples of blood, you strive to master the very lifeforce of your enemies.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29867), +(@ENTRY, 1, 0, 'Be it by blade or incantation, blood feeds our attacks and weakens our foes.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29868), +(@ENTRY, 2, 0, 'True masters learn to make blood serve more than just their strength in battle.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29869), +(@ENTRY, 3, 0, 'Stripping energy from our foes, both fighting and fallen, allows us to persevere where lesser beigns falls exhausted.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29870), +(@ENTRY, 4, 0, 'And every foe that falls, energy sapped and stolen, only further fuels our assault.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29871), +(@ENTRY, 5, 0, 'As masters of blood, we know battle without end...', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29872), +(@ENTRY, 6, 0, 'We know hunger never to be quenched...', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29873), +(@ENTRY, 7, 0, 'We know power never to be overcome...', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29874), +(@ENTRY, 8, 0, 'As masters of blood, we are masters of life and death itself. Agains us, even hope falls drained and lifeless.', 12, 0, 100, 1, 0, 0, 'Lord Thorval', 29875); +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_17_01.sql b/data/sql/updates/db_world/2017_10_17_01.sql new file mode 100644 index 0000000000..a15b0c1505 --- /dev/null +++ b/data/sql/updates/db_world/2017_10_17_01.sql @@ -0,0 +1,32 @@ +-- DB update 2017_10_17_00 -> 2017_10_17_01 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_17_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_17_00 2017_10_17_01 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1508171834127824700'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1508171834127824700'); + +-- Warsong Recruitment Officer - Gossip (Hellscream's Vigil) +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=19 AND (`SourceEntry`=11586 OR `SourceEntry`=11585); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionValue1`,`Comment`) VALUES +(19, 11585, 14, 10172, "Accept quest 11585 - Quest 10172 needs to be incomplete"), +(19, 11586, 8, 10172, "Accept quest 11586 - Quest 10172 needs to be rewarded"); + +UPDATE `quest_template_addon` SET `ExclusiveGroup`=11585 WHERE `ID` IN (11585,11586); +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_10_17_02.sql b/data/sql/updates/db_world/2017_10_17_02.sql new file mode 100644 index 0000000000..ccad68b870 --- /dev/null +++ b/data/sql/updates/db_world/2017_10_17_02.sql @@ -0,0 +1,29 @@ +-- DB update 2017_10_17_01 -> 2017_10_17_02 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_17_01'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_17_01 2017_10_17_02 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1508172729879058700'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1508172729879058700'); + +-- Fix Startup Errors +UPDATE `creature_addon` SET `auras`='' WHERE `guid`=6432; +UPDATE `creature_template` SET `skinloot`=80102 WHERE `entry` IN (18343, 20268); +DELETE FROM `creature_addon` WHERE `guid`=3574; +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_11_14_00.sql b/data/sql/updates/db_world/2017_11_14_00.sql new file mode 100644 index 0000000000..d5cc81382e --- /dev/null +++ b/data/sql/updates/db_world/2017_11_14_00.sql @@ -0,0 +1,34 @@ +-- DB update 2017_10_17_02 -> 2017_11_14_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_10_17_02'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_10_17_02 2017_11_14_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1509271997120618300'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1509271997120618300'); + +-- Quest: A Suitable Test Subject (11719) +DELETE FROM `spell_script_names` WHERE `ScriptName`="spell_q11719_bloodspore_ruination_45997"; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(45997, "spell_q11719_bloodspore_ruination_45997"); + +UPDATE `creature_template` SET `ScriptName`="npc_bloodmage_laurith" WHERE `entry`=25381; + +DELETE FROM `creature_text` WHERE `entry`=25381; +INSERT INTO `creature_text` (`entry`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES +(25381, 0, 0, "How positively awful! You were totally incapacitated? Weak? Hot flashes?", 15, 0, 100, 21, 0, 0, 24992, 0, "Bloodmage Laurith");-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_11_14_01.sql b/data/sql/updates/db_world/2017_11_14_01.sql new file mode 100644 index 0000000000..3206d93673 --- /dev/null +++ b/data/sql/updates/db_world/2017_11_14_01.sql @@ -0,0 +1,33 @@ +-- DB update 2017_11_14_00 -> 2017_11_14_01 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_11_14_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_11_14_00 2017_11_14_01 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1510696617496219500'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1510696617496219500'); + +DELETE FROM `command` WHERE `name`='mmap' OR `name` LIKE 'mmap%'; +DELETE FROM `command` WHERE `name` LIKE 'disable add mmap' OR `name` LIKE 'disable remove mmap'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('mmap', 3, 'Syntax: Syntax: .mmaps $subcommand Type .mmaps to see the list of possible subcommands or .help mmaps $subcommand to see info on subcommands'), +('mmap path', 3, 'Syntax: .mmap path to calculate and show a path to current select unit'), +('mmap loc', 3, 'Syntax: .mmap loc to print on which tile one is'), +('mmap loadedtiles', 3, 'Syntax: .mmap loadedtiles to show which tiles are currently loaded'), +('mmap stats', 3, 'Syntax: .mmap stats to show information about current state of mmaps'), +('mmap testarea', 3, 'Syntax: .mmap testarea to calculate paths for all nearby npcs to player');-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_11_16_00.sql b/data/sql/updates/db_world/2017_11_16_00.sql new file mode 100644 index 0000000000..0ca780be8d --- /dev/null +++ b/data/sql/updates/db_world/2017_11_16_00.sql @@ -0,0 +1,26 @@ +-- DB update 2017_11_14_01 -> 2017_11_16_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_11_14_01'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_11_14_01 2017_11_16_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1510843288942649400'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1510843288942649400'); + +UPDATE `creature_model_info` SET `BoundingRadius`=7.5, `CombatReach`=6 WHERE `DisplayID`=30890;-- +-- END UPDATING QUERIES +-- +COMMIT; +END; +// +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_11_17_00.sql b/data/sql/updates/db_world/2017_11_17_00.sql new file mode 100644 index 0000000000..d58ae81671 --- /dev/null +++ b/data/sql/updates/db_world/2017_11_17_00.sql @@ -0,0 +1,61 @@ +-- DB update 2017_11_16_00 -> 2017_11_17_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_11_16_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_11_16_00 2017_11_17_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1509353420962391661'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1509353420962391661'); + +-- change script name to arena kills by type +UPDATE achievement_criteria_data SET ScriptName="achievement_arena_2v2_check" WHERE criteria_id = 5541 AND TYPE = 11; +UPDATE achievement_criteria_data SET ScriptName="achievement_arena_3v3_check" WHERE criteria_id = 5542 AND TYPE = 11; +UPDATE achievement_criteria_data SET ScriptName="achievement_arena_5v5_check" WHERE criteria_id = 5543 AND TYPE = 11; + +-- arena matches by type +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (5728,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8615,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8616,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8617,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8618,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (5725,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8611,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8612,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8613,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8614,11,'achievement_arena_2v2_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (5727,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8607,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8608,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8609,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8610,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (5724,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8603,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8604,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8605,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8606,11,'achievement_arena_3v3_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (5726,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8599,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8600,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8601,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8602,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (5723,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8595,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8596,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8597,11,'achievement_arena_5v5_check'); +INSERT INTO achievement_criteria_data (criteria_id,TYPE,ScriptName) VALUES (8598,11,'achievement_arena_5v5_check'); +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_11_19_00.sql b/data/sql/updates/db_world/2017_11_19_00.sql new file mode 100644 index 0000000000..cc59e7fe34 --- /dev/null +++ b/data/sql/updates/db_world/2017_11_19_00.sql @@ -0,0 +1,208 @@ +-- DB update 2017_11_17_00 -> 2017_11_19_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_11_17_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_11_17_00 2017_11_19_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1509375074619158078'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- +INSERT INTO version_db_world (`sql_rev`) VALUES ('1509375074619158078'); + +-- lady deathwhisper and marrowgar 25 heroic (difficulty 3) +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '3' WHERE `criteria_id` = '13091' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '3' WHERE `criteria_id` = '13106' AND `type` = '0'; + +-- fix various stats for 25 normal (difficulty 1) +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13108' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12242' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13105' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12231' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12230' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12234' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12235' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13092' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12243' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12246' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12247' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '11903' AND `type` = '0'; +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (4989,12,1,0); + +-- lady deathwhisper and marrowgar 10 heroic (difficulty 2) +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '2' WHERE `criteria_id` = '13090' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '2' WHERE `criteria_id` = '13104' AND `type` = '0'; +-- gunship and deathbringer 10 heroic +UPDATE `achievement_criteria_data` SET `value1` = '2' WHERE `criteria_id` = '13110' AND `type` = '12'; +UPDATE `achievement_criteria_data` SET `value1` = '2' WHERE `criteria_id` = '13113' AND `type` = '12'; + +-- fix various 10 normal stats (difficulty 0) +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13093' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12228' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12229' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12232' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12233' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13107' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12240' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12241' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12244' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12245' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '11902' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13089' AND `type` = '0'; +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (4988,12,0,0); + +-- fix various heroic dungeons +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13179' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12798' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12799' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12800' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13182' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12802' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12808' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12803' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12804' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12805' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12806' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12807' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13177' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '12809' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13167' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13168' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13173' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' , `value1` = '1' WHERE `criteria_id` = '13175' AND `type` = '0'; +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (5620,12,1,0); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (12801,12,1,0); + + +-- fix all other normal criteria for dungeon and raids + +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12686' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12678' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12679' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '8803' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '8802' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '8801' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '8800' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '8799' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '8798' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12680' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5468' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5469' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5466' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5467' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5465' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5464' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5463' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5462' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5461' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5460' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5459' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5458' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5457' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5456' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5455' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5454' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5453' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5452' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5451' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5450' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5449' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5448' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5446' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5447' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5445' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5444' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5443' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5442' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5441' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5440' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5439' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5438' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5437' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5436' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5384' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5383' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5382' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5381' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5380' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5379' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5378' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5377' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3239' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12682' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3241' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12683' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12684' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12685' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3242' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12687' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12688' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '12689' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13166' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13169' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13170' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13172' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13174' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13176' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '13178' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3240' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5631' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5630' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5629' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5628' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5627' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5626' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5625' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5624' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5623' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5622' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '5621' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3275' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3274' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3273' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3272' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3271' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3270' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3266' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3268' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3265' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3264' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3263' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3261' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3260' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3259' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3258' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3257' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3262' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3256' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3255' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3254' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3253' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3252' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3251' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3250' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3249' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3248' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3247' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3246' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3245' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3244' AND `type` = '0'; +UPDATE `achievement_criteria_data` SET `type` = '12' WHERE `criteria_id` = '3243' AND `type` = '0'; +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (5632,12,0,0); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (5619,12,0,0); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (12681,12,0,0); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`) VALUES (4987,12,0,0); +-- +-- END UPDATING QUERIES +-- +COMMIT; +END; +// +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_11_21_00.sql b/data/sql/updates/db_world/2017_11_21_00.sql new file mode 100644 index 0000000000..1139f7b587 --- /dev/null +++ b/data/sql/updates/db_world/2017_11_21_00.sql @@ -0,0 +1,33 @@ +-- DB update 2017_11_19_00 -> 2017_11_21_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_11_19_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_11_19_00 2017_11_21_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1511275510595112400'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- + +INSERT INTO version_db_world (`sql_rev`) VALUES ('1511275510595112400'); + +-- fix Wintergrasp aura limiting to its zone/area +INSERT INTO`spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +('55774', '4197', '0', '0', '0', '0', '2', '0', '0', '0'); + +INSERT INTO`spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +('55773', '4197', '0', '0', '0', '0', '2', '0', '0', '0'); + +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/db_world/2017_12_08_00.sql b/data/sql/updates/db_world/2017_12_08_00.sql new file mode 100644 index 0000000000..114b1fda2e --- /dev/null +++ b/data/sql/updates/db_world/2017_12_08_00.sql @@ -0,0 +1,35 @@ +-- DB update 2017_11_21_00 -> 2017_12_08_00 +DROP PROCEDURE IF EXISTS `updateDb`; +DELIMITER // +CREATE PROCEDURE updateDb () +proc:BEGIN DECLARE OK VARCHAR(100) DEFAULT 'FALSE'; +SELECT COUNT(*) INTO @COLEXISTS +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'version_db_world' AND COLUMN_NAME = '2017_12_08_00'; +IF @COLEXISTS = 0 THEN LEAVE proc; END IF; +START TRANSACTION; +ALTER TABLE version_db_world CHANGE COLUMN 2017_11_21_00 2017_12_08_00 bit; +SELECT sql_rev INTO OK FROM version_db_world WHERE sql_rev = '1512664376513425042'; IF OK <> 'FALSE' THEN LEAVE proc; END IF; +-- +-- START UPDATING QUERIES +-- + +INSERT INTO version_db_world (`sql_rev`) VALUES ('1512664376513425042'); + +UPDATE `creature_template` SET `mechanic_immune_mask` = '65536' WHERE `entry` = '29274'; +UPDATE `creature_template` SET `spell2` = '54097' WHERE `entry` = '29274'; + +DELETE FROM `spell_scripts` WHERE `id` IN +(28732,54097); +INSERT INTO `spell_scripts` (`id`, `effIndex`, command, datalong, datalong2, dataint, `x`) VALUES +(28732, 1, 15, 0, 4, 15953, 100), # Widow's Embrace +(54097, 1, 15, 0, 4, 15953, 100); # Widow's Embrace + +-- +-- END UPDATING QUERIES +-- +COMMIT; +END // +DELIMITER ; +CALL updateDb(); +DROP PROCEDURE IF EXISTS `updateDb`; diff --git a/data/sql/updates/pending_db_world/rev_1506719089670151700.sql b/data/sql/updates/pending_db_world/rev_1506719089670151700.sql deleted file mode 100644 index 4e4bdb8048..0000000000 --- a/data/sql/updates/pending_db_world/rev_1506719089670151700.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO version_db_world (`sql_rev`) VALUES ('1506719089670151700'); - -UPDATE creature_template SET flags_extra =+ 2 WHERE entry IN (69,299); diff --git a/data/sql/updates/pending_db_world/rev_1512840854590821700.sql b/data/sql/updates/pending_db_world/rev_1512840854590821700.sql new file mode 100644 index 0000000000..290a046804 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1512840854590821700.sql @@ -0,0 +1,7487 @@ +INSERT INTO version_db_world (`sql_rev`) VALUES ('1512840854590821700'); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41, 4, 0, -1, 'NPC Equip 41', 7, 4553, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42, 4, 0, -1, 'NPC Equip 42', 7, 4562, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46, 4, 0, -1, 'NPC Equip 46', 7, 4528, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50, 4, 0, -1, 'NPC Equip 50', 7, 4535, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (54, 4, 0, -1, 'NPC Equip 54', 7, 4541, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (58, 4, 0, -1, 'NPC Equip 58', 7, 4499, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (77, 4, 1, -1, 'NPC Equip 77', 7, 2645, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (86, 4, 0, -1, 'NPC Equip 86', 7, 4525, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (87, 4, 0, -1, 'NPC Equip 87', 7, 261, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (89, 4, 0, -1, 'NPC Equip 89', 7, 7848, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (90, 4, 0, -1, 'NPC Equip 90', 7, 4519, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (92, 4, 0, -1, 'NPC Equip 92', 7, 249, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (93, 4, 0, -1, 'NPC Equip 93', 7, 369, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (94, 4, 0, -1, 'NPC Equip 94', 7, 4522, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (95, 4, 0, -1, 'NPC Equip 95', 7, 242, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (97, 4, 1, -1, 'NPC Equip 97', 7, 12662, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (98, 4, 0, -1, 'NPC Equip 98', 7, 4524, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (99, 4, 0, -1, 'NPC Equip 99', 7, 257, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (101, 4, 0, -1, 'NPC Equip 101', 7, 373, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (102, 4, 0, -1, 'NPC Equip 102', 7, 4523, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (103, 4, 0, -1, 'NPC Equip 103', 7, 5901, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (104, 4, 1, -1, 'NPC Equip 104', 7, 370, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (105, 4, 0, -1, 'NPC Equip 105', 7, 371, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (113, 4, 1, -1, 'NPC Equip 113', 7, 365, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (114, 4, 0, -1, 'NPC Equip 114', 7, 245, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (115, 4, 0, -1, 'NPC Equip 115', 7, 4517, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (122, 4, 0, -1, 'NPC Equip 122', 7, 4538, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (123, 4, 0, -1, 'NPC Equip 123', 7, 383, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (124, 4, 1, -1, 'NPC Equip 124', 7, 3268, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (125, 4, 0, -1, 'NPC Equip 125', 7, 3269, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (126, 4, 0, -1, 'NPC Equip 126', 7, 4543, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (130, 4, 0, -1, 'NPC Equip 130', 7, 4572, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (131, 4, 0, -1, 'NPC Equip 131', 7, 4542, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (132, 4, 0, -1, 'NPC Equip 132', 7, 295, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (133, 4, 0, -1, 'NPC Equip 133', 7, 7912, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (134, 4, 0, -1, 'NPC Equip 134', 7, 387, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (135, 4, 1, -1, 'NPC Equip 135', 7, 386, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (136, 4, 0, -1, 'NPC Equip 136', 7, 311, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (137, 4, 0, -1, 'NPC Equip 137', 7, 4540, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (141, 4, 0, -1, 'NPC Equip 141', 7, 4507, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (146, 4, 0, -1, 'NPC Equip 146', 7, 4544, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (149, 4, 0, -1, 'NPC Equip 149', 7, 4569, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (150, 4, 1, -1, 'NPC Equip 150', 7, 392, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (151, 4, 0, -1, 'NPC Equip 151', 7, 393, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (152, 4, 0, -1, 'NPC Equip 152', 7, 4570, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (155, 4, 0, -1, 'NPC Equip 155', 7, 4571, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (157, 4, 0, -1, 'NPC Equip 157', 7, 395, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (184, 1, 0, -1, 'NPC Equip 184', 8, 362, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (527, 12, 0, -1, 'NPC Equip 527', 2, 7090, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (741, 7, 7, -1, 'NPC Equip 741', 1, 7391, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (746, 4, 0, -1, 'NPC Equip 746', 7, 3865, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (751, 2, 4, -1, 'NPC Equip 751', 2, 1515, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (759, 7, 0, -1, 'NPC Equip 759', 2, 942, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (761, 0, 8, -1, 'NPC Equip 761', 8, 1208, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (784, 7, 11, -1, 'NPC Equip 784', -1, 1438, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (786, 7, 7, -1, 'NPC Equip 786', 1, 7391, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (788, 2, 7, -1, 'NPC Equip 788', 1, 5750, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (806, 1, 0, -1, 'NPC Equip 806', -1, 2585, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (807, 7, 7, -1, 'NPC Equip 807', 1, 7356, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (808, 7, 11, -1, 'NPC Equip 808', -1, 7353, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (823, 15, 0, -1, 'NPC Equip 823', -1, 7014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (836, 0, 8, -1, 'NPC Equip 836', 8, 1007, 0, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (842, 15, 0, -1, 'NPC Equip 842', -1, 7015, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (855, 1, 0, -1, 'NPC Equip 855', 8, 1281, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (875, 15, 0, -1, 'NPC Equip 875', -1, 6423, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (877, 12, 0, -1, 'NPC Equip 877', -1, 7099, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (883, 12, 0, -1, 'NPC Equip 883', -1, 7088, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (894, 15, 0, -1, 'NPC Equip 894', -1, 6642, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (898, 12, 0, -1, 'NPC Equip 898', -1, 959, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (901, 15, 0, -1, 'NPC Equip 901', -1, 7014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (902, 15, 0, -1, 'NPC Equip 902', -1, 7014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (903, 15, 0, -1, 'NPC Equip 903', -1, 7014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (905, 4, 1, -1, 'NPC Equip 905', 7, 1057, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (906, 4, 1, -1, 'NPC Equip 906', 7, 1058, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (907, 4, 3, -1, 'NPC Equip 907', 7, 6480, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (908, 4, 1, -1, 'NPC Equip 908', 7, 6545, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (909, 4, 1, -1, 'NPC Equip 909', 7, 6557, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (917, 4, 2, -1, 'NPC Equip 917', 8, 1080, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (930, 1, 0, -1, 'NPC Equip 930', 7, 1283, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (941, 4, 0, -1, 'NPC Equip 941', -1, 6513, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (945, 2, 7, -1, 'NPC Equip 945', 1, 859, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (948, 2, 7, -1, 'NPC Equip 948', 1, 859, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (951, 0, 8, -1, 'NPC Equip 951', 0, 1093, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (965, 1, 0, -1, 'NPC Equip 965', 7, 981, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (966, 9, 0, -1, 'NPC Equip 966', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (967, 9, 0, -1, 'NPC Equip 967', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (968, 9, 0, -1, 'NPC Equip 968', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (973, 9, 0, -1, 'NPC Equip 973', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (974, 9, 0, -1, 'NPC Equip 974', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (975, 9, 0, -1, 'NPC Equip 975', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (976, 9, 0, -1, 'NPC Equip 976', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (980, 9, 0, -1, 'NPC Equip 980', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (985, 9, 0, -1, 'NPC Equip 985', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (986, 9, 0, -1, 'NPC Equip 986', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (989, 9, 0, -1, 'NPC Equip 989', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (992, 9, 0, -1, 'NPC Equip 992', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (994, 9, 0, -1, 'NPC Equip 994', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1002, 9, 0, -1, 'NPC Equip 1002', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1004, 9, 0, -1, 'NPC Equip 1004', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1016, 15, 0, -1, 'NPC Equip 1016', -1, 6619, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1018, 2, 7, -1, 'NPC Equip 1018', 1, 1121, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1022, 4, 2, -1, 'NPC Equip 1022', 8, 15299, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1023, 4, 2, -1, 'NPC Equip 1023', 8, 15297, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1026, 4, 4, -1, 'NPC Equip 1026', 8, 15305, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1030, 9, 0, -1, 'NPC Equip 1030', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1031, 9, 0, -1, 'NPC Equip 1031', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1032, 9, 0, -1, 'NPC Equip 1032', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1033, 9, 0, -1, 'NPC Equip 1033', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1034, 9, 0, -1, 'NPC Equip 1034', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1035, 9, 0, -1, 'NPC Equip 1035', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1036, 9, 0, -1, 'NPC Equip 1036', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1037, 9, 0, -1, 'NPC Equip 1037', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1038, 9, 0, -1, 'NPC Equip 1038', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1042, 15, 0, -1, 'NPC Equip 1042', -1, 7015, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1043, 15, 0, -1, 'NPC Equip 1043', -1, 7015, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1044, 15, 0, -1, 'NPC Equip 1044', -1, 7015, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1046, 2, 3, -1, 'NPC Equip 1046', 1, 6596, 26, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1047, 2, 3, -1, 'NPC Equip 1047', 1, 6595, 26, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1048, 9, 0, -1, 'NPC Equip 1048', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1049, 9, 0, -1, 'NPC Equip 1049', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1052, 9, 0, -1, 'NPC Equip 1052', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1053, 9, 0, -1, 'NPC Equip 1053', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1058, 9, 0, -1, 'NPC Equip 1058', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1061, 9, 0, -1, 'NPC Equip 1061', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1063, 9, 0, -1, 'NPC Equip 1063', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1072, 0, 5, -1, 'NPC Equip 1072', -1, 18080, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1078, 12, 0, -1, 'NPC Equip 1078', -1, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1084, 9, 0, -1, 'NPC Equip 1084', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1085, 9, 0, -1, 'NPC Equip 1085', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1086, 9, 0, -1, 'NPC Equip 1086', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1087, 9, 0, -1, 'NPC Equip 1087', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1088, 9, 0, -1, 'NPC Equip 1088', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1089, 9, 0, -1, 'NPC Equip 1089', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1090, 9, 0, -1, 'NPC Equip 1090', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1091, 9, 0, -1, 'NPC Equip 1091', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1092, 9, 0, -1, 'NPC Equip 1092', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1093, 9, 0, -1, 'NPC Equip 1093', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1095, 9, 0, -1, 'NPC Equip 1095', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1096, 9, 0, -1, 'NPC Equip 1096', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1099, 9, 0, -1, 'NPC Equip 1099', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1100, 1, 0, -1, 'NPC Equip 1100', 8, 21586, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1101, 9, 0, -1, 'NPC Equip 1101', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1102, 9, 0, -1, 'NPC Equip 1102', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1105, 9, 0, -1, 'NPC Equip 1105', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1108, 9, 0, -1, 'NPC Equip 1108', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1109, 9, 0, -1, 'NPC Equip 1109', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1111, 9, 0, -1, 'NPC Equip 1111', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1112, 9, 0, -1, 'NPC Equip 1112', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1115, 12, 0, -1, 'NPC Equip 1115', -1, 7097, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1117, 2, 4, -1, 'NPC Equip 1117', 2, 7453, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1119, 0, 5, -1, 'NPC Equip 1119', -1, 18077, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1122, 4, 0, -1, 'NPC Equip 1122', -1, 6494, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1123, 4, 0, -1, 'NPC Equip 1123', -1, 6494, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1124, 4, 0, -1, 'NPC Equip 1124', -1, 6494, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1125, 12, 0, -1, 'NPC Equip 1125', 1, 6494, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1128, 0, 8, -1, 'NPC Equip 1128', -1, 1150, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1136, 9, 0, -1, 'NPC Equip 1136', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1138, 9, 0, -1, 'NPC Equip 1138', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1139, 9, 0, -1, 'NPC Equip 1139', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1141, 9, 0, -1, 'NPC Equip 1141', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1144, 9, 0, -1, 'NPC Equip 1144', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1149, 9, 0, -1, 'NPC Equip 1149', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1150, 9, 0, -1, 'NPC Equip 1150', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1151, 9, 0, -1, 'NPC Equip 1151', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1157, 2, 0, -1, 'NPC Equip 1157', 1, 5066, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1163, 4, 1, -1, 'NPC Equip 1163', 7, 13218, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1164, 9, 0, -1, 'NPC Equip 1164', -1, 49933, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1165, 0, 5, -1, 'NPC Equip 1165', -1, 6422, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1170, 4, 2, -1, 'NPC Equip 1170', 8, 8647, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1174, 4, 3, -1, 'NPC Equip 1174', 5, 6956, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1176, 0, 0, -1, 'NPC Equip 1176', -1, 6412, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1184, 4, 0, -1, 'NPC Equip 1184', 1, 6510, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1186, 4, 0, -1, 'NPC Equip 1186', 7, 6503, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1199, 0, 0, -1, 'NPC Equip 1199', 3, 6014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1216, 4, 1, -1, 'NPC Equip 1216', 7, 9559, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1224, 9, 0, -1, 'NPC Equip 1224', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1228, 9, 0, -1, 'NPC Equip 1228', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1229, 9, 0, -1, 'NPC Equip 1229', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1231, 9, 0, -1, 'NPC Equip 1231', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1232, 9, 0, -1, 'NPC Equip 1232', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1238, 9, 0, -1, 'NPC Equip 1238', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1239, 9, 0, -1, 'NPC Equip 1239', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1243, 9, 0, -1, 'NPC Equip 1243', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1244, 9, 0, -1, 'NPC Equip 1244', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1245, 9, 0, -1, 'NPC Equip 1245', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1246, 9, 0, -1, 'NPC Equip 1246', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1250, 9, 0, -1, 'NPC Equip 1250', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1253, 13, 1, -1, 'NPC Equip 1253', 1, 6707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1258, 4, 0, -1, 'NPC Equip 1258', 1, 6511, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1266, 2, 8, -1, 'NPC Equip 1266', 1, 4909, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1267, 0, 8, -1, 'NPC Equip 1267', -1, 6359, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1268, 0, 8, -1, 'NPC Equip 1268', -1, 2357, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1269, 0, 8, -1, 'NPC Equip 1269', -1, 6367, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1272, 4, 1, -1, 'NPC Equip 1272', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1279, 4, 2, -1, 'NPC Equip 1279', 8, 13255, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1281, 11, 2, -1, 'NPC Equip 1281', -1, 3337, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1311, 2, 1, -1, 'NPC Equip 1311', 1, 8513, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1312, 2, 4, -1, 'NPC Equip 1312', 2, 8576, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1313, 2, 15, -1, 'NPC Equip 1313', 1, 6458, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1321, 0, 8, -1, 'NPC Equip 1321', -1, 6335, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1323, 9, 0, -1, 'NPC Equip 1323', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1328, 9, 0, -1, 'NPC Equip 1328', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1332, 9, 0, -1, 'NPC Equip 1332', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1334, 9, 0, -1, 'NPC Equip 1334', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1335, 9, 0, -1, 'NPC Equip 1335', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1339, 9, 0, -1, 'NPC Equip 1339', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1341, 9, 0, -1, 'NPC Equip 1341', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1350, 4, 0, -1, 'NPC Equip 1350', -1, 6358, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1354, 4, 1, -1, 'NPC Equip 1354', 7, 8776, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1371, 4, 2, -1, 'NPC Equip 1371', 8, 5495, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1379, 4, 1, -1, 'NPC Equip 1379', 7, 5494, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1385, 2, 5, -1, 'NPC Equip 1385', 2, 8593, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1392, 4, 1, -1, 'NPC Equip 1392', 7, 3642, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1397, 4, 1, -1, 'NPC Equip 1397', 7, 3587, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1398, 4, 1, -1, 'NPC Equip 1398', 7, 1357, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1400, 0, 8, -1, 'NPC Equip 1400', -1, 6418, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1402, 0, 8, -1, 'NPC Equip 1402', -1, 6334, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1403, 4, 0, -1, 'NPC Equip 1403', -1, 6499, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1424, 4, 2, -1, 'NPC Equip 1424', 8, 7836, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1432, 4, 1, -1, 'NPC Equip 1432', 7, 2539, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1435, 4, 2, -1, 'NPC Equip 1435', 8, 2960, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1444, 4, 0, -1, 'NPC Equip 1444', -1, 6504, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1472, 4, 0, -1, 'NPC Equip 1472', -1, 6508, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1492, 9, 0, -1, 'NPC Equip 1492', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1500, 15, 1, -1, 'NPC Equip 1500', 2, 37388, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1508, 4, 2, -1, 'NPC Equip 1508', 8, 2563, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1527, 12, 0, -1, 'NPC Equip 1527', -1, 1442, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1533, 0, 8, -1, 'NPC Equip 1533', -1, 6358, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1534, 9, 0, -1, 'NPC Equip 1534', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1535, 4, 2, -1, 'NPC Equip 1535', 8, 1787, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1536, 9, 0, -1, 'NPC Equip 1536', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1544, 4, 0, -1, 'NPC Equip 1544', -1, 6498, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1545, 4, 1, -1, 'NPC Equip 1545', 7, 2539, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1554, 9, 0, -1, 'NPC Equip 1554', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1559, 9, 0, -1, 'NPC Equip 1559', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1567, 9, 0, -1, 'NPC Equip 1567', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1568, 9, 0, -1, 'NPC Equip 1568', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1571, 9, 0, -1, 'NPC Equip 1571', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1574, 9, 0, -1, 'NPC Equip 1574', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1588, 9, 0, -1, 'NPC Equip 1588', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1589, 9, 0, -1, 'NPC Equip 1589', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1591, 9, 0, -1, 'NPC Equip 1591', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1597, 9, 0, -1, 'NPC Equip 1597', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1599, 9, 0, -1, 'NPC Equip 1599', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1603, 9, 0, -1, 'NPC Equip 1603', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1612, 0, 8, -1, 'NPC Equip 1612', -1, 6368, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1619, 9, 0, -1, 'NPC Equip 1619', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1622, 4, 0, -1, 'NPC Equip 1622', 7, 6501, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1638, 7, 11, -1, 'NPC Equip 1638', -1, 6623, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1641, 9, 0, -1, 'NPC Equip 1641', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1648, 9, 0, -1, 'NPC Equip 1648', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1649, 0, 8, -1, 'NPC Equip 1649', -1, 1483, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1651, 9, 0, -1, 'NPC Equip 1651', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1654, 7, 11, -1, 'NPC Equip 1654', -1, 7356, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1655, 9, 0, -1, 'NPC Equip 1655', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1657, 9, 0, -1, 'NPC Equip 1657', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1658, 9, 0, -1, 'NPC Equip 1658', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1663, 12, 0, -1, 'NPC Equip 1663', -1, 1322, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1676, 9, 0, -1, 'NPC Equip 1676', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1681, 9, 0, -1, 'NPC Equip 1681', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1684, 4, 2, -1, 'NPC Equip 1684', 8, 13256, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1689, 7, 11, -1, 'NPC Equip 1689', 8, 7354, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1690, 15, 0, -1, 'NPC Equip 1690', 8, 1007, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1691, 15, 0, -1, 'NPC Equip 1691', -1, 6360, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1692, 12, 0, -1, 'NPC Equip 1692', -1, 959, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1693, 7, 11, -1, 'NPC Equip 1693', 8, 6655, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1694, 7, 11, -1, 'NPC Equip 1694', 8, 6655, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1695, 7, 11, -1, 'NPC Equip 1695', 8, 6655, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1698, 12, 0, -1, 'NPC Equip 1698', -1, 1498, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1699, 12, 0, -1, 'NPC Equip 1699', -1, 6665, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1704, 0, 8, -1, 'NPC Equip 1704', -1, 1504, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1719, 2, 0, -1, 'NPC Equip 1719', 1, 7429, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1724, 1, 0, -1, 'NPC Equip 1724', 8, 2592, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1736, 4, 3, -1, 'NPC Equip 1736', 5, 6906, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1851, 0, 8, -1, 'NPC Equip 1851', -1, 6340, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1854, 4, 0, -1, 'NPC Equip 1854', 4, 6497, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1877, 9, 0, -1, 'NPC Equip 1877', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1878, 9, 0, -1, 'NPC Equip 1878', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1880, 9, 0, -1, 'NPC Equip 1880', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1882, 9, 0, -1, 'NPC Equip 1882', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1886, 9, 0, -1, 'NPC Equip 1886', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1895, 2, 7, -1, 'NPC Equip 1895', 1, 7488, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1896, 2, 7, -1, 'NPC Equip 1896', 1, 7487, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1897, 2, 7, -1, 'NPC Equip 1897', 1, 7485, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1899, 2, 7, -1, 'NPC Equip 1899', 1, 7483, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1900, 2, 7, -1, 'NPC Equip 1900', 1, 7492, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1901, 2, 4, -1, 'NPC Equip 1901', 2, 7440, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1903, 2, 4, -1, 'NPC Equip 1903', 2, 7439, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1904, 2, 0, -1, 'NPC Equip 1904', 1, 7429, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1905, 2, 0, -1, 'NPC Equip 1905', 1, 7428, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1906, 2, 4, -1, 'NPC Equip 1906', 2, 12236, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1907, 2, 10, -1, 'NPC Equip 1907', 2, 10654, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1908, 2, 10, -1, 'NPC Equip 1908', 2, 1600, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1909, 2, 0, -1, 'NPC Equip 1909', 1, 7426, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1910, 2, 0, -1, 'NPC Equip 1910', 1, 7493, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1912, 4, 0, -1, 'NPC Equip 1912', 2, 6509, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1915, 15, 0, -1, 'NPC Equip 1915', -1, 1183, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1918, 13, 1, -1, 'NPC Equip 1918', -1, 6706, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1924, 12, 0, -1, 'NPC Equip 1924', 2, 2618, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1940, 12, 0, -1, 'NPC Equip 1940', 8, 18084, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1948, 2, 10, -1, 'NPC Equip 1948', 2, 1661, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1950, 7, 7, -1, 'NPC Equip 1950', 4, 7352, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1957, 4, 6, -1, 'NPC Equip 1957', 1, 1684, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1960, 4, 3, -1, 'NPC Equip 1960', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1961, 4, 6, -1, 'NPC Equip 1961', 1, 1685, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1963, 7, 11, -1, 'NPC Equip 1963', -1, 7350, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1969, 4, 3, -1, 'NPC Equip 1969', 5, 7001, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1983, 2, 8, -1, 'NPC Equip 1983', 1, 7490, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1984, 4, 6, -1, 'NPC Equip 1984', 1, 1705, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1985, 4, 6, -1, 'NPC Equip 1985', 1, 1706, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1995, 0, 0, -1, 'NPC Equip 1995', -1, 1496, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (1999, 4, 2, -1, 'NPC Equip 1999', 8, 1330, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2002, 11, 2, -1, 'NPC Equip 2002', 8, 3337, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2003, 11, 2, -1, 'NPC Equip 2003', -1, 1244, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2012, 4, 0, -1, 'NPC Equip 2012', -1, 6507, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2023, 2, 6, -1, 'NPC Equip 2023', 1, 7481, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2038, 4, 2, -1, 'NPC Equip 2038', 8, 13248, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2045, 4, 1, -1, 'NPC Equip 2045', 7, 13537, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2050, 7, 7, -1, 'NPC Equip 2050', 3, 7355, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2051, 4, 6, -1, 'NPC Equip 2051', 1, 1755, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2052, 4, 6, -1, 'NPC Equip 2052', 1, 1755, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2053, 4, 6, -1, 'NPC Equip 2053', 1, 1757, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2056, 2, 4, -1, 'NPC Equip 2056', 2, 1758, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2060, 7, 11, -1, 'NPC Equip 2060', -1, 1762, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2071, 0, 8, -1, 'NPC Equip 2071', -1, 18084, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2103, 6, 2, -1, 'NPC Equip 2103', 2, 26499, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2104, 6, 3, -1, 'NPC Equip 2104', 2, 5999, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2106, 4, 1, -1, 'NPC Equip 2106', 7, 1818, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2107, 4, 0, -1, 'NPC Equip 2107', 7, 845, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2115, 1, 0, -1, 'NPC Equip 2115', 8, 3237, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2147, 2, 7, -1, 'NPC Equip 2147', 1, 7419, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2170, 4, 6, -1, 'NPC Equip 2170', 1, 3127, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2176, 2, 10, -1, 'NPC Equip 2176', 2, 1926, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2177, 2, 10, -1, 'NPC Equip 2177', 2, 1927, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2178, 2, 7, -1, 'NPC Equip 2178', 1, 7482, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2179, 2, 7, -1, 'NPC Equip 2179', 1, 7420, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2180, 2, 7, -1, 'NPC Equip 2180', 1, 7486, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2181, 2, 8, -1, 'NPC Equip 2181', 1, 7489, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2182, 2, 4, -1, 'NPC Equip 2182', 2, 7438, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2183, 2, 0, -1, 'NPC Equip 2183', 1, 7427, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2189, 2, 4, -1, 'NPC Equip 2189', 2, 1938, 21, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2191, 12, 0, -1, 'NPC Equip 2191', -1, 7087, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2196, 2, 4, -1, 'NPC Equip 2196', 2, 7462, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2197, 2, 4, -1, 'NPC Equip 2197', 2, 7443, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2198, 2, 14, -1, 'NPC Equip 2198', 1, 7465, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2199, 2, 14, -1, 'NPC Equip 2199', 1, 7474, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2200, 2, 14, -1, 'NPC Equip 2200', 1, 7466, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2201, 2, 14, -1, 'NPC Equip 2201', 1, 7473, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2202, 2, 4, -1, 'NPC Equip 2202', 2, 7463, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2206, 2, 15, -1, 'NPC Equip 2206', 1, 6445, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2248, 4, 4, -1, 'NPC Equip 2248', 6, 1184, 4, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2255, 4, 2, -1, 'NPC Equip 2255', 8, 2057, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2301, 4, 2, -1, 'NPC Equip 2301', 8, 2083, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2322, 7, 11, -1, 'NPC Equip 2322', 8, 6644, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2323, 7, 11, -1, 'NPC Equip 2323', 8, 6644, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2363, 13, 0, -1, 'NPC Equip 2363', 0, 6708, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2404, 9, 1, -1, 'NPC Equip 2404', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2405, 9, 1, -1, 'NPC Equip 2405', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2412, 15, 0, -1, 'NPC Equip 2412', -1, 1007, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2461, 0, 1, -1, 'NPC Equip 2461', 3, 2357, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2462, 0, 1, -1, 'NPC Equip 2462', 3, 1805, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2478, 4, 0, -1, 'NPC Equip 2478', 1, 1805, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2513, 6, 3, -1, 'NPC Equip 2513', 2, 5998, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2514, 6, 2, -1, 'NPC Equip 2514', 2, 5996, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2517, 6, 2, -1, 'NPC Equip 2517', 2, 5996, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2518, 6, 3, -1, 'NPC Equip 2518', 2, 5998, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2543, 4, 3, -1, 'NPC Equip 2543', 5, 704, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2551, 2, 18, -1, 'NPC Equip 2551', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2552, 2, 3, -1, 'NPC Equip 2552', 1, 6593, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2554, 9, 6, -1, 'NPC Equip 2554', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2557, 2, 5, -1, 'NPC Equip 2557', 2, 2466, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2558, 2, 4, -1, 'NPC Equip 2558', 2, 7442, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2559, 2, 10, -1, 'NPC Equip 2559', 2, 2469, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2573, 4, 1, -1, 'NPC Equip 2573', 7, 2489, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2574, 4, 1, -1, 'NPC Equip 2574', 7, 2490, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2600, 9, 1, -1, 'NPC Equip 2600', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2602, 9, 1, -1, 'NPC Equip 2602', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2647, 4, 3, -1, 'NPC Equip 2647', 5, 6906, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2655, 4, 3, -1, 'NPC Equip 2655', 5, 6914, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2669, 12, 0, -1, 'NPC Equip 2669', -1, 6651, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2688, 0, 8, -1, 'NPC Equip 2688', 3, 6417, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2695, 2, 4, -1, 'NPC Equip 2695', 2, 7432, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2703, 2, 14, -1, 'NPC Equip 2703', 1, 24596, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2704, 2, 14, -1, 'NPC Equip 2704', 1, 24594, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2706, 2, 14, -1, 'NPC Equip 2706', 1, 7454, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2707, 2, 14, -1, 'NPC Equip 2707', 1, 7456, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2708, 2, 14, -1, 'NPC Equip 2708', 1, 7448, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2709, 2, 14, -1, 'NPC Equip 2709', 1, 7455, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2710, 2, 14, -1, 'NPC Equip 2710', 1, 7447, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2711, 2, 15, -1, 'NPC Equip 2711', 1, 7433, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2714, 2, 14, -1, 'NPC Equip 2714', 1, 7461, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2716, 2, 14, -1, 'NPC Equip 2716', 1, 7446, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2717, 2, 14, -1, 'NPC Equip 2717', 1, 7445, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2718, 2, 14, -1, 'NPC Equip 2718', 1, 7457, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2761, 12, 0, -1, 'NPC Equip 2761', -1, 2760, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2762, 12, 0, -1, 'NPC Equip 2762', -1, 2760, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2767, 12, 0, -1, 'NPC Equip 2767', -1, 1695, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2789, 13, 1, -1, 'NPC Equip 2789', 4, 6707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2790, 13, 1, -1, 'NPC Equip 2790', 4, 6707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2791, 13, 1, -1, 'NPC Equip 2791', 4, 6707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2792, 13, 1, -1, 'NPC Equip 2792', 4, 6707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2793, 12, 0, -1, 'NPC Equip 2793', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2803, 4, 0, -1, 'NPC Equip 2803', -1, 6514, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2804, 4, 0, -1, 'NPC Equip 2804', -1, 6502, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2809, 2, 4, -1, 'NPC Equip 2809', 2, 7476, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2811, 2, 10, -1, 'NPC Equip 2811', 2, 7308, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2812, 2, 15, -1, 'NPC Equip 2812', 1, 6448, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2813, 2, 4, -1, 'NPC Equip 2813', 2, 7478, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2814, 2, 5, -1, 'NPC Equip 2814', 2, 3151, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2826, 4, 0, -1, 'NPC Equip 2826', -1, 6497, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2827, 2, 0, -1, 'NPC Equip 2827', 1, 7431, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2884, 2, 4, -1, 'NPC Equip 2884', 2, 26367, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2887, 15, 0, -1, 'NPC Equip 2887', 8, 6687, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2890, 15, 0, -1, 'NPC Equip 2890', 8, 6684, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2895, 15, 1, -1, 'NPC Equip 2895', 3, 2947, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2896, 15, 1, -1, 'NPC Equip 2896', 3, 2947, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2919, 4, 0, -1, 'NPC Equip 2919', 2, 6526, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2923, 4, 0, -1, 'NPC Equip 2923', 2, 6550, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2935, 12, 0, -1, 'NPC Equip 2935', -1, 3004, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2936, 12, 0, -1, 'NPC Equip 2936', -1, 3004, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2937, 12, 0, -1, 'NPC Equip 2937', -1, 3004, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2945, 12, 0, -1, 'NPC Equip 2945', 1, 16754, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2948, 4, 0, -1, 'NPC Equip 2948', 4, 6515, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2952, 4, 2, -1, 'NPC Equip 2952', 8, 3040, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2993, 4, 2, -1, 'NPC Equip 2993', 8, 13252, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (2994, 4, 1, -1, 'NPC Equip 2994', 7, 13217, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3001, 4, 0, -1, 'NPC Equip 3001', 2, 18087, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3002, 4, 0, -1, 'NPC Equip 3002', 2, 6338, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3006, 4, 0, -1, 'NPC Equip 3006', 2, 6521, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3007, 4, 3, -1, 'NPC Equip 3007', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3015, 4, 0, -1, 'NPC Equip 3015', -1, 18109, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3028, 2, 2, -1, 'NPC Equip 3028', 2, 8104, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3029, 6, 2, -1, 'NPC Equip 3029', 2, 5996, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3032, 6, 3, -1, 'NPC Equip 3032', 2, 5998, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3038, 2, 2, -1, 'NPC Equip 3038', 2, 3185, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3043, 6, 2, -1, 'NPC Equip 3043', 2, 2414, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3044, 2, 4, -1, 'NPC Equip 3044', 2, 3191, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3050, 4, 3, -1, 'NPC Equip 3050', 5, 3058, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3051, 4, 3, -1, 'NPC Equip 3051', 5, 6901, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3054, 4, 3, -1, 'NPC Equip 3054', 5, 6898, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3059, 4, 2, -1, 'NPC Equip 3059', 8, 13252, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3060, 4, 2, -1, 'NPC Equip 3060', 8, 6730, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3061, 4, 2, -1, 'NPC Equip 3061', 8, 9112, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3064, 4, 2, -1, 'NPC Equip 3064', 8, 3205, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3077, 4, 1, -1, 'NPC Equip 3077', 7, 13542, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3088, 9, 0, -1, 'NPC Equip 3088', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3089, 9, 0, -1, 'NPC Equip 3089', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3090, 9, 0, -1, 'NPC Equip 3090', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3091, 9, 0, -1, 'NPC Equip 3091', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3092, 9, 0, -1, 'NPC Equip 3092', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3093, 9, 0, -1, 'NPC Equip 3093', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3094, 9, 0, -1, 'NPC Equip 3094', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3095, 9, 0, -1, 'NPC Equip 3095', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3096, 9, 0, -1, 'NPC Equip 3096', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3097, 9, 0, -1, 'NPC Equip 3097', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3098, 9, 0, -1, 'NPC Equip 3098', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3099, 9, 0, -1, 'NPC Equip 3099', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3100, 9, 0, -1, 'NPC Equip 3100', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3101, 9, 0, -1, 'NPC Equip 3101', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3102, 9, 0, -1, 'NPC Equip 3102', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3104, 15, 0, -1, 'NPC Equip 3104', -1, 3155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3105, 15, 0, -1, 'NPC Equip 3105', -1, 3155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3106, 15, 0, -1, 'NPC Equip 3106', -1, 3155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3109, 12, 0, -1, 'NPC Equip 3109', 1, 16753, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3112, 9, 0, -1, 'NPC Equip 3112', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3113, 9, 0, -1, 'NPC Equip 3113', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3114, 9, 0, -1, 'NPC Equip 3114', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3115, 9, 0, -1, 'NPC Equip 3115', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3116, 9, 0, -1, 'NPC Equip 3116', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3118, 9, 0, -1, 'NPC Equip 3118', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3119, 9, 0, -1, 'NPC Equip 3119', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3120, 9, 0, -1, 'NPC Equip 3120', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3121, 9, 0, -1, 'NPC Equip 3121', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3123, 9, 0, -1, 'NPC Equip 3123', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3124, 9, 0, -1, 'NPC Equip 3124', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3125, 9, 0, -1, 'NPC Equip 3125', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3126, 9, 0, -1, 'NPC Equip 3126', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3127, 9, 0, -1, 'NPC Equip 3127', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3128, 12, 0, -1, 'NPC Equip 3128', 1, 16755, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3129, 9, 0, -1, 'NPC Equip 3129', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3130, 9, 0, -1, 'NPC Equip 3130', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3132, 9, 0, -1, 'NPC Equip 3132', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3133, 9, 0, -1, 'NPC Equip 3133', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3134, 9, 0, -1, 'NPC Equip 3134', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3136, 12, 0, -1, 'NPC Equip 3136', 1, 35701, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3138, 9, 0, -1, 'NPC Equip 3138', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3139, 9, 0, -1, 'NPC Equip 3139', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3140, 9, 0, -1, 'NPC Equip 3140', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3141, 9, 0, -1, 'NPC Equip 3141', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3142, 9, 0, -1, 'NPC Equip 3142', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3143, 9, 0, -1, 'NPC Equip 3143', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3145, 2, 15, -1, 'NPC Equip 3145', 1, 3288, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3146, 9, 0, -1, 'NPC Equip 3146', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3147, 4, 0, -1, 'NPC Equip 3147', 7, 3289, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3149, 4, 0, -1, 'NPC Equip 3149', 7, 3291, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3150, 4, 1, -1, 'NPC Equip 3150', 7, 3292, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3159, 4, 3, -1, 'NPC Equip 3159', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3215, 4, 3, -1, 'NPC Equip 3215', 5, 6899, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3219, 4, 1, -1, 'NPC Equip 3219', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3221, 4, 1, -1, 'NPC Equip 3221', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3226, 4, 3, -1, 'NPC Equip 3226', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3232, 4, 3, -1, 'NPC Equip 3232', 5, 3409, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3242, 4, 4, -1, 'NPC Equip 3242', 6, 3413, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3243, 4, 4, -1, 'NPC Equip 3243', 6, 3414, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3244, 4, 4, -1, 'NPC Equip 3244', 6, 7017, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3246, 4, 4, -1, 'NPC Equip 3246', 6, 7019, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3247, 4, 3, -1, 'NPC Equip 3247', 5, 6961, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3249, 15, 0, -1, 'NPC Equip 3249', 0, 6632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3259, 15, 0, -1, 'NPC Equip 3259', 8, 11164, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3271, 4, 1, -1, 'NPC Equip 3271', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3278, 2, 7, -1, 'NPC Equip 3278', 1, 3447, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3298, 1, 0, -1, 'NPC Equip 3298', 8, 3410, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3326, 2, 5, -1, 'NPC Equip 3326', 2, 3502, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3333, 4, 3, -1, 'NPC Equip 3333', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3338, 12, 0, -1, 'NPC Equip 3338', -1, 7094, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3346, 2, 6, -1, 'NPC Equip 3346', 1, 7495, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3350, 2, 4, -1, 'NPC Equip 3350', 2, 7444, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3351, 2, 14, -1, 'NPC Equip 3351', 2, 7468, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3359, 2, 7, -1, 'NPC Equip 3359', 1, 1115, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3361, 2, 4, -1, 'NPC Equip 3361', 2, 7477, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3362, 2, 14, -1, 'NPC Equip 3362', 2, 7449, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3364, 2, 7, -1, 'NPC Equip 3364', 1, 7484, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3366, 2, 8, -1, 'NPC Equip 3366', 1, 7491, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3367, 2, 6, -1, 'NPC Equip 3367', 1, 7464, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3398, 2, 14, -1, 'NPC Equip 3398', 4, 3746, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3410, 12, 0, -1, 'NPC Equip 3410', -1, 7089, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3432, 2, 6, -1, 'NPC Equip 3432', 1, 7437, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3433, 2, 6, -1, 'NPC Equip 3433', 1, 7480, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3436, 4, 1, -1, 'NPC Equip 3436', 7, 2539, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3438, 0, 0, -1, 'NPC Equip 3438', -1, 3026, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3441, 0, 8, -1, 'NPC Equip 3441', 2, 2947, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3459, 4, 2, -1, 'NPC Equip 3459', 8, 2563, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3479, 4, 3, -1, 'NPC Equip 3479', 5, 3760, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3494, 2, 13, -1, 'NPC Equip 3494', 1, 7430, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3500, 15, 0, -1, 'NPC Equip 3500', -1, 1046, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3501, 15, 0, -1, 'NPC Equip 3501', -1, 6643, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3503, 15, 0, -1, 'NPC Equip 3503', -1, 1323, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3504, 12, 0, -1, 'NPC Equip 3504', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3507, 0, 8, -1, 'NPC Equip 3507', -1, 983, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3512, 12, 0, -1, 'NPC Equip 3512', -1, 1096, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3519, 12, 0, -1, 'NPC Equip 3519', 2, 1323, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3522, 4, 3, -1, 'NPC Equip 3522', 5, 7421, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3523, 4, 3, -1, 'NPC Equip 3523', 5, 7422, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3524, 4, 3, -1, 'NPC Equip 3524', 5, 6834, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3525, 4, 3, -1, 'NPC Equip 3525', 5, 6835, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3526, 4, 3, -1, 'NPC Equip 3526', 5, 6836, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3527, 4, 3, -1, 'NPC Equip 3527', 5, 7424, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3528, 4, 2, -1, 'NPC Equip 3528', 8, 6764, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3529, 4, 3, -1, 'NPC Equip 3529', 5, 12906, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3532, 4, 2, -1, 'NPC Equip 3532', 8, 6766, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3533, 4, 2, -1, 'NPC Equip 3533', 8, 6762, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3534, 4, 2, -1, 'NPC Equip 3534', 8, 6765, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3535, 4, 2, -1, 'NPC Equip 3535', 8, 6763, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3537, 4, 2, -1, 'NPC Equip 3537', 8, 6722, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3538, 4, 2, -1, 'NPC Equip 3538', 8, 6743, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3539, 4, 2, -1, 'NPC Equip 3539', 8, 6724, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3540, 4, 2, -1, 'NPC Equip 3540', 8, 6745, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3541, 4, 2, -1, 'NPC Equip 3541', 8, 6720, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3542, 4, 2, -1, 'NPC Equip 3542', 8, 6741, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3543, 4, 2, -1, 'NPC Equip 3543', 8, 6723, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3544, 4, 2, -1, 'NPC Equip 3544', 8, 6744, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3545, 4, 2, -1, 'NPC Equip 3545', 8, 6721, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3546, 4, 2, -1, 'NPC Equip 3546', 8, 6742, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3547, 4, 2, -1, 'NPC Equip 3547', 8, 6784, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3548, 4, 2, -1, 'NPC Equip 3548', 8, 6786, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3549, 4, 2, -1, 'NPC Equip 3549', 8, 6785, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3557, 4, 0, -1, 'NPC Equip 3557', 7, 3864, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3568, 1, 0, -1, 'NPC Equip 3568', 8, 1244, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3579, 4, 3, -1, 'NPC Equip 3579', 5, 3747, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3580, 13, 0, -1, 'NPC Equip 3580', -1, 6713, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3620, 12, 0, -1, 'NPC Equip 3620', -1, 7104, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3624, 12, 0, -1, 'NPC Equip 3624', -1, 7038, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3646, 4, 1, -1, 'NPC Equip 3646', 7, 3740, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3677, 12, 0, -1, 'NPC Equip 3677', 2, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3687, 2, 8, -1, 'NPC Equip 3687', 1, 3092, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3694, 4, 0, -1, 'NPC Equip 3694', 2, 6534, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3695, 4, 0, -1, 'NPC Equip 3695', 2, 6535, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3696, 2, 14, -1, 'NPC Equip 3696', 2, 7475, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3697, 4, 0, -1, 'NPC Equip 3697', 2, 6531, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3698, 4, 0, -1, 'NPC Equip 3698', 2, 6532, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3699, 2, 14, -1, 'NPC Equip 3699', 2, 7467, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3700, 12, 0, -1, 'NPC Equip 3700', -1, 2945, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3705, 15, 0, -1, 'NPC Equip 3705', -1, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3709, 12, 0, -1, 'NPC Equip 3709', -1, 2945, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3746, 15, 0, -1, 'NPC Equip 3746', -1, 1244, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3756, 4, 0, -1, 'NPC Equip 3756', 2, 6529, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3757, 4, 0, -1, 'NPC Equip 3757', 2, 6530, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3768, 0, 8, -1, 'NPC Equip 3768', -1, 6326, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3773, 0, 8, -1, 'NPC Equip 3773', 7, 18084, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3788, 4, 0, -1, 'NPC Equip 3788', 2, 6563, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3789, 4, 0, -1, 'NPC Equip 3789', 2, 6554, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3790, 4, 0, -1, 'NPC Equip 3790', 2, 3331, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3791, 4, 0, -1, 'NPC Equip 3791', 2, 6552, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3861, 7, 7, -1, 'NPC Equip 3861', 2, 7356, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3865, 2, 15, -1, 'NPC Equip 3865', 1, 6474, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3878, 15, 0, -1, 'NPC Equip 3878', 1, 1262, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3881, 12, 0, -1, 'NPC Equip 3881', -1, 7038, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3883, 4, 1, -1, 'NPC Equip 3883', 7, 13228, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3885, 4, 3, -1, 'NPC Equip 3885', 5, 13278, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3886, 4, 1, -1, 'NPC Equip 3886', 7, 13539, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3887, 4, 2, -1, 'NPC Equip 3887', 8, 13249, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3888, 4, 3, -1, 'NPC Equip 3888', 5, 13278, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3896, 4, 1, -1, 'NPC Equip 3896', 7, 3749, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3903, 12, 0, -1, 'NPC Equip 3903', -1, 4258, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3929, 12, 0, -1, 'NPC Equip 3929', -1, 7162, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (3933, 2, 7, -1, 'NPC Equip 3933', 1, 7312, 21, 6); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4030, 4, 0, -1, 'NPC Equip 4030', 2, 6381, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4031, 4, 0, -1, 'NPC Equip 4031', 2, 6515, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4032, 4, 0, -1, 'NPC Equip 4032', 2, 6548, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4033, 4, 0, -1, 'NPC Equip 4033', 2, 6496, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4081, 4, 3, -1, 'NPC Equip 4081', 5, 4419, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4095, 15, 0, -1, 'NPC Equip 4095', -1, 7302, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4141, 9, 0, -1, 'NPC Equip 4141', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4142, 9, 0, -1, 'NPC Equip 4142', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4144, 9, 0, -1, 'NPC Equip 4144', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4145, 9, 0, -1, 'NPC Equip 4145', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4146, 9, 0, -1, 'NPC Equip 4146', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4147, 9, 0, -1, 'NPC Equip 4147', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4148, 9, 0, -1, 'NPC Equip 4148', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4149, 9, 0, -1, 'NPC Equip 4149', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4150, 9, 0, -1, 'NPC Equip 4150', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4151, 9, 0, -1, 'NPC Equip 4151', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4152, 9, 0, -1, 'NPC Equip 4152', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4153, 9, 0, -1, 'NPC Equip 4153', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4154, 9, 0, -1, 'NPC Equip 4154', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4155, 9, 0, -1, 'NPC Equip 4155', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4156, 9, 0, -1, 'NPC Equip 4156', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4157, 9, 0, -1, 'NPC Equip 4157', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4158, 9, 0, -1, 'NPC Equip 4158', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4159, 9, 0, -1, 'NPC Equip 4159', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4160, 9, 0, -1, 'NPC Equip 4160', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4161, 9, 0, -1, 'NPC Equip 4161', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4162, 9, 0, -1, 'NPC Equip 4162', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4163, 9, 0, -1, 'NPC Equip 4163', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4164, 9, 0, -1, 'NPC Equip 4164', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4165, 9, 0, -1, 'NPC Equip 4165', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4166, 9, 0, -1, 'NPC Equip 4166', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4167, 9, 0, -1, 'NPC Equip 4167', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4168, 9, 0, -1, 'NPC Equip 4168', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4169, 9, 0, -1, 'NPC Equip 4169', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4170, 9, 0, -1, 'NPC Equip 4170', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4171, 9, 0, -1, 'NPC Equip 4171', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4172, 9, 0, -1, 'NPC Equip 4172', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4173, 9, 0, -1, 'NPC Equip 4173', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4174, 9, 0, -1, 'NPC Equip 4174', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4175, 9, 0, -1, 'NPC Equip 4175', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4176, 9, 0, -1, 'NPC Equip 4176', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4177, 9, 0, -1, 'NPC Equip 4177', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4178, 9, 0, -1, 'NPC Equip 4178', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4179, 9, 0, -1, 'NPC Equip 4179', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4180, 9, 0, -1, 'NPC Equip 4180', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4181, 9, 0, -1, 'NPC Equip 4181', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4182, 9, 0, -1, 'NPC Equip 4182', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4183, 9, 0, -1, 'NPC Equip 4183', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4184, 9, 0, -1, 'NPC Equip 4184', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4185, 9, 0, -1, 'NPC Equip 4185', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4186, 9, 0, -1, 'NPC Equip 4186', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4187, 9, 0, -1, 'NPC Equip 4187', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4188, 9, 0, -1, 'NPC Equip 4188', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4189, 9, 0, -1, 'NPC Equip 4189', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4190, 4, 2, -1, 'NPC Equip 4190', 8, 8660, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4192, 4, 2, -1, 'NPC Equip 4192', 8, 4919, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4194, 4, 2, -1, 'NPC Equip 4194', 8, 4494, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4195, 4, 2, -1, 'NPC Equip 4195', 8, 4493, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4198, 9, 0, -1, 'NPC Equip 4198', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4199, 9, 0, -1, 'NPC Equip 4199', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4201, 9, 0, -1, 'NPC Equip 4201', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4202, 9, 0, -1, 'NPC Equip 4202', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4203, 9, 0, -1, 'NPC Equip 4203', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4204, 9, 0, -1, 'NPC Equip 4204', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4205, 9, 0, -1, 'NPC Equip 4205', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4206, 9, 0, -1, 'NPC Equip 4206', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4207, 9, 0, -1, 'NPC Equip 4207', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4208, 9, 0, -1, 'NPC Equip 4208', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4209, 9, 0, -1, 'NPC Equip 4209', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4210, 9, 0, -1, 'NPC Equip 4210', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4211, 9, 0, -1, 'NPC Equip 4211', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4212, 9, 0, -1, 'NPC Equip 4212', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4214, 9, 0, -1, 'NPC Equip 4214', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4215, 9, 0, -1, 'NPC Equip 4215', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4216, 9, 0, -1, 'NPC Equip 4216', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4217, 9, 0, -1, 'NPC Equip 4217', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4218, 9, 0, -1, 'NPC Equip 4218', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4219, 9, 0, -1, 'NPC Equip 4219', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4220, 9, 0, -1, 'NPC Equip 4220', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4221, 9, 0, -1, 'NPC Equip 4221', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4222, 9, 0, -1, 'NPC Equip 4222', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4223, 9, 0, -1, 'NPC Equip 4223', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4224, 9, 0, -1, 'NPC Equip 4224', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4225, 9, 0, -1, 'NPC Equip 4225', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4226, 9, 0, -1, 'NPC Equip 4226', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4227, 9, 0, -1, 'NPC Equip 4227', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4228, 9, 0, -1, 'NPC Equip 4228', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4229, 9, 0, -1, 'NPC Equip 4229', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4230, 9, 0, -1, 'NPC Equip 4230', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4266, 9, 0, -1, 'NPC Equip 4266', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4267, 9, 0, -1, 'NPC Equip 4267', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4268, 9, 0, -1, 'NPC Equip 4268', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4269, 9, 0, -1, 'NPC Equip 4269', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4270, 9, 0, -1, 'NPC Equip 4270', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4271, 9, 0, -1, 'NPC Equip 4271', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4272, 9, 0, -1, 'NPC Equip 4272', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4274, 9, 0, -1, 'NPC Equip 4274', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4275, 9, 0, -1, 'NPC Equip 4275', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4276, 9, 0, -1, 'NPC Equip 4276', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4277, 9, 0, -1, 'NPC Equip 4277', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4279, 9, 0, -1, 'NPC Equip 4279', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4280, 9, 0, -1, 'NPC Equip 4280', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4281, 9, 0, -1, 'NPC Equip 4281', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4282, 9, 0, -1, 'NPC Equip 4282', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4283, 9, 0, -1, 'NPC Equip 4283', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4284, 9, 0, -1, 'NPC Equip 4284', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4285, 9, 0, -1, 'NPC Equip 4285', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4286, 9, 0, -1, 'NPC Equip 4286', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4287, 9, 0, -1, 'NPC Equip 4287', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4288, 9, 0, -1, 'NPC Equip 4288', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4295, 9, 1, -1, 'NPC Equip 4295', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4418, 0, 5, -1, 'NPC Equip 4418', -1, 6342, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4420, 0, 0, -1, 'NPC Equip 4420', 7, 1097, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4423, 0, 0, -1, 'NPC Equip 4423', 7, 1097, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4427, 0, 8, -1, 'NPC Equip 4427', 7, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4431, 12, 0, -1, 'NPC Equip 4431', -1, 6614, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4442, 4, 2, -1, 'NPC Equip 4442', 8, 2563, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4451, 15, 0, -1, 'NPC Equip 4451', -1, 7298, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4452, 12, 0, -1, 'NPC Equip 4452', -1, 6521, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4475, 15, 0, -1, 'NPC Equip 4475', 0, 6645, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4486, 15, 0, -1, 'NPC Equip 4486', -1, 6640, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4501, 1, 0, -1, 'NPC Equip 4501', 8, 6430, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4523, 12, 0, -1, 'NPC Equip 4523', -1, 7098, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4559, 12, 0, -1, 'NPC Equip 4559', -1, 6521, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4572, 12, 0, -1, 'NPC Equip 4572', -1, 4282, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4573, 15, 0, -1, 'NPC Equip 4573', -1, 1244, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4574, 4, 3, -1, 'NPC Equip 4574', 5, 4202, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4578, 15, 0, -1, 'NPC Equip 4578', 8, 6641, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4579, 15, 0, -1, 'NPC Equip 4579', 8, 6644, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4617, 12, 0, -1, 'NPC Equip 4617', -1, 4831, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4618, 12, 0, -1, 'NPC Equip 4618', -1, 4832, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4619, 12, 0, -1, 'NPC Equip 4619', -1, 4833, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4620, 12, 0, -1, 'NPC Equip 4620', -1, 3093, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4642, 4, 0, -1, 'NPC Equip 4642', 3, 4843, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4651, 12, 0, -1, 'NPC Equip 4651', -1, 4742, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4657, 4, 3, -1, 'NPC Equip 4657', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4664, 4, 2, -1, 'NPC Equip 4664', 8, 2563, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4667, 4, 3, -1, 'NPC Equip 4667', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4670, 4, 1, -1, 'NPC Equip 4670', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4673, 4, 2, -1, 'NPC Equip 4673', 8, 2563, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4679, 4, 3, -1, 'NPC Equip 4679', 5, 6832, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4682, 4, 1, -1, 'NPC Equip 4682', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4685, 4, 1, -1, 'NPC Equip 4685', 7, 3396, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4691, 4, 2, -1, 'NPC Equip 4691', 8, 2563, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4728, 4, 3, -1, 'NPC Equip 4728', 5, 7004, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4730, 2, 0, -1, 'NPC Equip 4730', 1, 6261, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4747, 12, 0, -1, 'NPC Equip 4747', -1, 6414, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4748, 12, 0, -1, 'NPC Equip 4748', -1, 6414, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4750, 4, 0, -1, 'NPC Equip 4750', 2, 6566, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4754, 12, 0, -1, 'NPC Equip 4754', -1, 18083, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4756, 15, 0, -1, 'NPC Equip 4756', 8, 6685, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4760, 4, 0, -1, 'NPC Equip 4760', 2, 6566, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4762, 4, 0, -1, 'NPC Equip 4762', 2, 6566, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4764, 4, 2, -1, 'NPC Equip 4764', 8, 6716, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4811, 4, 2, -1, 'NPC Equip 4811', 8, 6781, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4812, 4, 3, -1, 'NPC Equip 4812', 5, 6879, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4815, 4, 3, -1, 'NPC Equip 4815', 5, 6935, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4839, 12, 0, -1, 'NPC Equip 4839', -1, 7086, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4842, 0, 0, -1, 'NPC Equip 4842', 0, 6421, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4853, 4, 2, -1, 'NPC Equip 4853', 8, 15330, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4855, 4, 1, -1, 'NPC Equip 4855', 7, 5093, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4856, 4, 1, -1, 'NPC Equip 4856', 7, 5094, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4857, 4, 1, -1, 'NPC Equip 4857', 7, 5115, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4884, 12, 0, -1, 'NPC Equip 4884', -1, 7252, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4885, 12, 0, -1, 'NPC Equip 4885', -1, 7156, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4889, 12, 0, -1, 'NPC Equip 4889', -1, 2599, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4899, 2, 18, -1, 'NPC Equip 4899', 2, 10672, 26, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4900, 2, 17, -1, 'NPC Equip 4900', 2, 5289, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4901, 2, 6, -1, 'NPC Equip 4901', 1, 5290, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4902, 2, 19, -1, 'NPC Equip 4902', 2, 6098, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4927, 12, 0, -1, 'NPC Equip 4927', -1, 8382, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4934, 4, 1, -1, 'NPC Equip 4934', 7, 5394, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4943, 2, 5, -1, 'NPC Equip 4943', 2, 8691, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4950, 4, 6, -1, 'NPC Equip 4950', 1, 5411, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4955, 4, 2, -1, 'NPC Equip 4955', 8, 5414, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4956, 2, 14, -1, 'NPC Equip 4956', 2, 6566, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4966, 12, 0, -1, 'NPC Equip 4966', -1, 7163, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4985, 2, 19, -1, 'NPC Equip 4985', 2, 6109, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4991, 2, 8, -1, 'NPC Equip 4991', 1, 5175, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4993, 2, 4, -1, 'NPC Equip 4993', 2, 7469, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4994, 2, 14, -1, 'NPC Equip 4994', 1, 5569, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4996, 2, 4, -1, 'NPC Equip 4996', 2, 6798, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (4997, 9, 5, -1, 'NPC Equip 4997', 2, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5014, 0, 8, -1, 'NPC Equip 5014', 0, 6429, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5015, 0, 8, -1, 'NPC Equip 5015', 0, 6429, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5031, 2, 8, -1, 'NPC Equip 5031', 1, 5536, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5032, 2, 8, -1, 'NPC Equip 5032', 1, 5125, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5033, 2, 8, -1, 'NPC Equip 5033', 1, 5125, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5034, 2, 8, -1, 'NPC Equip 5034', 1, 5125, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5035, 2, 8, -1, 'NPC Equip 5035', 1, 5125, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5036, 2, 8, -1, 'NPC Equip 5036', 1, 5536, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5037, 2, 8, -1, 'NPC Equip 5037', 1, 5125, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5039, 2, 8, -1, 'NPC Equip 5039', 1, 5125, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5041, 0, 8, -1, 'NPC Equip 5041', 0, 6423, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5045, 0, 8, -1, 'NPC Equip 5045', 0, 6411, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5046, 0, 0, -1, 'NPC Equip 5046', -1, 6394, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5047, 0, 0, -1, 'NPC Equip 5047', -1, 6330, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5049, 0, 8, -1, 'NPC Equip 5049', -1, 6405, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5053, 4, 1, -1, 'NPC Equip 5053', 7, 20406, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5070, 2, 19, -1, 'NPC Equip 5070', 2, 5291, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5090, 4, 0, -1, 'NPC Equip 5090', 7, 7908, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5091, 4, 0, -1, 'NPC Equip 5091', 7, 5805, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5126, 9, 0, -1, 'NPC Equip 5126', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5127, 9, 0, -1, 'NPC Equip 5127', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5129, 9, 0, -1, 'NPC Equip 5129', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5130, 9, 0, -1, 'NPC Equip 5130', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5131, 9, 0, -1, 'NPC Equip 5131', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5132, 9, 0, -1, 'NPC Equip 5132', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5139, 9, 0, -1, 'NPC Equip 5139', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5141, 9, 0, -1, 'NPC Equip 5141', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5142, 9, 0, -1, 'NPC Equip 5142', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5144, 9, 0, -1, 'NPC Equip 5144', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5145, 9, 0, -1, 'NPC Equip 5145', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5146, 9, 0, -1, 'NPC Equip 5146', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5147, 9, 0, -1, 'NPC Equip 5147', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5148, 9, 0, -1, 'NPC Equip 5148', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5149, 9, 0, -1, 'NPC Equip 5149', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5151, 9, 0, -1, 'NPC Equip 5151', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5152, 9, 0, -1, 'NPC Equip 5152', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5153, 9, 0, -1, 'NPC Equip 5153', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5154, 9, 0, -1, 'NPC Equip 5154', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5155, 9, 0, -1, 'NPC Equip 5155', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5156, 9, 0, -1, 'NPC Equip 5156', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5157, 9, 0, -1, 'NPC Equip 5157', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5158, 9, 0, -1, 'NPC Equip 5158', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5159, 9, 0, -1, 'NPC Equip 5159', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5160, 9, 0, -1, 'NPC Equip 5160', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5161, 9, 0, -1, 'NPC Equip 5161', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5162, 9, 0, -1, 'NPC Equip 5162', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5163, 9, 0, -1, 'NPC Equip 5163', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5171, 12, 0, -1, 'NPC Equip 5171', -1, 6521, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5172, 15, 1, -1, 'NPC Equip 5172', -1, 6354, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5174, 12, 0, -1, 'NPC Equip 5174', -1, 7187, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5222, 4, 0, -1, 'NPC Equip 5222', 1, 6001, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5223, 0, 8, -1, 'NPC Equip 5223', 1, 1262, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5224, 0, 0, -1, 'NPC Equip 5224', 0, 6000, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5225, 0, 0, -1, 'NPC Equip 5225', 0, 6000, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5226, 4, 0, -1, 'NPC Equip 5226', 1, 6001, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5227, 0, 8, -1, 'NPC Equip 5227', 1, 1262, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5228, 0, 8, -1, 'NPC Equip 5228', 1, 6007, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5230, 4, 0, -1, 'NPC Equip 5230', 1, 6008, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5231, 4, 0, -1, 'NPC Equip 5231', 1, 6008, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5258, 2, 2, -1, 'NPC Equip 5258', 2, 6231, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5260, 2, 2, -1, 'NPC Equip 5260', 2, 6233, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5261, 2, 2, -1, 'NPC Equip 5261', 2, 6234, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5262, 2, 2, -1, 'NPC Equip 5262', 2, 6235, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5264, 12, 0, -1, 'NPC Equip 5264', -1, 6244, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5265, 0, 5, -1, 'NPC Equip 5265', -1, 18117, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5276, 2, 10, -1, 'NPC Equip 5276', 2, 5010, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5277, 2, 10, -1, 'NPC Equip 5277', 2, 5542, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5278, 2, 15, -1, 'NPC Equip 5278', 1, 6434, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5280, 2, 15, -1, 'NPC Equip 5280', 1, 6441, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5281, 2, 15, -1, 'NPC Equip 5281', 1, 6443, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5282, 2, 15, -1, 'NPC Equip 5282', 1, 6447, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5284, 2, 15, -1, 'NPC Equip 5284', 1, 6454, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5285, 2, 15, -1, 'NPC Equip 5285', 1, 6469, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5286, 2, 0, -1, 'NPC Equip 5286', 1, 7508, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5287, 2, 1, -1, 'NPC Equip 5287', 1, 3385, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5288, 2, 1, -1, 'NPC Equip 5288', 1, 5128, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5289, 2, 1, -1, 'NPC Equip 5289', 1, 3797, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5290, 2, 2, -1, 'NPC Equip 5290', 2, 4441, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5291, 2, 4, -1, 'NPC Equip 5291', 2, 5224, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5292, 2, 5, -1, 'NPC Equip 5292', 2, 2777, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5293, 2, 5, -1, 'NPC Equip 5293', 2, 6799, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5294, 4, 2, -1, 'NPC Equip 5294', 8, 9587, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5295, 4, 2, -1, 'NPC Equip 5295', 8, 9587, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5296, 4, 2, -1, 'NPC Equip 5296', 8, 9587, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5297, 4, 2, -1, 'NPC Equip 5297', 8, 9587, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5298, 4, 2, -1, 'NPC Equip 5298', 8, 9587, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5300, 2, 5, -1, 'NPC Equip 5300', 2, 5527, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5301, 2, 5, -1, 'NPC Equip 5301', 2, 3879, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5303, 2, 10, -1, 'NPC Equip 5303', 2, 2840, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5304, 2, 10, -1, 'NPC Equip 5304', 2, 5098, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5305, 2, 7, -1, 'NPC Equip 5305', 1, 7526, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5307, 4, 2, -1, 'NPC Equip 5307', 8, 13300, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5308, 4, 2, -1, 'NPC Equip 5308', 8, 7530, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5331, 15, 0, -1, 'NPC Equip 5331', -1, 7425, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5358, 4, 3, -1, 'NPC Equip 5358', 5, 13282, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5365, 15, 0, -1, 'NPC Equip 5365', -1, 6700, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5372, 12, 0, -1, 'NPC Equip 5372', -1, 8051, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5378, 0, 0, -1, 'NPC Equip 5378', 0, 14964, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5380, 12, 0, -1, 'NPC Equip 5380', -1, 7726, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5381, 12, 0, -1, 'NPC Equip 5381', -1, 7733, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5384, 12, 0, -1, 'NPC Equip 5384', -1, 7737, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5401, 12, 0, -1, 'NPC Equip 5401', -1, 1150, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5402, 12, 0, -1, 'NPC Equip 5402', -1, 1150, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5403, 12, 0, -1, 'NPC Equip 5403', -1, 1150, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5406, 0, 8, -1, 'NPC Equip 5406', 1, 6007, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5407, 0, 8, -1, 'NPC Equip 5407', 1, 6007, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5408, 4, 0, -1, 'NPC Equip 5408', 1, 6008, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5409, 4, 0, -1, 'NPC Equip 5409', 1, 6008, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5434, 15, 0, -1, 'NPC Equip 5434', -1, 7723, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5436, 15, 0, -1, 'NPC Equip 5436', -1, 7723, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5438, 12, 0, -1, 'NPC Equip 5438', -1, 3788, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5449, 12, 0, -1, 'NPC Equip 5449', -1, 7954, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5450, 12, 0, -1, 'NPC Equip 5450', -1, 7954, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5452, 15, 0, -1, 'NPC Equip 5452', -1, 7954, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5453, 12, 0, -1, 'NPC Equip 5453', -1, 7954, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5454, 12, 0, -1, 'NPC Equip 5454', -1, 7954, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5491, 2, 5, -1, 'NPC Equip 5491', 2, 2839, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5497, 7, 0, -1, 'NPC Equip 5497', -1, 8018, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5501, 7, 0, -1, 'NPC Equip 5501', -1, 7380, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5502, 2, 7, -1, 'NPC Equip 5502', 1, 8016, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5532, 2, 14, -1, 'NPC Equip 5532', 1, 8078, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5545, 2, 6, -1, 'NPC Equip 5545', 1, 5290, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5546, 2, 18, -1, 'NPC Equip 5546', 2, 10673, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5548, 2, 2, -1, 'NPC Equip 5548', 2, 3187, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5551, 2, 0, -1, 'NPC Equip 5551', 1, 5066, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5552, 2, 1, -1, 'NPC Equip 5552', 1, 5509, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5553, 2, 4, -1, 'NPC Equip 5553', 2, 5194, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5554, 2, 5, -1, 'NPC Equip 5554', 2, 47303, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5556, 2, 8, -1, 'NPC Equip 5556', 1, 1628, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5557, 2, 17, -1, 'NPC Equip 5557', 1, 5638, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5558, 2, 10, -1, 'NPC Equip 5558', 2, 2388, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5559, 15, 0, -1, 'NPC Equip 5559', 2, 16762, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5561, 2, 14, -1, 'NPC Equip 5561', 1, 8127, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5564, 15, 1, -1, 'NPC Equip 5564', -1, 8132, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5577, 9, 4, -1, 'NPC Equip 5577', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5597, 2, 0, -1, 'NPC Equip 5597', 1, 8376, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5598, 2, 0, -1, 'NPC Equip 5598', 1, 8377, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5599, 2, 0, -1, 'NPC Equip 5599', 1, 8378, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5607, 4, 3, -1, 'NPC Equip 5607', 5, 8399, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5641, 9, 6, -1, 'NPC Equip 5641', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5644, 9, 0, -1, 'NPC Equip 5644', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5647, 9, 0, -1, 'NPC Equip 5647', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5648, 9, 0, -1, 'NPC Equip 5648', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5649, 9, 0, -1, 'NPC Equip 5649', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5650, 9, 0, -1, 'NPC Equip 5650', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5651, 12, 0, -1, 'NPC Equip 5651', -1, 8555, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5652, 12, 0, -1, 'NPC Equip 5652', -1, 8556, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5653, 12, 0, -1, 'NPC Equip 5653', -1, 8557, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5658, 9, 0, -1, 'NPC Equip 5658', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5661, 9, 0, -1, 'NPC Equip 5661', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5662, 9, 0, -1, 'NPC Equip 5662', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5666, 9, 0, -1, 'NPC Equip 5666', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5667, 9, 0, -1, 'NPC Equip 5667', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5670, 9, 0, -1, 'NPC Equip 5670', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5671, 9, 0, -1, 'NPC Equip 5671', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5672, 9, 0, -1, 'NPC Equip 5672', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5673, 9, 0, -1, 'NPC Equip 5673', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5674, 9, 0, -1, 'NPC Equip 5674', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5676, 9, 0, -1, 'NPC Equip 5676', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5677, 9, 0, -1, 'NPC Equip 5677', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5678, 9, 0, -1, 'NPC Equip 5678', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5679, 9, 0, -1, 'NPC Equip 5679', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5680, 9, 0, -1, 'NPC Equip 5680', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5682, 9, 0, -1, 'NPC Equip 5682', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5683, 9, 0, -1, 'NPC Equip 5683', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5684, 9, 0, -1, 'NPC Equip 5684', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5685, 9, 0, -1, 'NPC Equip 5685', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5688, 9, 0, -1, 'NPC Equip 5688', 0, 8616, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5696, 9, 0, -1, 'NPC Equip 5696', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5697, 9, 0, -1, 'NPC Equip 5697', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5698, 9, 0, -1, 'NPC Equip 5698', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5699, 9, 0, -1, 'NPC Equip 5699', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5700, 9, 0, -1, 'NPC Equip 5700', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5701, 9, 0, -1, 'NPC Equip 5701', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5702, 9, 0, -1, 'NPC Equip 5702', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5703, 9, 0, -1, 'NPC Equip 5703', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5704, 9, 0, -1, 'NPC Equip 5704', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5705, 9, 0, -1, 'NPC Equip 5705', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5706, 9, 0, -1, 'NPC Equip 5706', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5707, 9, 0, -1, 'NPC Equip 5707', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5708, 9, 0, -1, 'NPC Equip 5708', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5709, 9, 0, -1, 'NPC Equip 5709', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5710, 9, 0, -1, 'NPC Equip 5710', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5711, 9, 0, -1, 'NPC Equip 5711', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5712, 9, 0, -1, 'NPC Equip 5712', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5713, 9, 0, -1, 'NPC Equip 5713', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5714, 9, 0, -1, 'NPC Equip 5714', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5715, 9, 0, -1, 'NPC Equip 5715', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5716, 9, 0, -1, 'NPC Equip 5716', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5719, 9, 0, -1, 'NPC Equip 5719', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5720, 9, 0, -1, 'NPC Equip 5720', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5721, 9, 0, -1, 'NPC Equip 5721', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5722, 9, 0, -1, 'NPC Equip 5722', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5723, 9, 0, -1, 'NPC Equip 5723', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5724, 9, 0, -1, 'NPC Equip 5724', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5725, 9, 0, -1, 'NPC Equip 5725', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5726, 9, 0, -1, 'NPC Equip 5726', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5727, 9, 0, -1, 'NPC Equip 5727', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5728, 9, 0, -1, 'NPC Equip 5728', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5729, 9, 0, -1, 'NPC Equip 5729', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5730, 9, 0, -1, 'NPC Equip 5730', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5745, 2, 6, -1, 'NPC Equip 5745', 1, 8745, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5746, 2, 6, -1, 'NPC Equip 5746', 1, 8746, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5747, 2, 6, -1, 'NPC Equip 5747', 1, 8747, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5856, 2, 16, -1, 'NPC Equip 5856', 1, 16751, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5857, 12, 0, -1, 'NPC Equip 5857', -1, 9162, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5870, 2, 16, -1, 'NPC Equip 5870', 1, 22671, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5896, 12, 0, -1, 'NPC Equip 5896', -1, 9310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5916, 13, 0, -1, 'NPC Equip 5916', -1, 7737, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5937, 13, 0, -1, 'NPC Equip 5937', -1, 9345, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5949, 12, 0, -1, 'NPC Equip 5949', -1, 9135, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5953, 2, 7, -1, 'NPC Equip 5953', 1, 15804, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (5954, 2, 7, -1, 'NPC Equip 5954', 1, 9465, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6036, 2, 15, -1, 'NPC Equip 6036', 1, 6475, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6088, 2, 16, -1, 'NPC Equip 6088', 2, 19805, 25, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6090, 12, 0, -1, 'NPC Equip 6090', -1, 10453, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6128, 4, 1, -1, 'NPC Equip 6128', 7, 10028, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6132, 9, 0, -1, 'NPC Equip 6132', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6133, 9, 0, -1, 'NPC Equip 6133', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6141, 4, 1, -1, 'NPC Equip 6141', 7, 9913, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6142, 4, 0, -1, 'NPC Equip 6142', 7, 10126, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6143, 4, 0, -1, 'NPC Equip 6143', 7, 9915, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6192, 12, 0, -1, 'NPC Equip 6192', -1, 9666, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6207, 13, 0, -1, 'NPC Equip 6207', -1, 6710, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6208, 13, 0, -1, 'NPC Equip 6208', -1, 6710, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6209, 13, 0, -1, 'NPC Equip 6209', -1, 6710, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6210, 13, 0, -1, 'NPC Equip 6210', -1, 6710, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6213, 0, 8, -1, 'NPC Equip 6213', -1, 4717, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6221, 9, 8, -1, 'NPC Equip 6221', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6222, 9, 8, -1, 'NPC Equip 6222', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6224, 2, 8, -1, 'NPC Equip 6224', 1, 5176, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6228, 2, 14, -1, 'NPC Equip 6228', 1, 10816, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6229, 2, 14, -1, 'NPC Equip 6229', 1, 10817, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6230, 2, 19, -1, 'NPC Equip 6230', 2, 21095, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6231, 2, 19, -1, 'NPC Equip 6231', 2, 21094, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6233, 2, 14, -1, 'NPC Equip 6233', 1, 10821, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6234, 2, 14, -1, 'NPC Equip 6234', 1, 10822, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6235, 2, 14, -1, 'NPC Equip 6235', 1, 10823, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6236, 2, 14, -1, 'NPC Equip 6236', 1, 10824, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6237, 2, 14, -1, 'NPC Equip 6237', 1, 10825, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6244, 0, 0, -1, 'NPC Equip 6244', 0, 10913, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6254, 4, 6, -1, 'NPC Equip 6254', 1, 10968, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6255, 2, 3, -1, 'NPC Equip 6255', 1, 6590, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6262, 12, 0, -1, 'NPC Equip 6262', -1, 7152, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6273, 9, 2, -1, 'NPC Equip 6273', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6322, 2, 10, -1, 'NPC Equip 6322', 2, 11259, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6334, 2, 4, -1, 'NPC Equip 6334', 2, 11289, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6434, 4, 6, -1, 'NPC Equip 6434', 1, 18690, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6437, 12, 0, -1, 'NPC Equip 6437', 1, 11780, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6489, 12, 0, -1, 'NPC Equip 6489', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6493, 12, 0, -1, 'NPC Equip 6493', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6494, 12, 0, -1, 'NPC Equip 6494', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6499, 12, 0, -1, 'NPC Equip 6499', -1, 12222, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6606, 4, 2, -1, 'NPC Equip 6606', 8, 12503, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6618, 2, 4, -1, 'NPC Equip 6618', 2, 8043, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6620, 12, 0, -1, 'NPC Equip 6620', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6621, 9, 0, -1, 'NPC Equip 6621', -1, 12556, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6638, 0, 0, -1, 'NPC Equip 6638', -1, 6340, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6639, 12, 0, -1, 'NPC Equip 6639', -1, 18107, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6644, 15, 4, -1, 'NPC Equip 6644', 8, 24697, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6646, 15, 4, -1, 'NPC Equip 6646', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6673, 4, 0, -1, 'NPC Equip 6673', 5, 9832, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6674, 4, 0, -1, 'NPC Equip 6674', 5, 9832, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6680, 2, 6, -1, 'NPC Equip 6680', 1, 12857, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6683, 12, 0, -1, 'NPC Equip 6683', 1, 12863, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6698, 4, 0, -1, 'NPC Equip 6698', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6706, 4, 0, -1, 'NPC Equip 6706', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6707, 4, 0, -1, 'NPC Equip 6707', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6708, 4, 0, -1, 'NPC Equip 6708', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6711, 4, 0, -1, 'NPC Equip 6711', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6724, 4, 0, -1, 'NPC Equip 6724', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6728, 4, 0, -1, 'NPC Equip 6728', 5, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6734, 9, 4, -1, 'NPC Equip 6734', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6736, 9, 4, -1, 'NPC Equip 6736', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6768, 12, 0, -1, 'NPC Equip 6768', 0, 13005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6769, 12, 0, -1, 'NPC Equip 6769', 0, 13005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6770, 12, 0, -1, 'NPC Equip 6770', 0, 13006, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6771, 12, 0, -1, 'NPC Equip 6771', 0, 13005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6772, 12, 0, -1, 'NPC Equip 6772', 0, 13005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6777, 12, 0, -1, 'NPC Equip 6777', -1, 13006, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6778, 12, 0, -1, 'NPC Equip 6778', 0, 13005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6779, 12, 0, -1, 'NPC Equip 6779', 0, 13005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6837, 4, 0, -1, 'NPC Equip 6837', 7, 13119, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6850, 12, 0, -1, 'NPC Equip 6850', -1, 13128, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6852, 0, 0, -1, 'NPC Equip 6852', -1, 13129, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6886, 2, 16, -1, 'NPC Equip 6886', 1, 16752, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6896, 2, 14, -1, 'NPC Equip 6896', 6, 30610, 10, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6897, 9, 0, -1, 'NPC Equip 6897', -1, 12547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6899, 4, 0, -1, 'NPC Equip 6899', -1, 21597, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (6946, 2, 4, -1, 'NPC Equip 6946', 2, 13455, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7007, 12, 0, -1, 'NPC Equip 7007', -1, 6340, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7066, 4, 1, -1, 'NPC Equip 7066', 7, 13685, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7093, 9, 2, -1, 'NPC Equip 7093', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7147, 0, 0, -1, 'NPC Equip 7147', -1, 13829, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7167, 2, 15, -1, 'NPC Equip 7167', 1, 6471, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7168, 0, 0, -1, 'NPC Equip 7168', 0, 13849, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7169, 2, 15, -1, 'NPC Equip 7169', 1, 13848, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7171, 2, 7, -1, 'NPC Equip 7171', 1, 13585, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7186, 2, 19, -1, 'NPC Equip 7186', 2, 6081, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7246, 12, 0, -1, 'NPC Equip 7246', 0, 12925, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7248, 4, 1, -1, 'NPC Equip 7248', 7, 8801, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7275, 12, 0, -1, 'NPC Equip 7275', -1, 12328, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7299, 4, 1, -1, 'NPC Equip 7299', 7, 22021, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7347, 12, 0, -1, 'NPC Equip 7347', -1, 14307, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7388, 0, 0, -1, 'NPC Equip 7388', -1, 9134, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7425, 12, 0, -1, 'NPC Equip 7425', -1, 3920, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7612, 2, 1, -1, 'NPC Equip 7612', 1, 15576, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7677, 2, 8, -1, 'NPC Equip 7677', 1, 15704, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7706, 2, 5, -1, 'NPC Equip 7706', 2, 15786, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7707, 2, 5, -1, 'NPC Equip 7707', 2, 15795, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7732, 12, 0, -1, 'NPC Equip 7732', 0, 15825, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7826, 2, 10, -1, 'NPC Equip 7826', 2, 15990, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7868, 15, 0, -1, 'NPC Equip 7868', 2, 9288, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7869, 15, 0, -1, 'NPC Equip 7869', -1, 16028, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7872, 7, 11, -1, 'NPC Equip 7872', 1, 7411, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7940, 2, 1, -1, 'NPC Equip 7940', 1, 8533, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7962, 7, 0, -1, 'NPC Equip 7962', 1, 2460, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (7977, 9, 4, -1, 'NPC Equip 7977', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8148, 15, 1, -1, 'NPC Equip 8148', -1, 9660, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8166, 15, 0, -1, 'NPC Equip 8166', -1, 4433, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8243, 0, 5, -1, 'NPC Equip 8243', 0, 16547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8323, 12, 0, -1, 'NPC Equip 8323', 0, 16598, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8388, 9, 1, -1, 'NPC Equip 8388', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8493, 0, 8, -1, 'NPC Equip 8493', -1, 17288, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8502, 15, 0, -1, 'NPC Equip 8502', 1, 12333, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8503, 15, 0, -1, 'NPC Equip 8503', 1, 12333, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8504, 15, 0, -1, 'NPC Equip 8504', 1, 12334, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8505, 15, 0, -1, 'NPC Equip 8505', 1, 12334, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8506, 15, 0, -1, 'NPC Equip 8506', 1, 17329, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8507, 15, 0, -1, 'NPC Equip 8507', 1, 17329, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8543, 0, 5, -1, 'NPC Equip 8543', -1, 15851, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8547, 9, 7, -1, 'NPC Equip 8547', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8706, 12, 0, -1, 'NPC Equip 8706', -1, 7841, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8743, 9, 0, -1, 'NPC Equip 8743', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8744, 9, 0, -1, 'NPC Equip 8744', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8745, 9, 0, -1, 'NPC Equip 8745', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8756, 9, 0, -1, 'NPC Equip 8756', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8757, 9, 0, -1, 'NPC Equip 8757', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8758, 9, 0, -1, 'NPC Equip 8758', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8759, 9, 0, -1, 'NPC Equip 8759', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8760, 9, 0, -1, 'NPC Equip 8760', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8761, 9, 0, -1, 'NPC Equip 8761', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8762, 9, 0, -1, 'NPC Equip 8762', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8763, 9, 0, -1, 'NPC Equip 8763', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8764, 9, 0, -1, 'NPC Equip 8764', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8765, 9, 0, -1, 'NPC Equip 8765', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8767, 9, 0, -1, 'NPC Equip 8767', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8768, 9, 0, -1, 'NPC Equip 8768', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8769, 9, 0, -1, 'NPC Equip 8769', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8770, 9, 0, -1, 'NPC Equip 8770', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8771, 9, 0, -1, 'NPC Equip 8771', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8772, 9, 0, -1, 'NPC Equip 8772', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8773, 9, 0, -1, 'NPC Equip 8773', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8774, 9, 0, -1, 'NPC Equip 8774', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8775, 9, 0, -1, 'NPC Equip 8775', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8776, 9, 0, -1, 'NPC Equip 8776', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8777, 9, 0, -1, 'NPC Equip 8777', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8778, 9, 0, -1, 'NPC Equip 8778', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8779, 9, 0, -1, 'NPC Equip 8779', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8780, 9, 0, -1, 'NPC Equip 8780', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8781, 9, 0, -1, 'NPC Equip 8781', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8782, 9, 0, -1, 'NPC Equip 8782', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8783, 9, 0, -1, 'NPC Equip 8783', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8784, 9, 0, -1, 'NPC Equip 8784', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8785, 9, 0, -1, 'NPC Equip 8785', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8786, 9, 0, -1, 'NPC Equip 8786', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8787, 9, 0, -1, 'NPC Equip 8787', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8788, 9, 0, -1, 'NPC Equip 8788', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8789, 9, 0, -1, 'NPC Equip 8789', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8790, 9, 0, -1, 'NPC Equip 8790', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8791, 9, 0, -1, 'NPC Equip 8791', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8792, 9, 0, -1, 'NPC Equip 8792', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8793, 9, 0, -1, 'NPC Equip 8793', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8794, 9, 0, -1, 'NPC Equip 8794', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8795, 9, 0, -1, 'NPC Equip 8795', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8796, 9, 0, -1, 'NPC Equip 8796', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8797, 9, 0, -1, 'NPC Equip 8797', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8798, 9, 0, -1, 'NPC Equip 8798', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8799, 9, 0, -1, 'NPC Equip 8799', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8800, 9, 0, -1, 'NPC Equip 8800', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8801, 9, 0, -1, 'NPC Equip 8801', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8802, 9, 0, -1, 'NPC Equip 8802', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8803, 9, 0, -1, 'NPC Equip 8803', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8804, 9, 0, -1, 'NPC Equip 8804', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8805, 9, 0, -1, 'NPC Equip 8805', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8806, 9, 0, -1, 'NPC Equip 8806', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8807, 9, 0, -1, 'NPC Equip 8807', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8808, 9, 0, -1, 'NPC Equip 8808', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8809, 9, 0, -1, 'NPC Equip 8809', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8810, 9, 0, -1, 'NPC Equip 8810', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8811, 9, 0, -1, 'NPC Equip 8811', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8812, 9, 0, -1, 'NPC Equip 8812', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8813, 9, 0, -1, 'NPC Equip 8813', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8814, 9, 0, -1, 'NPC Equip 8814', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8815, 9, 0, -1, 'NPC Equip 8815', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8816, 9, 0, -1, 'NPC Equip 8816', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8817, 9, 0, -1, 'NPC Equip 8817', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8818, 9, 0, -1, 'NPC Equip 8818', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8819, 9, 0, -1, 'NPC Equip 8819', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8820, 9, 0, -1, 'NPC Equip 8820', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8821, 9, 0, -1, 'NPC Equip 8821', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8822, 9, 0, -1, 'NPC Equip 8822', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8823, 9, 0, -1, 'NPC Equip 8823', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8824, 9, 0, -1, 'NPC Equip 8824', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8825, 9, 0, -1, 'NPC Equip 8825', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8826, 9, 0, -1, 'NPC Equip 8826', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8828, 9, 0, -1, 'NPC Equip 8828', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8829, 9, 0, -1, 'NPC Equip 8829', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8830, 9, 0, -1, 'NPC Equip 8830', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8832, 9, 0, -1, 'NPC Equip 8832', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8833, 9, 0, -1, 'NPC Equip 8833', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8834, 9, 0, -1, 'NPC Equip 8834', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8835, 9, 0, -1, 'NPC Equip 8835', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8837, 9, 0, -1, 'NPC Equip 8837', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8841, 9, 0, -1, 'NPC Equip 8841', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8842, 9, 0, -1, 'NPC Equip 8842', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8843, 9, 0, -1, 'NPC Equip 8843', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8844, 9, 0, -1, 'NPC Equip 8844', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8847, 9, 0, -1, 'NPC Equip 8847', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8848, 9, 0, -1, 'NPC Equip 8848', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8849, 9, 0, -1, 'NPC Equip 8849', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8850, 9, 0, -1, 'NPC Equip 8850', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8851, 9, 0, -1, 'NPC Equip 8851', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8852, 9, 0, -1, 'NPC Equip 8852', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8853, 9, 0, -1, 'NPC Equip 8853', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8854, 9, 0, -1, 'NPC Equip 8854', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8855, 9, 0, -1, 'NPC Equip 8855', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8856, 9, 0, -1, 'NPC Equip 8856', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8857, 9, 0, -1, 'NPC Equip 8857', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8858, 9, 0, -1, 'NPC Equip 8858', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8859, 9, 0, -1, 'NPC Equip 8859', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8860, 9, 0, -1, 'NPC Equip 8860', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8861, 9, 0, -1, 'NPC Equip 8861', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8862, 9, 0, -1, 'NPC Equip 8862', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8863, 9, 0, -1, 'NPC Equip 8863', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8864, 9, 0, -1, 'NPC Equip 8864', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8865, 9, 0, -1, 'NPC Equip 8865', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8866, 9, 0, -1, 'NPC Equip 8866', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8867, 9, 0, -1, 'NPC Equip 8867', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8868, 9, 0, -1, 'NPC Equip 8868', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8869, 9, 0, -1, 'NPC Equip 8869', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8870, 9, 0, -1, 'NPC Equip 8870', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8871, 9, 0, -1, 'NPC Equip 8871', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8872, 9, 0, -1, 'NPC Equip 8872', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8873, 9, 0, -1, 'NPC Equip 8873', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8874, 9, 0, -1, 'NPC Equip 8874', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8875, 9, 0, -1, 'NPC Equip 8875', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8876, 9, 0, -1, 'NPC Equip 8876', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8877, 9, 0, -1, 'NPC Equip 8877', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8878, 9, 0, -1, 'NPC Equip 8878', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8879, 9, 0, -1, 'NPC Equip 8879', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8880, 9, 0, -1, 'NPC Equip 8880', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8881, 9, 0, -1, 'NPC Equip 8881', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8882, 9, 0, -1, 'NPC Equip 8882', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8883, 9, 0, -1, 'NPC Equip 8883', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8884, 9, 0, -1, 'NPC Equip 8884', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8885, 9, 0, -1, 'NPC Equip 8885', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8886, 9, 0, -1, 'NPC Equip 8886', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8887, 9, 0, -1, 'NPC Equip 8887', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8888, 9, 0, -1, 'NPC Equip 8888', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8889, 9, 0, -1, 'NPC Equip 8889', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8890, 9, 0, -1, 'NPC Equip 8890', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8891, 9, 0, -1, 'NPC Equip 8891', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8892, 9, 0, -1, 'NPC Equip 8892', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8893, 9, 0, -1, 'NPC Equip 8893', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8894, 9, 0, -1, 'NPC Equip 8894', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8895, 9, 0, -1, 'NPC Equip 8895', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8896, 9, 0, -1, 'NPC Equip 8896', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8897, 9, 0, -1, 'NPC Equip 8897', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8898, 9, 0, -1, 'NPC Equip 8898', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8899, 9, 0, -1, 'NPC Equip 8899', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8900, 9, 0, -1, 'NPC Equip 8900', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8901, 9, 0, -1, 'NPC Equip 8901', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8902, 9, 0, -1, 'NPC Equip 8902', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8903, 9, 0, -1, 'NPC Equip 8903', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8904, 9, 0, -1, 'NPC Equip 8904', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8905, 9, 0, -1, 'NPC Equip 8905', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8906, 9, 0, -1, 'NPC Equip 8906', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8907, 9, 0, -1, 'NPC Equip 8907', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8908, 9, 0, -1, 'NPC Equip 8908', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8909, 9, 0, -1, 'NPC Equip 8909', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8910, 9, 0, -1, 'NPC Equip 8910', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8911, 9, 0, -1, 'NPC Equip 8911', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8912, 9, 0, -1, 'NPC Equip 8912', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8913, 9, 0, -1, 'NPC Equip 8913', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8914, 9, 0, -1, 'NPC Equip 8914', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8915, 9, 0, -1, 'NPC Equip 8915', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8916, 9, 0, -1, 'NPC Equip 8916', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8917, 9, 0, -1, 'NPC Equip 8917', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8918, 9, 0, -1, 'NPC Equip 8918', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8919, 9, 0, -1, 'NPC Equip 8919', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8920, 9, 0, -1, 'NPC Equip 8920', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8921, 9, 0, -1, 'NPC Equip 8921', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8922, 9, 0, -1, 'NPC Equip 8922', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8929, 9, 0, -1, 'NPC Equip 8929', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8930, 9, 0, -1, 'NPC Equip 8930', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8931, 9, 0, -1, 'NPC Equip 8931', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8933, 9, 0, -1, 'NPC Equip 8933', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8934, 9, 0, -1, 'NPC Equip 8934', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8935, 9, 0, -1, 'NPC Equip 8935', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8936, 9, 0, -1, 'NPC Equip 8936', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8937, 9, 0, -1, 'NPC Equip 8937', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8938, 9, 0, -1, 'NPC Equip 8938', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8939, 9, 0, -1, 'NPC Equip 8939', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8940, 9, 0, -1, 'NPC Equip 8940', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8941, 9, 0, -1, 'NPC Equip 8941', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8942, 9, 0, -1, 'NPC Equip 8942', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8943, 9, 0, -1, 'NPC Equip 8943', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8944, 9, 0, -1, 'NPC Equip 8944', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8945, 9, 0, -1, 'NPC Equip 8945', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8946, 9, 0, -1, 'NPC Equip 8946', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8947, 9, 0, -1, 'NPC Equip 8947', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8954, 9, 0, -1, 'NPC Equip 8954', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8955, 9, 0, -1, 'NPC Equip 8955', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8958, 9, 0, -1, 'NPC Equip 8958', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8960, 9, 0, -1, 'NPC Equip 8960', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8961, 9, 0, -1, 'NPC Equip 8961', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8962, 9, 0, -1, 'NPC Equip 8962', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8963, 9, 0, -1, 'NPC Equip 8963', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8965, 9, 0, -1, 'NPC Equip 8965', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8966, 9, 0, -1, 'NPC Equip 8966', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8967, 9, 0, -1, 'NPC Equip 8967', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8968, 9, 0, -1, 'NPC Equip 8968', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8969, 9, 0, -1, 'NPC Equip 8969', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8970, 9, 0, -1, 'NPC Equip 8970', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8971, 9, 0, -1, 'NPC Equip 8971', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8972, 9, 0, -1, 'NPC Equip 8972', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8974, 9, 0, -1, 'NPC Equip 8974', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8975, 9, 0, -1, 'NPC Equip 8975', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8976, 9, 0, -1, 'NPC Equip 8976', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8977, 9, 0, -1, 'NPC Equip 8977', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8978, 9, 0, -1, 'NPC Equip 8978', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8979, 9, 0, -1, 'NPC Equip 8979', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8980, 9, 0, -1, 'NPC Equip 8980', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8981, 9, 0, -1, 'NPC Equip 8981', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8982, 9, 0, -1, 'NPC Equip 8982', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8983, 9, 0, -1, 'NPC Equip 8983', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8986, 9, 0, -1, 'NPC Equip 8986', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8987, 9, 0, -1, 'NPC Equip 8987', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8988, 9, 0, -1, 'NPC Equip 8988', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8989, 9, 0, -1, 'NPC Equip 8989', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8990, 9, 0, -1, 'NPC Equip 8990', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8991, 9, 0, -1, 'NPC Equip 8991', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8992, 9, 0, -1, 'NPC Equip 8992', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8994, 9, 0, -1, 'NPC Equip 8994', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8995, 9, 0, -1, 'NPC Equip 8995', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8996, 9, 0, -1, 'NPC Equip 8996', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8997, 9, 0, -1, 'NPC Equip 8997', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8998, 9, 0, -1, 'NPC Equip 8998', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (8999, 9, 0, -1, 'NPC Equip 8999', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9000, 9, 0, -1, 'NPC Equip 9000', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9001, 9, 0, -1, 'NPC Equip 9001', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9002, 9, 0, -1, 'NPC Equip 9002', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9003, 9, 0, -1, 'NPC Equip 9003', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9004, 9, 0, -1, 'NPC Equip 9004', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9005, 9, 0, -1, 'NPC Equip 9005', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9006, 9, 0, -1, 'NPC Equip 9006', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9007, 9, 0, -1, 'NPC Equip 9007', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9008, 9, 0, -1, 'NPC Equip 9008', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9009, 9, 0, -1, 'NPC Equip 9009', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9010, 9, 0, -1, 'NPC Equip 9010', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9011, 9, 0, -1, 'NPC Equip 9011', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9012, 9, 0, -1, 'NPC Equip 9012', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9013, 9, 0, -1, 'NPC Equip 9013', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9014, 9, 0, -1, 'NPC Equip 9014', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9015, 9, 0, -1, 'NPC Equip 9015', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9016, 9, 0, -1, 'NPC Equip 9016', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9017, 9, 0, -1, 'NPC Equip 9017', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9018, 9, 0, -1, 'NPC Equip 9018', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9019, 9, 0, -1, 'NPC Equip 9019', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9020, 9, 0, -1, 'NPC Equip 9020', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9021, 9, 0, -1, 'NPC Equip 9021', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9022, 9, 0, -1, 'NPC Equip 9022', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9023, 9, 0, -1, 'NPC Equip 9023', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9024, 9, 0, -1, 'NPC Equip 9024', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9025, 9, 0, -1, 'NPC Equip 9025', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9026, 9, 0, -1, 'NPC Equip 9026', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9027, 9, 0, -1, 'NPC Equip 9027', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9028, 9, 0, -1, 'NPC Equip 9028', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9029, 9, 0, -1, 'NPC Equip 9029', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9031, 9, 0, -1, 'NPC Equip 9031', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9032, 9, 0, -1, 'NPC Equip 9032', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9033, 9, 0, -1, 'NPC Equip 9033', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9034, 9, 0, -1, 'NPC Equip 9034', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9035, 9, 0, -1, 'NPC Equip 9035', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9037, 9, 0, -1, 'NPC Equip 9037', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9038, 9, 0, -1, 'NPC Equip 9038', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9039, 9, 0, -1, 'NPC Equip 9039', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9040, 9, 0, -1, 'NPC Equip 9040', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9041, 9, 0, -1, 'NPC Equip 9041', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9042, 2, 15, -1, 'NPC Equip 9042', 1, 7430, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9043, 9, 0, -1, 'NPC Equip 9043', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9044, 9, 0, -1, 'NPC Equip 9044', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9045, 9, 0, -1, 'NPC Equip 9045', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9046, 9, 0, -1, 'NPC Equip 9046', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9047, 9, 0, -1, 'NPC Equip 9047', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9048, 9, 0, -1, 'NPC Equip 9048', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9049, 9, 0, -1, 'NPC Equip 9049', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9050, 9, 0, -1, 'NPC Equip 9050', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9051, 9, 0, -1, 'NPC Equip 9051', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9052, 9, 0, -1, 'NPC Equip 9052', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9053, 9, 0, -1, 'NPC Equip 9053', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9054, 9, 0, -1, 'NPC Equip 9054', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9055, 9, 0, -1, 'NPC Equip 9055', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9056, 9, 0, -1, 'NPC Equip 9056', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9057, 9, 0, -1, 'NPC Equip 9057', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9058, 9, 0, -1, 'NPC Equip 9058', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9059, 9, 0, -1, 'NPC Equip 9059', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9062, 9, 0, -1, 'NPC Equip 9062', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9063, 9, 0, -1, 'NPC Equip 9063', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9064, 9, 0, -1, 'NPC Equip 9064', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9065, 9, 0, -1, 'NPC Equip 9065', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9066, 9, 0, -1, 'NPC Equip 9066', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9067, 9, 0, -1, 'NPC Equip 9067', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9068, 9, 0, -1, 'NPC Equip 9068', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9069, 9, 0, -1, 'NPC Equip 9069', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9070, 9, 0, -1, 'NPC Equip 9070', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9071, 9, 0, -1, 'NPC Equip 9071', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9072, 9, 0, -1, 'NPC Equip 9072', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9073, 9, 0, -1, 'NPC Equip 9073', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9074, 9, 0, -1, 'NPC Equip 9074', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9075, 9, 0, -1, 'NPC Equip 9075', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9076, 9, 0, -1, 'NPC Equip 9076', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9077, 9, 0, -1, 'NPC Equip 9077', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9078, 9, 0, -1, 'NPC Equip 9078', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9079, 9, 0, -1, 'NPC Equip 9079', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9080, 9, 0, -1, 'NPC Equip 9080', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9081, 9, 0, -1, 'NPC Equip 9081', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9082, 9, 0, -1, 'NPC Equip 9082', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9083, 9, 0, -1, 'NPC Equip 9083', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9084, 9, 0, -1, 'NPC Equip 9084', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9085, 9, 0, -1, 'NPC Equip 9085', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9086, 9, 0, -1, 'NPC Equip 9086', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9087, 9, 0, -1, 'NPC Equip 9087', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9089, 9, 0, -1, 'NPC Equip 9089', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9090, 9, 0, -1, 'NPC Equip 9090', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9091, 9, 0, -1, 'NPC Equip 9091', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9092, 9, 0, -1, 'NPC Equip 9092', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9093, 9, 0, -1, 'NPC Equip 9093', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9094, 9, 0, -1, 'NPC Equip 9094', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9095, 9, 0, -1, 'NPC Equip 9095', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9096, 9, 0, -1, 'NPC Equip 9096', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9097, 9, 0, -1, 'NPC Equip 9097', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9098, 9, 0, -1, 'NPC Equip 9098', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9099, 9, 0, -1, 'NPC Equip 9099', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9100, 9, 0, -1, 'NPC Equip 9100', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9101, 9, 0, -1, 'NPC Equip 9101', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9102, 9, 0, -1, 'NPC Equip 9102', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9103, 9, 0, -1, 'NPC Equip 9103', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9104, 9, 0, -1, 'NPC Equip 9104', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9105, 9, 0, -1, 'NPC Equip 9105', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9123, 9, 0, -1, 'NPC Equip 9123', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9124, 9, 0, -1, 'NPC Equip 9124', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9125, 9, 0, -1, 'NPC Equip 9125', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9126, 9, 0, -1, 'NPC Equip 9126', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9127, 9, 0, -1, 'NPC Equip 9127', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9128, 9, 0, -1, 'NPC Equip 9128', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9129, 9, 0, -1, 'NPC Equip 9129', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9130, 9, 0, -1, 'NPC Equip 9130', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9131, 9, 0, -1, 'NPC Equip 9131', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9132, 9, 0, -1, 'NPC Equip 9132', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9133, 9, 0, -1, 'NPC Equip 9133', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9134, 9, 0, -1, 'NPC Equip 9134', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9135, 9, 0, -1, 'NPC Equip 9135', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9136, 9, 0, -1, 'NPC Equip 9136', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9137, 9, 0, -1, 'NPC Equip 9137', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9138, 9, 0, -1, 'NPC Equip 9138', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9139, 9, 0, -1, 'NPC Equip 9139', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9140, 9, 0, -1, 'NPC Equip 9140', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9141, 9, 0, -1, 'NPC Equip 9141', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9142, 9, 0, -1, 'NPC Equip 9142', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9143, 9, 0, -1, 'NPC Equip 9143', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9145, 9, 0, -1, 'NPC Equip 9145', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9146, 9, 0, -1, 'NPC Equip 9146', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9147, 9, 0, -1, 'NPC Equip 9147', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9148, 9, 0, -1, 'NPC Equip 9148', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9150, 9, 0, -1, 'NPC Equip 9150', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9151, 9, 0, -1, 'NPC Equip 9151', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9152, 9, 0, -1, 'NPC Equip 9152', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9156, 9, 0, -1, 'NPC Equip 9156', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9157, 9, 0, -1, 'NPC Equip 9157', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9158, 9, 0, -1, 'NPC Equip 9158', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9159, 9, 0, -1, 'NPC Equip 9159', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9160, 9, 0, -1, 'NPC Equip 9160', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9161, 9, 0, -1, 'NPC Equip 9161', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9162, 9, 0, -1, 'NPC Equip 9162', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9163, 9, 0, -1, 'NPC Equip 9163', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9164, 9, 0, -1, 'NPC Equip 9164', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9165, 9, 0, -1, 'NPC Equip 9165', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9166, 9, 0, -1, 'NPC Equip 9166', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9167, 9, 0, -1, 'NPC Equip 9167', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9168, 9, 0, -1, 'NPC Equip 9168', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9169, 9, 0, -1, 'NPC Equip 9169', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9170, 9, 0, -1, 'NPC Equip 9170', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9171, 9, 0, -1, 'NPC Equip 9171', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9174, 9, 0, -1, 'NPC Equip 9174', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9175, 9, 0, -1, 'NPC Equip 9175', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9176, 9, 0, -1, 'NPC Equip 9176', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9177, 9, 0, -1, 'NPC Equip 9177', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9178, 9, 0, -1, 'NPC Equip 9178', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9180, 9, 0, -1, 'NPC Equip 9180', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9181, 9, 0, -1, 'NPC Equip 9181', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9182, 9, 0, -1, 'NPC Equip 9182', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9183, 9, 0, -1, 'NPC Equip 9183', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9184, 9, 0, -1, 'NPC Equip 9184', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9185, 9, 0, -1, 'NPC Equip 9185', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9188, 9, 0, -1, 'NPC Equip 9188', -1, 5563, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9190, 9, 0, -1, 'NPC Equip 9190', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9191, 9, 0, -1, 'NPC Equip 9191', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9192, 9, 0, -1, 'NPC Equip 9192', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9193, 9, 0, -1, 'NPC Equip 9193', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9194, 9, 0, -1, 'NPC Equip 9194', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9195, 9, 0, -1, 'NPC Equip 9195', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9196, 9, 0, -1, 'NPC Equip 9196', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9198, 9, 0, -1, 'NPC Equip 9198', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9199, 9, 0, -1, 'NPC Equip 9199', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9200, 9, 0, -1, 'NPC Equip 9200', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9201, 9, 0, -1, 'NPC Equip 9201', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9202, 9, 0, -1, 'NPC Equip 9202', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9203, 9, 0, -1, 'NPC Equip 9203', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9204, 9, 0, -1, 'NPC Equip 9204', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9205, 9, 0, -1, 'NPC Equip 9205', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9207, 9, 0, -1, 'NPC Equip 9207', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9208, 9, 0, -1, 'NPC Equip 9208', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9209, 9, 0, -1, 'NPC Equip 9209', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9211, 9, 0, -1, 'NPC Equip 9211', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9212, 9, 0, -1, 'NPC Equip 9212', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9213, 9, 0, -1, 'NPC Equip 9213', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9215, 9, 0, -1, 'NPC Equip 9215', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9216, 9, 0, -1, 'NPC Equip 9216', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9217, 9, 0, -1, 'NPC Equip 9217', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9218, 9, 0, -1, 'NPC Equip 9218', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9219, 9, 0, -1, 'NPC Equip 9219', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9220, 9, 0, -1, 'NPC Equip 9220', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9221, 9, 0, -1, 'NPC Equip 9221', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9222, 9, 0, -1, 'NPC Equip 9222', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9223, 9, 0, -1, 'NPC Equip 9223', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9225, 9, 0, -1, 'NPC Equip 9225', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9226, 9, 0, -1, 'NPC Equip 9226', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9227, 9, 0, -1, 'NPC Equip 9227', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9228, 9, 0, -1, 'NPC Equip 9228', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9229, 9, 0, -1, 'NPC Equip 9229', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9230, 9, 0, -1, 'NPC Equip 9230', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9231, 9, 0, -1, 'NPC Equip 9231', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9232, 0, 0, -1, 'NPC Equip 9232', 3, 17904, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9239, 2, 14, -1, 'NPC Equip 9239', 0, 17914, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9310, 15, 0, -1, 'NPC Equip 9310', -1, 18724, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9376, 2, 11, -1, 'NPC Equip 9376', 1, 18254, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9377, 2, 11, -1, 'NPC Equip 9377', 1, 18255, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9464, 12, 0, -1, 'NPC Equip 9464', 1, 7495, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9529, 15, 0, -1, 'NPC Equip 9529', -1, 12331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9532, 15, 0, -1, 'NPC Equip 9532', -1, 12331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9537, 15, 0, -1, 'NPC Equip 9537', -1, 18499, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9549, 12, 0, -1, 'NPC Equip 9549', -1, 3669, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9659, 2, 4, -1, 'NPC Equip 9659', 2, 18583, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (9702, 2, 14, -1, 'NPC Equip 9702', 2, 18635, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10006, 4, 1, -1, 'NPC Equip 10006', 7, 18837, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10037, 4, 1, -1, 'NPC Equip 10037', 7, 18861, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10284, 7, 0, -1, 'NPC Equip 10284', 8, 12105, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10303, 9, 2, -1, 'NPC Equip 10303', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10304, 9, 2, -1, 'NPC Equip 10304', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10313, 9, 2, -1, 'NPC Equip 10313', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10319, 9, 2, -1, 'NPC Equip 10319', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10322, 9, 2, -1, 'NPC Equip 10322', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10324, 9, 2, -1, 'NPC Equip 10324', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10419, 0, 0, -1, 'NPC Equip 10419', -1, 9711, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10422, 4, 3, -1, 'NPC Equip 10422', 5, 9415, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10448, 0, 0, -1, 'NPC Equip 10448', 0, 17917, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10449, 0, 0, -1, 'NPC Equip 10449', 0, 17917, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10451, 0, 0, -1, 'NPC Equip 10451', 0, 17917, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10452, 0, 0, -1, 'NPC Equip 10452', 0, 19254, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10453, 0, 0, -1, 'NPC Equip 10453', 0, 17917, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10478, 12, 0, -1, 'NPC Equip 10478', -1, 1659, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10555, 4, 0, -1, 'NPC Equip 10555', -1, 6478, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10568, 2, 5, -1, 'NPC Equip 10568', 2, 19500, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10591, 2, 4, -1, 'NPC Equip 10591', 2, 19519, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10594, 15, 0, -1, 'NPC Equip 10594', 5, 15692, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10596, 4, 1, -1, 'NPC Equip 10596', 7, 19411, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10611, 2, 0, -1, 'NPC Equip 10611', 1, 19549, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10612, 2, 0, -1, 'NPC Equip 10612', 1, 19550, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10613, 2, 7, -1, 'NPC Equip 10613', 1, 19551, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10614, 2, 7, -1, 'NPC Equip 10614', 1, 19552, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10615, 2, 7, -1, 'NPC Equip 10615', 1, 19553, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10616, 2, 15, -1, 'NPC Equip 10616', 1, 19555, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10617, 2, 15, -1, 'NPC Equip 10617', 1, 19556, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10618, 2, 15, -1, 'NPC Equip 10618', 1, 6436, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10619, 2, 15, -1, 'NPC Equip 10619', 1, 19557, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10650, 12, 0, -1, 'NPC Equip 10650', -1, 6685, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10651, 12, 0, -1, 'NPC Equip 10651', -1, 7050, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10685, 2, 5, -1, 'NPC Equip 10685', 2, 19599, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10756, 2, 5, -1, 'NPC Equip 10756', 2, 19766, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10825, 2, 7, -1, 'NPC Equip 10825', 1, 19835, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10878, 2, 7, -1, 'NPC Equip 10878', 1, 20036, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (10898, 2, 7, -1, 'NPC Equip 10898', 1, 20095, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11019, 2, 7, -1, 'NPC Equip 11019', 1, 20502, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11021, 2, 3, -1, 'NPC Equip 11021', 1, 20504, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11025, 2, 7, -1, 'NPC Equip 11025', 1, 20507, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11041, 4, 6, -1, 'NPC Equip 11041', 1, 20537, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11042, 2, 7, -1, 'NPC Equip 11042', 1, 20538, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11085, 13, 0, -1, 'NPC Equip 11085', -1, 4287, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11087, 2, 8, -1, 'NPC Equip 11087', 1, 20640, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11099, 7, 7, -1, 'NPC Equip 11099', 1, 4691, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11100, 13, 0, -1, 'NPC Equip 11100', -1, 4287, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11115, 13, 0, -1, 'NPC Equip 11115', -1, 4287, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11171, 12, 0, -1, 'NPC Equip 11171', -1, 8560, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11182, 0, 0, -1, 'NPC Equip 11182', 0, 20976, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11183, 0, 0, -1, 'NPC Equip 11183', 0, 20976, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11198, 12, 0, -1, 'NPC Equip 11198', -1, 20984, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11199, 4, 6, -1, 'NPC Equip 11199', 1, 20985, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11200, 4, 6, -1, 'NPC Equip 11200', 1, 20986, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11201, 4, 6, -1, 'NPC Equip 11201', 1, 20987, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11228, 15, 0, -1, 'NPC Equip 11228', 8, 19502, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11264, 2, 4, -1, 'NPC Equip 11264', 2, 19635, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11314, 2, 13, -1, 'NPC Equip 11314', 1, 21462, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11317, 2, 1, -1, 'NPC Equip 11317', 1, 21159, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11321, 2, 8, -1, 'NPC Equip 11321', 1, 21192, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11322, 2, 8, -1, 'NPC Equip 11322', 1, 21193, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11323, 2, 8, -1, 'NPC Equip 11323', 1, 21194, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11342, 2, 1, -1, 'NPC Equip 11342', 1, 21238, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11343, 2, 10, -1, 'NPC Equip 11343', 2, 21251, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11344, 4, 2, -1, 'NPC Equip 11344', 8, 21256, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11345, 4, 2, -1, 'NPC Equip 11345', 8, 17212, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11365, 2, 10, -1, 'NPC Equip 11365', 2, 21341, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11369, 2, 4, -1, 'NPC Equip 11369', 2, 21751, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11383, 2, 4, -1, 'NPC Equip 11383', 2, 21362, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11424, 2, 10, -1, 'NPC Equip 11424', 2, 21376, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11442, 15, 0, -1, 'NPC Equip 11442', -1, 16028, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11443, 0, 8, -1, 'NPC Equip 11443', -1, 2376, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11473, 12, 0, -1, 'NPC Equip 11473', -1, 21414, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11505, 2, 13, -1, 'NPC Equip 11505', 1, 21461, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11506, 2, 13, -1, 'NPC Equip 11506', 1, 21144, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11542, 2, 10, -1, 'NPC Equip 11542', 2, 21514, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11585, 4, 6, -1, 'NPC Equip 11585', 1, 21539, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11586, 4, 6, -1, 'NPC Equip 11586', 1, 21540, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11587, 4, 6, -1, 'NPC Equip 11587', 1, 21541, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11588, 2, 10, -1, 'NPC Equip 11588', 2, 21552, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11589, 4, 6, -1, 'NPC Equip 11589', 1, 21553, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11591, 2, 8, -1, 'NPC Equip 11591', 1, 21555, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11663, 12, 0, -1, 'NPC Equip 11663', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11664, 12, 0, -1, 'NPC Equip 11664', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11666, 12, 0, -1, 'NPC Equip 11666', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11667, 12, 0, -1, 'NPC Equip 11667', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11670, 12, 0, -1, 'NPC Equip 11670', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11673, 12, 0, -1, 'NPC Equip 11673', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11676, 12, 0, -1, 'NPC Equip 11676', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11683, 12, 0, -1, 'NPC Equip 11683', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11762, 2, 0, -1, 'NPC Equip 11762', 1, 21752, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11763, 2, 0, -1, 'NPC Equip 11763', 1, 19132, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11806, 4, 0, -1, 'NPC Equip 11806', 0, 9310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11836, 12, 0, -1, 'NPC Equip 11836', 3, 21673, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (11838, 2, 6, -1, 'NPC Equip 11838', 1, 22032, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12063, 2, 6, -1, 'NPC Equip 12063', 1, 22031, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12142, 2, 7, -1, 'NPC Equip 12142', 1, 8090, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12143, 13, 0, -1, 'NPC Equip 12143', -1, 22071, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12182, 2, 10, -1, 'NPC Equip 12182', 2, 22178, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12183, 2, 4, -1, 'NPC Equip 12183', 2, 22180, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12186, 12, 0, -1, 'NPC Equip 12186', 1, 22185, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12187, 4, 4, -1, 'NPC Equip 12187', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12188, 4, 4, -1, 'NPC Equip 12188', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12189, 4, 4, -1, 'NPC Equip 12189', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12211, 0, 5, -1, 'NPC Equip 12211', -1, 22196, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12221, 2, 20, -1, 'NPC Equip 12221', -1, 20618, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12222, 4, 0, -1, 'NPC Equip 12222', -1, 16548, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12244, 4, 4, -1, 'NPC Equip 12244', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12245, 4, 4, -1, 'NPC Equip 12245', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12246, 0, 0, -1, 'NPC Equip 12246', 0, 22243, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12285, 2, 1, -1, 'NPC Equip 12285', 1, 18607, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12290, 2, 0, -1, 'NPC Equip 12290', 1, 22319, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12294, 2, 1, -1, 'NPC Equip 12294', 1, 22598, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12297, 2, 7, -1, 'NPC Equip 12297', 1, 22366, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12298, 2, 15, -1, 'NPC Equip 12298', 1, 22367, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12304, 2, 7, -1, 'NPC Equip 12304', 1, 22378, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12322, 2, 10, -1, 'NPC Equip 12322', 2, 22391, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12328, 2, 10, -1, 'NPC Equip 12328', 2, 22394, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12329, 2, 10, -1, 'NPC Equip 12329', 2, 22395, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12331, 2, 8, -1, 'NPC Equip 12331', 1, 22402, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12332, 2, 15, -1, 'NPC Equip 12332', 1, 22403, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12333, 2, 6, -1, 'NPC Equip 12333', 1, 22404, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12338, 2, 6, -1, 'NPC Equip 12338', 1, 22411, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12340, 12, 0, -1, 'NPC Equip 12340', -1, 6614, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12357, 7, 0, -1, 'NPC Equip 12357', 4, 20656, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12362, 7, 0, -1, 'NPC Equip 12362', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12369, 12, 0, -1, 'NPC Equip 12369', -1, 10275, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12385, 0, 0, -1, 'NPC Equip 12385', 0, 22485, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12403, 2, 6, -1, 'NPC Equip 12403', 1, 22492, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12407, 4, 4, -1, 'NPC Equip 12407', 6, 22534, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12413, 4, 4, -1, 'NPC Equip 12413', 6, 22520, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12421, 2, 10, -1, 'NPC Equip 12421', 2, 22563, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12423, 4, 4, -1, 'NPC Equip 12423', 6, 22517, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12439, 0, 0, -1, 'NPC Equip 12439', 0, 22611, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12440, 0, 8, -1, 'NPC Equip 12440', -1, 11947, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12441, 0, 0, -1, 'NPC Equip 12441', 0, 22612, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12442, 4, 0, -1, 'NPC Equip 12442', -1, 22617, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12443, 4, 0, -1, 'NPC Equip 12443', -1, 22618, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12452, 4, 6, -1, 'NPC Equip 12452', 1, 22635, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12453, 4, 6, -1, 'NPC Equip 12453', 1, 22637, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12454, 4, 6, -1, 'NPC Equip 12454', 1, 22638, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12456, 4, 6, -1, 'NPC Equip 12456', 1, 22640, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12461, 2, 1, -1, 'NPC Equip 12461', 1, 22645, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12482, 2, 0, -1, 'NPC Equip 12482', 1, 22672, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12502, 2, 0, -1, 'NPC Equip 12502', 1, 22695, 22, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12523, 2, 3, -1, 'NPC Equip 12523', 1, 20726, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12526, 0, 8, -1, 'NPC Equip 12526', -1, 9666, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12585, 15, 0, -1, 'NPC Equip 12585', -1, 6418, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12591, 2, 10, -1, 'NPC Equip 12591', 2, 22802, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12593, 2, 7, -1, 'NPC Equip 12593', 1, 22814, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12629, 2, 0, -1, 'NPC Equip 12629', 1, 22893, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12686, 2, 15, -1, 'NPC Equip 12686', 1, 22971, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12729, 0, 8, -1, 'NPC Equip 12729', -1, 2533, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12742, 2, 14, -1, 'NPC Equip 12742', 1, 23171, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12743, 4, 0, -1, 'NPC Equip 12743', 1, 23171, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12744, 2, 14, -1, 'NPC Equip 12744', 1, 23172, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12745, 4, 0, -1, 'NPC Equip 12745', 1, 23172, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12746, 2, 14, -1, 'NPC Equip 12746', 1, 23173, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12747, 2, 14, -1, 'NPC Equip 12747', 1, 23173, 22, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12748, 2, 14, -1, 'NPC Equip 12748', 1, 23174, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12749, 4, 0, -1, 'NPC Equip 12749', 1, 23174, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12750, 2, 14, -1, 'NPC Equip 12750', 1, 23175, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12751, 2, 14, -1, 'NPC Equip 12751', 1, 23177, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12754, 2, 1, -1, 'NPC Equip 12754', 1, 23198, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12755, 2, 8, -1, 'NPC Equip 12755', 1, 22906, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12762, 12, 0, -1, 'NPC Equip 12762', 0, 23201, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12763, 0, 5, -1, 'NPC Equip 12763', 7, 26735, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12767, 2, 15, -1, 'NPC Equip 12767', 1, 16130, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12778, 12, 0, -1, 'NPC Equip 12778', 0, 9126, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12786, 2, 4, -1, 'NPC Equip 12786', 2, 23253, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12788, 2, 4, -1, 'NPC Equip 12788', 2, 23255, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12789, 15, 0, -1, 'NPC Equip 12789', -1, 17514, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12801, 2, 14, -1, 'NPC Equip 12801', 2, 23281, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12805, 4, 0, -1, 'NPC Equip 12805', -1, 23727, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12816, 9, 4, -1, 'NPC Equip 12816', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12817, 9, 4, -1, 'NPC Equip 12817', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12818, 9, 4, -1, 'NPC Equip 12818', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12826, 9, 4, -1, 'NPC Equip 12826', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12831, 9, 4, -1, 'NPC Equip 12831', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12832, 9, 4, -1, 'NPC Equip 12832', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12850, 2, 14, -1, 'NPC Equip 12850', 1, 23316, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12851, 4, 0, -1, 'NPC Equip 12851', 1, 23316, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12852, 2, 14, -1, 'NPC Equip 12852', 1, 23317, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12853, 4, 0, -1, 'NPC Equip 12853', 1, 23317, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12854, 2, 14, -1, 'NPC Equip 12854', 1, 23318, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12855, 4, 0, -1, 'NPC Equip 12855', 1, 23318, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12856, 2, 14, -1, 'NPC Equip 12856', 1, 23319, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12857, 4, 0, -1, 'NPC Equip 12857', 1, 23319, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12858, 2, 14, -1, 'NPC Equip 12858', 1, 23320, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12859, 4, 0, -1, 'NPC Equip 12859', 1, 23320, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12860, 4, 0, -1, 'NPC Equip 12860', 1, 23177, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12861, 4, 0, -1, 'NPC Equip 12861', 1, 23175, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12862, 2, 14, -1, 'NPC Equip 12862', 1, 23321, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12863, 4, 0, -1, 'NPC Equip 12863', 1, 23321, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12864, 2, 14, -1, 'NPC Equip 12864', 1, 23322, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12865, 4, 0, -1, 'NPC Equip 12865', 1, 23322, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12867, 4, 0, -1, 'NPC Equip 12867', 1, 23323, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12868, 2, 14, -1, 'NPC Equip 12868', 1, 23324, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12869, 4, 0, -1, 'NPC Equip 12869', 1, 23324, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12870, 4, 0, -1, 'NPC Equip 12870', 2, 6533, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12882, 2, 8, -1, 'NPC Equip 12882', 1, 23355, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12883, 2, 4, -1, 'NPC Equip 12883', 2, 23357, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12889, 2, 8, -1, 'NPC Equip 12889', 1, 23379, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12890, 2, 7, -1, 'NPC Equip 12890', 1, 12274, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12892, 2, 7, -1, 'NPC Equip 12892', 1, 23386, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12893, 4, 6, -1, 'NPC Equip 12893', 1, 23387, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12901, 2, 5, -1, 'NPC Equip 12901', 2, 23401, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12902, 2, 8, -1, 'NPC Equip 12902', 1, 23405, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12931, 4, 6, -1, 'NPC Equip 12931', 1, 23445, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12932, 4, 6, -1, 'NPC Equip 12932', 1, 23446, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12933, 4, 6, -1, 'NPC Equip 12933', 1, 23447, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12934, 2, 4, -1, 'NPC Equip 12934', 2, 23448, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12937, 2, 10, -1, 'NPC Equip 12937', 2, 2388, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12941, 2, 19, -1, 'NPC Equip 12941', 2, 23455, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12944, 2, 7, -1, 'NPC Equip 12944', 1, 23472, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12948, 4, 0, -1, 'NPC Equip 12948', 2, 23497, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12949, 2, 8, -1, 'NPC Equip 12949', 1, 23508, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12950, 2, 5, -1, 'NPC Equip 12950', 2, 23509, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12951, 2, 1, -1, 'NPC Equip 12951', 1, 3243, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12959, 2, 10, -1, 'NPC Equip 12959', 2, 23539, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12961, 4, 6, -1, 'NPC Equip 12961', 1, 23545, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12962, 4, 2, -1, 'NPC Equip 12962', 8, 23546, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12971, 2, 7, -1, 'NPC Equip 12971', 1, 23561, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12972, 2, 7, -1, 'NPC Equip 12972', 1, 23561, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12980, 4, 6, -1, 'NPC Equip 12980', 1, 23568, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12981, 4, 6, -1, 'NPC Equip 12981', 1, 23569, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12986, 2, 17, -1, 'NPC Equip 12986', 1, 7480, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12993, 2, 7, -1, 'NPC Equip 12993', 1, 23574, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (12995, 4, 6, -1, 'NPC Equip 12995', 1, 23575, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13050, 2, 10, -1, 'NPC Equip 13050', 2, 23586, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13061, 2, 10, -1, 'NPC Equip 13061', 2, 23590, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13069, 2, 10, -1, 'NPC Equip 13069', 2, 23594, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13078, 2, 10, -1, 'NPC Equip 13078', 2, 23601, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13104, 2, 0, -1, 'NPC Equip 13104', 1, 23617, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13147, 2, 2, -1, 'NPC Equip 13147', 2, 23639, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13149, 0, 0, -1, 'NPC Equip 13149', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13150, 2, 8, -1, 'NPC Equip 13150', 1, 23656, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13151, 0, 0, -1, 'NPC Equip 13151', -1, 1317, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13152, 0, 0, -1, 'NPC Equip 13152', -1, 1134, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13153, 0, 0, -1, 'NPC Equip 13153', -1, 7139, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13154, 0, 0, -1, 'NPC Equip 13154', -1, 6672, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13160, 2, 8, -1, 'NPC Equip 13160', 1, 23669, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13165, 2, 7, -1, 'NPC Equip 13165', 1, 23692, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13214, 4, 4, -1, 'NPC Equip 13214', 6, 23775, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13215, 12, 0, -1, 'NPC Equip 13215', -1, 23776, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13219, 4, 0, -1, 'NPC Equip 13219', 2, 23497, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13220, 2, 4, -1, 'NPC Equip 13220', 2, 23792, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13221, 4, 0, -1, 'NPC Equip 13221', 2, 23797, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13222, 2, 7, -1, 'NPC Equip 13222', 1, 23798, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13223, 12, 0, -1, 'NPC Equip 13223', -1, 1283, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13256, 12, 0, -1, 'NPC Equip 13256', -1, 23850, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13290, 2, 19, -1, 'NPC Equip 13290', 2, 23917, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13291, 2, 19, -1, 'NPC Equip 13291', 2, 23918, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13292, 2, 19, -1, 'NPC Equip 13292', 2, 23919, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13293, 2, 19, -1, 'NPC Equip 13293', 2, 23920, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13294, 0, 0, -1, 'NPC Equip 13294', 0, 23923, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13312, 2, 4, -1, 'NPC Equip 13312', 2, 23948, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13318, 4, 6, -1, 'NPC Equip 13318', 1, 23976, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13319, 4, 6, -1, 'NPC Equip 13319', 1, 23977, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13330, 1, 0, -1, 'NPC Equip 13330', -1, 23991, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13336, 2, 10, -1, 'NPC Equip 13336', 2, 24014, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13338, 2, 10, -1, 'NPC Equip 13338', 2, 21513, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13341, 4, 0, -1, 'NPC Equip 13341', 2, 6536, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13342, 15, 2, -1, 'NPC Equip 13342', -1, 24020, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13343, 15, 2, -1, 'NPC Equip 13343', -1, 24019, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13355, 12, 0, -1, 'NPC Equip 13355', -1, 24044, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13406, 4, 0, -1, 'NPC Equip 13406', 2, 24116, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13407, 4, 0, -1, 'NPC Equip 13407', 2, 24117, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13449, 12, 0, -1, 'NPC Equip 13449', -1, 16065, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13472, 4, 1, -1, 'NPC Equip 13472', 7, 24174, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13500, 9, 6, -1, 'NPC Equip 13500', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13504, 2, 7, -1, 'NPC Equip 13504', 1, 52723, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13516, 4, 0, -1, 'NPC Equip 13516', -1, 24175, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13543, 12, 0, -1, 'NPC Equip 13543', -1, 19595, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13586, 4, 4, -1, 'NPC Equip 13586', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13604, 4, 0, -1, 'NPC Equip 13604', 2, 24281, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13605, 4, 0, -1, 'NPC Equip 13605', 2, 24282, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13606, 4, 0, -1, 'NPC Equip 13606', 2, 24283, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13607, 2, 14, -1, 'NPC Equip 13607', 2, 24284, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13608, 2, 14, -1, 'NPC Equip 13608', 2, 24285, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13609, 4, 0, -1, 'NPC Equip 13609', 2, 24293, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13610, 4, 0, -1, 'NPC Equip 13610', 2, 24294, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13611, 4, 0, -1, 'NPC Equip 13611', 2, 24295, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13622, 2, 10, -1, 'NPC Equip 13622', 2, 24343, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13623, 2, 8, -1, 'NPC Equip 13623', 1, 24342, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13625, 2, 0, -1, 'NPC Equip 13625', 1, 24351, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13627, 2, 7, -1, 'NPC Equip 13627', 1, 24366, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13628, 4, 6, -1, 'NPC Equip 13628', 1, 24367, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13629, 4, 6, -1, 'NPC Equip 13629', 1, 24368, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13630, 4, 6, -1, 'NPC Equip 13630', 1, 24369, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13631, 2, 6, -1, 'NPC Equip 13631', 1, 19804, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13632, 2, 6, -1, 'NPC Equip 13632', 1, 24370, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13642, 15, 0, -1, 'NPC Equip 13642', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13643, 15, 0, -1, 'NPC Equip 13643', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13644, 15, 0, -1, 'NPC Equip 13644', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13645, 15, 0, -1, 'NPC Equip 13645', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13646, 15, 0, -1, 'NPC Equip 13646', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13647, 15, 0, -1, 'NPC Equip 13647', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13648, 15, 0, -1, 'NPC Equip 13648', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13649, 15, 0, -1, 'NPC Equip 13649', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13650, 15, 0, -1, 'NPC Equip 13650', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13651, 15, 0, -1, 'NPC Equip 13651', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13652, 15, 0, -1, 'NPC Equip 13652', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13653, 15, 0, -1, 'NPC Equip 13653', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13654, 15, 0, -1, 'NPC Equip 13654', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13655, 15, 0, -1, 'NPC Equip 13655', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13656, 15, 0, -1, 'NPC Equip 13656', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13657, 15, 0, -1, 'NPC Equip 13657', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13658, 15, 0, -1, 'NPC Equip 13658', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13659, 15, 0, -1, 'NPC Equip 13659', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13660, 15, 0, -1, 'NPC Equip 13660', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13661, 15, 0, -1, 'NPC Equip 13661', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13662, 15, 0, -1, 'NPC Equip 13662', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13663, 15, 0, -1, 'NPC Equip 13663', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13664, 15, 0, -1, 'NPC Equip 13664', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13665, 15, 0, -1, 'NPC Equip 13665', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13666, 15, 0, -1, 'NPC Equip 13666', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13667, 15, 0, -1, 'NPC Equip 13667', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13668, 15, 0, -1, 'NPC Equip 13668', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13669, 15, 0, -1, 'NPC Equip 13669', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13670, 15, 0, -1, 'NPC Equip 13670', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13671, 15, 0, -1, 'NPC Equip 13671', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13672, 15, 0, -1, 'NPC Equip 13672', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13674, 15, 0, -1, 'NPC Equip 13674', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13675, 15, 0, -1, 'NPC Equip 13675', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13676, 15, 0, -1, 'NPC Equip 13676', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13677, 15, 0, -1, 'NPC Equip 13677', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13678, 15, 0, -1, 'NPC Equip 13678', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13679, 15, 0, -1, 'NPC Equip 13679', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13680, 15, 0, -1, 'NPC Equip 13680', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13681, 15, 0, -1, 'NPC Equip 13681', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13682, 15, 0, -1, 'NPC Equip 13682', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13683, 15, 0, -1, 'NPC Equip 13683', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13684, 15, 0, -1, 'NPC Equip 13684', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13685, 15, 0, -1, 'NPC Equip 13685', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13686, 15, 0, -1, 'NPC Equip 13686', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13687, 15, 0, -1, 'NPC Equip 13687', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13688, 15, 0, -1, 'NPC Equip 13688', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13689, 15, 0, -1, 'NPC Equip 13689', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13690, 15, 0, -1, 'NPC Equip 13690', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13691, 15, 0, -1, 'NPC Equip 13691', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13692, 15, 0, -1, 'NPC Equip 13692', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13693, 15, 0, -1, 'NPC Equip 13693', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13694, 15, 0, -1, 'NPC Equip 13694', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13695, 15, 0, -1, 'NPC Equip 13695', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13696, 15, 0, -1, 'NPC Equip 13696', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13697, 15, 0, -1, 'NPC Equip 13697', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13698, 2, 10, -1, 'NPC Equip 13698', 2, 24394, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13705, 2, 10, -1, 'NPC Equip 13705', 2, 24445, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13706, 2, 1, -1, 'NPC Equip 13706', 1, 24446, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13707, 2, 7, -1, 'NPC Equip 13707', 1, 24452, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13708, 2, 8, -1, 'NPC Equip 13708', 1, 24461, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13709, 2, 10, -1, 'NPC Equip 13709', 2, 24473, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13710, 4, 4, -1, 'NPC Equip 13710', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13711, 4, 4, -1, 'NPC Equip 13711', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13712, 4, 4, -1, 'NPC Equip 13712', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13713, 4, 4, -1, 'NPC Equip 13713', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13714, 4, 4, -1, 'NPC Equip 13714', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13715, 4, 4, -1, 'NPC Equip 13715', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13716, 4, 4, -1, 'NPC Equip 13716', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13717, 4, 4, -1, 'NPC Equip 13717', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13718, 2, 7, -1, 'NPC Equip 13718', 1, 24478, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13719, 2, 7, -1, 'NPC Equip 13719', 1, 24479, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13720, 2, 10, -1, 'NPC Equip 13720', 2, 24480, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13721, 2, 10, -1, 'NPC Equip 13721', 2, 24483, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13722, 2, 10, -1, 'NPC Equip 13722', 2, 24489, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13723, 2, 10, -1, 'NPC Equip 13723', 2, 24490, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13729, 4, 2, -1, 'NPC Equip 13729', 8, 24563, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13735, 4, 2, -1, 'NPC Equip 13735', 8, 24563, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13750, 2, 10, -1, 'NPC Equip 13750', 2, 24499, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13751, 2, 10, -1, 'NPC Equip 13751', 2, 24503, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13753, 2, 10, -1, 'NPC Equip 13753', 2, 24517, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13774, 4, 1, -1, 'NPC Equip 13774', 7, 24551, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13786, 4, 1, -1, 'NPC Equip 13786', 7, 24555, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13789, 4, 2, -1, 'NPC Equip 13789', 8, 24556, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13792, 4, 3, -1, 'NPC Equip 13792', 5, 24557, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13795, 4, 4, -1, 'NPC Equip 13795', 6, 24558, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13799, 4, 1, -1, 'NPC Equip 13799', 7, 24565, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13800, 4, 1, -1, 'NPC Equip 13800', 7, 24565, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13811, 4, 0, -1, 'NPC Equip 13811', -1, 6502, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13814, 4, 6, -1, 'NPC Equip 13814', 1, 24571, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13842, 15, 0, -1, 'NPC Equip 13842', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13843, 15, 0, -1, 'NPC Equip 13843', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13844, 15, 0, -1, 'NPC Equip 13844', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13845, 15, 0, -1, 'NPC Equip 13845', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13846, 15, 0, -1, 'NPC Equip 13846', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13847, 15, 0, -1, 'NPC Equip 13847', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13848, 15, 0, -1, 'NPC Equip 13848', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13849, 15, 0, -1, 'NPC Equip 13849', -1, 18705, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13854, 4, 0, -1, 'NPC Equip 13854', 2, 24594, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13855, 4, 0, -1, 'NPC Equip 13855', 2, 24595, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13859, 4, 0, -1, 'NPC Equip 13859', 2, 24596, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13861, 2, 14, -1, 'NPC Equip 13861', 1, 24597, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13862, 4, 0, -1, 'NPC Equip 13862', 2, 24597, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13894, 2, 4, -1, 'NPC Equip 13894', 2, 24634, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13919, 2, 6, -1, 'NPC Equip 13919', 1, 24655, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13922, 4, 6, -1, 'NPC Equip 13922', 1, 24695, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13923, 2, 3, -1, 'NPC Equip 13923', 1, 24720, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13924, 2, 3, -1, 'NPC Equip 13924', 1, 24721, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13925, 2, 5, -1, 'NPC Equip 13925', 2, 24729, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (13985, 4, 1, -1, 'NPC Equip 13985', 7, 24817, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14082, 2, 5, -1, 'NPC Equip 14082', 2, 24919, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14084, 2, 5, -1, 'NPC Equip 14084', 2, 24924, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14085, 2, 7, -1, 'NPC Equip 14085', 1, 24925, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14092, 2, 10, -1, 'NPC Equip 14092', 2, 24926, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14105, 2, 2, -1, 'NPC Equip 14105', 2, 24930, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14118, 2, 2, -1, 'NPC Equip 14118', 2, 24931, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14135, 12, 0, -1, 'NPC Equip 14135', -1, 15738, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14362, 12, 0, -1, 'NPC Equip 14362', -1, 25080, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14363, 4, 1, -1, 'NPC Equip 14363', 7, 16591, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14382, 4, 1, -1, 'NPC Equip 14382', 7, 17251, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14383, 4, 1, -1, 'NPC Equip 14383', 7, 17262, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14384, 4, 1, -1, 'NPC Equip 14384', 7, 17256, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14385, 4, 1, -1, 'NPC Equip 14385', 7, 13984, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14386, 4, 1, -1, 'NPC Equip 14386', 7, 17274, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14387, 4, 1, -1, 'NPC Equip 14387', 7, 17255, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14388, 4, 1, -1, 'NPC Equip 14388', 7, 17252, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14389, 4, 1, -1, 'NPC Equip 14389', 7, 17271, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14391, 2, 7, -1, 'NPC Equip 14391', 1, 20173, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14393, 4, 6, -1, 'NPC Equip 14393', 1, 2552, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14394, 2, 2, -1, 'NPC Equip 14394', 2, 20550, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14475, 2, 1, -1, 'NPC Equip 14475', 1, 3367, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14524, 2, 7, -1, 'NPC Equip 14524', 1, 25120, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14527, 2, 5, -1, 'NPC Equip 14527', 2, 25139, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14532, 2, 5, -1, 'NPC Equip 14532', 2, 25152, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14533, 2, 4, -1, 'NPC Equip 14533', 2, 25153, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14534, 2, 0, -1, 'NPC Equip 14534', 1, 25154, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14535, 2, 6, -1, 'NPC Equip 14535', 1, 25155, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14556, 4, 0, -1, 'NPC Equip 14556', -1, 6522, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14575, 2, 4, -1, 'NPC Equip 14575', 2, 25620, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14597, 4, 6, -1, 'NPC Equip 14597', 1, 6272, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14609, 4, 6, -1, 'NPC Equip 14609', 1, 18488, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14618, 2, 10, -1, 'NPC Equip 14618', 2, 25197, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14642, 2, 3, -1, 'NPC Equip 14642', 1, 25260, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14643, 2, 1, -1, 'NPC Equip 14643', 1, 5509, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14689, 4, 3, -1, 'NPC Equip 14689', 5, 22673, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14690, 4, 3, -1, 'NPC Equip 14690', 5, 22674, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14691, 4, 6, -1, 'NPC Equip 14691', 1, 18492, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14692, 4, 1, -1, 'NPC Equip 14692', 7, 22675, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14693, 4, 3, -1, 'NPC Equip 14693', 5, 11131, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14694, 4, 3, -1, 'NPC Equip 14694', 5, 22676, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14695, 4, 3, -1, 'NPC Equip 14695', 5, 7193, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14696, 4, 6, -1, 'NPC Equip 14696', 1, 2633, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14697, 4, 3, -1, 'NPC Equip 14697', 5, 22677, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14698, 4, 3, -1, 'NPC Equip 14698', 5, 22689, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14699, 4, 3, -1, 'NPC Equip 14699', 5, 22690, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14700, 4, 3, -1, 'NPC Equip 14700', 5, 6953, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14701, 4, 1, -1, 'NPC Equip 14701', 7, 22691, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14702, 4, 3, -1, 'NPC Equip 14702', 5, 22692, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14703, 4, 3, -1, 'NPC Equip 14703', 5, 12450, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14704, 4, 3, -1, 'NPC Equip 14704', 5, 22693, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14705, 4, 6, -1, 'NPC Equip 14705', 1, 3932, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14706, 2, 10, -1, 'NPC Equip 14706', 2, 5417, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14707, 2, 10, -1, 'NPC Equip 14707', 2, 25278, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14818, 2, 5, -1, 'NPC Equip 14818', 2, 25362, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14819, 2, 5, -1, 'NPC Equip 14819', 2, 25363, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14820, 2, 5, -1, 'NPC Equip 14820', 2, 25364, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14822, 2, 5, -1, 'NPC Equip 14822', 2, 25365, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14823, 2, 5, -1, 'NPC Equip 14823', 2, 25366, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14824, 2, 5, -1, 'NPC Equip 14824', 2, 25367, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14836, 2, 10, -1, 'NPC Equip 14836', 2, 25377, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14837, 2, 10, -1, 'NPC Equip 14837', 2, 25378, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14845, 2, 10, -1, 'NPC Equip 14845', 2, 25382, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14870, 2, 1, -1, 'NPC Equip 14870', 1, 25410, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14871, 2, 7, -1, 'NPC Equip 14871', 1, 25411, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14873, 2, 10, -1, 'NPC Equip 14873', 2, 25437, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14874, 2, 0, -1, 'NPC Equip 14874', 1, 25441, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14875, 2, 0, -1, 'NPC Equip 14875', 1, 25470, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14876, 2, 0, -1, 'NPC Equip 14876', 1, 25471, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14877, 2, 0, -1, 'NPC Equip 14877', 1, 25474, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14878, 2, 8, -1, 'NPC Equip 14878', 1, 9055, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14879, 2, 6, -1, 'NPC Equip 14879', 1, 25496, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14880, 2, 0, -1, 'NPC Equip 14880', 1, 25499, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14881, 2, 0, -1, 'NPC Equip 14881', 1, 25503, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14882, 2, 0, -1, 'NPC Equip 14882', 1, 25504, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14883, 2, 7, -1, 'NPC Equip 14883', 1, 25506, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14884, 2, 7, -1, 'NPC Equip 14884', 1, 25507, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14885, 2, 7, -1, 'NPC Equip 14885', 1, 25508, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14886, 2, 7, -1, 'NPC Equip 14886', 1, 25509, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14887, 2, 7, -1, 'NPC Equip 14887', 1, 25510, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14888, 2, 7, -1, 'NPC Equip 14888', 1, 25511, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14889, 2, 7, -1, 'NPC Equip 14889', 1, 25513, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14890, 2, 7, -1, 'NPC Equip 14890', 1, 25514, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14892, 2, 7, -1, 'NPC Equip 14892', 1, 25516, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (14893, 2, 0, -1, 'NPC Equip 14893', 1, 25533, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15022, 12, 0, -1, 'NPC Equip 15022', -1, 24496, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15089, 4, 3, -1, 'NPC Equip 15089', 5, 25710, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15446, 12, 0, -1, 'NPC Equip 15446', -1, 26381, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15460, 2, 3, -1, 'NPC Equip 15460', 1, 26385, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15586, 12, 0, -1, 'NPC Equip 15586', -1, 19495, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15688, 12, 0, -1, 'NPC Equip 15688', -1, 1443, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15888, 4, 6, -1, 'NPC Equip 15888', 1, 20909, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15889, 4, 6, -1, 'NPC Equip 15889', 1, 18811, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (15910, 2, 6, -1, 'NPC Equip 15910', 1, 26598, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16024, 12, 0, -1, 'NPC Equip 16024', -1, 26653, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16025, 12, 0, -1, 'NPC Equip 16025', -1, 26653, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16027, 4, 4, -1, 'NPC Equip 16027', 6, 26658, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16028, 4, 4, -1, 'NPC Equip 16028', 6, 26659, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16029, 4, 4, -1, 'NPC Equip 16029', 6, 26753, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16030, 4, 4, -1, 'NPC Equip 16030', 6, 26752, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16031, 4, 4, -1, 'NPC Equip 16031', 6, 26662, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16032, 4, 0, -1, 'NPC Equip 16032', 0, 26663, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16033, 4, 4, -1, 'NPC Equip 16033', 6, 26664, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16034, 4, 0, -1, 'NPC Equip 16034', 0, 26665, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16035, 4, 4, -1, 'NPC Equip 16035', 6, 26668, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16036, 4, 0, -1, 'NPC Equip 16036', 0, 26667, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16037, 4, 0, -1, 'NPC Equip 16037', 0, 26669, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16038, 4, 4, -1, 'NPC Equip 16038', 6, 26670, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16061, 4, 1, -1, 'NPC Equip 16061', 7, 28729, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16062, 4, 1, -1, 'NPC Equip 16062', 7, 28730, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16063, 4, 1, -1, 'NPC Equip 16063', 7, 16601, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16064, 4, 3, -1, 'NPC Equip 16064', 5, 25981, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16065, 4, 2, -1, 'NPC Equip 16065', 8, 28734, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16066, 4, 3, -1, 'NPC Equip 16066', 5, 14895, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16067, 4, 0, -1, 'NPC Equip 16067', -1, 22415, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16068, 15, 0, -1, 'NPC Equip 16068', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16069, 15, 0, -1, 'NPC Equip 16069', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16070, 15, 0, -1, 'NPC Equip 16070', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16071, 15, 0, -1, 'NPC Equip 16071', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16073, 9, 5, -1, 'NPC Equip 16073', -1, 1134, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16074, 15, 0, -1, 'NPC Equip 16074', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16075, 15, 0, -1, 'NPC Equip 16075', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16076, 15, 0, -1, 'NPC Equip 16076', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16077, 15, 0, -1, 'NPC Equip 16077', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16078, 15, 0, -1, 'NPC Equip 16078', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16079, 15, 0, -1, 'NPC Equip 16079', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16080, 15, 0, -1, 'NPC Equip 16080', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16081, 15, 0, -1, 'NPC Equip 16081', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16086, 0, 8, -1, 'NPC Equip 16086', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16102, 0, 8, -1, 'NPC Equip 16102', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16103, 0, 8, -1, 'NPC Equip 16103', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16104, 0, 8, -1, 'NPC Equip 16104', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16105, 0, 8, -1, 'NPC Equip 16105', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16106, 0, 8, -1, 'NPC Equip 16106', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16107, 0, 8, -1, 'NPC Equip 16107', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16108, 0, 8, -1, 'NPC Equip 16108', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16109, 15, 0, -1, 'NPC Equip 16109', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16116, 4, 1, -1, 'NPC Equip 16116', 7, 25910, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16117, 4, 1, -1, 'NPC Equip 16117', 7, 16601, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16118, 4, 1, -1, 'NPC Equip 16118', 7, 16719, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16119, 4, 1, -1, 'NPC Equip 16119', 7, 16604, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16120, 4, 1, -1, 'NPC Equip 16120', 7, 28730, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16121, 4, 1, -1, 'NPC Equip 16121', 7, 15293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16122, 4, 1, -1, 'NPC Equip 16122', 7, 28729, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16123, 4, 0, -1, 'NPC Equip 16123', 3, 6539, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16124, 4, 0, -1, 'NPC Equip 16124', 3, 6539, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16125, 4, 0, -1, 'NPC Equip 16125', 3, 6539, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16126, 4, 2, -1, 'NPC Equip 16126', 8, 28730, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16127, 4, 2, -1, 'NPC Equip 16127', 8, 16604, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16128, 4, 2, -1, 'NPC Equip 16128', 8, 15293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16129, 4, 3, -1, 'NPC Equip 16129', 5, 14895, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16130, 4, 4, -1, 'NPC Equip 16130', 6, 15293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16131, 4, 3, -1, 'NPC Equip 16131', 5, 25981, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16132, 4, 2, -1, 'NPC Equip 16132', 8, 16604, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16133, 4, 2, -1, 'NPC Equip 16133', 8, 15293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16134, 4, 3, -1, 'NPC Equip 16134', 5, 13670, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16135, 4, 1, -1, 'NPC Equip 16135', 7, 28734, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16136, 4, 1, -1, 'NPC Equip 16136', 7, 28730, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16137, 4, 1, -1, 'NPC Equip 16137', 7, 16604, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16138, 4, 1, -1, 'NPC Equip 16138', 7, 15293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16139, 4, 2, -1, 'NPC Equip 16139', 8, 21298, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16140, 4, 2, -1, 'NPC Equip 16140', 8, 21298, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16141, 4, 3, -1, 'NPC Equip 16141', 5, 30091, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16142, 4, 3, -1, 'NPC Equip 16142', 5, 25861, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16143, 4, 3, -1, 'NPC Equip 16143', 5, 25847, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16144, 4, 2, -1, 'NPC Equip 16144', 8, 14950, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16145, 4, 1, -1, 'NPC Equip 16145', 7, 28730, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16146, 4, 1, -1, 'NPC Equip 16146', 7, 15293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16147, 4, 1, -1, 'NPC Equip 16147', 7, 28729, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16148, 4, 2, -1, 'NPC Equip 16148', 8, 14950, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16149, 4, 3, -1, 'NPC Equip 16149', 5, 25847, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16150, 4, 2, -1, 'NPC Equip 16150', 8, 11956, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16151, 4, 1, -1, 'NPC Equip 16151', 7, 28734, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16152, 4, 1, -1, 'NPC Equip 16152', 7, 28730, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16153, 4, 1, -1, 'NPC Equip 16153', 7, 16604, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16154, 4, 1, -1, 'NPC Equip 16154', 7, 28729, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16155, 4, 2, -1, 'NPC Equip 16155', 8, 11956, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16156, 4, 2, -1, 'NPC Equip 16156', 8, 21298, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16157, 4, 3, -1, 'NPC Equip 16157', 5, 14895, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16158, 4, 3, -1, 'NPC Equip 16158', 5, 25861, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16159, 4, 3, -1, 'NPC Equip 16159', 5, 30091, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16160, 4, 4, -1, 'NPC Equip 16160', 6, 19727, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16161, 4, 4, -1, 'NPC Equip 16161', 6, 19678, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16162, 4, 4, -1, 'NPC Equip 16162', 6, 19727, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16163, 4, 3, -1, 'NPC Equip 16163', 5, 25784, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16164, 4, 3, -1, 'NPC Equip 16164', 5, 25788, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16172, 4, 4, -1, 'NPC Equip 16172', 6, 19678, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16173, 15, 0, -1, 'NPC Equip 16173', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16174, 15, 0, -1, 'NPC Equip 16174', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16175, 15, 0, -1, 'NPC Equip 16175', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16176, 15, 0, -1, 'NPC Equip 16176', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16177, 15, 0, -1, 'NPC Equip 16177', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16178, 15, 0, -1, 'NPC Equip 16178', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16179, 15, 0, -1, 'NPC Equip 16179', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16181, 15, 0, -1, 'NPC Equip 16181', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16182, 15, 0, -1, 'NPC Equip 16182', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16183, 15, 0, -1, 'NPC Equip 16183', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16184, 15, 0, -1, 'NPC Equip 16184', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16185, 15, 0, -1, 'NPC Equip 16185', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16186, 15, 0, -1, 'NPC Equip 16186', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16187, 15, 0, -1, 'NPC Equip 16187', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16188, 15, 0, -1, 'NPC Equip 16188', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16191, 12, 0, -1, 'NPC Equip 16191', -1, 26754, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16211, 4, 4, -1, 'NPC Equip 16211', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16212, 2, 7, -1, 'NPC Equip 16212', 1, 9465, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16213, 4, 4, -1, 'NPC Equip 16213', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16308, 13, 0, -1, 'NPC Equip 16308', -1, 26926, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16338, 15, 0, -1, 'NPC Equip 16338', -1, 13108, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16343, 15, 0, -1, 'NPC Equip 16343', -1, 16208, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16344, 15, 0, -1, 'NPC Equip 16344', -1, 16208, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16367, 4, 1, -1, 'NPC Equip 16367', 7, 27163, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16370, 4, 1, -1, 'NPC Equip 16370', 7, 27165, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16394, 4, 2, -1, 'NPC Equip 16394', 8, 27204, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16395, 4, 2, -1, 'NPC Equip 16395', 8, 27204, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16398, 4, 2, -1, 'NPC Equip 16398', 8, 27209, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16399, 4, 2, -1, 'NPC Equip 16399', 8, 27209, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16400, 4, 3, -1, 'NPC Equip 16400', 5, 27211, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16402, 4, 3, -1, 'NPC Equip 16402', 5, 27217, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16404, 4, 4, -1, 'NPC Equip 16404', 6, 27223, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16407, 4, 4, -1, 'NPC Equip 16407', 6, 27226, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16411, 4, 4, -1, 'NPC Equip 16411', 6, 27226, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16412, 4, 4, -1, 'NPC Equip 16412', 6, 27223, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16438, 4, 1, -1, 'NPC Equip 16438', 7, 30338, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16439, 4, 1, -1, 'NPC Equip 16439', 7, 30340, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16445, 4, 2, -1, 'NPC Equip 16445', 8, 30331, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16447, 4, 2, -1, 'NPC Equip 16447', 8, 30332, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16458, 4, 2, -1, 'NPC Equip 16458', 8, 30332, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16460, 4, 2, -1, 'NPC Equip 16460', 8, 30331, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16461, 4, 3, -1, 'NPC Equip 16461', 5, 30324, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16464, 4, 3, -1, 'NPC Equip 16464', 5, 30325, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16469, 4, 4, -1, 'NPC Equip 16469', 6, 30320, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16470, 4, 4, -1, 'NPC Equip 16470', 6, 30322, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16481, 4, 4, -1, 'NPC Equip 16481', 6, 30320, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16482, 4, 4, -1, 'NPC Equip 16482', 6, 30322, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16488, 4, 1, -1, 'NPC Equip 16488', 7, 27257, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16493, 4, 2, -1, 'NPC Equip 16493', 8, 27262, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16495, 4, 2, -1, 'NPC Equip 16495', 8, 27264, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16500, 4, 2, -1, 'NPC Equip 16500', 8, 27264, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16511, 4, 4, -1, 'NPC Equip 16511', 6, 27272, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16512, 4, 4, -1, 'NPC Equip 16512', 6, 27273, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16517, 4, 3, -1, 'NPC Equip 16517', 5, 27277, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16520, 4, 3, -1, 'NPC Equip 16520', 5, 27280, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16529, 4, 3, -1, 'NPC Equip 16529', 5, 27280, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16537, 4, 1, -1, 'NPC Equip 16537', 7, 30346, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16538, 4, 1, -1, 'NPC Equip 16538', 7, 30345, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16546, 4, 4, -1, 'NPC Equip 16546', 6, 30369, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16547, 4, 4, -1, 'NPC Equip 16547', 6, 30372, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16553, 4, 2, -1, 'NPC Equip 16553', 8, 30353, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16556, 4, 2, -1, 'NPC Equip 16556', 8, 30354, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16557, 4, 2, -1, 'NPC Equip 16557', 8, 30354, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16559, 4, 2, -1, 'NPC Equip 16559', 8, 30353, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16570, 4, 3, -1, 'NPC Equip 16570', 5, 30362, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16572, 4, 3, -1, 'NPC Equip 16572', 5, 30364, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16575, 4, 3, -1, 'NPC Equip 16575', 5, 30364, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16576, 4, 3, -1, 'NPC Equip 16576', 5, 30362, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16582, 2, 19, -1, 'NPC Equip 16582', 2, 27451, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (16657, 12, 0, -1, 'NPC Equip 16657', -1, 7629, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17000, 4, 0, -1, 'NPC Equip 17000', -1, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17040, 2, 4, -1, 'NPC Equip 17040', 2, 28866, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17041, 2, 4, -1, 'NPC Equip 17041', 2, 28867, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17108, 4, 0, -1, 'NPC Equip 17108', 3, 23728, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17115, 12, 0, -1, 'NPC Equip 17115', -1, 9649, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17116, 12, 0, -1, 'NPC Equip 17116', -1, 9649, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17122, 12, 0, -1, 'NPC Equip 17122', -1, 29050, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17123, 2, 7, -1, 'NPC Equip 17123', 1, 29066, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17162, 0, 8, -1, 'NPC Equip 17162', -1, 2760, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17163, 0, 8, -1, 'NPC Equip 17163', -1, 29131, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17199, 0, 5, -1, 'NPC Equip 17199', -1, 29173, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17282, 2, 15, -1, 'NPC Equip 17282', 1, 29276, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17283, 2, 15, -1, 'NPC Equip 17283', 1, 6249, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17342, 2, 7, -1, 'NPC Equip 17342', 1, 1121, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17343, 4, 1, -1, 'NPC Equip 17343', 6, 15897, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17347, 12, 0, -1, 'NPC Equip 17347', 0, 23475, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17350, 0, 0, -1, 'NPC Equip 17350', 3, 15717, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17354, 12, 0, -1, 'NPC Equip 17354', -1, 29355, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17382, 2, 0, -1, 'NPC Equip 17382', 1, 29397, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17383, 2, 1, -1, 'NPC Equip 17383', 1, 29408, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17409, 12, 0, -1, 'NPC Equip 17409', -1, 29450, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17412, 9, 0, -1, 'NPC Equip 17412', -1, 1143, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17462, 2, 0, -1, 'NPC Equip 17462', 1, 29495, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17463, 2, 1, -1, 'NPC Equip 17463', 1, 29496, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17482, 4, 6, -1, 'NPC Equip 17482', 1, 29550, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17563, 4, 1, -1, 'NPC Equip 17563', 7, 27165, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17565, 4, 1, -1, 'NPC Equip 17565', 7, 27163, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17574, 4, 1, -1, 'NPC Equip 17574', 7, 27257, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17575, 4, 1, -1, 'NPC Equip 17575', 7, 27255, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17582, 4, 1, -1, 'NPC Equip 17582', 7, 30338, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17585, 4, 1, -1, 'NPC Equip 17585', 7, 30340, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17587, 4, 1, -1, 'NPC Equip 17587', 7, 30345, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17589, 4, 1, -1, 'NPC Equip 17589', 7, 30346, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17595, 4, 1, -1, 'NPC Equip 17595', 7, 27165, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17597, 4, 1, -1, 'NPC Equip 17597', 7, 27163, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17606, 4, 1, -1, 'NPC Equip 17606', 7, 30338, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17609, 4, 1, -1, 'NPC Equip 17609', 7, 30340, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17614, 4, 1, -1, 'NPC Equip 17614', 7, 27257, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17615, 4, 1, -1, 'NPC Equip 17615', 7, 27255, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17619, 4, 1, -1, 'NPC Equip 17619', 7, 30345, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17621, 4, 1, -1, 'NPC Equip 17621', 7, 30346, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17729, 0, 0, -1, 'NPC Equip 17729', 0, 29906, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17731, 12, 0, -1, 'NPC Equip 17731', -1, 3331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17783, 4, 0, -1, 'NPC Equip 17783', -1, 6494, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17824, 15, 0, -1, 'NPC Equip 17824', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17825, 15, 0, -1, 'NPC Equip 17825', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17826, 15, 0, -1, 'NPC Equip 17826', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17827, 0, 8, -1, 'NPC Equip 17827', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17828, 0, 8, -1, 'NPC Equip 17828', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17829, 0, 8, -1, 'NPC Equip 17829', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17830, 0, 8, -1, 'NPC Equip 17830', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17831, 15, 0, -1, 'NPC Equip 17831', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17832, 15, 0, -1, 'NPC Equip 17832', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17833, 15, 0, -1, 'NPC Equip 17833', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17834, 15, 0, -1, 'NPC Equip 17834', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17835, 15, 0, -1, 'NPC Equip 17835', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17836, 15, 0, -1, 'NPC Equip 17836', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17837, 15, 0, -1, 'NPC Equip 17837', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17838, 15, 0, -1, 'NPC Equip 17838', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17839, 15, 0, -1, 'NPC Equip 17839', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17840, 15, 0, -1, 'NPC Equip 17840', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17841, 15, 0, -1, 'NPC Equip 17841', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17842, 15, 0, -1, 'NPC Equip 17842', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17843, 15, 0, -1, 'NPC Equip 17843', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17844, 15, 0, -1, 'NPC Equip 17844', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17845, 15, 0, -1, 'NPC Equip 17845', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17846, 15, 0, -1, 'NPC Equip 17846', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17847, 15, 0, -1, 'NPC Equip 17847', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17848, 15, 0, -1, 'NPC Equip 17848', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17851, 15, 0, -1, 'NPC Equip 17851', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17852, 15, 0, -1, 'NPC Equip 17852', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17853, 15, 0, -1, 'NPC Equip 17853', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17854, 15, 0, -1, 'NPC Equip 17854', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17855, 15, 0, -1, 'NPC Equip 17855', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17856, 15, 0, -1, 'NPC Equip 17856', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17857, 15, 0, -1, 'NPC Equip 17857', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17858, 15, 0, -1, 'NPC Equip 17858', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17859, 15, 0, -1, 'NPC Equip 17859', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17860, 15, 0, -1, 'NPC Equip 17860', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17861, 15, 0, -1, 'NPC Equip 17861', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17862, 15, 0, -1, 'NPC Equip 17862', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17883, 0, 8, -1, 'NPC Equip 17883', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17884, 0, 8, -1, 'NPC Equip 17884', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17885, 0, 8, -1, 'NPC Equip 17885', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17888, 0, 8, -1, 'NPC Equip 17888', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17889, 0, 8, -1, 'NPC Equip 17889', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17890, 0, 8, -1, 'NPC Equip 17890', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17891, 0, 8, -1, 'NPC Equip 17891', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17892, 0, 8, -1, 'NPC Equip 17892', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17893, 0, 8, -1, 'NPC Equip 17893', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17894, 0, 8, -1, 'NPC Equip 17894', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17895, 0, 8, -1, 'NPC Equip 17895', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17896, 0, 8, -1, 'NPC Equip 17896', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17897, 0, 8, -1, 'NPC Equip 17897', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17898, 0, 8, -1, 'NPC Equip 17898', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17899, 0, 8, -1, 'NPC Equip 17899', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17910, 15, 0, -1, 'NPC Equip 17910', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17911, 15, 0, -1, 'NPC Equip 17911', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (17942, 2, 5, -1, 'NPC Equip 17942', 2, 30255, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18023, 4, 0, -1, 'NPC Equip 18023', 3, 4006, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18062, 2, 5, -1, 'NPC Equip 18062', 2, 30455, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18063, 15, 0, -1, 'NPC Equip 18063', -1, 24011, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18105, 0, 8, -1, 'NPC Equip 18105', 0, 30494, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18106, 0, 8, -1, 'NPC Equip 18106', 0, 12206, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18122, 2, 10, -1, 'NPC Equip 18122', 2, 30516, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18123, 2, 10, -1, 'NPC Equip 18123', 2, 30517, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18155, 12, 0, -1, 'NPC Equip 18155', -1, 30534, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18156, 12, 0, -1, 'NPC Equip 18156', -1, 30534, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18157, 12, 0, -1, 'NPC Equip 18157', -1, 30534, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18158, 12, 0, -1, 'NPC Equip 18158', -1, 30534, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18159, 12, 0, -1, 'NPC Equip 18159', -1, 30534, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18161, 4, 0, -1, 'NPC Equip 18161', 7, 9992, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18162, 4, 0, -1, 'NPC Equip 18162', 7, 9992, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18163, 4, 0, -1, 'NPC Equip 18163', 3, 9992, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18164, 4, 0, -1, 'NPC Equip 18164', 7, 9992, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18165, 4, 0, -1, 'NPC Equip 18165', 7, 9992, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18166, 4, 6, -1, 'NPC Equip 18166', 1, 30559, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18167, 2, 7, -1, 'NPC Equip 18167', 1, 16539, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18209, 0, 0, -1, 'NPC Equip 18209', -1, 26618, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18235, 9, 3, -1, 'NPC Equip 18235', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18293, 2, 0, -1, 'NPC Equip 18293', 1, 30638, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18316, 4, 0, -1, 'NPC Equip 18316', 3, 24122, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18355, 4, 0, -1, 'NPC Equip 18355', 3, 15420, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18419, 2, 1, -1, 'NPC Equip 18419', 1, 30791, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18431, 4, 4, -1, 'NPC Equip 18431', 6, 27273, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18433, 4, 3, -1, 'NPC Equip 18433', 5, 27277, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18438, 4, 0, -1, 'NPC Equip 18438', 1, 23521, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18439, 4, 1, -1, 'NPC Equip 18439', 7, 27088, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18446, 4, 4, -1, 'NPC Equip 18446', 6, 27223, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18474, 15, 0, -1, 'NPC Equip 18474', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18589, 12, 0, -1, 'NPC Equip 18589', -1, 20872, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18593, 12, 0, -1, 'NPC Equip 18593', 1, 30953, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18595, 0, 0, -1, 'NPC Equip 18595', -1, 7050, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18596, 2, 0, -1, 'NPC Equip 18596', 1, 30956, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18599, 0, 8, -1, 'NPC Equip 18599', -1, 36684, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18627, 12, 0, -1, 'NPC Equip 18627', -1, 31168, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18630, 12, 0, -1, 'NPC Equip 18630', -1, 31170, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18644, 2, 10, -1, 'NPC Equip 18644', 2, 31016, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18666, 0, 8, -1, 'NPC Equip 18666', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18667, 0, 8, -1, 'NPC Equip 18667', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18668, 0, 8, -1, 'NPC Equip 18668', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18669, 0, 8, -1, 'NPC Equip 18669', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18685, 12, 0, -1, 'NPC Equip 18685', -1, 16325, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18732, 4, 0, -1, 'NPC Equip 18732', -1, 25992, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18733, 4, 0, -1, 'NPC Equip 18733', -1, 25990, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18747, 4, 1, -1, 'NPC Equip 18747', 7, 27231, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18748, 12, 0, -1, 'NPC Equip 18748', -1, 3233, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18750, 12, 0, -1, 'NPC Equip 18750', -1, 18072, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18751, 12, 0, -1, 'NPC Equip 18751', -1, 6349, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18763, 2, 3, -1, 'NPC Equip 18763', 1, 31224, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18764, 2, 3, -1, 'NPC Equip 18764', 1, 31225, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18765, 2, 3, -1, 'NPC Equip 18765', 1, 31226, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18800, 2, 4, -1, 'NPC Equip 18800', 2, 31258, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18801, 2, 10, -1, 'NPC Equip 18801', -1, 31250, 21, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18882, 2, 8, -1, 'NPC Equip 18882', 1, 29170, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18903, 12, 0, -1, 'NPC Equip 18903', 8, 20625, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18942, 12, 0, -1, 'NPC Equip 18942', -1, 31376, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18963, 15, 2, -1, 'NPC Equip 18963', -1, 18051, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18965, 15, 2, -1, 'NPC Equip 18965', -1, 18051, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18966, 15, 2, -1, 'NPC Equip 18966', -1, 18051, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18967, 15, 2, -1, 'NPC Equip 18967', -1, 18048, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18968, 4, 0, -1, 'NPC Equip 18968', -1, 9836, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18971, 4, 0, -1, 'NPC Equip 18971', -1, 9837, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18982, 4, 0, -1, 'NPC Equip 18982', -1, 9840, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18983, 2, 7, -1, 'NPC Equip 18983', 1, 31419, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (18985, 2, 7, -1, 'NPC Equip 18985', 1, 31424, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19014, 2, 0, -1, 'NPC Equip 19014', 1, 22893, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19015, 2, 0, -1, 'NPC Equip 19015', 1, 5027, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19053, 2, 14, -1, 'NPC Equip 19053', 1, 31553, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19063, 0, 0, -1, 'NPC Equip 19063', -1, 21203, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19082, 6, 2, -1, 'NPC Equip 19082', 2, 23211, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19122, 4, 0, -1, 'NPC Equip 19122', 8, 31633, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19184, 2, 1, -1, 'NPC Equip 19184', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19185, 2, 1, -1, 'NPC Equip 19185', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19186, 2, 1, -1, 'NPC Equip 19186', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19187, 2, 1, -1, 'NPC Equip 19187', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19188, 2, 1, -1, 'NPC Equip 19188', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19189, 2, 1, -1, 'NPC Equip 19189', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19190, 2, 1, -1, 'NPC Equip 19190', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19191, 2, 1, -1, 'NPC Equip 19191', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19192, 2, 1, -1, 'NPC Equip 19192', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19193, 2, 1, -1, 'NPC Equip 19193', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19194, 2, 1, -1, 'NPC Equip 19194', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19195, 2, 1, -1, 'NPC Equip 19195', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19196, 2, 1, -1, 'NPC Equip 19196', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19197, 2, 1, -1, 'NPC Equip 19197', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19198, 2, 1, -1, 'NPC Equip 19198', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19199, 2, 1, -1, 'NPC Equip 19199', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19200, 2, 1, -1, 'NPC Equip 19200', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19201, 2, 1, -1, 'NPC Equip 19201', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19214, 2, 10, -1, 'NPC Equip 19214', 2, 31740, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19226, 2, 13, -1, 'NPC Equip 19226', 1, 6592, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19285, 6, 3, -1, 'NPC Equip 19285', 1, 8127, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19286, 6, 3, -1, 'NPC Equip 19286', 2, 26613, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19294, 4, 0, -1, 'NPC Equip 19294', -1, 6479, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19313, 2, 15, -1, 'NPC Equip 19313', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19314, 2, 15, -1, 'NPC Equip 19314', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19359, 2, 4, -1, 'NPC Equip 19359', 1, 31861, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19404, 2, 4, -1, 'NPC Equip 19404', 2, 31935, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19427, 2, 7, -1, 'NPC Equip 19427', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19428, 2, 7, -1, 'NPC Equip 19428', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19429, 15, 0, -1, 'NPC Equip 19429', 1, 26420, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19455, 2, 1, -1, 'NPC Equip 19455', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19456, 2, 7, -1, 'NPC Equip 19456', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19457, 2, 7, -1, 'NPC Equip 19457', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19482, 12, 0, -1, 'NPC Equip 19482', -1, 31995, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19485, 2, 14, -1, 'NPC Equip 19485', 1, 10814, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19486, 2, 14, -1, 'NPC Equip 19486', 1, 10815, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19487, 2, 14, -1, 'NPC Equip 19487', 1, 10816, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19488, 2, 14, -1, 'NPC Equip 19488', 1, 10817, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19489, 2, 18, -1, 'NPC Equip 19489', 2, 31239, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19490, 2, 2, -1, 'NPC Equip 19490', 2, 30926, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19502, 2, 7, -1, 'NPC Equip 19502', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19503, 2, 7, -1, 'NPC Equip 19503', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19504, 2, 7, -1, 'NPC Equip 19504', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19622, 2, 15, -1, 'NPC Equip 19622', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19623, 2, 5, -1, 'NPC Equip 19623', 2, 32140, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19662, 2, 1, -1, 'NPC Equip 19662', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19742, 4, 2, -1, 'NPC Equip 19742', 8, 32192, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19743, 4, 2, -1, 'NPC Equip 19743', 8, 32193, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19762, 2, 0, -1, 'NPC Equip 19762', 1, 32216, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19763, 4, 6, -1, 'NPC Equip 19763', 1, 32217, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19804, 15, 0, -1, 'NPC Equip 19804', -1, 24694, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19809, 2, 1, -1, 'NPC Equip 19809', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19810, 2, 15, -1, 'NPC Equip 19810', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19811, 2, 1, -1, 'NPC Equip 19811', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19837, 4, 2, -1, 'NPC Equip 19837', 2, 28827, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19844, 4, 1, -1, 'NPC Equip 19844', 7, 32544, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19847, 4, 1, -1, 'NPC Equip 19847', 7, 32544, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19860, 12, 0, -1, 'NPC Equip 19860', -1, 32302, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19868, 2, 2, -1, 'NPC Equip 19868', 2, 32570, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19916, 2, 4, -1, 'NPC Equip 19916', 2, 11958, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19917, 4, 0, -1, 'NPC Equip 19917', 1, 32382, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19926, 4, 1, -1, 'NPC Equip 19926', 7, 32400, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19932, 12, 0, -1, 'NPC Equip 19932', 0, 32414, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19966, 2, 2, -1, 'NPC Equip 19966', 2, 32766, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19976, 12, 0, -1, 'NPC Equip 19976', -1, 17288, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19977, 0, 0, -1, 'NPC Equip 19977', 0, 4181, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19980, 2, 15, -1, 'NPC Equip 19980', 1, 6451, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19981, 2, 8, -1, 'NPC Equip 19981', 1, 32490, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19983, 2, 19, -1, 'NPC Equip 19983', 2, 32507, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19985, 4, 4, -1, 'NPC Equip 19985', 6, 32509, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19987, 2, 15, -1, 'NPC Equip 19987', 1, 32511, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19988, 2, 5, -1, 'NPC Equip 19988', 2, 32514, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (19989, 4, 0, -1, 'NPC Equip 19989', -1, 32515, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20024, 12, 0, -1, 'NPC Equip 20024', -1, 4045, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20026, 12, 0, -1, 'NPC Equip 20026', -1, 6680, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20084, 15, 0, -1, 'NPC Equip 20084', 8, 1007, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20133, 4, 3, -1, 'NPC Equip 20133', 5, 32700, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20135, 4, 4, -1, 'NPC Equip 20135', 6, 29859, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20136, 4, 4, -1, 'NPC Equip 20136', 6, 29858, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20137, 4, 4, -1, 'NPC Equip 20137', 6, 29860, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20138, 4, 4, -1, 'NPC Equip 20138', 6, 29865, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20139, 4, 4, -1, 'NPC Equip 20139', 6, 25226, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20140, 4, 4, -1, 'NPC Equip 20140', 6, 29867, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20141, 4, 4, -1, 'NPC Equip 20141', 6, 29863, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20143, 4, 0, -1, 'NPC Equip 20143', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20144, 4, 0, -1, 'NPC Equip 20144', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20145, 4, 1, -1, 'NPC Equip 20145', 7, 27088, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20146, 2, 3, -1, 'NPC Equip 20146', 1, 31210, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20147, 4, 0, -1, 'NPC Equip 20147', -1, 31769, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20148, 4, 0, -1, 'NPC Equip 20148', -1, 31769, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20149, 2, 1, -1, 'NPC Equip 20149', 1, 39901, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20238, 2, 1, -1, 'NPC Equip 20238', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20239, 4, 4, -1, 'NPC Equip 20239', 6, 29859, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20240, 4, 4, -1, 'NPC Equip 20240', 6, 29858, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20241, 4, 1, -1, 'NPC Equip 20241', 7, 27088, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20242, 4, 4, -1, 'NPC Equip 20242', 6, 29860, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20245, 2, 3, -1, 'NPC Equip 20245', 1, 31210, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20246, 4, 4, -1, 'NPC Equip 20246', 6, 29865, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20247, 4, 4, -1, 'NPC Equip 20247', 6, 25226, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20248, 4, 0, -1, 'NPC Equip 20248', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20249, 4, 4, -1, 'NPC Equip 20249', 6, 29867, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20250, 4, 0, -1, 'NPC Equip 20250', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20251, 4, 4, -1, 'NPC Equip 20251', 6, 29863, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20252, 4, 4, -1, 'NPC Equip 20252', 6, 29864, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20267, 4, 2, -1, 'NPC Equip 20267', 8, 28177, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20268, 4, 2, -1, 'NPC Equip 20268', 8, 28162, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20269, 4, 2, -1, 'NPC Equip 20269', 8, 24190, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20270, 4, 2, -1, 'NPC Equip 20270', 8, 28180, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20271, 4, 2, -1, 'NPC Equip 20271', 8, 28166, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20272, 4, 2, -1, 'NPC Equip 20272', 8, 28161, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20273, 4, 2, -1, 'NPC Equip 20273', 8, 28179, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20274, 4, 2, -1, 'NPC Equip 20274', 8, 28160, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20275, 4, 0, -1, 'NPC Equip 20275', 5, 23716, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20276, 4, 1, -1, 'NPC Equip 20276', 7, 23553, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20277, 4, 0, -1, 'NPC Equip 20277', 5, 9837, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20278, 2, 2, -1, 'NPC Equip 20278', 2, 28827, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20279, 2, 15, -1, 'NPC Equip 20279', 1, 23262, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20280, 2, 1, -1, 'NPC Equip 20280', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20281, 4, 4, -1, 'NPC Equip 20281', 6, 29859, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20282, 4, 4, -1, 'NPC Equip 20282', 6, 29858, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20283, 4, 1, -1, 'NPC Equip 20283', 7, 27088, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20284, 4, 4, -1, 'NPC Equip 20284', 6, 29860, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20285, 2, 3, -1, 'NPC Equip 20285', 1, 31210, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20286, 4, 4, -1, 'NPC Equip 20286', 6, 29865, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20287, 4, 4, -1, 'NPC Equip 20287', 6, 25226, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20288, 4, 0, -1, 'NPC Equip 20288', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20289, 4, 4, -1, 'NPC Equip 20289', 6, 29867, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20290, 4, 0, -1, 'NPC Equip 20290', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20291, 4, 4, -1, 'NPC Equip 20291', 6, 29863, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20292, 4, 4, -1, 'NPC Equip 20292', 6, 29864, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20294, 4, 2, -1, 'NPC Equip 20294', 8, 28162, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20297, 4, 2, -1, 'NPC Equip 20297', 8, 28177, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20298, 4, 2, -1, 'NPC Equip 20298', 8, 28162, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20299, 2, 2, -1, 'NPC Equip 20299', 2, 28827, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20300, 4, 2, -1, 'NPC Equip 20300', 8, 24190, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20301, 4, 2, -1, 'NPC Equip 20301', 8, 28180, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20302, 4, 1, -1, 'NPC Equip 20302', 7, 23553, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20303, 2, 15, -1, 'NPC Equip 20303', 1, 23262, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20304, 4, 2, -1, 'NPC Equip 20304', 8, 28166, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20305, 4, 0, -1, 'NPC Equip 20305', 5, 23716, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20306, 4, 2, -1, 'NPC Equip 20306', 8, 28161, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20307, 4, 0, -1, 'NPC Equip 20307', 5, 9837, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20308, 4, 2, -1, 'NPC Equip 20308', 8, 28179, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20309, 4, 2, -1, 'NPC Equip 20309', 8, 28160, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20311, 4, 2, -1, 'NPC Equip 20311', 8, 28177, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20312, 4, 2, -1, 'NPC Equip 20312', 8, 28162, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20313, 2, 2, -1, 'NPC Equip 20313', 2, 28827, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20314, 4, 2, -1, 'NPC Equip 20314', 8, 24190, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20315, 4, 2, -1, 'NPC Equip 20315', 8, 28180, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20316, 4, 1, -1, 'NPC Equip 20316', 7, 23553, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20317, 2, 15, -1, 'NPC Equip 20317', 1, 23262, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20318, 4, 2, -1, 'NPC Equip 20318', 8, 28166, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20319, 4, 0, -1, 'NPC Equip 20319', 5, 23716, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20320, 4, 2, -1, 'NPC Equip 20320', 8, 28161, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20321, 4, 0, -1, 'NPC Equip 20321', 5, 9837, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20322, 4, 2, -1, 'NPC Equip 20322', 8, 28179, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20323, 4, 2, -1, 'NPC Equip 20323', 8, 28160, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20324, 4, 1, -1, 'NPC Equip 20324', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20325, 4, 1, -1, 'NPC Equip 20325', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20326, 4, 1, -1, 'NPC Equip 20326', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20327, 4, 1, -1, 'NPC Equip 20327', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20328, 4, 1, -1, 'NPC Equip 20328', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20330, 4, 1, -1, 'NPC Equip 20330', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20331, 4, 1, -1, 'NPC Equip 20331', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20332, 4, 0, -1, 'NPC Equip 20332', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20333, 4, 0, -1, 'NPC Equip 20333', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20334, 2, 10, -1, 'NPC Equip 20334', 2, 30870, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20335, 2, 19, -1, 'NPC Equip 20335', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20336, 4, 1, -1, 'NPC Equip 20336', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20337, 0, 8, -1, 'NPC Equip 20337', 0, 32768, 22, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20338, 4, 1, -1, 'NPC Equip 20338', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20339, 4, 1, -1, 'NPC Equip 20339', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20340, 4, 1, -1, 'NPC Equip 20340', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20341, 4, 1, -1, 'NPC Equip 20341', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20342, 4, 1, -1, 'NPC Equip 20342', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20343, 4, 1, -1, 'NPC Equip 20343', 7, 29273, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20344, 4, 1, -1, 'NPC Equip 20344', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20345, 4, 0, -1, 'NPC Equip 20345', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20346, 4, 0, -1, 'NPC Equip 20346', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20347, 4, 1, -1, 'NPC Equip 20347', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20348, 4, 1, -1, 'NPC Equip 20348', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20349, 2, 10, -1, 'NPC Equip 20349', 2, 30870, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20350, 2, 19, -1, 'NPC Equip 20350', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20351, 4, 1, -1, 'NPC Equip 20351', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20352, 4, 1, -1, 'NPC Equip 20352', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20353, 4, 1, -1, 'NPC Equip 20353', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20354, 4, 1, -1, 'NPC Equip 20354', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20355, 4, 1, -1, 'NPC Equip 20355', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20356, 4, 1, -1, 'NPC Equip 20356', 7, 29273, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20357, 4, 1, -1, 'NPC Equip 20357', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20358, 4, 0, -1, 'NPC Equip 20358', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20359, 4, 0, -1, 'NPC Equip 20359', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20360, 4, 1, -1, 'NPC Equip 20360', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20361, 4, 1, -1, 'NPC Equip 20361', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20362, 2, 10, -1, 'NPC Equip 20362', 2, 30870, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20363, 2, 19, -1, 'NPC Equip 20363', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20365, 0, 0, -1, 'NPC Equip 20365', 0, 32777, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20366, 15, 0, -1, 'NPC Equip 20366', 2, 32781, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20367, 15, 0, -1, 'NPC Equip 20367', 4, 32781, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20370, 2, 10, -1, 'NPC Equip 20370', 2, 20256, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20372, 2, 10, -1, 'NPC Equip 20372', 2, 20256, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20386, 0, 0, -1, 'NPC Equip 20386', 0, 32823, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20412, 2, 6, -1, 'NPC Equip 20412', 1, 32837, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20417, 2, 0, -1, 'NPC Equip 20417', 1, 25504, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20421, 15, 0, -1, 'NPC Equip 20421', -1, 9285, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20423, 7, 11, -1, 'NPC Equip 20423', 0, 2627, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20445, 4, 0, -1, 'NPC Equip 20445', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20446, 4, 0, -1, 'NPC Equip 20446', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20460, 15, 0, -1, 'NPC Equip 20460', -1, 32846, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20462, 12, 0, -1, 'NPC Equip 20462', 3, 32849, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20468, 2, 14, -1, 'NPC Equip 20468', 1, 32858, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20473, 0, 0, -1, 'NPC Equip 20473', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20484, 15, 0, -1, 'NPC Equip 20484', -1, 3029, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20485, 12, 0, -1, 'NPC Equip 20485', -1, 32879, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20486, 15, 0, -1, 'NPC Equip 20486', -1, 26420, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20489, 12, 0, -1, 'NPC Equip 20489', -1, 32880, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20523, 4, 2, -1, 'NPC Equip 20523', 7, 30582, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20525, 4, 0, -1, 'NPC Equip 20525', -1, 32912, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20529, 4, 1, -1, 'NPC Equip 20529', 7, 32916, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20583, 4, 0, -1, 'NPC Equip 20583', -1, 41720, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20584, 4, 0, -1, 'NPC Equip 20584', -1, 41721, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20585, 4, 0, -1, 'NPC Equip 20585', -1, 41722, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20586, 4, 0, -1, 'NPC Equip 20586', -1, 41723, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20587, 4, 0, -1, 'NPC Equip 20587', -1, 41724, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20588, 4, 0, -1, 'NPC Equip 20588', -1, 41725, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20589, 4, 0, -1, 'NPC Equip 20589', -1, 41726, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20590, 4, 0, -1, 'NPC Equip 20590', -1, 41727, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20592, 4, 0, -1, 'NPC Equip 20592', -1, 41729, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20593, 4, 0, -1, 'NPC Equip 20593', -1, 41730, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20594, 4, 0, -1, 'NPC Equip 20594', -1, 41731, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20595, 4, 0, -1, 'NPC Equip 20595', -1, 41732, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20597, 4, 0, -1, 'NPC Equip 20597', -1, 41734, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20598, 4, 0, -1, 'NPC Equip 20598', -1, 41735, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20609, 15, 0, -1, 'NPC Equip 20609', -1, 33025, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20718, 2, 10, -1, 'NPC Equip 20718', 2, 33163, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20719, 2, 10, -1, 'NPC Equip 20719', 2, 33170, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20737, 15, 0, -1, 'NPC Equip 20737', -1, 33177, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20738, 2, 4, -1, 'NPC Equip 20738', 1, 33181, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20739, 12, 0, -1, 'NPC Equip 20739', 1, 31500, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20740, 12, 0, -1, 'NPC Equip 20740', -1, 33188, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20751, 9, 8, -1, 'NPC Equip 20751', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20762, 12, 0, -1, 'NPC Equip 20762', 1, 33197, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20773, 4, 3, -1, 'NPC Equip 20773', 5, 45174, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20774, 4, 3, -1, 'NPC Equip 20774', 5, 30925, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20775, 4, 3, -1, 'NPC Equip 20775', 5, 31416, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20776, 4, 3, -1, 'NPC Equip 20776', 5, 31411, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20777, 4, 3, -1, 'NPC Equip 20777', 5, 31414, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20778, 4, 3, -1, 'NPC Equip 20778', 5, 31413, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20779, 4, 3, -1, 'NPC Equip 20779', 5, 31415, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20780, 4, 3, -1, 'NPC Equip 20780', 5, 31412, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20781, 4, 0, -1, 'NPC Equip 20781', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20782, 4, 1, -1, 'NPC Equip 20782', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20783, 4, 0, -1, 'NPC Equip 20783', -1, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20784, 2, 1, -1, 'NPC Equip 20784', 1, 23904, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20785, 4, 1, -1, 'NPC Equip 20785', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20786, 4, 3, -1, 'NPC Equip 20786', 5, 31411, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20787, 4, 3, -1, 'NPC Equip 20787', 5, 31412, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20788, 4, 3, -1, 'NPC Equip 20788', 5, 31117, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20789, 4, 3, -1, 'NPC Equip 20789', 5, 31413, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20790, 4, 3, -1, 'NPC Equip 20790', 5, 31414, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20791, 4, 3, -1, 'NPC Equip 20791', 5, 31415, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20792, 4, 0, -1, 'NPC Equip 20792', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20793, 4, 3, -1, 'NPC Equip 20793', 5, 30925, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20794, 4, 0, -1, 'NPC Equip 20794', -1, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20795, 4, 3, -1, 'NPC Equip 20795', 5, 31416, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20796, 2, 1, -1, 'NPC Equip 20796', 1, 23904, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20798, 12, 0, -1, 'NPC Equip 20798', -1, 18632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20811, 2, 7, -1, 'NPC Equip 20811', 1, 33220, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20814, 15, 0, -1, 'NPC Equip 20814', 1, 26361, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20834, 7, 3, -1, 'NPC Equip 20834', 8, 7365, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20883, 12, 0, -1, 'NPC Equip 20883', 1, 32253, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20905, 0, 0, -1, 'NPC Equip 20905', -1, 33261, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20908, 15, 3, -1, 'NPC Equip 20908', -1, 33261, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20936, 12, 0, -1, 'NPC Equip 20936', 1, 32253, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20937, 12, 0, -1, 'NPC Equip 20937', 1, 32253, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20946, 12, 0, -1, 'NPC Equip 20946', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20968, 4, 0, -1, 'NPC Equip 20968', -1, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (20972, 9, 10, -1, 'NPC Equip 20972', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21026, 15, 0, -1, 'NPC Equip 21026', 0, 13990, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21034, 2, 1, -1, 'NPC Equip 21034', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21035, 2, 15, -1, 'NPC Equip 21035', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21036, 2, 2, -1, 'NPC Equip 21036', 2, 28827, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21045, 4, 1, -1, 'NPC Equip 21045', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21046, 4, 1, -1, 'NPC Equip 21046', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21047, 4, 1, -1, 'NPC Equip 21047', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21048, 4, 1, -1, 'NPC Equip 21048', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21049, 4, 1, -1, 'NPC Equip 21049', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21050, 4, 1, -1, 'NPC Equip 21050', 7, 29273, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21051, 4, 1, -1, 'NPC Equip 21051', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21052, 4, 0, -1, 'NPC Equip 21052', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21053, 4, 0, -1, 'NPC Equip 21053', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21054, 4, 1, -1, 'NPC Equip 21054', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21055, 4, 1, -1, 'NPC Equip 21055', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21056, 2, 10, -1, 'NPC Equip 21056', 2, 30870, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21057, 2, 19, -1, 'NPC Equip 21057', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21058, 4, 1, -1, 'NPC Equip 21058', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21059, 4, 1, -1, 'NPC Equip 21059', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21060, 4, 1, -1, 'NPC Equip 21060', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21061, 4, 1, -1, 'NPC Equip 21061', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21062, 4, 1, -1, 'NPC Equip 21062', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21063, 4, 1, -1, 'NPC Equip 21063', 7, 29273, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21064, 4, 1, -1, 'NPC Equip 21064', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21065, 4, 0, -1, 'NPC Equip 21065', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21066, 4, 0, -1, 'NPC Equip 21066', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21067, 4, 1, -1, 'NPC Equip 21067', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21068, 4, 1, -1, 'NPC Equip 21068', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21069, 2, 10, -1, 'NPC Equip 21069', 2, 30870, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21070, 2, 19, -1, 'NPC Equip 21070', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21073, 4, 1, -1, 'NPC Equip 21073', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21074, 4, 1, -1, 'NPC Equip 21074', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21075, 4, 1, -1, 'NPC Equip 21075', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21076, 4, 1, -1, 'NPC Equip 21076', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21077, 4, 1, -1, 'NPC Equip 21077', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21078, 4, 1, -1, 'NPC Equip 21078', 7, 29273, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21079, 4, 1, -1, 'NPC Equip 21079', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21080, 4, 0, -1, 'NPC Equip 21080', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21081, 4, 0, -1, 'NPC Equip 21081', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21082, 4, 1, -1, 'NPC Equip 21082', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21083, 4, 1, -1, 'NPC Equip 21083', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21084, 2, 10, -1, 'NPC Equip 21084', 2, 30870, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21085, 2, 19, -1, 'NPC Equip 21085', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21086, 4, 1, -1, 'NPC Equip 21086', 7, 29596, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21087, 4, 1, -1, 'NPC Equip 21087', 7, 29597, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21088, 4, 1, -1, 'NPC Equip 21088', 7, 29594, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21089, 4, 1, -1, 'NPC Equip 21089', 7, 31087, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21090, 4, 1, -1, 'NPC Equip 21090', 7, 29593, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21091, 4, 1, -1, 'NPC Equip 21091', 7, 29273, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21092, 4, 1, -1, 'NPC Equip 21092', 7, 30211, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21093, 4, 0, -1, 'NPC Equip 21093', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21094, 4, 0, -1, 'NPC Equip 21094', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21095, 4, 1, -1, 'NPC Equip 21095', 7, 29591, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21096, 4, 1, -1, 'NPC Equip 21096', 7, 26681, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21097, 2, 10, -1, 'NPC Equip 21097', 2, 30870, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21098, 2, 19, -1, 'NPC Equip 21098', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21101, 2, 10, -1, 'NPC Equip 21101', 2, 33422, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21102, 2, 10, -1, 'NPC Equip 21102', 2, 33421, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21121, 2, 14, -1, 'NPC Equip 21121', 1, 33424, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21122, 2, 15, -1, 'NPC Equip 21122', 1, 33425, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21123, 2, 14, -1, 'NPC Equip 21123', 1, 33426, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21129, 2, 0, -1, 'NPC Equip 21129', 1, 33434, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21135, 15, 0, -1, 'NPC Equip 21135', 1, 26358, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21163, 15, 4, -1, 'NPC Equip 21163', -1, 7135, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21169, 15, 0, -1, 'NPC Equip 21169', 0, 33468, 22, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21170, 15, 0, -1, 'NPC Equip 21170', 0, 33469, 22, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21172, 15, 0, -1, 'NPC Equip 21172', 0, 33470, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21173, 15, 0, -1, 'NPC Equip 21173', -1, 33470, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21192, 2, 1, -1, 'NPC Equip 21192', 1, 33536, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21193, 1, 1, -1, 'NPC Equip 21193', 8, 20342, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21194, 1, 1, -1, 'NPC Equip 21194', 8, 20342, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21195, 1, 1, -1, 'NPC Equip 21195', 8, 20342, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21231, 15, 0, -1, 'NPC Equip 21231', 1, 33548, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21233, 15, 0, -1, 'NPC Equip 21233', 2, 33550, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21234, 15, 0, -1, 'NPC Equip 21234', 2, 31118, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21236, 0, 5, -1, 'NPC Equip 21236', -1, 6343, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21238, 0, 0, -1, 'NPC Equip 21238', -1, 33555, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21239, 15, 0, -1, 'NPC Equip 21239', 2, 33554, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21240, 0, 5, -1, 'NPC Equip 21240', -1, 29331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21246, 12, 0, -1, 'NPC Equip 21246', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21247, 12, 0, -1, 'NPC Equip 21247', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21274, 15, 0, -1, 'NPC Equip 21274', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21276, 2, 10, -1, 'NPC Equip 21276', 2, 33567, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21286, 2, 1, -1, 'NPC Equip 21286', 1, 33578, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21313, 1, 1, -1, 'NPC Equip 21313', 8, 20342, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21369, 9, 2, -1, 'NPC Equip 21369', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21419, 4, 0, -1, 'NPC Equip 21419', 0, 33779, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21420, 4, 0, -1, 'NPC Equip 21420', 0, 33766, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21421, 4, 0, -1, 'NPC Equip 21421', 0, 33767, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21422, 4, 0, -1, 'NPC Equip 21422', 0, 33768, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21423, 4, 0, -1, 'NPC Equip 21423', 0, 33770, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21424, 4, 0, -1, 'NPC Equip 21424', 0, 33770, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21425, 4, 0, -1, 'NPC Equip 21425', 0, 33771, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21426, 4, 0, -1, 'NPC Equip 21426', 0, 33772, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21427, 4, 0, -1, 'NPC Equip 21427', 0, 33775, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21428, 4, 0, -1, 'NPC Equip 21428', 0, 33776, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21429, 4, 0, -1, 'NPC Equip 21429', 0, 33780, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21430, 4, 0, -1, 'NPC Equip 21430', 0, 47348, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21431, 4, 0, -1, 'NPC Equip 21431', 0, 33782, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21432, 4, 0, -1, 'NPC Equip 21432', 0, 33783, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21433, 4, 0, -1, 'NPC Equip 21433', 0, 33784, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21434, 4, 0, -1, 'NPC Equip 21434', 0, 33785, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21435, 4, 0, -1, 'NPC Equip 21435', 0, 33787, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21437, 4, 0, -1, 'NPC Equip 21437', 0, 33788, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21439, 4, 0, -1, 'NPC Equip 21439', 0, 33791, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21440, 4, 0, -1, 'NPC Equip 21440', 0, 33792, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21441, 4, 0, -1, 'NPC Equip 21441', 0, 33793, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21443, 4, 0, -1, 'NPC Equip 21443', 0, 33796, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21444, 4, 0, -1, 'NPC Equip 21444', 0, 33799, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21445, 4, 0, -1, 'NPC Equip 21445', 0, 33793, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21446, 4, 0, -1, 'NPC Equip 21446', 0, 33802, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21447, 4, 0, -1, 'NPC Equip 21447', 0, 33767, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21448, 4, 0, -1, 'NPC Equip 21448', 0, 33803, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21449, 4, 0, -1, 'NPC Equip 21449', 0, 33804, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21450, 4, 0, -1, 'NPC Equip 21450', 0, 33806, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21451, 4, 0, -1, 'NPC Equip 21451', 0, 33807, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21465, 2, 0, -1, 'NPC Equip 21465', 1, 33835, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21516, 2, 15, -1, 'NPC Equip 21516', 2, 33422, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21518, 2, 15, -1, 'NPC Equip 21518', 2, 33422, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21549, 4, 6, -1, 'NPC Equip 21549', 1, 34101, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21550, 2, 18, -1, 'NPC Equip 21550', 2, 34115, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21551, 2, 15, -1, 'NPC Equip 21551', 1, 34105, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21553, 2, 8, -1, 'NPC Equip 21553', 1, 34106, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21554, 2, 3, -1, 'NPC Equip 21554', 1, 34107, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21555, 2, 5, -1, 'NPC Equip 21555', 2, 31954, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21556, 0, 0, -1, 'NPC Equip 21556', -1, 4181, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21564, 2, 3, -1, 'NPC Equip 21564', 1, 34116, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21572, 4, 6, -1, 'NPC Equip 21572', 1, 34127, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21573, 2, 7, -1, 'NPC Equip 21573', 1, 34128, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21575, 15, 3, -1, 'NPC Equip 21575', -1, 34273, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21580, 2, 1, -1, 'NPC Equip 21580', 1, 34133, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21628, 15, 0, -1, 'NPC Equip 21628', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21629, 15, 0, -1, 'NPC Equip 21629', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21630, 15, 0, -1, 'NPC Equip 21630', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21631, 15, 0, -1, 'NPC Equip 21631', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21632, 15, 0, -1, 'NPC Equip 21632', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21633, 15, 0, -1, 'NPC Equip 21633', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21634, 15, 0, -1, 'NPC Equip 21634', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21636, 15, 0, -1, 'NPC Equip 21636', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21637, 15, 0, -1, 'NPC Equip 21637', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21638, 15, 0, -1, 'NPC Equip 21638', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21641, 15, 0, -1, 'NPC Equip 21641', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21642, 15, 0, -1, 'NPC Equip 21642', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21643, 15, 0, -1, 'NPC Equip 21643', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21644, 15, 0, -1, 'NPC Equip 21644', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21646, 15, 0, -1, 'NPC Equip 21646', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21649, 15, 0, -1, 'NPC Equip 21649', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21653, 15, 0, -1, 'NPC Equip 21653', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21654, 15, 0, -1, 'NPC Equip 21654', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21655, 15, 0, -1, 'NPC Equip 21655', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21656, 15, 0, -1, 'NPC Equip 21656', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21657, 15, 0, -1, 'NPC Equip 21657', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21658, 15, 0, -1, 'NPC Equip 21658', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21659, 15, 0, -1, 'NPC Equip 21659', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21660, 15, 0, -1, 'NPC Equip 21660', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21661, 15, 0, -1, 'NPC Equip 21661', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21662, 15, 0, -1, 'NPC Equip 21662', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21717, 15, 3, -1, 'NPC Equip 21717', -1, 34357, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21719, 15, 3, -1, 'NPC Equip 21719', -1, 34359, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21720, 15, 3, -1, 'NPC Equip 21720', -1, 34360, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21736, 15, 0, -1, 'NPC Equip 21736', -1, 36142, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21739, 0, 0, -1, 'NPC Equip 21739', -1, 34342, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21759, 4, 0, -1, 'NPC Equip 21759', -1, 34374, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21782, 2, 7, -1, 'NPC Equip 21782', 1, 31808, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21787, 12, 0, -1, 'NPC Equip 21787', -1, 34390, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21788, 12, 0, -1, 'NPC Equip 21788', -1, 2480, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21794, 2, 8, -1, 'NPC Equip 21794', 1, 34304, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21795, 2, 10, -1, 'NPC Equip 21795', 2, 34391, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21796, 2, 14, -1, 'NPC Equip 21796', 1, 34399, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21797, 2, 8, -1, 'NPC Equip 21797', 6, 34402, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21798, 2, 8, -1, 'NPC Equip 21798', 6, 34404, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21799, 2, 8, -1, 'NPC Equip 21799', 1, 34405, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21811, 12, 0, -1, 'NPC Equip 21811', 0, 14005, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21832, 0, 0, -1, 'NPC Equip 21832', 0, 34430, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21834, 0, 0, -1, 'NPC Equip 21834', 0, 34431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21857, 1, 2, -1, 'NPC Equip 21857', 8, 33940, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21879, 7, 11, -1, 'NPC Equip 21879', -1, 20978, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21880, 12, 0, -1, 'NPC Equip 21880', -1, 4775, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21883, 7, 5, -1, 'NPC Equip 21883', 7, 25028, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21922, 0, 0, -1, 'NPC Equip 21922', -1, 34488, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21923, 12, 0, -1, 'NPC Equip 21923', -1, 22614, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21924, 9, 2, -1, 'NPC Equip 21924', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21930, 12, 0, -1, 'NPC Equip 21930', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21950, 9, 10, -1, 'NPC Equip 21950', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21951, 9, 10, -1, 'NPC Equip 21951', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21958, 9, 10, -1, 'NPC Equip 21958', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21959, 9, 10, -1, 'NPC Equip 21959', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21961, 0, 0, -1, 'NPC Equip 21961', -1, 22651, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21962, 12, 0, -1, 'NPC Equip 21962', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21963, 12, 0, -1, 'NPC Equip 21963', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21964, 12, 0, -1, 'NPC Equip 21964', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21965, 0, 0, -1, 'NPC Equip 21965', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21966, 0, 0, -1, 'NPC Equip 21966', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21967, 0, 0, -1, 'NPC Equip 21967', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21968, 0, 0, -1, 'NPC Equip 21968', -1, 30690, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21969, 0, 0, -1, 'NPC Equip 21969', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21970, 0, 0, -1, 'NPC Equip 21970', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21971, 0, 0, -1, 'NPC Equip 21971', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21972, 0, 0, -1, 'NPC Equip 21972', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21973, 0, 0, -1, 'NPC Equip 21973', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21974, 0, 0, -1, 'NPC Equip 21974', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21976, 0, 0, -1, 'NPC Equip 21976', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21977, 0, 0, -1, 'NPC Equip 21977', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (21978, 0, 0, -1, 'NPC Equip 21978', -1, 34490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22021, 0, 8, -1, 'NPC Equip 22021', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22022, 0, 8, -1, 'NPC Equip 22022', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22025, 0, 8, -1, 'NPC Equip 22025', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22026, 0, 8, -1, 'NPC Equip 22026', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22027, 0, 8, -1, 'NPC Equip 22027', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22028, 0, 8, -1, 'NPC Equip 22028', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22029, 0, 8, -1, 'NPC Equip 22029', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22030, 0, 8, -1, 'NPC Equip 22030', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22031, 0, 8, -1, 'NPC Equip 22031', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22032, 0, 8, -1, 'NPC Equip 22032', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22033, 0, 8, -1, 'NPC Equip 22033', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22034, 0, 8, -1, 'NPC Equip 22034', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22035, 0, 8, -1, 'NPC Equip 22035', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22036, 0, 8, -1, 'NPC Equip 22036', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22037, 0, 8, -1, 'NPC Equip 22037', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22038, 0, 8, -1, 'NPC Equip 22038', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22039, 0, 8, -1, 'NPC Equip 22039', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22040, 0, 8, -1, 'NPC Equip 22040', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22041, 0, 8, -1, 'NPC Equip 22041', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22043, 0, 8, -1, 'NPC Equip 22043', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22118, 0, 0, -1, 'NPC Equip 22118', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22124, 0, 0, -1, 'NPC Equip 22124', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22125, 0, 0, -1, 'NPC Equip 22125', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22126, 0, 0, -1, 'NPC Equip 22126', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22127, 0, 0, -1, 'NPC Equip 22127', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22129, 0, 0, -1, 'NPC Equip 22129', -1, 15589, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22130, 15, 3, -1, 'NPC Equip 22130', -1, 7045, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22151, 12, 0, -1, 'NPC Equip 22151', -1, 3665, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22152, 15, 0, -1, 'NPC Equip 22152', -1, 2584, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22199, 2, 1, -1, 'NPC Equip 22199', 1, 34534, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22210, 2, 13, -1, 'NPC Equip 22210', 1, 34557, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22211, 2, 13, -1, 'NPC Equip 22211', 1, 34557, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22213, 2, 4, -1, 'NPC Equip 22213', 2, 34559, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22215, 2, 15, -1, 'NPC Equip 22215', 1, 34560, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22233, 1, 0, -1, 'NPC Equip 22233', 1, 12333, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22258, 15, 0, -1, 'NPC Equip 22258', -1, 983, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22316, 4, 7, -1, 'NPC Equip 22316', 0, 34795, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22323, 0, 0, -1, 'NPC Equip 22323', -1, 26733, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22341, 2, 4, -1, 'NPC Equip 22341', 2, 34820, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22346, 2, 5, -1, 'NPC Equip 22346', 2, 34822, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22391, 2, 10, -1, 'NPC Equip 22391', 2, 34891, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22415, 12, 0, -1, 'NPC Equip 22415', -1, 19528, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22453, 5, 0, -1, 'NPC Equip 22453', -1, 23287, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22454, 5, 0, -1, 'NPC Equip 22454', -1, 13689, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22455, 5, 0, -1, 'NPC Equip 22455', -1, 23285, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22474, 12, 0, -1, 'NPC Equip 22474', -1, 34962, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22475, 12, 0, -1, 'NPC Equip 22475', -1, 34963, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22485, 15, 0, -1, 'NPC Equip 22485', -1, 20220, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22486, 13, 0, -1, 'NPC Equip 22486', -1, 10365, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22546, 9, 8, -1, 'NPC Equip 22546', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22564, 9, 8, -1, 'NPC Equip 22564', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22569, 12, 0, -1, 'NPC Equip 22569', -1, 3671, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22581, 12, 0, -1, 'NPC Equip 22581', -1, 8926, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22582, 12, 0, -1, 'NPC Equip 22582', -1, 8928, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22585, 0, 8, -1, 'NPC Equip 22585', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22586, 0, 8, -1, 'NPC Equip 22586', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22587, 0, 8, -1, 'NPC Equip 22587', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22588, 0, 8, -1, 'NPC Equip 22588', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22596, 2, 8, -1, 'NPC Equip 22596', 0, 35031, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22619, 12, 0, -1, 'NPC Equip 22619', -1, 16065, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22625, 12, 0, -1, 'NPC Equip 22625', -1, 16065, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22626, 12, 0, -1, 'NPC Equip 22626', -1, 16065, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22643, 7, 0, -1, 'NPC Equip 22643', -1, 25467, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22684, 9, 2, -1, 'NPC Equip 22684', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22685, 9, 2, -1, 'NPC Equip 22685', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22686, 9, 2, -1, 'NPC Equip 22686', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22687, 9, 2, -1, 'NPC Equip 22687', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22692, 9, 1, -1, 'NPC Equip 22692', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22694, 9, 2, -1, 'NPC Equip 22694', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22695, 9, 2, -1, 'NPC Equip 22695', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22696, 9, 1, -1, 'NPC Equip 22696', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22697, 9, 2, -1, 'NPC Equip 22697', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22698, 9, 2, -1, 'NPC Equip 22698', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22703, 9, 4, -1, 'NPC Equip 22703', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22704, 9, 4, -1, 'NPC Equip 22704', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22705, 9, 4, -1, 'NPC Equip 22705', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22724, 2, 4, -1, 'NPC Equip 22724', 2, 35129, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22738, 2, 7, -1, 'NPC Equip 22738', 1, 35151, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22751, 4, 4, -1, 'NPC Equip 22751', 6, 35069, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22765, 15, 0, -1, 'NPC Equip 22765', 7, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22898, 12, 0, -1, 'NPC Equip 22898', -1, 2516, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22928, 12, 0, -1, 'NPC Equip 22928', -1, 2516, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22929, 12, 0, -1, 'NPC Equip 22929', -1, 2516, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22931, 12, 0, -1, 'NPC Equip 22931', -1, 2516, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22933, 12, 0, -1, 'NPC Equip 22933', -1, 20661, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (22989, 12, 0, -1, 'NPC Equip 22989', -1, 31604, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23026, 12, 0, -1, 'NPC Equip 23026', -1, 35425, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23052, 2, 18, -1, 'NPC Equip 23052', 1, 35456, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23074, 12, 0, -1, 'NPC Equip 23074', -1, 7054, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23080, 7, 0, -1, 'NPC Equip 23080', -1, 33298, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23086, 15, 3, -1, 'NPC Equip 23086', 0, 35546, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23102, 7, 0, -1, 'NPC Equip 23102', -1, 20978, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23158, 3, 7, -1, 'NPC Equip 23158', -1, 13496, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23159, 3, 7, -1, 'NPC Equip 23159', -1, 13496, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23163, 0, 0, -1, 'NPC Equip 23163', -1, 35583, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23164, 0, 0, -1, 'NPC Equip 23164', -1, 18114, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23172, 0, 5, -1, 'NPC Equip 23172', -1, 6410, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23174, 2, 15, -1, 'NPC Equip 23174', 1, 2738, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23175, 0, 0, -1, 'NPC Equip 23175', -1, 26732, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23176, 0, 0, -1, 'NPC Equip 23176', 3, 35592, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23185, 12, 0, -1, 'NPC Equip 23185', -1, 35595, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23186, 12, 0, -1, 'NPC Equip 23186', -1, 35596, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23187, 12, 0, -1, 'NPC Equip 23187', -1, 30562, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23188, 12, 0, -1, 'NPC Equip 23188', -1, 30562, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23189, 12, 0, -1, 'NPC Equip 23189', -1, 35595, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23190, 12, 0, -1, 'NPC Equip 23190', -1, 35596, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23202, 4, 7, -1, 'NPC Equip 23202', 2, 34960, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23204, 4, 7, -1, 'NPC Equip 23204', 2, 34959, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23208, 4, 0, -1, 'NPC Equip 23208', -1, 35621, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23209, 0, 0, -1, 'NPC Equip 23209', 0, 35657, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23210, 0, 0, -1, 'NPC Equip 23210', -1, 3568, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23212, 4, 0, -1, 'NPC Equip 23212', 7, 35675, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23213, 4, 1, -1, 'NPC Equip 23213', 7, 6773, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23216, 12, 0, -1, 'NPC Equip 23216', -1, 9731, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23222, 12, 0, -1, 'NPC Equip 23222', -1, 13002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23223, 12, 0, -1, 'NPC Equip 23223', -1, 22207, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23225, 2, 7, -1, 'NPC Equip 23225', 1, 33304, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23230, 2, 7, -1, 'NPC Equip 23230', 1, 35716, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23231, 12, 0, -1, 'NPC Equip 23231', -1, 35761, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23232, 2, 7, -1, 'NPC Equip 23232', 1, 25646, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23236, 7, 4, -1, 'NPC Equip 23236', -1, 4171, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23240, 2, 10, -1, 'NPC Equip 23240', 2, 33299, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23241, 2, 7, -1, 'NPC Equip 23241', 1, 35731, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23245, 0, 8, -1, 'NPC Equip 23245', 0, 35738, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23271, 15, 0, -1, 'NPC Equip 23271', -1, 12333, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23325, 15, 0, -1, 'NPC Equip 23325', -1, 35830, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23328, 2, 8, -1, 'NPC Equip 23328', 1, 35839, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23335, 2, 10, -1, 'NPC Equip 23335', 2, 35855, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23349, 4, 0, -1, 'NPC Equip 23349', 7, 9977, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23351, 4, 0, -1, 'NPC Equip 23351', 7, 9976, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23356, 4, 6, -1, 'NPC Equip 23356', 1, 35878, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23357, 12, 0, -1, 'NPC Equip 23357', -1, 18053, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23359, 7, 0, -1, 'NPC Equip 23359', 3, 2516, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23369, 2, 15, -1, 'NPC Equip 23369', 1, 35899, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23374, 12, 0, -1, 'NPC Equip 23374', -1, 19312, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23382, 2, 7, -1, 'NPC Equip 23382', 1, 35912, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23388, 4, 0, -1, 'NPC Equip 23388', 7, 35929, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23416, 2, 10, -1, 'NPC Equip 23416', 2, 35945, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23418, 7, 2, -1, 'NPC Equip 23418', 8, 20535, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23419, 2, 15, -1, 'NPC Equip 23419', 1, 20425, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23428, 2, 0, -1, 'NPC Equip 23428', 1, 37666, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23443, 12, 0, -1, 'NPC Equip 23443', -1, 35948, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23450, 2, 15, -1, 'NPC Equip 23450', 1, 36036, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23463, 4, 0, -1, 'NPC Equip 23463', 3, 36268, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23470, 4, 0, -1, 'NPC Equip 23470', 7, 36103, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23472, 4, 0, -1, 'NPC Equip 23472', 7, 36108, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23481, 2, 15, -1, 'NPC Equip 23481', 1, 36154, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23496, 0, 0, -1, 'NPC Equip 23496', -1, 34281, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23581, 12, 0, -1, 'NPC Equip 23581', -1, 7287, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23582, 2, 0, -1, 'NPC Equip 23582', 1, 36381, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23583, 2, 4, -1, 'NPC Equip 23583', 1, 36382, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23616, 15, 0, -1, 'NPC Equip 23616', -1, 6689, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23640, 0, 0, -1, 'NPC Equip 23640', 0, 32426, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23641, 0, 0, -1, 'NPC Equip 23641', 0, 36405, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23647, 2, 7, -1, 'NPC Equip 23647', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23648, 2, 7, -1, 'NPC Equip 23648', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23649, 2, 7, -1, 'NPC Equip 23649', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23650, 2, 15, -1, 'NPC Equip 23650', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23651, 2, 7, -1, 'NPC Equip 23651', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23652, 2, 7, -1, 'NPC Equip 23652', 1, 26494, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23653, 2, 7, -1, 'NPC Equip 23653', 1, 26494, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23655, 12, 0, -1, 'NPC Equip 23655', -1, 34509, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23656, 0, 8, -1, 'NPC Equip 23656', 0, 34744, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23673, 2, 7, -1, 'NPC Equip 23673', 3, 36442, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23674, 13, 0, -1, 'NPC Equip 23674', -1, 9154, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23689, 9, 7, -1, 'NPC Equip 23689', -1, 8117, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23690, 9, 5, -1, 'NPC Equip 23690', -1, 12547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23696, 0, 1, -1, 'NPC Equip 23696', 0, 15788, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23698, 0, 1, -1, 'NPC Equip 23698', 0, 24211, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23699, 0, 8, -1, 'NPC Equip 23699', 0, 36460, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23700, 0, 8, -1, 'NPC Equip 23700', 0, 31256, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23701, 0, 8, -1, 'NPC Equip 23701', 0, 31257, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23704, 0, 5, -1, 'NPC Equip 23704', 3, 18080, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23708, 2, 4, -1, 'NPC Equip 23708', 2, 36467, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23710, 4, 0, -1, 'NPC Equip 23710', 7, 36469, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23715, 0, 0, -1, 'NPC Equip 23715', -1, 18114, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23718, 0, 0, -1, 'NPC Equip 23718', -1, 2638, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23719, 0, 0, -1, 'NPC Equip 23719', -1, 16836, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23721, 0, 0, -1, 'NPC Equip 23721', -1, 36475, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23722, 0, 0, -1, 'NPC Equip 23722', -1, 20894, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23724, 4, 0, -1, 'NPC Equip 23724', 7, 36135, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23725, 0, 8, -1, 'NPC Equip 23725', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23727, 0, 8, -1, 'NPC Equip 23727', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23728, 0, 8, -1, 'NPC Equip 23728', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23740, 12, 0, -1, 'NPC Equip 23740', -1, 36488, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23741, 2, 7, -1, 'NPC Equip 23741', 1, 35247, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23743, 2, 7, -1, 'NPC Equip 23743', 1, 35247, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23794, 0, 0, -1, 'NPC Equip 23794', 3, 24211, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23795, 0, 0, -1, 'NPC Equip 23795', 3, 17896, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23796, 0, 0, -1, 'NPC Equip 23796', 3, 24156, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23812, 9, 3, -1, 'NPC Equip 23812', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23813, 9, 3, -1, 'NPC Equip 23813', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23842, 4, 0, -1, 'NPC Equip 23842', 0, 4361, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23853, 12, 0, -1, 'NPC Equip 23853', -1, 7649, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23856, 2, 5, -1, 'NPC Equip 23856', 2, 36599, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23861, 12, 0, -1, 'NPC Equip 23861', -1, 17329, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23872, 0, 0, -1, 'NPC Equip 23872', 8, 2591, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23889, 2, 2, -1, 'NPC Equip 23889', 2, 36600, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23895, 15, 0, -1, 'NPC Equip 23895', -1, 36601, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23904, 12, 0, -1, 'NPC Equip 23904', 0, 36629, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23905, 2, 15, -1, 'NPC Equip 23905', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23906, 2, 4, -1, 'NPC Equip 23906', 2, 36631, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23907, 4, 6, -1, 'NPC Equip 23907', 1, 36637, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23908, 2, 15, -1, 'NPC Equip 23908', 1, 36638, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23911, 2, 15, -1, 'NPC Equip 23911', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23912, 2, 15, -1, 'NPC Equip 23912', 1, 26494, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23913, 2, 7, -1, 'NPC Equip 23913', 1, 26494, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23914, 2, 7, -1, 'NPC Equip 23914', 1, 26494, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23915, 2, 15, -1, 'NPC Equip 23915', 1, 26494, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23916, 2, 15, -1, 'NPC Equip 23916', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23917, 2, 15, -1, 'NPC Equip 23917', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23918, 2, 7, -1, 'NPC Equip 23918', 1, 26494, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23935, 12, 0, -1, 'NPC Equip 23935', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23936, 12, 0, -1, 'NPC Equip 23936', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23940, 15, 0, -1, 'NPC Equip 23940', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23941, 15, 0, -1, 'NPC Equip 23941', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23942, 15, 0, -1, 'NPC Equip 23942', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23943, 15, 0, -1, 'NPC Equip 23943', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23950, 15, 0, -1, 'NPC Equip 23950', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23951, 15, 0, -1, 'NPC Equip 23951', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23953, 15, 0, -1, 'NPC Equip 23953', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23954, 15, 0, -1, 'NPC Equip 23954', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23955, 15, 0, -1, 'NPC Equip 23955', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23956, 13, 0, -1, 'NPC Equip 23956', -1, 36683, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23957, 15, 0, -1, 'NPC Equip 23957', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23958, 15, 0, -1, 'NPC Equip 23958', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23959, 15, 0, -1, 'NPC Equip 23959', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23960, 15, 0, -1, 'NPC Equip 23960', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23961, 15, 0, -1, 'NPC Equip 23961', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23962, 15, 0, -1, 'NPC Equip 23962', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23963, 15, 0, -1, 'NPC Equip 23963', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23964, 15, 0, -1, 'NPC Equip 23964', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23966, 15, 0, -1, 'NPC Equip 23966', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23967, 15, 0, -1, 'NPC Equip 23967', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23968, 15, 0, -1, 'NPC Equip 23968', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23969, 15, 0, -1, 'NPC Equip 23969', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23970, 15, 0, -1, 'NPC Equip 23970', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23971, 15, 0, -1, 'NPC Equip 23971', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23972, 15, 0, -1, 'NPC Equip 23972', -1, 36682, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23973, 15, 0, -1, 'NPC Equip 23973', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23974, 15, 0, -1, 'NPC Equip 23974', -1, 35014, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23975, 15, 0, -1, 'NPC Equip 23975', 8, 6002, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23982, 0, 0, -1, 'NPC Equip 23982', -1, 36688, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23983, 12, 0, -1, 'NPC Equip 23983', -1, 15741, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23990, 12, 0, -1, 'NPC Equip 23990', -1, 3331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23991, 15, 0, -1, 'NPC Equip 23991', -1, 6666, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23992, 15, 0, -1, 'NPC Equip 23992', 8, 7086, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23993, 15, 0, -1, 'NPC Equip 23993', 8, 7048, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23996, 2, 0, -1, 'NPC Equip 23996', 1, 40065, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (23998, 2, 10, -1, 'NPC Equip 23998', 2, 36698, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24005, 12, 0, -1, 'NPC Equip 24005', -1, 8628, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24010, 13, 0, -1, 'NPC Equip 24010', -1, 22477, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24011, 2, 5, -1, 'NPC Equip 24011', 2, 36706, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24012, 2, 5, -1, 'NPC Equip 24012', 2, 36707, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24013, 2, 5, -1, 'NPC Equip 24013', 2, 36708, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24014, 2, 5, -1, 'NPC Equip 24014', 2, 36709, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24015, 2, 5, -1, 'NPC Equip 24015', 2, 36710, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24016, 2, 5, -1, 'NPC Equip 24016', 2, 36711, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24017, 2, 5, -1, 'NPC Equip 24017', 2, 36712, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24018, 2, 5, -1, 'NPC Equip 24018', 2, 36713, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24019, 2, 5, -1, 'NPC Equip 24019', 2, 36714, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24034, 2, 7, -1, 'NPC Equip 24034', 1, 36725, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24038, 4, 6, -1, 'NPC Equip 24038', 1, 36726, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24068, 15, 0, -1, 'NPC Equip 24068', -1, 20614, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24070, 2, 15, -1, 'NPC Equip 24070', 2, 34891, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24115, 7, 11, -1, 'NPC Equip 24115', 1, 4689, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24147, 12, 0, -1, 'NPC Equip 24147', -1, 3331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24148, 12, 0, -1, 'NPC Equip 24148', -1, 3331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24149, 12, 0, -1, 'NPC Equip 24149', -1, 3331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24187, 15, 0, -1, 'NPC Equip 24187', 2, 36866, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24191, 15, 0, -1, 'NPC Equip 24191', 2, 7162, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24228, 15, 0, -1, 'NPC Equip 24228', -1, 634, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24229, 15, 0, -1, 'NPC Equip 24229', -1, 634, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24244, 2, 3, -1, 'NPC Equip 24244', 2, 36925, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24319, 2, 2, -1, 'NPC Equip 24319', 2, 37000, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24320, 2, 0, -1, 'NPC Equip 24320', 1, 37101, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24321, 2, 10, -1, 'NPC Equip 24321', 2, 37003, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24322, 4, 6, -1, 'NPC Equip 24322', 1, 33307, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24324, 2, 15, -1, 'NPC Equip 24324', 1, 37017, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24325, 2, 8, -1, 'NPC Equip 24325', 1, 37018, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24326, 2, 2, -1, 'NPC Equip 24326', 2, 37019, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24327, 2, 0, -1, 'NPC Equip 24327', 1, 37020, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24328, 4, 6, -1, 'NPC Equip 24328', 1, 33309, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24329, 4, 0, -1, 'NPC Equip 24329', 0, 47456, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24331, 4, 6, -1, 'NPC Equip 24331', 1, 37030, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24332, 2, 4, -1, 'NPC Equip 24332', 2, 37031, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24333, 2, 4, -1, 'NPC Equip 24333', 2, 37034, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24358, 4, 0, -1, 'NPC Equip 24358', 3, 31664, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24369, 12, 0, -1, 'NPC Equip 24369', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24370, 12, 0, -1, 'NPC Equip 24370', -1, 23315, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24371, 12, 0, -1, 'NPC Equip 24371', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24377, 2, 15, -1, 'NPC Equip 24377', 1, 23248, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24409, 2, 0, -1, 'NPC Equip 24409', 1, 37135, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24410, 15, 0, -1, 'NPC Equip 24410', 1, 37149, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24418, 2, 15, -1, 'NPC Equip 24418', 1, 36036, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24420, 4, 0, -1, 'NPC Equip 24420', 1, 6511, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24491, 0, 8, -1, 'NPC Equip 24491', 0, 24591, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24495, 2, 8, -1, 'NPC Equip 24495', 1, 43311, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24512, 2, 1, -1, 'NPC Equip 24512', 1, 37257, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24515, 15, 0, -1, 'NPC Equip 24515', 8, 18092, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24518, 15, 0, -1, 'NPC Equip 24518', 8, 18095, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24524, 2, 1, -1, 'NPC Equip 24524', 1, 39902, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24525, 2, 1, -1, 'NPC Equip 24525', 1, 31721, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24527, 4, 4, -1, 'NPC Equip 24527', 6, 29858, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24528, 4, 1, -1, 'NPC Equip 24528', 7, 27088, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24529, 4, 4, -1, 'NPC Equip 24529', 6, 29860, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24530, 2, 3, -1, 'NPC Equip 24530', 1, 31210, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24531, 4, 4, -1, 'NPC Equip 24531', 6, 29865, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24532, 4, 4, -1, 'NPC Equip 24532', 6, 25226, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24533, 4, 0, -1, 'NPC Equip 24533', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24534, 4, 4, -1, 'NPC Equip 24534', 6, 29867, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24535, 4, 0, -1, 'NPC Equip 24535', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24536, 4, 4, -1, 'NPC Equip 24536', 6, 29863, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24537, 4, 4, -1, 'NPC Equip 24537', 6, 29864, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24541, 0, 8, -1, 'NPC Equip 24541', -1, 3427, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24548, 4, 4, -1, 'NPC Equip 24548', 6, 37303, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24562, 4, 1, -1, 'NPC Equip 24562', 7, 29798, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24563, 4, 1, -1, 'NPC Equip 24563', 7, 31263, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24564, 4, 1, -1, 'NPC Equip 24564', 7, 29792, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24565, 4, 1, -1, 'NPC Equip 24565', 7, 29799, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24566, 4, 1, -1, 'NPC Equip 24566', 7, 29800, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24568, 4, 0, -1, 'NPC Equip 24568', 5, 24022, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24569, 2, 19, -1, 'NPC Equip 24569', 2, 28828, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24570, 2, 10, -1, 'NPC Equip 24570', 2, 30870, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24571, 4, 0, -1, 'NPC Equip 24571', 5, 23717, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (24572, 4, 1, -1, 'NPC Equip 24572', 7, 29795, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25493, 2, 1, -1, 'NPC Equip 25493', 1, 19311, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25497, 15, 0, -1, 'NPC Equip 25497', 1, 32693, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25520, 2, 6, -1, 'NPC Equip 25520', 1, 37469, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25546, 4, 4, -1, 'NPC Equip 25546', 6, 37481, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25547, 4, 2, -1, 'NPC Equip 25547', 8, 37482, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25551, 4, 3, -1, 'NPC Equip 25551', 5, 37483, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25571, 4, 2, -1, 'NPC Equip 25571', 8, 17269, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25572, 4, 3, -1, 'NPC Equip 25572', 5, 37501, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25587, 2, 14, -1, 'NPC Equip 25587', 2, 37524, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25588, 2, 5, -1, 'NPC Equip 25588', 2, 37525, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25625, 2, 10, -1, 'NPC Equip 25625', 2, 37550, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25626, 4, 4, -1, 'NPC Equip 25626', 6, 30704, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25646, 2, 4, -1, 'NPC Equip 25646', 2, 7468, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25663, 2, 4, -1, 'NPC Equip 25663', 2, 37589, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25664, 15, 0, -1, 'NPC Equip 25664', -1, 37590, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25665, 15, 0, -1, 'NPC Equip 25665', 1, 23723, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25688, 2, 8, -1, 'NPC Equip 25688', 1, 37628, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25698, 2, 10, -1, 'NPC Equip 25698', 2, 37660, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25704, 15, 0, -1, 'NPC Equip 25704', -1, 37672, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25709, 7, 0, -1, 'NPC Equip 25709', 8, 16474, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25752, 12, 0, -1, 'NPC Equip 25752', -1, 7744, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25753, 12, 0, -1, 'NPC Equip 25753', -1, 7744, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25758, 2, 6, -1, 'NPC Equip 25758', 1, 37774, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25798, 4, 0, -1, 'NPC Equip 25798', 4, 35442, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25799, 2, 0, -1, 'NPC Equip 25799', -1, 36257, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25800, 4, 1, -1, 'NPC Equip 25800', 7, 29797, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25801, 4, 0, -1, 'NPC Equip 25801', 4, 35445, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25816, 2, 7, -1, 'NPC Equip 25816', 1, 37828, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25818, 4, 6, -1, 'NPC Equip 25818', 1, 37829, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25839, 2, 10, -1, 'NPC Equip 25839', 2, 1768, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25851, 12, 0, -1, 'NPC Equip 25851', -1, 37880, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25859, 2, 0, -1, 'NPC Equip 25859', 1, 7040, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25860, 2, 7, -1, 'NPC Equip 25860', 1, 37078, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25871, 2, 16, -1, 'NPC Equip 25871', -1, 37935, 25, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25879, 2, 7, -1, 'NPC Equip 25879', 1, 37989, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25885, 2, 10, -1, 'NPC Equip 25885', 2, 20378, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25888, 9, 10, -1, 'NPC Equip 25888', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (25892, 12, 0, -1, 'NPC Equip 25892', -1, 7987, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26003, 2, 8, -1, 'NPC Equip 26003', 1, 38142, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26046, 0, 0, -1, 'NPC Equip 26046', -1, 19764, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26047, 0, 0, -1, 'NPC Equip 26047', -1, 37331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26056, 4, 1, -1, 'NPC Equip 26056', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26057, 4, 1, -1, 'NPC Equip 26057', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26058, 4, 1, -1, 'NPC Equip 26058', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26059, 4, 1, -1, 'NPC Equip 26059', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26060, 4, 1, -1, 'NPC Equip 26060', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26061, 4, 1, -1, 'NPC Equip 26061', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26062, 4, 1, -1, 'NPC Equip 26062', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26063, 4, 1, -1, 'NPC Equip 26063', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26064, 4, 1, -1, 'NPC Equip 26064', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26065, 4, 1, -1, 'NPC Equip 26065', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26066, 4, 1, -1, 'NPC Equip 26066', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26067, 4, 1, -1, 'NPC Equip 26067', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26068, 4, 1, -1, 'NPC Equip 26068', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26069, 4, 1, -1, 'NPC Equip 26069', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26070, 4, 1, -1, 'NPC Equip 26070', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26071, 4, 1, -1, 'NPC Equip 26071', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26072, 4, 1, -1, 'NPC Equip 26072', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26073, 4, 1, -1, 'NPC Equip 26073', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26074, 4, 1, -1, 'NPC Equip 26074', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26075, 4, 1, -1, 'NPC Equip 26075', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26076, 4, 1, -1, 'NPC Equip 26076', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26077, 4, 1, -1, 'NPC Equip 26077', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26078, 4, 1, -1, 'NPC Equip 26078', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26079, 4, 1, -1, 'NPC Equip 26079', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26080, 4, 1, -1, 'NPC Equip 26080', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26081, 4, 1, -1, 'NPC Equip 26081', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26082, 4, 1, -1, 'NPC Equip 26082', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26083, 4, 1, -1, 'NPC Equip 26083', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26084, 4, 1, -1, 'NPC Equip 26084', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26085, 4, 1, -1, 'NPC Equip 26085', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26086, 4, 1, -1, 'NPC Equip 26086', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26087, 4, 1, -1, 'NPC Equip 26087', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26088, 4, 1, -1, 'NPC Equip 26088', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26089, 4, 1, -1, 'NPC Equip 26089', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26090, 4, 1, -1, 'NPC Equip 26090', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26091, 4, 1, -1, 'NPC Equip 26091', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26092, 4, 1, -1, 'NPC Equip 26092', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26093, 4, 1, -1, 'NPC Equip 26093', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26094, 4, 1, -1, 'NPC Equip 26094', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26095, 4, 1, -1, 'NPC Equip 26095', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26096, 4, 1, -1, 'NPC Equip 26096', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26097, 4, 1, -1, 'NPC Equip 26097', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26098, 4, 1, -1, 'NPC Equip 26098', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26099, 4, 1, -1, 'NPC Equip 26099', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26100, 4, 1, -1, 'NPC Equip 26100', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26101, 4, 1, -1, 'NPC Equip 26101', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26102, 4, 1, -1, 'NPC Equip 26102', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26103, 4, 1, -1, 'NPC Equip 26103', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26104, 4, 1, -1, 'NPC Equip 26104', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26105, 4, 1, -1, 'NPC Equip 26105', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26106, 4, 1, -1, 'NPC Equip 26106', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26107, 4, 1, -1, 'NPC Equip 26107', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26108, 4, 1, -1, 'NPC Equip 26108', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26109, 4, 1, -1, 'NPC Equip 26109', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26110, 4, 1, -1, 'NPC Equip 26110', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26111, 4, 1, -1, 'NPC Equip 26111', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26112, 4, 1, -1, 'NPC Equip 26112', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26113, 4, 1, -1, 'NPC Equip 26113', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26114, 4, 1, -1, 'NPC Equip 26114', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26115, 4, 1, -1, 'NPC Equip 26115', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26116, 4, 1, -1, 'NPC Equip 26116', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26117, 4, 1, -1, 'NPC Equip 26117', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26118, 4, 1, -1, 'NPC Equip 26118', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26119, 4, 1, -1, 'NPC Equip 26119', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26120, 4, 1, -1, 'NPC Equip 26120', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26121, 4, 1, -1, 'NPC Equip 26121', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26122, 4, 1, -1, 'NPC Equip 26122', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26123, 4, 1, -1, 'NPC Equip 26123', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26124, 4, 1, -1, 'NPC Equip 26124', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26125, 4, 1, -1, 'NPC Equip 26125', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26126, 4, 1, -1, 'NPC Equip 26126', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26127, 4, 1, -1, 'NPC Equip 26127', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26136, 4, 1, -1, 'NPC Equip 26136', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26137, 4, 1, -1, 'NPC Equip 26137', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26138, 4, 1, -1, 'NPC Equip 26138', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26139, 4, 1, -1, 'NPC Equip 26139', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26140, 4, 1, -1, 'NPC Equip 26140', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26141, 4, 1, -1, 'NPC Equip 26141', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26142, 4, 1, -1, 'NPC Equip 26142', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26143, 4, 1, -1, 'NPC Equip 26143', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26144, 4, 1, -1, 'NPC Equip 26144', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26145, 4, 1, -1, 'NPC Equip 26145', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26146, 4, 1, -1, 'NPC Equip 26146', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26147, 4, 1, -1, 'NPC Equip 26147', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26148, 4, 1, -1, 'NPC Equip 26148', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26149, 4, 1, -1, 'NPC Equip 26149', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26150, 4, 1, -1, 'NPC Equip 26150', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26151, 4, 1, -1, 'NPC Equip 26151', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26152, 4, 1, -1, 'NPC Equip 26152', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26153, 4, 1, -1, 'NPC Equip 26153', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26154, 4, 1, -1, 'NPC Equip 26154', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26155, 4, 1, -1, 'NPC Equip 26155', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26156, 4, 1, -1, 'NPC Equip 26156', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26157, 4, 1, -1, 'NPC Equip 26157', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26158, 4, 1, -1, 'NPC Equip 26158', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26159, 4, 1, -1, 'NPC Equip 26159', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26160, 4, 1, -1, 'NPC Equip 26160', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26161, 4, 1, -1, 'NPC Equip 26161', 7, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26162, 4, 1, -1, 'NPC Equip 26162', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26163, 4, 1, -1, 'NPC Equip 26163', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26164, 4, 1, -1, 'NPC Equip 26164', 7, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26165, 4, 1, -1, 'NPC Equip 26165', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26166, 4, 1, -1, 'NPC Equip 26166', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26167, 4, 1, -1, 'NPC Equip 26167', 7, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26168, 4, 2, -1, 'NPC Equip 26168', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26169, 4, 2, -1, 'NPC Equip 26169', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26170, 4, 2, -1, 'NPC Equip 26170', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26171, 4, 2, -1, 'NPC Equip 26171', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26172, 4, 2, -1, 'NPC Equip 26172', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26176, 4, 2, -1, 'NPC Equip 26176', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26177, 4, 2, -1, 'NPC Equip 26177', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26178, 4, 2, -1, 'NPC Equip 26178', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26179, 4, 2, -1, 'NPC Equip 26179', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26181, 4, 2, -1, 'NPC Equip 26181', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26182, 4, 2, -1, 'NPC Equip 26182', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26183, 4, 2, -1, 'NPC Equip 26183', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26184, 4, 2, -1, 'NPC Equip 26184', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26185, 4, 2, -1, 'NPC Equip 26185', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26186, 4, 2, -1, 'NPC Equip 26186', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26187, 4, 2, -1, 'NPC Equip 26187', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26188, 4, 2, -1, 'NPC Equip 26188', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26189, 4, 2, -1, 'NPC Equip 26189', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26190, 4, 2, -1, 'NPC Equip 26190', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26191, 4, 2, -1, 'NPC Equip 26191', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26192, 4, 2, -1, 'NPC Equip 26192', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26193, 4, 2, -1, 'NPC Equip 26193', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26194, 4, 2, -1, 'NPC Equip 26194', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26195, 4, 2, -1, 'NPC Equip 26195', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26196, 4, 2, -1, 'NPC Equip 26196', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26197, 4, 2, -1, 'NPC Equip 26197', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26198, 4, 2, -1, 'NPC Equip 26198', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26199, 4, 2, -1, 'NPC Equip 26199', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26200, 4, 2, -1, 'NPC Equip 26200', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26201, 4, 2, -1, 'NPC Equip 26201', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26202, 4, 2, -1, 'NPC Equip 26202', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26203, 4, 2, -1, 'NPC Equip 26203', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26204, 4, 2, -1, 'NPC Equip 26204', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26205, 4, 2, -1, 'NPC Equip 26205', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26206, 4, 2, -1, 'NPC Equip 26206', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26207, 4, 2, -1, 'NPC Equip 26207', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26208, 4, 2, -1, 'NPC Equip 26208', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26209, 4, 2, -1, 'NPC Equip 26209', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26210, 4, 2, -1, 'NPC Equip 26210', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26211, 4, 2, -1, 'NPC Equip 26211', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26212, 4, 2, -1, 'NPC Equip 26212', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26213, 4, 2, -1, 'NPC Equip 26213', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26214, 4, 2, -1, 'NPC Equip 26214', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26215, 4, 2, -1, 'NPC Equip 26215', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26216, 4, 2, -1, 'NPC Equip 26216', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26217, 4, 2, -1, 'NPC Equip 26217', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26218, 4, 2, -1, 'NPC Equip 26218', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26219, 4, 2, -1, 'NPC Equip 26219', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26220, 4, 2, -1, 'NPC Equip 26220', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26221, 4, 2, -1, 'NPC Equip 26221', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26222, 4, 2, -1, 'NPC Equip 26222', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26223, 4, 2, -1, 'NPC Equip 26223', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26224, 4, 2, -1, 'NPC Equip 26224', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26225, 4, 2, -1, 'NPC Equip 26225', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26226, 4, 2, -1, 'NPC Equip 26226', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26227, 4, 2, -1, 'NPC Equip 26227', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26228, 4, 2, -1, 'NPC Equip 26228', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26229, 4, 2, -1, 'NPC Equip 26229', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26230, 4, 2, -1, 'NPC Equip 26230', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26231, 4, 2, -1, 'NPC Equip 26231', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26232, 4, 2, -1, 'NPC Equip 26232', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26233, 4, 2, -1, 'NPC Equip 26233', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26234, 4, 2, -1, 'NPC Equip 26234', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26236, 4, 2, -1, 'NPC Equip 26236', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26237, 4, 2, -1, 'NPC Equip 26237', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26238, 4, 2, -1, 'NPC Equip 26238', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26239, 4, 2, -1, 'NPC Equip 26239', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26240, 4, 2, -1, 'NPC Equip 26240', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26241, 4, 2, -1, 'NPC Equip 26241', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26242, 4, 2, -1, 'NPC Equip 26242', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26243, 4, 2, -1, 'NPC Equip 26243', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26244, 4, 2, -1, 'NPC Equip 26244', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26245, 4, 2, -1, 'NPC Equip 26245', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26246, 4, 2, -1, 'NPC Equip 26246', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26247, 4, 2, -1, 'NPC Equip 26247', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26248, 4, 2, -1, 'NPC Equip 26248', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26249, 4, 2, -1, 'NPC Equip 26249', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26250, 4, 2, -1, 'NPC Equip 26250', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26251, 4, 2, -1, 'NPC Equip 26251', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26252, 4, 2, -1, 'NPC Equip 26252', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26253, 4, 2, -1, 'NPC Equip 26253', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26254, 4, 2, -1, 'NPC Equip 26254', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26255, 4, 2, -1, 'NPC Equip 26255', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26256, 4, 2, -1, 'NPC Equip 26256', 8, 43783, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26257, 4, 2, -1, 'NPC Equip 26257', 8, 43782, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26258, 4, 2, -1, 'NPC Equip 26258', 8, 43778, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26259, 4, 2, -1, 'NPC Equip 26259', 8, 43781, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26260, 4, 2, -1, 'NPC Equip 26260', 8, 43777, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26261, 4, 2, -1, 'NPC Equip 26261', 8, 43779, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26262, 4, 2, -1, 'NPC Equip 26262', 8, 43784, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26263, 4, 2, -1, 'NPC Equip 26263', 8, 43780, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26264, 4, 2, -1, 'NPC Equip 26264', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26265, 4, 2, -1, 'NPC Equip 26265', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26266, 4, 2, -1, 'NPC Equip 26266', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26267, 4, 2, -1, 'NPC Equip 26267', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26268, 4, 2, -1, 'NPC Equip 26268', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26269, 4, 2, -1, 'NPC Equip 26269', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26270, 4, 2, -1, 'NPC Equip 26270', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26271, 4, 2, -1, 'NPC Equip 26271', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26272, 4, 2, -1, 'NPC Equip 26272', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26273, 4, 2, -1, 'NPC Equip 26273', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26274, 4, 2, -1, 'NPC Equip 26274', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26275, 4, 2, -1, 'NPC Equip 26275', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26276, 4, 2, -1, 'NPC Equip 26276', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26277, 4, 2, -1, 'NPC Equip 26277', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26278, 4, 2, -1, 'NPC Equip 26278', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26279, 4, 2, -1, 'NPC Equip 26279', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26280, 4, 3, -1, 'NPC Equip 26280', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26281, 4, 3, -1, 'NPC Equip 26281', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26282, 4, 3, -1, 'NPC Equip 26282', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26283, 4, 3, -1, 'NPC Equip 26283', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26284, 4, 3, -1, 'NPC Equip 26284', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26285, 4, 3, -1, 'NPC Equip 26285', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26286, 4, 3, -1, 'NPC Equip 26286', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26287, 4, 3, -1, 'NPC Equip 26287', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26288, 4, 3, -1, 'NPC Equip 26288', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26289, 4, 3, -1, 'NPC Equip 26289', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26290, 4, 3, -1, 'NPC Equip 26290', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26291, 4, 3, -1, 'NPC Equip 26291', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26292, 4, 3, -1, 'NPC Equip 26292', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26293, 4, 3, -1, 'NPC Equip 26293', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26294, 4, 2, -1, 'NPC Equip 26294', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26295, 4, 3, -1, 'NPC Equip 26295', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26296, 4, 3, -1, 'NPC Equip 26296', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26297, 4, 3, -1, 'NPC Equip 26297', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26298, 4, 3, -1, 'NPC Equip 26298', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26299, 4, 3, -1, 'NPC Equip 26299', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26300, 4, 3, -1, 'NPC Equip 26300', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26301, 4, 3, -1, 'NPC Equip 26301', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26302, 4, 3, -1, 'NPC Equip 26302', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26303, 4, 3, -1, 'NPC Equip 26303', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26304, 4, 3, -1, 'NPC Equip 26304', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26305, 4, 3, -1, 'NPC Equip 26305', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26306, 4, 3, -1, 'NPC Equip 26306', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26307, 4, 3, -1, 'NPC Equip 26307', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26308, 4, 3, -1, 'NPC Equip 26308', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26309, 4, 3, -1, 'NPC Equip 26309', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26310, 4, 3, -1, 'NPC Equip 26310', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26311, 4, 3, -1, 'NPC Equip 26311', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26312, 4, 3, -1, 'NPC Equip 26312', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26313, 4, 3, -1, 'NPC Equip 26313', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26314, 4, 3, -1, 'NPC Equip 26314', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26315, 4, 3, -1, 'NPC Equip 26315', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26316, 4, 3, -1, 'NPC Equip 26316', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26317, 4, 3, -1, 'NPC Equip 26317', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26318, 4, 3, -1, 'NPC Equip 26318', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26319, 4, 3, -1, 'NPC Equip 26319', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26320, 4, 3, -1, 'NPC Equip 26320', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26321, 4, 3, -1, 'NPC Equip 26321', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26322, 4, 3, -1, 'NPC Equip 26322', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26323, 4, 3, -1, 'NPC Equip 26323', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26325, 4, 3, -1, 'NPC Equip 26325', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26326, 4, 3, -1, 'NPC Equip 26326', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26327, 4, 3, -1, 'NPC Equip 26327', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26328, 4, 3, -1, 'NPC Equip 26328', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26329, 4, 3, -1, 'NPC Equip 26329', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26330, 4, 3, -1, 'NPC Equip 26330', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26331, 4, 3, -1, 'NPC Equip 26331', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26332, 4, 3, -1, 'NPC Equip 26332', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26333, 4, 3, -1, 'NPC Equip 26333', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26334, 4, 3, -1, 'NPC Equip 26334', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26335, 4, 3, -1, 'NPC Equip 26335', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26336, 4, 3, -1, 'NPC Equip 26336', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26337, 4, 3, -1, 'NPC Equip 26337', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26338, 4, 3, -1, 'NPC Equip 26338', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26339, 4, 3, -1, 'NPC Equip 26339', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26340, 4, 3, -1, 'NPC Equip 26340', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26341, 4, 3, -1, 'NPC Equip 26341', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26342, 4, 3, -1, 'NPC Equip 26342', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26343, 4, 3, -1, 'NPC Equip 26343', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26344, 4, 3, -1, 'NPC Equip 26344', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26345, 4, 3, -1, 'NPC Equip 26345', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26346, 4, 3, -1, 'NPC Equip 26346', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26347, 4, 3, -1, 'NPC Equip 26347', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26348, 4, 3, -1, 'NPC Equip 26348', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26349, 4, 3, -1, 'NPC Equip 26349', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26350, 4, 3, -1, 'NPC Equip 26350', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26351, 4, 3, -1, 'NPC Equip 26351', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26352, 4, 3, -1, 'NPC Equip 26352', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26353, 4, 3, -1, 'NPC Equip 26353', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26354, 4, 3, -1, 'NPC Equip 26354', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26355, 4, 3, -1, 'NPC Equip 26355', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26356, 4, 3, -1, 'NPC Equip 26356', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26357, 4, 3, -1, 'NPC Equip 26357', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26358, 4, 3, -1, 'NPC Equip 26358', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26359, 4, 3, -1, 'NPC Equip 26359', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26360, 4, 3, -1, 'NPC Equip 26360', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26361, 4, 3, -1, 'NPC Equip 26361', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26362, 4, 3, -1, 'NPC Equip 26362', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26363, 4, 3, -1, 'NPC Equip 26363', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26364, 4, 3, -1, 'NPC Equip 26364', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26365, 4, 3, -1, 'NPC Equip 26365', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26366, 4, 3, -1, 'NPC Equip 26366', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26367, 4, 3, -1, 'NPC Equip 26367', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26369, 4, 3, -1, 'NPC Equip 26369', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26370, 4, 3, -1, 'NPC Equip 26370', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26371, 4, 3, -1, 'NPC Equip 26371', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26373, 4, 3, -1, 'NPC Equip 26373', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26374, 4, 3, -1, 'NPC Equip 26374', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26375, 4, 3, -1, 'NPC Equip 26375', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26376, 4, 3, -1, 'NPC Equip 26376', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26377, 4, 3, -1, 'NPC Equip 26377', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26378, 4, 3, -1, 'NPC Equip 26378', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26379, 4, 3, -1, 'NPC Equip 26379', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26380, 4, 3, -1, 'NPC Equip 26380', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26381, 4, 3, -1, 'NPC Equip 26381', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26382, 4, 3, -1, 'NPC Equip 26382', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26383, 4, 3, -1, 'NPC Equip 26383', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26384, 4, 3, -1, 'NPC Equip 26384', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26385, 4, 3, -1, 'NPC Equip 26385', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26386, 4, 3, -1, 'NPC Equip 26386', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26387, 4, 3, -1, 'NPC Equip 26387', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26388, 4, 3, -1, 'NPC Equip 26388', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26389, 4, 3, -1, 'NPC Equip 26389', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26390, 4, 3, -1, 'NPC Equip 26390', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26391, 4, 3, -1, 'NPC Equip 26391', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26392, 4, 4, -1, 'NPC Equip 26392', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26393, 4, 4, -1, 'NPC Equip 26393', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26394, 4, 4, -1, 'NPC Equip 26394', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26395, 4, 4, -1, 'NPC Equip 26395', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26396, 4, 4, -1, 'NPC Equip 26396', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26397, 4, 4, -1, 'NPC Equip 26397', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26398, 4, 4, -1, 'NPC Equip 26398', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26399, 4, 4, -1, 'NPC Equip 26399', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26400, 4, 4, -1, 'NPC Equip 26400', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26401, 4, 4, -1, 'NPC Equip 26401', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26402, 4, 4, -1, 'NPC Equip 26402', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26403, 4, 4, -1, 'NPC Equip 26403', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26404, 4, 4, -1, 'NPC Equip 26404', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26405, 4, 4, -1, 'NPC Equip 26405', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26406, 4, 4, -1, 'NPC Equip 26406', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26407, 4, 4, -1, 'NPC Equip 26407', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26408, 4, 4, -1, 'NPC Equip 26408', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26409, 4, 4, -1, 'NPC Equip 26409', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26410, 4, 4, -1, 'NPC Equip 26410', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26411, 4, 4, -1, 'NPC Equip 26411', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26412, 4, 4, -1, 'NPC Equip 26412', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26413, 4, 4, -1, 'NPC Equip 26413', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26414, 4, 4, -1, 'NPC Equip 26414', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26415, 4, 4, -1, 'NPC Equip 26415', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26416, 4, 4, -1, 'NPC Equip 26416', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26417, 4, 4, -1, 'NPC Equip 26417', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26418, 4, 4, -1, 'NPC Equip 26418', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26419, 4, 4, -1, 'NPC Equip 26419', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26420, 4, 4, -1, 'NPC Equip 26420', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26421, 4, 4, -1, 'NPC Equip 26421', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26422, 4, 4, -1, 'NPC Equip 26422', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26423, 4, 4, -1, 'NPC Equip 26423', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26424, 4, 4, -1, 'NPC Equip 26424', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26425, 4, 4, -1, 'NPC Equip 26425', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26426, 4, 4, -1, 'NPC Equip 26426', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26427, 4, 4, -1, 'NPC Equip 26427', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26428, 4, 4, -1, 'NPC Equip 26428', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26429, 4, 4, -1, 'NPC Equip 26429', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26430, 4, 4, -1, 'NPC Equip 26430', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26431, 4, 4, -1, 'NPC Equip 26431', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26432, 4, 4, -1, 'NPC Equip 26432', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26433, 4, 4, -1, 'NPC Equip 26433', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26434, 4, 4, -1, 'NPC Equip 26434', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26435, 4, 4, -1, 'NPC Equip 26435', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26436, 4, 4, -1, 'NPC Equip 26436', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26437, 4, 4, -1, 'NPC Equip 26437', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26438, 4, 4, -1, 'NPC Equip 26438', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26439, 4, 4, -1, 'NPC Equip 26439', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26440, 4, 4, -1, 'NPC Equip 26440', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26441, 4, 4, -1, 'NPC Equip 26441', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26442, 4, 4, -1, 'NPC Equip 26442', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26443, 4, 4, -1, 'NPC Equip 26443', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26444, 4, 4, -1, 'NPC Equip 26444', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26445, 4, 4, -1, 'NPC Equip 26445', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26446, 4, 4, -1, 'NPC Equip 26446', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26447, 4, 4, -1, 'NPC Equip 26447', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26448, 4, 4, -1, 'NPC Equip 26448', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26449, 4, 4, -1, 'NPC Equip 26449', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26450, 4, 4, -1, 'NPC Equip 26450', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26451, 4, 4, -1, 'NPC Equip 26451', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26452, 4, 4, -1, 'NPC Equip 26452', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26453, 4, 4, -1, 'NPC Equip 26453', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26454, 4, 4, -1, 'NPC Equip 26454', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26455, 4, 4, -1, 'NPC Equip 26455', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26456, 4, 4, -1, 'NPC Equip 26456', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26457, 4, 4, -1, 'NPC Equip 26457', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26458, 4, 4, -1, 'NPC Equip 26458', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26459, 4, 4, -1, 'NPC Equip 26459', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26460, 4, 4, -1, 'NPC Equip 26460', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26461, 4, 4, -1, 'NPC Equip 26461', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26462, 4, 4, -1, 'NPC Equip 26462', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26463, 4, 4, -1, 'NPC Equip 26463', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26466, 4, 4, -1, 'NPC Equip 26466', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26467, 4, 4, -1, 'NPC Equip 26467', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26468, 4, 4, -1, 'NPC Equip 26468', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26469, 4, 4, -1, 'NPC Equip 26469', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26470, 4, 4, -1, 'NPC Equip 26470', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26471, 4, 4, -1, 'NPC Equip 26471', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26472, 4, 4, -1, 'NPC Equip 26472', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26473, 4, 4, -1, 'NPC Equip 26473', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26474, 4, 4, -1, 'NPC Equip 26474', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26475, 4, 4, -1, 'NPC Equip 26475', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26476, 4, 4, -1, 'NPC Equip 26476', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26477, 4, 4, -1, 'NPC Equip 26477', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26478, 4, 4, -1, 'NPC Equip 26478', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26479, 4, 4, -1, 'NPC Equip 26479', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26480, 4, 4, -1, 'NPC Equip 26480', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26481, 4, 4, -1, 'NPC Equip 26481', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26482, 4, 4, -1, 'NPC Equip 26482', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26483, 4, 4, -1, 'NPC Equip 26483', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26484, 4, 4, -1, 'NPC Equip 26484', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26485, 4, 4, -1, 'NPC Equip 26485', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26486, 4, 4, -1, 'NPC Equip 26486', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26487, 4, 4, -1, 'NPC Equip 26487', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26488, 4, 4, -1, 'NPC Equip 26488', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26489, 4, 4, -1, 'NPC Equip 26489', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26490, 4, 4, -1, 'NPC Equip 26490', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26491, 4, 4, -1, 'NPC Equip 26491', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26492, 4, 4, -1, 'NPC Equip 26492', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26493, 4, 4, -1, 'NPC Equip 26493', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26494, 4, 4, -1, 'NPC Equip 26494', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26495, 4, 4, -1, 'NPC Equip 26495', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26496, 4, 4, -1, 'NPC Equip 26496', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26497, 4, 4, -1, 'NPC Equip 26497', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26498, 4, 4, -1, 'NPC Equip 26498', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26499, 4, 4, -1, 'NPC Equip 26499', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26500, 4, 4, -1, 'NPC Equip 26500', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26501, 4, 4, -1, 'NPC Equip 26501', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26502, 4, 4, -1, 'NPC Equip 26502', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26503, 4, 4, -1, 'NPC Equip 26503', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26504, 4, 1, -1, 'NPC Equip 26504', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26505, 4, 1, -1, 'NPC Equip 26505', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26506, 4, 1, -1, 'NPC Equip 26506', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26507, 4, 1, -1, 'NPC Equip 26507', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26508, 4, 1, -1, 'NPC Equip 26508', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26509, 4, 1, -1, 'NPC Equip 26509', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26510, 4, 1, -1, 'NPC Equip 26510', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26511, 4, 1, -1, 'NPC Equip 26511', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26512, 4, 1, -1, 'NPC Equip 26512', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26514, 4, 1, -1, 'NPC Equip 26514', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26515, 4, 1, -1, 'NPC Equip 26515', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26516, 4, 1, -1, 'NPC Equip 26516', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26517, 4, 1, -1, 'NPC Equip 26517', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26518, 4, 0, -1, 'NPC Equip 26518', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26519, 4, 0, -1, 'NPC Equip 26519', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26520, 4, 0, -1, 'NPC Equip 26520', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26521, 4, 0, -1, 'NPC Equip 26521', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26522, 4, 0, -1, 'NPC Equip 26522', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26523, 4, 0, -1, 'NPC Equip 26523', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26524, 4, 0, -1, 'NPC Equip 26524', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26525, 4, 0, -1, 'NPC Equip 26525', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26526, 4, 0, -1, 'NPC Equip 26526', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26528, 4, 0, -1, 'NPC Equip 26528', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26529, 4, 0, -1, 'NPC Equip 26529', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26530, 4, 0, -1, 'NPC Equip 26530', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26531, 4, 0, -1, 'NPC Equip 26531', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26532, 4, 0, -1, 'NPC Equip 26532', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26533, 4, 0, -1, 'NPC Equip 26533', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26534, 4, 0, -1, 'NPC Equip 26534', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26535, 4, 0, -1, 'NPC Equip 26535', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26536, 4, 0, -1, 'NPC Equip 26536', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26537, 4, 0, -1, 'NPC Equip 26537', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26538, 4, 0, -1, 'NPC Equip 26538', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26539, 4, 0, -1, 'NPC Equip 26539', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26540, 4, 0, -1, 'NPC Equip 26540', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26542, 4, 0, -1, 'NPC Equip 26542', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26543, 4, 0, -1, 'NPC Equip 26543', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26544, 4, 0, -1, 'NPC Equip 26544', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26545, 4, 0, -1, 'NPC Equip 26545', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26546, 4, 6, -1, 'NPC Equip 26546', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26547, 4, 6, -1, 'NPC Equip 26547', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26549, 4, 6, -1, 'NPC Equip 26549', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26550, 4, 6, -1, 'NPC Equip 26550', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26551, 4, 6, -1, 'NPC Equip 26551', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26552, 4, 6, -1, 'NPC Equip 26552', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26553, 4, 6, -1, 'NPC Equip 26553', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26554, 4, 6, -1, 'NPC Equip 26554', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26555, 4, 6, -1, 'NPC Equip 26555', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26556, 4, 6, -1, 'NPC Equip 26556', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26557, 4, 6, -1, 'NPC Equip 26557', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26558, 4, 6, -1, 'NPC Equip 26558', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26559, 4, 6, -1, 'NPC Equip 26559', 1, 28449, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26560, 4, 0, -1, 'NPC Equip 26560', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26561, 4, 0, -1, 'NPC Equip 26561', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26562, 4, 0, -1, 'NPC Equip 26562', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26563, 4, 0, -1, 'NPC Equip 26563', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26564, 4, 0, -1, 'NPC Equip 26564', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26565, 4, 0, -1, 'NPC Equip 26565', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26566, 4, 0, -1, 'NPC Equip 26566', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26567, 4, 0, -1, 'NPC Equip 26567', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26568, 4, 0, -1, 'NPC Equip 26568', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26570, 4, 0, -1, 'NPC Equip 26570', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26571, 4, 0, -1, 'NPC Equip 26571', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26572, 4, 0, -1, 'NPC Equip 26572', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26573, 4, 0, -1, 'NPC Equip 26573', 3, 22923, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26574, 2, 15, -1, 'NPC Equip 26574', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26575, 2, 15, -1, 'NPC Equip 26575', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26576, 2, 15, -1, 'NPC Equip 26576', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26577, 2, 15, -1, 'NPC Equip 26577', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26578, 2, 15, -1, 'NPC Equip 26578', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26579, 2, 15, -1, 'NPC Equip 26579', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26580, 2, 15, -1, 'NPC Equip 26580', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26581, 2, 15, -1, 'NPC Equip 26581', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26582, 2, 15, -1, 'NPC Equip 26582', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26583, 2, 15, -1, 'NPC Equip 26583', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26584, 2, 15, -1, 'NPC Equip 26584', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26585, 2, 15, -1, 'NPC Equip 26585', 1, 43775, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26586, 2, 15, -1, 'NPC Equip 26586', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26587, 2, 15, -1, 'NPC Equip 26587', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26588, 2, 4, -1, 'NPC Equip 26588', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26589, 2, 4, -1, 'NPC Equip 26589', 2, 5203, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26590, 2, 4, -1, 'NPC Equip 26590', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26591, 2, 4, -1, 'NPC Equip 26591', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26592, 2, 4, -1, 'NPC Equip 26592', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26593, 2, 4, -1, 'NPC Equip 26593', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26594, 2, 4, -1, 'NPC Equip 26594', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26595, 2, 4, -1, 'NPC Equip 26595', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26596, 2, 4, -1, 'NPC Equip 26596', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26597, 2, 4, -1, 'NPC Equip 26597', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26598, 2, 4, -1, 'NPC Equip 26598', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26599, 2, 4, -1, 'NPC Equip 26599', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26600, 2, 4, -1, 'NPC Equip 26600', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26601, 2, 4, -1, 'NPC Equip 26601', 2, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26602, 2, 5, -1, 'NPC Equip 26602', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26603, 2, 5, -1, 'NPC Equip 26603', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26604, 2, 5, -1, 'NPC Equip 26604', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26605, 2, 5, -1, 'NPC Equip 26605', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26606, 2, 5, -1, 'NPC Equip 26606', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26607, 2, 5, -1, 'NPC Equip 26607', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26608, 2, 5, -1, 'NPC Equip 26608', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26609, 2, 5, -1, 'NPC Equip 26609', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26610, 2, 5, -1, 'NPC Equip 26610', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26611, 2, 5, -1, 'NPC Equip 26611', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26612, 2, 5, -1, 'NPC Equip 26612', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26613, 2, 5, -1, 'NPC Equip 26613', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26614, 2, 5, -1, 'NPC Equip 26614', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26615, 2, 5, -1, 'NPC Equip 26615', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26616, 2, 7, -1, 'NPC Equip 26616', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26617, 2, 7, -1, 'NPC Equip 26617', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26618, 2, 7, -1, 'NPC Equip 26618', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26619, 2, 7, -1, 'NPC Equip 26619', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26620, 2, 7, -1, 'NPC Equip 26620', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26621, 2, 7, -1, 'NPC Equip 26621', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26622, 2, 7, -1, 'NPC Equip 26622', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26623, 2, 7, -1, 'NPC Equip 26623', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26624, 2, 7, -1, 'NPC Equip 26624', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26625, 2, 7, -1, 'NPC Equip 26625', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26626, 2, 7, -1, 'NPC Equip 26626', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26627, 2, 7, -1, 'NPC Equip 26627', 1, 43773, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26628, 2, 7, -1, 'NPC Equip 26628', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26629, 2, 7, -1, 'NPC Equip 26629', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26630, 2, 8, -1, 'NPC Equip 26630', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26631, 2, 8, -1, 'NPC Equip 26631', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26632, 2, 8, -1, 'NPC Equip 26632', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26633, 2, 8, -1, 'NPC Equip 26633', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26634, 2, 8, -1, 'NPC Equip 26634', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26635, 2, 8, -1, 'NPC Equip 26635', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26636, 2, 8, -1, 'NPC Equip 26636', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26637, 2, 8, -1, 'NPC Equip 26637', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26638, 2, 8, -1, 'NPC Equip 26638', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26639, 2, 8, -1, 'NPC Equip 26639', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26640, 2, 8, -1, 'NPC Equip 26640', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26641, 2, 8, -1, 'NPC Equip 26641', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26642, 2, 8, -1, 'NPC Equip 26642', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26643, 2, 8, -1, 'NPC Equip 26643', 1, 50656, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26644, 2, 10, -1, 'NPC Equip 26644', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26645, 2, 10, -1, 'NPC Equip 26645', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26646, 2, 10, -1, 'NPC Equip 26646', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26647, 2, 10, -1, 'NPC Equip 26647', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26648, 2, 10, -1, 'NPC Equip 26648', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26649, 2, 10, -1, 'NPC Equip 26649', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26650, 2, 10, -1, 'NPC Equip 26650', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26651, 2, 10, -1, 'NPC Equip 26651', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26652, 2, 10, -1, 'NPC Equip 26652', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26653, 2, 10, -1, 'NPC Equip 26653', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26654, 2, 10, -1, 'NPC Equip 26654', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26656, 2, 10, -1, 'NPC Equip 26656', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26657, 2, 10, -1, 'NPC Equip 26657', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26658, 2, 13, -1, 'NPC Equip 26658', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26659, 2, 13, -1, 'NPC Equip 26659', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26660, 2, 13, -1, 'NPC Equip 26660', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26661, 2, 13, -1, 'NPC Equip 26661', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26662, 2, 13, -1, 'NPC Equip 26662', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26663, 2, 13, -1, 'NPC Equip 26663', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26664, 2, 13, -1, 'NPC Equip 26664', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26665, 2, 13, -1, 'NPC Equip 26665', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26666, 2, 13, -1, 'NPC Equip 26666', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26667, 2, 13, -1, 'NPC Equip 26667', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26668, 2, 13, -1, 'NPC Equip 26668', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26669, 2, 13, -1, 'NPC Equip 26669', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26670, 2, 13, -1, 'NPC Equip 26670', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26671, 2, 13, -1, 'NPC Equip 26671', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26672, 2, 0, -1, 'NPC Equip 26672', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26673, 2, 0, -1, 'NPC Equip 26673', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26674, 2, 0, -1, 'NPC Equip 26674', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26675, 2, 0, -1, 'NPC Equip 26675', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26676, 2, 0, -1, 'NPC Equip 26676', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26677, 2, 0, -1, 'NPC Equip 26677', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26678, 2, 0, -1, 'NPC Equip 26678', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26679, 2, 0, -1, 'NPC Equip 26679', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26680, 2, 0, -1, 'NPC Equip 26680', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26681, 2, 0, -1, 'NPC Equip 26681', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26682, 2, 0, -1, 'NPC Equip 26682', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26683, 2, 0, -1, 'NPC Equip 26683', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26684, 2, 0, -1, 'NPC Equip 26684', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26685, 2, 0, -1, 'NPC Equip 26685', 1, 22118, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26686, 2, 1, -1, 'NPC Equip 26686', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26687, 2, 1, -1, 'NPC Equip 26687', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26688, 2, 1, -1, 'NPC Equip 26688', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26689, 2, 1, -1, 'NPC Equip 26689', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26690, 2, 1, -1, 'NPC Equip 26690', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26691, 2, 1, -1, 'NPC Equip 26691', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26692, 2, 1, -1, 'NPC Equip 26692', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26693, 2, 1, -1, 'NPC Equip 26693', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26694, 2, 1, -1, 'NPC Equip 26694', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26695, 2, 1, -1, 'NPC Equip 26695', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26696, 2, 1, -1, 'NPC Equip 26696', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26697, 2, 1, -1, 'NPC Equip 26697', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26698, 2, 1, -1, 'NPC Equip 26698', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26699, 2, 1, -1, 'NPC Equip 26699', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26700, 2, 6, -1, 'NPC Equip 26700', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26701, 2, 6, -1, 'NPC Equip 26701', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26702, 2, 6, -1, 'NPC Equip 26702', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26703, 2, 6, -1, 'NPC Equip 26703', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26704, 2, 6, -1, 'NPC Equip 26704', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26705, 2, 6, -1, 'NPC Equip 26705', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26706, 2, 6, -1, 'NPC Equip 26706', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26707, 2, 6, -1, 'NPC Equip 26707', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26708, 2, 6, -1, 'NPC Equip 26708', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26709, 2, 6, -1, 'NPC Equip 26709', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26710, 2, 6, -1, 'NPC Equip 26710', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26711, 2, 6, -1, 'NPC Equip 26711', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26712, 2, 6, -1, 'NPC Equip 26712', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26713, 2, 6, -1, 'NPC Equip 26713', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26714, 2, 2, -1, 'NPC Equip 26714', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26715, 2, 2, -1, 'NPC Equip 26715', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26716, 2, 2, -1, 'NPC Equip 26716', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26717, 2, 2, -1, 'NPC Equip 26717', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26718, 2, 2, -1, 'NPC Equip 26718', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26719, 2, 2, -1, 'NPC Equip 26719', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26720, 2, 2, -1, 'NPC Equip 26720', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26721, 2, 2, -1, 'NPC Equip 26721', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26722, 2, 2, -1, 'NPC Equip 26722', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26723, 2, 2, -1, 'NPC Equip 26723', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26724, 2, 2, -1, 'NPC Equip 26724', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26725, 2, 2, -1, 'NPC Equip 26725', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26726, 2, 2, -1, 'NPC Equip 26726', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26727, 2, 2, -1, 'NPC Equip 26727', 2, 2786, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26728, 2, 18, -1, 'NPC Equip 26728', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26729, 2, 18, -1, 'NPC Equip 26729', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26730, 2, 18, -1, 'NPC Equip 26730', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26731, 2, 18, -1, 'NPC Equip 26731', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26732, 2, 18, -1, 'NPC Equip 26732', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26733, 2, 18, -1, 'NPC Equip 26733', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26734, 2, 18, -1, 'NPC Equip 26734', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26735, 2, 18, -1, 'NPC Equip 26735', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26736, 2, 18, -1, 'NPC Equip 26736', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26737, 2, 18, -1, 'NPC Equip 26737', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26739, 2, 18, -1, 'NPC Equip 26739', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26740, 2, 18, -1, 'NPC Equip 26740', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26741, 2, 18, -1, 'NPC Equip 26741', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26742, 2, 3, -1, 'NPC Equip 26742', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26743, 2, 3, -1, 'NPC Equip 26743', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26744, 2, 3, -1, 'NPC Equip 26744', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26745, 2, 3, -1, 'NPC Equip 26745', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26746, 2, 3, -1, 'NPC Equip 26746', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26747, 2, 3, -1, 'NPC Equip 26747', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26748, 2, 3, -1, 'NPC Equip 26748', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26749, 2, 3, -1, 'NPC Equip 26749', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26750, 2, 3, -1, 'NPC Equip 26750', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26751, 2, 3, -1, 'NPC Equip 26751', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26752, 2, 3, -1, 'NPC Equip 26752', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26753, 2, 3, -1, 'NPC Equip 26753', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26754, 2, 3, -1, 'NPC Equip 26754', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26755, 2, 3, -1, 'NPC Equip 26755', 1, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26756, 2, 19, -1, 'NPC Equip 26756', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26757, 2, 19, -1, 'NPC Equip 26757', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26758, 2, 19, -1, 'NPC Equip 26758', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26759, 2, 19, -1, 'NPC Equip 26759', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26760, 2, 19, -1, 'NPC Equip 26760', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26761, 2, 19, -1, 'NPC Equip 26761', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26762, 2, 19, -1, 'NPC Equip 26762', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26763, 2, 19, -1, 'NPC Equip 26763', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26764, 2, 19, -1, 'NPC Equip 26764', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26766, 2, 19, -1, 'NPC Equip 26766', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26767, 2, 19, -1, 'NPC Equip 26767', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26768, 2, 19, -1, 'NPC Equip 26768', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26769, 2, 19, -1, 'NPC Equip 26769', 2, 10671, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26770, 2, 15, -1, 'NPC Equip 26770', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26771, 2, 15, -1, 'NPC Equip 26771', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26772, 2, 15, -1, 'NPC Equip 26772', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26773, 2, 15, -1, 'NPC Equip 26773', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26774, 2, 15, -1, 'NPC Equip 26774', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26775, 2, 15, -1, 'NPC Equip 26775', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26776, 2, 15, -1, 'NPC Equip 26776', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26777, 2, 15, -1, 'NPC Equip 26777', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26778, 2, 15, -1, 'NPC Equip 26778', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26780, 2, 15, -1, 'NPC Equip 26780', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26781, 2, 15, -1, 'NPC Equip 26781', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26782, 2, 15, -1, 'NPC Equip 26782', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26783, 2, 15, -1, 'NPC Equip 26783', 1, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26784, 2, 4, -1, 'NPC Equip 26784', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26785, 2, 4, -1, 'NPC Equip 26785', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26786, 2, 4, -1, 'NPC Equip 26786', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26787, 2, 4, -1, 'NPC Equip 26787', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26788, 2, 4, -1, 'NPC Equip 26788', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26789, 2, 4, -1, 'NPC Equip 26789', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26790, 2, 4, -1, 'NPC Equip 26790', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26791, 2, 4, -1, 'NPC Equip 26791', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26793, 2, 4, -1, 'NPC Equip 26793', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26794, 2, 4, -1, 'NPC Equip 26794', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26795, 2, 4, -1, 'NPC Equip 26795', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26796, 2, 4, -1, 'NPC Equip 26796', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26797, 2, 4, -1, 'NPC Equip 26797', 2, 22118, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26798, 2, 10, -1, 'NPC Equip 26798', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26799, 2, 10, -1, 'NPC Equip 26799', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26800, 2, 10, -1, 'NPC Equip 26800', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26801, 2, 10, -1, 'NPC Equip 26801', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26802, 2, 10, -1, 'NPC Equip 26802', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26803, 2, 10, -1, 'NPC Equip 26803', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26804, 2, 10, -1, 'NPC Equip 26804', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26805, 2, 10, -1, 'NPC Equip 26805', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26806, 2, 10, -1, 'NPC Equip 26806', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26807, 2, 10, -1, 'NPC Equip 26807', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26808, 2, 10, -1, 'NPC Equip 26808', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26809, 2, 10, -1, 'NPC Equip 26809', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26810, 2, 10, -1, 'NPC Equip 26810', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26811, 2, 10, -1, 'NPC Equip 26811', 2, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26812, 4, 2, -1, 'NPC Equip 26812', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26813, 4, 2, -1, 'NPC Equip 26813', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26814, 4, 2, -1, 'NPC Equip 26814', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26815, 4, 2, -1, 'NPC Equip 26815', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26816, 4, 2, -1, 'NPC Equip 26816', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26817, 4, 2, -1, 'NPC Equip 26817', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26818, 4, 2, -1, 'NPC Equip 26818', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26819, 4, 2, -1, 'NPC Equip 26819', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26820, 4, 2, -1, 'NPC Equip 26820', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26821, 4, 2, -1, 'NPC Equip 26821', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26822, 4, 2, -1, 'NPC Equip 26822', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26823, 4, 2, -1, 'NPC Equip 26823', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26824, 4, 2, -1, 'NPC Equip 26824', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26825, 4, 2, -1, 'NPC Equip 26825', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26826, 4, 2, -1, 'NPC Equip 26826', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26827, 4, 2, -1, 'NPC Equip 26827', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26828, 4, 2, -1, 'NPC Equip 26828', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26829, 4, 2, -1, 'NPC Equip 26829', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26830, 4, 2, -1, 'NPC Equip 26830', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26831, 4, 2, -1, 'NPC Equip 26831', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26832, 4, 2, -1, 'NPC Equip 26832', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26833, 4, 2, -1, 'NPC Equip 26833', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26834, 4, 2, -1, 'NPC Equip 26834', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26835, 4, 2, -1, 'NPC Equip 26835', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26836, 4, 2, -1, 'NPC Equip 26836', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26837, 4, 2, -1, 'NPC Equip 26837', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26838, 4, 2, -1, 'NPC Equip 26838', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26839, 4, 2, -1, 'NPC Equip 26839', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26840, 4, 2, -1, 'NPC Equip 26840', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26841, 4, 2, -1, 'NPC Equip 26841', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26842, 4, 2, -1, 'NPC Equip 26842', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26844, 4, 2, -1, 'NPC Equip 26844', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26845, 4, 2, -1, 'NPC Equip 26845', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26846, 4, 2, -1, 'NPC Equip 26846', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26847, 4, 2, -1, 'NPC Equip 26847', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26848, 4, 2, -1, 'NPC Equip 26848', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26849, 4, 2, -1, 'NPC Equip 26849', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26850, 4, 2, -1, 'NPC Equip 26850', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26851, 4, 2, -1, 'NPC Equip 26851', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26852, 4, 2, -1, 'NPC Equip 26852', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26853, 4, 2, -1, 'NPC Equip 26853', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26854, 4, 2, -1, 'NPC Equip 26854', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26855, 4, 2, -1, 'NPC Equip 26855', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26856, 4, 2, -1, 'NPC Equip 26856', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26857, 4, 2, -1, 'NPC Equip 26857', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26858, 4, 2, -1, 'NPC Equip 26858', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26859, 4, 2, -1, 'NPC Equip 26859', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26860, 4, 2, -1, 'NPC Equip 26860', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26861, 4, 2, -1, 'NPC Equip 26861', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26862, 4, 2, -1, 'NPC Equip 26862', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26863, 4, 2, -1, 'NPC Equip 26863', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26864, 4, 2, -1, 'NPC Equip 26864', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26865, 4, 2, -1, 'NPC Equip 26865', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26866, 4, 2, -1, 'NPC Equip 26866', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26867, 4, 2, -1, 'NPC Equip 26867', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26868, 4, 2, -1, 'NPC Equip 26868', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26869, 4, 2, -1, 'NPC Equip 26869', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26870, 4, 2, -1, 'NPC Equip 26870', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26871, 4, 2, -1, 'NPC Equip 26871', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26872, 4, 2, -1, 'NPC Equip 26872', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26873, 4, 2, -1, 'NPC Equip 26873', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26874, 4, 2, -1, 'NPC Equip 26874', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26875, 4, 2, -1, 'NPC Equip 26875', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26876, 4, 2, -1, 'NPC Equip 26876', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26877, 4, 2, -1, 'NPC Equip 26877', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26878, 4, 2, -1, 'NPC Equip 26878', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26879, 4, 2, -1, 'NPC Equip 26879', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26880, 4, 2, -1, 'NPC Equip 26880', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26881, 4, 2, -1, 'NPC Equip 26881', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26882, 4, 2, -1, 'NPC Equip 26882', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26883, 4, 2, -1, 'NPC Equip 26883', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26884, 4, 2, -1, 'NPC Equip 26884', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26885, 4, 2, -1, 'NPC Equip 26885', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26886, 4, 2, -1, 'NPC Equip 26886', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26887, 4, 2, -1, 'NPC Equip 26887', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26888, 4, 2, -1, 'NPC Equip 26888', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26889, 4, 2, -1, 'NPC Equip 26889', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26890, 4, 2, -1, 'NPC Equip 26890', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26891, 4, 2, -1, 'NPC Equip 26891', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26892, 4, 2, -1, 'NPC Equip 26892', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26893, 4, 2, -1, 'NPC Equip 26893', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26894, 4, 2, -1, 'NPC Equip 26894', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26895, 4, 2, -1, 'NPC Equip 26895', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26896, 4, 2, -1, 'NPC Equip 26896', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26897, 4, 2, -1, 'NPC Equip 26897', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26898, 4, 2, -1, 'NPC Equip 26898', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26899, 4, 2, -1, 'NPC Equip 26899', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26900, 4, 2, -1, 'NPC Equip 26900', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26901, 4, 2, -1, 'NPC Equip 26901', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26902, 4, 2, -1, 'NPC Equip 26902', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26903, 4, 2, -1, 'NPC Equip 26903', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26904, 4, 2, -1, 'NPC Equip 26904', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26905, 4, 2, -1, 'NPC Equip 26905', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26906, 4, 2, -1, 'NPC Equip 26906', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26907, 4, 2, -1, 'NPC Equip 26907', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26908, 4, 2, -1, 'NPC Equip 26908', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26909, 4, 2, -1, 'NPC Equip 26909', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26910, 4, 2, -1, 'NPC Equip 26910', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26911, 4, 2, -1, 'NPC Equip 26911', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26912, 4, 2, -1, 'NPC Equip 26912', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26913, 4, 2, -1, 'NPC Equip 26913', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26914, 4, 2, -1, 'NPC Equip 26914', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26915, 4, 2, -1, 'NPC Equip 26915', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26916, 4, 2, -1, 'NPC Equip 26916', 8, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26917, 4, 2, -1, 'NPC Equip 26917', 8, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26918, 4, 2, -1, 'NPC Equip 26918', 8, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26919, 4, 2, -1, 'NPC Equip 26919', 8, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26920, 4, 2, -1, 'NPC Equip 26920', 8, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26921, 4, 2, -1, 'NPC Equip 26921', 8, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26922, 4, 2, -1, 'NPC Equip 26922', 8, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26923, 4, 2, -1, 'NPC Equip 26923', 8, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26924, 4, 3, -1, 'NPC Equip 26924', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26925, 4, 3, -1, 'NPC Equip 26925', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26926, 4, 3, -1, 'NPC Equip 26926', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26927, 4, 3, -1, 'NPC Equip 26927', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26928, 4, 3, -1, 'NPC Equip 26928', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26929, 4, 3, -1, 'NPC Equip 26929', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26930, 4, 3, -1, 'NPC Equip 26930', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26931, 4, 3, -1, 'NPC Equip 26931', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26932, 4, 3, -1, 'NPC Equip 26932', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26933, 4, 3, -1, 'NPC Equip 26933', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26934, 4, 3, -1, 'NPC Equip 26934', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26935, 4, 3, -1, 'NPC Equip 26935', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26936, 4, 3, -1, 'NPC Equip 26936', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26937, 4, 3, -1, 'NPC Equip 26937', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26938, 4, 3, -1, 'NPC Equip 26938', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26939, 4, 3, -1, 'NPC Equip 26939', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26940, 4, 3, -1, 'NPC Equip 26940', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26941, 4, 3, -1, 'NPC Equip 26941', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26942, 4, 3, -1, 'NPC Equip 26942', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26943, 4, 3, -1, 'NPC Equip 26943', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26944, 4, 3, -1, 'NPC Equip 26944', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26945, 4, 3, -1, 'NPC Equip 26945', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26946, 4, 3, -1, 'NPC Equip 26946', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26947, 4, 3, -1, 'NPC Equip 26947', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26948, 4, 3, -1, 'NPC Equip 26948', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26949, 4, 3, -1, 'NPC Equip 26949', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26950, 4, 3, -1, 'NPC Equip 26950', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26951, 4, 3, -1, 'NPC Equip 26951', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26952, 4, 3, -1, 'NPC Equip 26952', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26953, 4, 3, -1, 'NPC Equip 26953', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26954, 4, 3, -1, 'NPC Equip 26954', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26955, 4, 3, -1, 'NPC Equip 26955', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26956, 4, 3, -1, 'NPC Equip 26956', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26957, 4, 3, -1, 'NPC Equip 26957', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26958, 4, 3, -1, 'NPC Equip 26958', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26959, 4, 3, -1, 'NPC Equip 26959', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26960, 4, 3, -1, 'NPC Equip 26960', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26961, 4, 3, -1, 'NPC Equip 26961', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26962, 4, 3, -1, 'NPC Equip 26962', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26963, 4, 3, -1, 'NPC Equip 26963', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26964, 4, 3, -1, 'NPC Equip 26964', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26965, 4, 3, -1, 'NPC Equip 26965', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26966, 4, 3, -1, 'NPC Equip 26966', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26967, 4, 3, -1, 'NPC Equip 26967', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26968, 4, 3, -1, 'NPC Equip 26968', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26969, 4, 3, -1, 'NPC Equip 26969', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26970, 4, 3, -1, 'NPC Equip 26970', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26971, 4, 3, -1, 'NPC Equip 26971', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26972, 4, 3, -1, 'NPC Equip 26972', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26973, 4, 3, -1, 'NPC Equip 26973', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26974, 4, 3, -1, 'NPC Equip 26974', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26975, 4, 3, -1, 'NPC Equip 26975', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26976, 4, 3, -1, 'NPC Equip 26976', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26977, 4, 3, -1, 'NPC Equip 26977', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26978, 4, 3, -1, 'NPC Equip 26978', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26979, 4, 3, -1, 'NPC Equip 26979', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26980, 4, 3, -1, 'NPC Equip 26980', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26981, 4, 3, -1, 'NPC Equip 26981', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26982, 4, 3, -1, 'NPC Equip 26982', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26983, 4, 3, -1, 'NPC Equip 26983', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26984, 4, 3, -1, 'NPC Equip 26984', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26985, 4, 3, -1, 'NPC Equip 26985', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26986, 4, 3, -1, 'NPC Equip 26986', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26987, 4, 3, -1, 'NPC Equip 26987', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26988, 4, 3, -1, 'NPC Equip 26988', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26989, 4, 3, -1, 'NPC Equip 26989', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26990, 4, 3, -1, 'NPC Equip 26990', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26991, 4, 3, -1, 'NPC Equip 26991', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26992, 4, 3, -1, 'NPC Equip 26992', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26993, 4, 3, -1, 'NPC Equip 26993', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26994, 4, 3, -1, 'NPC Equip 26994', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26995, 4, 3, -1, 'NPC Equip 26995', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26996, 4, 3, -1, 'NPC Equip 26996', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26997, 4, 3, -1, 'NPC Equip 26997', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26998, 4, 3, -1, 'NPC Equip 26998', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (26999, 4, 3, -1, 'NPC Equip 26999', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27000, 4, 3, -1, 'NPC Equip 27000', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27001, 4, 3, -1, 'NPC Equip 27001', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27003, 4, 3, -1, 'NPC Equip 27003', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27004, 4, 3, -1, 'NPC Equip 27004', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27005, 4, 3, -1, 'NPC Equip 27005', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27006, 4, 3, -1, 'NPC Equip 27006', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27008, 4, 3, -1, 'NPC Equip 27008', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27009, 4, 3, -1, 'NPC Equip 27009', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27010, 4, 3, -1, 'NPC Equip 27010', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27011, 4, 3, -1, 'NPC Equip 27011', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27012, 4, 3, -1, 'NPC Equip 27012', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27013, 4, 3, -1, 'NPC Equip 27013', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27014, 4, 3, -1, 'NPC Equip 27014', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27015, 4, 3, -1, 'NPC Equip 27015', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27016, 4, 3, -1, 'NPC Equip 27016', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27017, 4, 3, -1, 'NPC Equip 27017', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27018, 4, 3, -1, 'NPC Equip 27018', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27019, 4, 3, -1, 'NPC Equip 27019', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27020, 4, 3, -1, 'NPC Equip 27020', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27021, 4, 3, -1, 'NPC Equip 27021', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27022, 4, 3, -1, 'NPC Equip 27022', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27023, 4, 3, -1, 'NPC Equip 27023', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27024, 4, 3, -1, 'NPC Equip 27024', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27025, 4, 3, -1, 'NPC Equip 27025', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27026, 4, 3, -1, 'NPC Equip 27026', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27027, 4, 3, -1, 'NPC Equip 27027', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27028, 4, 3, -1, 'NPC Equip 27028', 5, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27029, 4, 3, -1, 'NPC Equip 27029', 5, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27030, 4, 3, -1, 'NPC Equip 27030', 5, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27031, 4, 3, -1, 'NPC Equip 27031', 5, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27032, 4, 3, -1, 'NPC Equip 27032', 5, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27033, 4, 3, -1, 'NPC Equip 27033', 5, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27034, 4, 3, -1, 'NPC Equip 27034', 5, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27035, 4, 3, -1, 'NPC Equip 27035', 5, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27036, 4, 4, -1, 'NPC Equip 27036', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27037, 4, 4, -1, 'NPC Equip 27037', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27038, 4, 4, -1, 'NPC Equip 27038', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27039, 4, 4, -1, 'NPC Equip 27039', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27040, 4, 4, -1, 'NPC Equip 27040', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27041, 4, 4, -1, 'NPC Equip 27041', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27042, 4, 4, -1, 'NPC Equip 27042', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27043, 4, 4, -1, 'NPC Equip 27043', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27044, 4, 4, -1, 'NPC Equip 27044', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27045, 4, 4, -1, 'NPC Equip 27045', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27046, 4, 4, -1, 'NPC Equip 27046', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27047, 4, 4, -1, 'NPC Equip 27047', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27048, 4, 4, -1, 'NPC Equip 27048', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27049, 4, 4, -1, 'NPC Equip 27049', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27050, 4, 4, -1, 'NPC Equip 27050', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27051, 4, 4, -1, 'NPC Equip 27051', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27052, 4, 4, -1, 'NPC Equip 27052', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27053, 4, 4, -1, 'NPC Equip 27053', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27054, 4, 4, -1, 'NPC Equip 27054', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27055, 4, 4, -1, 'NPC Equip 27055', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27056, 4, 4, -1, 'NPC Equip 27056', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27057, 4, 4, -1, 'NPC Equip 27057', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27058, 4, 4, -1, 'NPC Equip 27058', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27059, 4, 4, -1, 'NPC Equip 27059', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27060, 4, 4, -1, 'NPC Equip 27060', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27061, 4, 4, -1, 'NPC Equip 27061', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27062, 4, 4, -1, 'NPC Equip 27062', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27063, 4, 4, -1, 'NPC Equip 27063', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27064, 4, 4, -1, 'NPC Equip 27064', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27065, 4, 4, -1, 'NPC Equip 27065', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27066, 4, 4, -1, 'NPC Equip 27066', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27067, 4, 4, -1, 'NPC Equip 27067', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27068, 4, 4, -1, 'NPC Equip 27068', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27069, 4, 4, -1, 'NPC Equip 27069', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27070, 4, 4, -1, 'NPC Equip 27070', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27071, 4, 4, -1, 'NPC Equip 27071', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27072, 4, 4, -1, 'NPC Equip 27072', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27073, 4, 4, -1, 'NPC Equip 27073', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27074, 4, 4, -1, 'NPC Equip 27074', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27075, 4, 4, -1, 'NPC Equip 27075', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27076, 4, 4, -1, 'NPC Equip 27076', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27077, 4, 4, -1, 'NPC Equip 27077', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27078, 4, 4, -1, 'NPC Equip 27078', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27079, 4, 4, -1, 'NPC Equip 27079', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27080, 4, 4, -1, 'NPC Equip 27080', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27081, 4, 4, -1, 'NPC Equip 27081', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27082, 4, 4, -1, 'NPC Equip 27082', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27083, 4, 4, -1, 'NPC Equip 27083', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27084, 4, 4, -1, 'NPC Equip 27084', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27085, 4, 4, -1, 'NPC Equip 27085', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27086, 4, 4, -1, 'NPC Equip 27086', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27087, 4, 4, -1, 'NPC Equip 27087', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27088, 4, 4, -1, 'NPC Equip 27088', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27089, 4, 4, -1, 'NPC Equip 27089', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27090, 4, 4, -1, 'NPC Equip 27090', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27091, 4, 4, -1, 'NPC Equip 27091', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27092, 4, 4, -1, 'NPC Equip 27092', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27093, 4, 4, -1, 'NPC Equip 27093', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27094, 4, 4, -1, 'NPC Equip 27094', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27095, 4, 4, -1, 'NPC Equip 27095', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27096, 4, 4, -1, 'NPC Equip 27096', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27097, 4, 4, -1, 'NPC Equip 27097', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27098, 4, 4, -1, 'NPC Equip 27098', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27099, 4, 4, -1, 'NPC Equip 27099', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27100, 4, 4, -1, 'NPC Equip 27100', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27101, 4, 4, -1, 'NPC Equip 27101', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27102, 4, 4, -1, 'NPC Equip 27102', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27103, 4, 4, -1, 'NPC Equip 27103', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27104, 4, 4, -1, 'NPC Equip 27104', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27105, 4, 4, -1, 'NPC Equip 27105', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27106, 4, 4, -1, 'NPC Equip 27106', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27107, 4, 4, -1, 'NPC Equip 27107', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27108, 4, 4, -1, 'NPC Equip 27108', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27109, 4, 4, -1, 'NPC Equip 27109', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27110, 4, 4, -1, 'NPC Equip 27110', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27111, 4, 4, -1, 'NPC Equip 27111', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27112, 4, 4, -1, 'NPC Equip 27112', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27113, 4, 4, -1, 'NPC Equip 27113', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27114, 4, 4, -1, 'NPC Equip 27114', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27115, 4, 4, -1, 'NPC Equip 27115', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27116, 4, 4, -1, 'NPC Equip 27116', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27117, 4, 4, -1, 'NPC Equip 27117', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27118, 4, 4, -1, 'NPC Equip 27118', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27119, 4, 4, -1, 'NPC Equip 27119', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27120, 4, 4, -1, 'NPC Equip 27120', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27121, 4, 4, -1, 'NPC Equip 27121', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27122, 4, 4, -1, 'NPC Equip 27122', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27123, 4, 4, -1, 'NPC Equip 27123', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27124, 4, 4, -1, 'NPC Equip 27124', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27125, 4, 4, -1, 'NPC Equip 27125', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27126, 4, 4, -1, 'NPC Equip 27126', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27127, 4, 4, -1, 'NPC Equip 27127', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27128, 4, 4, -1, 'NPC Equip 27128', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27129, 4, 4, -1, 'NPC Equip 27129', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27130, 4, 4, -1, 'NPC Equip 27130', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27131, 4, 4, -1, 'NPC Equip 27131', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27132, 4, 4, -1, 'NPC Equip 27132', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27133, 4, 4, -1, 'NPC Equip 27133', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27134, 4, 4, -1, 'NPC Equip 27134', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27135, 4, 4, -1, 'NPC Equip 27135', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27136, 4, 4, -1, 'NPC Equip 27136', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27137, 4, 4, -1, 'NPC Equip 27137', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27138, 4, 4, -1, 'NPC Equip 27138', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27139, 4, 4, -1, 'NPC Equip 27139', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27140, 4, 4, -1, 'NPC Equip 27140', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27141, 4, 4, -1, 'NPC Equip 27141', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27142, 4, 4, -1, 'NPC Equip 27142', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27143, 4, 4, -1, 'NPC Equip 27143', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27144, 4, 4, -1, 'NPC Equip 27144', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27145, 4, 4, -1, 'NPC Equip 27145', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27146, 4, 4, -1, 'NPC Equip 27146', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27147, 4, 4, -1, 'NPC Equip 27147', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27148, 4, 1, -1, 'NPC Equip 27148', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27149, 4, 1, -1, 'NPC Equip 27149', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27150, 4, 1, -1, 'NPC Equip 27150', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27151, 4, 1, -1, 'NPC Equip 27151', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27152, 4, 1, -1, 'NPC Equip 27152', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27153, 4, 1, -1, 'NPC Equip 27153', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27154, 4, 1, -1, 'NPC Equip 27154', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27155, 4, 1, -1, 'NPC Equip 27155', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27156, 4, 1, -1, 'NPC Equip 27156', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27157, 4, 1, -1, 'NPC Equip 27157', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27158, 4, 1, -1, 'NPC Equip 27158', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27159, 4, 1, -1, 'NPC Equip 27159', 7, 26202, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27160, 4, 1, -1, 'NPC Equip 27160', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27161, 4, 1, -1, 'NPC Equip 27161', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27162, 4, 0, -1, 'NPC Equip 27162', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27163, 4, 0, -1, 'NPC Equip 27163', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27164, 4, 0, -1, 'NPC Equip 27164', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27165, 4, 0, -1, 'NPC Equip 27165', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27166, 4, 0, -1, 'NPC Equip 27166', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27167, 4, 0, -1, 'NPC Equip 27167', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27168, 4, 0, -1, 'NPC Equip 27168', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27169, 4, 0, -1, 'NPC Equip 27169', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27170, 4, 0, -1, 'NPC Equip 27170', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27171, 4, 0, -1, 'NPC Equip 27171', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27172, 4, 0, -1, 'NPC Equip 27172', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27173, 4, 0, -1, 'NPC Equip 27173', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27174, 4, 0, -1, 'NPC Equip 27174', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27175, 4, 0, -1, 'NPC Equip 27175', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27176, 4, 0, -1, 'NPC Equip 27176', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27177, 4, 0, -1, 'NPC Equip 27177', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27178, 4, 0, -1, 'NPC Equip 27178', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27179, 4, 0, -1, 'NPC Equip 27179', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27180, 4, 0, -1, 'NPC Equip 27180', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27181, 4, 0, -1, 'NPC Equip 27181', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27182, 4, 0, -1, 'NPC Equip 27182', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27183, 4, 0, -1, 'NPC Equip 27183', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27184, 4, 0, -1, 'NPC Equip 27184', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27185, 4, 0, -1, 'NPC Equip 27185', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27186, 4, 0, -1, 'NPC Equip 27186', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27187, 4, 0, -1, 'NPC Equip 27187', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27188, 4, 0, -1, 'NPC Equip 27188', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27189, 4, 0, -1, 'NPC Equip 27189', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27190, 4, 1, -1, 'NPC Equip 27190', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27191, 4, 1, -1, 'NPC Equip 27191', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27192, 4, 1, -1, 'NPC Equip 27192', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27193, 4, 1, -1, 'NPC Equip 27193', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27194, 4, 1, -1, 'NPC Equip 27194', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27195, 4, 1, -1, 'NPC Equip 27195', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27197, 4, 1, -1, 'NPC Equip 27197', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27198, 4, 1, -1, 'NPC Equip 27198', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27199, 4, 1, -1, 'NPC Equip 27199', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27200, 4, 1, -1, 'NPC Equip 27200', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27201, 4, 1, -1, 'NPC Equip 27201', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27202, 4, 1, -1, 'NPC Equip 27202', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27203, 4, 1, -1, 'NPC Equip 27203', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27204, 4, 0, -1, 'NPC Equip 27204', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27205, 4, 0, -1, 'NPC Equip 27205', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27206, 4, 0, -1, 'NPC Equip 27206', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27207, 4, 0, -1, 'NPC Equip 27207', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27208, 4, 0, -1, 'NPC Equip 27208', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27209, 4, 0, -1, 'NPC Equip 27209', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27210, 4, 0, -1, 'NPC Equip 27210', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27211, 4, 0, -1, 'NPC Equip 27211', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27212, 4, 0, -1, 'NPC Equip 27212', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27213, 4, 0, -1, 'NPC Equip 27213', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27214, 4, 0, -1, 'NPC Equip 27214', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27215, 4, 0, -1, 'NPC Equip 27215', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27216, 4, 0, -1, 'NPC Equip 27216', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27217, 4, 0, -1, 'NPC Equip 27217', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27219, 4, 0, -1, 'NPC Equip 27219', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27220, 4, 0, -1, 'NPC Equip 27220', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27221, 4, 0, -1, 'NPC Equip 27221', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27222, 4, 0, -1, 'NPC Equip 27222', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27223, 4, 0, -1, 'NPC Equip 27223', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27224, 4, 0, -1, 'NPC Equip 27224', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27225, 4, 0, -1, 'NPC Equip 27225', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27226, 4, 0, -1, 'NPC Equip 27226', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27227, 4, 0, -1, 'NPC Equip 27227', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27228, 4, 0, -1, 'NPC Equip 27228', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27229, 4, 0, -1, 'NPC Equip 27229', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27230, 4, 0, -1, 'NPC Equip 27230', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27231, 4, 0, -1, 'NPC Equip 27231', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27232, 4, 1, -1, 'NPC Equip 27232', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27233, 4, 1, -1, 'NPC Equip 27233', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27234, 4, 1, -1, 'NPC Equip 27234', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27235, 4, 1, -1, 'NPC Equip 27235', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27236, 4, 1, -1, 'NPC Equip 27236', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27237, 4, 1, -1, 'NPC Equip 27237', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27238, 4, 1, -1, 'NPC Equip 27238', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27239, 4, 1, -1, 'NPC Equip 27239', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27240, 4, 1, -1, 'NPC Equip 27240', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27241, 4, 1, -1, 'NPC Equip 27241', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27242, 4, 1, -1, 'NPC Equip 27242', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27243, 4, 1, -1, 'NPC Equip 27243', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27244, 4, 1, -1, 'NPC Equip 27244', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27245, 4, 1, -1, 'NPC Equip 27245', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27246, 4, 0, -1, 'NPC Equip 27246', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27247, 4, 0, -1, 'NPC Equip 27247', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27248, 4, 0, -1, 'NPC Equip 27248', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27249, 4, 0, -1, 'NPC Equip 27249', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27250, 4, 0, -1, 'NPC Equip 27250', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27251, 4, 0, -1, 'NPC Equip 27251', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27252, 4, 0, -1, 'NPC Equip 27252', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27253, 4, 0, -1, 'NPC Equip 27253', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27254, 4, 0, -1, 'NPC Equip 27254', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27255, 4, 0, -1, 'NPC Equip 27255', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27256, 4, 0, -1, 'NPC Equip 27256', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27257, 4, 0, -1, 'NPC Equip 27257', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27258, 4, 0, -1, 'NPC Equip 27258', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27259, 4, 0, -1, 'NPC Equip 27259', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27260, 4, 0, -1, 'NPC Equip 27260', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27261, 4, 0, -1, 'NPC Equip 27261', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27262, 4, 0, -1, 'NPC Equip 27262', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27263, 4, 0, -1, 'NPC Equip 27263', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27264, 4, 0, -1, 'NPC Equip 27264', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27265, 4, 0, -1, 'NPC Equip 27265', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27266, 4, 0, -1, 'NPC Equip 27266', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27267, 4, 0, -1, 'NPC Equip 27267', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27268, 4, 0, -1, 'NPC Equip 27268', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27269, 4, 0, -1, 'NPC Equip 27269', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27270, 4, 0, -1, 'NPC Equip 27270', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27271, 4, 0, -1, 'NPC Equip 27271', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27272, 4, 0, -1, 'NPC Equip 27272', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27273, 4, 0, -1, 'NPC Equip 27273', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27274, 4, 1, -1, 'NPC Equip 27274', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27275, 4, 1, -1, 'NPC Equip 27275', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27276, 4, 1, -1, 'NPC Equip 27276', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27277, 4, 1, -1, 'NPC Equip 27277', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27278, 4, 1, -1, 'NPC Equip 27278', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27279, 4, 1, -1, 'NPC Equip 27279', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27280, 4, 1, -1, 'NPC Equip 27280', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27281, 4, 1, -1, 'NPC Equip 27281', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27282, 4, 1, -1, 'NPC Equip 27282', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27283, 4, 1, -1, 'NPC Equip 27283', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27284, 4, 1, -1, 'NPC Equip 27284', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27285, 4, 1, -1, 'NPC Equip 27285', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27286, 4, 1, -1, 'NPC Equip 27286', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27287, 4, 1, -1, 'NPC Equip 27287', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27288, 4, 0, -1, 'NPC Equip 27288', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27289, 4, 0, -1, 'NPC Equip 27289', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27290, 4, 0, -1, 'NPC Equip 27290', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27291, 4, 0, -1, 'NPC Equip 27291', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27292, 4, 0, -1, 'NPC Equip 27292', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27293, 4, 0, -1, 'NPC Equip 27293', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27294, 4, 0, -1, 'NPC Equip 27294', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27295, 4, 0, -1, 'NPC Equip 27295', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27296, 4, 0, -1, 'NPC Equip 27296', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27297, 4, 0, -1, 'NPC Equip 27297', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27298, 4, 0, -1, 'NPC Equip 27298', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27299, 4, 0, -1, 'NPC Equip 27299', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27300, 4, 0, -1, 'NPC Equip 27300', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27301, 4, 0, -1, 'NPC Equip 27301', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27302, 4, 0, -1, 'NPC Equip 27302', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27303, 4, 0, -1, 'NPC Equip 27303', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27304, 4, 0, -1, 'NPC Equip 27304', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27305, 4, 0, -1, 'NPC Equip 27305', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27306, 4, 0, -1, 'NPC Equip 27306', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27307, 4, 0, -1, 'NPC Equip 27307', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27308, 4, 0, -1, 'NPC Equip 27308', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27309, 4, 0, -1, 'NPC Equip 27309', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27310, 4, 0, -1, 'NPC Equip 27310', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27311, 4, 0, -1, 'NPC Equip 27311', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27312, 4, 0, -1, 'NPC Equip 27312', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27313, 4, 0, -1, 'NPC Equip 27313', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27314, 4, 0, -1, 'NPC Equip 27314', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27315, 4, 0, -1, 'NPC Equip 27315', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27316, 15, 0, -1, 'NPC Equip 27316', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27318, 15, 0, -1, 'NPC Equip 27318', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27319, 15, 0, -1, 'NPC Equip 27319', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27320, 15, 0, -1, 'NPC Equip 27320', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27321, 15, 0, -1, 'NPC Equip 27321', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27322, 15, 0, -1, 'NPC Equip 27322', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27323, 15, 0, -1, 'NPC Equip 27323', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27324, 15, 0, -1, 'NPC Equip 27324', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27325, 15, 0, -1, 'NPC Equip 27325', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27326, 15, 0, -1, 'NPC Equip 27326', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27327, 15, 0, -1, 'NPC Equip 27327', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27328, 15, 0, -1, 'NPC Equip 27328', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27329, 15, 0, -1, 'NPC Equip 27329', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27330, 15, 0, -1, 'NPC Equip 27330', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27331, 15, 0, -1, 'NPC Equip 27331', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27332, 15, 0, -1, 'NPC Equip 27332', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27333, 15, 0, -1, 'NPC Equip 27333', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27334, 15, 0, -1, 'NPC Equip 27334', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27335, 15, 0, -1, 'NPC Equip 27335', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27336, 15, 0, -1, 'NPC Equip 27336', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27337, 15, 0, -1, 'NPC Equip 27337', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27338, 15, 0, -1, 'NPC Equip 27338', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27339, 15, 0, -1, 'NPC Equip 27339', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27340, 15, 0, -1, 'NPC Equip 27340', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27341, 15, 0, -1, 'NPC Equip 27341', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27342, 15, 0, -1, 'NPC Equip 27342', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27343, 15, 0, -1, 'NPC Equip 27343', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27344, 15, 0, -1, 'NPC Equip 27344', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27345, 15, 0, -1, 'NPC Equip 27345', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27346, 15, 0, -1, 'NPC Equip 27346', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27347, 15, 0, -1, 'NPC Equip 27347', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27348, 15, 0, -1, 'NPC Equip 27348', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27349, 15, 0, -1, 'NPC Equip 27349', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27350, 15, 0, -1, 'NPC Equip 27350', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27351, 15, 0, -1, 'NPC Equip 27351', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27352, 15, 0, -1, 'NPC Equip 27352', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27353, 15, 0, -1, 'NPC Equip 27353', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27354, 15, 0, -1, 'NPC Equip 27354', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27355, 15, 0, -1, 'NPC Equip 27355', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27356, 15, 0, -1, 'NPC Equip 27356', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27357, 15, 0, -1, 'NPC Equip 27357', -1, 9731, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27358, 15, 0, -1, 'NPC Equip 27358', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27359, 15, 0, -1, 'NPC Equip 27359', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27360, 15, 0, -1, 'NPC Equip 27360', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27361, 15, 0, -1, 'NPC Equip 27361', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27362, 15, 0, -1, 'NPC Equip 27362', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27363, 15, 0, -1, 'NPC Equip 27363', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27364, 15, 0, -1, 'NPC Equip 27364', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27365, 15, 0, -1, 'NPC Equip 27365', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27366, 15, 0, -1, 'NPC Equip 27366', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27367, 15, 0, -1, 'NPC Equip 27367', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27368, 15, 0, -1, 'NPC Equip 27368', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27369, 15, 0, -1, 'NPC Equip 27369', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27370, 15, 0, -1, 'NPC Equip 27370', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27371, 15, 0, -1, 'NPC Equip 27371', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27372, 15, 0, -1, 'NPC Equip 27372', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27373, 15, 0, -1, 'NPC Equip 27373', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27374, 15, 0, -1, 'NPC Equip 27374', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27375, 15, 0, -1, 'NPC Equip 27375', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27376, 15, 0, -1, 'NPC Equip 27376', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27377, 15, 0, -1, 'NPC Equip 27377', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27378, 15, 0, -1, 'NPC Equip 27378', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27379, 15, 0, -1, 'NPC Equip 27379', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27380, 15, 0, -1, 'NPC Equip 27380', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27381, 15, 0, -1, 'NPC Equip 27381', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27382, 15, 0, -1, 'NPC Equip 27382', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27383, 15, 0, -1, 'NPC Equip 27383', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27384, 15, 0, -1, 'NPC Equip 27384', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27385, 15, 0, -1, 'NPC Equip 27385', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27386, 15, 0, -1, 'NPC Equip 27386', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27387, 15, 0, -1, 'NPC Equip 27387', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27391, 15, 0, -1, 'NPC Equip 27391', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27392, 15, 0, -1, 'NPC Equip 27392', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27393, 15, 0, -1, 'NPC Equip 27393', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27394, 15, 0, -1, 'NPC Equip 27394', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27395, 15, 0, -1, 'NPC Equip 27395', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27396, 15, 0, -1, 'NPC Equip 27396', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27397, 15, 0, -1, 'NPC Equip 27397', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27405, 2, 7, -1, 'NPC Equip 27405', 1, 38181, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27406, 4, 6, -1, 'NPC Equip 27406', 1, 38182, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27407, 2, 4, -1, 'NPC Equip 27407', 2, 38183, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27421, 12, 0, -1, 'NPC Equip 27421', -1, 992, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27444, 7, 8, -1, 'NPC Equip 27444', -1, 38902, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27482, 15, 0, -1, 'NPC Equip 27482', 2, 7913, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27486, 4, 4, -1, 'NPC Equip 27486', -1, 38197, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27496, 2, 15, -1, 'NPC Equip 27496', 1, 38198, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27504, 0, 0, -1, 'NPC Equip 27504', 7, 3331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27530, 4, 1, -1, 'NPC Equip 27530', 7, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27554, 15, 0, -1, 'NPC Equip 27554', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27555, 15, 0, -1, 'NPC Equip 27555', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27556, 15, 0, -1, 'NPC Equip 27556', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27557, 15, 0, -1, 'NPC Equip 27557', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27558, 15, 0, -1, 'NPC Equip 27558', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27559, 15, 0, -1, 'NPC Equip 27559', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27560, 15, 0, -1, 'NPC Equip 27560', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27561, 15, 0, -1, 'NPC Equip 27561', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27562, 15, 0, -1, 'NPC Equip 27562', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27563, 15, 0, -1, 'NPC Equip 27563', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27564, 15, 0, -1, 'NPC Equip 27564', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27565, 15, 0, -1, 'NPC Equip 27565', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27566, 15, 0, -1, 'NPC Equip 27566', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27567, 15, 0, -1, 'NPC Equip 27567', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27568, 15, 0, -1, 'NPC Equip 27568', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27569, 15, 0, -1, 'NPC Equip 27569', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27570, 15, 0, -1, 'NPC Equip 27570', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27571, 15, 0, -1, 'NPC Equip 27571', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27572, 15, 0, -1, 'NPC Equip 27572', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27573, 15, 0, -1, 'NPC Equip 27573', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27574, 15, 0, -1, 'NPC Equip 27574', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27575, 15, 0, -1, 'NPC Equip 27575', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27576, 15, 0, -1, 'NPC Equip 27576', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27577, 15, 0, -1, 'NPC Equip 27577', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27578, 15, 0, -1, 'NPC Equip 27578', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27579, 15, 0, -1, 'NPC Equip 27579', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27580, 15, 0, -1, 'NPC Equip 27580', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27581, 15, 0, -1, 'NPC Equip 27581', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27582, 15, 0, -1, 'NPC Equip 27582', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27583, 15, 0, -1, 'NPC Equip 27583', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27584, 15, 0, -1, 'NPC Equip 27584', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27585, 15, 0, -1, 'NPC Equip 27585', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27586, 15, 0, -1, 'NPC Equip 27586', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27587, 15, 0, -1, 'NPC Equip 27587', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27588, 15, 0, -1, 'NPC Equip 27588', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27589, 15, 0, -1, 'NPC Equip 27589', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27591, 15, 0, -1, 'NPC Equip 27591', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27592, 15, 0, -1, 'NPC Equip 27592', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27593, 15, 0, -1, 'NPC Equip 27593', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27594, 15, 0, -1, 'NPC Equip 27594', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27595, 15, 0, -1, 'NPC Equip 27595', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27596, 15, 0, -1, 'NPC Equip 27596', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27597, 15, 0, -1, 'NPC Equip 27597', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27598, 15, 0, -1, 'NPC Equip 27598', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27599, 15, 0, -1, 'NPC Equip 27599', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27600, 15, 0, -1, 'NPC Equip 27600', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27601, 15, 0, -1, 'NPC Equip 27601', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27602, 15, 0, -1, 'NPC Equip 27602', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27603, 15, 0, -1, 'NPC Equip 27603', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27604, 15, 0, -1, 'NPC Equip 27604', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27605, 15, 0, -1, 'NPC Equip 27605', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27606, 15, 0, -1, 'NPC Equip 27606', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27607, 15, 0, -1, 'NPC Equip 27607', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27608, 15, 0, -1, 'NPC Equip 27608', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27609, 15, 0, -1, 'NPC Equip 27609', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27610, 15, 0, -1, 'NPC Equip 27610', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27611, 15, 0, -1, 'NPC Equip 27611', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27612, 15, 0, -1, 'NPC Equip 27612', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27613, 15, 0, -1, 'NPC Equip 27613', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27614, 15, 0, -1, 'NPC Equip 27614', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27615, 15, 0, -1, 'NPC Equip 27615', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27616, 15, 0, -1, 'NPC Equip 27616', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27617, 15, 0, -1, 'NPC Equip 27617', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27618, 15, 0, -1, 'NPC Equip 27618', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27619, 15, 0, -1, 'NPC Equip 27619', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27620, 15, 0, -1, 'NPC Equip 27620', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27621, 15, 0, -1, 'NPC Equip 27621', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27622, 15, 0, -1, 'NPC Equip 27622', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27623, 15, 0, -1, 'NPC Equip 27623', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27624, 15, 0, -1, 'NPC Equip 27624', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27625, 15, 0, -1, 'NPC Equip 27625', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27626, 15, 0, -1, 'NPC Equip 27626', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27627, 15, 0, -1, 'NPC Equip 27627', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27628, 15, 0, -1, 'NPC Equip 27628', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27629, 15, 0, -1, 'NPC Equip 27629', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27630, 15, 0, -1, 'NPC Equip 27630', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27642, 4, 3, -1, 'NPC Equip 27642', 5, 34241, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27670, 4, 0, -1, 'NPC Equip 27670', 3, 9657, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27675, 7, 4, -1, 'NPC Equip 27675', -1, 18707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27701, 2, 4, -1, 'NPC Equip 27701', 2, 38288, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27782, 7, 4, -1, 'NPC Equip 27782', -1, 7122, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27810, 7, 4, -1, 'NPC Equip 27810', -1, 35843, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27819, 15, 5, -1, 'NPC Equip 27819', -1, 17494, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27836, 2, 4, -1, 'NPC Equip 27836', 2, 38387, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27849, 2, 0, -1, 'NPC Equip 27849', 1, 782, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27850, 2, 0, -1, 'NPC Equip 27850', 1, 38411, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27851, 4, 6, -1, 'NPC Equip 27851', 1, 38412, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27852, 2, 5, -1, 'NPC Equip 27852', 2, 38413, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27853, 15, 5, -1, 'NPC Equip 27853', -1, 17494, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27862, 2, 5, -1, 'NPC Equip 27862', 2, 37525, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27894, 15, 0, -1, 'NPC Equip 27894', 8, 18095, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27923, 2, 10, -1, 'NPC Equip 27923', 2, 24503, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27950, 4, 4, -1, 'NPC Equip 27950', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27951, 4, 4, -1, 'NPC Equip 27951', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27952, 4, 4, -1, 'NPC Equip 27952', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27953, 4, 4, -1, 'NPC Equip 27953', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27954, 4, 4, -1, 'NPC Equip 27954', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27955, 4, 4, -1, 'NPC Equip 27955', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27956, 4, 4, -1, 'NPC Equip 27956', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27957, 4, 4, -1, 'NPC Equip 27957', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27958, 4, 0, -1, 'NPC Equip 27958', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27959, 4, 0, -1, 'NPC Equip 27959', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27960, 4, 1, -1, 'NPC Equip 27960', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27961, 2, 8, -1, 'NPC Equip 27961', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27962, 2, 8, -1, 'NPC Equip 27962', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27963, 4, 4, -1, 'NPC Equip 27963', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27964, 4, 4, -1, 'NPC Equip 27964', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27966, 4, 4, -1, 'NPC Equip 27966', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27967, 4, 4, -1, 'NPC Equip 27967', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27968, 4, 4, -1, 'NPC Equip 27968', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27969, 4, 4, -1, 'NPC Equip 27969', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27970, 4, 4, -1, 'NPC Equip 27970', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27971, 4, 0, -1, 'NPC Equip 27971', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27972, 4, 0, -1, 'NPC Equip 27972', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27973, 4, 1, -1, 'NPC Equip 27973', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27974, 2, 8, -1, 'NPC Equip 27974', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27975, 2, 8, -1, 'NPC Equip 27975', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27997, 4, 4, -1, 'NPC Equip 27997', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27998, 4, 4, -1, 'NPC Equip 27998', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (27999, 4, 4, -1, 'NPC Equip 27999', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28000, 4, 4, -1, 'NPC Equip 28000', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28001, 4, 4, -1, 'NPC Equip 28001', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28002, 4, 4, -1, 'NPC Equip 28002', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28003, 4, 4, -1, 'NPC Equip 28003', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28004, 4, 4, -1, 'NPC Equip 28004', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28005, 4, 0, -1, 'NPC Equip 28005', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28006, 4, 0, -1, 'NPC Equip 28006', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28007, 4, 1, -1, 'NPC Equip 28007', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28008, 2, 8, -1, 'NPC Equip 28008', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28009, 2, 8, -1, 'NPC Equip 28009', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28010, 4, 4, -1, 'NPC Equip 28010', 6, 16704, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28011, 4, 4, -1, 'NPC Equip 28011', 6, 16703, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28012, 4, 4, -1, 'NPC Equip 28012', 6, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28013, 4, 4, -1, 'NPC Equip 28013', 6, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28014, 4, 4, -1, 'NPC Equip 28014', 6, 18422, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28015, 4, 4, -1, 'NPC Equip 28015', 6, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28016, 4, 4, -1, 'NPC Equip 28016', 6, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28017, 4, 4, -1, 'NPC Equip 28017', 6, 9894, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28018, 4, 0, -1, 'NPC Equip 28018', 3, 4841, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28019, 4, 0, -1, 'NPC Equip 28019', 3, 9834, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28020, 4, 1, -1, 'NPC Equip 28020', 7, 16707, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28021, 2, 8, -1, 'NPC Equip 28021', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28022, 2, 8, -1, 'NPC Equip 28022', 1, 33299, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28025, 15, 0, -1, 'NPC Equip 28025', -1, 17785, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28035, 15, 0, -1, 'NPC Equip 28035', -1, 25484, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28036, 0, 0, -1, 'NPC Equip 28036', -1, 6399, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28037, 2, 7, -1, 'NPC Equip 28037', 1, 38642, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28049, 12, 0, -1, 'NPC Equip 28049', -1, 38673, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28067, 2, 10, -1, 'NPC Equip 28067', 2, 36698, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28076, 15, 0, -1, 'NPC Equip 28076', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28077, 15, 0, -1, 'NPC Equip 28077', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28078, 15, 0, -1, 'NPC Equip 28078', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28079, 15, 0, -1, 'NPC Equip 28079', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28080, 15, 0, -1, 'NPC Equip 28080', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28081, 15, 0, -1, 'NPC Equip 28081', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28082, 15, 0, -1, 'NPC Equip 28082', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28083, 15, 0, -1, 'NPC Equip 28083', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28084, 15, 0, -1, 'NPC Equip 28084', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28085, 15, 0, -1, 'NPC Equip 28085', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28086, 15, 0, -1, 'NPC Equip 28086', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28087, 2, 7, -1, 'NPC Equip 28087', 1, 36376, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28088, 15, 0, -1, 'NPC Equip 28088', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28089, 15, 0, -1, 'NPC Equip 28089', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28090, 15, 0, -1, 'NPC Equip 28090', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28091, 15, 0, -1, 'NPC Equip 28091', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28092, 15, 0, -1, 'NPC Equip 28092', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28093, 15, 0, -1, 'NPC Equip 28093', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28094, 15, 0, -1, 'NPC Equip 28094', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28095, 15, 0, -1, 'NPC Equip 28095', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28096, 15, 0, -1, 'NPC Equip 28096', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28097, 15, 0, -1, 'NPC Equip 28097', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28098, 15, 0, -1, 'NPC Equip 28098', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28113, 15, 0, -1, 'NPC Equip 28113', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28114, 15, 0, -1, 'NPC Equip 28114', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28115, 2, 8, -1, 'NPC Equip 28115', 1, 34112, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28125, 2, 8, -1, 'NPC Equip 28125', 1, 38930, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28133, 2, 7, -1, 'NPC Equip 28133', 1, 43826, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28135, 15, 0, -1, 'NPC Equip 28135', -1, 8928, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28165, 2, 3, -1, 'NPC Equip 28165', 1, 39107, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28195, 2, 10, -1, 'NPC Equip 28195', 2, 39146, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28196, 2, 10, -1, 'NPC Equip 28196', 2, 39147, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28197, 2, 10, -1, 'NPC Equip 28197', 2, 39148, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28198, 2, 10, -1, 'NPC Equip 28198', 2, 39149, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28199, 2, 10, -1, 'NPC Equip 28199', 2, 39150, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28200, 2, 10, -1, 'NPC Equip 28200', 2, 39151, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28201, 2, 4, -1, 'NPC Equip 28201', 2, 39154, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28208, 2, 10, -1, 'NPC Equip 28208', 2, 39159, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28261, 15, 0, -1, 'NPC Equip 28261', -1, 17785, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28289, 15, 0, -1, 'NPC Equip 28289', -1, 39189, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28326, 15, 2, -1, 'NPC Equip 28326', -1, 39330, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28329, 4, 3, -1, 'NPC Equip 28329', 5, 32103, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28330, 4, 3, -1, 'NPC Equip 28330', 5, 32100, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28354, 2, 1, -1, 'NPC Equip 28354', 1, 39351, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28365, 2, 6, -1, 'NPC Equip 28365', 1, 39393, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28366, 4, 0, -1, 'NPC Equip 28366', 3, 33529, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28382, 4, 4, -1, 'NPC Equip 28382', 6, 27273, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28456, 2, 10, -1, 'NPC Equip 28456', 2, 40438, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28471, 12, 0, -1, 'NPC Equip 28471', -1, 8093, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28480, 4, 4, -1, 'NPC Equip 28480', 1, 35044, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28487, 2, 4, -1, 'NPC Equip 28487', 2, 39673, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28488, 2, 8, -1, 'NPC Equip 28488', 1, 39678, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28546, 4, 0, -1, 'NPC Equip 28546', -1, 39824, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28549, 12, 0, -1, 'NPC Equip 28549', -1, 7636, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28648, 2, 14, -1, 'NPC Equip 28648', 1, 23175, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28650, 2, 6, -1, 'NPC Equip 28650', 1, 39287, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28678, 2, 15, -1, 'NPC Equip 28678', 1, 39974, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28682, 4, 4, -1, 'NPC Equip 28682', 6, 38295, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28736, 2, 4, -1, 'NPC Equip 28736', 2, 34109, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28737, 4, 6, -1, 'NPC Equip 28737', 1, 29702, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28798, 4, 0, -1, 'NPC Equip 28798', 7, 40076, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28816, 4, 0, -1, 'NPC Equip 28816', 3, 31664, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28876, 12, 0, -1, 'NPC Equip 28876', -1, 30690, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28877, 12, 0, -1, 'NPC Equip 28877', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28879, 12, 0, -1, 'NPC Equip 28879', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28880, 12, 0, -1, 'NPC Equip 28880', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28883, 12, 0, -1, 'NPC Equip 28883', -1, 30690, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28884, 12, 0, -1, 'NPC Equip 28884', -1, 30690, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28890, 12, 0, -1, 'NPC Equip 28890', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28891, 12, 0, -1, 'NPC Equip 28891', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28892, 12, 0, -1, 'NPC Equip 28892', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28893, 12, 0, -1, 'NPC Equip 28893', -1, 40088, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28894, 12, 0, -1, 'NPC Equip 28894', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28895, 12, 0, -1, 'NPC Equip 28895', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28896, 12, 0, -1, 'NPC Equip 28896', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28897, 12, 0, -1, 'NPC Equip 28897', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28898, 12, 0, -1, 'NPC Equip 28898', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28899, 12, 0, -1, 'NPC Equip 28899', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28900, 12, 0, -1, 'NPC Equip 28900', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28901, 12, 0, -1, 'NPC Equip 28901', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28902, 12, 0, -1, 'NPC Equip 28902', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28906, 2, 13, -1, 'NPC Equip 28906', 1, 40875, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28914, 2, 6, -1, 'NPC Equip 28914', 1, 23283, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28916, 2, 8, -1, 'NPC Equip 28916', 2, 41066, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28932, 2, 16, -1, 'NPC Equip 28932', 1, 38679, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28958, 2, 16, -1, 'NPC Equip 28958', 1, 38679, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28961, 4, 6, -1, 'NPC Equip 28961', 1, 31746, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (28965, 2, 6, -1, 'NPC Equip 28965', 1, 40127, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29025, 12, 0, -1, 'NPC Equip 29025', -1, 40122, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29052, 12, 0, -1, 'NPC Equip 29052', -1, 40248, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29107, 2, 10, -1, 'NPC Equip 29107', 2, 40276, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29114, 2, 10, -1, 'NPC Equip 29114', 2, 40311, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29178, 4, 0, -1, 'NPC Equip 29178', 3, 35423, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29188, 12, 0, -1, 'NPC Equip 29188', -1, 40397, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29208, 15, 0, -1, 'NPC Equip 29208', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29256, 4, 1, -1, 'NPC Equip 29256', 7, 35519, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29293, 0, 5, -1, 'NPC Equip 29293', -1, 22200, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29310, 2, 10, -1, 'NPC Equip 29310', 2, 40520, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29358, 4, 6, -1, 'NPC Equip 29358', 6, 41648, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29392, 12, 0, -1, 'NPC Equip 29392', 0, 19479, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29402, 0, 5, -1, 'NPC Equip 29402', -1, 40653, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29403, 2, 7, -1, 'NPC Equip 29403', 1, 40654, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29404, 2, 7, -1, 'NPC Equip 29404', 1, 40655, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29405, 2, 7, -1, 'NPC Equip 29405', 1, 40655, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29406, 2, 7, -1, 'NPC Equip 29406', 1, 40656, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29407, 2, 5, -1, 'NPC Equip 29407', 2, 40657, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29408, 2, 5, -1, 'NPC Equip 29408', 2, 40662, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29409, 2, 5, -1, 'NPC Equip 29409', 2, 40661, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29413, 2, 0, -1, 'NPC Equip 29413', 1, 40663, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29414, 2, 0, -1, 'NPC Equip 29414', 1, 40664, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29415, 2, 7, -1, 'NPC Equip 29415', 1, 40665, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29416, 2, 10, -1, 'NPC Equip 29416', 1, 40666, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29417, 2, 0, -1, 'NPC Equip 29417', 1, 40678, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29418, 2, 0, -1, 'NPC Equip 29418', 1, 40668, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29420, 2, 7, -1, 'NPC Equip 29420', 1, 40671, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29421, 2, 10, -1, 'NPC Equip 29421', 1, 40673, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29422, 2, 0, -1, 'NPC Equip 29422', 1, 40677, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29423, 2, 5, -1, 'NPC Equip 29423', 1, 40675, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29424, 2, 4, -1, 'NPC Equip 29424', 1, 40676, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29427, 12, 0, -1, 'NPC Equip 29427', -1, 40681, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29430, 2, 0, -1, 'NPC Equip 29430', 1, 40716, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29431, 2, 10, -1, 'NPC Equip 29431', 2, 40750, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29432, 2, 10, -1, 'NPC Equip 29432', 2, 40751, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29433, 2, 0, -1, 'NPC Equip 29433', 1, 40752, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29435, 2, 15, -1, 'NPC Equip 29435', 1, 40754, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29436, 2, 0, -1, 'NPC Equip 29436', 1, 40755, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29437, 2, 0, -1, 'NPC Equip 29437', 1, 40760, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29438, 2, 0, -1, 'NPC Equip 29438', 1, 40778, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29439, 2, 7, -1, 'NPC Equip 29439', 1, 40780, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29440, 2, 10, -1, 'NPC Equip 29440', 1, 40784, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29441, 2, 10, -1, 'NPC Equip 29441', 1, 40800, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29442, 2, 10, -1, 'NPC Equip 29442', 2, 40821, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29444, 2, 0, -1, 'NPC Equip 29444', 1, 40828, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29446, 2, 7, -1, 'NPC Equip 29446', 1, 40863, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29455, 2, 5, -1, 'NPC Equip 29455', 1, 67223, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29462, 2, 7, -1, 'NPC Equip 29462', 1, 40889, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29479, 2, 5, -1, 'NPC Equip 29479', 1, 39841, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29484, 2, 5, -1, 'NPC Equip 29484', 1, 39840, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29537, 2, 10, -1, 'NPC Equip 29537', 2, 41057, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29538, 2, 8, -1, 'NPC Equip 29538', 1, 41070, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29541, 2, 0, -1, 'NPC Equip 29541', 1, 41071, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29542, 2, 7, -1, 'NPC Equip 29542', 1, 41072, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29543, 2, 4, -1, 'NPC Equip 29543', 2, 41073, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29544, 2, 10, -1, 'NPC Equip 29544', 2, 41074, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29551, 15, 0, -1, 'NPC Equip 29551', 7, 18092, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29552, 15, 0, -1, 'NPC Equip 29552', -1, 959, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29557, 15, 0, -1, 'NPC Equip 29557', -1, 37887, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29558, 15, 0, -1, 'NPC Equip 29558', -1, 34035, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29566, 15, 0, -1, 'NPC Equip 29566', -1, 19573, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29585, 0, 0, -1, 'NPC Equip 29585', -1, 41193, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29587, 12, 0, -1, 'NPC Equip 29587', -1, 25271, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29619, 2, 4, -1, 'NPC Equip 29619', 2, 41279, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29620, 2, 1, -1, 'NPC Equip 29620', 1, 41280, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29621, 2, 1, -1, 'NPC Equip 29621', 1, 41281, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29622, 2, 1, -1, 'NPC Equip 29622', 1, 41282, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29623, 2, 1, -1, 'NPC Equip 29623', 1, 41283, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29626, 2, 3, -1, 'NPC Equip 29626', 2, 44573, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29627, 2, 3, -1, 'NPC Equip 29627', 2, 41291, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29628, 2, 3, -1, 'NPC Equip 29628', 2, 41292, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29629, 2, 3, -1, 'NPC Equip 29629', 2, 41293, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29630, 2, 4, -1, 'NPC Equip 29630', 2, 41294, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29631, 2, 4, -1, 'NPC Equip 29631', 2, 41295, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29632, 2, 4, -1, 'NPC Equip 29632', 2, 41296, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29633, 2, 4, -1, 'NPC Equip 29633', 2, 41297, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29634, 2, 4, -1, 'NPC Equip 29634', 2, 41298, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29635, 4, 6, -1, 'NPC Equip 29635', 1, 41299, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29636, 4, 6, -1, 'NPC Equip 29636', 1, 41300, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29637, 4, 6, -1, 'NPC Equip 29637', 1, 41301, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29638, 4, 6, -1, 'NPC Equip 29638', 1, 41302, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29639, 4, 6, -1, 'NPC Equip 29639', 1, 41303, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29640, 4, 6, -1, 'NPC Equip 29640', 1, 41304, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29641, 4, 6, -1, 'NPC Equip 29641', 1, 41305, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29642, 4, 6, -1, 'NPC Equip 29642', 1, 41306, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29643, 2, 8, -1, 'NPC Equip 29643', 1, 41307, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29644, 2, 8, -1, 'NPC Equip 29644', 1, 41308, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29646, 2, 8, -1, 'NPC Equip 29646', 1, 41310, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29647, 2, 8, -1, 'NPC Equip 29647', 1, 41311, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29648, 2, 8, -1, 'NPC Equip 29648', 1, 41312, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29649, 2, 8, -1, 'NPC Equip 29649', 1, 41313, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29650, 2, 8, -1, 'NPC Equip 29650', 1, 41314, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29651, 2, 1, -1, 'NPC Equip 29651', 1, 41315, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29652, 2, 1, -1, 'NPC Equip 29652', 1, 41316, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29653, 2, 1, -1, 'NPC Equip 29653', 1, 41317, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29654, 2, 1, -1, 'NPC Equip 29654', 1, 41318, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29655, 2, 1, -1, 'NPC Equip 29655', 1, 41319, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29656, 2, 1, -1, 'NPC Equip 29656', 1, 41320, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29657, 2, 1, -1, 'NPC Equip 29657', 1, 41321, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29658, 2, 1, -1, 'NPC Equip 29658', 1, 41322, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29659, 2, 1, -1, 'NPC Equip 29659', 1, 41323, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29660, 2, 1, -1, 'NPC Equip 29660', 1, 41324, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29661, 2, 1, -1, 'NPC Equip 29661', 1, 41325, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29662, 2, 1, -1, 'NPC Equip 29662', 1, 41326, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29663, 2, 1, -1, 'NPC Equip 29663', 1, 41327, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29665, 2, 1, -1, 'NPC Equip 29665', 1, 41328, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29666, 2, 7, -1, 'NPC Equip 29666', 1, 41329, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29667, 2, 7, -1, 'NPC Equip 29667', 1, 41330, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29668, 2, 7, -1, 'NPC Equip 29668', 1, 41331, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29670, 2, 7, -1, 'NPC Equip 29670', 1, 41332, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29671, 2, 7, -1, 'NPC Equip 29671', 1, 41333, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29676, 2, 10, -1, 'NPC Equip 29676', 2, 41334, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29678, 2, 10, -1, 'NPC Equip 29678', 2, 41335, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29679, 2, 10, -1, 'NPC Equip 29679', 2, 41336, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29680, 2, 10, -1, 'NPC Equip 29680', 2, 41337, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29681, 2, 10, -1, 'NPC Equip 29681', 2, 41338, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29683, 2, 10, -1, 'NPC Equip 29683', 2, 41339, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29685, 2, 10, -1, 'NPC Equip 29685', 2, 41340, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29686, 2, 10, -1, 'NPC Equip 29686', 2, 41341, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29687, 2, 10, -1, 'NPC Equip 29687', 2, 41342, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29688, 2, 10, -1, 'NPC Equip 29688', 2, 41343, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29690, 2, 10, -1, 'NPC Equip 29690', 2, 41344, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29692, 2, 10, -1, 'NPC Equip 29692', 2, 41345, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29694, 2, 10, -1, 'NPC Equip 29694', 2, 41346, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29695, 2, 10, -1, 'NPC Equip 29695', 2, 41347, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29696, 2, 10, -1, 'NPC Equip 29696', 2, 41348, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29697, 2, 10, -1, 'NPC Equip 29697', 2, 41349, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29705, 2, 0, -1, 'NPC Equip 29705', 1, 41351, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29706, 2, 0, -1, 'NPC Equip 29706', 1, 41352, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29707, 2, 0, -1, 'NPC Equip 29707', 1, 41353, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29708, 2, 0, -1, 'NPC Equip 29708', 1, 41354, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29709, 2, 0, -1, 'NPC Equip 29709', 1, 41355, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29710, 2, 0, -1, 'NPC Equip 29710', 1, 41356, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29711, 2, 0, -1, 'NPC Equip 29711', 1, 41357, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29715, 2, 10, -1, 'NPC Equip 29715', 2, 41359, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29716, 2, 10, -1, 'NPC Equip 29716', 2, 41360, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29748, 2, 10, -1, 'NPC Equip 29748', 2, 40371, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29752, 4, 4, -1, 'NPC Equip 29752', 1, 35044, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29802, 12, 0, -1, 'NPC Equip 29802', -1, 37083, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29809, 2, 0, -1, 'NPC Equip 29809', 1, 25410, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29816, 2, 7, -1, 'NPC Equip 29816', 1, 41460, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29819, 2, 8, -1, 'NPC Equip 29819', 1, 41464, 17, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29820, 2, 7, -1, 'NPC Equip 29820', 1, 41464, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29821, 4, 6, -1, 'NPC Equip 29821', 1, 41465, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29823, 4, 2, -1, 'NPC Equip 29823', 8, 40465, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29824, 4, 2, -1, 'NPC Equip 29824', 8, 40465, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29825, 2, 15, -1, 'NPC Equip 29825', 1, 35819, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29826, 2, 15, -1, 'NPC Equip 29826', 1, 35819, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29827, 2, 15, -1, 'NPC Equip 29827', 1, 35819, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29829, 4, 4, -1, 'NPC Equip 29829', 1, 40484, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29830, 4, 4, -1, 'NPC Equip 29830', 1, 40484, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29831, 2, 7, -1, 'NPC Equip 29831', -1, 41414, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29832, 2, 7, -1, 'NPC Equip 29832', -1, 41414, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29833, 2, 1, -1, 'NPC Equip 29833', 1, 40922, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29834, 2, 1, -1, 'NPC Equip 29834', 1, 40922, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29835, 4, 4, -1, 'NPC Equip 29835', 1, 35618, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29836, 4, 4, -1, 'NPC Equip 29836', 1, 35618, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29837, 0, 8, -1, 'NPC Equip 29837', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29838, 0, 8, -1, 'NPC Equip 29838', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29843, 0, 8, -1, 'NPC Equip 29843', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29844, 0, 8, -1, 'NPC Equip 29844', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29845, 0, 8, -1, 'NPC Equip 29845', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29846, 0, 8, -1, 'NPC Equip 29846', -1, 36684, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29847, 0, 8, -1, 'NPC Equip 29847', -1, 36684, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29848, 0, 8, -1, 'NPC Equip 29848', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29849, 0, 8, -1, 'NPC Equip 29849', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29850, 0, 8, -1, 'NPC Equip 29850', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29851, 0, 8, -1, 'NPC Equip 29851', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29853, 0, 8, -1, 'NPC Equip 29853', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29854, 0, 8, -1, 'NPC Equip 29854', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29855, 4, 1, -1, 'NPC Equip 29855', 7, 40468, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29858, 0, 8, -1, 'NPC Equip 29858', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29859, 0, 8, -1, 'NPC Equip 29859', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29862, 0, 8, -1, 'NPC Equip 29862', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29864, 0, 8, -1, 'NPC Equip 29864', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29865, 4, 1, -1, 'NPC Equip 29865', 7, 40468, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29866, 0, 8, -1, 'NPC Equip 29866', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29867, 0, 8, -1, 'NPC Equip 29867', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29869, 0, 8, -1, 'NPC Equip 29869', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29870, 0, 8, -1, 'NPC Equip 29870', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29873, 0, 8, -1, 'NPC Equip 29873', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29875, 4, 1, -1, 'NPC Equip 29875', 7, 40482, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29876, 4, 1, -1, 'NPC Equip 29876', 7, 40482, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29877, 0, 0, -1, 'NPC Equip 29877', 4, 39888, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29878, 4, 1, -1, 'NPC Equip 29878', 7, 36354, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29879, 4, 1, -1, 'NPC Equip 29879', 7, 36354, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29880, 2, 1, -1, 'NPC Equip 29880', 1, 40922, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29881, 2, 1, -1, 'NPC Equip 29881', 1, 40922, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29882, 4, 3, -1, 'NPC Equip 29882', 5, 40448, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29883, 4, 3, -1, 'NPC Equip 29883', 5, 40448, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29884, 2, 3, -1, 'NPC Equip 29884', 1, 41430, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29886, 15, 0, -1, 'NPC Equip 29886', 1, 9632, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29888, 2, 3, -1, 'NPC Equip 29888', 1, 41430, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29889, 11, 3, -1, 'NPC Equip 29889', 8, 1282, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29890, 4, 2, -1, 'NPC Equip 29890', 8, 35159, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29891, 4, 2, -1, 'NPC Equip 29891', 8, 35159, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29892, 4, 2, -1, 'NPC Equip 29892', 8, 35159, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29893, 4, 2, -1, 'NPC Equip 29893', 8, 35159, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29894, 4, 4, -1, 'NPC Equip 29894', 6, 41133, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29895, 4, 4, -1, 'NPC Equip 29895', 6, 41133, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29896, 4, 3, -1, 'NPC Equip 29896', 5, 40445, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29897, 4, 3, -1, 'NPC Equip 29897', 5, 40445, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29898, 4, 3, -1, 'NPC Equip 29898', 5, 35752, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29899, 4, 3, -1, 'NPC Equip 29899', 5, 35752, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29900, 2, 0, -1, 'NPC Equip 29900', 1, 41487, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (29907, 6, 2, -1, 'NPC Equip 29907', 2, 41489, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30078, 2, 4, -1, 'NPC Equip 30078', 2, 41619, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30128, 2, 3, -1, 'NPC Equip 30128', 1, 31210, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30147, 2, 7, -1, 'NPC Equip 30147', 1, 41653, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30176, 2, 0, -1, 'NPC Equip 30176', 1, 41663, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30178, 2, 1, -1, 'NPC Equip 30178', 1, 41691, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30179, 2, 5, -1, 'NPC Equip 30179', 1, 41692, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30180, 2, 0, -1, 'NPC Equip 30180', 1, 41693, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30181, 2, 7, -1, 'NPC Equip 30181', 1, 41694, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30182, 2, 6, -1, 'NPC Equip 30182', 1, 41696, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30191, 0, 8, -1, 'NPC Equip 30191', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30195, 0, 8, -1, 'NPC Equip 30195', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30198, 0, 8, -1, 'NPC Equip 30198', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30199, 0, 8, -1, 'NPC Equip 30199', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30202, 4, 0, -1, 'NPC Equip 30202', -1, 41735, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30203, 4, 1, -1, 'NPC Equip 30203', -1, 41736, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30204, 2, 8, -1, 'NPC Equip 30204', 1, 41740, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30208, 2, 0, -1, 'NPC Equip 30208', 1, 41752, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30209, 2, 0, -1, 'NPC Equip 30209', 1, 41753, 22, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30261, 2, 5, -1, 'NPC Equip 30261', 2, 41801, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30292, 12, 0, -1, 'NPC Equip 30292', -1, 41837, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30310, 2, 10, -1, 'NPC Equip 30310', 2, 41866, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30325, 12, 0, -1, 'NPC Equip 30325', -1, 18050, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30347, 0, 8, -1, 'NPC Equip 30347', 1, 8026, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30367, 2, 8, -1, 'NPC Equip 30367', 1, 41957, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30376, 2, 4, -1, 'NPC Equip 30376', 2, 41965, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30385, 4, 4, -1, 'NPC Equip 30385', 6, 9388, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30387, 2, 4, -1, 'NPC Equip 30387', 1, 41873, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30388, 2, 1, -1, 'NPC Equip 30388', 1, 41560, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30389, 2, 15, -1, 'NPC Equip 30389', 1, 41872, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30390, 2, 2, -1, 'NPC Equip 30390', 2, 41875, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30391, 4, 6, -1, 'NPC Equip 30391', 6, 40867, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30392, 2, 10, -1, 'NPC Equip 30392', 1, 41895, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30393, 2, 7, -1, 'NPC Equip 30393', 1, 41867, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30403, 2, 7, -1, 'NPC Equip 30403', 1, 41973, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30405, 2, 7, -1, 'NPC Equip 30405', 1, 41975, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30406, 2, 7, -1, 'NPC Equip 30406', 1, 41976, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30407, 2, 7, -1, 'NPC Equip 30407', 1, 41977, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30408, 2, 7, -1, 'NPC Equip 30408', 1, 41978, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30409, 2, 7, -1, 'NPC Equip 30409', 1, 41979, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30410, 2, 7, -1, 'NPC Equip 30410', 1, 41980, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30411, 2, 7, -1, 'NPC Equip 30411', 1, 41981, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30412, 2, 7, -1, 'NPC Equip 30412', 1, 41983, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30423, 2, 10, -1, 'NPC Equip 30423', 2, 42000, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30424, 2, 10, -1, 'NPC Equip 30424', 2, 42001, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30439, 2, 6, -1, 'NPC Equip 30439', 1, 42042, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30441, 2, 10, -1, 'NPC Equip 30441', 2, 42049, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30445, 2, 4, -1, 'NPC Equip 30445', 2, 42062, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30452, 2, 2, -1, 'NPC Equip 30452', 2, 43519, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30455, 2, 8, -1, 'NPC Equip 30455', 1, 30886, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30456, 2, 2, -1, 'NPC Equip 30456', 2, 34102, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30469, 9, 2, -1, 'NPC Equip 30469', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30470, 9, 2, -1, 'NPC Equip 30470', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30471, 9, 2, -1, 'NPC Equip 30471', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30472, 9, 2, -1, 'NPC Equip 30472', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30473, 9, 2, -1, 'NPC Equip 30473', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30474, 9, 2, -1, 'NPC Equip 30474', -1, 1301, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30482, 2, 8, -1, 'NPC Equip 30482', 1, 42125, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30484, 2, 7, -1, 'NPC Equip 30484', 1, 42160, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30485, 2, 7, -1, 'NPC Equip 30485', 1, 42162, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30492, 4, 4, -1, 'NPC Equip 30492', 6, 32644, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30493, 4, 3, -1, 'NPC Equip 30493', 6, 32644, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30494, 4, 4, -1, 'NPC Equip 30494', 6, 32644, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30495, 4, 4, -1, 'NPC Equip 30495', 6, 32644, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30496, 4, 4, -1, 'NPC Equip 30496', 6, 32822, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30502, 2, 1, -1, 'NPC Equip 30502', 0, 42252, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30528, 4, 2, -1, 'NPC Equip 30528', 8, 35159, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30537, 4, 1, -1, 'NPC Equip 30537', 7, 42444, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30545, 12, 0, -1, 'NPC Equip 30545', -1, 39214, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30557, 2, 2, -1, 'NPC Equip 30557', 2, 41874, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30562, 7, 4, -1, 'NPC Equip 30562', -1, 39930, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30576, 2, 15, -1, 'NPC Equip 30576', 1, 42337, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30577, 2, 1, -1, 'NPC Equip 30577', 1, 42340, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30578, 2, 15, -1, 'NPC Equip 30578', 1, 42341, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30580, 2, 18, -1, 'NPC Equip 30580', 1, 42343, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30624, 2, 7, -1, 'NPC Equip 30624', 1, 42420, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30625, 2, 1, -1, 'NPC Equip 30625', 1, 42421, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30636, 2, 8, -1, 'NPC Equip 30636', 1, 42434, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30647, 2, 7, -1, 'NPC Equip 30647', -1, 42504, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30648, 2, 7, -1, 'NPC Equip 30648', 1, 42514, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30660, 2, 15, -1, 'NPC Equip 30660', 1, 43350, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30661, 2, 0, -1, 'NPC Equip 30661', 1, 42551, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30662, 4, 6, -1, 'NPC Equip 30662', 1, 42552, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30669, 2, 10, -1, 'NPC Equip 30669', 2, 40075, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30670, 2, 4, -1, 'NPC Equip 30670', 2, 42555, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30671, 2, 4, -1, 'NPC Equip 30671', 2, 42556, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30697, 2, 6, -1, 'NPC Equip 30697', 1, 42655, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30698, 2, 6, -1, 'NPC Equip 30698', 1, 42660, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30699, 2, 0, -1, 'NPC Equip 30699', 1, 43903, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30702, 2, 0, -1, 'NPC Equip 30702', 1, 7040, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30711, 15, 0, -1, 'NPC Equip 30711', -1, 17514, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30714, 2, 8, -1, 'NPC Equip 30714', 1, 42704, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30715, 2, 0, -1, 'NPC Equip 30715', 1, 42705, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30718, 4, 1, -1, 'NPC Equip 30718', 7, 12645, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30790, 2, 6, -1, 'NPC Equip 30790', 2, 24472, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30793, 0, 1, -1, 'NPC Equip 30793', -1, 3664, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30795, 2, 6, -1, 'NPC Equip 30795', 1, 42793, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30796, 12, 0, -1, 'NPC Equip 30796', -1, 41755, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30801, 2, 8, -1, 'NPC Equip 30801', 1, 42807, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30802, 2, 5, -1, 'NPC Equip 30802', 2, 42820, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30806, 1, 0, -1, 'NPC Equip 30806', -1, 3565, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30848, 2, 1, -1, 'NPC Equip 30848', 1, 42979, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30877, 0, 8, -1, 'NPC Equip 30877', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30920, 4, 1, -1, 'NPC Equip 30920', 7, 43211, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30921, 4, 1, -1, 'NPC Equip 30921', 7, 43212, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30934, 4, 2, -1, 'NPC Equip 30934', 8, 43223, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30935, 4, 2, -1, 'NPC Equip 30935', 8, 43230, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30949, 4, 3, -1, 'NPC Equip 30949', 7, 43244, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30954, 4, 3, -1, 'NPC Equip 30954', 5, 43255, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30963, 4, 4, -1, 'NPC Equip 30963', 6, 43280, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (30965, 4, 4, -1, 'NPC Equip 30965', 6, 43288, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31081, 2, 8, -1, 'NPC Equip 31081', 1, 42704, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31082, 2, 5, -1, 'NPC Equip 31082', 1, 41558, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31083, 2, 2, -1, 'NPC Equip 31083', 2, 43386, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31087, 12, 0, -1, 'NPC Equip 31087', -1, 36597, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31167, 0, 8, -1, 'NPC Equip 31167', -1, 40372, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31171, 12, 0, -1, 'NPC Equip 31171', -1, 43680, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31205, 2, 0, -1, 'NPC Equip 31205', 1, 41487, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31206, 2, 0, -1, 'NPC Equip 31206', 1, 33835, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31207, 2, 8, -1, 'NPC Equip 31207', 1, 43711, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31208, 2, 5, -1, 'NPC Equip 31208', 2, 43712, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31253, 2, 10, -1, 'NPC Equip 31253', -1, 43753, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31257, 2, 10, -1, 'NPC Equip 31257', -1, 43754, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31259, 2, 7, -1, 'NPC Equip 31259', -1, 43756, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31265, 4, 6, -1, 'NPC Equip 31265', -1, 43760, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31267, 2, 8, -1, 'NPC Equip 31267', -1, 43763, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31273, 2, 6, -1, 'NPC Equip 31273', 1, 41554, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31274, 2, 6, -1, 'NPC Equip 31274', 1, 43785, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31296, 2, 10, -1, 'NPC Equip 31296', 2, 43802, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31301, 2, 10, -1, 'NPC Equip 31301', 2, 43810, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31302, 2, 7, -1, 'NPC Equip 31302', 1, 43811, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31309, 2, 10, -1, 'NPC Equip 31309', 2, 43818, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31311, 2, 7, -1, 'NPC Equip 31311', 1, 43820, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31325, 2, 2, -1, 'NPC Equip 31325', 2, 43835, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31327, 2, 6, -1, 'NPC Equip 31327', 1, 43838, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31348, 2, 2, -1, 'NPC Equip 31348', 2, 43880, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31352, 2, 18, -1, 'NPC Equip 31352', 1, 33020, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31353, 2, 0, -1, 'NPC Equip 31353', 1, 43936, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31385, 2, 16, -1, 'NPC Equip 31385', 1, 43948, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31388, 2, 16, -1, 'NPC Equip 31388', 1, 43949, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31389, 12, 0, -1, 'NPC Equip 31389', -1, 6334, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31466, 4, 6, -1, 'NPC Equip 31466', 1, 44023, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31467, 4, 6, -1, 'NPC Equip 31467', 1, 44024, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31468, 4, 6, -1, 'NPC Equip 31468', 1, 44026, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31469, 12, 0, -1, 'NPC Equip 31469', -1, 31434, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31496, 9, 0, -1, 'NPC Equip 31496', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31497, 2, 16, -1, 'NPC Equip 31497', 1, 44046, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31498, 9, 0, -1, 'NPC Equip 31498', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31499, 2, 16, -1, 'NPC Equip 31499', 1, 44047, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31500, 9, 0, -1, 'NPC Equip 31500', -1, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31502, 9, 0, -1, 'NPC Equip 31502', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31503, 9, 0, -1, 'NPC Equip 31503', -1, 1155, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31505, 9, 0, -1, 'NPC Equip 31505', -1, 3426, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31506, 9, 0, -1, 'NPC Equip 31506', -1, 3426, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31507, 9, 0, -1, 'NPC Equip 31507', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31551, 2, 5, -1, 'NPC Equip 31551', 1, 44085, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31600, 2, 0, -1, 'NPC Equip 31600', 1, 44148, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31601, 2, 1, -1, 'NPC Equip 31601', 1, 44150, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31602, 2, 5, -1, 'NPC Equip 31602', 1, 44085, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31603, 2, 7, -1, 'NPC Equip 31603', 1, 44152, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31604, 2, 1, -1, 'NPC Equip 31604', 1, 44153, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31605, 2, 10, -1, 'NPC Equip 31605', 1, 44155, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31608, 2, 10, -1, 'NPC Equip 31608', 2, 44213, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31609, 2, 15, -1, 'NPC Equip 31609', 1, 44233, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31611, 2, 7, -1, 'NPC Equip 31611', 1, 44234, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31612, 2, 7, -1, 'NPC Equip 31612', 1, 44236, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31645, 13, 0, -1, 'NPC Equip 31645', -1, 22071, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31654, 2, 4, -1, 'NPC Equip 31654', 1, 44250, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31667, 2, 5, -1, 'NPC Equip 31667', 4, 44286, 0, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31669, 2, 15, -1, 'NPC Equip 31669', 1, 44289, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31738, 12, 0, -1, 'NPC Equip 31738', -1, 13082, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31743, 2, 4, -1, 'NPC Equip 31743', 2, 44370, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31767, 12, 0, -1, 'NPC Equip 31767', -1, 20774, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31771, 4, 3, -1, 'NPC Equip 31771', 5, 44431, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31801, 2, 10, -1, 'NPC Equip 31801', 2, 44489, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31803, 2, 13, -1, 'NPC Equip 31803', 1, 44491, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31805, 2, 15, -1, 'NPC Equip 31805', 1, 44497, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31806, 2, 7, -1, 'NPC Equip 31806', 1, 44498, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31822, 2, 7, -1, 'NPC Equip 31822', 1, 26572, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31842, 0, 8, -1, 'NPC Equip 31842', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31844, 0, 8, -1, 'NPC Equip 31844', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31846, 0, 8, -1, 'NPC Equip 31846', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31847, 0, 8, -1, 'NPC Equip 31847', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31848, 0, 8, -1, 'NPC Equip 31848', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31850, 4, 0, -1, 'NPC Equip 31850', 3, 31664, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31851, 4, 0, -1, 'NPC Equip 31851', 3, 31664, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31897, 15, 0, -1, 'NPC Equip 31897', -1, 31756, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31930, 4, 0, -1, 'NPC Equip 31930', 3, 36755, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31931, 4, 0, -1, 'NPC Equip 31931', 3, 31899, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31932, 4, 0, -1, 'NPC Equip 31932', 3, 39211, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31933, 4, 0, -1, 'NPC Equip 31933', 3, 39212, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31934, 4, 0, -1, 'NPC Equip 31934', 3, 9852, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31947, 12, 0, -1, 'NPC Equip 31947', -1, 41533, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31948, 12, 0, 0, 'NPC Equip 31948', -1, 40924, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31954, 0, 0, -1, 'NPC Equip 31954', -1, 13118, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (31970, 4, 2, -1, 'NPC Equip 31970', 8, 41445, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32065, 2, 0, -1, 'NPC Equip 32065', 1, 44690, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32066, 2, 0, -1, 'NPC Equip 32066', 1, 44691, 22, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32075, 12, 0, 0, 'NPC Equip 32075', -1, 9129, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32091, 2, 4, -1, 'NPC Equip 32091', -1, 32332, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32191, 4, 0, -1, 'NPC Equip 32191', 7, 42092, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32246, 2, 4, -1, 'NPC Equip 32246', 2, 44728, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32272, 2, 7, -1, 'NPC Equip 32272', 1, 44738, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32322, 4, 0, -1, 'NPC Equip 32322', 2, 44765, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32360, 2, 10, -1, 'NPC Equip 32360', 2, 44776, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32371, 2, 6, -1, 'NPC Equip 32371', 1, 44787, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32372, 12, 0, 0, 'NPC Equip 32372', -1, 36540, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32384, 2, 7, -1, 'NPC Equip 32384', 4, 31867, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32424, 0, 0, -1, 'NPC Equip 32424', 3, 18102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32425, 2, 7, -1, 'NPC Equip 32425', 1, 44850, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32426, 0, 0, -1, 'NPC Equip 32426', 3, 7264, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32448, 2, 6, -1, 'NPC Equip 32448', 1, 44855, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32457, 12, 0, 0, 'NPC Equip 32457', 0, 7887, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32460, 2, 8, -1, 'NPC Equip 32460', 1, 44892, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32463, 2, 4, -1, 'NPC Equip 32463', 1, 44932, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32477, 2, 13, -1, 'NPC Equip 32477', 1, 34296, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32484, 2, 7, -1, 'NPC Equip 32484', 1, 44955, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32499, 2, 5, -1, 'NPC Equip 32499', 2, 45630, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32504, 2, 13, -1, 'NPC Equip 32504', 1, 44971, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32507, 2, 6, -1, 'NPC Equip 32507', 2, 45510, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32511, 9, 10, -1, 'NPC Equip 32511', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32530, 2, 6, -1, 'NPC Equip 32530', 1, 45011, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32562, 2, 15, -1, 'NPC Equip 32562', 1, 45059, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32565, 2, 1, -1, 'NPC Equip 32565', 1, 45060, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32603, 2, 8, -1, 'NPC Equip 32603', 1, 45069, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32604, 2, 0, -1, 'NPC Equip 32604', 1, 45073, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32605, 2, 10, -1, 'NPC Equip 32605', 1, 45087, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32607, 2, 10, -1, 'NPC Equip 32607', 1, 45095, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32610, 2, 10, -1, 'NPC Equip 32610', 2, 45096, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32611, 2, 4, -1, 'NPC Equip 32611', 1, 45396, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32612, 2, 1, -1, 'NPC Equip 32612', 1, 45110, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32613, 2, 2, -1, 'NPC Equip 32613', 1, 45111, 15, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32614, 2, 8, -1, 'NPC Equip 32614', 1, 45118, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32632, 2, 7, -1, 'NPC Equip 32632', 1, 45150, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32644, 2, 4, -1, 'NPC Equip 32644', 2, 22178, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32669, 0, 0, -1, 'NPC Equip 32669', -1, 45198, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32699, 2, 1, -1, 'NPC Equip 32699', 1, 45308, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32719, 2, 4, -1, 'NPC Equip 32719', 1, 45367, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32729, 2, 6, -1, 'NPC Equip 32729', 1, 45392, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32730, 2, 2, -1, 'NPC Equip 32730', 2, 45393, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32731, 2, 15, -1, 'NPC Equip 32731', 1, 36036, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32740, 2, 16, -1, 'NPC Equip 32740', 1, 45416, 26, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32743, 2, 0, -1, 'NPC Equip 32743', 1, 43355, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32775, 0, 8, -1, 'NPC Equip 32775', -1, 12310, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32815, 4, 2, -1, 'NPC Equip 32815', 8, 30804, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32826, 2, 2, -1, 'NPC Equip 32826', 2, 43383, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32827, 2, 2, -1, 'NPC Equip 32827', 2, 45469, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32855, 3, 6, -1, 'NPC Equip 32855', -1, 39205, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32856, 2, 15, -1, 'NPC Equip 32856', 1, 45497, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32873, 2, 10, -1, 'NPC Equip 32873', 2, 45509, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32874, 2, 7, -1, 'NPC Equip 32874', 1, 45518, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32875, 2, 1, -1, 'NPC Equip 32875', 1, 45526, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32876, 2, 18, -1, 'NPC Equip 32876', 1, 45530, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32877, 2, 13, -1, 'NPC Equip 32877', 1, 45585, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32878, 2, 13, -1, 'NPC Equip 32878', 1, 45549, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32879, 2, 8, -1, 'NPC Equip 32879', 1, 45544, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32880, 6, 3, -1, 'NPC Equip 32880', 6, 45547, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32881, 6, 3, -1, 'NPC Equip 32881', 6, 45547, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32884, 2, 10, -1, 'NPC Equip 32884', 1, 45557, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32885, 4, 6, -1, 'NPC Equip 32885', 1, 45559, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32886, 2, 0, -1, 'NPC Equip 32886', 1, 45560, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32887, 2, 0, -1, 'NPC Equip 32887', 1, 45564, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32889, 2, 7, -1, 'NPC Equip 32889', 1, 45568, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32890, 2, 7, -1, 'NPC Equip 32890', 1, 45569, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32891, 4, 6, -1, 'NPC Equip 32891', 1, 45580, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32892, 2, 4, -1, 'NPC Equip 32892', 1, 45579, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32893, 2, 10, -1, 'NPC Equip 32893', 1, 45595, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32894, 2, 15, -1, 'NPC Equip 32894', 1, 45594, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32908, 12, 0, -1, 'NPC Equip 32908', -1, 45613, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32913, 0, 0, -1, 'NPC Equip 32913', 3, 18115, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32916, 12, 0, 0, 'NPC Equip 32916', -1, 8927, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32921, 15, 0, -1, 'NPC Equip 32921', 4, 33469, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32922, 2, 8, -1, 'NPC Equip 32922', 1, 45632, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32923, 2, 15, -1, 'NPC Equip 32923', 1, 45633, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32924, 2, 6, -1, 'NPC Equip 32924', 1, 45634, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32925, 2, 8, -1, 'NPC Equip 32925', 1, 45635, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32926, 2, 15, -1, 'NPC Equip 32926', 1, 45636, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32927, 2, 15, -1, 'NPC Equip 32927', 1, 45637, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32928, 2, 8, -1, 'NPC Equip 32928', 1, 45638, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32929, 2, 15, -1, 'NPC Equip 32929', 1, 45639, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32930, 2, 8, -1, 'NPC Equip 32930', 1, 45640, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32931, 2, 15, -1, 'NPC Equip 32931', 1, 45641, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32932, 2, 8, -1, 'NPC Equip 32932', 1, 45642, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32933, 2, 15, -1, 'NPC Equip 32933', 1, 45643, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32934, 2, 8, -1, 'NPC Equip 32934', 1, 45644, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32935, 2, 8, -1, 'NPC Equip 32935', 1, 45645, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32936, 2, 15, -1, 'NPC Equip 32936', 1, 45646, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32937, 2, 15, -1, 'NPC Equip 32937', 1, 45647, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32938, 2, 8, -1, 'NPC Equip 32938', 1, 45648, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32939, 2, 15, -1, 'NPC Equip 32939', 1, 45649, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32940, 2, 8, -1, 'NPC Equip 32940', 1, 45650, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32951, 2, 8, 8, 'NPC Equip 32951', 6, 45692, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32952, 0, 8, -1, 'NPC Equip 32952', 8, 7899, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32953, 2, 8, -1, 'NPC Equip 32953', 0, 45777, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32965, 0, 8, 0, 'NPC Equip 32965', 0, 45808, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32966, 0, 8, 0, 'NPC Equip 32966', 0, 20874, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32967, 0, 8, 0, 'NPC Equip 32967', 0, 45809, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32968, 4, 3, -1, 'NPC Equip 32968', 5, 7118, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32969, 4, 3, -1, 'NPC Equip 32969', 5, 45827, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (32970, 4, 3, -1, 'NPC Equip 32970', 5, 45828, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33000, 4, 4, -1, 'NPC Equip 33000', 6, 29860, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33001, 12, 0, 0, 'NPC Equip 33001', -1, 35023, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33002, 2, 10, -1, 'NPC Equip 33002', 2, 45887, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33003, 4, 0, -1, 'NPC Equip 33003', 4, 35442, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33005, 4, 3, 0, 'NPC Equip 33005', 0, 45896, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33011, 2, 14, -1, 'NPC Equip 33011', 1, 10822, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33022, 15, 0, -1, 'NPC Equip 33022', 4, 33469, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33027, 4, 1, -1, 'NPC Equip 33027', 1, 51619, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33046, 4, 0, -1, 'NPC Equip 33046', -1, 37840, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33049, 2, 0, -1, 'NPC Equip 33049', 1, 45945, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33059, 4, 0, -1, 'NPC Equip 33059', 5, 39129, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33062, 15, 0, -1, 'NPC Equip 33062', -1, 47446, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33073, 4, 1, 0, 'NPC Equip 33073', 0, 46034, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33074, 4, 1, 0, 'NPC Equip 33074', 0, 46037, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33075, 4, 1, 0, 'NPC Equip 33075', 0, 46038, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33090, 0, 0, -1, 'NPC Equip 33090', -1, 21473, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33094, 2, 0, -1, 'NPC Equip 33094', 1, 5122, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33097, 4, 0, -1, 'NPC Equip 33097', 1, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33100, 0, 0, 0, 'NPC Equip 33100', -1, 46200, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33104, 4, 0, -1, 'NPC Equip 33104', 1, 46210, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33116, 2, 1, -1, 'NPC Equip 33116', 1, 46231, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33118, 4, 1, -1, 'NPC Equip 33118', 7, 40622, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33125, 2, 14, -1, 'NPC Equip 33125', 1, 46247, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33128, 15, 0, -1, 'NPC Equip 33128', -1, 46249, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33130, 3, 0, -1, 'NPC Equip 33130', -1, 44920, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33136, 3, 1, -1, 'NPC Equip 33136', -1, 44930, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33145, 9, 10, -1, 'NPC Equip 33145', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33146, 15, 0, -1, 'NPC Equip 33146', -1, 39635, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33161, 2, 14, -1, 'NPC Equip 33161', 1, 46260, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33162, 4, 0, -1, 'NPC Equip 33162', 2, 46260, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33167, 15, 0, -1, 'NPC Equip 33167', -1, 46298, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33168, 2, 4, -1, 'NPC Equip 33168', 2, 46294, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33169, 2, 0, -1, 'NPC Equip 33169', 2, 46424, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33170, 2, 10, -1, 'NPC Equip 33170', 1, 46369, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33171, 2, 0, -1, 'NPC Equip 33171', 1, 46297, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33172, 2, 8, -1, 'NPC Equip 33172', 1, 46322, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33177, 2, 1, -1, 'NPC Equip 33177', 1, 46331, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33178, 2, 1, -1, 'NPC Equip 33178', 1, 46523, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33179, 15, 0, -1, 'NPC Equip 33179', -1, 46325, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33180, 2, 8, -1, 'NPC Equip 33180', 1, 20640, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33181, 4, 6, -1, 'NPC Equip 33181', 1, 46336, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33193, 4, 0, -1, 'NPC Equip 33193', 1, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33194, 4, 0, -1, 'NPC Equip 33194', 1, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33195, 4, 0, -1, 'NPC Equip 33195', 1, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33196, 4, 0, -1, 'NPC Equip 33196', 1, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33198, 4, 0, -1, 'NPC Equip 33198', 1, 9852, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33199, 4, 0, -1, 'NPC Equip 33199', 1, 9858, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33200, 4, 0, -1, 'NPC Equip 33200', 1, 9858, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33201, 4, 0, -1, 'NPC Equip 33201', 1, 31603, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33210, 4, 6, -1, 'NPC Equip 33210', 1, 46383, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33212, 4, 6, -1, 'NPC Equip 33212', 1, 46413, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33213, 2, 8, -1, 'NPC Equip 33213', 1, 46410, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33217, 0, 0, 0, 'NPC Equip 33217', -1, 3225, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33220, 4, 6, -1, 'NPC Equip 33220', 1, 46425, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33227, 4, 0, 0, 'NPC Equip 33227', 0, 46427, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33275, 2, 8, -1, 'NPC Equip 33275', 1, 46485, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33276, 2, 1, -1, 'NPC Equip 33276', 2, 46486, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33288, 15, 0, -1, 'NPC Equip 33288', -1, 46195, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33294, 4, 6, 0, 'NPC Equip 33294', 0, 46520, 14, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33295, 2, 7, -1, 'NPC Equip 33295', 1, 41333, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33301, 2, 1, -1, 'NPC Equip 33301', 2, 46522, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33302, 15, 0, -1, 'NPC Equip 33302', -1, 7280, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33318, 2, 0, -1, 'NPC Equip 33318', 1, 7590, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33319, 2, 1, -1, 'NPC Equip 33319', 1, 46588, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33320, 2, 0, -1, 'NPC Equip 33320', 1, 46589, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33338, 2, 16, -1, 'NPC Equip 33338', 1, 46602, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33353, 12, 0, 0, 'NPC Equip 33353', -1, 39723, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33442, 12, 0, 3, 'NPC Equip 33442', 1, 47710, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33456, 13, 0, -1, 'NPC Equip 33456', -1, 20802, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33511, 2, 5, -1, 'NPC Equip 33511', 2, 46691, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33521, 2, 5, -1, 'NPC Equip 33521', 2, 46692, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33525, 2, 13, -1, 'NPC Equip 33525', 1, 46693, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33526, 2, 13, -1, 'NPC Equip 33526', 1, 46694, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33542, 2, 0, -1, 'NPC Equip 33542', 1, 40066, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33543, 2, 15, -1, 'NPC Equip 33543', 1, 40937, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33544, 2, 0, 0, 'NPC Equip 33544', 2, 46700, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33564, 15, 0, -1, 'NPC Equip 33564', -1, 16065, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33565, 15, 0, -1, 'NPC Equip 33565', -1, 16065, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33570, 0, 0, 0, 'NPC Equip 33570', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33572, 0, 0, 0, 'NPC Equip 33572', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33573, 0, 0, 0, 'NPC Equip 33573', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33574, 0, 0, 0, 'NPC Equip 33574', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33594, 2, 0, 0, 'NPC Equip 33594', 2, 46750, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33595, 2, 4, 4, 'NPC Equip 33595', 2, 46751, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33596, 4, 6, 0, 'NPC Equip 33596', -1, 46752, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33597, 2, 1, 1, 'NPC Equip 33597', 2, 46748, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33598, 2, 6, 6, 'NPC Equip 33598', 2, 46753, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33600, 0, 0, 0, 'NPC Equip 33600', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33601, 0, 0, 0, 'NPC Equip 33601', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33602, 0, 0, 0, 'NPC Equip 33602', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33603, 0, 0, 0, 'NPC Equip 33603', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33608, 2, 10, 10, 'NPC Equip 33608', 2, 46769, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33609, 2, 7, 7, 'NPC Equip 33609', 2, 46770, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33623, 0, 0, 0, 'NPC Equip 33623', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33624, 0, 0, 0, 'NPC Equip 33624', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33625, 0, 0, 0, 'NPC Equip 33625', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33626, 0, 0, 0, 'NPC Equip 33626', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33633, 3, 6, -1, 'NPC Equip 33633', -1, 39203, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33636, 4, 1, -1, 'NPC Equip 33636', 7, 45714, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33641, 4, 6, -1, 'NPC Equip 33641', 1, 42376, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33642, 2, 4, -1, 'NPC Equip 33642', 1, 39278, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33643, 2, 5, -1, 'NPC Equip 33643', 1, 41558, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33644, 4, 3, -1, 'NPC Equip 33644', 5, 45963, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33645, 4, 3, -1, 'NPC Equip 33645', 5, 45964, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33646, 4, 3, -1, 'NPC Equip 33646', 5, 45965, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33647, 4, 3, -1, 'NPC Equip 33647', 5, 45966, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33648, 4, 3, -1, 'NPC Equip 33648', 5, 45967, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33649, 2, 0, -1, 'NPC Equip 33649', 1, 41559, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33650, 2, 1, -1, 'NPC Equip 33650', 1, 41560, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33651, 4, 2, -1, 'NPC Equip 33651', 8, 45993, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33652, 4, 2, -1, 'NPC Equip 33652', 8, 45998, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33653, 4, 2, -1, 'NPC Equip 33653', 8, 46347, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33654, 4, 2, -1, 'NPC Equip 33654', 8, 45996, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33655, 4, 2, -1, 'NPC Equip 33655', 8, 45997, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33656, 4, 1, -1, 'NPC Equip 33656', 7, 45974, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33657, 4, 1, -1, 'NPC Equip 33657', 7, 45975, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33658, 4, 1, -1, 'NPC Equip 33658', 7, 46107, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33659, 4, 1, -1, 'NPC Equip 33659', 7, 45976, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33660, 4, 4, -1, 'NPC Equip 33660', 1, 42651, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33772, 4, 4, -1, 'NPC Equip 33772', 6, 46012, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33773, 2, 8, 8, 'NPC Equip 33773', 2, 49657, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33775, 15, 0, -1, 'NPC Equip 33775', -1, 6358, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33776, 15, 0, -1, 'NPC Equip 33776', -1, 6358, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33777, 15, 0, -1, 'NPC Equip 33777', -1, 6358, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33785, 0, 0, 0, 'NPC Equip 33785', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33786, 0, 0, 0, 'NPC Equip 33786', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33787, 0, 0, 0, 'NPC Equip 33787', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33788, 0, 0, 0, 'NPC Equip 33788', 0, 46712, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33789, 4, 6, -1, 'NPC Equip 33789', 1, 46831, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33790, 2, 0, -1, 'NPC Equip 33790', 1, 46832, 26, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33793, 2, 4, -1, 'NPC Equip 33793', 2, 46840, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33795, 2, 10, -1, 'NPC Equip 33795', 2, 46863, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33798, 2, 10, -1, 'NPC Equip 33798', 2, 46916, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33799, 4, 0, -1, 'NPC Equip 33799', -1, 45840, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33800, 0, 0, 0, 'NPC Equip 33800', -1, 46560, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33802, 12, 0, 0, 'NPC Equip 33802', 4, 38757, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33807, 12, 0, -1, 'NPC Equip 33807', -1, 13082, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33817, 15, 2, -1, 'NPC Equip 33817', -1, 33467, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33822, 0, 5, -1, 'NPC Equip 33822', -1, 1208, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33845, 4, 0, -1, 'NPC Equip 33845', -1, 34732, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33958, 4, 0, -1, 'NPC Equip 33958', 3, 47144, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33963, 2, 14, -1, 'NPC Equip 33963', 1, 47311, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33975, 2, 13, 13, 'NPC Equip 33975', 0, 47174, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33979, 2, 5, 5, 'NPC Equip 33979', -1, 47188, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33980, 2, 0, 0, 'NPC Equip 33980', -1, 47192, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33981, 2, 0, 0, 'NPC Equip 33981', -1, 47198, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33982, 2, 0, 0, 'NPC Equip 33982', -1, 47207, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33983, 2, 10, 10, 'NPC Equip 33983', -1, 47212, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33984, 2, 7, 7, 'NPC Equip 33984', -1, 47225, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33986, 4, 0, -1, 'NPC Equip 33986', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33988, 4, 0, -1, 'NPC Equip 33988', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33989, 4, 0, -1, 'NPC Equip 33989', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33990, 2, 7, 7, 'NPC Equip 33990', -1, 47230, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33991, 2, 2, 2, 'NPC Equip 33991', -1, 47228, 26, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33992, 2, 7, 7, 'NPC Equip 33992', -1, 47229, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33994, 4, 0, -1, 'NPC Equip 33994', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33995, 4, 0, -1, 'NPC Equip 33995', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33996, 4, 0, -1, 'NPC Equip 33996', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (33998, 4, 0, -1, 'NPC Equip 33998', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34004, 4, 0, -1, 'NPC Equip 34004', -1, 50845, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34005, 4, 0, -1, 'NPC Equip 34005', -1, 50842, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34006, 4, 0, -1, 'NPC Equip 34006', -1, 50843, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34007, 4, 0, -1, 'NPC Equip 34007', -1, 50844, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34034, 2, 3, -1, 'NPC Equip 34034', 1, 47277, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34036, 4, 0, -1, 'NPC Equip 34036', 3, 7899, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34037, 4, 0, -1, 'NPC Equip 34037', 3, 7899, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34038, 4, 0, -1, 'NPC Equip 34038', 3, 7899, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34039, 2, 2, -1, 'NPC Equip 34039', 2, 30926, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34045, 2, 15, 15, 'NPC Equip 34045', -1, 47285, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34046, 0, 0, 0, 'NPC Equip 34046', 0, 47291, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34047, 0, 0, 0, 'NPC Equip 34047', 0, 47293, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34048, 0, 0, 0, 'NPC Equip 34048', 0, 4933, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34058, 2, 6, 6, 'NPC Equip 34058', 2, 46753, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34071, 0, 0, 0, 'NPC Equip 34071', -1, 46266, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34072, 12, 0, -1, 'NPC Equip 34072', 7, 23161, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34079, 2, 10, -1, 'NPC Equip 34079', 2, 47346, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34080, 2, 0, -1, 'NPC Equip 34080', 1, 36381, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34093, 2, 1, -1, 'NPC Equip 34093', 1, 39902, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34094, 4, 0, -1, 'NPC Equip 34094', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34095, 4, 0, -1, 'NPC Equip 34095', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34096, 2, 1, -1, 'NPC Equip 34096', 1, 47439, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34097, 2, 1, -1, 'NPC Equip 34097', 1, 47440, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34098, 2, 3, -1, 'NPC Equip 34098', 1, 47444, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34103, 9, 1, -1, 'NPC Equip 34103', -1, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34104, 9, 1, -1, 'NPC Equip 34104', -1, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34108, 12, 0, 0, 'NPC Equip 34108', -1, 47460, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34110, 9, 8, -1, 'NPC Equip 34110', -1, 7798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34150, 15, 0, -1, 'NPC Equip 34150', -1, 47917, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34151, 0, 0, 0, 'NPC Equip 34151', 0, 47507, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34152, 0, 0, 0, 'NPC Equip 34152', 0, 47508, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34153, 0, 0, 0, 'NPC Equip 34153', 0, 47509, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34154, 0, 0, 0, 'NPC Equip 34154', 0, 47510, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34155, 0, 0, 0, 'NPC Equip 34155', 0, 47511, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34156, 0, 0, 0, 'NPC Equip 34156', -1, 47512, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34159, 4, 0, -1, 'NPC Equip 34159', 7, 44440, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34161, 12, 0, -1, 'NPC Equip 34161', -1, 7111, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34217, 4, 6, -1, 'NPC Equip 34217', 1, 47534, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34250, 0, 0, 0, 'NPC Equip 34250', 0, 4233, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34251, 0, 0, 0, 'NPC Equip 34251', 0, 24591, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34252, 0, 0, 0, 'NPC Equip 34252', 0, 47577, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34260, 12, 0, 0, 'NPC Equip 34260', -1, 6748, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34263, 2, 2, -1, 'NPC Equip 34263', 2, 47630, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34264, 2, 2, -1, 'NPC Equip 34264', 2, 47631, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34265, 2, 2, -1, 'NPC Equip 34265', 2, 47632, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34266, 2, 2, -1, 'NPC Equip 34266', 2, 47633, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34267, 2, 2, -1, 'NPC Equip 34267', 2, 47634, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34268, 2, 2, -1, 'NPC Equip 34268', 2, 47636, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34269, 2, 2, -1, 'NPC Equip 34269', 2, 47637, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34270, 2, 2, -1, 'NPC Equip 34270', 2, 47638, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34271, 2, 2, -1, 'NPC Equip 34271', 2, 47639, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34272, 2, 2, -1, 'NPC Equip 34272', 2, 47640, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34273, 2, 2, -1, 'NPC Equip 34273', 2, 43880, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34274, 2, 2, -1, 'NPC Equip 34274', 2, 47641, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34275, 2, 2, -1, 'NPC Equip 34275', 2, 47642, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34276, 2, 2, -1, 'NPC Equip 34276', 2, 47643, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34277, 2, 2, -1, 'NPC Equip 34277', 2, 43383, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34278, 2, 2, -1, 'NPC Equip 34278', 2, 47644, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34279, 2, 2, -1, 'NPC Equip 34279', 2, 47645, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34280, 2, 2, -1, 'NPC Equip 34280', 2, 45469, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34281, 2, 2, -1, 'NPC Equip 34281', 2, 43519, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34282, 2, 7, -1, 'NPC Equip 34282', 1, 47646, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34283, 2, 7, -1, 'NPC Equip 34283', 1, 47647, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34284, 2, 7, -1, 'NPC Equip 34284', 1, 47648, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34285, 2, 7, -1, 'NPC Equip 34285', 1, 47649, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34286, 2, 7, -1, 'NPC Equip 34286', 1, 47650, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34287, 2, 8, -1, 'NPC Equip 34287', 1, 47653, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34288, 2, 7, -1, 'NPC Equip 34288', 1, 47652, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34289, 2, 8, -1, 'NPC Equip 34289', 1, 47654, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34290, 2, 8, -1, 'NPC Equip 34290', 1, 47655, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34291, 2, 8, -1, 'NPC Equip 34291', 1, 47656, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34292, 2, 8, -1, 'NPC Equip 34292', 1, 47657, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34293, 2, 8, -1, 'NPC Equip 34293', 1, 47658, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34294, 2, 8, -1, 'NPC Equip 34294', 1, 47659, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34295, 2, 8, -1, 'NPC Equip 34295', 1, 47660, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34296, 2, 8, -1, 'NPC Equip 34296', 1, 47661, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34297, 2, 8, -1, 'NPC Equip 34297', 1, 47662, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34298, 2, 8, -1, 'NPC Equip 34298', 1, 47663, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34299, 2, 8, -1, 'NPC Equip 34299', 1, 47664, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34300, 2, 8, -1, 'NPC Equip 34300', 1, 47665, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34301, 2, 8, -1, 'NPC Equip 34301', 1, 47666, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34302, 2, 8, -1, 'NPC Equip 34302', 1, 47667, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34303, 2, 8, -1, 'NPC Equip 34303', 1, 47668, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34304, 2, 8, -1, 'NPC Equip 34304', 1, 47669, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34305, 2, 8, -1, 'NPC Equip 34305', 1, 47670, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34306, 2, 8, -1, 'NPC Equip 34306', 1, 47671, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34307, 2, 8, -1, 'NPC Equip 34307', 1, 47672, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34308, 2, 8, -1, 'NPC Equip 34308', 1, 47673, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34309, 2, 8, -1, 'NPC Equip 34309', 1, 47674, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34310, 2, 8, -1, 'NPC Equip 34310', 1, 47675, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34311, 2, 8, -1, 'NPC Equip 34311', 1, 47676, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34312, 2, 18, -1, 'NPC Equip 34312', 1, 37194, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34313, 2, 18, -1, 'NPC Equip 34313', 1, 47677, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34314, 2, 18, -1, 'NPC Equip 34314', 1, 47678, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34315, 2, 18, -1, 'NPC Equip 34315', 1, 47679, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34316, 2, 18, -1, 'NPC Equip 34316', 1, 47680, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34317, 2, 18, -1, 'NPC Equip 34317', 1, 47681, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34318, 2, 18, -1, 'NPC Equip 34318', 1, 47682, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34320, 2, 18, -1, 'NPC Equip 34320', 1, 47683, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34321, 2, 18, -1, 'NPC Equip 34321', 1, 47684, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34322, 2, 18, -1, 'NPC Equip 34322', 1, 47685, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34323, 2, 18, -1, 'NPC Equip 34323', 1, 47686, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34324, 2, 7, -1, 'NPC Equip 34324', 1, 47687, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34325, 2, 18, -1, 'NPC Equip 34325', 1, 45530, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34326, 2, 18, -1, 'NPC Equip 34326', 1, 47688, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34327, 2, 18, -1, 'NPC Equip 34327', 1, 47689, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34328, 2, 18, -1, 'NPC Equip 34328', 1, 47690, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34449, 2, 15, -1, 'NPC Equip 34449', 1, 47711, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34450, 2, 15, -1, 'NPC Equip 34450', 1, 47712, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34451, 2, 15, -1, 'NPC Equip 34451', 1, 47713, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34452, 2, 15, -1, 'NPC Equip 34452', 1, 39978, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34453, 2, 15, -1, 'NPC Equip 34453', 1, 47714, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34454, 2, 15, -1, 'NPC Equip 34454', 1, 47715, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34455, 2, 15, -1, 'NPC Equip 34455', 1, 47716, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34456, 2, 15, -1, 'NPC Equip 34456', 1, 47717, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34457, 2, 15, -1, 'NPC Equip 34457', 1, 47718, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34458, 2, 15, -1, 'NPC Equip 34458', 1, 47719, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34459, 2, 15, -1, 'NPC Equip 34459', 1, 47720, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34460, 2, 15, -1, 'NPC Equip 34460', 1, 47721, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34461, 2, 15, -1, 'NPC Equip 34461', 1, 47722, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34462, 2, 15, -1, 'NPC Equip 34462', 1, 47723, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34463, 2, 15, -1, 'NPC Equip 34463', 1, 47724, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34464, 1, 2, -1, 'NPC Equip 34464', 8, 34779, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34465, 7, 9, -1, 'NPC Equip 34465', 7, 19495, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34466, 1, 4, -1, 'NPC Equip 34466', 8, 36511, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34481, 9, 6, -1, 'NPC Equip 34481', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34495, 15, 2, -1, 'NPC Equip 34495', -1, 19115, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34496, 15, 0, 0, 'NPC Equip 34496', 0, 8117, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34503, 15, 0, 0, 'NPC Equip 34503', -1, 12331, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34505, 2, 7, -1, 'NPC Equip 34505', 1, 47802, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34506, 2, 0, -1, 'NPC Equip 34506', 1, 47803, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34507, 2, 0, -1, 'NPC Equip 34507', 1, 47804, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34508, 2, 0, -1, 'NPC Equip 34508', 1, 47805, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34509, 2, 0, -1, 'NPC Equip 34509', 1, 47806, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34510, 2, 0, -1, 'NPC Equip 34510', 1, 47807, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34511, 2, 0, -1, 'NPC Equip 34511', 1, 47808, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34512, 2, 0, -1, 'NPC Equip 34512', 1, 47809, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34513, 2, 0, -1, 'NPC Equip 34513', 1, 47810, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34514, 2, 0, -1, 'NPC Equip 34514', 1, 47811, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34515, 2, 0, -1, 'NPC Equip 34515', 1, 47812, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34516, 2, 4, -1, 'NPC Equip 34516', 2, 39488, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34517, 2, 4, -1, 'NPC Equip 34517', 2, 39004, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34520, 2, 0, -1, 'NPC Equip 34520', 1, 47818, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34521, 2, 0, -1, 'NPC Equip 34521', 1, 47819, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34522, 2, 0, -1, 'NPC Equip 34522', 1, 47820, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34523, 2, 0, -1, 'NPC Equip 34523', 1, 47821, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34524, 2, 0, -1, 'NPC Equip 34524', 1, 47822, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34525, 2, 0, -1, 'NPC Equip 34525', 1, 47823, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34526, 2, 0, -1, 'NPC Equip 34526', 1, 47824, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34531, 2, 7, -1, 'NPC Equip 34531', 1, 47879, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34532, 4, 6, -1, 'NPC Equip 34532', 1, 47908, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34534, 6, 3, -1, 'NPC Equip 34534', 2, 23211, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34536, 2, 5, -1, 'NPC Equip 34536', 2, 47894, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34550, 4, 0, -1, 'NPC Equip 34550', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34551, 4, 0, -1, 'NPC Equip 34551', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34552, 2, 7, -1, 'NPC Equip 34552', 1, 47909, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34553, 4, 6, -1, 'NPC Equip 34553', 1, 47911, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34586, 4, 6, -1, 'NPC Equip 34586', 1, 47920, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34588, 4, 6, -1, 'NPC Equip 34588', 1, 47907, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34596, 2, 7, -1, 'NPC Equip 34596', 1, 47923, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34626, 7, 3, -1, 'NPC Equip 34626', -1, 44269, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34628, 15, 0, -1, 'NPC Equip 34628', -1, 41438, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34629, 15, 0, -1, 'NPC Equip 34629', -1, 41438, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34630, 15, 0, -1, 'NPC Equip 34630', -1, 41438, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34631, 15, 0, -1, 'NPC Equip 34631', -1, 41440, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34632, 15, 0, -1, 'NPC Equip 34632', -1, 41440, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34633, 15, 0, -1, 'NPC Equip 34633', -1, 41440, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34634, 15, 0, -1, 'NPC Equip 34634', -1, 41441, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34635, 15, 0, -1, 'NPC Equip 34635', -1, 41441, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34636, 15, 0, -1, 'NPC Equip 34636', -1, 41441, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34637, 2, 0, -1, 'NPC Equip 34637', 2, 47970, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34638, 2, 1, -1, 'NPC Equip 34638', 1, 47971, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34639, 2, 5, -1, 'NPC Equip 34639', 2, 47972, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34640, 2, 7, -1, 'NPC Equip 34640', 1, 47973, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34641, 0, 3, -1, 'NPC Equip 34641', 3, 15736, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34642, 7, 11, -1, 'NPC Equip 34642', 3, 2873, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34643, 7, 11, -1, 'NPC Equip 34643', 2, 19572, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34644, 7, 11, -1, 'NPC Equip 34644', 3, 47978, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34646, 0, 1, 0, 'NPC Equip 34646', -1, 48901, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34654, 4, 4, -1, 'NPC Equip 34654', 6, 33117, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34660, 7, 11, -1, 'NPC Equip 34660', 3, 47978, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34662, 2, 16, -1, 'NPC Equip 34662', 1, 40411, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34668, 2, 1, -1, 'NPC Equip 34668', 1, 3243, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34681, 2, 6, -1, 'NPC Equip 34681', 1, 48076, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34682, 2, 7, -1, 'NPC Equip 34682', 1, 48075, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34687, 12, 0, -1, 'NPC Equip 34687', -1, 3018, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34693, 2, 8, -1, 'NPC Equip 34693', 1, 48192, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34696, 2, 7, -1, 'NPC Equip 34696', 1, 48199, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34712, 4, 0, -1, 'NPC Equip 34712', -1, 9837, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34717, 4, 0, -1, 'NPC Equip 34717', 2, 48229, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34723, 7, 8, -1, 'NPC Equip 34723', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34724, 7, 8, -1, 'NPC Equip 34724', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34725, 7, 8, -1, 'NPC Equip 34725', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34726, 7, 8, -1, 'NPC Equip 34726', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34727, 7, 8, -1, 'NPC Equip 34727', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34728, 7, 8, -1, 'NPC Equip 34728', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34729, 7, 8, -1, 'NPC Equip 34729', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34730, 7, 8, -1, 'NPC Equip 34730', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34731, 7, 8, -1, 'NPC Equip 34731', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34732, 7, 8, -1, 'NPC Equip 34732', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34733, 7, 8, -1, 'NPC Equip 34733', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34734, 7, 8, -1, 'NPC Equip 34734', -1, 24704, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34770, 0, 5, -1, 'NPC Equip 34770', -1, 39114, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34771, 2, 10, -1, 'NPC Equip 34771', 2, 48239, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34776, 4, 0, -1, 'NPC Equip 34776', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34803, 12, 0, 0, 'NPC Equip 34803', -1, 42490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34805, 4, 0, -1, 'NPC Equip 34805', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34816, 2, 0, 0, 'NPC Equip 34816', 0, 48327, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34817, 2, 1, 1, 'NPC Equip 34817', 0, 48328, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34818, 2, 5, 5, 'NPC Equip 34818', 0, 48329, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34819, 2, 4, 4, 'NPC Equip 34819', 0, 48331, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34820, 2, 8, 8, 'NPC Equip 34820', 0, 48332, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34821, 2, 7, 7, 'NPC Equip 34821', 0, 48333, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34849, 15, 0, -1, 'NPC Equip 34849', -1, 48374, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34873, 2, 2, -1, 'NPC Equip 34873', 2, 48395, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34874, 2, 6, -1, 'NPC Equip 34874', 1, 48396, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34875, 2, 15, -1, 'NPC Equip 34875', 1, 48397, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34876, 2, 8, -1, 'NPC Equip 34876', 1, 48398, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34877, 2, 10, -1, 'NPC Equip 34877', 2, 48399, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34878, 2, 10, -1, 'NPC Equip 34878', 2, 48400, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34879, 2, 7, -1, 'NPC Equip 34879', 1, 48401, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34881, 2, 14, -1, 'NPC Equip 34881', 1, 48403, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34882, 2, 10, -1, 'NPC Equip 34882', 2, 48404, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34883, 2, 0, -1, 'NPC Equip 34883', 1, 48405, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34884, 2, 10, -1, 'NPC Equip 34884', 2, 48406, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34885, 2, 4, -1, 'NPC Equip 34885', 2, 48407, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34886, 2, 7, -1, 'NPC Equip 34886', 1, 48408, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34899, 2, 10, -1, 'NPC Equip 34899', 2, 48416, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34965, 4, 4, -1, 'NPC Equip 34965', 1, 47022, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34966, 4, 4, -1, 'NPC Equip 34966', 1, 47022, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34969, 4, 4, -1, 'NPC Equip 34969', 8, 15305, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (34970, 4, 4, -1, 'NPC Equip 34970', 8, 15305, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35117, 2, 7, -1, 'NPC Equip 35117', 1, 48521, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35118, 12, 0, 0, 'NPC Equip 35118', 0, 32777, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35120, 0, 0, 0, 'NPC Equip 35120', 0, 50273, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35124, 12, 0, 0, 'NPC Equip 35124', 0, 32777, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35220, 2, 10, -1, 'NPC Equip 35220', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35235, 2, 6, -1, 'NPC Equip 35235', 1, 48667, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35236, 2, 8, -1, 'NPC Equip 35236', 1, 48680, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35274, 4, 0, -1, 'NPC Equip 35274', 3, 34149, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35312, 2, 13, -1, 'NPC Equip 35312', 1, 48712, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35351, 15, 0, -1, 'NPC Equip 35351', -1, 42378, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35463, 2, 0, -1, 'NPC Equip 35463', 1, 48806, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35480, 12, 0, -1, 'NPC Equip 35480', -1, 1134, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35482, 12, 0, -1, 'NPC Equip 35482', -1, 3426, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35485, 4, 0, -1, 'NPC Equip 35485', 8, 40556, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35499, 7, 2, -1, 'NPC Equip 35499', 6, 25482, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35510, 2, 7, -1, 'NPC Equip 35510', 1, 48875, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35515, 2, 7, 7, 'NPC Equip 35515', 4, 48879, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35534, 9, 10, -1, 'NPC Equip 35534', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35536, 9, 10, -1, 'NPC Equip 35536', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35540, 9, 1, -1, 'NPC Equip 35540', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35542, 9, 1, -1, 'NPC Equip 35542', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35543, 9, 1, -1, 'NPC Equip 35543', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35547, 9, 1, -1, 'NPC Equip 35547', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35552, 9, 2, -1, 'NPC Equip 35552', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35554, 9, 4, -1, 'NPC Equip 35554', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35556, 9, 4, -1, 'NPC Equip 35556', -1, 7085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35558, 12, 0, -1, 'NPC Equip 35558', -1, 3032, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35559, 2, 8, -1, 'NPC Equip 35559', 1, 48884, 21, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35560, 2, 8, -1, 'NPC Equip 35560', 1, 48884, 22, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35561, 2, 7, -1, 'NPC Equip 35561', 1, 48884, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35567, 12, 0, 0, 'NPC Equip 35567', -1, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35621, 7, 10, -1, 'NPC Equip 35621', -1, 41678, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35667, 0, 0, 0, 'NPC Equip 35667', -1, 48953, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35674, 2, 5, -1, 'NPC Equip 35674', 4, 41913, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35684, 2, 15, -1, 'NPC Equip 35684', 1, 48965, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35689, 4, 0, -1, 'NPC Equip 35689', 3, 44358, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35710, 0, 5, -1, 'NPC Equip 35710', -1, 20803, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35712, 2, 8, -1, 'NPC Equip 35712', 1, 48983, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35713, 15, 0, -1, 'NPC Equip 35713', -1, 48725, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35714, 2, 10, -1, 'NPC Equip 35714', 2, 40075, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35715, 16, 3, 0, 'NPC Equip 35715', -1, 7015, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35719, 2, 13, -1, 'NPC Equip 35719', 1, 48996, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35721, 15, 0, 0, 'NPC Equip 35721', -1, 47901, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35724, 2, 5, 5, 'NPC Equip 35724', -1, 49030, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35727, 2, 4, -1, 'NPC Equip 35727', 2, 49051, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35732, 4, 4, 0, 'NPC Equip 35732', 8, 49062, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35735, 4, 4, -1, 'NPC Equip 35735', 1, 48472, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35740, 2, 10, -1, 'NPC Equip 35740', 2, 49074, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35741, 2, 10, -1, 'NPC Equip 35741', 2, 49075, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35742, 2, 10, -1, 'NPC Equip 35742', 2, 49076, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35743, 2, 10, -1, 'NPC Equip 35743', 2, 49077, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35744, 12, 0, -1, 'NPC Equip 35744', -1, 44707, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35745, 15, 0, -1, 'NPC Equip 35745', 3, 49078, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35770, 7, 11, -1, 'NPC Equip 35770', 2, 43359, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35771, 7, 11, -1, 'NPC Equip 35771', 2, 43359, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35772, 7, 11, -1, 'NPC Equip 35772', 2, 43359, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35773, 7, 11, -1, 'NPC Equip 35773', 2, 43359, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35775, 15, 0, -1, 'NPC Equip 35775', -1, 33399, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35776, 15, 0, -1, 'NPC Equip 35776', -1, 992, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35778, 15, 0, -1, 'NPC Equip 35778', -1, 7957, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35779, 2, 0, -1, 'NPC Equip 35779', 1, 49089, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35780, 2, 7, -1, 'NPC Equip 35780', 1, 49091, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35781, 2, 10, -1, 'NPC Equip 35781', 2, 49096, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35785, 4, 2, -1, 'NPC Equip 35785', 8, 49104, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35786, 4, 2, -1, 'NPC Equip 35786', 8, 49105, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35787, 15, 0, -1, 'NPC Equip 35787', -1, 31756, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35789, 12, 0, -1, 'NPC Equip 35789', -1, 31756, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35793, 2, 15, -1, 'NPC Equip 35793', 1, 45233, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35804, 2, 2, -1, 'NPC Equip 35804', 2, 49121, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35805, 2, 3, -1, 'NPC Equip 35805', 1, 49122, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35825, 16, 1, 0, 'NPC Equip 35825', 4, 37541, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35847, 12, 0, 0, 'NPC Equip 35847', 0, 49129, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35853, 12, 0, 0, 'NPC Equip 35853', -1, 2247, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35855, 12, 0, 0, 'NPC Equip 35855', -1, 49131, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35874, 1, 0, 0, 'NPC Equip 35874', 4, 34865, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35939, 2, 8, -1, 'NPC Equip 35939', 1, 49195, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35940, 12, 0, -1, 'NPC Equip 35940', -1, 46253, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (35942, 2, 10, -1, 'NPC Equip 35942', 2, 49218, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36745, 12, 0, 0, 'NPC Equip 36745', 4, 24687, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36749, 2, 7, -1, 'NPC Equip 36749', 1, 20154, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36750, 2, 10, -1, 'NPC Equip 36750', 2, 49285, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36755, 2, 2, -1, 'NPC Equip 36755', 2, 49295, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36761, 4, 0, -1, 'NPC Equip 36761', 1, 46247, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36762, 2, 18, -1, 'NPC Equip 36762', 1, 49297, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36763, 13, 0, -1, 'NPC Equip 36763', -1, 9154, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36773, 12, 0, 0, 'NPC Equip 36773', -1, 21402, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36778, 2, 6, -1, 'NPC Equip 36778', 1, 49311, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36785, 12, 0, -1, 'NPC Equip 36785', -1, 49330, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36790, 2, 6, -1, 'NPC Equip 36790', 1, 49337, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36791, 2, 6, -1, 'NPC Equip 36791', 1, 49338, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36792, 2, 6, -1, 'NPC Equip 36792', 1, 49339, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36831, 0, 5, -1, 'NPC Equip 36831', -1, 21327, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36837, 9, 8, -1, 'NPC Equip 36837', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36838, 9, 8, -1, 'NPC Equip 36838', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36839, 9, 8, -1, 'NPC Equip 36839', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36840, 9, 8, -1, 'NPC Equip 36840', -1, 9135, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36841, 9, 6, -1, 'NPC Equip 36841', -1, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36842, 9, 6, -1, 'NPC Equip 36842', -1, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36843, 9, 6, -1, 'NPC Equip 36843', -1, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36844, 9, 6, -1, 'NPC Equip 36844', -1, 1096, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36845, 0, 2, -1, 'NPC Equip 36845', 3, 17882, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36869, 2, 10, -1, 'NPC Equip 36869', 2, 49422, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36898, 7, 12, -1, 'NPC Equip 36898', 1, 56467, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36911, 7, 7, -1, 'NPC Equip 36911', 1, 38648, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36963, 9, 0, -1, 'NPC Equip 36963', -1, 1246, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36987, 7, 6, -1, 'NPC Equip 36987', 8, 49549, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (36990, 2, 7, -1, 'NPC Equip 36990', 1, 49548, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37001, 2, 7, -1, 'NPC Equip 37001', 4, 49526, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37059, 2, 14, -1, 'NPC Equip 37059', 1, 47158, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37102, 7, 1, -1, 'NPC Equip 37102', 3, 3663, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37103, 7, 13, -1, 'NPC Equip 37103', 3, 6381, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37119, 4, 6, -1, 'NPC Equip 37119', 1, 49611, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37120, 2, 4, -1, 'NPC Equip 37120', 2, 49612, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37123, 2, 8, -1, 'NPC Equip 37123', 1, 49616, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37130, 2, 16, -1, 'NPC Equip 37130', 2, 7459, 26, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37131, 4, 0, -1, 'NPC Equip 37131', -1, 49641, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37132, 4, 0, -1, 'NPC Equip 37132', -1, 49642, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37133, 4, 0, -1, 'NPC Equip 37133', -1, 49643, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37142, 4, 3, -1, 'NPC Equip 37142', 5, 42891, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37146, 2, 8, -1, 'NPC Equip 37146', 1, 49691, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37249, 2, 2, -1, 'NPC Equip 37249', 2, 49681, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37266, 2, 19, -1, 'NPC Equip 37266', 2, 49709, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37308, 2, 8, -1, 'NPC Equip 37308', 1, 49745, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37309, 6, 2, -1, 'NPC Equip 37309', 2, 41489, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37310, 2, 4, -1, 'NPC Equip 37310', 2, 49750, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37327, 9, 8, -1, 'NPC Equip 37327', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37328, 9, 8, -1, 'NPC Equip 37328', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37341, 9, 8, -1, 'NPC Equip 37341', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37342, 9, 8, -1, 'NPC Equip 37342', -1, 11431, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37531, 4, 0, -1, 'NPC Equip 37531', 8, 49225, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37532, 4, 0, -1, 'NPC Equip 37532', 8, 51243, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37533, 4, 0, -1, 'NPC Equip 37533', 3, 29697, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37549, 4, 0, -1, 'NPC Equip 37549', 3, 9858, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37550, 16, 5, 0, 'NPC Equip 37550', 0, 49722, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37551, 16, 3, 0, 'NPC Equip 37551', 0, 49819, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37552, 4, 8, -1, 'NPC Equip 37552', 2, 43316, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37553, 4, 7, -1, 'NPC Equip 37553', 2, 34960, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37554, 4, 9, -1, 'NPC Equip 37554', 2, 43317, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37561, 4, 0, -1, 'NPC Equip 37561', 4, 52821, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37563, 4, 0, -1, 'NPC Equip 37563', 8, 34188, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37578, 4, 0, -1, 'NPC Equip 37578', 8, 34188, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37589, 7, 3, -1, 'NPC Equip 37589', 8, 40557, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37596, 2, 15, -1, 'NPC Equip 37596', 1, 49873, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37600, 12, 0, -1, 'NPC Equip 37600', 8, 1464, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37605, 15, 0, 0, 'NPC Equip 37605', 4, 49881, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37608, 2, 0, 0, 'NPC Equip 37608', 0, 49891, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37609, 2, 8, -1, 'NPC Equip 37609', 1, 49892, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37610, 2, 8, -1, 'NPC Equip 37610', 1, 49893, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37709, 15, 3, -1, 'NPC Equip 37709', 4, 44269, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37720, 4, 2, -1, 'NPC Equip 37720', 8, 42947, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37738, 15, 0, -1, 'NPC Equip 37738', -1, 7134, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37832, 2, 0, -1, 'NPC Equip 37832', 1, 23904, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37834, 2, 0, -1, 'NPC Equip 37834', 1, 23904, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37838, 7, 8, -1, 'NPC Equip 37838', 4, 2618, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37866, 4, 4, -1, 'NPC Equip 37866', 6, 42849, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37885, 4, 4, -1, 'NPC Equip 37885', 6, 42831, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37914, 2, 4, 4, 'NPC Equip 37914', 2, 50213, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37916, 4, 6, -1, 'NPC Equip 37916', 1, 50214, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37917, 2, 6, -1, 'NPC Equip 37917', 1, 50215, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37919, 2, 2, -1, 'NPC Equip 37919', 2, 50451, 15, 5); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37924, 2, 15, -1, 'NPC Equip 37924', 1, 50282, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37926, 0, 1, -1, 'NPC Equip 37926', 3, 37808, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37946, 4, 1, -1, 'NPC Equip 37946', 6, 51338, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37951, 4, 1, -1, 'NPC Equip 37951', 7, 51326, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37952, 4, 0, -1, 'NPC Equip 37952', 3, 28812, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37972, 4, 1, -1, 'NPC Equip 37972', 6, 51339, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37973, 4, 1, -1, 'NPC Equip 37973', 7, 51327, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37974, 4, 1, -1, 'NPC Equip 37974', 7, 15218, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37975, 4, 1, -1, 'NPC Equip 37975', 7, 49464, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37977, 4, 1, -1, 'NPC Equip 37977', 7, 51199, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37978, 4, 1, -1, 'NPC Equip 37978', 7, 51304, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37979, 4, 1, -1, 'NPC Equip 37979', 7, 51232, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37994, 4, 2, -1, 'NPC Equip 37994', 8, 49842, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (37997, 4, 0, -1, 'NPC Equip 37997', -1, 6490, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38009, 4, 0, -1, 'NPC Equip 38009', 3, 26001, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38015, 4, 2, -1, 'NPC Equip 38015', 8, 56436, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38016, 4, 2, -1, 'NPC Equip 38016', 8, 56446, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38017, 4, 2, -1, 'NPC Equip 38017', 8, 49251, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38018, 4, 2, -1, 'NPC Equip 38018', 8, 56450, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38019, 4, 2, -1, 'NPC Equip 38019', 6, 56452, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38020, 4, 2, -1, 'NPC Equip 38020', 8, 56457, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38021, 4, 2, -1, 'NPC Equip 38021', 8, 49842, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38022, 4, 2, -1, 'NPC Equip 38022', 8, 49920, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38038, 4, 3, -1, 'NPC Equip 38038', 5, 51293, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38058, 4, 3, -1, 'NPC Equip 38058', 5, 51213, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38059, 1, 0, -1, 'NPC Equip 38059', 8, 50457, 18, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38060, 4, 3, -1, 'NPC Equip 38060', 5, 56447, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38061, 4, 3, -1, 'NPC Equip 38061', 5, 56451, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38062, 4, 3, -1, 'NPC Equip 38062', 5, 56453, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38063, 4, 3, -1, 'NPC Equip 38063', 5, 56468, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38064, 4, 3, -1, 'NPC Equip 38064', 5, 51351, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38065, 4, 3, -1, 'NPC Equip 38065', 5, 52499, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38066, 4, 3, -1, 'NPC Equip 38066', 5, 51077, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38067, 4, 0, -1, 'NPC Equip 38067', 3, 23629, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38069, 4, 0, -1, 'NPC Equip 38069', 3, 34034, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38074, 4, 0, -1, 'NPC Equip 38074', 8, 34188, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38075, 4, 0, -1, 'NPC Equip 38075', 8, 34188, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38076, 4, 0, -1, 'NPC Equip 38076', 4, 16283, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38077, 4, 0, -1, 'NPC Equip 38077', 8, 34188, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38078, 4, 0, -1, 'NPC Equip 38078', 4, 16283, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38079, 4, 0, -1, 'NPC Equip 38079', 4, 16283, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38099, 2, 1, -1, 'NPC Equip 38099', 2, 50461, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38113, 4, 4, -1, 'NPC Equip 38113', 6, 51391, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38119, 4, 4, -1, 'NPC Equip 38119', 6, 51904, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38120, 4, 4, -1, 'NPC Equip 38120', 6, 51899, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38121, 4, 4, -1, 'NPC Equip 38121', 6, 49725, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38122, 4, 4, -1, 'NPC Equip 38122', 6, 56454, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38123, 4, 4, -1, 'NPC Equip 38123', 6, 51295, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38124, 4, 4, -1, 'NPC Equip 38124', 6, 51087, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38125, 4, 4, -1, 'NPC Equip 38125', 6, 56189, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38136, 2, 10, -1, 'NPC Equip 38136', 2, 49232, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38139, 2, 4, -1, 'NPC Equip 38139', 1, 49233, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38158, 2, 7, -1, 'NPC Equip 38158', 1, 50266, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38159, 2, 13, -1, 'NPC Equip 38159', 1, 51152, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38165, 0, 0, 0, 'NPC Equip 38165', 0, 50493, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38166, 2, 3, -1, 'NPC Equip 38166', 1, 49226, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38167, 2, 16, -1, 'NPC Equip 38167', 2, 40005, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38168, 2, 2, -1, 'NPC Equip 38168', 2, 50158, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38179, 2, 13, -1, 'NPC Equip 38179', 1, 51152, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38180, 2, 13, -1, 'NPC Equip 38180', 1, 51171, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38182, 2, 8, -1, 'NPC Equip 38182', 1, 50326, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38183, 2, 7, -1, 'NPC Equip 38183', 1, 49221, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38184, 2, 15, -1, 'NPC Equip 38184', 1, 50130, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38185, 2, 2, -1, 'NPC Equip 38185', 2, 50149, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38192, 2, 16, -1, 'NPC Equip 38192', 2, 40005, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38193, 2, 5, -1, 'NPC Equip 38193', 2, 49203, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38199, 2, 7, -1, 'NPC Equip 38199', 1, 49199, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38200, 2, 18, -1, 'NPC Equip 38200', 2, 49202, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38201, 2, 19, -1, 'NPC Equip 38201', 2, 57175, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38203, 2, 19, -1, 'NPC Equip 38203', 2, 57174, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38205, 2, 19, -1, 'NPC Equip 38205', 2, 57178, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38209, 2, 6, -1, 'NPC Equip 38209', 1, 50504, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38210, 2, 6, -1, 'NPC Equip 38210', 1, 40368, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38211, 2, 6, -1, 'NPC Equip 38211', 1, 50505, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38215, 2, 7, -1, 'NPC Equip 38215', 1, 50521, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38216, 2, 0, -1, 'NPC Equip 38216', 1, 50527, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38234, 15, 2, -1, 'NPC Equip 38234', -1, 26532, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38235, 2, 5, -1, 'NPC Equip 38235', 2, 45626, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38236, 0, 0, 0, 'NPC Equip 38236', 4, 7008, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38249, 2, 16, -1, 'NPC Equip 38249', 1, 50542, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38253, 4, 1, -1, 'NPC Equip 38253', 7, 15206, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38275, 4, 0, -1, 'NPC Equip 38275', -1, 50564, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38279, 4, 1, -1, 'NPC Equip 38279', 7, 50568, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38283, 12, 0, 0, 'NPC Equip 38283', -1, 1588, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38296, 2, 6, -1, 'NPC Equip 38296', 1, 50591, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38297, 2, 6, -1, 'NPC Equip 38297', 1, 50592, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38298, 2, 10, -1, 'NPC Equip 38298', 2, 50595, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38299, 15, 2, -1, 'NPC Equip 38299', -1, 26532, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38304, 2, 1, 1, 'NPC Equip 38304', 1, 50627, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38306, 0, 8, -1, 'NPC Equip 38306', 8, 50629, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38315, 2, 10, -1, 'NPC Equip 38315', 2, 50730, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38316, 4, 1, -1, 'NPC Equip 38316', 7, 10448, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38317, 12, 0, 0, 'NPC Equip 38317', -1, 34059, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38331, 4, 0, -1, 'NPC Equip 38331', 2, 32546, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38352, 4, 0, -1, 'NPC Equip 38352', 7, 50689, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38385, 4, 0, -1, 'NPC Equip 38385', 8, 37549, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38391, 2, 7, -1, 'NPC Equip 38391', 1, 41615, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38392, 2, 8, -1, 'NPC Equip 38392', 1, 41773, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38394, 2, 19, -1, 'NPC Equip 38394', 2, 32582, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38395, 2, 2, -1, 'NPC Equip 38395', 2, 20550, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38423, 4, 3, -1, 'NPC Equip 38423', 8, 8098, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38446, 4, 3, -1, 'NPC Equip 38446', 8, 14408, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38447, 4, 2, -1, 'NPC Equip 38447', 8, 16972, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38449, 4, 2, -1, 'NPC Equip 38449', 8, 16994, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38450, 4, 2, -1, 'NPC Equip 38450', 8, 11138, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38451, 4, 2, -1, 'NPC Equip 38451', 8, 4486, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38470, 2, 15, 15, 'NPC Equip 38470', 6, 50709, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38472, 2, 18, -1, 'NPC Equip 38472', 2, 50721, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38474, 0, 8, -1, 'NPC Equip 38474', 2, 41062, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38475, 0, 8, -1, 'NPC Equip 38475', 2, 41061, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38476, 0, 8, -1, 'NPC Equip 38476', 2, 41050, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38478, 0, 8, -1, 'NPC Equip 38478', 2, 41050, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38479, 4, 0, -1, 'NPC Equip 38479', -1, 47773, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38482, 2, 6, 6, 'NPC Equip 38482', 6, 22242, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38485, 4, 0, -1, 'NPC Equip 38485', 3, 31664, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38486, 4, 0, 0, 'NPC Equip 38486', 0, 3332, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38487, 2, 6, -1, 'NPC Equip 38487', 1, 50715, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38488, 2, 6, -1, 'NPC Equip 38488', 1, 50716, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38489, 4, 0, 0, 'NPC Equip 38489', 0, 3332, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38490, 2, 6, -1, 'NPC Equip 38490', 1, 50722, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38491, 2, 6, -1, 'NPC Equip 38491', 1, 50718, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38492, 4, 1, -1, 'NPC Equip 38492', 7, 16700, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38493, 4, 1, -1, 'NPC Equip 38493', 7, 16701, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38494, 4, 1, -1, 'NPC Equip 38494', 7, 16706, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38495, 4, 1, -1, 'NPC Equip 38495', 7, 16702, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38499, 3, 1, 0, 'NPC Equip 38499', 0, 50740, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38500, 3, 0, 0, 'NPC Equip 38500', 0, 50743, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38501, 3, 2, 0, 'NPC Equip 38501', 0, 50744, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38502, 3, 5, 0, 'NPC Equip 38502', 0, 50742, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38503, 3, 4, 0, 'NPC Equip 38503', 0, 50741, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38507, 2, 10, -1, 'NPC Equip 38507', 2, 50729, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38508, 2, 6, -1, 'NPC Equip 38508', 1, 50731, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38509, 2, 1, -1, 'NPC Equip 38509', 1, 50732, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38511, 2, 4, -1, 'NPC Equip 38511', 2, 50736, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38526, 4, 0, -1, 'NPC Equip 38526', 8, 34188, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38554, 4, 6, -1, 'NPC Equip 38554', 1, 50766, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38565, 12, 0, 0, 'NPC Equip 38565', 4, 50797, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38568, 15, 4, -1, 'NPC Equip 38568', 4, 50799, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38569, 15, 4, -1, 'NPC Equip 38569', 4, 50800, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38570, 15, 4, -1, 'NPC Equip 38570', 4, 50801, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38571, 0, 8, 0, 'NPC Equip 38571', 4, 7374, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38580, 2, 10, -1, 'NPC Equip 38580', 2, 50854, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38582, 15, 4, -1, 'NPC Equip 38582', -1, 36754, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38593, 9, 1, -1, 'NPC Equip 38593', 4, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38594, 9, 1, -1, 'NPC Equip 38594', 4, 15274, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38595, 9, 1, -1, 'NPC Equip 38595', 4, 6270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38596, 9, 1, -1, 'NPC Equip 38596', 4, 1096, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38598, 9, 1, -1, 'NPC Equip 38598', 4, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38599, 9, 1, -1, 'NPC Equip 38599', 4, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38602, 2, 13, -1, 'NPC Equip 38602', 1, 50884, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38603, 2, 13, -1, 'NPC Equip 38603', 1, 50885, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38604, 2, 6, -1, 'NPC Equip 38604', 1, 32837, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38608, 15, 0, -1, 'NPC Equip 38608', 4, 3093, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38609, 2, 6, 6, 'NPC Equip 38609', 4, 50890, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38612, 15, 2, -1, 'NPC Equip 38612', -1, 19091, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38635, 4, 6, -1, 'NPC Equip 38635', 1, 50972, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38636, 12, 0, -1, 'NPC Equip 38636', 4, 44523, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38641, 0, 7, -1, 'NPC Equip 38641', 7, 51021, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38652, 2, 10, -1, 'NPC Equip 38652', 2, 51056, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38685, 0, 0, 0, 'NPC Equip 38685', 4, 1093, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38690, 15, 5, -1, 'NPC Equip 38690', -1, 13291, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38692, 2, 10, -1, 'NPC Equip 38692', 2, 51406, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38693, 2, 7, -1, 'NPC Equip 38693', 1, 29677, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38694, 4, 2, -1, 'NPC Equip 38694', 8, 34688, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38702, 0, 0, 0, 'NPC Equip 38702', 0, 51426, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38704, 0, 0, 0, 'NPC Equip 38704', 4, 51446, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38720, 2, 6, 6, 'NPC Equip 38720', 1, 51448, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38721, 2, 0, 0, 'NPC Equip 38721', 2, 51449, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38722, 2, 4, 4, 'NPC Equip 38722', 2, 51450, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38723, 2, 7, 7, 'NPC Equip 38723', 1, 51451, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38724, 16, 11, 0, 'NPC Equip 38724', 4, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38725, 15, 0, 0, 'NPC Equip 38725', 4, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38738, 4, 1, -1, 'NPC Equip 38738', 7, 51312, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38740, 4, 1, -1, 'NPC Equip 38740', 7, 51370, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38742, 4, 1, -1, 'NPC Equip 38742', 7, 51208, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (38952, 0, 6, -1, 'NPC Equip 38952', 8, 811, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39007, 2, 19, -1, 'NPC Equip 39007', 2, 57309, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39008, 2, 19, -1, 'NPC Equip 39008', 2, 57323, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39009, 4, 6, -1, 'NPC Equip 39009', 1, 51091, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39012, 4, 6, -1, 'NPC Equip 39012', 1, 51091, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39014, 15, 0, 0, 'NPC Equip 39014', 4, 1588, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39024, 2, 8, -1, 'NPC Equip 39024', 1, 51461, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39032, 2, 2, 2, 'NPC Equip 39032', 2, 51462, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39037, 4, 2, -1, 'NPC Equip 39037', 6, 51333, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39039, 4, 2, -1, 'NPC Equip 39039', 8, 51164, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39042, 4, 2, -1, 'NPC Equip 39042', 8, 49246, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39061, 0, 8, 0, 'NPC Equip 39061', 4, 1103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39067, 4, 3, -1, 'NPC Equip 39067', 5, 51148, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39069, 4, 3, -1, 'NPC Equip 39069', 5, 51310, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39071, 4, 3, -1, 'NPC Equip 39071', 5, 51300, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39101, 2, 2, 2, 'NPC Equip 39101', 2, 51536, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39103, 4, 4, -1, 'NPC Equip 39103', 6, 51298, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39106, 4, 4, -1, 'NPC Equip 39106', 5, 51387, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39107, 4, 4, -1, 'NPC Equip 39107', 6, 51247, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39111, 2, 10, -1, 'NPC Equip 39111', 2, 51382, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39122, 2, 10, -1, 'NPC Equip 39122', 2, 50137, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39123, 2, 6, -1, 'NPC Equip 39123', 2, 51530, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39126, 2, 15, -1, 'NPC Equip 39126', 1, 50122, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39137, 2, 0, -1, 'NPC Equip 39137', 1, 51463, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39145, 2, 4, -1, 'NPC Equip 39145', 1, 50208, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39147, 15, 0, -1, 'NPC Equip 39147', -1, 51537, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39149, 15, 0, 0, 'NPC Equip 39149', 4, 24694, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39155, 2, 13, -1, 'NPC Equip 39155', 2, 51552, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39184, 2, 6, -1, 'NPC Equip 39184', 1, 5636, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39185, 2, 16, -1, 'NPC Equip 39185', 1, 40409, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39186, 2, 6, -1, 'NPC Equip 39186', 4, 51579, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39214, 4, 0, -1, 'NPC Equip 39214', 3, 38671, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39287, 2, 7, 7, 'NPC Equip 39287', 1, 51677, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39288, 4, 6, -1, 'NPC Equip 39288', 1, 51678, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39289, 2, 10, -1, 'NPC Equip 39289', 2, 51679, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39290, 2, 0, -1, 'NPC Equip 39290', 1, 51680, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39300, 0, 6, 0, 'NPC Equip 39300', 4, 20628, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39304, 0, 8, 0, 'NPC Equip 39304', 0, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39312, 2, 8, -1, 'NPC Equip 39312', 1, 46322, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39321, 4, 1, -1, 'NPC Equip 39321', 7, 51737, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39325, 2, 0, -1, 'NPC Equip 39325', 1, 42655, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39352, 7, 1, -1, 'NPC Equip 39352', 3, 45064, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39359, 2, 1, 0, 'NPC Equip 39359', 2, 46750, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39381, 2, 1, -1, 'NPC Equip 39381', 2, 51760, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39382, 2, 0, 0, 'NPC Equip 39382', 2, 51761, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39384, 4, 6, -1, 'NPC Equip 39384', 1, 51762, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39447, 2, 1, -1, 'NPC Equip 39447', 1, 51764, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39456, 2, 5, 5, 'NPC Equip 39456', 2, 51766, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39511, 7, 11, -1, 'NPC Equip 39511', -1, 31769, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39537, 4, 3, -1, 'NPC Equip 39537', 5, 42919, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39584, 16, 11, 0, 'NPC Equip 39584', 4, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39585, 16, 11, 0, 'NPC Equip 39585', 4, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39586, 16, 11, 0, 'NPC Equip 39586', 4, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39587, 16, 11, 0, 'NPC Equip 39587', 4, 7270, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39600, 0, 0, 0, 'NPC Equip 39600', 0, 51822, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39658, 2, 5, -1, 'NPC Equip 39658', 2, 51968, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39659, 2, 7, -1, 'NPC Equip 39659', 1, 51969, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39660, 4, 6, -1, 'NPC Equip 39660', 1, 51972, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39661, 2, 4, -1, 'NPC Equip 39661', 2, 51977, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39662, 2, 7, -1, 'NPC Equip 39662', 1, 51980, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39663, 2, 4, -1, 'NPC Equip 39663', 2, 51986, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39677, 4, 4, -1, 'NPC Equip 39677', 8, 34688, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39699, 2, 10, -1, 'NPC Equip 39699', 2, 52023, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39705, 4, 3, -1, 'NPC Equip 39705', 8, 34688, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39736, 4, 2, -1, 'NPC Equip 39736', 8, 52030, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39741, 2, 1, 0, 'NPC Equip 39741', 2, 52062, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39742, 2, 10, -1, 'NPC Equip 39742', 2, 52038, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39744, 2, 10, -1, 'NPC Equip 39744', 2, 52078, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39745, 2, 10, 10, 'NPC Equip 39745', 2, 52081, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39746, 2, 10, -1, 'NPC Equip 39746', 2, 52084, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39749, 2, 4, -1, 'NPC Equip 39749', 1, 52088, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39750, 2, 10, -1, 'NPC Equip 39750', 2, 52087, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39751, 2, 8, -1, 'NPC Equip 39751', 1, 52090, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39752, 2, 4, -1, 'NPC Equip 39752', 2, 52100, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39753, 2, 5, -1, 'NPC Equip 39753', 1, 52098, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39813, 4, 1, -1, 'NPC Equip 39813', 7, 51145, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39832, 4, 0, -1, 'NPC Equip 39832', 4, 50191, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39879, 4, 2, -1, 'NPC Equip 39879', 8, 49246, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39884, 4, 3, -1, 'NPC Equip 39884', 5, 51148, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39885, 4, 4, -1, 'NPC Equip 39885', 6, 51306, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39892, 2, 10, 10, 'NPC Equip 39892', 2, 52159, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39901, 3, 3, -1, 'NPC Equip 39901', 4, 35847, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39902, 3, 0, -1, 'NPC Equip 39902', 4, 35930, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39913, 7, 11, -1, 'NPC Equip 39913', 2, 31769, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39921, 4, 6, -1, 'NPC Equip 39921', 1, 52199, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39922, 4, 6, -1, 'NPC Equip 39922', 1, 52200, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39923, 4, 6, -1, 'NPC Equip 39923', 1, 52201, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39924, 4, 6, -1, 'NPC Equip 39924', 1, 52202, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39925, 4, 6, -1, 'NPC Equip 39925', 1, 38258, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39926, 4, 6, -1, 'NPC Equip 39926', 1, 52203, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39928, 4, 6, -1, 'NPC Equip 39928', 1, 52205, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39929, 4, 6, -1, 'NPC Equip 39929', 1, 52206, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39930, 4, 6, -1, 'NPC Equip 39930', 1, 52207, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39931, 4, 6, -1, 'NPC Equip 39931', 1, 52209, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39971, 0, 1, 0, 'NPC Equip 39971', 4, 47132, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39972, 0, 8, -1, 'NPC Equip 39972', 2, 41062, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39993, 2, 0, -1, 'NPC Equip 39993', 1, 52251, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (39994, 2, 2, -1, 'NPC Equip 39994', 0, 52252, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40183, 2, 15, -1, 'NPC Equip 40183', 1, 52258, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40276, 2, 7, 7, 'NPC Equip 40276', 1, 53592, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40308, 0, 0, 0, 'NPC Equip 40308', 4, 52293, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40309, 4, 4, -1, 'NPC Equip 40309', 1, 52295, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40310, 4, 4, -1, 'NPC Equip 40310', 6, 52383, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40311, 4, 4, -1, 'NPC Equip 40311', 1, 52297, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40312, 4, 4, -1, 'NPC Equip 40312', 6, 52298, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40313, 4, 4, -1, 'NPC Equip 40313', 1, 52384, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40314, 4, 4, -1, 'NPC Equip 40314', 6, 52300, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40355, 15, 2, -1, 'NPC Equip 40355', 4, 47892, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40413, 0, 2, -1, 'NPC Equip 40413', 3, 52490, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40434, 2, 5, 5, 'NPC Equip 40434', 0, 52522, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40435, 2, 1, -1, 'NPC Equip 40435', 2, 52523, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40436, 2, 6, 6, 'NPC Equip 40436', 2, 52524, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40452, 2, 4, -1, 'NPC Equip 40452', 2, 52540, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40464, 2, 8, -1, 'NPC Equip 40464', 1, 52542, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40478, 2, 6, -1, 'NPC Equip 40478', 1, 52556, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40479, 4, 4, -1, 'NPC Equip 40479', 1, 46351, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40485, 2, 6, -1, 'NPC Equip 40485', 1, 52560, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40487, 2, 1, -1, 'NPC Equip 40487', 1, 52564, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40498, 4, 2, -1, 'NPC Equip 40498', 8, 42410, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40501, 2, 4, 4, 'NPC Equip 40501', 2, 50213, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40534, 2, 0, 0, 'NPC Equip 40534', 2, 52579, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40535, 2, 5, -1, 'NPC Equip 40535', 2, 53225, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40537, 2, 1, -1, 'NPC Equip 40537', 2, 52583, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40538, 7, 2, -1, 'NPC Equip 40538', 8, 7841, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40540, 2, 0, 0, 'NPC Equip 40540', 0, 52585, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40542, 2, 0, 0, 'NPC Equip 40542', 2, 52586, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40595, 2, 4, -1, 'NPC Equip 40595', 2, 52645, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40596, 4, 6, -1, 'NPC Equip 40596', 2, 52646, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40597, 4, 6, -1, 'NPC Equip 40597', 2, 52655, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40598, 2, 4, -1, 'NPC Equip 40598', 2, 52656, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40604, 4, 4, -1, 'NPC Equip 40604', 1, 45324, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40605, 2, 10, -1, 'NPC Equip 40605', 2, 51056, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40606, 2, 10, -1, 'NPC Equip 40606', 2, 52667, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40607, 2, 6, 6, 'NPC Equip 40607', 1, 52669, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40608, 2, 1, 1, 'NPC Equip 40608', 1, 52670, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40609, 2, 0, 0, 'NPC Equip 40609', 1, 52671, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40644, 2, 8, 8, 'NPC Equip 40644', 1, 52679, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40646, 4, 4, -1, 'NPC Equip 40646', 1, 46351, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40647, 4, 4, -1, 'NPC Equip 40647', 1, 46351, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40648, 4, 4, -1, 'NPC Equip 40648', 1, 52297, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40649, 4, 4, -1, 'NPC Equip 40649', 1, 52297, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40651, 4, 4, -1, 'NPC Equip 40651', 1, 45748, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40654, 4, 1, -1, 'NPC Equip 40654', 7, 45335, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40655, 4, 1, -1, 'NPC Equip 40655', 7, 45335, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40656, 4, 1, -1, 'NPC Equip 40656', 7, 45335, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40657, 4, 1, -1, 'NPC Equip 40657', 7, 45335, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40658, 4, 1, -1, 'NPC Equip 40658', 7, 50012, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40659, 4, 1, -1, 'NPC Equip 40659', 7, 50012, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40660, 4, 1, -1, 'NPC Equip 40660', 7, 50012, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40661, 4, 1, -1, 'NPC Equip 40661', 7, 50012, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40662, 4, 1, -1, 'NPC Equip 40662', 7, 51007, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40663, 4, 1, -1, 'NPC Equip 40663', 7, 51007, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40664, 4, 1, -1, 'NPC Equip 40664', 7, 51007, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40665, 4, 1, -1, 'NPC Equip 40665', 7, 51007, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40667, 0, 5, -1, 'NPC Equip 40667', 4, 45198, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40677, 0, 1, -1, 'NPC Equip 40677', 3, 42031, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40729, 2, 6, -1, 'NPC Equip 40729', 1, 52706, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40759, 2, 2, -1, 'NPC Equip 40759', 2, 52724, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40760, 4, 1, -1, 'NPC Equip 40760', 7, 52726, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40761, 4, 1, -1, 'NPC Equip 40761', 7, 52737, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40763, 4, 1, -1, 'NPC Equip 40763', 7, 52732, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40764, 4, 1, -1, 'NPC Equip 40764', 7, 52734, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40765, 4, 1, -1, 'NPC Equip 40765', 7, 52736, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40766, 4, 1, -1, 'NPC Equip 40766', 7, 52735, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40770, 2, 4, 4, 'NPC Equip 40770', 1, 52740, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40774, 0, 8, -1, 'NPC Equip 40774', -1, 52745, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40793, 4, 4, -1, 'NPC Equip 40793', 6, 49999, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40794, 4, 4, -1, 'NPC Equip 40794', 6, 49999, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40795, 4, 4, -1, 'NPC Equip 40795', 6, 49999, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40796, 12, 0, 0, 'NPC Equip 40796', 4, 24156, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40800, 0, 6, 0, 'NPC Equip 40800', 4, 31199, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40813, 4, 4, -1, 'NPC Equip 40813', 6, 49998, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40814, 4, 4, -1, 'NPC Equip 40814', 6, 49998, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40815, 4, 4, -1, 'NPC Equip 40815', 6, 49998, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40833, 4, 4, -1, 'NPC Equip 40833', 6, 49685, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40834, 4, 4, -1, 'NPC Equip 40834', 6, 49685, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40835, 4, 4, -1, 'NPC Equip 40835', 6, 49685, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40843, 12, 0, 0, 'NPC Equip 40843', 4, 40697, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40853, 4, 4, -1, 'NPC Equip 40853', 6, 49996, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40854, 4, 4, -1, 'NPC Equip 40854', 6, 49996, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40855, 4, 4, -1, 'NPC Equip 40855', 6, 49996, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40873, 4, 4, -1, 'NPC Equip 40873', 6, 49995, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40874, 4, 4, -1, 'NPC Equip 40874', 6, 49995, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40876, 4, 4, -1, 'NPC Equip 40876', 6, 49995, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40885, 4, 4, -1, 'NPC Equip 40885', 6, 48661, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40886, 4, 4, -1, 'NPC Equip 40886', 6, 48669, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40891, 4, 4, -1, 'NPC Equip 40891', 6, 48664, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40894, 2, 7, 7, 'NPC Equip 40894', 0, 52781, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40911, 4, 4, -1, 'NPC Equip 40911', 6, 50001, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40929, 4, 4, -1, 'NPC Equip 40929', 6, 48640, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40935, 4, 4, -1, 'NPC Equip 40935', 6, 48740, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40941, 4, 4, -1, 'NPC Equip 40941', 6, 50002, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40945, 12, 0, -1, 'NPC Equip 40945', -1, 35178, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40965, 4, 4, -1, 'NPC Equip 40965', 6, 50003, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40967, 2, 13, 13, 'NPC Equip 40967', 1, 52809, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40968, 2, 13, 13, 'NPC Equip 40968', 1, 52810, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40980, 4, 4, -1, 'NPC Equip 40980', 6, 48660, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40981, 4, 4, -1, 'NPC Equip 40981', 6, 48663, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40985, 4, 4, -1, 'NPC Equip 40985', 6, 48662, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40996, 4, 3, -1, 'NPC Equip 40996', 5, 49969, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (40997, 4, 3, -1, 'NPC Equip 40997', 5, 49969, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41003, 4, 3, -1, 'NPC Equip 41003', 5, 48611, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41009, 4, 3, -1, 'NPC Equip 41009', 5, 48611, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41015, 4, 3, -1, 'NPC Equip 41015', 5, 48613, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41021, 4, 3, -1, 'NPC Equip 41021', 5, 48613, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41022, 2, 6, -1, 'NPC Equip 41022', 1, 52830, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41029, 4, 3, -1, 'NPC Equip 41029', 5, 48615, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41035, 4, 3, -1, 'NPC Equip 41035', 5, 48615, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41040, 4, 3, -1, 'NPC Equip 41040', 5, 48616, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41046, 4, 3, -1, 'NPC Equip 41046', 5, 48616, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41053, 4, 3, -1, 'NPC Equip 41053', 5, 48674, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41057, 4, 3, -1, 'NPC Equip 41057', 5, 48675, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41062, 4, 3, -1, 'NPC Equip 41062', 5, 48673, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41067, 4, 3, -1, 'NPC Equip 41067', 5, 48673, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41072, 4, 3, -1, 'NPC Equip 41072', 5, 48674, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41077, 4, 3, -1, 'NPC Equip 41077', 5, 48675, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41083, 4, 3, -1, 'NPC Equip 41083', 5, 49969, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41089, 4, 3, -1, 'NPC Equip 41089', 5, 53567, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41090, 2, 10, 10, 'NPC Equip 41090', -1, 52835, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41139, 4, 3, -1, 'NPC Equip 41139', 5, 48611, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41145, 4, 3, -1, 'NPC Equip 41145', 5, 48611, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41153, 4, 3, -1, 'NPC Equip 41153', 5, 48613, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41159, 4, 3, -1, 'NPC Equip 41159', 5, 48613, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41175, 2, 1, -1, 'NPC Equip 41175', 1, 52923, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41176, 2, 10, -1, 'NPC Equip 41176', 2, 52920, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41177, 2, 7, -1, 'NPC Equip 41177', 1, 52919, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41180, 2, 10, 10, 'NPC Equip 41180', 2, 52921, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41201, 4, 3, -1, 'NPC Equip 41201', 5, 48615, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41207, 4, 3, -1, 'NPC Equip 41207', 5, 48615, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41213, 4, 3, -1, 'NPC Equip 41213', 5, 48616, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41219, 4, 3, -1, 'NPC Equip 41219', 5, 48616, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41220, 4, 3, -1, 'NPC Equip 41220', 5, 48673, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41221, 4, 3, -1, 'NPC Equip 41221', 5, 48674, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41222, 4, 3, -1, 'NPC Equip 41222', 5, 48675, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41227, 4, 3, -1, 'NPC Equip 41227', 5, 48673, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41232, 4, 3, -1, 'NPC Equip 41232', 5, 48675, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41237, 4, 3, -1, 'NPC Equip 41237', 5, 48674, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41244, 2, 15, -1, 'NPC Equip 41244', 1, 52943, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41246, 2, 5, -1, 'NPC Equip 41246', 1, 52948, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41247, 7, 7, -1, 'NPC Equip 41247', 1, 29946, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41256, 2, 6, -1, 'NPC Equip 41256', 1, 12857, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41259, 2, 8, -1, 'NPC Equip 41259', 1, 52968, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41261, 2, 1, -1, 'NPC Equip 41261', 2, 52972, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41263, 2, 7, -1, 'NPC Equip 41263', 1, 41089, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41277, 4, 2, -1, 'NPC Equip 41277', 8, 48591, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41283, 4, 2, -1, 'NPC Equip 41283', 8, 48591, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41289, 4, 2, -1, 'NPC Equip 41289', 8, 49966, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41295, 4, 2, -1, 'NPC Equip 41295', 8, 49966, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41300, 4, 2, -1, 'NPC Equip 41300', 8, 48603, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41306, 4, 2, -1, 'NPC Equip 41306', 8, 48603, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41312, 4, 2, -1, 'NPC Equip 41312', 8, 49968, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41318, 4, 2, -1, 'NPC Equip 41318', 8, 49968, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41323, 4, 2, -1, 'NPC Equip 41323', 8, 48602, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41329, 4, 2, -1, 'NPC Equip 41329', 8, 48602, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41343, 2, 7, -1, 'NPC Equip 41343', 1, 52993, 21, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41358, 2, 6, -1, 'NPC Equip 41358', 1, 53012, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41360, 2, 2, -1, 'NPC Equip 41360', 2, 53014, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41364, 2, 10, -1, 'NPC Equip 41364', 2, 53160, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41365, 2, 10, -1, 'NPC Equip 41365', 2, 53017, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41370, 2, 8, -1, 'NPC Equip 41370', 1, 53022, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41371, 2, 8, -1, 'NPC Equip 41371', 1, 53023, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41374, 0, 5, -1, 'NPC Equip 41374', 3, 18060, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41402, 9, 10, -1, 'NPC Equip 41402', -1, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41425, 4, 0, 0, 'NPC Equip 41425', 4, 53043, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41583, 2, 1, -1, 'NPC Equip 41583', 2, 53106, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41613, 2, 3, -1, 'NPC Equip 41613', 1, 53113, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41619, 4, 2, -1, 'NPC Equip 41619', 8, 48676, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41623, 4, 2, -1, 'NPC Equip 41623', 8, 48678, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41627, 4, 2, -1, 'NPC Equip 41627', 8, 48681, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41632, 4, 2, -1, 'NPC Equip 41632', 8, 48676, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41637, 4, 2, -1, 'NPC Equip 41637', 8, 48678, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41642, 4, 2, -1, 'NPC Equip 41642', 8, 48681, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41652, 4, 2, -1, 'NPC Equip 41652', 8, 48599, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41657, 4, 2, -1, 'NPC Equip 41657', 8, 48597, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41663, 4, 2, -1, 'NPC Equip 41663', 8, 48599, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41669, 4, 2, -1, 'NPC Equip 41669', 8, 48597, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41674, 4, 2, -1, 'NPC Equip 41674', 8, 48739, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41680, 4, 2, -1, 'NPC Equip 41680', 8, 48739, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41685, 4, 2, -1, 'NPC Equip 41685', 8, 48598, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41691, 2, 0, 0, 'NPC Equip 41691', 2, 52583, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41695, 2, 6, 6, 'NPC Equip 41695', 1, 53115, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41717, 4, 2, -1, 'NPC Equip 41717', 8, 48598, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41748, 2, 7, 7, 'NPC Equip 41748', 4, 48879, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41764, 2, 0, 0, 'NPC Equip 41764', 1, 53161, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41769, 4, 2, -1, 'NPC Equip 41769', 8, 49965, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41775, 4, 2, -1, 'NPC Equip 41775', 8, 49965, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41823, 4, 4, -1, 'NPC Equip 41823', 6, 53005, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41834, 4, 2, -1, 'NPC Equip 41834', 8, 48677, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41838, 4, 2, -1, 'NPC Equip 41838', 8, 48679, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41842, 4, 2, -1, 'NPC Equip 41842', 8, 48682, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41856, 4, 1, -1, 'NPC Equip 41856', 7, 50007, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41861, 4, 1, -1, 'NPC Equip 41861', 7, 49963, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41866, 4, 1, -1, 'NPC Equip 41866', 7, 49964, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41871, 4, 1, -1, 'NPC Equip 41871', 7, 50010, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41876, 4, 1, -1, 'NPC Equip 41876', 7, 49960, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41883, 4, 1, -1, 'NPC Equip 41883', 7, 48686, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41887, 4, 1, -1, 'NPC Equip 41887', 7, 48688, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41889, 2, 6, -1, 'NPC Equip 41889', 1, 53192, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41895, 4, 1, -1, 'NPC Equip 41895', 7, 48687, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41906, 4, 1, -1, 'NPC Equip 41906', 7, 48688, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41917, 4, 1, -1, 'NPC Equip 41917', 7, 50007, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41923, 4, 1, -1, 'NPC Equip 41923', 7, 49963, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41929, 4, 1, -1, 'NPC Equip 41929', 7, 49964, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41936, 4, 1, -1, 'NPC Equip 41936', 7, 50010, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41942, 4, 1, -1, 'NPC Equip 41942', 7, 49960, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41948, 4, 1, -1, 'NPC Equip 41948', 7, 50007, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41952, 4, 1, -1, 'NPC Equip 41952', 7, 49963, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41955, 4, 1, -1, 'NPC Equip 41955', 7, 49963, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41961, 4, 1, -1, 'NPC Equip 41961', 7, 49964, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41967, 4, 1, -1, 'NPC Equip 41967', 7, 50010, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41973, 4, 1, -1, 'NPC Equip 41973', 7, 49960, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41977, 2, 5, -1, 'NPC Equip 41977', 2, 53226, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41978, 2, 5, -1, 'NPC Equip 41978', 2, 53227, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41979, 2, 5, -1, 'NPC Equip 41979', 2, 53228, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41980, 2, 5, -1, 'NPC Equip 41980', 2, 53229, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41981, 2, 5, -1, 'NPC Equip 41981', 2, 53230, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41982, 2, 5, -1, 'NPC Equip 41982', 2, 53231, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (41983, 2, 5, -1, 'NPC Equip 41983', 2, 53232, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42048, 4, 0, -1, 'NPC Equip 42048', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42049, 4, 0, -1, 'NPC Equip 42049', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42050, 4, 0, -1, 'NPC Equip 42050', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42051, 4, 0, -1, 'NPC Equip 42051', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42052, 4, 0, -1, 'NPC Equip 42052', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42053, 4, 0, -1, 'NPC Equip 42053', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42054, 4, 0, -1, 'NPC Equip 42054', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42085, 4, 1, -1, 'NPC Equip 42085', 5, 53264, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42086, 4, 1, -1, 'NPC Equip 42086', 5, 53264, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42087, 4, 1, -1, 'NPC Equip 42087', 5, 53264, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42089, 4, 1, -1, 'NPC Equip 42089', 5, 53264, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42090, 4, 1, -1, 'NPC Equip 42090', 5, 53264, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42091, 4, 1, -1, 'NPC Equip 42091', 5, 53910, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42120, 4, 0, -1, 'NPC Equip 42120', 5, 39129, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42121, 4, 0, -1, 'NPC Equip 42121', 5, 39129, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42125, 4, 0, -1, 'NPC Equip 42125', 4, 37840, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42127, 4, 0, -1, 'NPC Equip 42127', 4, 37841, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42139, 2, 10, 10, 'NPC Equip 42139', 2, 53318, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42140, 2, 2, 2, 'NPC Equip 42140', 2, 53319, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42141, 3, 8, -1, 'NPC Equip 42141', 4, 2516, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42161, 2, 7, -1, 'NPC Equip 42161', 1, 53327, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42165, 2, 10, -1, 'NPC Equip 42165', 2, 53361, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42166, 2, 15, -1, 'NPC Equip 42166', 1, 53362, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42167, 2, 15, -1, 'NPC Equip 42167', 1, 53363, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42168, 2, 4, -1, 'NPC Equip 42168', 2, 39358, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42169, 2, 5, -1, 'NPC Equip 42169', 2, 53364, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42205, 12, 0, 0, 'NPC Equip 42205', -1, 53382, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42211, 2, 0, -1, 'NPC Equip 42211', 1, 49150, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42230, 2, 0, -1, 'NPC Equip 42230', 1, 49150, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42235, 2, 0, -1, 'NPC Equip 42235', 1, 49150, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42239, 2, 0, -1, 'NPC Equip 42239', 1, 49152, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42240, 2, 0, -1, 'NPC Equip 42240', 1, 49152, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42245, 2, 15, -1, 'NPC Equip 42245', 1, 49141, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42251, 2, 15, -1, 'NPC Equip 42251', 1, 49141, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42258, 2, 15, -1, 'NPC Equip 42258', 1, 49141, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42263, 2, 13, -1, 'NPC Equip 42263', 1, 49145, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42268, 2, 13, -1, 'NPC Equip 42268', 1, 49139, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42273, 2, 13, -1, 'NPC Equip 42273', 1, 49139, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42278, 2, 4, -1, 'NPC Equip 42278', 1, 49136, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42283, 2, 4, -1, 'NPC Equip 42283', 1, 49136, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42288, 2, 7, -1, 'NPC Equip 42288', 1, 49143, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42293, 2, 7, -1, 'NPC Equip 42293', 1, 49143, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42320, 2, 1, -1, 'NPC Equip 42320', 1, 49149, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42325, 2, 5, -1, 'NPC Equip 42325', 1, 49993, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42330, 2, 6, -1, 'NPC Equip 42330', 1, 49142, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42335, 2, 8, -1, 'NPC Equip 42335', 1, 49137, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42349, 2, 15, -1, 'NPC Equip 42349', 1, 49147, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42355, 2, 4, -1, 'NPC Equip 42355', 1, 49146, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42357, 2, 10, -1, 'NPC Equip 42357', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42358, 2, 10, -1, 'NPC Equip 42358', 1, 49148, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42367, 2, 10, -1, 'NPC Equip 42367', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42379, 4, 0, 0, 'NPC Equip 42379', 0, 53428, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42380, 4, 0, 0, 'NPC Equip 42380', 0, 53429, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42387, 2, 10, -1, 'NPC Equip 42387', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42393, 2, 10, -1, 'NPC Equip 42393', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42426, 2, 10, 10, 'NPC Equip 42426', 1, 53464, 13, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42427, 2, 7, 7, 'NPC Equip 42427', 1, 55891, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42437, 0, 0, 0, 'NPC Equip 42437', 4, 47763, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42452, 2, 16, -1, 'NPC Equip 42452', 1, 38679, 25, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42477, 2, 8, -1, 'NPC Equip 42477', 1, 53483, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42478, 2, 8, -1, 'NPC Equip 42478', 1, 53484, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42488, 2, 3, -1, 'NPC Equip 42488', 1, 49393, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42493, 2, 2, -1, 'NPC Equip 42493', 2, 49140, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42497, 2, 18, -1, 'NPC Equip 42497', 2, 49138, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42505, 2, 19, -1, 'NPC Equip 42505', 2, 46606, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42506, 2, 4, -1, 'NPC Equip 42506', 2, 53529, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42507, 2, 6, -1, 'NPC Equip 42507', 1, 53530, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42509, 2, 6, 6, 'NPC Equip 42509', 1, 53533, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42516, 2, 19, -1, 'NPC Equip 42516', 2, 46606, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42522, 2, 19, -1, 'NPC Equip 42522', 2, 46606, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42528, 4, 0, -1, 'NPC Equip 42528', 3, 39505, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42534, 4, 0, -1, 'NPC Equip 42534', 3, 39505, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42540, 4, 0, -1, 'NPC Equip 42540', 3, 39505, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42543, 4, 6, -1, 'NPC Equip 42543', 2, 53550, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42544, 2, 4, -1, 'NPC Equip 42544', 2, 53551, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42547, 2, 8, -1, 'NPC Equip 42547', 1, 53553, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42548, 0, 1, -1, 'NPC Equip 42548', 3, 8546, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42562, 4, 6, -1, 'NPC Equip 42562', 1, 49155, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42567, 4, 6, -1, 'NPC Equip 42567', 1, 49153, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42573, 4, 6, -1, 'NPC Equip 42573', 1, 49153, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42581, 4, 8, -1, 'NPC Equip 42581', 2, 9659, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42586, 4, 8, -1, 'NPC Equip 42586', 2, 34953, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42592, 4, 8, -1, 'NPC Equip 42592', 2, 34953, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42600, 4, 9, -1, 'NPC Equip 42600', 2, 46045, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42605, 4, 9, -1, 'NPC Equip 42605', 2, 25246, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42610, 4, 9, -1, 'NPC Equip 42610', 2, 25246, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42617, 4, 7, -1, 'NPC Equip 42617', 2, 1103, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42623, 4, 10, -1, 'NPC Equip 42623', 2, 51913, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42756, 4, 0, -1, 'NPC Equip 42756', 8, 34802, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42757, 2, 7, -1, 'NPC Equip 42757', 1, 53602, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42759, 2, 4, -1, 'NPC Equip 42759', 2, 53603, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42764, 0, 0, 0, 'NPC Equip 42764', 0, 53619, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42771, 12, 0, 0, 'NPC Equip 42771', 4, 53675, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42773, 2, 10, -1, 'NPC Equip 42773', 2, 53677, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42775, 2, 2, -1, 'NPC Equip 42775', 2, 53690, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42855, 4, 7, -1, 'NPC Equip 42855', 2, 34960, 28, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42856, 4, 0, -1, 'NPC Equip 42856', 4, 6543, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42873, 2, 6, -1, 'NPC Equip 42873', 1, 53703, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42919, 2, 1, -1, 'NPC Equip 42919', 1, 49149, 22, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42920, 2, 7, -1, 'NPC Equip 42920', 1, 53708, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42921, 2, 2, -1, 'NPC Equip 42921', 2, 53709, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42923, 2, 10, 10, 'NPC Equip 42923', 2, 53723, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42924, 2, 10, 10, 'NPC Equip 42924', 2, 53724, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42925, 2, 10, 10, 'NPC Equip 42925', 2, 53725, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42929, 15, 0, -1, 'NPC Equip 42929', 8, 16205, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42932, 2, 7, 7, 'NPC Equip 42932', -1, 53774, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42933, 2, 7, 7, 'NPC Equip 42933', -1, 53773, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42934, 2, 8, 8, 'NPC Equip 42934', -1, 53775, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42935, 2, 8, 8, 'NPC Equip 42935', -1, 53776, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42936, 4, 6, -1, 'NPC Equip 42936', 1, 53777, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42937, 4, 6, -1, 'NPC Equip 42937', 1, 53778, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42938, 4, 6, -1, 'NPC Equip 42938', 1, 53779, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42939, 2, 4, -1, 'NPC Equip 42939', 2, 53780, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (42941, 2, 10, -1, 'NPC Equip 42941', 2, 53786, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43008, 2, 1, -1, 'NPC Equip 43008', 1, 60263, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43014, 2, 10, -1, 'NPC Equip 43014', 2, 53860, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43040, 4, 1, -1, 'NPC Equip 43040', 7, 35556, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43041, 4, 1, -1, 'NPC Equip 43041', 7, 53960, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43042, 4, 1, -1, 'NPC Equip 43042', 7, 53953, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43043, 4, 2, -1, 'NPC Equip 43043', 8, 53959, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43044, 4, 2, -1, 'NPC Equip 43044', 8, 36481, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43045, 4, 2, -1, 'NPC Equip 43045', 8, 36480, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43046, 4, 3, -1, 'NPC Equip 43046', 5, 53971, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43047, 4, 3, -1, 'NPC Equip 43047', 5, 35557, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43048, 4, 3, -1, 'NPC Equip 43048', 5, 35554, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43049, 4, 4, -1, 'NPC Equip 43049', 1, 35555, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43050, 4, 4, -1, 'NPC Equip 43050', 1, 35550, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43051, 4, 4, -1, 'NPC Equip 43051', 1, 36077, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43052, 4, 1, -1, 'NPC Equip 43052', 7, 53955, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43053, 4, 4, -1, 'NPC Equip 43053', 1, 53947, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43054, 4, 2, -1, 'NPC Equip 43054', 8, 53963, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43055, 4, 3, -1, 'NPC Equip 43055', 5, 53969, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43056, 4, 3, -1, 'NPC Equip 43056', 5, 53970, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43057, 4, 4, -1, 'NPC Equip 43057', 1, 53975, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43058, 4, 2, -1, 'NPC Equip 43058', 8, 53956, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43060, 4, 1, -1, 'NPC Equip 43060', 7, 53973, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43061, 4, 4, -1, 'NPC Equip 43061', 1, 53974, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43062, 4, 4, -1, 'NPC Equip 43062', 1, 53980, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43063, 4, 4, -1, 'NPC Equip 43063', 1, 53981, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43064, 4, 4, -1, 'NPC Equip 43064', 1, 53975, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43065, 4, 4, -1, 'NPC Equip 43065', 1, 53978, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43066, 4, 4, -1, 'NPC Equip 43066', 1, 53983, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43067, 4, 4, -1, 'NPC Equip 43067', 1, 53984, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43091, 2, 7, -1, 'NPC Equip 43091', 1, 54098, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43092, 4, 6, -1, 'NPC Equip 43092', 1, 54099, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43098, 7, 11, 0, 'NPC Equip 43098', 4, 38475, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43110, 2, 6, -1, 'NPC Equip 43110', 1, 54107, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43111, 2, 1, -1, 'NPC Equip 43111', 2, 54113, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43112, 2, 4, -1, 'NPC Equip 43112', 2, 54109, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43113, 2, 4, -1, 'NPC Equip 43113', 2, 54110, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43114, 2, 6, -1, 'NPC Equip 43114', 1, 54111, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43152, 2, 10, 10, 'NPC Equip 43152', 2, 54168, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43170, 7, 11, -1, 'NPC Equip 43170', 4, 16211, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43175, 2, 0, -1, 'NPC Equip 43175', 1, 54203, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43196, 2, 10, -1, 'NPC Equip 43196', 2, 54266, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43199, 2, 4, -1, 'NPC Equip 43199', 2, 54267, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43205, 2, 5, -1, 'NPC Equip 43205', 2, 54286, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43216, 2, 10, 10, 'NPC Equip 43216', 2, 54348, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43219, 2, 10, -1, 'NPC Equip 43219', 2, 54409, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43220, 2, 10, -1, 'NPC Equip 43220', 2, 54421, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43221, 2, 7, 7, 'NPC Equip 43221', 1, 54433, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43222, 4, 6, 7, 'NPC Equip 43222', 1, 54434, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43223, 2, 10, 10, 'NPC Equip 43223', 1, 54435, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43224, 2, 2, 2, 'NPC Equip 43224', 2, 54437, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43226, 2, 10, -1, 'NPC Equip 43226', 2, 54439, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43227, 2, 10, -1, 'NPC Equip 43227', 2, 54440, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43254, 12, 0, -1, 'NPC Equip 43254', -1, 47969, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43292, 4, 6, -1, 'NPC Equip 43292', 1, 54541, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43293, 4, 6, -1, 'NPC Equip 43293', 1, 54542, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43294, 4, 6, -1, 'NPC Equip 43294', 1, 54543, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43295, 4, 6, -1, 'NPC Equip 43295', 1, 54544, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43296, 2, 0, 0, 'NPC Equip 43296', 2, 54545, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43301, 4, 0, 0, 'NPC Equip 43301', 7, 54559, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43383, 16, 7, 0, 'NPC Equip 43383', 4, 54596, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43474, 2, 10, -1, 'NPC Equip 43474', 2, 54736, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43477, 2, 6, -1, 'NPC Equip 43477', 1, 54737, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43479, 2, 15, 15, 'NPC Equip 43479', 1, 54741, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43483, 4, 0, -1, 'NPC Equip 43483', -1, 41731, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43487, 2, 7, 7, 'NPC Equip 43487', 1, 54742, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43496, 0, 5, -1, 'NPC Equip 43496', 4, 53880, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43503, 4, 2, -1, 'NPC Equip 43503', 5, 56699, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43514, 15, 0, -1, 'NPC Equip 43514', -1, 44964, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43525, 2, 4, -1, 'NPC Equip 43525', 1, 54899, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43532, 2, 1, -1, 'NPC Equip 43532', 2, 54947, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43540, 15, 0, 0, 'NPC Equip 43540', 4, 54953, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43578, 2, 8, -1, 'NPC Equip 43578', 1, 55034, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43579, 2, 8, -1, 'NPC Equip 43579', 1, 55038, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43580, 2, 7, -1, 'NPC Equip 43580', 1, 46410, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43581, 2, 4, 5, 'NPC Equip 43581', 0, 48329, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43596, 2, 10, -1, 'NPC Equip 43596', 2, 55059, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43598, 2, 15, -1, 'NPC Equip 43598', 1, 55062, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43602, 7, 1, -1, 'NPC Equip 43602', 3, 4135, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43603, 7, 1, -1, 'NPC Equip 43603', 3, 15791, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43604, 7, 1, -1, 'NPC Equip 43604', 3, 37857, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43605, 7, 1, -1, 'NPC Equip 43605', 3, 17889, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43606, 7, 1, -1, 'NPC Equip 43606', 3, 37849, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43607, 7, 1, -1, 'NPC Equip 43607', 3, 37846, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43623, 2, 1, -1, 'NPC Equip 43623', 2, 55162, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43625, 2, 0, 0, 'NPC Equip 43625', 2, 55166, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43642, 15, 0, 0, 'NPC Equip 43642', 4, 55248, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43649, 4, 0, -1, 'NPC Equip 43649', 8, 52268, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43692, 2, 8, -1, 'NPC Equip 43692', 1, 55276, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43700, 4, 2, -1, 'NPC Equip 43700', 8, 55287, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43886, 4, 0, -1, 'NPC Equip 43886', 4, 50191, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43887, 4, 2, -1, 'NPC Equip 43887', 8, 56493, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43901, 4, 3, -1, 'NPC Equip 43901', 5, 56495, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43902, 4, 4, -1, 'NPC Equip 43902', 6, 51297, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43957, 15, 5, -1, 'NPC Equip 43957', -1, 44588, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43960, 15, 5, -1, 'NPC Equip 43960', -1, 44588, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43965, 15, 5, -1, 'NPC Equip 43965', -1, 36142, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43967, 2, 7, -1, 'NPC Equip 43967', 1, 55346, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43985, 12, 0, -1, 'NPC Equip 43985', -1, 55362, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (43999, 4, 0, -1, 'NPC Equip 43999', 3, 39123, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44056, 2, 0, -1, 'NPC Equip 44056', 1, 55588, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44070, 12, 0, -1, 'NPC Equip 44070', -1, 55664, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44079, 15, 5, -1, 'NPC Equip 44079', -1, 44588, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44085, 15, 5, -1, 'NPC Equip 44085', -1, 44588, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44119, 9, 5, -1, 'NPC Equip 44119', 2, 1102, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44124, 12, 0, -1, 'NPC Equip 44124', 4, 40395, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44125, 12, 0, -1, 'NPC Equip 44125', 4, 40103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44126, 12, 0, -1, 'NPC Equip 44126', 4, 40103, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44162, 2, 7, -1, 'NPC Equip 44162', 1, 55796, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44169, 2, 5, -1, 'NPC Equip 44169', 2, 55822, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44172, 2, 1, -1, 'NPC Equip 44172', 2, 55824, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44209, 10, 0, -1, 'NPC Equip 44209', -1, 7111, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44227, 2, 1, -1, 'NPC Equip 44227', 1, 56157, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44232, 2, 4, -1, 'NPC Equip 44232', 2, 56123, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44233, 4, 6, -1, 'NPC Equip 44233', 1, 56124, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44237, 2, 7, -1, 'NPC Equip 44237', 1, 20502, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44238, 2, 7, 7, 'NPC Equip 44238', 1, 56142, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44252, 2, 1, -1, 'NPC Equip 44252', 1, 56245, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44389, 4, 0, -1, 'NPC Equip 44389', 4, 51280, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44390, 4, 0, -1, 'NPC Equip 44390', 4, 9860, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44414, 12, 0, 0, 'NPC Equip 44414', 4, 47149, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44425, 2, 10, -1, 'NPC Equip 44425', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44426, 2, 10, -1, 'NPC Equip 44426', 2, 47994, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44427, 4, 3, -1, 'NPC Equip 44427', 7, 52945, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44439, 2, 7, 7, 'NPC Equip 44439', 1, 56651, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44454, 2, 16, -1, 'NPC Equip 44454', 1, 30956, 25, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44572, 0, 5, -1, 'NPC Equip 44572', -1, 18085, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44603, 2, 6, -1, 'NPC Equip 44603', 1, 56879, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44611, 2, 14, -1, 'NPC Equip 44611', 1, 54107, 23, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44624, 0, 0, 0, 'NPC Equip 44624', 4, 47763, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44628, 0, 0, 0, 'NPC Equip 44628', 4, 47763, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44630, 0, 0, 0, 'NPC Equip 44630', 4, 47763, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44633, 4, 0, -1, 'NPC Equip 44633', 4, 56978, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44634, 4, 0, -1, 'NPC Equip 44634', 4, 56976, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44699, 15, 0, -1, 'NPC Equip 44699', -1, 57623, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44706, 2, 10, -1, 'NPC Equip 44706', 2, 57097, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44712, 4, 0, -1, 'NPC Equip 44712', -1, 39915, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44715, 2, 3, -1, 'NPC Equip 44715', 1, 57220, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44720, 4, 0, -1, 'NPC Equip 44720', 5, 26537, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44726, 2, 4, -1, 'NPC Equip 44726', 2, 57257, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44727, 2, 7, -1, 'NPC Equip 44727', 1, 57258, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44730, 4, 1, -1, 'NPC Equip 44730', 7, 44949, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44733, 2, 4, -1, 'NPC Equip 44733', 2, 57308, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44744, 15, 0, 0, 'NPC Equip 44744', 4, 45938, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44786, 4, 0, 0, 'NPC Equip 44786', 7, 58011, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44787, 4, 0, 0, 'NPC Equip 44787', 0, 58014, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44795, 15, 0, -1, 'NPC Equip 44795', 4, 57529, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44796, 4, 0, -1, 'NPC Equip 44796', 7, 57511, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44797, 4, 0, -1, 'NPC Equip 44797', 7, 13117, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44798, 4, 0, -1, 'NPC Equip 44798', 7, 57566, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44799, 4, 0, -1, 'NPC Equip 44799', 7, 57510, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44801, 4, 0, -1, 'NPC Equip 44801', 4, 6560, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44804, 0, 0, -1, 'NPC Equip 44804', 4, 39888, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44805, 0, 0, -1, 'NPC Equip 44805', 4, 39888, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44813, 0, 0, -1, 'NPC Equip 44813', -1, 57551, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44814, 4, 0, -1, 'NPC Equip 44814', 7, 15966, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44816, 0, 0, 0, 'NPC Equip 44816', -1, 47314, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44821, 2, 5, 5, 'NPC Equip 44821', -1, 57599, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44823, 15, 2, -1, 'NPC Equip 44823', 4, 57527, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44824, 15, 2, -1, 'NPC Equip 44824', 4, 15798, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44825, 15, 2, -1, 'NPC Equip 44825', 4, 59495, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44826, 15, 2, -1, 'NPC Equip 44826', 4, 19091, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44827, 15, 2, -1, 'NPC Equip 44827', 4, 17284, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44828, 15, 2, -1, 'NPC Equip 44828', 4, 20629, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44829, 15, 2, -1, 'NPC Equip 44829', 4, 41547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44845, 2, 5, -1, 'NPC Equip 44845', 1, 33731, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44846, 2, 5, -1, 'NPC Equip 44846', 1, 33830, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44847, 2, 5, -1, 'NPC Equip 44847', 1, 33017, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44848, 2, 5, -1, 'NPC Equip 44848', 1, 35710, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44857, 15, 5, -1, 'NPC Equip 44857', 4, 41547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44865, 4, 0, -1, 'NPC Equip 44865', 8, 52575, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44867, 0, 0, 0, 'NPC Equip 44867', 4, 8928, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44885, 15, 5, -1, 'NPC Equip 44885', -1, 44739, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44952, 2, 6, -1, 'NPC Equip 44952', 1, 40367, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (44964, 0, 0, 0, 'NPC Equip 44964', 4, 57819, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45010, 4, 0, -1, 'NPC Equip 45010', 7, 55265, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45041, 2, 5, -1, 'NPC Equip 45041', 1, 60428, 21, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45048, 2, 1, -1, 'NPC Equip 45048', 1, 58002, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45053, 2, 5, -1, 'NPC Equip 45053', 2, 58012, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45055, 2, 5, -1, 'NPC Equip 45055', 2, 2775, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45081, 2, 6, -1, 'NPC Equip 45081', 1, 58123, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45084, 4, 0, -1, 'NPC Equip 45084', 7, 58153, 0, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45123, 2, 4, -1, 'NPC Equip 45123', 1, 8568, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45124, 2, 8, -1, 'NPC Equip 45124', 1, 58171, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45290, 15, 4, -1, 'NPC Equip 45290', 4, 58209, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45366, 4, 1, -1, 'NPC Equip 45366', 7, 58258, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45407, 4, 3, -1, 'NPC Equip 45407', 5, 59061, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45499, 4, 1, -1, 'NPC Equip 45499', 7, 54686, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45528, 2, 1, -1, 'NPC Equip 45528', 1, 58347, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45692, 2, 8, 8, 'NPC Equip 45692', 1, 58439, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45726, 2, 4, -1, 'NPC Equip 45726', 2, 58502, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45727, 2, 7, 7, 'NPC Equip 45727', 1, 58503, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45763, 2, 14, 6, 'NPC Equip 45763', 4, 58520, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45856, 4, 6, -1, 'NPC Equip 45856', 1, 58575, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45884, 2, 6, -1, 'NPC Equip 45884', 1, 53115, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45889, 4, 0, -1, 'NPC Equip 45889', 3, 39505, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45890, 4, 0, -1, 'NPC Equip 45890', 3, 39505, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45891, 4, 0, -1, 'NPC Equip 45891', 3, 39505, 23, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45910, 2, 15, 6, 'NPC Equip 45910', 4, 58520, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45913, 2, 15, 6, 'NPC Equip 45913', 4, 50138, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45914, 2, 15, 6, 'NPC Equip 45914', 4, 58518, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45915, 2, 15, 6, 'NPC Equip 45915', 4, 58507, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45916, 2, 15, 6, 'NPC Equip 45916', 4, 58514, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45917, 2, 15, 6, 'NPC Equip 45917', 4, 58509, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45918, 2, 15, 6, 'NPC Equip 45918', 2, 58505, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45919, 2, 15, 6, 'NPC Equip 45919', 4, 58498, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45920, 2, 15, 6, 'NPC Equip 45920', 4, 58512, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45921, 2, 15, 6, 'NPC Equip 45921', 4, 58506, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45922, 2, 15, 6, 'NPC Equip 45922', 4, 58510, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45923, 2, 15, 6, 'NPC Equip 45923', 4, 40609, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45925, 2, 15, 8, 'NPC Equip 45925', 1, 58521, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45926, 2, 8, -1, 'NPC Equip 45926', 1, 58676, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (45985, 2, 15, -1, 'NPC Equip 45985', 1, 58713, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46020, 2, 0, -1, 'NPC Equip 46020', 1, 58733, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46089, 2, 15, 6, 'NPC Equip 46089', 2, 58873, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46090, 2, 15, 6, 'NPC Equip 46090', 2, 58809, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46092, 4, 6, -1, 'NPC Equip 46092', 1, 58869, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46093, 4, 6, -1, 'NPC Equip 46093', 1, 58870, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46107, 2, 15, 6, 'NPC Equip 46107', 2, 59115, 21, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46112, 2, 3, -1, 'NPC Equip 46112', 1, 59329, 21, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46229, 4, 1, -1, 'NPC Equip 46229', 7, 58280, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46326, 4, 4, -1, 'NPC Equip 46326', 6, 59528, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46327, 4, 4, -1, 'NPC Equip 46327', 6, 59529, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46328, 4, 4, -1, 'NPC Equip 46328', 6, 59530, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46329, 4, 4, -1, 'NPC Equip 46329', 6, 59531, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46330, 4, 4, -1, 'NPC Equip 46330', 6, 59532, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46332, 4, 4, -1, 'NPC Equip 46332', 6, 59534, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46333, 4, 4, -1, 'NPC Equip 46333', 6, 59535, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46334, 4, 4, -1, 'NPC Equip 46334', 6, 59537, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46335, 4, 4, -1, 'NPC Equip 46335', 6, 59539, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46336, 0, 3, -1, 'NPC Equip 46336', 3, 56991, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46358, 15, 0, 0, 'NPC Equip 46358', 4, 59577, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46371, 2, 14, -1, 'NPC Equip 46371', 1, 59619, 13, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46375, 4, 0, -1, 'NPC Equip 46375', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46393, 4, 1, -1, 'NPC Equip 46393', 7, 33257, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46394, 4, 1, -1, 'NPC Equip 46394', 7, 33258, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46547, 2, 14, -1, 'NPC Equip 46547', 4, 34365, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46689, 2, 14, 14, 'NPC Equip 46689', 2, 59838, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46712, 4, 0, -1, 'NPC Equip 46712', 4, 59878, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46717, 0, 0, -1, 'NPC Equip 46717', 4, 59878, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46733, 2, 14, -1, 'NPC Equip 46733', 1, 59919, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46736, 2, 8, -1, 'NPC Equip 46736', 1, 59923, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46737, 2, 8, -1, 'NPC Equip 46737', 1, 59924, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46738, 2, 10, -1, 'NPC Equip 46738', 2, 59925, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46799, 7, 8, -1, 'NPC Equip 46799', 4, 4112, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46837, 2, 6, -1, 'NPC Equip 46837', 1, 60071, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46839, 4, 0, -1, 'NPC Equip 46839', -1, 31479, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46840, 4, 0, -1, 'NPC Equip 46840', -1, 31479, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46841, 2, 15, -1, 'NPC Equip 46841', 1, 7481, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46842, 4, 0, -1, 'NPC Equip 46842', 3, 44357, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46844, 4, 0, -1, 'NPC Equip 46844', 5, 39162, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46845, 0, 8, -1, 'NPC Equip 46845', 4, 8625, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46846, 0, 8, -1, 'NPC Equip 46846', 4, 8625, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46854, 6, 2, -1, 'NPC Equip 46854', 2, 60089, 24, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46862, 4, 2, -1, 'NPC Equip 46862', 8, 58797, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46863, 4, 2, -1, 'NPC Equip 46863', 8, 58798, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46864, 4, 2, -1, 'NPC Equip 46864', 8, 58799, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46865, 4, 2, -1, 'NPC Equip 46865', 8, 58800, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46866, 4, 2, -1, 'NPC Equip 46866', 8, 58796, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46873, 4, 0, -1, 'NPC Equip 46873', 7, 54171, 19, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46886, 12, 0, -1, 'NPC Equip 46886', 4, 60170, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46890, 15, 2, -1, 'NPC Equip 46890', 4, 25593, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46891, 15, 2, -1, 'NPC Equip 46891', 4, 60207, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46894, 15, 2, -1, 'NPC Equip 46894', 4, 1262, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46981, 2, 13, -1, 'NPC Equip 46981', 1, 31754, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46982, 2, 13, -1, 'NPC Equip 46982', 1, 60254, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46983, 2, 10, -1, 'NPC Equip 46983', 1, 60261, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46984, 2, 10, -1, 'NPC Equip 46984', 1, 60264, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46987, 2, 4, -1, 'NPC Equip 46987', 1, 60258, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (46998, 2, 3, -1, 'NPC Equip 46998', 1, 60259, 26, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47005, 2, 15, -1, 'NPC Equip 47005', 1, 60262, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47013, 2, 6, -1, 'NPC Equip 47013', 2, 60281, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47014, 2, 2, -1, 'NPC Equip 47014', 1, 60282, 15, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47024, 2, 0, -1, 'NPC Equip 47024', 1, 55906, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47025, 2, 18, -1, 'NPC Equip 47025', 2, 58880, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47026, 4, 4, -1, 'NPC Equip 47026', 6, 58746, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47027, 4, 4, -1, 'NPC Equip 47027', 1, 59219, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47028, 4, 2, -1, 'NPC Equip 47028', 8, 59746, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47031, 2, 6, -1, 'NPC Equip 47031', 2, 60283, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47032, 2, 0, -1, 'NPC Equip 47032', 1, 60284, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47034, 2, 1, -1, 'NPC Equip 47034', 1, 60286, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47065, 4, 0, -1, 'NPC Equip 47065', 3, 39123, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47102, 4, 1, -1, 'NPC Equip 47102', 7, 60350, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47103, 4, 1, -1, 'NPC Equip 47103', 7, 60352, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47117, 2, 15, -1, 'NPC Equip 47117', 1, 23248, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47118, 2, 1, -1, 'NPC Equip 47118', 1, 23904, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47119, 4, 3, -1, 'NPC Equip 47119', 5, 15809, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47120, 2, 4, -1, 'NPC Equip 47120', 2, 34109, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47122, 2, 2, -1, 'NPC Equip 47122', 2, 30926, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47123, 2, 10, -1, 'NPC Equip 47123', 2, 45947, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47124, 4, 0, -1, 'NPC Equip 47124', 4, 24784, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47125, 4, 3, -1, 'NPC Equip 47125', 5, 30925, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47127, 4, 4, -1, 'NPC Equip 47127', 6, 29964, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47128, 4, 2, -1, 'NPC Equip 47128', 8, 25700, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47134, 4, 2, -1, 'NPC Equip 47134', 8, 28179, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47135, 4, 0, -1, 'NPC Equip 47135', 4, 6337, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47136, 4, 1, -1, 'NPC Equip 47136', 7, 29798, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47137, 2, 7, -1, 'NPC Equip 47137', 1, 25648, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47158, 4, 3, -1, 'NPC Equip 47158', 5, 59148, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47159, 4, 4, -1, 'NPC Equip 47159', 1, 59696, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47160, 4, 2, -1, 'NPC Equip 47160', 8, 59741, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47161, 2, 0, -1, 'NPC Equip 47161', 1, 55906, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47162, 4, 0, -1, 'NPC Equip 47162', 3, 35313, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47331, 4, 4, -1, 'NPC Equip 47331', 1, 58748, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47332, 2, 6, -1, 'NPC Equip 47332', 1, 58913, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47333, 4, 1, -1, 'NPC Equip 47333', 7, 59028, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47334, 4, 0, -1, 'NPC Equip 47334', 3, 39123, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47335, 4, 1, -1, 'NPC Equip 47335', 7, 59734, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47336, 4, 3, -1, 'NPC Equip 47336', 5, 59181, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47337, 4, 1, -1, 'NPC Equip 47337', 7, 59004, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47338, 4, 4, -1, 'NPC Equip 47338', 1, 59194, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47339, 2, 4, -1, 'NPC Equip 47339', 1, 59368, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47340, 4, 1, -1, 'NPC Equip 47340', 7, 59727, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47341, 4, 1, -1, 'NPC Equip 47341', 7, 58998, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47342, 4, 3, -1, 'NPC Equip 47342', 5, 59185, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47343, 4, 2, -1, 'NPC Equip 47343', 8, 59127, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47344, 4, 1, -1, 'NPC Equip 47344', 7, 59732, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47345, 4, 0, -1, 'NPC Equip 47345', 4, 59249, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47346, 4, 0, -1, 'NPC Equip 47346', 3, 35313, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47347, 2, 0, -1, 'NPC Equip 47347', 1, 55906, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47348, 4, 2, -1, 'NPC Equip 47348', 8, 59741, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47349, 4, 4, -1, 'NPC Equip 47349', 1, 59696, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47350, 4, 3, -1, 'NPC Equip 47350', 5, 59148, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47351, 4, 4, -1, 'NPC Equip 47351', 1, 59207, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47352, 4, 0, -1, 'NPC Equip 47352', 3, 59661, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47353, 4, 2, -1, 'NPC Equip 47353', 8, 59112, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47354, 4, 0, -1, 'NPC Equip 47354', 4, 59307, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47355, 4, 1, -1, 'NPC Equip 47355', 7, 59728, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47356, 4, 0, -1, 'NPC Equip 47356', 4, 48510, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47357, 4, 4, -1, 'NPC Equip 47357', 6, 59697, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47358, 4, 0, -1, 'NPC Equip 47358', 4, 59322, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47359, 2, 10, -1, 'NPC Equip 47359', 2, 58927, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47360, 4, 1, -1, 'NPC Equip 47360', 7, 59508, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47361, 2, 15, -1, 'NPC Equip 47361', 1, 59371, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47362, 4, 2, -1, 'NPC Equip 47362', 8, 59114, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47363, 4, 4, -1, 'NPC Equip 47363', 6, 59713, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47364, 4, 0, -1, 'NPC Equip 47364', 3, 39209, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47365, 4, 3, -1, 'NPC Equip 47365', 5, 59248, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47366, 4, 3, -1, 'NPC Equip 47366', 5, 59166, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47367, 4, 4, -1, 'NPC Equip 47367', 6, 59205, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47368, 4, 1, -1, 'NPC Equip 47368', 7, 59024, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47369, 4, 2, -1, 'NPC Equip 47369', 8, 59129, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47370, 4, 1, -1, 'NPC Equip 47370', 7, 58997, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47371, 4, 0, -1, 'NPC Equip 47371', 4, 59320, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47372, 4, 3, -1, 'NPC Equip 47372', 5, 59257, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47373, 4, 4, -1, 'NPC Equip 47373', 1, 59705, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47374, 4, 6, -1, 'NPC Equip 47374', 6, 61786, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47375, 4, 1, -1, 'NPC Equip 47375', 7, 59726, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47376, 2, 1, -1, 'NPC Equip 47376', 1, 58876, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47377, 4, 2, -1, 'NPC Equip 47377', 8, 59738, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47378, 4, 4, -1, 'NPC Equip 47378', 6, 58770, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47379, 4, 0, -1, 'NPC Equip 47379', 5, 33808, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47380, 4, 3, -1, 'NPC Equip 47380', 5, 59236, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47381, 4, 3, -1, 'NPC Equip 47381', 5, 59159, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47382, 4, 4, -1, 'NPC Equip 47382', 6, 59201, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47383, 4, 0, -1, 'NPC Equip 47383', 3, 39123, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47384, 4, 2, -1, 'NPC Equip 47384', 8, 59100, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47385, 4, 0, -1, 'NPC Equip 47385', 3, 61790, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47386, 4, 1, -1, 'NPC Equip 47386', 7, 35430, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47387, 4, 1, -1, 'NPC Equip 47387', 7, 59010, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47388, 4, 4, -1, 'NPC Equip 47388', 1, 59714, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47389, 4, 0, -1, 'NPC Equip 47389', 3, 9858, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47390, 4, 0, -1, 'NPC Equip 47390', 4, 59319, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47391, 4, 2, -1, 'NPC Equip 47391', 8, 59746, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47392, 4, 4, -1, 'NPC Equip 47392', 1, 59219, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47393, 4, 4, -1, 'NPC Equip 47393', 6, 58746, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47394, 2, 18, -1, 'NPC Equip 47394', 2, 58880, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47396, 2, 0, -1, 'NPC Equip 47396', 1, 55906, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47397, 4, 3, -1, 'NPC Equip 47397', 5, 59153, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47398, 4, 1, -1, 'NPC Equip 47398', 7, 59021, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47399, 4, 4, -1, 'NPC Equip 47399', 1, 59204, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47400, 4, 2, -1, 'NPC Equip 47400', 8, 59094, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47401, 2, 15, -1, 'NPC Equip 47401', 1, 58888, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47402, 4, 6, -1, 'NPC Equip 47402', 6, 59290, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47403, 4, 2, -1, 'NPC Equip 47403', 8, 58763, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47404, 4, 1, -1, 'NPC Equip 47404', 7, 59003, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47405, 4, 1, -1, 'NPC Equip 47405', 7, 51374, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47406, 4, 1, -1, 'NPC Equip 47406', 7, 59028, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47407, 2, 15, -1, 'NPC Equip 47407', 1, 59371, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47408, 4, 4, -1, 'NPC Equip 47408', 1, 59716, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47409, 4, 4, -1, 'NPC Equip 47409', 1, 59698, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47410, 4, 0, -1, 'NPC Equip 47410', 5, 53042, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47411, 4, 3, -1, 'NPC Equip 47411', 5, 61858, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47488, 4, 0, -1, 'NPC Equip 47488', 3, 39123, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47505, 2, 6, -1, 'NPC Equip 47505', 1, 60430, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47542, 4, 1, -1, 'NPC Equip 47542', 7, 59202, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47543, 4, 1, -1, 'NPC Equip 47543', 7, 59202, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47544, 4, 1, -1, 'NPC Equip 47544', 7, 59202, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47555, 4, 1, -1, 'NPC Equip 47555', 7, 59028, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47842, 7, 3, -1, 'NPC Equip 47842', 8, 40557, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47844, 2, 15, -1, 'NPC Equip 47844', 1, 60542, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (47846, 2, 7, -1, 'NPC Equip 47846', 1, 60543, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48311, 4, 3, -1, 'NPC Equip 48311', 5, 59181, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48416, 0, 0, 3, 'NPC Equip 48416', 4, 59906, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48947, 2, 0, 0, 'NPC Equip 48947', 2, 60827, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48949, 2, 1, -1, 'NPC Equip 48949', 2, 60835, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48984, 4, 2, -1, 'NPC Equip 48984', 8, 60860, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48985, 4, 4, -1, 'NPC Equip 48985', 6, 60200, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48986, 4, 1, -1, 'NPC Equip 48986', 7, 60184, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48989, 4, 3, -1, 'NPC Equip 48989', 5, 60886, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48995, 4, 1, -1, 'NPC Equip 48995', 7, 60159, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (48996, 4, 4, -1, 'NPC Equip 48996', 6, 60898, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49016, 2, 14, -1, 'NPC Equip 49016', 2, 23917, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49018, 2, 4, -1, 'NPC Equip 49018', 1, 60973, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49020, 2, 4, -1, 'NPC Equip 49020', 1, 60978, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49022, 2, 2, -1, 'NPC Equip 49022', 2, 60979, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49024, 2, 4, -1, 'NPC Equip 49024', 1, 60980, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49070, 2, 13, -1, 'NPC Equip 49070', 1, 61020, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49072, 2, 13, -1, 'NPC Equip 49072', 1, 61021, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49106, 2, 8, -1, 'NPC Equip 49106', 1, 61058, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49122, 4, 4, -1, 'NPC Equip 49122', 8, 51920, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49148, 2, 1, -1, 'NPC Equip 49148', 1, 61095, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49152, 2, 15, -1, 'NPC Equip 49152', 1, 61115, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49154, 2, 15, -1, 'NPC Equip 49154', 1, 61117, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49156, 2, 1, -1, 'NPC Equip 49156', 1, 61133, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49158, 2, 2, -1, 'NPC Equip 49158', 2, 61136, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49160, 4, 0, -1, 'NPC Equip 49160', 1, 61143, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49198, 2, 1, -1, 'NPC Equip 49198', 2, 61565, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49206, 2, 4, -1, 'NPC Equip 49206', 2, 40660, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49224, 0, 0, -1, 'NPC Equip 49224', 4, 61964, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49225, 0, 0, -1, 'NPC Equip 49225', 4, 8623, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49291, 2, 1, 1, 'NPC Equip 49291', 1, 64907, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49292, 2, 8, -1, 'NPC Equip 49292', 1, 62259, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49293, 2, 5, -1, 'NPC Equip 49293', 1, 62244, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49311, 2, 10, -1, 'NPC Equip 49311', 2, 62257, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49341, 2, 7, -1, 'NPC Equip 49341', 1, 62282, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49342, 2, 7, -1, 'NPC Equip 49342', 1, 62283, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49344, 2, 7, -1, 'NPC Equip 49344', 1, 62286, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49345, 2, 7, -1, 'NPC Equip 49345', 1, 62287, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49346, 2, 7, -1, 'NPC Equip 49346', 1, 62288, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49349, 0, 0, -1, 'NPC Equip 49349', 4, 62351, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49353, 2, 6, -1, 'NPC Equip 49353', 1, 62366, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49357, 2, 4, -1, 'NPC Equip 49357', 1, 62414, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49358, 2, 4, -1, 'NPC Equip 49358', 2, 62413, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49363, 2, 6, 6, 'NPC Equip 49363', 1, 62481, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49372, 0, 0, -1, 'NPC Equip 49372', 4, 8623, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49374, 0, 0, -1, 'NPC Equip 49374', 4, 57288, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49377, 12, 0, -1, 'NPC Equip 49377', -1, 62525, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49637, 2, 7, -1, 'NPC Equip 49637', 1, 62880, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49638, 4, 6, -1, 'NPC Equip 49638', 1, 62881, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49653, 2, 10, -1, 'NPC Equip 49653', 2, 62902, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49654, 2, 6, -1, 'NPC Equip 49654', 1, 62906, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49658, 12, 0, -1, 'NPC Equip 49658', 4, 62910, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49659, 15, 2, -1, 'NPC Equip 49659', 4, 62911, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49660, 15, 2, -1, 'NPC Equip 49660', 4, 62912, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49664, 15, 2, -1, 'NPC Equip 49664', 4, 54324, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49666, 2, 8, -1, 'NPC Equip 49666', 1, 57463, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49675, 4, 0, -1, 'NPC Equip 49675', 8, 62218, 4, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49677, 12, 0, -1, 'NPC Equip 49677', 4, 62932, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49681, 2, 1, -1, 'NPC Equip 49681', 2, 62933, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49684, 2, 8, -1, 'NPC Equip 49684', 1, 62934, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49687, 2, 7, -1, 'NPC Equip 49687', 1, 62943, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49690, 2, 0, -1, 'NPC Equip 49690', 2, 63283, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49691, 2, 0, -1, 'NPC Equip 49691', 2, 62961, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49692, 0, 0, -1, 'NPC Equip 49692', 4, 62991, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49709, 2, 10, -1, 'NPC Equip 49709', 2, 63077, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49713, 2, 15, -1, 'NPC Equip 49713', 1, 60577, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49714, 2, 15, -1, 'NPC Equip 49714', 1, 60610, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49716, 2, 10, -1, 'NPC Equip 49716', 2, 58921, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49717, 2, 4, -1, 'NPC Equip 49717', 1, 61659, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49719, 2, 7, -1, 'NPC Equip 49719', 1, 60617, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49720, 4, 6, -1, 'NPC Equip 49720', 6, 61781, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49721, 2, 7, -1, 'NPC Equip 49721', 1, 60666, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49722, 4, 0, -1, 'NPC Equip 49722', 3, 61788, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49724, 2, 10, -1, 'NPC Equip 49724', 2, 60611, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49725, 2, 4, -1, 'NPC Equip 49725', 1, 60675, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49726, 4, 6, -1, 'NPC Equip 49726', 6, 54064, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49727, 2, 7, -1, 'NPC Equip 49727', 1, 60674, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49728, 4, 6, -1, 'NPC Equip 49728', 6, 62299, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49729, 2, 7, -1, 'NPC Equip 49729', 1, 60671, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49730, 4, 0, -1, 'NPC Equip 49730', 3, 61790, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49731, 2, 4, -1, 'NPC Equip 49731', 1, 61658, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49732, 4, 6, -1, 'NPC Equip 49732', 6, 59289, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49734, 2, 15, -1, 'NPC Equip 49734', 1, 60660, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49735, 2, 15, -1, 'NPC Equip 49735', 1, 60815, 22, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49736, 2, 10, -1, 'NPC Equip 49736', 2, 60626, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49737, 2, 4, -1, 'NPC Equip 49737', 1, 60673, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49738, 4, 6, -1, 'NPC Equip 49738', 6, 61785, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49741, 12, 0, -1, 'NPC Equip 49741', 4, 63118, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49761, 2, 2, -1, 'NPC Equip 49761', 1, 61687, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49762, 2, 3, -1, 'NPC Equip 49762', 1, 60623, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49763, 2, 7, -1, 'NPC Equip 49763', 1, 56663, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49764, 2, 15, -1, 'NPC Equip 49764', 1, 60592, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49767, 2, 8, -1, 'NPC Equip 49767', 1, 63202, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49768, 0, 4, -1, 'NPC Equip 49768', 7, 56319, 0, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49773, 2, 1, -1, 'NPC Equip 49773', 1, 63226, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49774, 2, 0, -1, 'NPC Equip 49774', 1, 63232, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49775, 2, 4, -1, 'NPC Equip 49775', 1, 63233, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49777, 4, 6, -1, 'NPC Equip 49777', 6, 63273, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49814, 2, 7, -1, 'NPC Equip 49814', 1, 63334, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49862, 2, 2, -1, 'NPC Equip 49862', 2, 63363, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49863, 0, 5, -1, 'NPC Equip 49863', 4, 34584, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49864, 2, 8, 8, 'NPC Equip 49864', 1, 63366, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49865, 12, 0, -1, 'NPC Equip 49865', -1, 63369, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49868, 12, 0, 0, 'NPC Equip 49868', -1, 63381, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49886, 2, 1, -1, 'NPC Equip 49886', 2, 63405, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49911, 15, 2, -1, 'NPC Equip 49911', 4, 63419, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49913, 12, 0, -1, 'NPC Equip 49913', 4, 64028, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49914, 2, 2, -1, 'NPC Equip 49914', 2, 63421, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49931, 2, 7, -1, 'NPC Equip 49931', 1, 63202, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49933, 4, 6, -1, 'NPC Equip 49933', 1, 63463, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (49935, 2, 15, -1, 'NPC Equip 49935', 1, 63448, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50004, 4, 0, -1, 'NPC Equip 50004', 4, 34132, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50007, 4, 0, -1, 'NPC Equip 50007', 4, 59319, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50013, 4, 0, -1, 'NPC Equip 50013', 4, 59318, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50029, 4, 0, -1, 'NPC Equip 50029', 4, 59249, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50039, 2, 8, 7, 'NPC Equip 50039', 0, 63548, 17, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50043, 2, 1, -1, 'NPC Equip 50043', 1, 63549, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50058, 4, 2, -1, 'NPC Equip 50058', 8, 59127, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50066, 4, 0, -1, 'NPC Equip 50066', 4, 59318, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50076, 0, 0, 0, 'NPC Equip 50076', 7, 12547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50083, 4, 4, -1, 'NPC Equip 50083', 6, 63560, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50084, 4, 4, -1, 'NPC Equip 50084', 6, 63561, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50085, 4, 4, -1, 'NPC Equip 50085', 6, 63563, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50091, 0, 0, 0, 'NPC Equip 50091', 7, 12547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50092, 0, 0, 0, 'NPC Equip 50092', 7, 12547, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50099, 4, 4, -1, 'NPC Equip 50099', 6, 63570, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50100, 4, 4, -1, 'NPC Equip 50100', 6, 63569, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50101, 4, 4, -1, 'NPC Equip 50101', 6, 63568, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50102, 4, 2, -1, 'NPC Equip 50102', 8, 63688, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50103, 4, 2, -1, 'NPC Equip 50103', 8, 63581, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50104, 4, 2, -1, 'NPC Equip 50104', 8, 63694, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50110, 4, 2, -1, 'NPC Equip 50110', 8, 63592, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50111, 4, 2, -1, 'NPC Equip 50111', 8, 63593, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50112, 4, 2, -1, 'NPC Equip 50112', 8, 63595, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50119, 4, 3, -1, 'NPC Equip 50119', 5, 63604, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50120, 4, 3, -1, 'NPC Equip 50120', 5, 63605, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50121, 4, 3, -1, 'NPC Equip 50121', 5, 63606, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50123, 4, 3, -1, 'NPC Equip 50123', 5, 63605, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50124, 4, 3, -1, 'NPC Equip 50124', 5, 63606, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50129, 2, 5, -1, 'NPC Equip 50129', 2, 63625, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50132, 4, 0, -1, 'NPC Equip 50132', 5, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50133, 4, 0, -1, 'NPC Equip 50133', 5, 35431, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50151, 15, 2, -1, 'NPC Equip 50151', 4, 34535, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50164, 0, 0, -1, 'NPC Equip 50164', 4, 64023, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50201, 4, 3, -1, 'NPC Equip 50201', 5, 59257, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50216, 4, 6, -1, 'NPC Equip 50216', 1, 63750, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50217, 2, 7, 7, 'NPC Equip 50217', 1, 63754, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50221, 2, 1, -1, 'NPC Equip 50221', 2, 63784, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50224, 2, 10, -1, 'NPC Equip 50224', 2, 63806, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50225, 2, 10, -1, 'NPC Equip 50225', 2, 63807, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50245, 4, 1, -1, 'NPC Equip 50245', 7, 63839, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50246, 4, 1, -1, 'NPC Equip 50246', 7, 63840, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50247, 4, 1, -1, 'NPC Equip 50247', 7, 63845, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50249, 2, 7, 7, 'NPC Equip 50249', 1, 63855, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50251, 2, 0, -1, 'NPC Equip 50251', 4, 63787, 22, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50252, 2, 7, 8, 'NPC Equip 50252', 0, 63548, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50256, 2, 0, -1, 'NPC Equip 50256', 4, 63787, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50257, 2, 7, -1, 'NPC Equip 50257', 1, 63859, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50280, 4, 1, -1, 'NPC Equip 50280', 7, 63884, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50281, 4, 1, -1, 'NPC Equip 50281', 7, 63885, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50282, 4, 1, -1, 'NPC Equip 50282', 7, 63886, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50321, 4, 4, -1, 'NPC Equip 50321', 6, 63928, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50322, 4, 4, -1, 'NPC Equip 50322', 6, 63927, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50323, 4, 4, -1, 'NPC Equip 50323', 6, 63934, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50329, 15, 0, -1, 'NPC Equip 50329', 6, 63935, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50330, 15, 0, -1, 'NPC Equip 50330', 6, 63935, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50331, 15, 0, -1, 'NPC Equip 50331', 6, 63935, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50332, 15, 0, -1, 'NPC Equip 50332', 6, 63935, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50347, 4, 0, -1, 'NPC Equip 50347', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50350, 4, 0, -1, 'NPC Equip 50350', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50389, 4, 1, -1, 'NPC Equip 50389', 7, 64164, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50390, 4, 1, -1, 'NPC Equip 50390', 7, 64165, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50395, 4, 1, -1, 'NPC Equip 50395', 7, 64166, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50419, 4, 6, -1, 'NPC Equip 50419', 1, 63998, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50422, 7, 2, -1, 'NPC Equip 50422', 8, 7627, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50433, 2, 0, -1, 'NPC Equip 50433', 1, 64009, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50434, 2, 1, -1, 'NPC Equip 50434', 2, 61565, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50475, 2, 5, -1, 'NPC Equip 50475', 1, 63834, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50476, 4, 0, -1, 'NPC Equip 50476', 5, 33808, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50477, 4, 3, -1, 'NPC Equip 50477', 5, 59660, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50478, 4, 4, -1, 'NPC Equip 50478', 1, 61879, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50479, 4, 2, -1, 'NPC Equip 50479', 8, 59738, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50480, 2, 15, -1, 'NPC Equip 50480', 1, 58888, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50481, 4, 0, -1, 'NPC Equip 50481', 4, 35358, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50482, 4, 0, -1, 'NPC Equip 50482', 3, 50376, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50483, 4, 4, -1, 'NPC Equip 50483', 6, 59713, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50484, 4, 4, -1, 'NPC Equip 50484', 1, 59714, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50485, 4, 1, -1, 'NPC Equip 50485', 7, 59726, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50486, 4, 0, -1, 'NPC Equip 50486', 3, 44841, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50487, 4, 2, -1, 'NPC Equip 50487', 8, 59123, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50488, 4, 6, -1, 'NPC Equip 50488', 6, 61888, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50489, 4, 4, -1, 'NPC Equip 50489', 1, 59210, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50490, 4, 0, -1, 'NPC Equip 50490', 5, 33808, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50491, 4, 3, -1, 'NPC Equip 50491', 5, 59631, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50492, 4, 4, -1, 'NPC Equip 50492', 6, 59700, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50493, 2, 15, -1, 'NPC Equip 50493', 1, 58881, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50494, 4, 0, -1, 'NPC Equip 50494', 3, 52632, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50495, 4, 4, -1, 'NPC Equip 50495', 6, 59201, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50496, 4, 4, -1, 'NPC Equip 50496', 6, 59697, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50497, 4, 4, -1, 'NPC Equip 50497', 1, 59707, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50498, 4, 3, -1, 'NPC Equip 50498', 5, 59280, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50499, 4, 0, -1, 'NPC Equip 50499', 4, 48510, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50500, 4, 1, -1, 'NPC Equip 50500', 7, 58977, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50501, 4, 1, -1, 'NPC Equip 50501', 7, 59508, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50502, 4, 2, -1, 'NPC Equip 50502', 8, 59100, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50503, 2, 19, -1, 'NPC Equip 50503', 2, 59389, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50504, 4, 4, -1, 'NPC Equip 50504', 1, 59204, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50505, 4, 0, -1, 'NPC Equip 50505', 3, 54999, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50506, 4, 0, -1, 'NPC Equip 50506', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50507, 4, 0, -1, 'NPC Equip 50507', 3, 61877, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50508, 4, 0, -1, 'NPC Equip 50508', 3, 50376, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50509, 4, 0, -1, 'NPC Equip 50509', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50510, 2, 2, -1, 'NPC Equip 50510', 1, 58878, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50511, 4, 4, -1, 'NPC Equip 50511', 1, 59696, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50512, 4, 4, -1, 'NPC Equip 50512', 1, 59711, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50513, 2, 15, -1, 'NPC Equip 50513', 1, 60171, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50514, 4, 0, -1, 'NPC Equip 50514', 3, 52632, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50515, 4, 1, -1, 'NPC Equip 50515', 7, 61862, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50516, 4, 0, -1, 'NPC Equip 50516', 3, 50376, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50517, 4, 3, -1, 'NPC Equip 50517', 5, 59185, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50518, 4, 2, -1, 'NPC Equip 50518', 8, 59744, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50519, 4, 0, -1, 'NPC Equip 50519', 3, 9852, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50520, 2, 10, -1, 'NPC Equip 50520', 2, 58920, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50521, 4, 2, -1, 'NPC Equip 50521', 8, 59128, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50522, 4, 4, -1, 'NPC Equip 50522', 1, 54711, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50523, 4, 1, -1, 'NPC Equip 50523', 7, 59728, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50524, 4, 3, -1, 'NPC Equip 50524', 5, 59166, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50525, 4, 1, -1, 'NPC Equip 50525', 7, 51374, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50526, 2, 0, -1, 'NPC Equip 50526', 1, 58877, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50527, 4, 3, -1, 'NPC Equip 50527', 5, 59236, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50528, 4, 2, -1, 'NPC Equip 50528', 8, 59746, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50529, 4, 0, -1, 'NPC Equip 50529', 5, 43095, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50530, 4, 0, -1, 'NPC Equip 50530', 3, 40051, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50531, 4, 4, -1, 'NPC Equip 50531', 1, 61876, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50532, 4, 4, -1, 'NPC Equip 50532', 1, 59715, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50533, 4, 1, -1, 'NPC Equip 50533', 7, 59989, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50534, 4, 0, -1, 'NPC Equip 50534', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50535, 4, 1, -1, 'NPC Equip 50535', 7, 61891, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50536, 4, 0, -1, 'NPC Equip 50536', 3, 34336, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50537, 4, 2, -1, 'NPC Equip 50537', 8, 59094, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50538, 4, 0, -1, 'NPC Equip 50538', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50539, 4, 4, -1, 'NPC Equip 50539', 1, 59194, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50540, 4, 1, -1, 'NPC Equip 50540', 7, 59028, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50541, 4, 0, -1, 'NPC Equip 50541', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50542, 4, 2, -1, 'NPC Equip 50542', 8, 59745, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50543, 4, 3, -1, 'NPC Equip 50543', 5, 59153, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50544, 2, 7, -1, 'NPC Equip 50544', 1, 59382, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50545, 4, 3, -1, 'NPC Equip 50545', 5, 59252, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50546, 4, 4, -1, 'NPC Equip 50546', 6, 59704, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50547, 4, 2, -1, 'NPC Equip 50547', 8, 58761, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50548, 2, 15, -1, 'NPC Equip 50548', 1, 60171, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50549, 4, 1, -1, 'NPC Equip 50549', 7, 58998, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50550, 4, 0, -1, 'NPC Equip 50550', 5, 31616, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50551, 4, 2, -1, 'NPC Equip 50551', 8, 59184, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50552, 4, 4, -1, 'NPC Equip 50552', 1, 59207, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50553, 4, 4, -1, 'NPC Equip 50553', 1, 59716, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50554, 4, 0, -1, 'NPC Equip 50554', 4, 48510, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50555, 4, 0, -1, 'NPC Equip 50555', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50556, 2, 19, -1, 'NPC Equip 50556', 2, 59389, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50557, 2, 4, -1, 'NPC Equip 50557', 1, 58909, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50558, 4, 1, -1, 'NPC Equip 50558', 7, 56215, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50559, 4, 3, -1, 'NPC Equip 50559', 5, 59284, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50560, 4, 3, -1, 'NPC Equip 50560', 5, 59148, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50561, 4, 3, -1, 'NPC Equip 50561', 5, 61885, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50562, 4, 4, -1, 'NPC Equip 50562', 1, 59699, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50563, 4, 4, -1, 'NPC Equip 50563', 6, 59708, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50564, 2, 13, -1, 'NPC Equip 50564', 1, 59387, 21, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50565, 4, 0, -1, 'NPC Equip 50565', 5, 43095, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50566, 4, 1, -1, 'NPC Equip 50566', 7, 59733, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50567, 2, 10, -1, 'NPC Equip 50567', 2, 58927, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50568, 4, 2, -1, 'NPC Equip 50568', 8, 59479, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50569, 4, 2, -1, 'NPC Equip 50569', 8, 58763, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50570, 4, 3, -1, 'NPC Equip 50570', 5, 59139, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50571, 4, 1, -1, 'NPC Equip 50571', 7, 59735, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50572, 4, 0, -1, 'NPC Equip 50572', 4, 35358, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50573, 4, 4, -1, 'NPC Equip 50573', -1, 59191, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50574, 4, 1, -1, 'NPC Equip 50574', 7, 61867, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50575, 4, 3, -1, 'NPC Equip 50575', 5, 59272, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50576, 2, 7, -1, 'NPC Equip 50576', 1, 58735, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50577, 4, 2, -1, 'NPC Equip 50577', 8, 59112, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50578, 4, 0, -1, 'NPC Equip 50578', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50579, 4, 2, -1, 'NPC Equip 50579', 8, 58747, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50580, 2, 4, -1, 'NPC Equip 50580', 1, 58908, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50581, 2, 1, -1, 'NPC Equip 50581', 1, 58876, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50582, 2, 13, -1, 'NPC Equip 50582', 1, 59387, 22, 7); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50583, 4, 3, -1, 'NPC Equip 50583', 5, 59248, 8, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50584, 4, 4, -1, 'NPC Equip 50584', 4, 59701, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50585, 4, 2, -1, 'NPC Equip 50585', 8, 59739, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50586, 4, 0, -1, 'NPC Equip 50586', 3, 44841, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50587, 4, 2, -1, 'NPC Equip 50587', 8, 59132, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50588, 4, 4, -1, 'NPC Equip 50588', 1, 59710, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50589, 4, 1, -1, 'NPC Equip 50589', 7, 61875, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50590, 4, 1, -1, 'NPC Equip 50590', 7, 59035, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50591, 4, 0, -1, 'NPC Equip 50591', 3, 61864, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50592, 4, 0, -1, 'NPC Equip 50592', 3, 50376, 11, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50593, 4, 4, -1, 'NPC Equip 50593', 6, 59205, 9, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50594, 4, 1, -1, 'NPC Equip 50594', 7, 59006, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50595, 4, 3, -1, 'NPC Equip 50595', 5, 59271, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50596, 4, 0, -1, 'NPC Equip 50596', 3, 40051, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50597, 2, 10, -1, 'NPC Equip 50597', 2, 58931, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50598, 4, 0, -1, 'NPC Equip 50598', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50599, 2, 6, -1, 'NPC Equip 50599', 1, 58915, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50600, 4, 0, -1, 'NPC Equip 50600', 3, 9852, 2, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50601, 4, 6, -1, 'NPC Equip 50601', 6, 57003, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50634, 4, 0, -1, 'NPC Equip 50634', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50637, 4, 0, -1, 'NPC Equip 50637', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50662, 4, 0, -1, 'NPC Equip 50662', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50666, 4, 0, -1, 'NPC Equip 50666', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50669, 4, 0, -1, 'NPC Equip 50669', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50683, 4, 0, -1, 'NPC Equip 50683', 4, 61409, 12, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50747, 4, 1, -1, 'NPC Equip 50747', 7, 61878, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50748, 4, 1, -1, 'NPC Equip 50748', 7, 61892, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50749, 4, 1, -1, 'NPC Equip 50749', 7, 61894, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50750, 4, 1, -1, 'NPC Equip 50750', 7, 62580, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50751, 4, 1, -1, 'NPC Equip 50751', 7, 61895, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50752, 2, 4, 4, 'NPC Equip 50752', 1, 64049, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50753, 2, 4, -1, 'NPC Equip 50753', 2, 64050, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50754, 2, 5, -1, 'NPC Equip 50754', 2, 55822, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50755, 2, 5, -1, 'NPC Equip 50755', 2, 64055, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50756, 2, 5, -1, 'NPC Equip 50756', 2, 64053, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50757, 2, 5, -1, 'NPC Equip 50757', 2, 53229, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50758, 2, 5, -1, 'NPC Equip 50758', 2, 64059, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50814, 2, 6, -1, 'NPC Equip 50814', 1, 63202, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50817, 2, 3, -1, 'NPC Equip 50817', 1, 20726, 26, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50870, 4, 4, -1, 'NPC Equip 50870', 6, 63571, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50871, 4, 4, -1, 'NPC Equip 50871', 6, 63572, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50872, 4, 4, -1, 'NPC Equip 50872', 4, 63573, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50873, 4, 4, -1, 'NPC Equip 50873', 1, 63574, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50874, 4, 4, -1, 'NPC Equip 50874', 1, 63575, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50875, 4, 4, -1, 'NPC Equip 50875', 1, 63575, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50876, 4, 4, -1, 'NPC Equip 50876', 1, 63574, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50877, 4, 4, -1, 'NPC Equip 50877', 4, 63573, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50878, 4, 4, -1, 'NPC Equip 50878', 6, 63572, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50879, 4, 4, -1, 'NPC Equip 50879', 6, 63571, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50880, 4, 2, -1, 'NPC Equip 50880', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50881, 4, 2, -1, 'NPC Equip 50881', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50882, 4, 2, -1, 'NPC Equip 50882', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50883, 4, 2, -1, 'NPC Equip 50883', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50884, 4, 2, -1, 'NPC Equip 50884', 8, 63587, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50885, 4, 2, -1, 'NPC Equip 50885', 8, 64085, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50886, 4, 2, -1, 'NPC Equip 50886', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50887, 4, 2, -1, 'NPC Equip 50887', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50888, 4, 2, -1, 'NPC Equip 50888', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50889, 4, 2, -1, 'NPC Equip 50889', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50890, 4, 2, -1, 'NPC Equip 50890', 8, 63587, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50891, 4, 2, -1, 'NPC Equip 50891', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50892, 4, 2, -1, 'NPC Equip 50892', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50893, 4, 2, -1, 'NPC Equip 50893', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50894, 4, 2, -1, 'NPC Equip 50894', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50895, 4, 3, -1, 'NPC Equip 50895', 5, 63602, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50896, 4, 3, -1, 'NPC Equip 50896', 5, 63603, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50897, 4, 3, -1, 'NPC Equip 50897', 5, 63600, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50898, 4, 3, -1, 'NPC Equip 50898', 5, 63599, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50899, 4, 3, -1, 'NPC Equip 50899', 5, 63597, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50900, 4, 1, -1, 'NPC Equip 50900', 7, 63883, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50901, 4, 1, -1, 'NPC Equip 50901', 7, 63882, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50902, 4, 1, -1, 'NPC Equip 50902', 7, 63881, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50903, 4, 1, -1, 'NPC Equip 50903', 7, 63880, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50904, 4, 1, -1, 'NPC Equip 50904', 7, 63879, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50905, 4, 4, -1, 'NPC Equip 50905', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50906, 4, 4, -1, 'NPC Equip 50906', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50907, 4, 4, -1, 'NPC Equip 50907', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50908, 4, 4, -1, 'NPC Equip 50908', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50909, 4, 4, -1, 'NPC Equip 50909', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50910, 4, 4, -1, 'NPC Equip 50910', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50911, 4, 4, -1, 'NPC Equip 50911', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50912, 4, 4, -1, 'NPC Equip 50912', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50913, 4, 4, -1, 'NPC Equip 50913', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50914, 4, 4, -1, 'NPC Equip 50914', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50915, 4, 4, -1, 'NPC Equip 50915', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50916, 4, 4, -1, 'NPC Equip 50916', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50917, 4, 4, -1, 'NPC Equip 50917', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50918, 4, 4, -1, 'NPC Equip 50918', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50919, 4, 4, -1, 'NPC Equip 50919', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50920, 4, 1, -1, 'NPC Equip 50920', 7, 63975, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50921, 4, 1, -1, 'NPC Equip 50921', 7, 63976, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50922, 4, 1, -1, 'NPC Equip 50922', 7, 63978, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50923, 4, 1, -1, 'NPC Equip 50923', 7, 63973, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50924, 4, 1, -1, 'NPC Equip 50924', 7, 63974, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50925, 4, 1, -1, 'NPC Equip 50925', 7, 63974, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50926, 4, 1, -1, 'NPC Equip 50926', 7, 64087, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50927, 4, 1, -1, 'NPC Equip 50927', 7, 63978, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50928, 4, 1, -1, 'NPC Equip 50928', 7, 63976, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50929, 4, 1, -1, 'NPC Equip 50929', 7, 63975, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50930, 4, 2, -1, 'NPC Equip 50930', 8, 63693, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50931, 4, 2, -1, 'NPC Equip 50931', 8, 63692, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50932, 4, 2, -1, 'NPC Equip 50932', 8, 63691, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50933, 4, 2, -1, 'NPC Equip 50933', 8, 63690, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50934, 4, 2, -1, 'NPC Equip 50934', 8, 63689, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50935, 4, 3, -1, 'NPC Equip 50935', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50936, 4, 3, -1, 'NPC Equip 50936', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50937, 4, 3, -1, 'NPC Equip 50937', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50938, 4, 3, -1, 'NPC Equip 50938', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50939, 4, 3, -1, 'NPC Equip 50939', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50940, 4, 3, -1, 'NPC Equip 50940', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50941, 4, 3, -1, 'NPC Equip 50941', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50942, 4, 3, -1, 'NPC Equip 50942', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50943, 4, 3, -1, 'NPC Equip 50943', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50944, 4, 3, -1, 'NPC Equip 50944', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50945, 4, 3, -1, 'NPC Equip 50945', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50946, 4, 3, -1, 'NPC Equip 50946', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50947, 4, 3, -1, 'NPC Equip 50947', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50948, 4, 3, -1, 'NPC Equip 50948', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50949, 4, 3, -1, 'NPC Equip 50949', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50950, 4, 1, -1, 'NPC Equip 50950', 7, 63846, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50951, 4, 1, -1, 'NPC Equip 50951', 7, 63844, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50952, 4, 1, -1, 'NPC Equip 50952', 7, 63984, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50953, 4, 1, -1, 'NPC Equip 50953', 7, 63842, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50954, 4, 1, -1, 'NPC Equip 50954', 7, 63841, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50955, 4, 4, -1, 'NPC Equip 50955', 6, 63566, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50956, 4, 4, -1, 'NPC Equip 50956', 6, 63565, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50957, 4, 4, -1, 'NPC Equip 50957', 4, 63830, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50958, 4, 4, -1, 'NPC Equip 50958', 1, 63562, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50959, 4, 4, -1, 'NPC Equip 50959', 1, 63559, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50960, 4, 4, -1, 'NPC Equip 50960', 1, 63559, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50961, 4, 4, -1, 'NPC Equip 50961', 1, 63562, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50962, 4, 4, -1, 'NPC Equip 50962', 4, 63830, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50963, 4, 4, -1, 'NPC Equip 50963', 6, 63565, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (50964, 4, 4, -1, 'NPC Equip 50964', 6, 63566, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51028, 2, 8, -1, 'NPC Equip 51028', 1, 60670, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51029, 2, 15, -1, 'NPC Equip 51029', 1, 60171, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51030, 4, 4, -1, 'NPC Equip 51030', 6, 63571, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51031, 4, 4, -1, 'NPC Equip 51031', 6, 63572, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51032, 4, 4, -1, 'NPC Equip 51032', 4, 63573, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51033, 4, 4, -1, 'NPC Equip 51033', 1, 63574, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51034, 4, 4, -1, 'NPC Equip 51034', 1, 63575, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51035, 4, 4, -1, 'NPC Equip 51035', 1, 63575, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51036, 4, 4, -1, 'NPC Equip 51036', 1, 63574, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51037, 4, 4, -1, 'NPC Equip 51037', 4, 63573, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51038, 4, 4, -1, 'NPC Equip 51038', 6, 63572, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51039, 4, 4, -1, 'NPC Equip 51039', 6, 63571, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51040, 4, 2, -1, 'NPC Equip 51040', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51041, 4, 2, -1, 'NPC Equip 51041', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51042, 4, 2, -1, 'NPC Equip 51042', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51043, 4, 2, -1, 'NPC Equip 51043', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51044, 4, 2, -1, 'NPC Equip 51044', 8, 63587, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51045, 4, 2, -1, 'NPC Equip 51045', 8, 64085, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51046, 4, 2, -1, 'NPC Equip 51046', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51047, 4, 2, -1, 'NPC Equip 51047', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51048, 4, 2, -1, 'NPC Equip 51048', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51049, 4, 2, -1, 'NPC Equip 51049', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51050, 4, 2, -1, 'NPC Equip 51050', 8, 63587, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51051, 4, 2, -1, 'NPC Equip 51051', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51052, 4, 2, -1, 'NPC Equip 51052', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51053, 4, 2, -1, 'NPC Equip 51053', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51054, 4, 2, -1, 'NPC Equip 51054', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51055, 4, 3, -1, 'NPC Equip 51055', 5, 63602, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51056, 4, 3, -1, 'NPC Equip 51056', 5, 63603, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51057, 4, 3, -1, 'NPC Equip 51057', 5, 63600, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51058, 4, 3, -1, 'NPC Equip 51058', 5, 63599, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51059, 4, 3, -1, 'NPC Equip 51059', 5, 63597, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51060, 4, 1, -1, 'NPC Equip 51060', 7, 63883, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51061, 4, 1, -1, 'NPC Equip 51061', 7, 63882, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51062, 4, 1, -1, 'NPC Equip 51062', 7, 63881, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51063, 4, 1, -1, 'NPC Equip 51063', 7, 63880, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51064, 4, 1, -1, 'NPC Equip 51064', 7, 63879, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51065, 4, 4, -1, 'NPC Equip 51065', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51066, 4, 4, -1, 'NPC Equip 51066', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51067, 4, 4, -1, 'NPC Equip 51067', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51068, 4, 4, -1, 'NPC Equip 51068', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51069, 4, 4, -1, 'NPC Equip 51069', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51070, 4, 4, -1, 'NPC Equip 51070', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51071, 4, 4, -1, 'NPC Equip 51071', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51072, 4, 4, -1, 'NPC Equip 51072', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51073, 4, 4, -1, 'NPC Equip 51073', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51074, 4, 4, -1, 'NPC Equip 51074', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51075, 4, 4, -1, 'NPC Equip 51075', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51076, 4, 4, -1, 'NPC Equip 51076', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51077, 4, 4, -1, 'NPC Equip 51077', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51078, 4, 4, -1, 'NPC Equip 51078', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51079, 4, 4, -1, 'NPC Equip 51079', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51080, 4, 1, -1, 'NPC Equip 51080', 7, 63975, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51081, 4, 1, -1, 'NPC Equip 51081', 7, 63976, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51082, 4, 1, -1, 'NPC Equip 51082', 7, 63978, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51083, 4, 1, -1, 'NPC Equip 51083', 7, 63973, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51084, 4, 1, -1, 'NPC Equip 51084', 7, 63974, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51085, 4, 1, -1, 'NPC Equip 51085', 7, 63974, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51086, 4, 1, -1, 'NPC Equip 51086', 7, 64087, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51087, 4, 1, -1, 'NPC Equip 51087', 7, 63978, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51088, 4, 1, -1, 'NPC Equip 51088', 7, 63976, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51089, 4, 1, -1, 'NPC Equip 51089', 7, 63975, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51090, 4, 2, -1, 'NPC Equip 51090', 8, 63693, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51091, 4, 2, -1, 'NPC Equip 51091', 8, 63692, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51092, 4, 2, -1, 'NPC Equip 51092', 8, 63691, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51093, 4, 2, -1, 'NPC Equip 51093', 8, 63690, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51094, 4, 2, -1, 'NPC Equip 51094', 8, 63689, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51095, 4, 3, -1, 'NPC Equip 51095', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51096, 4, 3, -1, 'NPC Equip 51096', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51097, 4, 3, -1, 'NPC Equip 51097', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51098, 4, 3, -1, 'NPC Equip 51098', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51099, 4, 3, -1, 'NPC Equip 51099', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51100, 4, 3, -1, 'NPC Equip 51100', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51101, 4, 3, -1, 'NPC Equip 51101', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51102, 4, 3, -1, 'NPC Equip 51102', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51103, 4, 3, -1, 'NPC Equip 51103', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51104, 4, 3, -1, 'NPC Equip 51104', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51105, 4, 3, -1, 'NPC Equip 51105', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51106, 4, 3, -1, 'NPC Equip 51106', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51107, 4, 3, -1, 'NPC Equip 51107', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51108, 4, 3, -1, 'NPC Equip 51108', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51109, 4, 3, -1, 'NPC Equip 51109', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51110, 4, 1, -1, 'NPC Equip 51110', 7, 63846, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51111, 4, 1, -1, 'NPC Equip 51111', 7, 63844, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51112, 4, 1, -1, 'NPC Equip 51112', 7, 63984, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51113, 4, 1, -1, 'NPC Equip 51113', 7, 63842, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51114, 4, 1, -1, 'NPC Equip 51114', 7, 63841, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51115, 4, 4, -1, 'NPC Equip 51115', 6, 63566, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51116, 4, 4, -1, 'NPC Equip 51116', 6, 63565, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51117, 4, 4, -1, 'NPC Equip 51117', 4, 63830, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51118, 4, 4, -1, 'NPC Equip 51118', 1, 63562, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51119, 4, 4, -1, 'NPC Equip 51119', 1, 63559, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51120, 4, 4, -1, 'NPC Equip 51120', 1, 63559, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51121, 4, 4, -1, 'NPC Equip 51121', 1, 63562, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51122, 4, 4, -1, 'NPC Equip 51122', 4, 63830, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51123, 4, 4, -1, 'NPC Equip 51123', 6, 63565, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51124, 4, 4, -1, 'NPC Equip 51124', 6, 63566, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51322, 2, 1, -1, 'NPC Equip 51322', 1, 58876, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51323, 2, 7, -1, 'NPC Equip 51323', 1, 59382, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51324, 4, 6, -1, 'NPC Equip 51324', 6, 57003, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51587, 4, 4, -1, 'NPC Equip 51587', 6, 63571, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51588, 4, 4, -1, 'NPC Equip 51588', 6, 63572, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51589, 4, 4, -1, 'NPC Equip 51589', 4, 63573, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51590, 4, 4, -1, 'NPC Equip 51590', 1, 63574, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51591, 4, 4, -1, 'NPC Equip 51591', 1, 63575, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51592, 4, 4, -1, 'NPC Equip 51592', 1, 63575, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51593, 4, 4, -1, 'NPC Equip 51593', 1, 63574, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51594, 4, 4, -1, 'NPC Equip 51594', 4, 63573, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51595, 4, 4, -1, 'NPC Equip 51595', 6, 63572, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51596, 4, 4, -1, 'NPC Equip 51596', 6, 63571, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51597, 4, 2, -1, 'NPC Equip 51597', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51598, 4, 2, -1, 'NPC Equip 51598', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51599, 4, 2, -1, 'NPC Equip 51599', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51600, 4, 2, -1, 'NPC Equip 51600', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51601, 4, 2, -1, 'NPC Equip 51601', 8, 63587, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51602, 4, 2, -1, 'NPC Equip 51602', 8, 64085, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51603, 4, 2, -1, 'NPC Equip 51603', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51604, 4, 2, -1, 'NPC Equip 51604', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51605, 4, 2, -1, 'NPC Equip 51605', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51606, 4, 2, -1, 'NPC Equip 51606', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51607, 4, 2, -1, 'NPC Equip 51607', 8, 63587, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51608, 4, 2, -1, 'NPC Equip 51608', 8, 63588, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51609, 4, 2, -1, 'NPC Equip 51609', 8, 63589, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51610, 4, 2, -1, 'NPC Equip 51610', 8, 63590, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51611, 4, 2, -1, 'NPC Equip 51611', 8, 63596, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51612, 4, 3, -1, 'NPC Equip 51612', 5, 63602, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51613, 4, 3, -1, 'NPC Equip 51613', 5, 63603, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51614, 4, 3, -1, 'NPC Equip 51614', 5, 63600, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51615, 4, 3, -1, 'NPC Equip 51615', 5, 63599, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51616, 4, 3, -1, 'NPC Equip 51616', 5, 63597, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51617, 4, 1, -1, 'NPC Equip 51617', 7, 63883, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51618, 4, 1, -1, 'NPC Equip 51618', 7, 63882, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51619, 4, 1, -1, 'NPC Equip 51619', 7, 63881, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51620, 4, 1, -1, 'NPC Equip 51620', 7, 63880, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51621, 4, 1, -1, 'NPC Equip 51621', 7, 63879, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51622, 4, 4, -1, 'NPC Equip 51622', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51623, 4, 4, -1, 'NPC Equip 51623', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51624, 4, 4, -1, 'NPC Equip 51624', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51625, 4, 4, -1, 'NPC Equip 51625', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51626, 4, 4, -1, 'NPC Equip 51626', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51627, 4, 4, -1, 'NPC Equip 51627', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51628, 4, 4, -1, 'NPC Equip 51628', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51629, 4, 4, -1, 'NPC Equip 51629', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51630, 4, 4, -1, 'NPC Equip 51630', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51631, 4, 4, -1, 'NPC Equip 51631', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51632, 4, 4, -1, 'NPC Equip 51632', 1, 63929, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51633, 4, 4, -1, 'NPC Equip 51633', 1, 63930, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51634, 4, 4, -1, 'NPC Equip 51634', 4, 63931, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51635, 4, 4, -1, 'NPC Equip 51635', 6, 64061, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51636, 4, 4, -1, 'NPC Equip 51636', 6, 63933, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51637, 4, 1, -1, 'NPC Equip 51637', 7, 63975, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51638, 4, 1, -1, 'NPC Equip 51638', 7, 63976, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51639, 4, 1, -1, 'NPC Equip 51639', 7, 63978, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51640, 4, 1, -1, 'NPC Equip 51640', 7, 63973, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51641, 4, 1, -1, 'NPC Equip 51641', 7, 63974, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51642, 4, 1, -1, 'NPC Equip 51642', 7, 63974, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51643, 4, 1, -1, 'NPC Equip 51643', 7, 64087, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51644, 4, 1, -1, 'NPC Equip 51644', 7, 63978, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51645, 4, 1, -1, 'NPC Equip 51645', 7, 63976, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51646, 4, 1, -1, 'NPC Equip 51646', 7, 63975, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51647, 4, 2, -1, 'NPC Equip 51647', 8, 63693, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51648, 4, 2, -1, 'NPC Equip 51648', 8, 63692, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51649, 4, 2, -1, 'NPC Equip 51649', 8, 63691, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51650, 4, 2, -1, 'NPC Equip 51650', 8, 63690, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51651, 4, 2, -1, 'NPC Equip 51651', 8, 63689, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51652, 4, 3, -1, 'NPC Equip 51652', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51653, 4, 3, -1, 'NPC Equip 51653', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51654, 4, 3, -1, 'NPC Equip 51654', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51655, 4, 3, -1, 'NPC Equip 51655', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51656, 4, 3, -1, 'NPC Equip 51656', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51657, 4, 3, -1, 'NPC Equip 51657', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51658, 4, 3, -1, 'NPC Equip 51658', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51659, 4, 3, -1, 'NPC Equip 51659', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51660, 4, 3, -1, 'NPC Equip 51660', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51661, 4, 3, -1, 'NPC Equip 51661', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51662, 4, 3, -1, 'NPC Equip 51662', 5, 57057, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51663, 4, 3, -1, 'NPC Equip 51663', 5, 57060, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51664, 4, 3, -1, 'NPC Equip 51664', 5, 57058, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51665, 4, 3, -1, 'NPC Equip 51665', 5, 57065, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51666, 4, 3, -1, 'NPC Equip 51666', 5, 57063, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51667, 4, 1, -1, 'NPC Equip 51667', 7, 63846, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51668, 4, 1, -1, 'NPC Equip 51668', 7, 63844, 20, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51669, 4, 1, -1, 'NPC Equip 51669', 7, 63984, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51670, 4, 1, -1, 'NPC Equip 51670', 7, 63842, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51671, 4, 1, -1, 'NPC Equip 51671', 7, 63841, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51672, 4, 4, -1, 'NPC Equip 51672', 6, 63566, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51673, 4, 4, -1, 'NPC Equip 51673', 6, 63565, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51674, 4, 4, -1, 'NPC Equip 51674', 4, 63830, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51675, 4, 4, -1, 'NPC Equip 51675', 1, 63562, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51676, 4, 4, -1, 'NPC Equip 51676', 1, 63559, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51677, 4, 4, -1, 'NPC Equip 51677', 1, 63559, 5, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51678, 4, 4, -1, 'NPC Equip 51678', 1, 63562, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51679, 4, 4, -1, 'NPC Equip 51679', 4, 63830, 1, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51680, 4, 4, -1, 'NPC Equip 51680', 6, 63565, 7, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51681, 4, 4, -1, 'NPC Equip 51681', 6, 63566, 3, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51949, 2, 6, -1, 'NPC Equip 51949', 1, 64234, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51986, 4, 4, -1, 'NPC Equip 51986', 6, 52055, 6, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (51988, 4, 4, -1, 'NPC Equip 51988', 6, 52054, 10, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52007, 2, 7, -1, 'NPC Equip 52007', 1, 53563, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52008, 4, 6, -1, 'NPC Equip 52008', 1, 51453, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52009, 2, 10, -1, 'NPC Equip 52009', 2, 35563, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52010, 2, 6, -1, 'NPC Equip 52010', 1, 50350, 17, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52012, 2, 10, -1, 'NPC Equip 52012', 2, 48290, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52015, 2, 4, -1, 'NPC Equip 52015', 1, 54760, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52016, 2, 10, -1, 'NPC Equip 52016', 2, 55711, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52033, 2, 10, -1, 'NPC Equip 52033', 2, 64905, 17, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52034, 2, 7, -1, 'NPC Equip 52034', 1, 64906, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52037, 2, 4, -1, 'NPC Equip 52037', 2, 64910, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52042, 2, 4, -1, 'NPC Equip 52042', 1, 64994, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52058, 2, 2, -1, 'NPC Equip 52058', 2, 43809, 15, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52356, 2, 14, -1, 'NPC Equip 52356', 2, 65519, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52357, 4, 0, -1, 'NPC Equip 52357', 2, 65520, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52358, 2, 14, -1, 'NPC Equip 52358', 2, 65521, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52359, 4, 0, -1, 'NPC Equip 52359', 2, 65521, 23, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52361, 0, 0, -1, 'NPC Equip 52361', 4, 65526, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52686, 2, 7, -1, 'NPC Equip 52686', 1, 65871, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (52713, 12, 0, -1, 'NPC Equip 52713', 4, 65909, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53055, 2, 7, -1, 'NPC Equip 53055', 1, 66128, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53056, 2, 7, -1, 'NPC Equip 53056', 1, 66129, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53096, 2, 4, -1, 'NPC Equip 53096', 1, 60714, 21, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53473, 4, 0, -1, 'NPC Equip 53473', 7, 66207, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53474, 4, 0, -1, 'NPC Equip 53474', 7, 66212, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53475, 4, 0, -1, 'NPC Equip 53475', 7, 66213, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53476, 0, 0, -1, 'NPC Equip 53476', 7, 66218, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53477, 0, 0, -1, 'NPC Equip 53477', 7, 66228, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53785, 2, 4, 4, 'NPC Equip 53785', 1, 66474, 13, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53835, 2, 7, -1, 'NPC Equip 53835', 1, 66550, 13, 2); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53933, 4, 6, -1, 'NPC Equip 53933', 1, 52200, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53934, 4, 6, -1, 'NPC Equip 53934', 1, 52199, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53935, 4, 6, -1, 'NPC Equip 53935', 1, 52201, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53936, 4, 6, -1, 'NPC Equip 53936', 1, 52202, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53937, 4, 6, -1, 'NPC Equip 53937', 1, 23976, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53938, 4, 6, -1, 'NPC Equip 53938', 1, 38258, 14, 4); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (53963, 2, 1, -1, 'NPC Equip 53963', 2, 67204, 13, 1); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (54468, 15, 0, -1, 'NPC Equip 54468', 7, 23293, 0, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (54555, 2, 4, 4, 'NPC Equip 54555', 1, 67187, 17, 3); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (54612, 2, 14, -1, 'NPC Equip 54612', 1, 67215, 13, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (54647, 0, 0, -1, 'NPC Equip 54647', 7, 66184, 16, 0); +INSERT INTO item_template (entry, class, subclass, SoundOverrideSubclass, name, Material, displayid, InventoryType, sheath) VALUES (54848, 4, 3, -1, 'NPC Equip 54848', 5, 65233, 3, 0); diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index c64a15ca1c..30ce4fe1fc 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -20,6 +20,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux") if(SERVERS AND NOT NOJEM) add_subdirectory(jemalloc) endif() + if(TOOLS) + add_subdirectory(bzip2) + endif() + add_subdirectory(zlib) endif() if(CMAKE_SYSTEM_NAME MATCHES "Windows") diff --git a/deps/PackageList.txt b/deps/PackageList.txt index 41edd5348f..30fcb8dbab 100644 --- a/deps/PackageList.txt +++ b/deps/PackageList.txt @@ -14,7 +14,7 @@ G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License) jemalloc (a general-purpose scalable concurrent malloc-implementation) http://www.canonware.com/jemalloc/ - Version: 3.5.1 + Version: 5.0.1 libMPQ (a library for reading MPQ files) https://libmpq.org/ @@ -41,5 +41,5 @@ gSOAP (a portable development toolkit for C and C++ XML Web services and XML dat Version: 2.8.10 recastnavigation (Recast is state of the art navigation mesh construction toolset for games) - http://code.google.com/p/recastnavigation/ - Version: 1.4 + https://github.com/memononen/recastnavigation + Version: 64385e9ed0822427bca5814d03a3f4c4d7a6db9f diff --git a/deps/jemalloc/CMakeLists.txt b/deps/jemalloc/CMakeLists.txt index b1725f6e19..8e937b67c1 100644 --- a/deps/jemalloc/CMakeLists.txt +++ b/deps/jemalloc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) +# Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without @@ -8,14 +8,24 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# We need to generate the jemalloc_def.h header based on platform-specific settings -if (PLATFORM EQUAL 32) - set(JEM_SIZEDEF 2) - set(JEM_TLSMODEL) -else() - set(JEM_SIZEDEF 3) - set(JEM_TLSMODEL "__attribute__\(\(tls_model\(\"initial-exec\"\)\)\)") -endif() + # We need to generate the jemalloc_def.h header based on platform-specific settings + CHECK_SYMBOL_EXISTS(MADV_FREE "sys/mman.h" HAVE_MADV_FREE) + + if (PLATFORM EQUAL 32) + set(JEM_SIZEDEF 2) + set(JEM_TLSMODEL) + set(JEM_VADDRBITS 32) + else() + set(JEM_SIZEDEF 3) + set(JEM_TLSMODEL "__attribute__\(\(tls_model\(\"initial-exec\"\)\)\)") + set(JEM_VADDRBITS 48) + endif() + + if (HAVE_MADV_FREE) + set(JEM_MADFREE_DEF "#define") + else() + set(JEM_MADFREE_DEF "#undef") + endif() # Create the header, so we can use it configure_file( @@ -24,31 +34,38 @@ configure_file( @ONLY ) -# Done, let's continue -set(jemalloc_STAT_SRC - ${CMAKE_CURRENT_SOURCE_DIR}/src/arena.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/atomic.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/base.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/bitmap.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_dss.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/chunk_mmap.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ckh.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/ctl.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/extent.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/hash.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/huge.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/jemalloc.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/mb.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/mutex.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/prof.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/quarantine.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/rtree.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/stats.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/tcache.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/tsd.c - ${CMAKE_CURRENT_SOURCE_DIR}/src/util.c -) + # Done, let's continue + set(jemalloc_STAT_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/arena.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/background_thread.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/base.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/bitmap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ckh.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ctl.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/extent.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/extent_dss.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/extent_mmap.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hash.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hooks.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jemalloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/jemalloc_cpp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/large.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/malloc_io.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mutex.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/mutex_pool.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/nstime.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/pages.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/prng.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/prof.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/rtree.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/spin.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/stats.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/sz.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tcache.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/ticker.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/tsd.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/witness.c + ) include_directories( ${BUILDDIR}/ @@ -58,3 +75,12 @@ include_directories( add_definitions(-D_GNU_SOURCE -D_REENTRANT) add_library(jemalloc STATIC ${jemalloc_STAT_SRC}) + +target_link_libraries(jemalloc + PUBLIC + ${CMAKE_DL_LIBS}) + +set_target_properties(jemalloc + PROPERTIES + FOLDER + "deps") diff --git a/deps/jemalloc/COPYING b/deps/jemalloc/COPYING index bdda0feb9e..e308632a81 100644 --- a/deps/jemalloc/COPYING +++ b/deps/jemalloc/COPYING @@ -1,10 +1,10 @@ Unless otherwise specified, files in the jemalloc source distribution are subject to the following license: -------------------------------------------------------------------------------- -Copyright (C) 2002-2014 Jason Evans <jasone@canonware.com>. +Copyright (C) 2002-2017 Jason Evans <jasone@canonware.com>. All rights reserved. Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved. -Copyright (C) 2009-2014 Facebook, Inc. All rights reserved. +Copyright (C) 2009-2017 Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/deps/jemalloc/ChangeLog b/deps/jemalloc/ChangeLog index d56ee999e6..ee1b7ead39 100644 --- a/deps/jemalloc/ChangeLog +++ b/deps/jemalloc/ChangeLog @@ -1,10 +1,727 @@ Following are change highlights associated with official releases. Important -bug fixes are all mentioned, but internal enhancements are omitted here for -brevity (even though they are more fun to write about). Much more detail can be -found in the git revision history: +bug fixes are all mentioned, but some internal enhancements are omitted here for +brevity. Much more detail can be found in the git revision history: https://github.com/jemalloc/jemalloc +* 5.0.1 (July 1, 2017) + + This bugfix release fixes several issues, most of which are obscure enough + that typical applications are not impacted. + + Bug fixes: + - Update decay->nunpurged before purging, in order to avoid potential update + races and subsequent incorrect purging volume. (@interwq) + - Only abort on dlsym(3) error if the failure impacts an enabled feature (lazy + locking and/or background threads). This mitigates an initialization + failure bug for which we still do not have a clear reproduction test case. + (@interwq) + - Modify tsd management so that it neither crashes nor leaks if a thread's + only allocation activity is to call free() after TLS destructors have been + executed. This behavior was observed when operating with GNU libc, and is + unlikely to be an issue with other libc implementations. (@interwq) + - Mask signals during background thread creation. This prevents signals from + being inadvertently delivered to background threads. (@jasone, + @davidgoldblatt, @interwq) + - Avoid inactivity checks within background threads, in order to prevent + recursive mutex acquisition. (@interwq) + - Fix extent_grow_retained() to use the specified hooks when the + arena.<i>.extent_hooks mallctl is used to override the default hooks. + (@interwq) + - Add missing reentrancy support for custom extent hooks which allocate. + (@interwq) + - Post-fork(2), re-initialize the list of tcaches associated with each arena + to contain no tcaches except the forking thread's. (@interwq) + - Add missing post-fork(2) mutex reinitialization for extent_grow_mtx. This + fixes potential deadlocks after fork(2). (@interwq) + - Enforce minimum autoconf version (currently 2.68), since 2.63 is known to + generate corrupt configure scripts. (@jasone) + - Ensure that the configured page size (--with-lg-page) is no larger than the + configured huge page size (--with-lg-hugepage). (@jasone) + +* 5.0.0 (June 13, 2017) + + Unlike all previous jemalloc releases, this release does not use naturally + aligned "chunks" for virtual memory management, and instead uses page-aligned + "extents". This change has few externally visible effects, but the internal + impacts are... extensive. Many other internal changes combine to make this + the most cohesively designed version of jemalloc so far, with ample + opportunity for further enhancements. + + Continuous integration is now an integral aspect of development thanks to the + efforts of @davidtgoldblatt, and the dev branch tends to remain reasonably + stable on the tested platforms (Linux, FreeBSD, macOS, and Windows). As a + side effect the official release frequency may decrease over time. + + New features: + - Implement optional per-CPU arena support; threads choose which arena to use + based on current CPU rather than on fixed thread-->arena associations. + (@interwq) + - Implement two-phase decay of unused dirty pages. Pages transition from + dirty-->muzzy-->clean, where the first phase transition relies on + madvise(... MADV_FREE) semantics, and the second phase transition discards + pages such that they are replaced with demand-zeroed pages on next access. + (@jasone) + - Increase decay time resolution from seconds to milliseconds. (@jasone) + - Implement opt-in per CPU background threads, and use them for asynchronous + decay-driven unused dirty page purging. (@interwq) + - Add mutex profiling, which collects a variety of statistics useful for + diagnosing overhead/contention issues. (@interwq) + - Add C++ new/delete operator bindings. (@djwatson) + - Support manually created arena destruction, such that all data and metadata + are discarded. Add MALLCTL_ARENAS_DESTROYED for accessing merged stats + associated with destroyed arenas. (@jasone) + - Add MALLCTL_ARENAS_ALL as a fixed index for use in accessing + merged/destroyed arena statistics via mallctl. (@jasone) + - Add opt.abort_conf to optionally abort if invalid configuration options are + detected during initialization. (@interwq) + - Add opt.stats_print_opts, so that e.g. JSON output can be selected for the + stats dumped during exit if opt.stats_print is true. (@jasone) + - Add --with-version=VERSION for use when embedding jemalloc into another + project's git repository. (@jasone) + - Add --disable-thp to support cross compiling. (@jasone) + - Add --with-lg-hugepage to support cross compiling. (@jasone) + - Add mallctl interfaces (various authors): + + background_thread + + opt.abort_conf + + opt.retain + + opt.percpu_arena + + opt.background_thread + + opt.{dirty,muzzy}_decay_ms + + opt.stats_print_opts + + arena.<i>.initialized + + arena.<i>.destroy + + arena.<i>.{dirty,muzzy}_decay_ms + + arena.<i>.extent_hooks + + arenas.{dirty,muzzy}_decay_ms + + arenas.bin.<i>.slab_size + + arenas.nlextents + + arenas.lextent.<i>.size + + arenas.create + + stats.background_thread.{num_threads,num_runs,run_interval} + + stats.mutexes.{ctl,background_thread,prof,reset}. + {num_ops,num_spin_acq,num_wait,max_wait_time,total_wait_time,max_num_thds, + num_owner_switch} + + stats.arenas.<i>.{dirty,muzzy}_decay_ms + + stats.arenas.<i>.uptime + + stats.arenas.<i>.{pmuzzy,base,internal,resident} + + stats.arenas.<i>.{dirty,muzzy}_{npurge,nmadvise,purged} + + stats.arenas.<i>.bins.<j>.{nslabs,reslabs,curslabs} + + stats.arenas.<i>.bins.<j>.mutex. + {num_ops,num_spin_acq,num_wait,max_wait_time,total_wait_time,max_num_thds, + num_owner_switch} + + stats.arenas.<i>.lextents.<j>.{nmalloc,ndalloc,nrequests,curlextents} + + stats.arenas.i.mutexes.{large,extent_avail,extents_dirty,extents_muzzy, + extents_retained,decay_dirty,decay_muzzy,base,tcache_list}. + {num_ops,num_spin_acq,num_wait,max_wait_time,total_wait_time,max_num_thds, + num_owner_switch} + + Portability improvements: + - Improve reentrant allocation support, such that deadlock is less likely if + e.g. a system library call in turn allocates memory. (@davidtgoldblatt, + @interwq) + - Support static linking of jemalloc with glibc. (@djwatson) + + Optimizations and refactors: + - Organize virtual memory as "extents" of virtual memory pages, rather than as + naturally aligned "chunks", and store all metadata in arbitrarily distant + locations. This reduces virtual memory external fragmentation, and will + interact better with huge pages (not yet explicitly supported). (@jasone) + - Fold large and huge size classes together; only small and large size classes + remain. (@jasone) + - Unify the allocation paths, and merge most fast-path branching decisions. + (@davidtgoldblatt, @interwq) + - Embed per thread automatic tcache into thread-specific data, which reduces + conditional branches and dereferences. Also reorganize tcache to increase + fast-path data locality. (@interwq) + - Rewrite atomics to closely model the C11 API, convert various + synchronization from mutex-based to atomic, and use the explicit memory + ordering control to resolve various hypothetical races without increasing + synchronization overhead. (@davidtgoldblatt) + - Extensively optimize rtree via various methods: + + Add multiple layers of rtree lookup caching, since rtree lookups are now + part of fast-path deallocation. (@interwq) + + Determine rtree layout at compile time. (@jasone) + + Make the tree shallower for common configurations. (@jasone) + + Embed the root node in the top-level rtree data structure, thus avoiding + one level of indirection. (@jasone) + + Further specialize leaf elements as compared to internal node elements, + and directly embed extent metadata needed for fast-path deallocation. + (@jasone) + + Ignore leading always-zero address bits (architecture-specific). + (@jasone) + - Reorganize headers (ongoing work) to make them hermetic, and disentangle + various module dependencies. (@davidtgoldblatt) + - Convert various internal data structures such as size class metadata from + boot-time-initialized to compile-time-initialized. Propagate resulting data + structure simplifications, such as making arena metadata fixed-size. + (@jasone) + - Simplify size class lookups when constrained to size classes that are + multiples of the page size. This speeds lookups, but the primary benefit is + complexity reduction in code that was the source of numerous regressions. + (@jasone) + - Lock individual extents when possible for localized extent operations, + rather than relying on a top-level arena lock. (@davidtgoldblatt, @jasone) + - Use first fit layout policy instead of best fit, in order to improve + packing. (@jasone) + - If munmap(2) is not in use, use an exponential series to grow each arena's + virtual memory, so that the number of disjoint virtual memory mappings + remains low. (@jasone) + - Implement per arena base allocators, so that arenas never share any virtual + memory pages. (@jasone) + - Automatically generate private symbol name mangling macros. (@jasone) + + Incompatible changes: + - Replace chunk hooks with an expanded/normalized set of extent hooks. + (@jasone) + - Remove ratio-based purging. (@jasone) + - Remove --disable-tcache. (@jasone) + - Remove --disable-tls. (@jasone) + - Remove --enable-ivsalloc. (@jasone) + - Remove --with-lg-size-class-group. (@jasone) + - Remove --with-lg-tiny-min. (@jasone) + - Remove --disable-cc-silence. (@jasone) + - Remove --enable-code-coverage. (@jasone) + - Remove --disable-munmap (replaced by opt.retain). (@jasone) + - Remove Valgrind support. (@jasone) + - Remove quarantine support. (@jasone) + - Remove redzone support. (@jasone) + - Remove mallctl interfaces (various authors): + + config.munmap + + config.tcache + + config.tls + + config.valgrind + + opt.lg_chunk + + opt.purge + + opt.lg_dirty_mult + + opt.decay_time + + opt.quarantine + + opt.redzone + + opt.thp + + arena.<i>.lg_dirty_mult + + arena.<i>.decay_time + + arena.<i>.chunk_hooks + + arenas.initialized + + arenas.lg_dirty_mult + + arenas.decay_time + + arenas.bin.<i>.run_size + + arenas.nlruns + + arenas.lrun.<i>.size + + arenas.nhchunks + + arenas.hchunk.<i>.size + + arenas.extend + + stats.cactive + + stats.arenas.<i>.lg_dirty_mult + + stats.arenas.<i>.decay_time + + stats.arenas.<i>.metadata.{mapped,allocated} + + stats.arenas.<i>.{npurge,nmadvise,purged} + + stats.arenas.<i>.huge.{allocated,nmalloc,ndalloc,nrequests} + + stats.arenas.<i>.bins.<j>.{nruns,reruns,curruns} + + stats.arenas.<i>.lruns.<j>.{nmalloc,ndalloc,nrequests,curruns} + + stats.arenas.<i>.hchunks.<j>.{nmalloc,ndalloc,nrequests,curhchunks} + + Bug fixes: + - Improve interval-based profile dump triggering to dump only one profile when + a single allocation's size exceeds the interval. (@jasone) + - Use prefixed function names (as controlled by --with-jemalloc-prefix) when + pruning backtrace frames in jeprof. (@jasone) + +* 4.5.0 (February 28, 2017) + + This is the first release to benefit from much broader continuous integration + testing, thanks to @davidtgoldblatt. Had we had this testing infrastructure + in place for prior releases, it would have caught all of the most serious + regressions fixed by this release. + + New features: + - Add --disable-thp and the opt.thp mallctl to provide opt-out mechanisms for + transparent huge page integration. (@jasone) + - Update zone allocator integration to work with macOS 10.12. (@glandium) + - Restructure *CFLAGS configuration, so that CFLAGS behaves typically, and + EXTRA_CFLAGS provides a way to specify e.g. -Werror during building, but not + during configuration. (@jasone, @ronawho) + + Bug fixes: + - Fix DSS (sbrk(2)-based) allocation. This regression was first released in + 4.3.0. (@jasone) + - Handle race in per size class utilization computation. This functionality + was first released in 4.0.0. (@interwq) + - Fix lock order reversal during gdump. (@jasone) + - Fix/refactor tcache synchronization. This regression was first released in + 4.0.0. (@jasone) + - Fix various JSON-formatted malloc_stats_print() bugs. This functionality + was first released in 4.3.0. (@jasone) + - Fix huge-aligned allocation. This regression was first released in 4.4.0. + (@jasone) + - When transparent huge page integration is enabled, detect what state pages + start in according to the kernel's current operating mode, and only convert + arena chunks to non-huge during purging if that is not their initial state. + This functionality was first released in 4.4.0. (@jasone) + - Fix lg_chunk clamping for the --enable-cache-oblivious --disable-fill case. + This regression was first released in 4.0.0. (@jasone, @428desmo) + - Properly detect sparc64 when building for Linux. (@glaubitz) + +* 4.4.0 (December 3, 2016) + + New features: + - Add configure support for *-*-linux-android. (@cferris1000, @jasone) + - Add the --disable-syscall configure option, for use on systems that place + security-motivated limitations on syscall(2). (@jasone) + - Add support for Debian GNU/kFreeBSD. (@thesam) + + Optimizations: + - Add extent serial numbers and use them where appropriate as a sort key that + is higher priority than address, so that the allocation policy prefers older + extents. This tends to improve locality (decrease fragmentation) when + memory grows downward. (@jasone) + - Refactor madvise(2) configuration so that MADV_FREE is detected and utilized + on Linux 4.5 and newer. (@jasone) + - Mark partially purged arena chunks as non-huge-page. This improves + interaction with Linux's transparent huge page functionality. (@jasone) + + Bug fixes: + - Fix size class computations for edge conditions involving extremely large + allocations. This regression was first released in 4.0.0. (@jasone, + @ingvarha) + - Remove overly restrictive assertions related to the cactive statistic. This + regression was first released in 4.1.0. (@jasone) + - Implement a more reliable detection scheme for os_unfair_lock on macOS. + (@jszakmeister) + +* 4.3.1 (November 7, 2016) + + Bug fixes: + - Fix a severe virtual memory leak. This regression was first released in + 4.3.0. (@interwq, @jasone) + - Refactor atomic and prng APIs to restore support for 32-bit platforms that + use pre-C11 toolchains, e.g. FreeBSD's mips. (@jasone) + +* 4.3.0 (November 4, 2016) + + This is the first release that passes the test suite for multiple Windows + configurations, thanks in large part to @glandium setting up continuous + integration via AppVeyor (and Travis CI for Linux and OS X). + + New features: + - Add "J" (JSON) support to malloc_stats_print(). (@jasone) + - Add Cray compiler support. (@ronawho) + + Optimizations: + - Add/use adaptive spinning for bootstrapping and radix tree node + initialization. (@jasone) + + Bug fixes: + - Fix large allocation to search starting in the optimal size class heap, + which can substantially reduce virtual memory churn and fragmentation. This + regression was first released in 4.0.0. (@mjp41, @jasone) + - Fix stats.arenas.<i>.nthreads accounting. (@interwq) + - Fix and simplify decay-based purging. (@jasone) + - Make DSS (sbrk(2)-related) operations lockless, which resolves potential + deadlocks during thread exit. (@jasone) + - Fix over-sized allocation of radix tree leaf nodes. (@mjp41, @ogaun, + @jasone) + - Fix over-sized allocation of arena_t (plus associated stats) data + structures. (@jasone, @interwq) + - Fix EXTRA_CFLAGS to not affect configuration. (@jasone) + - Fix a Valgrind integration bug. (@ronawho) + - Disallow 0x5a junk filling when running in Valgrind. (@jasone) + - Fix a file descriptor leak on Linux. This regression was first released in + 4.2.0. (@vsarunas, @jasone) + - Fix static linking of jemalloc with glibc. (@djwatson) + - Use syscall(2) rather than {open,read,close}(2) during boot on Linux. This + works around other libraries' system call wrappers performing reentrant + allocation. (@kspinka, @Whissi, @jasone) + - Fix OS X default zone replacement to work with OS X 10.12. (@glandium, + @jasone) + - Fix cached memory management to avoid needless commit/decommit operations + during purging, which resolves permanent virtual memory map fragmentation + issues on Windows. (@mjp41, @jasone) + - Fix TSD fetches to avoid (recursive) allocation. This is relevant to + non-TLS and Windows configurations. (@jasone) + - Fix malloc_conf overriding to work on Windows. (@jasone) + - Forcibly disable lazy-lock on Windows (was forcibly *enabled*). (@jasone) + +* 4.2.1 (June 8, 2016) + + Bug fixes: + - Fix bootstrapping issues for configurations that require allocation during + tsd initialization (e.g. --disable-tls). (@cferris1000, @jasone) + - Fix gettimeofday() version of nstime_update(). (@ronawho) + - Fix Valgrind regressions in calloc() and chunk_alloc_wrapper(). (@ronawho) + - Fix potential VM map fragmentation regression. (@jasone) + - Fix opt_zero-triggered in-place huge reallocation zeroing. (@jasone) + - Fix heap profiling context leaks in reallocation edge cases. (@jasone) + +* 4.2.0 (May 12, 2016) + + New features: + - Add the arena.<i>.reset mallctl, which makes it possible to discard all of + an arena's allocations in a single operation. (@jasone) + - Add the stats.retained and stats.arenas.<i>.retained statistics. (@jasone) + - Add the --with-version configure option. (@jasone) + - Support --with-lg-page values larger than actual page size. (@jasone) + + Optimizations: + - Use pairing heaps rather than red-black trees for various hot data + structures. (@djwatson, @jasone) + - Streamline fast paths of rtree operations. (@jasone) + - Optimize the fast paths of calloc() and [m,d,sd]allocx(). (@jasone) + - Decommit unused virtual memory if the OS does not overcommit. (@jasone) + - Specify MAP_NORESERVE on Linux if [heuristic] overcommit is active, in order + to avoid unfortunate interactions during fork(2). (@jasone) + + Bug fixes: + - Fix chunk accounting related to triggering gdump profiles. (@jasone) + - Link against librt for clock_gettime(2) if glibc < 2.17. (@jasone) + - Scale leak report summary according to sampling probability. (@jasone) + +* 4.1.1 (May 3, 2016) + + This bugfix release resolves a variety of mostly minor issues, though the + bitmap fix is critical for 64-bit Windows. + + Bug fixes: + - Fix the linear scan version of bitmap_sfu() to shift by the proper amount + even when sizeof(long) is not the same as sizeof(void *), as on 64-bit + Windows. (@jasone) + - Fix hashing functions to avoid unaligned memory accesses (and resulting + crashes). This is relevant at least to some ARM-based platforms. + (@rkmisra) + - Fix fork()-related lock rank ordering reversals. These reversals were + unlikely to cause deadlocks in practice except when heap profiling was + enabled and active. (@jasone) + - Fix various chunk leaks in OOM code paths. (@jasone) + - Fix malloc_stats_print() to print opt.narenas correctly. (@jasone) + - Fix MSVC-specific build/test issues. (@rustyx, @yuslepukhin) + - Fix a variety of test failures that were due to test fragility rather than + core bugs. (@jasone) + +* 4.1.0 (February 28, 2016) + + This release is primarily about optimizations, but it also incorporates a lot + of portability-motivated refactoring and enhancements. Many people worked on + this release, to an extent that even with the omission here of minor changes + (see git revision history), and of the people who reported and diagnosed + issues, so much of the work was contributed that starting with this release, + changes are annotated with author credits to help reflect the collaborative + effort involved. + + New features: + - Implement decay-based unused dirty page purging, a major optimization with + mallctl API impact. This is an alternative to the existing ratio-based + unused dirty page purging, and is intended to eventually become the sole + purging mechanism. New mallctls: + + opt.purge + + opt.decay_time + + arena.<i>.decay + + arena.<i>.decay_time + + arenas.decay_time + + stats.arenas.<i>.decay_time + (@jasone, @cevans87) + - Add --with-malloc-conf, which makes it possible to embed a default + options string during configuration. This was motivated by the desire to + specify --with-malloc-conf=purge:decay , since the default must remain + purge:ratio until the 5.0.0 release. (@jasone) + - Add MS Visual Studio 2015 support. (@rustyx, @yuslepukhin) + - Make *allocx() size class overflow behavior defined. The maximum + size class is now less than PTRDIFF_MAX to protect applications against + numerical overflow, and all allocation functions are guaranteed to indicate + errors rather than potentially crashing if the request size exceeds the + maximum size class. (@jasone) + - jeprof: + + Add raw heap profile support. (@jasone) + + Add --retain and --exclude for backtrace symbol filtering. (@jasone) + + Optimizations: + - Optimize the fast path to combine various bootstrapping and configuration + checks and execute more streamlined code in the common case. (@interwq) + - Use linear scan for small bitmaps (used for small object tracking). In + addition to speeding up bitmap operations on 64-bit systems, this reduces + allocator metadata overhead by approximately 0.2%. (@djwatson) + - Separate arena_avail trees, which substantially speeds up run tree + operations. (@djwatson) + - Use memoization (boot-time-computed table) for run quantization. Separate + arena_avail trees reduced the importance of this optimization. (@jasone) + - Attempt mmap-based in-place huge reallocation. This can dramatically speed + up incremental huge reallocation. (@jasone) + + Incompatible changes: + - Make opt.narenas unsigned rather than size_t. (@jasone) + + Bug fixes: + - Fix stats.cactive accounting regression. (@rustyx, @jasone) + - Handle unaligned keys in hash(). This caused problems for some ARM systems. + (@jasone, @cferris1000) + - Refactor arenas array. In addition to fixing a fork-related deadlock, this + makes arena lookups faster and simpler. (@jasone) + - Move retained memory allocation out of the default chunk allocation + function, to a location that gets executed even if the application installs + a custom chunk allocation function. This resolves a virtual memory leak. + (@buchgr) + - Fix a potential tsd cleanup leak. (@cferris1000, @jasone) + - Fix run quantization. In practice this bug had no impact unless + applications requested memory with alignment exceeding one page. + (@jasone, @djwatson) + - Fix LinuxThreads-specific bootstrapping deadlock. (Cosmin Paraschiv) + - jeprof: + + Don't discard curl options if timeout is not defined. (@djwatson) + + Detect failed profile fetches. (@djwatson) + - Fix stats.arenas.<i>.{dss,lg_dirty_mult,decay_time,pactive,pdirty} for + --disable-stats case. (@jasone) + +* 4.0.4 (October 24, 2015) + + This bugfix release fixes another xallocx() regression. No other regressions + have come to light in over a month, so this is likely a good starting point + for people who prefer to wait for "dot one" releases with all the major issues + shaken out. + + Bug fixes: + - Fix xallocx(..., MALLOCX_ZERO to zero the last full trailing page of large + allocations that have been randomly assigned an offset of 0 when + --enable-cache-oblivious configure option is enabled. + +* 4.0.3 (September 24, 2015) + + This bugfix release continues the trend of xallocx() and heap profiling fixes. + + Bug fixes: + - Fix xallocx(..., MALLOCX_ZERO) to zero all trailing bytes of large + allocations when --enable-cache-oblivious configure option is enabled. + - Fix xallocx(..., MALLOCX_ZERO) to zero trailing bytes of huge allocations + when resizing from/to a size class that is not a multiple of the chunk size. + - Fix prof_tctx_dump_iter() to filter out nodes that were created after heap + profile dumping started. + - Work around a potentially bad thread-specific data initialization + interaction with NPTL (glibc's pthreads implementation). + +* 4.0.2 (September 21, 2015) + + This bugfix release addresses a few bugs specific to heap profiling. + + Bug fixes: + - Fix ixallocx_prof_sample() to never modify nor create sampled small + allocations. xallocx() is in general incapable of moving small allocations, + so this fix removes buggy code without loss of generality. + - Fix irallocx_prof_sample() to always allocate large regions, even when + alignment is non-zero. + - Fix prof_alloc_rollback() to read tdata from thread-specific data rather + than dereferencing a potentially invalid tctx. + +* 4.0.1 (September 15, 2015) + + This is a bugfix release that is somewhat high risk due to the amount of + refactoring required to address deep xallocx() problems. As a side effect of + these fixes, xallocx() now tries harder to partially fulfill requests for + optional extra space. Note that a couple of minor heap profiling + optimizations are included, but these are better thought of as performance + fixes that were integral to disovering most of the other bugs. + + Optimizations: + - Avoid a chunk metadata read in arena_prof_tctx_set(), since it is in the + fast path when heap profiling is enabled. Additionally, split a special + case out into arena_prof_tctx_reset(), which also avoids chunk metadata + reads. + - Optimize irallocx_prof() to optimistically update the sampler state. The + prior implementation appears to have been a holdover from when + rallocx()/xallocx() functionality was combined as rallocm(). + + Bug fixes: + - Fix TLS configuration such that it is enabled by default for platforms on + which it works correctly. + - Fix arenas_cache_cleanup() and arena_get_hard() to handle + allocation/deallocation within the application's thread-specific data + cleanup functions even after arenas_cache is torn down. + - Fix xallocx() bugs related to size+extra exceeding HUGE_MAXCLASS. + - Fix chunk purge hook calls for in-place huge shrinking reallocation to + specify the old chunk size rather than the new chunk size. This bug caused + no correctness issues for the default chunk purge function, but was + visible to custom functions set via the "arena.<i>.chunk_hooks" mallctl. + - Fix heap profiling bugs: + + Fix heap profiling to distinguish among otherwise identical sample sites + with interposed resets (triggered via the "prof.reset" mallctl). This bug + could cause data structure corruption that would most likely result in a + segfault. + + Fix irealloc_prof() to prof_alloc_rollback() on OOM. + + Make one call to prof_active_get_unlocked() per allocation event, and use + the result throughout the relevant functions that handle an allocation + event. Also add a missing check in prof_realloc(). These fixes protect + allocation events against concurrent prof_active changes. + + Fix ixallocx_prof() to pass usize_max and zero to ixallocx_prof_sample() + in the correct order. + + Fix prof_realloc() to call prof_free_sampled_object() after calling + prof_malloc_sample_object(). Prior to this fix, if tctx and old_tctx were + the same, the tctx could have been prematurely destroyed. + - Fix portability bugs: + + Don't bitshift by negative amounts when encoding/decoding run sizes in + chunk header maps. This affected systems with page sizes greater than 8 + KiB. + + Rename index_t to szind_t to avoid an existing type on Solaris. + + Add JEMALLOC_CXX_THROW to the memalign() function prototype, in order to + match glibc and avoid compilation errors when including both + jemalloc/jemalloc.h and malloc.h in C++ code. + + Don't assume that /bin/sh is appropriate when running size_classes.sh + during configuration. + + Consider __sparcv9 a synonym for __sparc64__ when defining LG_QUANTUM. + + Link tests to librt if it contains clock_gettime(2). + +* 4.0.0 (August 17, 2015) + + This version contains many speed and space optimizations, both minor and + major. The major themes are generalization, unification, and simplification. + Although many of these optimizations cause no visible behavior change, their + cumulative effect is substantial. + + New features: + - Normalize size class spacing to be consistent across the complete size + range. By default there are four size classes per size doubling, but this + is now configurable via the --with-lg-size-class-group option. Also add the + --with-lg-page, --with-lg-page-sizes, --with-lg-quantum, and + --with-lg-tiny-min options, which can be used to tweak page and size class + settings. Impacts: + + Worst case performance for incrementally growing/shrinking reallocation + is improved because there are far fewer size classes, and therefore + copying happens less often. + + Internal fragmentation is limited to 20% for all but the smallest size + classes (those less than four times the quantum). (1B + 4 KiB) + and (1B + 4 MiB) previously suffered nearly 50% internal fragmentation. + + Chunk fragmentation tends to be lower because there are fewer distinct run + sizes to pack. + - Add support for explicit tcaches. The "tcache.create", "tcache.flush", and + "tcache.destroy" mallctls control tcache lifetime and flushing, and the + MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to the *allocx() API + control which tcache is used for each operation. + - Implement per thread heap profiling, as well as the ability to + enable/disable heap profiling on a per thread basis. Add the "prof.reset", + "prof.lg_sample", "thread.prof.name", "thread.prof.active", + "opt.prof_thread_active_init", "prof.thread_active_init", and + "thread.prof.active" mallctls. + - Add support for per arena application-specified chunk allocators, configured + via the "arena.<i>.chunk_hooks" mallctl. + - Refactor huge allocation to be managed by arenas, so that arenas now + function as general purpose independent allocators. This is important in + the context of user-specified chunk allocators, aside from the scalability + benefits. Related new statistics: + + The "stats.arenas.<i>.huge.allocated", "stats.arenas.<i>.huge.nmalloc", + "stats.arenas.<i>.huge.ndalloc", and "stats.arenas.<i>.huge.nrequests" + mallctls provide high level per arena huge allocation statistics. + + The "arenas.nhchunks", "arenas.hchunk.<i>.size", + "stats.arenas.<i>.hchunks.<j>.nmalloc", + "stats.arenas.<i>.hchunks.<j>.ndalloc", + "stats.arenas.<i>.hchunks.<j>.nrequests", and + "stats.arenas.<i>.hchunks.<j>.curhchunks" mallctls provide per size class + statistics. + - Add the 'util' column to malloc_stats_print() output, which reports the + proportion of available regions that are currently in use for each small + size class. + - Add "alloc" and "free" modes for for junk filling (see the "opt.junk" + mallctl), so that it is possible to separately enable junk filling for + allocation versus deallocation. + - Add the jemalloc-config script, which provides information about how + jemalloc was configured, and how to integrate it into application builds. + - Add metadata statistics, which are accessible via the "stats.metadata", + "stats.arenas.<i>.metadata.mapped", and + "stats.arenas.<i>.metadata.allocated" mallctls. + - Add the "stats.resident" mallctl, which reports the upper limit of + physically resident memory mapped by the allocator. + - Add per arena control over unused dirty page purging, via the + "arenas.lg_dirty_mult", "arena.<i>.lg_dirty_mult", and + "stats.arenas.<i>.lg_dirty_mult" mallctls. + - Add the "prof.gdump" mallctl, which makes it possible to toggle the gdump + feature on/off during program execution. + - Add sdallocx(), which implements sized deallocation. The primary + optimization over dallocx() is the removal of a metadata read, which often + suffers an L1 cache miss. + - Add missing header includes in jemalloc/jemalloc.h, so that applications + only have to #include <jemalloc/jemalloc.h>. + - Add support for additional platforms: + + Bitrig + + Cygwin + + DragonFlyBSD + + iOS + + OpenBSD + + OpenRISC/or1k + + Optimizations: + - Maintain dirty runs in per arena LRUs rather than in per arena trees of + dirty-run-containing chunks. In practice this change significantly reduces + dirty page purging volume. + - Integrate whole chunks into the unused dirty page purging machinery. This + reduces the cost of repeated huge allocation/deallocation, because it + effectively introduces a cache of chunks. + - Split the arena chunk map into two separate arrays, in order to increase + cache locality for the frequently accessed bits. + - Move small run metadata out of runs, into arena chunk headers. This reduces + run fragmentation, smaller runs reduce external fragmentation for small size + classes, and packed (less uniformly aligned) metadata layout improves CPU + cache set distribution. + - Randomly distribute large allocation base pointer alignment relative to page + boundaries in order to more uniformly utilize CPU cache sets. This can be + disabled via the --disable-cache-oblivious configure option, and queried via + the "config.cache_oblivious" mallctl. + - Micro-optimize the fast paths for the public API functions. + - Refactor thread-specific data to reside in a single structure. This assures + that only a single TLS read is necessary per call into the public API. + - Implement in-place huge allocation growing and shrinking. + - Refactor rtree (radix tree for chunk lookups) to be lock-free, and make + additional optimizations that reduce maximum lookup depth to one or two + levels. This resolves what was a concurrency bottleneck for per arena huge + allocation, because a global data structure is critical for determining + which arenas own which huge allocations. + + Incompatible changes: + - Replace --enable-cc-silence with --disable-cc-silence to suppress spurious + warnings by default. + - Assure that the constness of malloc_usable_size()'s return type matches that + of the system implementation. + - Change the heap profile dump format to support per thread heap profiling, + rename pprof to jeprof, and enhance it with the --thread=<n> option. As a + result, the bundled jeprof must now be used rather than the upstream + (gperftools) pprof. + - Disable "opt.prof_final" by default, in order to avoid atexit(3), which can + internally deadlock on some platforms. + - Change the "arenas.nlruns" mallctl type from size_t to unsigned. + - Replace the "stats.arenas.<i>.bins.<j>.allocated" mallctl with + "stats.arenas.<i>.bins.<j>.curregs". + - Ignore MALLOC_CONF in set{uid,gid,cap} binaries. + - Ignore MALLOCX_ARENA(a) in dallocx(), in favor of using the + MALLOCX_TCACHE(tc) and MALLOCX_TCACHE_NONE flags to control tcache usage. + + Removed features: + - Remove the *allocm() API, which is superseded by the *allocx() API. + - Remove the --enable-dss options, and make dss non-optional on all platforms + which support sbrk(2). + - Remove the "arenas.purge" mallctl, which was obsoleted by the + "arena.<i>.purge" mallctl in 3.1.0. + - Remove the unnecessary "opt.valgrind" mallctl; jemalloc automatically + detects whether it is running inside Valgrind. + - Remove the "stats.huge.allocated", "stats.huge.nmalloc", and + "stats.huge.ndalloc" mallctls. + - Remove the --enable-mremap option. + - Remove the "stats.chunks.current", "stats.chunks.total", and + "stats.chunks.high" mallctls. + + Bug fixes: + - Fix the cactive statistic to decrease (rather than increase) when active + memory decreases. This regression was first released in 3.5.0. + - Fix OOM handling in memalign() and valloc(). A variant of this bug existed + in all releases since 2.0.0, which introduced these functions. + - Fix an OOM-related regression in arena_tcache_fill_small(), which could + cause cache corruption on OOM. This regression was present in all releases + from 2.2.0 through 3.6.0. + - Fix size class overflow handling for malloc(), posix_memalign(), memalign(), + calloc(), and realloc() when profiling is enabled. + - Fix the "arena.<i>.dss" mallctl to return an error if "primary" or + "secondary" precedence is specified, but sbrk(2) is not supported. + - Fix fallback lg_floor() implementations to handle extremely large inputs. + - Ensure the default purgeable zone is after the default zone on OS X. + - Fix latent bugs in atomic_*(). + - Fix the "arena.<i>.dss" mallctl to handle read-only calls. + - Fix tls_model configuration to enable the initial-exec model when possible. + - Mark malloc_conf as a weak symbol so that the application can override it. + - Correctly detect glibc's adaptive pthread mutexes. + - Fix the --without-export configure option. + * 3.6.0 (March 31, 2014) This version contains a critical bug fix for a regression present in 3.5.0 and @@ -21,7 +738,7 @@ found in the git revision history: backtracing to be reliable. - Use dss allocation precedence for huge allocations as well as small/large allocations. - - Fix test assertion failure message formatting. This bug did not manifect on + - Fix test assertion failure message formatting. This bug did not manifest on x86_64 systems because of implementation subtleties in va_list. - Fix inconsequential test failures for hash and SFMT code. @@ -516,7 +1233,7 @@ found in the git revision history: - Make it possible for the application to manually flush a thread's cache, via the "tcache.flush" mallctl. - Base maximum dirty page count on proportion of active memory. - - Compute various addtional run-time statistics, including per size class + - Compute various additional run-time statistics, including per size class statistics for large objects. - Expose malloc_stats_print(), which can be called repeatedly by the application. diff --git a/deps/jemalloc/README b/deps/jemalloc/README index 9b268f4228..3a6e0d2725 100644 --- a/deps/jemalloc/README +++ b/deps/jemalloc/README @@ -3,12 +3,12 @@ fragmentation avoidance and scalable concurrency support. jemalloc first came into use as the FreeBSD libc allocator in 2005, and since then it has found its way into numerous applications that rely on its predictable behavior. In 2010 jemalloc development efforts broadened to include developer support features -such as heap profiling, Valgrind integration, and extensive monitoring/tuning -hooks. Modern jemalloc releases continue to be integrated back into FreeBSD, -and therefore versatility remains critical. Ongoing development efforts trend -toward making jemalloc among the best allocators for a broad range of demanding -applications, and eliminating/mitigating weaknesses that have practical -repercussions for real world applications. +such as heap profiling and extensive monitoring/tuning hooks. Modern jemalloc +releases continue to be integrated back into FreeBSD, and therefore versatility +remains critical. Ongoing development efforts trend toward making jemalloc +among the best allocators for a broad range of demanding applications, and +eliminating/mitigating weaknesses that have practical repercussions for real +world applications. The COPYING file contains copyright and licensing information. @@ -17,4 +17,4 @@ jemalloc. The ChangeLog file contains a brief summary of changes for each release. -URL: http://www.canonware.com/jemalloc/ +URL: http://jemalloc.net/ diff --git a/deps/jemalloc/include/jemalloc/internal/atomic.h b/deps/jemalloc/include/jemalloc/internal/atomic.h index 11a7b47fe0..adadb1a3ac 100644 --- a/deps/jemalloc/include/jemalloc/internal/atomic.h +++ b/deps/jemalloc/include/jemalloc/internal/atomic.h @@ -1,304 +1,77 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES - -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -#define atomic_read_uint64(p) atomic_add_uint64(p, 0) -#define atomic_read_uint32(p) atomic_add_uint32(p, 0) -#define atomic_read_z(p) atomic_add_z(p, 0) -#define atomic_read_u(p) atomic_add_u(p, 0) - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#ifndef JEMALLOC_ENABLE_INLINE -uint64_t atomic_add_uint64(uint64_t *p, uint64_t x); -uint64_t atomic_sub_uint64(uint64_t *p, uint64_t x); -uint32_t atomic_add_uint32(uint32_t *p, uint32_t x); -uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x); -size_t atomic_add_z(size_t *p, size_t x); -size_t atomic_sub_z(size_t *p, size_t x); -unsigned atomic_add_u(unsigned *p, unsigned x); -unsigned atomic_sub_u(unsigned *p, unsigned x); +#ifndef JEMALLOC_INTERNAL_ATOMIC_H +#define JEMALLOC_INTERNAL_ATOMIC_H + +#define ATOMIC_INLINE static inline + +#if defined(JEMALLOC_GCC_ATOMIC_ATOMICS) +# include "jemalloc/internal/atomic_gcc_atomic.h" +#elif defined(JEMALLOC_GCC_SYNC_ATOMICS) +# include "jemalloc/internal/atomic_gcc_sync.h" +#elif defined(_MSC_VER) +# include "jemalloc/internal/atomic_msvc.h" +#elif defined(JEMALLOC_C11_ATOMICS) +# include "jemalloc/internal/atomic_c11.h" +#else +# error "Don't have atomics implemented on this platform." #endif -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_)) -/******************************************************************************/ -/* 64-bit operations. */ +/* + * This header gives more or less a backport of C11 atomics. The user can write + * JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_sizeof_type); to generate + * counterparts of the C11 atomic functions for type, as so: + * JEMALLOC_GENERATE_ATOMICS(int *, pi, 3); + * and then write things like: + * int *some_ptr; + * atomic_pi_t atomic_ptr_to_int; + * atomic_store_pi(&atomic_ptr_to_int, some_ptr, ATOMIC_RELAXED); + * int *prev_value = atomic_exchange_pi(&ptr_to_int, NULL, ATOMIC_ACQ_REL); + * assert(some_ptr == prev_value); + * and expect things to work in the obvious way. + * + * Also included (with naming differences to avoid conflicts with the standard + * library): + * atomic_fence(atomic_memory_order_t) (mimics C11's atomic_thread_fence). + * ATOMIC_INIT (mimics C11's ATOMIC_VAR_INIT). + */ + +/* + * Pure convenience, so that we don't have to type "atomic_memory_order_" + * quite so often. + */ +#define ATOMIC_RELAXED atomic_memory_order_relaxed +#define ATOMIC_ACQUIRE atomic_memory_order_acquire +#define ATOMIC_RELEASE atomic_memory_order_release +#define ATOMIC_ACQ_REL atomic_memory_order_acq_rel +#define ATOMIC_SEQ_CST atomic_memory_order_seq_cst + +/* + * Not all platforms have 64-bit atomics. If we do, this #define exposes that + * fact. + */ #if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3) -# ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 -JEMALLOC_INLINE uint64_t -atomic_add_uint64(uint64_t *p, uint64_t x) -{ - - return (__sync_add_and_fetch(p, x)); -} - -JEMALLOC_INLINE uint64_t -atomic_sub_uint64(uint64_t *p, uint64_t x) -{ - - return (__sync_sub_and_fetch(p, x)); -} -#elif (defined(_MSC_VER)) -JEMALLOC_INLINE uint64_t -atomic_add_uint64(uint64_t *p, uint64_t x) -{ - - return (InterlockedExchangeAdd64(p, x)); -} - -JEMALLOC_INLINE uint64_t -atomic_sub_uint64(uint64_t *p, uint64_t x) -{ - - return (InterlockedExchangeAdd64(p, -((int64_t)x))); -} -#elif (defined(JEMALLOC_OSATOMIC)) -JEMALLOC_INLINE uint64_t -atomic_add_uint64(uint64_t *p, uint64_t x) -{ - - return (OSAtomicAdd64((int64_t)x, (int64_t *)p)); -} - -JEMALLOC_INLINE uint64_t -atomic_sub_uint64(uint64_t *p, uint64_t x) -{ - - return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p)); -} -# elif (defined(__amd64__) || defined(__x86_64__)) -JEMALLOC_INLINE uint64_t -atomic_add_uint64(uint64_t *p, uint64_t x) -{ - - asm volatile ( - "lock; xaddq %0, %1;" - : "+r" (x), "=m" (*p) /* Outputs. */ - : "m" (*p) /* Inputs. */ - ); - - return (x); -} - -JEMALLOC_INLINE uint64_t -atomic_sub_uint64(uint64_t *p, uint64_t x) -{ - - x = (uint64_t)(-(int64_t)x); - asm volatile ( - "lock; xaddq %0, %1;" - : "+r" (x), "=m" (*p) /* Outputs. */ - : "m" (*p) /* Inputs. */ - ); - - return (x); -} -# elif (defined(JEMALLOC_ATOMIC9)) -JEMALLOC_INLINE uint64_t -atomic_add_uint64(uint64_t *p, uint64_t x) -{ - - /* - * atomic_fetchadd_64() doesn't exist, but we only ever use this - * function on LP64 systems, so atomic_fetchadd_long() will do. - */ - assert(sizeof(uint64_t) == sizeof(unsigned long)); - - return (atomic_fetchadd_long(p, (unsigned long)x) + x); -} - -JEMALLOC_INLINE uint64_t -atomic_sub_uint64(uint64_t *p, uint64_t x) -{ - - assert(sizeof(uint64_t) == sizeof(unsigned long)); - - return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x); -} -# elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8)) -JEMALLOC_INLINE uint64_t -atomic_add_uint64(uint64_t *p, uint64_t x) -{ - - return (__sync_add_and_fetch(p, x)); -} - -JEMALLOC_INLINE uint64_t -atomic_sub_uint64(uint64_t *p, uint64_t x) -{ - - return (__sync_sub_and_fetch(p, x)); -} -# else -# error "Missing implementation for 64-bit atomic operations" -# endif +# define JEMALLOC_ATOMIC_U64 #endif -/******************************************************************************/ -/* 32-bit operations. */ -#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 -JEMALLOC_INLINE uint32_t -atomic_add_uint32(uint32_t *p, uint32_t x) -{ +JEMALLOC_GENERATE_ATOMICS(void *, p, LG_SIZEOF_PTR) - return (__sync_add_and_fetch(p, x)); -} +/* + * There's no actual guarantee that sizeof(bool) == 1, but it's true on the only + * platform that actually needs to know the size, MSVC. + */ +JEMALLOC_GENERATE_ATOMICS(bool, b, 0) -JEMALLOC_INLINE uint32_t -atomic_sub_uint32(uint32_t *p, uint32_t x) -{ +JEMALLOC_GENERATE_INT_ATOMICS(unsigned, u, LG_SIZEOF_INT) - return (__sync_sub_and_fetch(p, x)); -} -#elif (defined(_MSC_VER)) -JEMALLOC_INLINE uint32_t -atomic_add_uint32(uint32_t *p, uint32_t x) -{ +JEMALLOC_GENERATE_INT_ATOMICS(size_t, zu, LG_SIZEOF_PTR) - return (InterlockedExchangeAdd(p, x)); -} +JEMALLOC_GENERATE_INT_ATOMICS(ssize_t, zd, LG_SIZEOF_PTR) -JEMALLOC_INLINE uint32_t -atomic_sub_uint32(uint32_t *p, uint32_t x) -{ +JEMALLOC_GENERATE_INT_ATOMICS(uint32_t, u32, 2) - return (InterlockedExchangeAdd(p, -((int32_t)x))); -} -#elif (defined(JEMALLOC_OSATOMIC)) -JEMALLOC_INLINE uint32_t -atomic_add_uint32(uint32_t *p, uint32_t x) -{ - - return (OSAtomicAdd32((int32_t)x, (int32_t *)p)); -} - -JEMALLOC_INLINE uint32_t -atomic_sub_uint32(uint32_t *p, uint32_t x) -{ - - return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p)); -} -#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) -JEMALLOC_INLINE uint32_t -atomic_add_uint32(uint32_t *p, uint32_t x) -{ - - asm volatile ( - "lock; xaddl %0, %1;" - : "+r" (x), "=m" (*p) /* Outputs. */ - : "m" (*p) /* Inputs. */ - ); - - return (x); -} - -JEMALLOC_INLINE uint32_t -atomic_sub_uint32(uint32_t *p, uint32_t x) -{ - - x = (uint32_t)(-(int32_t)x); - asm volatile ( - "lock; xaddl %0, %1;" - : "+r" (x), "=m" (*p) /* Outputs. */ - : "m" (*p) /* Inputs. */ - ); - - return (x); -} -#elif (defined(JEMALLOC_ATOMIC9)) -JEMALLOC_INLINE uint32_t -atomic_add_uint32(uint32_t *p, uint32_t x) -{ - - return (atomic_fetchadd_32(p, x) + x); -} - -JEMALLOC_INLINE uint32_t -atomic_sub_uint32(uint32_t *p, uint32_t x) -{ - - return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x); -} -#elif (defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4)) -JEMALLOC_INLINE uint32_t -atomic_add_uint32(uint32_t *p, uint32_t x) -{ - - return (__sync_add_and_fetch(p, x)); -} - -JEMALLOC_INLINE uint32_t -atomic_sub_uint32(uint32_t *p, uint32_t x) -{ - - return (__sync_sub_and_fetch(p, x)); -} -#else -# error "Missing implementation for 32-bit atomic operations" -#endif - -/******************************************************************************/ -/* size_t operations. */ -JEMALLOC_INLINE size_t -atomic_add_z(size_t *p, size_t x) -{ - -#if (LG_SIZEOF_PTR == 3) - return ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x)); -#elif (LG_SIZEOF_PTR == 2) - return ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x)); -#endif -} - -JEMALLOC_INLINE size_t -atomic_sub_z(size_t *p, size_t x) -{ - -#if (LG_SIZEOF_PTR == 3) - return ((size_t)atomic_add_uint64((uint64_t *)p, - (uint64_t)-((int64_t)x))); -#elif (LG_SIZEOF_PTR == 2) - return ((size_t)atomic_add_uint32((uint32_t *)p, - (uint32_t)-((int32_t)x))); +#ifdef JEMALLOC_ATOMIC_U64 +JEMALLOC_GENERATE_INT_ATOMICS(uint64_t, u64, 3) #endif -} -/******************************************************************************/ -/* unsigned operations. */ -JEMALLOC_INLINE unsigned -atomic_add_u(unsigned *p, unsigned x) -{ - -#if (LG_SIZEOF_INT == 3) - return ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x)); -#elif (LG_SIZEOF_INT == 2) - return ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x)); -#endif -} - -JEMALLOC_INLINE unsigned -atomic_sub_u(unsigned *p, unsigned x) -{ - -#if (LG_SIZEOF_INT == 3) - return ((unsigned)atomic_add_uint64((uint64_t *)p, - (uint64_t)-((int64_t)x))); -#elif (LG_SIZEOF_INT == 2) - return ((unsigned)atomic_add_uint32((uint32_t *)p, - (uint32_t)-((int32_t)x))); -#endif -} -/******************************************************************************/ -#endif +#undef ATOMIC_INLINE -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_ATOMIC_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/bitmap.h b/deps/jemalloc/include/jemalloc/internal/bitmap.h index 605ebac58c..ac990290a5 100644 --- a/deps/jemalloc/include/jemalloc/internal/bitmap.h +++ b/deps/jemalloc/include/jemalloc/internal/bitmap.h @@ -1,37 +1,159 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES +#ifndef JEMALLOC_INTERNAL_BITMAP_H +#define JEMALLOC_INTERNAL_BITMAP_H -/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */ -#define LG_BITMAP_MAXBITS LG_RUN_MAXREGS +#include "jemalloc/internal/arena_types.h" +#include "jemalloc/internal/bit_util.h" +#include "jemalloc/internal/size_classes.h" -typedef struct bitmap_level_s bitmap_level_t; -typedef struct bitmap_info_s bitmap_info_t; typedef unsigned long bitmap_t; -#define LG_SIZEOF_BITMAP LG_SIZEOF_LONG +#define LG_SIZEOF_BITMAP LG_SIZEOF_LONG + +/* Maximum bitmap bit count is 2^LG_BITMAP_MAXBITS. */ +#if LG_SLAB_MAXREGS > LG_CEIL_NSIZES +/* Maximum bitmap bit count is determined by maximum regions per slab. */ +# define LG_BITMAP_MAXBITS LG_SLAB_MAXREGS +#else +/* Maximum bitmap bit count is determined by number of extent size classes. */ +# define LG_BITMAP_MAXBITS LG_CEIL_NSIZES +#endif +#define BITMAP_MAXBITS (ZU(1) << LG_BITMAP_MAXBITS) /* Number of bits per group. */ -#define LG_BITMAP_GROUP_NBITS (LG_SIZEOF_BITMAP + 3) -#define BITMAP_GROUP_NBITS (ZU(1) << LG_BITMAP_GROUP_NBITS) -#define BITMAP_GROUP_NBITS_MASK (BITMAP_GROUP_NBITS-1) +#define LG_BITMAP_GROUP_NBITS (LG_SIZEOF_BITMAP + 3) +#define BITMAP_GROUP_NBITS (1U << LG_BITMAP_GROUP_NBITS) +#define BITMAP_GROUP_NBITS_MASK (BITMAP_GROUP_NBITS-1) + +/* + * Do some analysis on how big the bitmap is before we use a tree. For a brute + * force linear search, if we would have to call ffs_lu() more than 2^3 times, + * use a tree instead. + */ +#if LG_BITMAP_MAXBITS - LG_BITMAP_GROUP_NBITS > 3 +# define BITMAP_USE_TREE +#endif + +/* Number of groups required to store a given number of bits. */ +#define BITMAP_BITS2GROUPS(nbits) \ + (((nbits) + BITMAP_GROUP_NBITS_MASK) >> LG_BITMAP_GROUP_NBITS) + +/* + * Number of groups required at a particular level for a given number of bits. + */ +#define BITMAP_GROUPS_L0(nbits) \ + BITMAP_BITS2GROUPS(nbits) +#define BITMAP_GROUPS_L1(nbits) \ + BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(nbits)) +#define BITMAP_GROUPS_L2(nbits) \ + BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS((nbits)))) +#define BITMAP_GROUPS_L3(nbits) \ + BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS( \ + BITMAP_BITS2GROUPS((nbits))))) +#define BITMAP_GROUPS_L4(nbits) \ + BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS( \ + BITMAP_BITS2GROUPS(BITMAP_BITS2GROUPS((nbits)))))) + +/* + * Assuming the number of levels, number of groups required for a given number + * of bits. + */ +#define BITMAP_GROUPS_1_LEVEL(nbits) \ + BITMAP_GROUPS_L0(nbits) +#define BITMAP_GROUPS_2_LEVEL(nbits) \ + (BITMAP_GROUPS_1_LEVEL(nbits) + BITMAP_GROUPS_L1(nbits)) +#define BITMAP_GROUPS_3_LEVEL(nbits) \ + (BITMAP_GROUPS_2_LEVEL(nbits) + BITMAP_GROUPS_L2(nbits)) +#define BITMAP_GROUPS_4_LEVEL(nbits) \ + (BITMAP_GROUPS_3_LEVEL(nbits) + BITMAP_GROUPS_L3(nbits)) +#define BITMAP_GROUPS_5_LEVEL(nbits) \ + (BITMAP_GROUPS_4_LEVEL(nbits) + BITMAP_GROUPS_L4(nbits)) + +/* + * Maximum number of groups required to support LG_BITMAP_MAXBITS. + */ +#ifdef BITMAP_USE_TREE -/* Maximum number of levels possible. */ -#define BITMAP_MAX_LEVELS \ - (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP) \ - + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP) +#if LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS +# define BITMAP_GROUPS(nbits) BITMAP_GROUPS_1_LEVEL(nbits) +# define BITMAP_GROUPS_MAX BITMAP_GROUPS_1_LEVEL(BITMAP_MAXBITS) +#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 2 +# define BITMAP_GROUPS(nbits) BITMAP_GROUPS_2_LEVEL(nbits) +# define BITMAP_GROUPS_MAX BITMAP_GROUPS_2_LEVEL(BITMAP_MAXBITS) +#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 3 +# define BITMAP_GROUPS(nbits) BITMAP_GROUPS_3_LEVEL(nbits) +# define BITMAP_GROUPS_MAX BITMAP_GROUPS_3_LEVEL(BITMAP_MAXBITS) +#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 4 +# define BITMAP_GROUPS(nbits) BITMAP_GROUPS_4_LEVEL(nbits) +# define BITMAP_GROUPS_MAX BITMAP_GROUPS_4_LEVEL(BITMAP_MAXBITS) +#elif LG_BITMAP_MAXBITS <= LG_BITMAP_GROUP_NBITS * 5 +# define BITMAP_GROUPS(nbits) BITMAP_GROUPS_5_LEVEL(nbits) +# define BITMAP_GROUPS_MAX BITMAP_GROUPS_5_LEVEL(BITMAP_MAXBITS) +#else +# error "Unsupported bitmap size" +#endif + +/* + * Maximum number of levels possible. This could be statically computed based + * on LG_BITMAP_MAXBITS: + * + * #define BITMAP_MAX_LEVELS \ + * (LG_BITMAP_MAXBITS / LG_SIZEOF_BITMAP) \ + * + !!(LG_BITMAP_MAXBITS % LG_SIZEOF_BITMAP) + * + * However, that would not allow the generic BITMAP_INFO_INITIALIZER() macro, so + * instead hardcode BITMAP_MAX_LEVELS to the largest number supported by the + * various cascading macros. The only additional cost this incurs is some + * unused trailing entries in bitmap_info_t structures; the bitmaps themselves + * are not impacted. + */ +#define BITMAP_MAX_LEVELS 5 + +#define BITMAP_INFO_INITIALIZER(nbits) { \ + /* nbits. */ \ + nbits, \ + /* nlevels. */ \ + (BITMAP_GROUPS_L0(nbits) > BITMAP_GROUPS_L1(nbits)) + \ + (BITMAP_GROUPS_L1(nbits) > BITMAP_GROUPS_L2(nbits)) + \ + (BITMAP_GROUPS_L2(nbits) > BITMAP_GROUPS_L3(nbits)) + \ + (BITMAP_GROUPS_L3(nbits) > BITMAP_GROUPS_L4(nbits)) + 1, \ + /* levels. */ \ + { \ + {0}, \ + {BITMAP_GROUPS_L0(nbits)}, \ + {BITMAP_GROUPS_L1(nbits) + BITMAP_GROUPS_L0(nbits)}, \ + {BITMAP_GROUPS_L2(nbits) + BITMAP_GROUPS_L1(nbits) + \ + BITMAP_GROUPS_L0(nbits)}, \ + {BITMAP_GROUPS_L3(nbits) + BITMAP_GROUPS_L2(nbits) + \ + BITMAP_GROUPS_L1(nbits) + BITMAP_GROUPS_L0(nbits)}, \ + {BITMAP_GROUPS_L4(nbits) + BITMAP_GROUPS_L3(nbits) + \ + BITMAP_GROUPS_L2(nbits) + BITMAP_GROUPS_L1(nbits) \ + + BITMAP_GROUPS_L0(nbits)} \ + } \ +} + +#else /* BITMAP_USE_TREE */ -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS +#define BITMAP_GROUPS(nbits) BITMAP_BITS2GROUPS(nbits) +#define BITMAP_GROUPS_MAX BITMAP_BITS2GROUPS(BITMAP_MAXBITS) -struct bitmap_level_s { +#define BITMAP_INFO_INITIALIZER(nbits) { \ + /* nbits. */ \ + nbits, \ + /* ngroups. */ \ + BITMAP_BITS2GROUPS(nbits) \ +} + +#endif /* BITMAP_USE_TREE */ + +typedef struct bitmap_level_s { /* Offset of this level's groups within the array of groups. */ size_t group_offset; -}; +} bitmap_level_t; -struct bitmap_info_s { +typedef struct bitmap_info_s { /* Logical number of bits in bitmap (stored at bottom level). */ size_t nbits; +#ifdef BITMAP_USE_TREE /* Number of levels necessary for nbits. */ unsigned nlevels; @@ -40,67 +162,62 @@ struct bitmap_info_s { * bottom to top (e.g. the bottom level is stored in levels[0]). */ bitmap_level_t levels[BITMAP_MAX_LEVELS+1]; -}; - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -void bitmap_info_init(bitmap_info_t *binfo, size_t nbits); -size_t bitmap_info_ngroups(const bitmap_info_t *binfo); -size_t bitmap_size(size_t nbits); -void bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo); - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#ifndef JEMALLOC_ENABLE_INLINE -bool bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo); -bool bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit); -void bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit); -size_t bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo); -void bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit); -#endif +#else /* BITMAP_USE_TREE */ + /* Number of groups necessary for nbits. */ + size_t ngroups; +#endif /* BITMAP_USE_TREE */ +} bitmap_info_t; + +void bitmap_info_init(bitmap_info_t *binfo, size_t nbits); +void bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo, bool fill); +size_t bitmap_size(const bitmap_info_t *binfo); -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_BITMAP_C_)) -JEMALLOC_INLINE bool -bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo) -{ - unsigned rgoff = binfo->levels[binfo->nlevels].group_offset - 1; +static inline bool +bitmap_full(bitmap_t *bitmap, const bitmap_info_t *binfo) { +#ifdef BITMAP_USE_TREE + size_t rgoff = binfo->levels[binfo->nlevels].group_offset - 1; bitmap_t rg = bitmap[rgoff]; /* The bitmap is full iff the root group is 0. */ return (rg == 0); +#else + size_t i; + + for (i = 0; i < binfo->ngroups; i++) { + if (bitmap[i] != 0) { + return false; + } + } + return true; +#endif } -JEMALLOC_INLINE bool -bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) -{ +static inline bool +bitmap_get(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) { size_t goff; bitmap_t g; assert(bit < binfo->nbits); goff = bit >> LG_BITMAP_GROUP_NBITS; g = bitmap[goff]; - return (!(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK)))); + return !(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))); } -JEMALLOC_INLINE void -bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) -{ +static inline void +bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) { size_t goff; bitmap_t *gp; bitmap_t g; assert(bit < binfo->nbits); - assert(bitmap_get(bitmap, binfo, bit) == false); + assert(!bitmap_get(bitmap, binfo, bit)); goff = bit >> LG_BITMAP_GROUP_NBITS; gp = &bitmap[goff]; g = *gp; - assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))); - g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + assert(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))); + g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK); *gp = g; assert(bitmap_get(bitmap, binfo, bit)); +#ifdef BITMAP_USE_TREE /* Propagate group state transitions up the tree. */ if (g == 0) { unsigned i; @@ -109,45 +226,113 @@ bitmap_set(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) goff = bit >> LG_BITMAP_GROUP_NBITS; gp = &bitmap[binfo->levels[i].group_offset + goff]; g = *gp; - assert(g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))); - g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + assert(g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))); + g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK); *gp = g; - if (g != 0) + if (g != 0) { break; + } } } +#endif +} + +/* ffu: find first unset >= bit. */ +static inline size_t +bitmap_ffu(const bitmap_t *bitmap, const bitmap_info_t *binfo, size_t min_bit) { + assert(min_bit < binfo->nbits); + +#ifdef BITMAP_USE_TREE + size_t bit = 0; + for (unsigned level = binfo->nlevels; level--;) { + size_t lg_bits_per_group = (LG_BITMAP_GROUP_NBITS * (level + + 1)); + bitmap_t group = bitmap[binfo->levels[level].group_offset + (bit + >> lg_bits_per_group)]; + unsigned group_nmask = (unsigned)(((min_bit > bit) ? (min_bit - + bit) : 0) >> (lg_bits_per_group - LG_BITMAP_GROUP_NBITS)); + assert(group_nmask <= BITMAP_GROUP_NBITS); + bitmap_t group_mask = ~((1LU << group_nmask) - 1); + bitmap_t group_masked = group & group_mask; + if (group_masked == 0LU) { + if (group == 0LU) { + return binfo->nbits; + } + /* + * min_bit was preceded by one or more unset bits in + * this group, but there are no other unset bits in this + * group. Try again starting at the first bit of the + * next sibling. This will recurse at most once per + * non-root level. + */ + size_t sib_base = bit + (ZU(1) << lg_bits_per_group); + assert(sib_base > min_bit); + assert(sib_base > bit); + if (sib_base >= binfo->nbits) { + return binfo->nbits; + } + return bitmap_ffu(bitmap, binfo, sib_base); + } + bit += ((size_t)(ffs_lu(group_masked) - 1)) << + (lg_bits_per_group - LG_BITMAP_GROUP_NBITS); + } + assert(bit >= min_bit); + assert(bit < binfo->nbits); + return bit; +#else + size_t i = min_bit >> LG_BITMAP_GROUP_NBITS; + bitmap_t g = bitmap[i] & ~((1LU << (min_bit & BITMAP_GROUP_NBITS_MASK)) + - 1); + size_t bit; + do { + bit = ffs_lu(g); + if (bit != 0) { + return (i << LG_BITMAP_GROUP_NBITS) + (bit - 1); + } + i++; + g = bitmap[i]; + } while (i < binfo->ngroups); + return binfo->nbits; +#endif } /* sfu: set first unset. */ -JEMALLOC_INLINE size_t -bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo) -{ +static inline size_t +bitmap_sfu(bitmap_t *bitmap, const bitmap_info_t *binfo) { size_t bit; bitmap_t g; unsigned i; - assert(bitmap_full(bitmap, binfo) == false); + assert(!bitmap_full(bitmap, binfo)); +#ifdef BITMAP_USE_TREE i = binfo->nlevels - 1; g = bitmap[binfo->levels[i].group_offset]; - bit = ffsl(g) - 1; + bit = ffs_lu(g) - 1; while (i > 0) { i--; g = bitmap[binfo->levels[i].group_offset + bit]; - bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffsl(g) - 1); + bit = (bit << LG_BITMAP_GROUP_NBITS) + (ffs_lu(g) - 1); } - +#else + i = 0; + g = bitmap[0]; + while ((bit = ffs_lu(g)) == 0) { + i++; + g = bitmap[i]; + } + bit = (i << LG_BITMAP_GROUP_NBITS) + (bit - 1); +#endif bitmap_set(bitmap, binfo, bit); - return (bit); + return bit; } -JEMALLOC_INLINE void -bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) -{ +static inline void +bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) { size_t goff; bitmap_t *gp; bitmap_t g; - bool propagate; + UNUSED bool propagate; assert(bit < binfo->nbits); assert(bitmap_get(bitmap, binfo, bit)); @@ -155,10 +340,11 @@ bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) gp = &bitmap[goff]; g = *gp; propagate = (g == 0); - assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) == 0); - g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + assert((g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))) == 0); + g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK); *gp = g; - assert(bitmap_get(bitmap, binfo, bit) == false); + assert(!bitmap_get(bitmap, binfo, bit)); +#ifdef BITMAP_USE_TREE /* Propagate group state transitions up the tree. */ if (propagate) { unsigned i; @@ -168,17 +354,16 @@ bitmap_unset(bitmap_t *bitmap, const bitmap_info_t *binfo, size_t bit) gp = &bitmap[binfo->levels[i].group_offset + goff]; g = *gp; propagate = (g == 0); - assert((g & (1LU << (bit & BITMAP_GROUP_NBITS_MASK))) + assert((g & (ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK))) == 0); - g ^= 1LU << (bit & BITMAP_GROUP_NBITS_MASK); + g ^= ZU(1) << (bit & BITMAP_GROUP_NBITS_MASK); *gp = g; - if (propagate == false) + if (!propagate) { break; + } } } +#endif /* BITMAP_USE_TREE */ } -#endif - -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_BITMAP_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/ckh.h b/deps/jemalloc/include/jemalloc/internal/ckh.h index 58712a6a76..7b3850bc16 100644 --- a/deps/jemalloc/include/jemalloc/internal/ckh.h +++ b/deps/jemalloc/include/jemalloc/internal/ckh.h @@ -1,88 +1,101 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES +#ifndef JEMALLOC_INTERNAL_CKH_H +#define JEMALLOC_INTERNAL_CKH_H -typedef struct ckh_s ckh_t; -typedef struct ckhc_s ckhc_t; +#include "jemalloc/internal/tsd.h" -/* Typedefs to allow easy function pointer passing. */ -typedef void ckh_hash_t (const void *, size_t[2]); -typedef bool ckh_keycomp_t (const void *, const void *); +/* Cuckoo hashing implementation. Skip to the end for the interface. */ + +/******************************************************************************/ +/* INTERNAL DEFINITIONS -- IGNORE */ +/******************************************************************************/ /* Maintain counters used to get an idea of performance. */ -/* #define CKH_COUNT */ +/* #define CKH_COUNT */ /* Print counter values in ckh_delete() (requires CKH_COUNT). */ -/* #define CKH_VERBOSE */ +/* #define CKH_VERBOSE */ /* * There are 2^LG_CKH_BUCKET_CELLS cells in each hash table bucket. Try to fit * one bucket per L1 cache line. */ -#define LG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1) +#define LG_CKH_BUCKET_CELLS (LG_CACHELINE - LG_SIZEOF_PTR - 1) -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS +/* Typedefs to allow easy function pointer passing. */ +typedef void ckh_hash_t (const void *, size_t[2]); +typedef bool ckh_keycomp_t (const void *, const void *); /* Hash table cell. */ -struct ckhc_s { - const void *key; - const void *data; -}; +typedef struct { + const void *key; + const void *data; +} ckhc_t; -struct ckh_s { +/* The hash table itself. */ +typedef struct { #ifdef CKH_COUNT /* Counters used to get an idea of performance. */ - uint64_t ngrows; - uint64_t nshrinks; - uint64_t nshrinkfails; - uint64_t ninserts; - uint64_t nrelocs; + uint64_t ngrows; + uint64_t nshrinks; + uint64_t nshrinkfails; + uint64_t ninserts; + uint64_t nrelocs; #endif /* Used for pseudo-random number generation. */ -#define CKH_A 1103515241 -#define CKH_C 12347 - uint32_t prng_state; + uint64_t prng_state; /* Total number of items. */ - size_t count; + size_t count; /* * Minimum and current number of hash table buckets. There are * 2^LG_CKH_BUCKET_CELLS cells per bucket. */ - unsigned lg_minbuckets; - unsigned lg_curbuckets; + unsigned lg_minbuckets; + unsigned lg_curbuckets; /* Hash and comparison functions. */ - ckh_hash_t *hash; - ckh_keycomp_t *keycomp; + ckh_hash_t *hash; + ckh_keycomp_t *keycomp; /* Hash table with 2^lg_curbuckets buckets. */ - ckhc_t *tab; -}; + ckhc_t *tab; +} ckh_t; -#endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS +/* BEGIN PUBLIC API */ +/******************************************************************************/ -bool ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, +/* Lifetime management. Minitems is the initial capacity. */ +bool ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp); -void ckh_delete(ckh_t *ckh); -size_t ckh_count(ckh_t *ckh); -bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data); -bool ckh_insert(ckh_t *ckh, const void *key, const void *data); -bool ckh_remove(ckh_t *ckh, const void *searchkey, void **key, +void ckh_delete(tsd_t *tsd, ckh_t *ckh); + +/* Get the number of elements in the set. */ +size_t ckh_count(ckh_t *ckh); + +/* + * To iterate over the elements in the table, initialize *tabind to 0 and call + * this function until it returns true. Each call that returns false will + * update *key and *data to the next element in the table, assuming the pointers + * are non-NULL. + */ +bool ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data); + +/* + * Basic hash table operations -- insert, removal, lookup. For ckh_remove and + * ckh_search, key or data can be NULL. The hash-table only stores pointers to + * the key and value, and doesn't do any lifetime management. + */ +bool ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data); +bool ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key, void **data); -bool ckh_search(ckh_t *ckh, const void *seachkey, void **key, void **data); -void ckh_string_hash(const void *key, size_t r_hash[2]); -bool ckh_string_keycomp(const void *k1, const void *k2); -void ckh_pointer_hash(const void *key, size_t r_hash[2]); -bool ckh_pointer_keycomp(const void *k1, const void *k2); +bool ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data); -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES +/* Some useful hash and comparison functions for strings and pointers. */ +void ckh_string_hash(const void *key, size_t r_hash[2]); +bool ckh_string_keycomp(const void *k1, const void *k2); +void ckh_pointer_hash(const void *key, size_t r_hash[2]); +bool ckh_pointer_keycomp(const void *k1, const void *k2); -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_CKH_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/ctl.h b/deps/jemalloc/include/jemalloc/internal/ctl.h index 0ffecc5f2a..a91c4cf556 100644 --- a/deps/jemalloc/include/jemalloc/internal/ctl.h +++ b/deps/jemalloc/include/jemalloc/internal/ctl.h @@ -1,87 +1,106 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES - -typedef struct ctl_node_s ctl_node_t; -typedef struct ctl_named_node_s ctl_named_node_t; -typedef struct ctl_indexed_node_s ctl_indexed_node_t; -typedef struct ctl_arena_stats_s ctl_arena_stats_t; -typedef struct ctl_stats_s ctl_stats_t; - -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - -struct ctl_node_s { - bool named; -}; - -struct ctl_named_node_s { - struct ctl_node_s node; - const char *name; +#ifndef JEMALLOC_INTERNAL_CTL_H +#define JEMALLOC_INTERNAL_CTL_H + +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/mutex_prof.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/stats.h" + +/* Maximum ctl tree depth. */ +#define CTL_MAX_DEPTH 7 + +typedef struct ctl_node_s { + bool named; +} ctl_node_t; + +typedef struct ctl_named_node_s { + ctl_node_t node; + const char *name; /* If (nchildren == 0), this is a terminal node. */ - unsigned nchildren; - const ctl_node_t *children; - int (*ctl)(const size_t *, size_t, void *, size_t *, - void *, size_t); -}; + size_t nchildren; + const ctl_node_t *children; + int (*ctl)(tsd_t *, const size_t *, size_t, void *, size_t *, void *, + size_t); +} ctl_named_node_t; -struct ctl_indexed_node_s { - struct ctl_node_s node; - const ctl_named_node_t *(*index)(const size_t *, size_t, size_t); -}; +typedef struct ctl_indexed_node_s { + struct ctl_node_s node; + const ctl_named_node_t *(*index)(tsdn_t *, const size_t *, size_t, + size_t); +} ctl_indexed_node_t; -struct ctl_arena_stats_s { - bool initialized; - unsigned nthreads; - const char *dss; - size_t pactive; - size_t pdirty; - arena_stats_t astats; +typedef struct ctl_arena_stats_s { + arena_stats_t astats; /* Aggregate stats for small size classes, based on bin stats. */ - size_t allocated_small; - uint64_t nmalloc_small; - uint64_t ndalloc_small; - uint64_t nrequests_small; - - malloc_bin_stats_t bstats[NBINS]; - malloc_large_stats_t *lstats; /* nlclasses elements. */ + size_t allocated_small; + uint64_t nmalloc_small; + uint64_t ndalloc_small; + uint64_t nrequests_small; + + malloc_bin_stats_t bstats[NBINS]; + malloc_large_stats_t lstats[NSIZES - NBINS]; +} ctl_arena_stats_t; + +typedef struct ctl_stats_s { + size_t allocated; + size_t active; + size_t metadata; + size_t resident; + size_t mapped; + size_t retained; + + background_thread_stats_t background_thread; + mutex_prof_data_t mutex_prof_data[mutex_prof_num_global_mutexes]; +} ctl_stats_t; + +typedef struct ctl_arena_s ctl_arena_t; +struct ctl_arena_s { + unsigned arena_ind; + bool initialized; + ql_elm(ctl_arena_t) destroyed_link; + + /* Basic stats, supported even if !config_stats. */ + unsigned nthreads; + const char *dss; + ssize_t dirty_decay_ms; + ssize_t muzzy_decay_ms; + size_t pactive; + size_t pdirty; + size_t pmuzzy; + + /* NULL if !config_stats. */ + ctl_arena_stats_t *astats; }; -struct ctl_stats_s { - size_t allocated; - size_t active; - size_t mapped; - struct { - size_t current; /* stats_chunks.curchunks */ - uint64_t total; /* stats_chunks.nchunks */ - size_t high; /* stats_chunks.highchunks */ - } chunks; - struct { - size_t allocated; /* huge_allocated */ - uint64_t nmalloc; /* huge_nmalloc */ - uint64_t ndalloc; /* huge_ndalloc */ - } huge; - unsigned narenas; - ctl_arena_stats_t *arenas; /* (narenas + 1) elements. */ -}; - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -int ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp, - size_t newlen); -int ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp); - -int ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, +typedef struct ctl_arenas_s { + uint64_t epoch; + unsigned narenas; + ql_head(ctl_arena_t) destroyed; + + /* + * Element 0 corresponds to merged stats for extant arenas (accessed via + * MALLCTL_ARENAS_ALL), element 1 corresponds to merged stats for + * destroyed arenas (accessed via MALLCTL_ARENAS_DESTROYED), and the + * remaining MALLOCX_ARENA_LIMIT elements correspond to arenas. + */ + ctl_arena_t *arenas[2 + MALLOCX_ARENA_LIMIT]; +} ctl_arenas_t; + +int ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen); -bool ctl_boot(void); -void ctl_prefork(void); -void ctl_postfork_parent(void); -void ctl_postfork_child(void); +int ctl_nametomib(tsd_t *tsd, const char *name, size_t *mibp, size_t *miblenp); -#define xmallctl(name, oldp, oldlenp, newp, newlen) do { \ +int ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen); +bool ctl_boot(void); +void ctl_prefork(tsdn_t *tsdn); +void ctl_postfork_parent(tsdn_t *tsdn); +void ctl_postfork_child(tsdn_t *tsdn); + +#define xmallctl(name, oldp, oldlenp, newp, newlen) do { \ if (je_mallctl(name, oldp, oldlenp, newp, newlen) \ != 0) { \ malloc_printf( \ @@ -91,7 +110,7 @@ void ctl_postfork_child(void); } \ } while (0) -#define xmallctlnametomib(name, mibp, miblenp) do { \ +#define xmallctlnametomib(name, mibp, miblenp) do { \ if (je_mallctlnametomib(name, mibp, miblenp) != 0) { \ malloc_printf("<jemalloc>: Failure in " \ "xmallctlnametomib(\"%s\", ...)\n", name); \ @@ -99,7 +118,7 @@ void ctl_postfork_child(void); } \ } while (0) -#define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \ +#define xmallctlbymib(mib, miblen, oldp, oldlenp, newp, newlen) do { \ if (je_mallctlbymib(mib, miblen, oldp, oldlenp, newp, \ newlen) != 0) { \ malloc_write( \ @@ -108,10 +127,4 @@ void ctl_postfork_child(void); } \ } while (0) -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ - +#endif /* JEMALLOC_INTERNAL_CTL_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/hash.h b/deps/jemalloc/include/jemalloc/internal/hash.h index c7183ede82..188296cf0e 100644 --- a/deps/jemalloc/include/jemalloc/internal/hash.h +++ b/deps/jemalloc/include/jemalloc/internal/hash.h @@ -1,92 +1,76 @@ +#ifndef JEMALLOC_INTERNAL_HASH_H +#define JEMALLOC_INTERNAL_HASH_H + +#include "jemalloc/internal/assert.h" + /* * The following hash function is based on MurmurHash3, placed into the public - * domain by Austin Appleby. See http://code.google.com/p/smhasher/ for + * domain by Austin Appleby. See https://github.com/aappleby/smhasher for * details. */ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#ifndef JEMALLOC_ENABLE_INLINE -uint32_t hash_x86_32(const void *key, int len, uint32_t seed); -void hash_x86_128(const void *key, const int len, uint32_t seed, - uint64_t r_out[2]); -void hash_x64_128(const void *key, const int len, const uint32_t seed, - uint64_t r_out[2]); -void hash(const void *key, size_t len, const uint32_t seed, - size_t r_hash[2]); -#endif - -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_HASH_C_)) /******************************************************************************/ /* Internal implementation. */ -JEMALLOC_INLINE uint32_t -hash_rotl_32(uint32_t x, int8_t r) -{ - - return (x << r) | (x >> (32 - r)); +static inline uint32_t +hash_rotl_32(uint32_t x, int8_t r) { + return ((x << r) | (x >> (32 - r))); } -JEMALLOC_INLINE uint64_t -hash_rotl_64(uint64_t x, int8_t r) -{ - return (x << r) | (x >> (64 - r)); +static inline uint64_t +hash_rotl_64(uint64_t x, int8_t r) { + return ((x << r) | (x >> (64 - r))); } -JEMALLOC_INLINE uint32_t -hash_get_block_32(const uint32_t *p, int i) -{ +static inline uint32_t +hash_get_block_32(const uint32_t *p, int i) { + /* Handle unaligned read. */ + if (unlikely((uintptr_t)p & (sizeof(uint32_t)-1)) != 0) { + uint32_t ret; - return (p[i]); + memcpy(&ret, (uint8_t *)(p + i), sizeof(uint32_t)); + return ret; + } + + return p[i]; } -JEMALLOC_INLINE uint64_t -hash_get_block_64(const uint64_t *p, int i) -{ +static inline uint64_t +hash_get_block_64(const uint64_t *p, int i) { + /* Handle unaligned read. */ + if (unlikely((uintptr_t)p & (sizeof(uint64_t)-1)) != 0) { + uint64_t ret; - return (p[i]); -} + memcpy(&ret, (uint8_t *)(p + i), sizeof(uint64_t)); + return ret; + } -JEMALLOC_INLINE uint32_t -hash_fmix_32(uint32_t h) -{ + return p[i]; +} +static inline uint32_t +hash_fmix_32(uint32_t h) { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; h *= 0xc2b2ae35; h ^= h >> 16; - return (h); + return h; } -JEMALLOC_INLINE uint64_t -hash_fmix_64(uint64_t k) -{ - +static inline uint64_t +hash_fmix_64(uint64_t k) { k ^= k >> 33; - k *= QU(0xff51afd7ed558ccdLLU); + k *= KQU(0xff51afd7ed558ccd); k ^= k >> 33; - k *= QU(0xc4ceb9fe1a85ec53LLU); + k *= KQU(0xc4ceb9fe1a85ec53); k ^= k >> 33; - return (k); + return k; } -JEMALLOC_INLINE uint32_t -hash_x86_32(const void *key, int len, uint32_t seed) -{ +static inline uint32_t +hash_x86_32(const void *key, int len, uint32_t seed) { const uint8_t *data = (const uint8_t *) key; const int nblocks = len / 4; @@ -132,13 +116,12 @@ hash_x86_32(const void *key, int len, uint32_t seed) h1 = hash_fmix_32(h1); - return (h1); + return h1; } -UNUSED JEMALLOC_INLINE void +UNUSED static inline void hash_x86_128(const void *key, const int len, uint32_t seed, - uint64_t r_out[2]) -{ + uint64_t r_out[2]) { const uint8_t * data = (const uint8_t *) key; const int nblocks = len / 16; @@ -237,18 +220,17 @@ hash_x86_128(const void *key, const int len, uint32_t seed, r_out[1] = (((uint64_t) h4) << 32) | h3; } -UNUSED JEMALLOC_INLINE void +UNUSED static inline void hash_x64_128(const void *key, const int len, const uint32_t seed, - uint64_t r_out[2]) -{ + uint64_t r_out[2]) { const uint8_t *data = (const uint8_t *) key; const int nblocks = len / 16; uint64_t h1 = seed; uint64_t h2 = seed; - const uint64_t c1 = QU(0x87c37b91114253d5LLU); - const uint64_t c2 = QU(0x4cf5ad432745937fLLU); + const uint64_t c1 = KQU(0x87c37b91114253d5); + const uint64_t c2 = KQU(0x4cf5ad432745937f); /* body */ { @@ -317,19 +299,20 @@ hash_x64_128(const void *key, const int len, const uint32_t seed, /******************************************************************************/ /* API. */ -JEMALLOC_INLINE void -hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2]) -{ +static inline void +hash(const void *key, size_t len, const uint32_t seed, size_t r_hash[2]) { + assert(len <= INT_MAX); /* Unfortunate implementation limitation. */ + #if (LG_SIZEOF_PTR == 3 && !defined(JEMALLOC_BIG_ENDIAN)) - hash_x64_128(key, len, seed, (uint64_t *)r_hash); + hash_x64_128(key, (int)len, seed, (uint64_t *)r_hash); #else - uint64_t hashes[2]; - hash_x86_128(key, len, seed, hashes); - r_hash[0] = (size_t)hashes[0]; - r_hash[1] = (size_t)hashes[1]; + { + uint64_t hashes[2]; + hash_x86_128(key, (int)len, seed, hashes); + r_hash[0] = (size_t)hashes[0]; + r_hash[1] = (size_t)hashes[1]; + } #endif } -#endif -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_HASH_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/mutex.h b/deps/jemalloc/include/jemalloc/internal/mutex.h index de44e1435a..6520c2512d 100644 --- a/deps/jemalloc/include/jemalloc/internal/mutex.h +++ b/deps/jemalloc/include/jemalloc/internal/mutex.h @@ -1,45 +1,123 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES +#ifndef JEMALLOC_INTERNAL_MUTEX_H +#define JEMALLOC_INTERNAL_MUTEX_H -typedef struct malloc_mutex_s malloc_mutex_t; +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex_prof.h" +#include "jemalloc/internal/tsd.h" +#include "jemalloc/internal/witness.h" + +typedef enum { + /* Can only acquire one mutex of a given witness rank at a time. */ + malloc_mutex_rank_exclusive, + /* + * Can acquire multiple mutexes of the same witness rank, but in + * address-ascending order only. + */ + malloc_mutex_address_ordered +} malloc_mutex_lock_order_t; +typedef struct malloc_mutex_s malloc_mutex_t; +struct malloc_mutex_s { + union { + struct { + /* + * prof_data is defined first to reduce cacheline + * bouncing: the data is not touched by the mutex holder + * during unlocking, while might be modified by + * contenders. Having it before the mutex itself could + * avoid prefetching a modified cacheline (for the + * unlocking thread). + */ + mutex_prof_data_t prof_data; #ifdef _WIN32 -# define MALLOC_MUTEX_INITIALIZER +# if _WIN32_WINNT >= 0x0600 + SRWLOCK lock; +# else + CRITICAL_SECTION lock; +# endif +#elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) + os_unfair_lock lock; #elif (defined(JEMALLOC_OSSPIN)) -# define MALLOC_MUTEX_INITIALIZER {0} + OSSpinLock lock; #elif (defined(JEMALLOC_MUTEX_INIT_CB)) -# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL} + pthread_mutex_t lock; + malloc_mutex_t *postponed_next; #else -# if (defined(PTHREAD_MUTEX_ADAPTIVE_NP) && \ - defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)) -# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_ADAPTIVE_NP -# define MALLOC_MUTEX_INITIALIZER {PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP} + pthread_mutex_t lock; +#endif + }; + /* + * We only touch witness when configured w/ debug. However we + * keep the field in a union when !debug so that we don't have + * to pollute the code base with #ifdefs, while avoid paying the + * memory cost. + */ +#if !defined(JEMALLOC_DEBUG) + witness_t witness; + malloc_mutex_lock_order_t lock_order; +#endif + }; + +#if defined(JEMALLOC_DEBUG) + witness_t witness; + malloc_mutex_lock_order_t lock_order; +#endif +}; + +/* + * Based on benchmark results, a fixed spin with this amount of retries works + * well for our critical sections. + */ +#define MALLOC_MUTEX_MAX_SPIN 250 + +#ifdef _WIN32 +# if _WIN32_WINNT >= 0x0600 +# define MALLOC_MUTEX_LOCK(m) AcquireSRWLockExclusive(&(m)->lock) +# define MALLOC_MUTEX_UNLOCK(m) ReleaseSRWLockExclusive(&(m)->lock) +# define MALLOC_MUTEX_TRYLOCK(m) (!TryAcquireSRWLockExclusive(&(m)->lock)) # else -# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT -# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER} +# define MALLOC_MUTEX_LOCK(m) EnterCriticalSection(&(m)->lock) +# define MALLOC_MUTEX_UNLOCK(m) LeaveCriticalSection(&(m)->lock) +# define MALLOC_MUTEX_TRYLOCK(m) (!TryEnterCriticalSection(&(m)->lock)) # endif +#elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) +# define MALLOC_MUTEX_LOCK(m) os_unfair_lock_lock(&(m)->lock) +# define MALLOC_MUTEX_UNLOCK(m) os_unfair_lock_unlock(&(m)->lock) +# define MALLOC_MUTEX_TRYLOCK(m) (!os_unfair_lock_trylock(&(m)->lock)) +#elif (defined(JEMALLOC_OSSPIN)) +# define MALLOC_MUTEX_LOCK(m) OSSpinLockLock(&(m)->lock) +# define MALLOC_MUTEX_UNLOCK(m) OSSpinLockUnlock(&(m)->lock) +# define MALLOC_MUTEX_TRYLOCK(m) (!OSSpinLockTry(&(m)->lock)) +#else +# define MALLOC_MUTEX_LOCK(m) pthread_mutex_lock(&(m)->lock) +# define MALLOC_MUTEX_UNLOCK(m) pthread_mutex_unlock(&(m)->lock) +# define MALLOC_MUTEX_TRYLOCK(m) (pthread_mutex_trylock(&(m)->lock) != 0) #endif -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS +#define LOCK_PROF_DATA_INITIALIZER \ + {NSTIME_ZERO_INITIALIZER, NSTIME_ZERO_INITIALIZER, 0, 0, 0, \ + ATOMIC_INIT(0), 0, NULL, 0} -struct malloc_mutex_s { #ifdef _WIN32 - CRITICAL_SECTION lock; +# define MALLOC_MUTEX_INITIALIZER +#elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, OS_UNFAIR_LOCK_INIT}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} #elif (defined(JEMALLOC_OSSPIN)) - OSSpinLock lock; +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, 0}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} #elif (defined(JEMALLOC_MUTEX_INIT_CB)) - pthread_mutex_t lock; - malloc_mutex_t *postponed_next; +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, NULL}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} #else - pthread_mutex_t lock; +# define MALLOC_MUTEX_TYPE PTHREAD_MUTEX_DEFAULT +# define MALLOC_MUTEX_INITIALIZER \ + {{{LOCK_PROF_DATA_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}}, \ + WITNESS_INITIALIZER("mutex", WITNESS_RANK_OMIT)} #endif -}; - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS #ifdef JEMALLOC_LAZY_LOCK extern bool isthreaded; @@ -48,52 +126,123 @@ extern bool isthreaded; # define isthreaded true #endif -bool malloc_mutex_init(malloc_mutex_t *mutex); -void malloc_mutex_prefork(malloc_mutex_t *mutex); -void malloc_mutex_postfork_parent(malloc_mutex_t *mutex); -void malloc_mutex_postfork_child(malloc_mutex_t *mutex); -bool mutex_boot(void); +bool malloc_mutex_init(malloc_mutex_t *mutex, const char *name, + witness_rank_t rank, malloc_mutex_lock_order_t lock_order); +void malloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex); +void malloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex); +void malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex); +bool malloc_mutex_boot(void); +void malloc_mutex_prof_data_reset(tsdn_t *tsdn, malloc_mutex_t *mutex); -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES +void malloc_mutex_lock_slow(malloc_mutex_t *mutex); -#ifndef JEMALLOC_ENABLE_INLINE -void malloc_mutex_lock(malloc_mutex_t *mutex); -void malloc_mutex_unlock(malloc_mutex_t *mutex); -#endif +static inline void +malloc_mutex_lock_final(malloc_mutex_t *mutex) { + MALLOC_MUTEX_LOCK(mutex); +} -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_)) -JEMALLOC_INLINE void -malloc_mutex_lock(malloc_mutex_t *mutex) -{ +static inline bool +malloc_mutex_trylock_final(malloc_mutex_t *mutex) { + return MALLOC_MUTEX_TRYLOCK(mutex); +} +static inline void +mutex_owner_stats_update(tsdn_t *tsdn, malloc_mutex_t *mutex) { + if (config_stats) { + mutex_prof_data_t *data = &mutex->prof_data; + data->n_lock_ops++; + if (data->prev_owner != tsdn) { + data->prev_owner = tsdn; + data->n_owner_switches++; + } + } +} + +/* Trylock: return false if the lock is successfully acquired. */ +static inline bool +malloc_mutex_trylock(tsdn_t *tsdn, malloc_mutex_t *mutex) { + witness_assert_not_owner(tsdn_witness_tsdp_get(tsdn), &mutex->witness); if (isthreaded) { -#ifdef _WIN32 - EnterCriticalSection(&mutex->lock); -#elif (defined(JEMALLOC_OSSPIN)) - OSSpinLockLock(&mutex->lock); -#else - pthread_mutex_lock(&mutex->lock); -#endif + if (malloc_mutex_trylock_final(mutex)) { + return true; + } + mutex_owner_stats_update(tsdn, mutex); } + witness_lock(tsdn_witness_tsdp_get(tsdn), &mutex->witness); + + return false; } -JEMALLOC_INLINE void -malloc_mutex_unlock(malloc_mutex_t *mutex) -{ +/* Aggregate lock prof data. */ +static inline void +malloc_mutex_prof_merge(mutex_prof_data_t *sum, mutex_prof_data_t *data) { + nstime_add(&sum->tot_wait_time, &data->tot_wait_time); + if (nstime_compare(&sum->max_wait_time, &data->max_wait_time) < 0) { + nstime_copy(&sum->max_wait_time, &data->max_wait_time); + } + + sum->n_wait_times += data->n_wait_times; + sum->n_spin_acquired += data->n_spin_acquired; + + if (sum->max_n_thds < data->max_n_thds) { + sum->max_n_thds = data->max_n_thds; + } + uint32_t cur_n_waiting_thds = atomic_load_u32(&sum->n_waiting_thds, + ATOMIC_RELAXED); + uint32_t new_n_waiting_thds = cur_n_waiting_thds + atomic_load_u32( + &data->n_waiting_thds, ATOMIC_RELAXED); + atomic_store_u32(&sum->n_waiting_thds, new_n_waiting_thds, + ATOMIC_RELAXED); + sum->n_owner_switches += data->n_owner_switches; + sum->n_lock_ops += data->n_lock_ops; +} +static inline void +malloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex) { + witness_assert_not_owner(tsdn_witness_tsdp_get(tsdn), &mutex->witness); if (isthreaded) { -#ifdef _WIN32 - LeaveCriticalSection(&mutex->lock); -#elif (defined(JEMALLOC_OSSPIN)) - OSSpinLockUnlock(&mutex->lock); -#else - pthread_mutex_unlock(&mutex->lock); -#endif + if (malloc_mutex_trylock_final(mutex)) { + malloc_mutex_lock_slow(mutex); + } + mutex_owner_stats_update(tsdn, mutex); } + witness_lock(tsdn_witness_tsdp_get(tsdn), &mutex->witness); +} + +static inline void +malloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex) { + witness_unlock(tsdn_witness_tsdp_get(tsdn), &mutex->witness); + if (isthreaded) { + MALLOC_MUTEX_UNLOCK(mutex); + } +} + +static inline void +malloc_mutex_assert_owner(tsdn_t *tsdn, malloc_mutex_t *mutex) { + witness_assert_owner(tsdn_witness_tsdp_get(tsdn), &mutex->witness); +} + +static inline void +malloc_mutex_assert_not_owner(tsdn_t *tsdn, malloc_mutex_t *mutex) { + witness_assert_not_owner(tsdn_witness_tsdp_get(tsdn), &mutex->witness); +} + +/* Copy the prof data from mutex for processing. */ +static inline void +malloc_mutex_prof_read(tsdn_t *tsdn, mutex_prof_data_t *data, + malloc_mutex_t *mutex) { + mutex_prof_data_t *source = &mutex->prof_data; + /* Can only read holding the mutex. */ + malloc_mutex_assert_owner(tsdn, mutex); + + /* + * Not *really* allowed (we shouldn't be doing non-atomic loads of + * atomic data), but the mutex protection makes this safe, and writing + * a member-for-member copy is tedious for this situation. + */ + *data = *source; + /* n_wait_thds is not reported (modified w/o locking). */ + atomic_store_u32(&data->n_waiting_thds, 0, ATOMIC_RELAXED); } -#endif -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_MUTEX_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/private_namespace.h b/deps/jemalloc/include/jemalloc/internal/private_namespace.h index 35c3b0c6c7..7ebeeba826 100644 --- a/deps/jemalloc/include/jemalloc/internal/private_namespace.h +++ b/deps/jemalloc/include/jemalloc/internal/private_namespace.h @@ -1,147 +1,199 @@ -#define a0calloc JEMALLOC_N(a0calloc) -#define a0free JEMALLOC_N(a0free) +#define a0dalloc JEMALLOC_N(a0dalloc) +#define a0get JEMALLOC_N(a0get) #define a0malloc JEMALLOC_N(a0malloc) +#define arena_aalloc JEMALLOC_N(arena_aalloc) #define arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small) +#define arena_basic_stats_merge JEMALLOC_N(arena_basic_stats_merge) #define arena_bin_index JEMALLOC_N(arena_bin_index) #define arena_bin_info JEMALLOC_N(arena_bin_info) +#define arena_bitselm_get_const JEMALLOC_N(arena_bitselm_get_const) +#define arena_bitselm_get_mutable JEMALLOC_N(arena_bitselm_get_mutable) #define arena_boot JEMALLOC_N(arena_boot) +#define arena_choose JEMALLOC_N(arena_choose) +#define arena_choose_hard JEMALLOC_N(arena_choose_hard) +#define arena_choose_impl JEMALLOC_N(arena_choose_impl) +#define arena_chunk_alloc_huge JEMALLOC_N(arena_chunk_alloc_huge) +#define arena_chunk_cache_maybe_insert JEMALLOC_N(arena_chunk_cache_maybe_insert) +#define arena_chunk_cache_maybe_remove JEMALLOC_N(arena_chunk_cache_maybe_remove) +#define arena_chunk_dalloc_huge JEMALLOC_N(arena_chunk_dalloc_huge) +#define arena_chunk_ralloc_huge_expand JEMALLOC_N(arena_chunk_ralloc_huge_expand) +#define arena_chunk_ralloc_huge_shrink JEMALLOC_N(arena_chunk_ralloc_huge_shrink) +#define arena_chunk_ralloc_huge_similar JEMALLOC_N(arena_chunk_ralloc_huge_similar) +#define arena_cleanup JEMALLOC_N(arena_cleanup) #define arena_dalloc JEMALLOC_N(arena_dalloc) #define arena_dalloc_bin JEMALLOC_N(arena_dalloc_bin) -#define arena_dalloc_bin_locked JEMALLOC_N(arena_dalloc_bin_locked) +#define arena_dalloc_bin_junked_locked JEMALLOC_N(arena_dalloc_bin_junked_locked) #define arena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large) #define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small) #define arena_dalloc_large JEMALLOC_N(arena_dalloc_large) -#define arena_dalloc_large_locked JEMALLOC_N(arena_dalloc_large_locked) +#define arena_dalloc_large_junked_locked JEMALLOC_N(arena_dalloc_large_junked_locked) #define arena_dalloc_small JEMALLOC_N(arena_dalloc_small) +#define arena_decay_tick JEMALLOC_N(arena_decay_tick) +#define arena_decay_ticks JEMALLOC_N(arena_decay_ticks) +#define arena_decay_time_default_get JEMALLOC_N(arena_decay_time_default_get) +#define arena_decay_time_default_set JEMALLOC_N(arena_decay_time_default_set) +#define arena_decay_time_get JEMALLOC_N(arena_decay_time_get) +#define arena_decay_time_set JEMALLOC_N(arena_decay_time_set) #define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get) #define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set) +#define arena_extent_sn_next JEMALLOC_N(arena_extent_sn_next) +#define arena_get JEMALLOC_N(arena_get) +#define arena_ichoose JEMALLOC_N(arena_ichoose) +#define arena_init JEMALLOC_N(arena_init) +#define arena_lg_dirty_mult_default_get JEMALLOC_N(arena_lg_dirty_mult_default_get) +#define arena_lg_dirty_mult_default_set JEMALLOC_N(arena_lg_dirty_mult_default_set) +#define arena_lg_dirty_mult_get JEMALLOC_N(arena_lg_dirty_mult_get) +#define arena_lg_dirty_mult_set JEMALLOC_N(arena_lg_dirty_mult_set) #define arena_malloc JEMALLOC_N(arena_malloc) +#define arena_malloc_hard JEMALLOC_N(arena_malloc_hard) #define arena_malloc_large JEMALLOC_N(arena_malloc_large) -#define arena_malloc_small JEMALLOC_N(arena_malloc_small) #define arena_mapbits_allocated_get JEMALLOC_N(arena_mapbits_allocated_get) #define arena_mapbits_binind_get JEMALLOC_N(arena_mapbits_binind_get) +#define arena_mapbits_decommitted_get JEMALLOC_N(arena_mapbits_decommitted_get) #define arena_mapbits_dirty_get JEMALLOC_N(arena_mapbits_dirty_get) #define arena_mapbits_get JEMALLOC_N(arena_mapbits_get) +#define arena_mapbits_internal_set JEMALLOC_N(arena_mapbits_internal_set) #define arena_mapbits_large_binind_set JEMALLOC_N(arena_mapbits_large_binind_set) #define arena_mapbits_large_get JEMALLOC_N(arena_mapbits_large_get) #define arena_mapbits_large_set JEMALLOC_N(arena_mapbits_large_set) #define arena_mapbits_large_size_get JEMALLOC_N(arena_mapbits_large_size_get) +#define arena_mapbits_size_decode JEMALLOC_N(arena_mapbits_size_decode) +#define arena_mapbits_size_encode JEMALLOC_N(arena_mapbits_size_encode) #define arena_mapbits_small_runind_get JEMALLOC_N(arena_mapbits_small_runind_get) #define arena_mapbits_small_set JEMALLOC_N(arena_mapbits_small_set) #define arena_mapbits_unallocated_set JEMALLOC_N(arena_mapbits_unallocated_set) #define arena_mapbits_unallocated_size_get JEMALLOC_N(arena_mapbits_unallocated_size_get) #define arena_mapbits_unallocated_size_set JEMALLOC_N(arena_mapbits_unallocated_size_set) #define arena_mapbits_unzeroed_get JEMALLOC_N(arena_mapbits_unzeroed_get) -#define arena_mapbits_unzeroed_set JEMALLOC_N(arena_mapbits_unzeroed_set) -#define arena_mapbitsp_get JEMALLOC_N(arena_mapbitsp_get) +#define arena_mapbitsp_get_const JEMALLOC_N(arena_mapbitsp_get_const) +#define arena_mapbitsp_get_mutable JEMALLOC_N(arena_mapbitsp_get_mutable) #define arena_mapbitsp_read JEMALLOC_N(arena_mapbitsp_read) #define arena_mapbitsp_write JEMALLOC_N(arena_mapbitsp_write) -#define arena_mapp_get JEMALLOC_N(arena_mapp_get) -#define arena_maxclass JEMALLOC_N(arena_maxclass) +#define arena_maxrun JEMALLOC_N(arena_maxrun) +#define arena_maybe_purge JEMALLOC_N(arena_maybe_purge) +#define arena_metadata_allocated_add JEMALLOC_N(arena_metadata_allocated_add) +#define arena_metadata_allocated_get JEMALLOC_N(arena_metadata_allocated_get) +#define arena_metadata_allocated_sub JEMALLOC_N(arena_metadata_allocated_sub) +#define arena_migrate JEMALLOC_N(arena_migrate) +#define arena_miscelm_get_const JEMALLOC_N(arena_miscelm_get_const) +#define arena_miscelm_get_mutable JEMALLOC_N(arena_miscelm_get_mutable) +#define arena_miscelm_to_pageind JEMALLOC_N(arena_miscelm_to_pageind) +#define arena_miscelm_to_rpages JEMALLOC_N(arena_miscelm_to_rpages) #define arena_new JEMALLOC_N(arena_new) +#define arena_node_alloc JEMALLOC_N(arena_node_alloc) +#define arena_node_dalloc JEMALLOC_N(arena_node_dalloc) +#define arena_nthreads_dec JEMALLOC_N(arena_nthreads_dec) +#define arena_nthreads_get JEMALLOC_N(arena_nthreads_get) +#define arena_nthreads_inc JEMALLOC_N(arena_nthreads_inc) #define arena_palloc JEMALLOC_N(arena_palloc) #define arena_postfork_child JEMALLOC_N(arena_postfork_child) #define arena_postfork_parent JEMALLOC_N(arena_postfork_parent) -#define arena_prefork JEMALLOC_N(arena_prefork) +#define arena_prefork0 JEMALLOC_N(arena_prefork0) +#define arena_prefork1 JEMALLOC_N(arena_prefork1) +#define arena_prefork2 JEMALLOC_N(arena_prefork2) +#define arena_prefork3 JEMALLOC_N(arena_prefork3) #define arena_prof_accum JEMALLOC_N(arena_prof_accum) #define arena_prof_accum_impl JEMALLOC_N(arena_prof_accum_impl) #define arena_prof_accum_locked JEMALLOC_N(arena_prof_accum_locked) -#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get) -#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set) #define arena_prof_promoted JEMALLOC_N(arena_prof_promoted) +#define arena_prof_tctx_get JEMALLOC_N(arena_prof_tctx_get) +#define arena_prof_tctx_reset JEMALLOC_N(arena_prof_tctx_reset) +#define arena_prof_tctx_set JEMALLOC_N(arena_prof_tctx_set) #define arena_ptr_small_binind_get JEMALLOC_N(arena_ptr_small_binind_get) -#define arena_purge_all JEMALLOC_N(arena_purge_all) +#define arena_purge JEMALLOC_N(arena_purge) #define arena_quarantine_junk_small JEMALLOC_N(arena_quarantine_junk_small) #define arena_ralloc JEMALLOC_N(arena_ralloc) #define arena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large) #define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move) +#define arena_rd_to_miscelm JEMALLOC_N(arena_rd_to_miscelm) #define arena_redzone_corruption JEMALLOC_N(arena_redzone_corruption) +#define arena_reset JEMALLOC_N(arena_reset) #define arena_run_regind JEMALLOC_N(arena_run_regind) +#define arena_run_to_miscelm JEMALLOC_N(arena_run_to_miscelm) #define arena_salloc JEMALLOC_N(arena_salloc) +#define arena_sdalloc JEMALLOC_N(arena_sdalloc) #define arena_stats_merge JEMALLOC_N(arena_stats_merge) #define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small) +#define arena_tdata_get JEMALLOC_N(arena_tdata_get) +#define arena_tdata_get_hard JEMALLOC_N(arena_tdata_get_hard) #define arenas JEMALLOC_N(arenas) -#define arenas_booted JEMALLOC_N(arenas_booted) -#define arenas_cleanup JEMALLOC_N(arenas_cleanup) -#define arenas_extend JEMALLOC_N(arenas_extend) -#define arenas_initialized JEMALLOC_N(arenas_initialized) -#define arenas_lock JEMALLOC_N(arenas_lock) -#define arenas_tls JEMALLOC_N(arenas_tls) -#define arenas_tsd JEMALLOC_N(arenas_tsd) -#define arenas_tsd_boot JEMALLOC_N(arenas_tsd_boot) -#define arenas_tsd_cleanup_wrapper JEMALLOC_N(arenas_tsd_cleanup_wrapper) -#define arenas_tsd_get JEMALLOC_N(arenas_tsd_get) -#define arenas_tsd_get_wrapper JEMALLOC_N(arenas_tsd_get_wrapper) -#define arenas_tsd_init_head JEMALLOC_N(arenas_tsd_init_head) -#define arenas_tsd_set JEMALLOC_N(arenas_tsd_set) +#define arenas_tdata_bypass_cleanup JEMALLOC_N(arenas_tdata_bypass_cleanup) +#define arenas_tdata_cleanup JEMALLOC_N(arenas_tdata_cleanup) +#define atomic_add_p JEMALLOC_N(atomic_add_p) #define atomic_add_u JEMALLOC_N(atomic_add_u) #define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32) #define atomic_add_uint64 JEMALLOC_N(atomic_add_uint64) #define atomic_add_z JEMALLOC_N(atomic_add_z) +#define atomic_cas_p JEMALLOC_N(atomic_cas_p) +#define atomic_cas_u JEMALLOC_N(atomic_cas_u) +#define atomic_cas_uint32 JEMALLOC_N(atomic_cas_uint32) +#define atomic_cas_uint64 JEMALLOC_N(atomic_cas_uint64) +#define atomic_cas_z JEMALLOC_N(atomic_cas_z) +#define atomic_sub_p JEMALLOC_N(atomic_sub_p) #define atomic_sub_u JEMALLOC_N(atomic_sub_u) #define atomic_sub_uint32 JEMALLOC_N(atomic_sub_uint32) #define atomic_sub_uint64 JEMALLOC_N(atomic_sub_uint64) #define atomic_sub_z JEMALLOC_N(atomic_sub_z) +#define atomic_write_p JEMALLOC_N(atomic_write_p) +#define atomic_write_u JEMALLOC_N(atomic_write_u) +#define atomic_write_uint32 JEMALLOC_N(atomic_write_uint32) +#define atomic_write_uint64 JEMALLOC_N(atomic_write_uint64) +#define atomic_write_z JEMALLOC_N(atomic_write_z) #define base_alloc JEMALLOC_N(base_alloc) #define base_boot JEMALLOC_N(base_boot) -#define base_calloc JEMALLOC_N(base_calloc) -#define base_node_alloc JEMALLOC_N(base_node_alloc) -#define base_node_dealloc JEMALLOC_N(base_node_dealloc) #define base_postfork_child JEMALLOC_N(base_postfork_child) #define base_postfork_parent JEMALLOC_N(base_postfork_parent) #define base_prefork JEMALLOC_N(base_prefork) +#define base_stats_get JEMALLOC_N(base_stats_get) #define bitmap_full JEMALLOC_N(bitmap_full) #define bitmap_get JEMALLOC_N(bitmap_get) #define bitmap_info_init JEMALLOC_N(bitmap_info_init) -#define bitmap_info_ngroups JEMALLOC_N(bitmap_info_ngroups) #define bitmap_init JEMALLOC_N(bitmap_init) #define bitmap_set JEMALLOC_N(bitmap_set) #define bitmap_sfu JEMALLOC_N(bitmap_sfu) #define bitmap_size JEMALLOC_N(bitmap_size) #define bitmap_unset JEMALLOC_N(bitmap_unset) +#define bootstrap_calloc JEMALLOC_N(bootstrap_calloc) +#define bootstrap_free JEMALLOC_N(bootstrap_free) +#define bootstrap_malloc JEMALLOC_N(bootstrap_malloc) #define bt_init JEMALLOC_N(bt_init) #define buferror JEMALLOC_N(buferror) -#define choose_arena JEMALLOC_N(choose_arena) -#define choose_arena_hard JEMALLOC_N(choose_arena_hard) -#define chunk_alloc JEMALLOC_N(chunk_alloc) +#define chunk_alloc_base JEMALLOC_N(chunk_alloc_base) +#define chunk_alloc_cache JEMALLOC_N(chunk_alloc_cache) #define chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss) #define chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap) +#define chunk_alloc_wrapper JEMALLOC_N(chunk_alloc_wrapper) #define chunk_boot JEMALLOC_N(chunk_boot) -#define chunk_dealloc JEMALLOC_N(chunk_dealloc) -#define chunk_dealloc_mmap JEMALLOC_N(chunk_dealloc_mmap) +#define chunk_dalloc_cache JEMALLOC_N(chunk_dalloc_cache) +#define chunk_dalloc_mmap JEMALLOC_N(chunk_dalloc_mmap) +#define chunk_dalloc_wrapper JEMALLOC_N(chunk_dalloc_wrapper) +#define chunk_deregister JEMALLOC_N(chunk_deregister) #define chunk_dss_boot JEMALLOC_N(chunk_dss_boot) -#define chunk_dss_postfork_child JEMALLOC_N(chunk_dss_postfork_child) -#define chunk_dss_postfork_parent JEMALLOC_N(chunk_dss_postfork_parent) +#define chunk_dss_mergeable JEMALLOC_N(chunk_dss_mergeable) #define chunk_dss_prec_get JEMALLOC_N(chunk_dss_prec_get) #define chunk_dss_prec_set JEMALLOC_N(chunk_dss_prec_set) -#define chunk_dss_prefork JEMALLOC_N(chunk_dss_prefork) +#define chunk_hooks_default JEMALLOC_N(chunk_hooks_default) +#define chunk_hooks_get JEMALLOC_N(chunk_hooks_get) +#define chunk_hooks_set JEMALLOC_N(chunk_hooks_set) #define chunk_in_dss JEMALLOC_N(chunk_in_dss) +#define chunk_lookup JEMALLOC_N(chunk_lookup) #define chunk_npages JEMALLOC_N(chunk_npages) -#define chunk_postfork_child JEMALLOC_N(chunk_postfork_child) -#define chunk_postfork_parent JEMALLOC_N(chunk_postfork_parent) -#define chunk_prefork JEMALLOC_N(chunk_prefork) -#define chunk_unmap JEMALLOC_N(chunk_unmap) -#define chunks_mtx JEMALLOC_N(chunks_mtx) +#define chunk_purge_wrapper JEMALLOC_N(chunk_purge_wrapper) +#define chunk_register JEMALLOC_N(chunk_register) #define chunks_rtree JEMALLOC_N(chunks_rtree) #define chunksize JEMALLOC_N(chunksize) #define chunksize_mask JEMALLOC_N(chunksize_mask) -#define ckh_bucket_search JEMALLOC_N(ckh_bucket_search) #define ckh_count JEMALLOC_N(ckh_count) #define ckh_delete JEMALLOC_N(ckh_delete) -#define ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert) #define ckh_insert JEMALLOC_N(ckh_insert) -#define ckh_isearch JEMALLOC_N(ckh_isearch) #define ckh_iter JEMALLOC_N(ckh_iter) #define ckh_new JEMALLOC_N(ckh_new) #define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash) #define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp) -#define ckh_rebuild JEMALLOC_N(ckh_rebuild) #define ckh_remove JEMALLOC_N(ckh_remove) #define ckh_search JEMALLOC_N(ckh_search) #define ckh_string_hash JEMALLOC_N(ckh_string_hash) #define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp) -#define ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert) -#define ckh_try_insert JEMALLOC_N(ckh_try_insert) #define ctl_boot JEMALLOC_N(ctl_boot) #define ctl_bymib JEMALLOC_N(ctl_bymib) #define ctl_byname JEMALLOC_N(ctl_byname) @@ -149,7 +201,33 @@ #define ctl_postfork_child JEMALLOC_N(ctl_postfork_child) #define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent) #define ctl_prefork JEMALLOC_N(ctl_prefork) +#define decay_ticker_get JEMALLOC_N(decay_ticker_get) #define dss_prec_names JEMALLOC_N(dss_prec_names) +#define extent_node_achunk_get JEMALLOC_N(extent_node_achunk_get) +#define extent_node_achunk_set JEMALLOC_N(extent_node_achunk_set) +#define extent_node_addr_get JEMALLOC_N(extent_node_addr_get) +#define extent_node_addr_set JEMALLOC_N(extent_node_addr_set) +#define extent_node_arena_get JEMALLOC_N(extent_node_arena_get) +#define extent_node_arena_set JEMALLOC_N(extent_node_arena_set) +#define extent_node_committed_get JEMALLOC_N(extent_node_committed_get) +#define extent_node_committed_set JEMALLOC_N(extent_node_committed_set) +#define extent_node_dirty_insert JEMALLOC_N(extent_node_dirty_insert) +#define extent_node_dirty_linkage_init JEMALLOC_N(extent_node_dirty_linkage_init) +#define extent_node_dirty_remove JEMALLOC_N(extent_node_dirty_remove) +#define extent_node_init JEMALLOC_N(extent_node_init) +#define extent_node_prof_tctx_get JEMALLOC_N(extent_node_prof_tctx_get) +#define extent_node_prof_tctx_set JEMALLOC_N(extent_node_prof_tctx_set) +#define extent_node_size_get JEMALLOC_N(extent_node_size_get) +#define extent_node_size_set JEMALLOC_N(extent_node_size_set) +#define extent_node_sn_get JEMALLOC_N(extent_node_sn_get) +#define extent_node_sn_set JEMALLOC_N(extent_node_sn_set) +#define extent_node_zeroed_get JEMALLOC_N(extent_node_zeroed_get) +#define extent_node_zeroed_set JEMALLOC_N(extent_node_zeroed_set) +#define extent_size_quantize_ceil JEMALLOC_N(extent_size_quantize_ceil) +#define extent_size_quantize_floor JEMALLOC_N(extent_size_quantize_floor) +#define extent_tree_ad_destroy JEMALLOC_N(extent_tree_ad_destroy) +#define extent_tree_ad_destroy_recurse JEMALLOC_N(extent_tree_ad_destroy_recurse) +#define extent_tree_ad_empty JEMALLOC_N(extent_tree_ad_empty) #define extent_tree_ad_first JEMALLOC_N(extent_tree_ad_first) #define extent_tree_ad_insert JEMALLOC_N(extent_tree_ad_insert) #define extent_tree_ad_iter JEMALLOC_N(extent_tree_ad_iter) @@ -166,22 +244,31 @@ #define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse) #define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start) #define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search) -#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first) -#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert) -#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter) -#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse) -#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start) -#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last) -#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new) -#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next) -#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch) -#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev) -#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch) -#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove) -#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter) -#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse) -#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start) -#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search) +#define extent_tree_szsnad_destroy JEMALLOC_N(extent_tree_szsnad_destroy) +#define extent_tree_szsnad_destroy_recurse JEMALLOC_N(extent_tree_szsnad_destroy_recurse) +#define extent_tree_szsnad_empty JEMALLOC_N(extent_tree_szsnad_empty) +#define extent_tree_szsnad_first JEMALLOC_N(extent_tree_szsnad_first) +#define extent_tree_szsnad_insert JEMALLOC_N(extent_tree_szsnad_insert) +#define extent_tree_szsnad_iter JEMALLOC_N(extent_tree_szsnad_iter) +#define extent_tree_szsnad_iter_recurse JEMALLOC_N(extent_tree_szsnad_iter_recurse) +#define extent_tree_szsnad_iter_start JEMALLOC_N(extent_tree_szsnad_iter_start) +#define extent_tree_szsnad_last JEMALLOC_N(extent_tree_szsnad_last) +#define extent_tree_szsnad_new JEMALLOC_N(extent_tree_szsnad_new) +#define extent_tree_szsnad_next JEMALLOC_N(extent_tree_szsnad_next) +#define extent_tree_szsnad_nsearch JEMALLOC_N(extent_tree_szsnad_nsearch) +#define extent_tree_szsnad_prev JEMALLOC_N(extent_tree_szsnad_prev) +#define extent_tree_szsnad_psearch JEMALLOC_N(extent_tree_szsnad_psearch) +#define extent_tree_szsnad_remove JEMALLOC_N(extent_tree_szsnad_remove) +#define extent_tree_szsnad_reverse_iter JEMALLOC_N(extent_tree_szsnad_reverse_iter) +#define extent_tree_szsnad_reverse_iter_recurse JEMALLOC_N(extent_tree_szsnad_reverse_iter_recurse) +#define extent_tree_szsnad_reverse_iter_start JEMALLOC_N(extent_tree_szsnad_reverse_iter_start) +#define extent_tree_szsnad_search JEMALLOC_N(extent_tree_szsnad_search) +#define ffs_llu JEMALLOC_N(ffs_llu) +#define ffs_lu JEMALLOC_N(ffs_lu) +#define ffs_u JEMALLOC_N(ffs_u) +#define ffs_u32 JEMALLOC_N(ffs_u32) +#define ffs_u64 JEMALLOC_N(ffs_u64) +#define ffs_zu JEMALLOC_N(ffs_zu) #define get_errno JEMALLOC_N(get_errno) #define hash JEMALLOC_N(hash) #define hash_fmix_32 JEMALLOC_N(hash_fmix_32) @@ -193,46 +280,51 @@ #define hash_x64_128 JEMALLOC_N(hash_x64_128) #define hash_x86_128 JEMALLOC_N(hash_x86_128) #define hash_x86_32 JEMALLOC_N(hash_x86_32) -#define huge_allocated JEMALLOC_N(huge_allocated) -#define huge_boot JEMALLOC_N(huge_boot) +#define huge_aalloc JEMALLOC_N(huge_aalloc) #define huge_dalloc JEMALLOC_N(huge_dalloc) #define huge_dalloc_junk JEMALLOC_N(huge_dalloc_junk) -#define huge_dss_prec_get JEMALLOC_N(huge_dss_prec_get) #define huge_malloc JEMALLOC_N(huge_malloc) -#define huge_mtx JEMALLOC_N(huge_mtx) -#define huge_ndalloc JEMALLOC_N(huge_ndalloc) -#define huge_nmalloc JEMALLOC_N(huge_nmalloc) #define huge_palloc JEMALLOC_N(huge_palloc) -#define huge_postfork_child JEMALLOC_N(huge_postfork_child) -#define huge_postfork_parent JEMALLOC_N(huge_postfork_parent) -#define huge_prefork JEMALLOC_N(huge_prefork) -#define huge_prof_ctx_get JEMALLOC_N(huge_prof_ctx_get) -#define huge_prof_ctx_set JEMALLOC_N(huge_prof_ctx_set) +#define huge_prof_tctx_get JEMALLOC_N(huge_prof_tctx_get) +#define huge_prof_tctx_reset JEMALLOC_N(huge_prof_tctx_reset) +#define huge_prof_tctx_set JEMALLOC_N(huge_prof_tctx_set) #define huge_ralloc JEMALLOC_N(huge_ralloc) #define huge_ralloc_no_move JEMALLOC_N(huge_ralloc_no_move) #define huge_salloc JEMALLOC_N(huge_salloc) -#define iallocm JEMALLOC_N(iallocm) -#define icalloc JEMALLOC_N(icalloc) -#define icalloct JEMALLOC_N(icalloct) +#define iaalloc JEMALLOC_N(iaalloc) +#define ialloc JEMALLOC_N(ialloc) +#define iallocztm JEMALLOC_N(iallocztm) +#define iarena_cleanup JEMALLOC_N(iarena_cleanup) #define idalloc JEMALLOC_N(idalloc) -#define idalloct JEMALLOC_N(idalloct) -#define imalloc JEMALLOC_N(imalloc) -#define imalloct JEMALLOC_N(imalloct) +#define idalloctm JEMALLOC_N(idalloctm) +#define in_valgrind JEMALLOC_N(in_valgrind) +#define index2size JEMALLOC_N(index2size) +#define index2size_compute JEMALLOC_N(index2size_compute) +#define index2size_lookup JEMALLOC_N(index2size_lookup) +#define index2size_tab JEMALLOC_N(index2size_tab) #define ipalloc JEMALLOC_N(ipalloc) #define ipalloct JEMALLOC_N(ipalloct) +#define ipallocztm JEMALLOC_N(ipallocztm) #define iqalloc JEMALLOC_N(iqalloc) -#define iqalloct JEMALLOC_N(iqalloct) #define iralloc JEMALLOC_N(iralloc) #define iralloct JEMALLOC_N(iralloct) #define iralloct_realign JEMALLOC_N(iralloct_realign) #define isalloc JEMALLOC_N(isalloc) +#define isdalloct JEMALLOC_N(isdalloct) +#define isqalloc JEMALLOC_N(isqalloc) #define isthreaded JEMALLOC_N(isthreaded) #define ivsalloc JEMALLOC_N(ivsalloc) #define ixalloc JEMALLOC_N(ixalloc) #define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child) #define jemalloc_postfork_parent JEMALLOC_N(jemalloc_postfork_parent) #define jemalloc_prefork JEMALLOC_N(jemalloc_prefork) +#define large_maxclass JEMALLOC_N(large_maxclass) +#define lg_floor JEMALLOC_N(lg_floor) +#define lg_prof_sample JEMALLOC_N(lg_prof_sample) #define malloc_cprintf JEMALLOC_N(malloc_cprintf) +#define malloc_mutex_assert_not_owner JEMALLOC_N(malloc_mutex_assert_not_owner) +#define malloc_mutex_assert_owner JEMALLOC_N(malloc_mutex_assert_owner) +#define malloc_mutex_boot JEMALLOC_N(malloc_mutex_boot) #define malloc_mutex_init JEMALLOC_N(malloc_mutex_init) #define malloc_mutex_lock JEMALLOC_N(malloc_mutex_lock) #define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child) @@ -242,7 +334,8 @@ #define malloc_printf JEMALLOC_N(malloc_printf) #define malloc_snprintf JEMALLOC_N(malloc_snprintf) #define malloc_strtoumax JEMALLOC_N(malloc_strtoumax) -#define malloc_tsd_boot JEMALLOC_N(malloc_tsd_boot) +#define malloc_tsd_boot0 JEMALLOC_N(malloc_tsd_boot0) +#define malloc_tsd_boot1 JEMALLOC_N(malloc_tsd_boot1) #define malloc_tsd_cleanup_register JEMALLOC_N(malloc_tsd_cleanup_register) #define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc) #define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc) @@ -251,16 +344,35 @@ #define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf) #define malloc_write JEMALLOC_N(malloc_write) #define map_bias JEMALLOC_N(map_bias) +#define map_misc_offset JEMALLOC_N(map_misc_offset) #define mb_write JEMALLOC_N(mb_write) -#define mutex_boot JEMALLOC_N(mutex_boot) #define narenas_auto JEMALLOC_N(narenas_auto) -#define narenas_total JEMALLOC_N(narenas_total) +#define narenas_tdata_cleanup JEMALLOC_N(narenas_tdata_cleanup) #define narenas_total_get JEMALLOC_N(narenas_total_get) #define ncpus JEMALLOC_N(ncpus) #define nhbins JEMALLOC_N(nhbins) +#define nhclasses JEMALLOC_N(nhclasses) +#define nlclasses JEMALLOC_N(nlclasses) +#define nstime_add JEMALLOC_N(nstime_add) +#define nstime_compare JEMALLOC_N(nstime_compare) +#define nstime_copy JEMALLOC_N(nstime_copy) +#define nstime_divide JEMALLOC_N(nstime_divide) +#define nstime_idivide JEMALLOC_N(nstime_idivide) +#define nstime_imultiply JEMALLOC_N(nstime_imultiply) +#define nstime_init JEMALLOC_N(nstime_init) +#define nstime_init2 JEMALLOC_N(nstime_init2) +#define nstime_monotonic JEMALLOC_N(nstime_monotonic) +#define nstime_ns JEMALLOC_N(nstime_ns) +#define nstime_nsec JEMALLOC_N(nstime_nsec) +#define nstime_sec JEMALLOC_N(nstime_sec) +#define nstime_subtract JEMALLOC_N(nstime_subtract) +#define nstime_update JEMALLOC_N(nstime_update) #define opt_abort JEMALLOC_N(opt_abort) +#define opt_decay_time JEMALLOC_N(opt_decay_time) #define opt_dss JEMALLOC_N(opt_dss) #define opt_junk JEMALLOC_N(opt_junk) +#define opt_junk_alloc JEMALLOC_N(opt_junk_alloc) +#define opt_junk_free JEMALLOC_N(opt_junk_free) #define opt_lg_chunk JEMALLOC_N(opt_lg_chunk) #define opt_lg_dirty_mult JEMALLOC_N(opt_lg_dirty_mult) #define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval) @@ -274,140 +386,254 @@ #define opt_prof_gdump JEMALLOC_N(opt_prof_gdump) #define opt_prof_leak JEMALLOC_N(opt_prof_leak) #define opt_prof_prefix JEMALLOC_N(opt_prof_prefix) +#define opt_prof_thread_active_init JEMALLOC_N(opt_prof_thread_active_init) +#define opt_purge JEMALLOC_N(opt_purge) #define opt_quarantine JEMALLOC_N(opt_quarantine) #define opt_redzone JEMALLOC_N(opt_redzone) #define opt_stats_print JEMALLOC_N(opt_stats_print) #define opt_tcache JEMALLOC_N(opt_tcache) +#define opt_thp JEMALLOC_N(opt_thp) #define opt_utrace JEMALLOC_N(opt_utrace) -#define opt_valgrind JEMALLOC_N(opt_valgrind) #define opt_xmalloc JEMALLOC_N(opt_xmalloc) #define opt_zero JEMALLOC_N(opt_zero) #define p2rz JEMALLOC_N(p2rz) +#define pages_boot JEMALLOC_N(pages_boot) +#define pages_commit JEMALLOC_N(pages_commit) +#define pages_decommit JEMALLOC_N(pages_decommit) +#define pages_huge JEMALLOC_N(pages_huge) +#define pages_map JEMALLOC_N(pages_map) +#define pages_nohuge JEMALLOC_N(pages_nohuge) #define pages_purge JEMALLOC_N(pages_purge) -#define pow2_ceil JEMALLOC_N(pow2_ceil) +#define pages_trim JEMALLOC_N(pages_trim) +#define pages_unmap JEMALLOC_N(pages_unmap) +#define pind2sz JEMALLOC_N(pind2sz) +#define pind2sz_compute JEMALLOC_N(pind2sz_compute) +#define pind2sz_lookup JEMALLOC_N(pind2sz_lookup) +#define pind2sz_tab JEMALLOC_N(pind2sz_tab) +#define pow2_ceil_u32 JEMALLOC_N(pow2_ceil_u32) +#define pow2_ceil_u64 JEMALLOC_N(pow2_ceil_u64) +#define pow2_ceil_zu JEMALLOC_N(pow2_ceil_zu) +#define prng_lg_range_u32 JEMALLOC_N(prng_lg_range_u32) +#define prng_lg_range_u64 JEMALLOC_N(prng_lg_range_u64) +#define prng_lg_range_zu JEMALLOC_N(prng_lg_range_zu) +#define prng_range_u32 JEMALLOC_N(prng_range_u32) +#define prng_range_u64 JEMALLOC_N(prng_range_u64) +#define prng_range_zu JEMALLOC_N(prng_range_zu) +#define prng_state_next_u32 JEMALLOC_N(prng_state_next_u32) +#define prng_state_next_u64 JEMALLOC_N(prng_state_next_u64) +#define prng_state_next_zu JEMALLOC_N(prng_state_next_zu) +#define prof_active JEMALLOC_N(prof_active) +#define prof_active_get JEMALLOC_N(prof_active_get) +#define prof_active_get_unlocked JEMALLOC_N(prof_active_get_unlocked) +#define prof_active_set JEMALLOC_N(prof_active_set) +#define prof_alloc_prep JEMALLOC_N(prof_alloc_prep) +#define prof_alloc_rollback JEMALLOC_N(prof_alloc_rollback) #define prof_backtrace JEMALLOC_N(prof_backtrace) #define prof_boot0 JEMALLOC_N(prof_boot0) #define prof_boot1 JEMALLOC_N(prof_boot1) #define prof_boot2 JEMALLOC_N(prof_boot2) #define prof_bt_count JEMALLOC_N(prof_bt_count) -#define prof_ctx_get JEMALLOC_N(prof_ctx_get) -#define prof_ctx_set JEMALLOC_N(prof_ctx_set) +#define prof_dump_header JEMALLOC_N(prof_dump_header) #define prof_dump_open JEMALLOC_N(prof_dump_open) #define prof_free JEMALLOC_N(prof_free) +#define prof_free_sampled_object JEMALLOC_N(prof_free_sampled_object) #define prof_gdump JEMALLOC_N(prof_gdump) +#define prof_gdump_get JEMALLOC_N(prof_gdump_get) +#define prof_gdump_get_unlocked JEMALLOC_N(prof_gdump_get_unlocked) +#define prof_gdump_set JEMALLOC_N(prof_gdump_set) +#define prof_gdump_val JEMALLOC_N(prof_gdump_val) #define prof_idump JEMALLOC_N(prof_idump) #define prof_interval JEMALLOC_N(prof_interval) #define prof_lookup JEMALLOC_N(prof_lookup) #define prof_malloc JEMALLOC_N(prof_malloc) +#define prof_malloc_sample_object JEMALLOC_N(prof_malloc_sample_object) #define prof_mdump JEMALLOC_N(prof_mdump) #define prof_postfork_child JEMALLOC_N(prof_postfork_child) #define prof_postfork_parent JEMALLOC_N(prof_postfork_parent) -#define prof_prefork JEMALLOC_N(prof_prefork) -#define prof_promote JEMALLOC_N(prof_promote) +#define prof_prefork0 JEMALLOC_N(prof_prefork0) +#define prof_prefork1 JEMALLOC_N(prof_prefork1) #define prof_realloc JEMALLOC_N(prof_realloc) +#define prof_reset JEMALLOC_N(prof_reset) #define prof_sample_accum_update JEMALLOC_N(prof_sample_accum_update) #define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update) -#define prof_tdata_booted JEMALLOC_N(prof_tdata_booted) +#define prof_tctx_get JEMALLOC_N(prof_tctx_get) +#define prof_tctx_reset JEMALLOC_N(prof_tctx_reset) +#define prof_tctx_set JEMALLOC_N(prof_tctx_set) #define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup) +#define prof_tdata_count JEMALLOC_N(prof_tdata_count) #define prof_tdata_get JEMALLOC_N(prof_tdata_get) #define prof_tdata_init JEMALLOC_N(prof_tdata_init) -#define prof_tdata_initialized JEMALLOC_N(prof_tdata_initialized) -#define prof_tdata_tls JEMALLOC_N(prof_tdata_tls) -#define prof_tdata_tsd JEMALLOC_N(prof_tdata_tsd) -#define prof_tdata_tsd_boot JEMALLOC_N(prof_tdata_tsd_boot) -#define prof_tdata_tsd_cleanup_wrapper JEMALLOC_N(prof_tdata_tsd_cleanup_wrapper) -#define prof_tdata_tsd_get JEMALLOC_N(prof_tdata_tsd_get) -#define prof_tdata_tsd_get_wrapper JEMALLOC_N(prof_tdata_tsd_get_wrapper) -#define prof_tdata_tsd_init_head JEMALLOC_N(prof_tdata_tsd_init_head) -#define prof_tdata_tsd_set JEMALLOC_N(prof_tdata_tsd_set) +#define prof_tdata_reinit JEMALLOC_N(prof_tdata_reinit) +#define prof_thread_active_get JEMALLOC_N(prof_thread_active_get) +#define prof_thread_active_init_get JEMALLOC_N(prof_thread_active_init_get) +#define prof_thread_active_init_set JEMALLOC_N(prof_thread_active_init_set) +#define prof_thread_active_set JEMALLOC_N(prof_thread_active_set) +#define prof_thread_name_get JEMALLOC_N(prof_thread_name_get) +#define prof_thread_name_set JEMALLOC_N(prof_thread_name_set) +#define psz2ind JEMALLOC_N(psz2ind) +#define psz2u JEMALLOC_N(psz2u) +#define purge_mode_names JEMALLOC_N(purge_mode_names) #define quarantine JEMALLOC_N(quarantine) #define quarantine_alloc_hook JEMALLOC_N(quarantine_alloc_hook) -#define quarantine_boot JEMALLOC_N(quarantine_boot) -#define quarantine_booted JEMALLOC_N(quarantine_booted) +#define quarantine_alloc_hook_work JEMALLOC_N(quarantine_alloc_hook_work) #define quarantine_cleanup JEMALLOC_N(quarantine_cleanup) -#define quarantine_init JEMALLOC_N(quarantine_init) -#define quarantine_tls JEMALLOC_N(quarantine_tls) -#define quarantine_tsd JEMALLOC_N(quarantine_tsd) -#define quarantine_tsd_boot JEMALLOC_N(quarantine_tsd_boot) -#define quarantine_tsd_cleanup_wrapper JEMALLOC_N(quarantine_tsd_cleanup_wrapper) -#define quarantine_tsd_get JEMALLOC_N(quarantine_tsd_get) -#define quarantine_tsd_get_wrapper JEMALLOC_N(quarantine_tsd_get_wrapper) -#define quarantine_tsd_init_head JEMALLOC_N(quarantine_tsd_init_head) -#define quarantine_tsd_set JEMALLOC_N(quarantine_tsd_set) -#define register_zone JEMALLOC_N(register_zone) +#define rtree_child_read JEMALLOC_N(rtree_child_read) +#define rtree_child_read_hard JEMALLOC_N(rtree_child_read_hard) +#define rtree_child_tryread JEMALLOC_N(rtree_child_tryread) #define rtree_delete JEMALLOC_N(rtree_delete) #define rtree_get JEMALLOC_N(rtree_get) -#define rtree_get_locked JEMALLOC_N(rtree_get_locked) #define rtree_new JEMALLOC_N(rtree_new) -#define rtree_postfork_child JEMALLOC_N(rtree_postfork_child) -#define rtree_postfork_parent JEMALLOC_N(rtree_postfork_parent) -#define rtree_prefork JEMALLOC_N(rtree_prefork) +#define rtree_node_valid JEMALLOC_N(rtree_node_valid) #define rtree_set JEMALLOC_N(rtree_set) +#define rtree_start_level JEMALLOC_N(rtree_start_level) +#define rtree_subkey JEMALLOC_N(rtree_subkey) +#define rtree_subtree_read JEMALLOC_N(rtree_subtree_read) +#define rtree_subtree_read_hard JEMALLOC_N(rtree_subtree_read_hard) +#define rtree_subtree_tryread JEMALLOC_N(rtree_subtree_tryread) +#define rtree_val_read JEMALLOC_N(rtree_val_read) +#define rtree_val_write JEMALLOC_N(rtree_val_write) +#define run_quantize_ceil JEMALLOC_N(run_quantize_ceil) +#define run_quantize_floor JEMALLOC_N(run_quantize_floor) #define s2u JEMALLOC_N(s2u) +#define s2u_compute JEMALLOC_N(s2u_compute) +#define s2u_lookup JEMALLOC_N(s2u_lookup) #define sa2u JEMALLOC_N(sa2u) #define set_errno JEMALLOC_N(set_errno) -#define small_size2bin JEMALLOC_N(small_size2bin) +#define size2index JEMALLOC_N(size2index) +#define size2index_compute JEMALLOC_N(size2index_compute) +#define size2index_lookup JEMALLOC_N(size2index_lookup) +#define size2index_tab JEMALLOC_N(size2index_tab) +#define spin_adaptive JEMALLOC_N(spin_adaptive) +#define spin_init JEMALLOC_N(spin_init) #define stats_cactive JEMALLOC_N(stats_cactive) #define stats_cactive_add JEMALLOC_N(stats_cactive_add) #define stats_cactive_get JEMALLOC_N(stats_cactive_get) #define stats_cactive_sub JEMALLOC_N(stats_cactive_sub) -#define stats_chunks JEMALLOC_N(stats_chunks) #define stats_print JEMALLOC_N(stats_print) #define tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy) #define tcache_alloc_large JEMALLOC_N(tcache_alloc_large) #define tcache_alloc_small JEMALLOC_N(tcache_alloc_small) #define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard) -#define tcache_arena_associate JEMALLOC_N(tcache_arena_associate) -#define tcache_arena_dissociate JEMALLOC_N(tcache_arena_dissociate) +#define tcache_arena_reassociate JEMALLOC_N(tcache_arena_reassociate) #define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large) #define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small) #define tcache_bin_info JEMALLOC_N(tcache_bin_info) -#define tcache_boot0 JEMALLOC_N(tcache_boot0) -#define tcache_boot1 JEMALLOC_N(tcache_boot1) -#define tcache_booted JEMALLOC_N(tcache_booted) +#define tcache_boot JEMALLOC_N(tcache_boot) +#define tcache_cleanup JEMALLOC_N(tcache_cleanup) #define tcache_create JEMALLOC_N(tcache_create) #define tcache_dalloc_large JEMALLOC_N(tcache_dalloc_large) #define tcache_dalloc_small JEMALLOC_N(tcache_dalloc_small) -#define tcache_destroy JEMALLOC_N(tcache_destroy) -#define tcache_enabled_booted JEMALLOC_N(tcache_enabled_booted) +#define tcache_enabled_cleanup JEMALLOC_N(tcache_enabled_cleanup) #define tcache_enabled_get JEMALLOC_N(tcache_enabled_get) -#define tcache_enabled_initialized JEMALLOC_N(tcache_enabled_initialized) #define tcache_enabled_set JEMALLOC_N(tcache_enabled_set) -#define tcache_enabled_tls JEMALLOC_N(tcache_enabled_tls) -#define tcache_enabled_tsd JEMALLOC_N(tcache_enabled_tsd) -#define tcache_enabled_tsd_boot JEMALLOC_N(tcache_enabled_tsd_boot) -#define tcache_enabled_tsd_cleanup_wrapper JEMALLOC_N(tcache_enabled_tsd_cleanup_wrapper) -#define tcache_enabled_tsd_get JEMALLOC_N(tcache_enabled_tsd_get) -#define tcache_enabled_tsd_get_wrapper JEMALLOC_N(tcache_enabled_tsd_get_wrapper) -#define tcache_enabled_tsd_init_head JEMALLOC_N(tcache_enabled_tsd_init_head) -#define tcache_enabled_tsd_set JEMALLOC_N(tcache_enabled_tsd_set) #define tcache_event JEMALLOC_N(tcache_event) #define tcache_event_hard JEMALLOC_N(tcache_event_hard) #define tcache_flush JEMALLOC_N(tcache_flush) #define tcache_get JEMALLOC_N(tcache_get) -#define tcache_initialized JEMALLOC_N(tcache_initialized) +#define tcache_get_hard JEMALLOC_N(tcache_get_hard) #define tcache_maxclass JEMALLOC_N(tcache_maxclass) +#define tcache_postfork_child JEMALLOC_N(tcache_postfork_child) +#define tcache_postfork_parent JEMALLOC_N(tcache_postfork_parent) +#define tcache_prefork JEMALLOC_N(tcache_prefork) #define tcache_salloc JEMALLOC_N(tcache_salloc) #define tcache_stats_merge JEMALLOC_N(tcache_stats_merge) -#define tcache_thread_cleanup JEMALLOC_N(tcache_thread_cleanup) -#define tcache_tls JEMALLOC_N(tcache_tls) -#define tcache_tsd JEMALLOC_N(tcache_tsd) -#define tcache_tsd_boot JEMALLOC_N(tcache_tsd_boot) -#define tcache_tsd_cleanup_wrapper JEMALLOC_N(tcache_tsd_cleanup_wrapper) -#define tcache_tsd_get JEMALLOC_N(tcache_tsd_get) -#define tcache_tsd_get_wrapper JEMALLOC_N(tcache_tsd_get_wrapper) -#define tcache_tsd_init_head JEMALLOC_N(tcache_tsd_init_head) -#define tcache_tsd_set JEMALLOC_N(tcache_tsd_set) -#define thread_allocated_booted JEMALLOC_N(thread_allocated_booted) -#define thread_allocated_initialized JEMALLOC_N(thread_allocated_initialized) -#define thread_allocated_tls JEMALLOC_N(thread_allocated_tls) -#define thread_allocated_tsd JEMALLOC_N(thread_allocated_tsd) -#define thread_allocated_tsd_boot JEMALLOC_N(thread_allocated_tsd_boot) -#define thread_allocated_tsd_cleanup_wrapper JEMALLOC_N(thread_allocated_tsd_cleanup_wrapper) -#define thread_allocated_tsd_get JEMALLOC_N(thread_allocated_tsd_get) -#define thread_allocated_tsd_get_wrapper JEMALLOC_N(thread_allocated_tsd_get_wrapper) -#define thread_allocated_tsd_init_head JEMALLOC_N(thread_allocated_tsd_init_head) -#define thread_allocated_tsd_set JEMALLOC_N(thread_allocated_tsd_set) +#define tcaches JEMALLOC_N(tcaches) +#define tcaches_create JEMALLOC_N(tcaches_create) +#define tcaches_destroy JEMALLOC_N(tcaches_destroy) +#define tcaches_flush JEMALLOC_N(tcaches_flush) +#define tcaches_get JEMALLOC_N(tcaches_get) +#define thread_allocated_cleanup JEMALLOC_N(thread_allocated_cleanup) +#define thread_deallocated_cleanup JEMALLOC_N(thread_deallocated_cleanup) +#define ticker_copy JEMALLOC_N(ticker_copy) +#define ticker_init JEMALLOC_N(ticker_init) +#define ticker_read JEMALLOC_N(ticker_read) +#define ticker_tick JEMALLOC_N(ticker_tick) +#define ticker_ticks JEMALLOC_N(ticker_ticks) +#define tsd_arena_get JEMALLOC_N(tsd_arena_get) +#define tsd_arena_set JEMALLOC_N(tsd_arena_set) +#define tsd_arenap_get JEMALLOC_N(tsd_arenap_get) +#define tsd_arenas_tdata_bypass_get JEMALLOC_N(tsd_arenas_tdata_bypass_get) +#define tsd_arenas_tdata_bypass_set JEMALLOC_N(tsd_arenas_tdata_bypass_set) +#define tsd_arenas_tdata_bypassp_get JEMALLOC_N(tsd_arenas_tdata_bypassp_get) +#define tsd_arenas_tdata_get JEMALLOC_N(tsd_arenas_tdata_get) +#define tsd_arenas_tdata_set JEMALLOC_N(tsd_arenas_tdata_set) +#define tsd_arenas_tdatap_get JEMALLOC_N(tsd_arenas_tdatap_get) +#define tsd_boot JEMALLOC_N(tsd_boot) +#define tsd_boot0 JEMALLOC_N(tsd_boot0) +#define tsd_boot1 JEMALLOC_N(tsd_boot1) +#define tsd_booted JEMALLOC_N(tsd_booted) +#define tsd_booted_get JEMALLOC_N(tsd_booted_get) +#define tsd_cleanup JEMALLOC_N(tsd_cleanup) +#define tsd_cleanup_wrapper JEMALLOC_N(tsd_cleanup_wrapper) +#define tsd_fetch JEMALLOC_N(tsd_fetch) +#define tsd_fetch_impl JEMALLOC_N(tsd_fetch_impl) +#define tsd_get JEMALLOC_N(tsd_get) +#define tsd_get_allocates JEMALLOC_N(tsd_get_allocates) +#define tsd_iarena_get JEMALLOC_N(tsd_iarena_get) +#define tsd_iarena_set JEMALLOC_N(tsd_iarena_set) +#define tsd_iarenap_get JEMALLOC_N(tsd_iarenap_get) +#define tsd_initialized JEMALLOC_N(tsd_initialized) #define tsd_init_check_recursion JEMALLOC_N(tsd_init_check_recursion) #define tsd_init_finish JEMALLOC_N(tsd_init_finish) +#define tsd_init_head JEMALLOC_N(tsd_init_head) +#define tsd_narenas_tdata_get JEMALLOC_N(tsd_narenas_tdata_get) +#define tsd_narenas_tdata_set JEMALLOC_N(tsd_narenas_tdata_set) +#define tsd_narenas_tdatap_get JEMALLOC_N(tsd_narenas_tdatap_get) +#define tsd_wrapper_get JEMALLOC_N(tsd_wrapper_get) +#define tsd_wrapper_set JEMALLOC_N(tsd_wrapper_set) +#define tsd_nominal JEMALLOC_N(tsd_nominal) +#define tsd_prof_tdata_get JEMALLOC_N(tsd_prof_tdata_get) +#define tsd_prof_tdata_set JEMALLOC_N(tsd_prof_tdata_set) +#define tsd_prof_tdatap_get JEMALLOC_N(tsd_prof_tdatap_get) +#define tsd_quarantine_get JEMALLOC_N(tsd_quarantine_get) +#define tsd_quarantine_set JEMALLOC_N(tsd_quarantine_set) +#define tsd_quarantinep_get JEMALLOC_N(tsd_quarantinep_get) +#define tsd_set JEMALLOC_N(tsd_set) +#define tsd_tcache_enabled_get JEMALLOC_N(tsd_tcache_enabled_get) +#define tsd_tcache_enabled_set JEMALLOC_N(tsd_tcache_enabled_set) +#define tsd_tcache_enabledp_get JEMALLOC_N(tsd_tcache_enabledp_get) +#define tsd_tcache_get JEMALLOC_N(tsd_tcache_get) +#define tsd_tcache_set JEMALLOC_N(tsd_tcache_set) +#define tsd_tcachep_get JEMALLOC_N(tsd_tcachep_get) +#define tsd_thread_allocated_get JEMALLOC_N(tsd_thread_allocated_get) +#define tsd_thread_allocated_set JEMALLOC_N(tsd_thread_allocated_set) +#define tsd_thread_allocatedp_get JEMALLOC_N(tsd_thread_allocatedp_get) +#define tsd_thread_deallocated_get JEMALLOC_N(tsd_thread_deallocated_get) +#define tsd_thread_deallocated_set JEMALLOC_N(tsd_thread_deallocated_set) +#define tsd_thread_deallocatedp_get JEMALLOC_N(tsd_thread_deallocatedp_get) +#define tsd_tls JEMALLOC_N(tsd_tls) +#define tsd_tsd JEMALLOC_N(tsd_tsd) +#define tsd_tsdn JEMALLOC_N(tsd_tsdn) +#define tsd_witness_fork_get JEMALLOC_N(tsd_witness_fork_get) +#define tsd_witness_fork_set JEMALLOC_N(tsd_witness_fork_set) +#define tsd_witness_forkp_get JEMALLOC_N(tsd_witness_forkp_get) +#define tsd_witnesses_get JEMALLOC_N(tsd_witnesses_get) +#define tsd_witnesses_set JEMALLOC_N(tsd_witnesses_set) +#define tsd_witnessesp_get JEMALLOC_N(tsd_witnessesp_get) +#define tsdn_fetch JEMALLOC_N(tsdn_fetch) +#define tsdn_null JEMALLOC_N(tsdn_null) +#define tsdn_tsd JEMALLOC_N(tsdn_tsd) #define u2rz JEMALLOC_N(u2rz) +#define valgrind_freelike_block JEMALLOC_N(valgrind_freelike_block) +#define valgrind_make_mem_defined JEMALLOC_N(valgrind_make_mem_defined) +#define valgrind_make_mem_noaccess JEMALLOC_N(valgrind_make_mem_noaccess) +#define valgrind_make_mem_undefined JEMALLOC_N(valgrind_make_mem_undefined) +#define witness_assert_depth JEMALLOC_N(witness_assert_depth) +#define witness_assert_depth_to_rank JEMALLOC_N(witness_assert_depth_to_rank) +#define witness_assert_lockless JEMALLOC_N(witness_assert_lockless) +#define witness_assert_not_owner JEMALLOC_N(witness_assert_not_owner) +#define witness_assert_owner JEMALLOC_N(witness_assert_owner) +#define witness_depth_error JEMALLOC_N(witness_depth_error) +#define witness_fork_cleanup JEMALLOC_N(witness_fork_cleanup) +#define witness_init JEMALLOC_N(witness_init) +#define witness_lock JEMALLOC_N(witness_lock) +#define witness_lock_error JEMALLOC_N(witness_lock_error) +#define witness_not_owner_error JEMALLOC_N(witness_not_owner_error) +#define witness_owner JEMALLOC_N(witness_owner) +#define witness_owner_error JEMALLOC_N(witness_owner_error) +#define witness_postfork_child JEMALLOC_N(witness_postfork_child) +#define witness_postfork_parent JEMALLOC_N(witness_postfork_parent) +#define witness_prefork JEMALLOC_N(witness_prefork) +#define witness_unlock JEMALLOC_N(witness_unlock) +#define witnesses_cleanup JEMALLOC_N(witnesses_cleanup) +#define zone_register JEMALLOC_N(zone_register) diff --git a/deps/jemalloc/include/jemalloc/internal/prng.h b/deps/jemalloc/include/jemalloc/internal/prng.h index 7b2b06512f..15cc2d18fa 100644 --- a/deps/jemalloc/include/jemalloc/internal/prng.h +++ b/deps/jemalloc/include/jemalloc/internal/prng.h @@ -1,5 +1,8 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES +#ifndef JEMALLOC_INTERNAL_PRNG_H +#define JEMALLOC_INTERNAL_PRNG_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/bit_util.h" /* * Simple linear congruential pseudo-random number generator: @@ -15,46 +18,168 @@ * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints. * * This choice of m has the disadvantage that the quality of the bits is - * proportional to bit position. For example. the lowest bit has a cycle of 2, + * proportional to bit position. For example, the lowest bit has a cycle of 2, * the next has a cycle of 4, etc. For this reason, we prefer to use the upper * bits. - * - * Macro parameters: - * uint32_t r : Result. - * unsigned lg_range : (0..32], number of least significant bits to return. - * uint32_t state : Seed value. - * const uint32_t a, c : See above discussion. */ -#define prng32(r, lg_range, state, a, c) do { \ - assert(lg_range > 0); \ - assert(lg_range <= 32); \ - \ - r = (state * (a)) + (c); \ - state = r; \ - r >>= (32 - lg_range); \ -} while (false) - -/* Same as prng32(), but 64 bits of pseudo-randomness, using uint64_t. */ -#define prng64(r, lg_range, state, a, c) do { \ - assert(lg_range > 0); \ - assert(lg_range <= 64); \ - \ - r = (state * (a)) + (c); \ - state = r; \ - r >>= (64 - lg_range); \ -} while (false) - -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS -#endif /* JEMALLOC_H_STRUCTS */ /******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -#endif /* JEMALLOC_H_EXTERNS */ +/* INTERNAL DEFINITIONS -- IGNORE */ /******************************************************************************/ -#ifdef JEMALLOC_H_INLINES +#define PRNG_A_32 UINT32_C(1103515241) +#define PRNG_C_32 UINT32_C(12347) + +#define PRNG_A_64 UINT64_C(6364136223846793005) +#define PRNG_C_64 UINT64_C(1442695040888963407) + +JEMALLOC_ALWAYS_INLINE uint32_t +prng_state_next_u32(uint32_t state) { + return (state * PRNG_A_32) + PRNG_C_32; +} + +JEMALLOC_ALWAYS_INLINE uint64_t +prng_state_next_u64(uint64_t state) { + return (state * PRNG_A_64) + PRNG_C_64; +} + +JEMALLOC_ALWAYS_INLINE size_t +prng_state_next_zu(size_t state) { +#if LG_SIZEOF_PTR == 2 + return (state * PRNG_A_32) + PRNG_C_32; +#elif LG_SIZEOF_PTR == 3 + return (state * PRNG_A_64) + PRNG_C_64; +#else +#error Unsupported pointer size +#endif +} -#endif /* JEMALLOC_H_INLINES */ /******************************************************************************/ +/* BEGIN PUBLIC API */ +/******************************************************************************/ + +/* + * The prng_lg_range functions give a uniform int in the half-open range [0, + * 2**lg_range). If atomic is true, they do so safely from multiple threads. + * Multithreaded 64-bit prngs aren't supported. + */ + +JEMALLOC_ALWAYS_INLINE uint32_t +prng_lg_range_u32(atomic_u32_t *state, unsigned lg_range, bool atomic) { + uint32_t ret, state0, state1; + + assert(lg_range > 0); + assert(lg_range <= 32); + + state0 = atomic_load_u32(state, ATOMIC_RELAXED); + + if (atomic) { + do { + state1 = prng_state_next_u32(state0); + } while (!atomic_compare_exchange_weak_u32(state, &state0, + state1, ATOMIC_RELAXED, ATOMIC_RELAXED)); + } else { + state1 = prng_state_next_u32(state0); + atomic_store_u32(state, state1, ATOMIC_RELAXED); + } + ret = state1 >> (32 - lg_range); + + return ret; +} + +JEMALLOC_ALWAYS_INLINE uint64_t +prng_lg_range_u64(uint64_t *state, unsigned lg_range) { + uint64_t ret, state1; + + assert(lg_range > 0); + assert(lg_range <= 64); + + state1 = prng_state_next_u64(*state); + *state = state1; + ret = state1 >> (64 - lg_range); + + return ret; +} + +JEMALLOC_ALWAYS_INLINE size_t +prng_lg_range_zu(atomic_zu_t *state, unsigned lg_range, bool atomic) { + size_t ret, state0, state1; + + assert(lg_range > 0); + assert(lg_range <= ZU(1) << (3 + LG_SIZEOF_PTR)); + + state0 = atomic_load_zu(state, ATOMIC_RELAXED); + + if (atomic) { + do { + state1 = prng_state_next_zu(state0); + } while (atomic_compare_exchange_weak_zu(state, &state0, + state1, ATOMIC_RELAXED, ATOMIC_RELAXED)); + } else { + state1 = prng_state_next_zu(state0); + atomic_store_zu(state, state1, ATOMIC_RELAXED); + } + ret = state1 >> ((ZU(1) << (3 + LG_SIZEOF_PTR)) - lg_range); + + return ret; +} + +/* + * The prng_range functions behave like the prng_lg_range, but return a result + * in [0, range) instead of [0, 2**lg_range). + */ + +JEMALLOC_ALWAYS_INLINE uint32_t +prng_range_u32(atomic_u32_t *state, uint32_t range, bool atomic) { + uint32_t ret; + unsigned lg_range; + + assert(range > 1); + + /* Compute the ceiling of lg(range). */ + lg_range = ffs_u32(pow2_ceil_u32(range)) - 1; + + /* Generate a result in [0..range) via repeated trial. */ + do { + ret = prng_lg_range_u32(state, lg_range, atomic); + } while (ret >= range); + + return ret; +} + +JEMALLOC_ALWAYS_INLINE uint64_t +prng_range_u64(uint64_t *state, uint64_t range) { + uint64_t ret; + unsigned lg_range; + + assert(range > 1); + + /* Compute the ceiling of lg(range). */ + lg_range = ffs_u64(pow2_ceil_u64(range)) - 1; + + /* Generate a result in [0..range) via repeated trial. */ + do { + ret = prng_lg_range_u64(state, lg_range); + } while (ret >= range); + + return ret; +} + +JEMALLOC_ALWAYS_INLINE size_t +prng_range_zu(atomic_zu_t *state, size_t range, bool atomic) { + size_t ret; + unsigned lg_range; + + assert(range > 1); + + /* Compute the ceiling of lg(range). */ + lg_range = ffs_u64(pow2_ceil_u64(range)) - 1; + + /* Generate a result in [0..range) via repeated trial. */ + do { + ret = prng_lg_range_zu(state, lg_range, atomic); + } while (ret >= range); + + return ret; +} + +#endif /* JEMALLOC_INTERNAL_PRNG_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/ql.h b/deps/jemalloc/include/jemalloc/internal/ql.h index f70c5f6f39..8029040771 100644 --- a/deps/jemalloc/include/jemalloc/internal/ql.h +++ b/deps/jemalloc/include/jemalloc/internal/ql.h @@ -1,61 +1,64 @@ -/* - * List definitions. - */ -#define ql_head(a_type) \ +#ifndef JEMALLOC_INTERNAL_QL_H +#define JEMALLOC_INTERNAL_QL_H + +#include "jemalloc/internal/qr.h" + +/* List definitions. */ +#define ql_head(a_type) \ struct { \ a_type *qlh_first; \ } -#define ql_head_initializer(a_head) {NULL} +#define ql_head_initializer(a_head) {NULL} -#define ql_elm(a_type) qr(a_type) +#define ql_elm(a_type) qr(a_type) /* List functions. */ -#define ql_new(a_head) do { \ +#define ql_new(a_head) do { \ (a_head)->qlh_first = NULL; \ } while (0) -#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field) +#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field) -#define ql_first(a_head) ((a_head)->qlh_first) +#define ql_first(a_head) ((a_head)->qlh_first) -#define ql_last(a_head, a_field) \ +#define ql_last(a_head, a_field) \ ((ql_first(a_head) != NULL) \ ? qr_prev(ql_first(a_head), a_field) : NULL) -#define ql_next(a_head, a_elm, a_field) \ +#define ql_next(a_head, a_elm, a_field) \ ((ql_last(a_head, a_field) != (a_elm)) \ ? qr_next((a_elm), a_field) : NULL) -#define ql_prev(a_head, a_elm, a_field) \ +#define ql_prev(a_head, a_elm, a_field) \ ((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \ : NULL) -#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \ +#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \ qr_before_insert((a_qlelm), (a_elm), a_field); \ if (ql_first(a_head) == (a_qlelm)) { \ ql_first(a_head) = (a_elm); \ } \ } while (0) -#define ql_after_insert(a_qlelm, a_elm, a_field) \ +#define ql_after_insert(a_qlelm, a_elm, a_field) \ qr_after_insert((a_qlelm), (a_elm), a_field) -#define ql_head_insert(a_head, a_elm, a_field) do { \ +#define ql_head_insert(a_head, a_elm, a_field) do { \ if (ql_first(a_head) != NULL) { \ qr_before_insert(ql_first(a_head), (a_elm), a_field); \ } \ ql_first(a_head) = (a_elm); \ } while (0) -#define ql_tail_insert(a_head, a_elm, a_field) do { \ +#define ql_tail_insert(a_head, a_elm, a_field) do { \ if (ql_first(a_head) != NULL) { \ qr_before_insert(ql_first(a_head), (a_elm), a_field); \ } \ ql_first(a_head) = qr_next((a_elm), a_field); \ } while (0) -#define ql_remove(a_head, a_elm, a_field) do { \ +#define ql_remove(a_head, a_elm, a_field) do { \ if (ql_first(a_head) == (a_elm)) { \ ql_first(a_head) = qr_next(ql_first(a_head), a_field); \ } \ @@ -66,18 +69,20 @@ struct { \ } \ } while (0) -#define ql_head_remove(a_head, a_type, a_field) do { \ +#define ql_head_remove(a_head, a_type, a_field) do { \ a_type *t = ql_first(a_head); \ ql_remove((a_head), t, a_field); \ } while (0) -#define ql_tail_remove(a_head, a_type, a_field) do { \ +#define ql_tail_remove(a_head, a_type, a_field) do { \ a_type *t = ql_last(a_head, a_field); \ ql_remove((a_head), t, a_field); \ } while (0) -#define ql_foreach(a_var, a_head, a_field) \ +#define ql_foreach(a_var, a_head, a_field) \ qr_foreach((a_var), ql_first(a_head), a_field) -#define ql_reverse_foreach(a_var, a_head, a_field) \ +#define ql_reverse_foreach(a_var, a_head, a_field) \ qr_reverse_foreach((a_var), ql_first(a_head), a_field) + +#endif /* JEMALLOC_INTERNAL_QL_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/qr.h b/deps/jemalloc/include/jemalloc/internal/qr.h index 602944b9b4..1e1056b386 100644 --- a/deps/jemalloc/include/jemalloc/internal/qr.h +++ b/deps/jemalloc/include/jemalloc/internal/qr.h @@ -1,38 +1,39 @@ +#ifndef JEMALLOC_INTERNAL_QR_H +#define JEMALLOC_INTERNAL_QR_H + /* Ring definitions. */ -#define qr(a_type) \ +#define qr(a_type) \ struct { \ a_type *qre_next; \ a_type *qre_prev; \ } /* Ring functions. */ -#define qr_new(a_qr, a_field) do { \ +#define qr_new(a_qr, a_field) do { \ (a_qr)->a_field.qre_next = (a_qr); \ (a_qr)->a_field.qre_prev = (a_qr); \ } while (0) -#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next) +#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next) -#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev) +#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev) -#define qr_before_insert(a_qrelm, a_qr, a_field) do { \ +#define qr_before_insert(a_qrelm, a_qr, a_field) do { \ (a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev; \ (a_qr)->a_field.qre_next = (a_qrelm); \ (a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr); \ (a_qrelm)->a_field.qre_prev = (a_qr); \ } while (0) -#define qr_after_insert(a_qrelm, a_qr, a_field) \ - do \ - { \ +#define qr_after_insert(a_qrelm, a_qr, a_field) do { \ (a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next; \ (a_qr)->a_field.qre_prev = (a_qrelm); \ (a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr); \ (a_qrelm)->a_field.qre_next = (a_qr); \ - } while (0) +} while (0) -#define qr_meld(a_qr_a, a_qr_b, a_field) do { \ - void *t; \ +#define qr_meld(a_qr_a, a_qr_b, a_type, a_field) do { \ + a_type *t; \ (a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b); \ (a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a); \ t = (a_qr_a)->a_field.qre_prev; \ @@ -40,12 +41,14 @@ struct { \ (a_qr_b)->a_field.qre_prev = t; \ } while (0) -/* qr_meld() and qr_split() are functionally equivalent, so there's no need to - * have two copies of the code. */ -#define qr_split(a_qr_a, a_qr_b, a_field) \ - qr_meld((a_qr_a), (a_qr_b), a_field) +/* + * qr_meld() and qr_split() are functionally equivalent, so there's no need to + * have two copies of the code. + */ +#define qr_split(a_qr_a, a_qr_b, a_type, a_field) \ + qr_meld((a_qr_a), (a_qr_b), a_type, a_field) -#define qr_remove(a_qr, a_field) do { \ +#define qr_remove(a_qr, a_field) do { \ (a_qr)->a_field.qre_prev->a_field.qre_next \ = (a_qr)->a_field.qre_next; \ (a_qr)->a_field.qre_next->a_field.qre_prev \ @@ -54,14 +57,16 @@ struct { \ (a_qr)->a_field.qre_prev = (a_qr); \ } while (0) -#define qr_foreach(var, a_qr, a_field) \ +#define qr_foreach(var, a_qr, a_field) \ for ((var) = (a_qr); \ (var) != NULL; \ (var) = (((var)->a_field.qre_next != (a_qr)) \ ? (var)->a_field.qre_next : NULL)) -#define qr_reverse_foreach(var, a_qr, a_field) \ +#define qr_reverse_foreach(var, a_qr, a_field) \ for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \ (var) != NULL; \ (var) = (((var) != (a_qr)) \ ? (var)->a_field.qre_prev : NULL)) + +#endif /* JEMALLOC_INTERNAL_QR_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/rb.h b/deps/jemalloc/include/jemalloc/internal/rb.h index 423802eb2d..47fa5ca99b 100644 --- a/deps/jemalloc/include/jemalloc/internal/rb.h +++ b/deps/jemalloc/include/jemalloc/internal/rb.h @@ -20,17 +20,21 @@ */ #ifndef RB_H_ -#define RB_H_ +#define RB_H_ + +#ifndef __PGI +#define RB_COMPACT +#endif #ifdef RB_COMPACT /* Node structure. */ -#define rb_node(a_type) \ +#define rb_node(a_type) \ struct { \ a_type *rbn_left; \ a_type *rbn_right_red; \ } #else -#define rb_node(a_type) \ +#define rb_node(a_type) \ struct { \ a_type *rbn_left; \ a_type *rbn_right; \ @@ -39,111 +43,116 @@ struct { \ #endif /* Root structure. */ -#define rb_tree(a_type) \ +#define rb_tree(a_type) \ struct { \ a_type *rbt_root; \ - a_type rbt_nil; \ } /* Left accessors. */ -#define rbtn_left_get(a_type, a_field, a_node) \ +#define rbtn_left_get(a_type, a_field, a_node) \ ((a_node)->a_field.rbn_left) -#define rbtn_left_set(a_type, a_field, a_node, a_left) do { \ +#define rbtn_left_set(a_type, a_field, a_node, a_left) do { \ (a_node)->a_field.rbn_left = a_left; \ } while (0) #ifdef RB_COMPACT /* Right accessors. */ -#define rbtn_right_get(a_type, a_field, a_node) \ +#define rbtn_right_get(a_type, a_field, a_node) \ ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \ & ((ssize_t)-2))) -#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \ +#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \ (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \ | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \ } while (0) /* Color accessors. */ -#define rbtn_red_get(a_type, a_field, a_node) \ +#define rbtn_red_get(a_type, a_field, a_node) \ ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \ & ((size_t)1))) -#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \ +#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \ (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \ (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \ | ((ssize_t)a_red)); \ } while (0) -#define rbtn_red_set(a_type, a_field, a_node) do { \ +#define rbtn_red_set(a_type, a_field, a_node) do { \ (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \ (a_node)->a_field.rbn_right_red) | ((size_t)1)); \ } while (0) -#define rbtn_black_set(a_type, a_field, a_node) do { \ +#define rbtn_black_set(a_type, a_field, a_node) do { \ (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \ (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \ } while (0) + +/* Node initializer. */ +#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \ + /* Bookkeeping bit cannot be used by node pointer. */ \ + assert(((uintptr_t)(a_node) & 0x1) == 0); \ + rbtn_left_set(a_type, a_field, (a_node), NULL); \ + rbtn_right_set(a_type, a_field, (a_node), NULL); \ + rbtn_red_set(a_type, a_field, (a_node)); \ +} while (0) #else /* Right accessors. */ -#define rbtn_right_get(a_type, a_field, a_node) \ +#define rbtn_right_get(a_type, a_field, a_node) \ ((a_node)->a_field.rbn_right) -#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \ +#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \ (a_node)->a_field.rbn_right = a_right; \ } while (0) /* Color accessors. */ -#define rbtn_red_get(a_type, a_field, a_node) \ +#define rbtn_red_get(a_type, a_field, a_node) \ ((a_node)->a_field.rbn_red) -#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \ +#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \ (a_node)->a_field.rbn_red = (a_red); \ } while (0) -#define rbtn_red_set(a_type, a_field, a_node) do { \ +#define rbtn_red_set(a_type, a_field, a_node) do { \ (a_node)->a_field.rbn_red = true; \ } while (0) -#define rbtn_black_set(a_type, a_field, a_node) do { \ +#define rbtn_black_set(a_type, a_field, a_node) do { \ (a_node)->a_field.rbn_red = false; \ } while (0) -#endif /* Node initializer. */ -#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \ - rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \ - rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \ +#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \ + rbtn_left_set(a_type, a_field, (a_node), NULL); \ + rbtn_right_set(a_type, a_field, (a_node), NULL); \ rbtn_red_set(a_type, a_field, (a_node)); \ } while (0) +#endif /* Tree initializer. */ -#define rb_new(a_type, a_field, a_rbt) do { \ - (a_rbt)->rbt_root = &(a_rbt)->rbt_nil; \ - rbt_node_new(a_type, a_field, a_rbt, &(a_rbt)->rbt_nil); \ - rbtn_black_set(a_type, a_field, &(a_rbt)->rbt_nil); \ +#define rb_new(a_type, a_field, a_rbt) do { \ + (a_rbt)->rbt_root = NULL; \ } while (0) /* Internal utility macros. */ -#define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \ +#define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \ (r_node) = (a_root); \ - if ((r_node) != &(a_rbt)->rbt_nil) { \ + if ((r_node) != NULL) { \ for (; \ - rbtn_left_get(a_type, a_field, (r_node)) != &(a_rbt)->rbt_nil;\ + rbtn_left_get(a_type, a_field, (r_node)) != NULL; \ (r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \ } \ } \ } while (0) -#define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \ +#define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \ (r_node) = (a_root); \ - if ((r_node) != &(a_rbt)->rbt_nil) { \ - for (; rbtn_right_get(a_type, a_field, (r_node)) != \ - &(a_rbt)->rbt_nil; (r_node) = rbtn_right_get(a_type, a_field, \ - (r_node))) { \ + if ((r_node) != NULL) { \ + for (; rbtn_right_get(a_type, a_field, (r_node)) != NULL; \ + (r_node) = rbtn_right_get(a_type, a_field, (r_node))) { \ } \ } \ } while (0) -#define rbtn_rotate_left(a_type, a_field, a_node, r_node) do { \ +#define rbtn_rotate_left(a_type, a_field, a_node, r_node) do { \ (r_node) = rbtn_right_get(a_type, a_field, (a_node)); \ rbtn_right_set(a_type, a_field, (a_node), \ rbtn_left_get(a_type, a_field, (r_node))); \ rbtn_left_set(a_type, a_field, (r_node), (a_node)); \ } while (0) -#define rbtn_rotate_right(a_type, a_field, a_node, r_node) do { \ +#define rbtn_rotate_right(a_type, a_field, a_node, r_node) do { \ (r_node) = rbtn_left_get(a_type, a_field, (a_node)); \ rbtn_left_set(a_type, a_field, (a_node), \ rbtn_right_get(a_type, a_field, (r_node))); \ @@ -155,9 +164,11 @@ struct { \ * functions generated by an equivalently parameterized call to rb_gen(). */ -#define rb_proto(a_attr, a_prefix, a_rbt_type, a_type) \ +#define rb_proto(a_attr, a_prefix, a_rbt_type, a_type) \ a_attr void \ a_prefix##new(a_rbt_type *rbtree); \ +a_attr bool \ +a_prefix##empty(a_rbt_type *rbtree); \ a_attr a_type * \ a_prefix##first(a_rbt_type *rbtree); \ a_attr a_type * \ @@ -167,11 +178,11 @@ a_prefix##next(a_rbt_type *rbtree, a_type *node); \ a_attr a_type * \ a_prefix##prev(a_rbt_type *rbtree, a_type *node); \ a_attr a_type * \ -a_prefix##search(a_rbt_type *rbtree, a_type *key); \ +a_prefix##search(a_rbt_type *rbtree, const a_type *key); \ a_attr a_type * \ -a_prefix##nsearch(a_rbt_type *rbtree, a_type *key); \ +a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key); \ a_attr a_type * \ -a_prefix##psearch(a_rbt_type *rbtree, a_type *key); \ +a_prefix##psearch(a_rbt_type *rbtree, const a_type *key); \ a_attr void \ a_prefix##insert(a_rbt_type *rbtree, a_type *node); \ a_attr void \ @@ -181,7 +192,10 @@ a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \ a_rbt_type *, a_type *, void *), void *arg); \ a_attr a_type * \ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ - a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg); + a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg); \ +a_attr void \ +a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \ + void *arg); /* * The rb_gen() macro generates a type-specific red-black tree implementation, @@ -198,7 +212,7 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ * int (a_cmp *)(a_type *a_node, a_type *a_other); * ^^^^^^ * or a_key - * Interpretation of comparision function return values: + * Interpretation of comparison function return values: * -1 : a_node < a_other * 0 : a_node == a_other * 1 : a_node > a_other @@ -224,6 +238,13 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ * Args: * tree: Pointer to an uninitialized red-black tree object. * + * static bool + * ex_empty(ex_t *tree); + * Description: Determine whether tree is empty. + * Args: + * tree: Pointer to an initialized red-black tree object. + * Ret: True if tree is empty, false otherwise. + * * static ex_node_t * * ex_first(ex_t *tree); * static ex_node_t * @@ -245,7 +266,7 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ * last/first. * * static ex_node_t * - * ex_search(ex_t *tree, ex_node_t *key); + * ex_search(ex_t *tree, const ex_node_t *key); * Description: Search for node that matches key. * Args: * tree: Pointer to an initialized red-black tree object. @@ -253,9 +274,9 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ * Ret: Node in tree that matches key, or NULL if no match. * * static ex_node_t * - * ex_nsearch(ex_t *tree, ex_node_t *key); + * ex_nsearch(ex_t *tree, const ex_node_t *key); * static ex_node_t * - * ex_psearch(ex_t *tree, ex_node_t *key); + * ex_psearch(ex_t *tree, const ex_node_t *key); * Description: Search for node that matches key. If no match is found, * return what would be key's successor/predecessor, were * key in tree. @@ -303,40 +324,52 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ * arg : Opaque pointer passed to cb(). * Ret: NULL if iteration completed, or the non-NULL callback return value * that caused termination of the iteration. + * + * static void + * ex_destroy(ex_t *tree, void (*cb)(ex_node_t *, void *), void *arg); + * Description: Iterate over the tree with post-order traversal, remove + * each node, and run the callback if non-null. This is + * used for destroying a tree without paying the cost to + * rebalance it. The tree must not be otherwise altered + * during traversal. + * Args: + * tree: Pointer to an initialized red-black tree object. + * cb : Callback function, which, if non-null, is called for each node + * during iteration. There is no way to stop iteration once it + * has begun. + * arg : Opaque pointer passed to cb(). */ -#define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \ +#define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \ a_attr void \ a_prefix##new(a_rbt_type *rbtree) { \ rb_new(a_type, a_field, rbtree); \ } \ +a_attr bool \ +a_prefix##empty(a_rbt_type *rbtree) { \ + return (rbtree->rbt_root == NULL); \ +} \ a_attr a_type * \ a_prefix##first(a_rbt_type *rbtree) { \ a_type *ret; \ rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ a_prefix##last(a_rbt_type *rbtree) { \ a_type *ret; \ rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ a_prefix##next(a_rbt_type *rbtree, a_type *node) { \ a_type *ret; \ - if (rbtn_right_get(a_type, a_field, node) != &rbtree->rbt_nil) { \ + if (rbtn_right_get(a_type, a_field, node) != NULL) { \ rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \ a_field, node), ret); \ } else { \ a_type *tnode = rbtree->rbt_root; \ - assert(tnode != &rbtree->rbt_nil); \ - ret = &rbtree->rbt_nil; \ + assert(tnode != NULL); \ + ret = NULL; \ while (true) { \ int cmp = (a_cmp)(node, tnode); \ if (cmp < 0) { \ @@ -347,24 +380,21 @@ a_prefix##next(a_rbt_type *rbtree, a_type *node) { \ } else { \ break; \ } \ - assert(tnode != &rbtree->rbt_nil); \ + assert(tnode != NULL); \ } \ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \ a_type *ret; \ - if (rbtn_left_get(a_type, a_field, node) != &rbtree->rbt_nil) { \ + if (rbtn_left_get(a_type, a_field, node) != NULL) { \ rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \ a_field, node), ret); \ } else { \ a_type *tnode = rbtree->rbt_root; \ - assert(tnode != &rbtree->rbt_nil); \ - ret = &rbtree->rbt_nil; \ + assert(tnode != NULL); \ + ret = NULL; \ while (true) { \ int cmp = (a_cmp)(node, tnode); \ if (cmp < 0) { \ @@ -375,20 +405,17 @@ a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \ } else { \ break; \ } \ - assert(tnode != &rbtree->rbt_nil); \ + assert(tnode != NULL); \ } \ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ -a_prefix##search(a_rbt_type *rbtree, a_type *key) { \ +a_prefix##search(a_rbt_type *rbtree, const a_type *key) { \ a_type *ret; \ int cmp; \ ret = rbtree->rbt_root; \ - while (ret != &rbtree->rbt_nil \ + while (ret != NULL \ && (cmp = (a_cmp)(key, ret)) != 0) { \ if (cmp < 0) { \ ret = rbtn_left_get(a_type, a_field, ret); \ @@ -396,17 +423,14 @@ a_prefix##search(a_rbt_type *rbtree, a_type *key) { \ ret = rbtn_right_get(a_type, a_field, ret); \ } \ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ -a_prefix##nsearch(a_rbt_type *rbtree, a_type *key) { \ +a_prefix##nsearch(a_rbt_type *rbtree, const a_type *key) { \ a_type *ret; \ a_type *tnode = rbtree->rbt_root; \ - ret = &rbtree->rbt_nil; \ - while (tnode != &rbtree->rbt_nil) { \ + ret = NULL; \ + while (tnode != NULL) { \ int cmp = (a_cmp)(key, tnode); \ if (cmp < 0) { \ ret = tnode; \ @@ -418,17 +442,14 @@ a_prefix##nsearch(a_rbt_type *rbtree, a_type *key) { \ break; \ } \ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ -a_prefix##psearch(a_rbt_type *rbtree, a_type *key) { \ +a_prefix##psearch(a_rbt_type *rbtree, const a_type *key) { \ a_type *ret; \ a_type *tnode = rbtree->rbt_root; \ - ret = &rbtree->rbt_nil; \ - while (tnode != &rbtree->rbt_nil) { \ + ret = NULL; \ + while (tnode != NULL) { \ int cmp = (a_cmp)(key, tnode); \ if (cmp < 0) { \ tnode = rbtn_left_get(a_type, a_field, tnode); \ @@ -440,10 +461,7 @@ a_prefix##psearch(a_rbt_type *rbtree, a_type *key) { \ break; \ } \ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ + return ret; \ } \ a_attr void \ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \ @@ -454,7 +472,7 @@ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \ rbt_node_new(a_type, a_field, rbtree, node); \ /* Wind. */ \ path->node = rbtree->rbt_root; \ - for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \ + for (pathp = path; pathp->node != NULL; pathp++) { \ int cmp = pathp->cmp = a_cmp(node, pathp->node); \ assert(cmp != 0); \ if (cmp < 0) { \ @@ -474,7 +492,8 @@ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \ rbtn_left_set(a_type, a_field, cnode, left); \ if (rbtn_red_get(a_type, a_field, left)) { \ a_type *leftleft = rbtn_left_get(a_type, a_field, left);\ - if (rbtn_red_get(a_type, a_field, leftleft)) { \ + if (leftleft != NULL && rbtn_red_get(a_type, a_field, \ + leftleft)) { \ /* Fix up 4-node. */ \ a_type *tnode; \ rbtn_black_set(a_type, a_field, leftleft); \ @@ -489,7 +508,8 @@ a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \ rbtn_right_set(a_type, a_field, cnode, right); \ if (rbtn_red_get(a_type, a_field, right)) { \ a_type *left = rbtn_left_get(a_type, a_field, cnode); \ - if (rbtn_red_get(a_type, a_field, left)) { \ + if (left != NULL && rbtn_red_get(a_type, a_field, \ + left)) { \ /* Split 4-node. */ \ rbtn_black_set(a_type, a_field, left); \ rbtn_black_set(a_type, a_field, right); \ @@ -522,7 +542,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ /* Wind. */ \ nodep = NULL; /* Silence compiler warning. */ \ path->node = rbtree->rbt_root; \ - for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \ + for (pathp = path; pathp->node != NULL; pathp++) { \ int cmp = pathp->cmp = a_cmp(node, pathp->node); \ if (cmp < 0) { \ pathp[1].node = rbtn_left_get(a_type, a_field, \ @@ -534,8 +554,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ /* Find node's successor, in preparation for swap. */ \ pathp->cmp = 1; \ nodep = pathp; \ - for (pathp++; pathp->node != &rbtree->rbt_nil; \ - pathp++) { \ + for (pathp++; pathp->node != NULL; pathp++) { \ pathp->cmp = -1; \ pathp[1].node = rbtn_left_get(a_type, a_field, \ pathp->node); \ @@ -577,10 +596,10 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ } \ } else { \ a_type *left = rbtn_left_get(a_type, a_field, node); \ - if (left != &rbtree->rbt_nil) { \ + if (left != NULL) { \ /* node has no successor, but it has a left child. */\ /* Splice node out, without losing the left child. */\ - assert(rbtn_red_get(a_type, a_field, node) == false); \ + assert(!rbtn_red_get(a_type, a_field, node)); \ assert(rbtn_red_get(a_type, a_field, left)); \ rbtn_black_set(a_type, a_field, left); \ if (pathp == path) { \ @@ -597,34 +616,32 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ return; \ } else if (pathp == path) { \ /* The tree only contained one node. */ \ - rbtree->rbt_root = &rbtree->rbt_nil; \ + rbtree->rbt_root = NULL; \ return; \ } \ } \ if (rbtn_red_get(a_type, a_field, pathp->node)) { \ /* Prune red node, which requires no fixup. */ \ assert(pathp[-1].cmp < 0); \ - rbtn_left_set(a_type, a_field, pathp[-1].node, \ - &rbtree->rbt_nil); \ + rbtn_left_set(a_type, a_field, pathp[-1].node, NULL); \ return; \ } \ /* The node to be pruned is black, so unwind until balance is */\ /* restored. */\ - pathp->node = &rbtree->rbt_nil; \ + pathp->node = NULL; \ for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \ assert(pathp->cmp != 0); \ if (pathp->cmp < 0) { \ rbtn_left_set(a_type, a_field, pathp->node, \ pathp[1].node); \ - assert(rbtn_red_get(a_type, a_field, pathp[1].node) \ - == false); \ if (rbtn_red_get(a_type, a_field, pathp->node)) { \ a_type *right = rbtn_right_get(a_type, a_field, \ pathp->node); \ a_type *rightleft = rbtn_left_get(a_type, a_field, \ right); \ a_type *tnode; \ - if (rbtn_red_get(a_type, a_field, rightleft)) { \ + if (rightleft != NULL && rbtn_red_get(a_type, a_field, \ + rightleft)) { \ /* In the following diagrams, ||, //, and \\ */\ /* indicate the path to the removed node. */\ /* */\ @@ -667,7 +684,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ pathp->node); \ a_type *rightleft = rbtn_left_get(a_type, a_field, \ right); \ - if (rbtn_red_get(a_type, a_field, rightleft)) { \ + if (rightleft != NULL && rbtn_red_get(a_type, a_field, \ + rightleft)) { \ /* || */\ /* pathp(b) */\ /* // \ */\ @@ -681,7 +699,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ rbtn_rotate_left(a_type, a_field, pathp->node, \ tnode); \ /* Balance restored, but rotation modified */\ - /* subree root, which may actually be the tree */\ + /* subtree root, which may actually be the tree */\ /* root. */\ if (pathp == path) { \ /* Set root. */ \ @@ -721,7 +739,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ left); \ a_type *leftrightleft = rbtn_left_get(a_type, a_field, \ leftright); \ - if (rbtn_red_get(a_type, a_field, leftrightleft)) { \ + if (leftrightleft != NULL && rbtn_red_get(a_type, \ + a_field, leftrightleft)) { \ /* || */\ /* pathp(b) */\ /* / \\ */\ @@ -747,7 +766,7 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ /* (b) */\ /* / */\ /* (b) */\ - assert(leftright != &rbtree->rbt_nil); \ + assert(leftright != NULL); \ rbtn_red_set(a_type, a_field, leftright); \ rbtn_rotate_right(a_type, a_field, pathp->node, \ tnode); \ @@ -770,7 +789,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ return; \ } else if (rbtn_red_get(a_type, a_field, pathp->node)) { \ a_type *leftleft = rbtn_left_get(a_type, a_field, left);\ - if (rbtn_red_get(a_type, a_field, leftleft)) { \ + if (leftleft != NULL && rbtn_red_get(a_type, a_field, \ + leftleft)) { \ /* || */\ /* pathp(r) */\ /* / \\ */\ @@ -808,7 +828,8 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ } \ } else { \ a_type *leftleft = rbtn_left_get(a_type, a_field, left);\ - if (rbtn_red_get(a_type, a_field, leftleft)) { \ + if (leftleft != NULL && rbtn_red_get(a_type, a_field, \ + leftleft)) { \ /* || */\ /* pathp(b) */\ /* / \\ */\ @@ -849,22 +870,22 @@ a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ } \ /* Set root. */ \ rbtree->rbt_root = path->node; \ - assert(rbtn_red_get(a_type, a_field, rbtree->rbt_root) == false); \ + assert(!rbtn_red_get(a_type, a_field, rbtree->rbt_root)); \ } \ a_attr a_type * \ a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \ a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \ - if (node == &rbtree->rbt_nil) { \ - return (&rbtree->rbt_nil); \ + if (node == NULL) { \ + return NULL; \ } else { \ a_type *ret; \ if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \ - a_field, node), cb, arg)) != &rbtree->rbt_nil \ - || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ + a_field, node), cb, arg)) != NULL || (ret = cb(rbtree, node, \ + arg)) != NULL) { \ + return ret; \ } \ - return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ - a_field, node), cb, arg)); \ + return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ + a_field, node), cb, arg); \ } \ } \ a_attr a_type * \ @@ -874,22 +895,22 @@ a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node, \ if (cmp < 0) { \ a_type *ret; \ if ((ret = a_prefix##iter_start(rbtree, start, \ - rbtn_left_get(a_type, a_field, node), cb, arg)) != \ - &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ + rbtn_left_get(a_type, a_field, node), cb, arg)) != NULL || \ + (ret = cb(rbtree, node, arg)) != NULL) { \ + return ret; \ } \ - return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ - a_field, node), cb, arg)); \ + return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ + a_field, node), cb, arg); \ } else if (cmp > 0) { \ - return (a_prefix##iter_start(rbtree, start, \ - rbtn_right_get(a_type, a_field, node), cb, arg)); \ + return a_prefix##iter_start(rbtree, start, \ + rbtn_right_get(a_type, a_field, node), cb, arg); \ } else { \ a_type *ret; \ if ((ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ + return ret; \ } \ - return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ - a_field, node), cb, arg)); \ + return a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ + a_field, node), cb, arg); \ } \ } \ a_attr a_type * \ @@ -902,25 +923,22 @@ a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \ } else { \ ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ + return ret; \ } \ a_attr a_type * \ a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \ a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \ - if (node == &rbtree->rbt_nil) { \ - return (&rbtree->rbt_nil); \ + if (node == NULL) { \ + return NULL; \ } else { \ a_type *ret; \ if ((ret = a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_right_get(a_type, a_field, node), cb, arg)) != \ - &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ + rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \ + (ret = cb(rbtree, node, arg)) != NULL) { \ + return ret; \ } \ - return (a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ + return a_prefix##reverse_iter_recurse(rbtree, \ + rbtn_left_get(a_type, a_field, node), cb, arg); \ } \ } \ a_attr a_type * \ @@ -931,22 +949,22 @@ a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start, \ if (cmp > 0) { \ a_type *ret; \ if ((ret = a_prefix##reverse_iter_start(rbtree, start, \ - rbtn_right_get(a_type, a_field, node), cb, arg)) != \ - &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ + rbtn_right_get(a_type, a_field, node), cb, arg)) != NULL || \ + (ret = cb(rbtree, node, arg)) != NULL) { \ + return ret; \ } \ - return (a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ + return a_prefix##reverse_iter_recurse(rbtree, \ + rbtn_left_get(a_type, a_field, node), cb, arg); \ } else if (cmp < 0) { \ - return (a_prefix##reverse_iter_start(rbtree, start, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ + return a_prefix##reverse_iter_start(rbtree, start, \ + rbtn_left_get(a_type, a_field, node), cb, arg); \ } else { \ a_type *ret; \ if ((ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ + return ret; \ } \ - return (a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ + return a_prefix##reverse_iter_recurse(rbtree, \ + rbtn_left_get(a_type, a_field, node), cb, arg); \ } \ } \ a_attr a_type * \ @@ -960,10 +978,29 @@ a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \ cb, arg); \ } \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ + return ret; \ +} \ +a_attr void \ +a_prefix##destroy_recurse(a_rbt_type *rbtree, a_type *node, void (*cb)( \ + a_type *, void *), void *arg) { \ + if (node == NULL) { \ + return; \ } \ - return (ret); \ + a_prefix##destroy_recurse(rbtree, rbtn_left_get(a_type, a_field, \ + node), cb, arg); \ + rbtn_left_set(a_type, a_field, (node), NULL); \ + a_prefix##destroy_recurse(rbtree, rbtn_right_get(a_type, a_field, \ + node), cb, arg); \ + rbtn_right_set(a_type, a_field, (node), NULL); \ + if (cb) { \ + cb(node, arg); \ + } \ +} \ +a_attr void \ +a_prefix##destroy(a_rbt_type *rbtree, void (*cb)(a_type *, void *), \ + void *arg) { \ + a_prefix##destroy_recurse(rbtree, rbtree->rbt_root, cb, arg); \ + rbtree->rbt_root = NULL; \ } #endif /* RB_H_ */ diff --git a/deps/jemalloc/include/jemalloc/internal/rtree.h b/deps/jemalloc/include/jemalloc/internal/rtree.h index bc74769f50..b5d4db3988 100644 --- a/deps/jemalloc/include/jemalloc/internal/rtree.h +++ b/deps/jemalloc/include/jemalloc/internal/rtree.h @@ -1,172 +1,474 @@ +#ifndef JEMALLOC_INTERNAL_RTREE_H +#define JEMALLOC_INTERNAL_RTREE_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/rtree_tsd.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/tsd.h" + /* * This radix tree implementation is tailored to the singular purpose of - * tracking which chunks are currently owned by jemalloc. This functionality - * is mandatory for OS X, where jemalloc must be able to respond to object - * ownership queries. + * associating metadata with extents that are currently owned by jemalloc. * ******************************************************************************* */ -#ifdef JEMALLOC_H_TYPES + +/* Number of high insignificant bits. */ +#define RTREE_NHIB ((1U << (LG_SIZEOF_PTR+3)) - LG_VADDR) +/* Number of low insigificant bits. */ +#define RTREE_NLIB LG_PAGE +/* Number of significant bits. */ +#define RTREE_NSB (LG_VADDR - RTREE_NLIB) +/* Number of levels in radix tree. */ +#if RTREE_NSB <= 10 +# define RTREE_HEIGHT 1 +#elif RTREE_NSB <= 36 +# define RTREE_HEIGHT 2 +#elif RTREE_NSB <= 52 +# define RTREE_HEIGHT 3 +#else +# error Unsupported number of significant virtual address bits +#endif +/* Use compact leaf representation if virtual address encoding allows. */ +#if RTREE_NHIB >= LG_CEIL_NSIZES +# define RTREE_LEAF_COMPACT +#endif + +/* Needed for initialization only. */ +#define RTREE_LEAFKEY_INVALID ((uintptr_t)1) + +typedef struct rtree_node_elm_s rtree_node_elm_t; +struct rtree_node_elm_s { + atomic_p_t child; /* (rtree_{node,leaf}_elm_t *) */ +}; + +struct rtree_leaf_elm_s { +#ifdef RTREE_LEAF_COMPACT + /* + * Single pointer-width field containing all three leaf element fields. + * For example, on a 64-bit x64 system with 48 significant virtual + * memory address bits, the index, extent, and slab fields are packed as + * such: + * + * x: index + * e: extent + * b: slab + * + * 00000000 xxxxxxxx eeeeeeee [...] eeeeeeee eeee000b + */ + atomic_p_t le_bits; +#else + atomic_p_t le_extent; /* (extent_t *) */ + atomic_u_t le_szind; /* (szind_t) */ + atomic_b_t le_slab; /* (bool) */ +#endif +}; + +typedef struct rtree_level_s rtree_level_t; +struct rtree_level_s { + /* Number of key bits distinguished by this level. */ + unsigned bits; + /* + * Cumulative number of key bits distinguished by traversing to + * corresponding tree level. + */ + unsigned cumbits; +}; typedef struct rtree_s rtree_t; +struct rtree_s { + malloc_mutex_t init_lock; + /* Number of elements based on rtree_levels[0].bits. */ +#if RTREE_HEIGHT > 1 + rtree_node_elm_t root[1U << (RTREE_NSB/RTREE_HEIGHT)]; +#else + rtree_leaf_elm_t root[1U << (RTREE_NSB/RTREE_HEIGHT)]; +#endif +}; /* - * Size of each radix tree node (must be a power of 2). This impacts tree - * depth. + * Split the bits into one to three partitions depending on number of + * significant bits. It the number of bits does not divide evenly into the + * number of levels, place one remainder bit per level starting at the leaf + * level. */ -#define RTREE_NODESIZE (1U << 16) +static const rtree_level_t rtree_levels[] = { +#if RTREE_HEIGHT == 1 + {RTREE_NSB, RTREE_NHIB + RTREE_NSB} +#elif RTREE_HEIGHT == 2 + {RTREE_NSB/2, RTREE_NHIB + RTREE_NSB/2}, + {RTREE_NSB/2 + RTREE_NSB%2, RTREE_NHIB + RTREE_NSB} +#elif RTREE_HEIGHT == 3 + {RTREE_NSB/3, RTREE_NHIB + RTREE_NSB/3}, + {RTREE_NSB/3 + RTREE_NSB%3/2, + RTREE_NHIB + RTREE_NSB/3*2 + RTREE_NSB%3/2}, + {RTREE_NSB/3 + RTREE_NSB%3 - RTREE_NSB%3/2, RTREE_NHIB + RTREE_NSB} +#else +# error Unsupported rtree height +#endif +}; -typedef void *(rtree_alloc_t)(size_t); -typedef void (rtree_dalloc_t)(void *); +bool rtree_new(rtree_t *rtree, bool zeroed); -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS +typedef rtree_node_elm_t *(rtree_node_alloc_t)(tsdn_t *, rtree_t *, size_t); +extern rtree_node_alloc_t *JET_MUTABLE rtree_node_alloc; -struct rtree_s { - rtree_alloc_t *alloc; - rtree_dalloc_t *dalloc; - malloc_mutex_t mutex; - void **root; - unsigned height; - unsigned level2bits[1]; /* Dynamically sized. */ -}; +typedef rtree_leaf_elm_t *(rtree_leaf_alloc_t)(tsdn_t *, rtree_t *, size_t); +extern rtree_leaf_alloc_t *JET_MUTABLE rtree_leaf_alloc; + +typedef void (rtree_node_dalloc_t)(tsdn_t *, rtree_t *, rtree_node_elm_t *); +extern rtree_node_dalloc_t *JET_MUTABLE rtree_node_dalloc; + +typedef void (rtree_leaf_dalloc_t)(tsdn_t *, rtree_t *, rtree_leaf_elm_t *); +extern rtree_leaf_dalloc_t *JET_MUTABLE rtree_leaf_dalloc; +#ifdef JEMALLOC_JET +void rtree_delete(tsdn_t *tsdn, rtree_t *rtree); +#endif +rtree_leaf_elm_t *rtree_leaf_elm_lookup_hard(tsdn_t *tsdn, rtree_t *rtree, + rtree_ctx_t *rtree_ctx, uintptr_t key, bool dependent, bool init_missing); + +JEMALLOC_ALWAYS_INLINE uintptr_t +rtree_leafkey(uintptr_t key) { + unsigned ptrbits = ZU(1) << (LG_SIZEOF_PTR+3); + unsigned cumbits = (rtree_levels[RTREE_HEIGHT-1].cumbits - + rtree_levels[RTREE_HEIGHT-1].bits); + unsigned maskbits = ptrbits - cumbits; + uintptr_t mask = ~((ZU(1) << maskbits) - 1); + return (key & mask); +} + +JEMALLOC_ALWAYS_INLINE size_t +rtree_cache_direct_map(uintptr_t key) { + unsigned ptrbits = ZU(1) << (LG_SIZEOF_PTR+3); + unsigned cumbits = (rtree_levels[RTREE_HEIGHT-1].cumbits - + rtree_levels[RTREE_HEIGHT-1].bits); + unsigned maskbits = ptrbits - cumbits; + return (size_t)((key >> maskbits) & (RTREE_CTX_NCACHE - 1)); +} + +JEMALLOC_ALWAYS_INLINE uintptr_t +rtree_subkey(uintptr_t key, unsigned level) { + unsigned ptrbits = ZU(1) << (LG_SIZEOF_PTR+3); + unsigned cumbits = rtree_levels[level].cumbits; + unsigned shiftbits = ptrbits - cumbits; + unsigned maskbits = rtree_levels[level].bits; + uintptr_t mask = (ZU(1) << maskbits) - 1; + return ((key >> shiftbits) & mask); +} + +/* + * Atomic getters. + * + * dependent: Reading a value on behalf of a pointer to a valid allocation + * is guaranteed to be a clean read even without synchronization, + * because the rtree update became visible in memory before the + * pointer came into existence. + * !dependent: An arbitrary read, e.g. on behalf of ivsalloc(), may not be + * dependent on a previous rtree write, which means a stale read + * could result if synchronization were omitted here. + */ +# ifdef RTREE_LEAF_COMPACT +JEMALLOC_ALWAYS_INLINE uintptr_t +rtree_leaf_elm_bits_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + bool dependent) { + return (uintptr_t)atomic_load_p(&elm->le_bits, dependent + ? ATOMIC_RELAXED : ATOMIC_ACQUIRE); +} + +JEMALLOC_ALWAYS_INLINE extent_t * +rtree_leaf_elm_bits_extent_get(uintptr_t bits) { + /* Restore sign-extended high bits, mask slab bit. */ + return (extent_t *)((uintptr_t)((intptr_t)(bits << RTREE_NHIB) >> + RTREE_NHIB) & ~((uintptr_t)0x1)); +} -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS +JEMALLOC_ALWAYS_INLINE szind_t +rtree_leaf_elm_bits_szind_get(uintptr_t bits) { + return (szind_t)(bits >> LG_VADDR); +} -rtree_t *rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc); -void rtree_delete(rtree_t *rtree); -void rtree_prefork(rtree_t *rtree); -void rtree_postfork_parent(rtree_t *rtree); -void rtree_postfork_child(rtree_t *rtree); +JEMALLOC_ALWAYS_INLINE bool +rtree_leaf_elm_bits_slab_get(uintptr_t bits) { + return (bool)(bits & (uintptr_t)0x1); +} -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES +# endif -#ifndef JEMALLOC_ENABLE_INLINE -#ifdef JEMALLOC_DEBUG -uint8_t rtree_get_locked(rtree_t *rtree, uintptr_t key); +JEMALLOC_ALWAYS_INLINE extent_t * +rtree_leaf_elm_extent_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + bool dependent) { +#ifdef RTREE_LEAF_COMPACT + uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); + return rtree_leaf_elm_bits_extent_get(bits); +#else + extent_t *extent = (extent_t *)atomic_load_p(&elm->le_extent, dependent + ? ATOMIC_RELAXED : ATOMIC_ACQUIRE); + return extent; #endif -uint8_t rtree_get(rtree_t *rtree, uintptr_t key); -bool rtree_set(rtree_t *rtree, uintptr_t key, uint8_t val); +} + +JEMALLOC_ALWAYS_INLINE szind_t +rtree_leaf_elm_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + bool dependent) { +#ifdef RTREE_LEAF_COMPACT + uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); + return rtree_leaf_elm_bits_szind_get(bits); +#else + return (szind_t)atomic_load_u(&elm->le_szind, dependent ? ATOMIC_RELAXED + : ATOMIC_ACQUIRE); #endif +} -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_RTREE_C_)) -#define RTREE_GET_GENERATE(f) \ -/* The least significant bits of the key are ignored. */ \ -JEMALLOC_INLINE uint8_t \ -f(rtree_t *rtree, uintptr_t key) \ -{ \ - uint8_t ret; \ - uintptr_t subkey; \ - unsigned i, lshift, height, bits; \ - void **node, **child; \ - \ - RTREE_LOCK(&rtree->mutex); \ - for (i = lshift = 0, height = rtree->height, node = rtree->root;\ - i < height - 1; \ - i++, lshift += bits, node = child) { \ - bits = rtree->level2bits[i]; \ - subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR + \ - 3)) - bits); \ - child = (void**)node[subkey]; \ - if (child == NULL) { \ - RTREE_UNLOCK(&rtree->mutex); \ - return (0); \ - } \ - } \ - \ - /* \ - * node is a leaf, so it contains values rather than node \ - * pointers. \ - */ \ - bits = rtree->level2bits[i]; \ - subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - \ - bits); \ - { \ - uint8_t *leaf = (uint8_t *)node; \ - ret = leaf[subkey]; \ - } \ - RTREE_UNLOCK(&rtree->mutex); \ - \ - RTREE_GET_VALIDATE \ - return (ret); \ -} - -#ifdef JEMALLOC_DEBUG -# define RTREE_LOCK(l) malloc_mutex_lock(l) -# define RTREE_UNLOCK(l) malloc_mutex_unlock(l) -# define RTREE_GET_VALIDATE -RTREE_GET_GENERATE(rtree_get_locked) -# undef RTREE_LOCK -# undef RTREE_UNLOCK -# undef RTREE_GET_VALIDATE +JEMALLOC_ALWAYS_INLINE bool +rtree_leaf_elm_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + bool dependent) { +#ifdef RTREE_LEAF_COMPACT + uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent); + return rtree_leaf_elm_bits_slab_get(bits); +#else + return atomic_load_b(&elm->le_slab, dependent ? ATOMIC_RELAXED : + ATOMIC_ACQUIRE); #endif +} -#define RTREE_LOCK(l) -#define RTREE_UNLOCK(l) -#ifdef JEMALLOC_DEBUG - /* - * Suppose that it were possible for a jemalloc-allocated chunk to be - * munmap()ped, followed by a different allocator in another thread re-using - * overlapping virtual memory, all without invalidating the cached rtree - * value. The result would be a false positive (the rtree would claim that - * jemalloc owns memory that it had actually discarded). This scenario - * seems impossible, but the following assertion is a prudent sanity check. - */ -# define RTREE_GET_VALIDATE \ - assert(rtree_get_locked(rtree, key) == ret); +static inline void +rtree_leaf_elm_extent_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + extent_t *extent) { +#ifdef RTREE_LEAF_COMPACT + uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, true); + uintptr_t bits = ((uintptr_t)rtree_leaf_elm_bits_szind_get(old_bits) << + LG_VADDR) | ((uintptr_t)extent & (((uintptr_t)0x1 << LG_VADDR) - 1)) + | ((uintptr_t)rtree_leaf_elm_bits_slab_get(old_bits)); + atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE); #else -# define RTREE_GET_VALIDATE + atomic_store_p(&elm->le_extent, extent, ATOMIC_RELEASE); #endif -RTREE_GET_GENERATE(rtree_get) -#undef RTREE_LOCK -#undef RTREE_UNLOCK -#undef RTREE_GET_VALIDATE - -JEMALLOC_INLINE bool -rtree_set(rtree_t *rtree, uintptr_t key, uint8_t val) -{ - uintptr_t subkey; - unsigned i, lshift, height, bits; - void **node, **child; - - malloc_mutex_lock(&rtree->mutex); - for (i = lshift = 0, height = rtree->height, node = rtree->root; - i < height - 1; - i++, lshift += bits, node = child) { - bits = rtree->level2bits[i]; - subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - - bits); - child = (void**)node[subkey]; - if (child == NULL) { - size_t size = ((i + 1 < height - 1) ? sizeof(void *) - : (sizeof(uint8_t))) << rtree->level2bits[i+1]; - child = (void**)rtree->alloc(size); - if (child == NULL) { - malloc_mutex_unlock(&rtree->mutex); - return (true); - } - memset(child, 0, size); - node[subkey] = child; - } +} + +static inline void +rtree_leaf_elm_szind_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + szind_t szind) { + assert(szind <= NSIZES); + +#ifdef RTREE_LEAF_COMPACT + uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, + true); + uintptr_t bits = ((uintptr_t)szind << LG_VADDR) | + ((uintptr_t)rtree_leaf_elm_bits_extent_get(old_bits) & + (((uintptr_t)0x1 << LG_VADDR) - 1)) | + ((uintptr_t)rtree_leaf_elm_bits_slab_get(old_bits)); + atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE); +#else + atomic_store_u(&elm->le_szind, szind, ATOMIC_RELEASE); +#endif +} + +static inline void +rtree_leaf_elm_slab_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + bool slab) { +#ifdef RTREE_LEAF_COMPACT + uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, + true); + uintptr_t bits = ((uintptr_t)rtree_leaf_elm_bits_szind_get(old_bits) << + LG_VADDR) | ((uintptr_t)rtree_leaf_elm_bits_extent_get(old_bits) & + (((uintptr_t)0x1 << LG_VADDR) - 1)) | ((uintptr_t)slab); + atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE); +#else + atomic_store_b(&elm->le_slab, slab, ATOMIC_RELEASE); +#endif +} + +static inline void +rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm, + extent_t *extent, szind_t szind, bool slab) { +#ifdef RTREE_LEAF_COMPACT + uintptr_t bits = ((uintptr_t)szind << LG_VADDR) | + ((uintptr_t)extent & (((uintptr_t)0x1 << LG_VADDR) - 1)) | + ((uintptr_t)slab); + atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE); +#else + rtree_leaf_elm_slab_write(tsdn, rtree, elm, slab); + rtree_leaf_elm_szind_write(tsdn, rtree, elm, szind); + /* + * Write extent last, since the element is atomically considered valid + * as soon as the extent field is non-NULL. + */ + rtree_leaf_elm_extent_write(tsdn, rtree, elm, extent); +#endif +} + +static inline void +rtree_leaf_elm_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree, + rtree_leaf_elm_t *elm, szind_t szind, bool slab) { + assert(!slab || szind < NBINS); + + /* + * The caller implicitly assures that it is the only writer to the szind + * and slab fields, and that the extent field cannot currently change. + */ + rtree_leaf_elm_slab_write(tsdn, rtree, elm, slab); + rtree_leaf_elm_szind_write(tsdn, rtree, elm, szind); +} + +JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t * +rtree_leaf_elm_lookup(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, bool dependent, bool init_missing) { + assert(key != 0); + assert(!dependent || !init_missing); + + size_t slot = rtree_cache_direct_map(key); + uintptr_t leafkey = rtree_leafkey(key); + assert(leafkey != RTREE_LEAFKEY_INVALID); + + /* Fast path: L1 direct mapped cache. */ + if (likely(rtree_ctx->cache[slot].leafkey == leafkey)) { + rtree_leaf_elm_t *leaf = rtree_ctx->cache[slot].leaf; + assert(leaf != NULL); + uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1); + return &leaf[subkey]; } + /* + * Search the L2 LRU cache. On hit, swap the matching element into the + * slot in L1 cache, and move the position in L2 up by 1. + */ +#define RTREE_CACHE_CHECK_L2(i) do { \ + if (likely(rtree_ctx->l2_cache[i].leafkey == leafkey)) { \ + rtree_leaf_elm_t *leaf = rtree_ctx->l2_cache[i].leaf; \ + assert(leaf != NULL); \ + if (i > 0) { \ + /* Bubble up by one. */ \ + rtree_ctx->l2_cache[i].leafkey = \ + rtree_ctx->l2_cache[i - 1].leafkey; \ + rtree_ctx->l2_cache[i].leaf = \ + rtree_ctx->l2_cache[i - 1].leaf; \ + rtree_ctx->l2_cache[i - 1].leafkey = \ + rtree_ctx->cache[slot].leafkey; \ + rtree_ctx->l2_cache[i - 1].leaf = \ + rtree_ctx->cache[slot].leaf; \ + } else { \ + rtree_ctx->l2_cache[0].leafkey = \ + rtree_ctx->cache[slot].leafkey; \ + rtree_ctx->l2_cache[0].leaf = \ + rtree_ctx->cache[slot].leaf; \ + } \ + rtree_ctx->cache[slot].leafkey = leafkey; \ + rtree_ctx->cache[slot].leaf = leaf; \ + uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1); \ + return &leaf[subkey]; \ + } \ +} while (0) + /* Check the first cache entry. */ + RTREE_CACHE_CHECK_L2(0); + /* Search the remaining cache elements. */ + for (unsigned i = 1; i < RTREE_CTX_NCACHE_L2; i++) { + RTREE_CACHE_CHECK_L2(i); + } +#undef RTREE_CACHE_CHECK_L2 + + return rtree_leaf_elm_lookup_hard(tsdn, rtree, rtree_ctx, key, + dependent, init_missing); +} + +static inline bool +rtree_write(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key, + extent_t *extent, szind_t szind, bool slab) { + /* Use rtree_clear() to set the extent to NULL. */ + assert(extent != NULL); - /* node is a leaf, so it contains values rather than node pointers. */ - bits = rtree->level2bits[i]; - subkey = (key << lshift) >> ((ZU(1) << (LG_SIZEOF_PTR+3)) - bits); - { - uint8_t *leaf = (uint8_t *)node; - leaf[subkey] = val; + rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx, + key, false, true); + if (elm == NULL) { + return true; } - malloc_mutex_unlock(&rtree->mutex); - return (false); + assert(rtree_leaf_elm_extent_read(tsdn, rtree, elm, false) == NULL); + rtree_leaf_elm_write(tsdn, rtree, elm, extent, szind, slab); + + return false; +} + +JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t * +rtree_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key, + bool dependent) { + rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx, + key, dependent, false); + if (!dependent && elm == NULL) { + return NULL; + } + assert(elm != NULL); + return elm; +} + +JEMALLOC_ALWAYS_INLINE extent_t * +rtree_extent_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, bool dependent) { + rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, + dependent); + if (!dependent && elm == NULL) { + return NULL; + } + return rtree_leaf_elm_extent_read(tsdn, rtree, elm, dependent); +} + +JEMALLOC_ALWAYS_INLINE szind_t +rtree_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, bool dependent) { + rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, + dependent); + if (!dependent && elm == NULL) { + return NSIZES; + } + return rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent); +} + +/* + * rtree_slab_read() is intentionally omitted because slab is always read in + * conjunction with szind, which makes rtree_szind_slab_read() a better choice. + */ + +JEMALLOC_ALWAYS_INLINE bool +rtree_extent_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, bool dependent, extent_t **r_extent, szind_t *r_szind) { + rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, + dependent); + if (!dependent && elm == NULL) { + return true; + } + *r_extent = rtree_leaf_elm_extent_read(tsdn, rtree, elm, dependent); + *r_szind = rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent); + return false; +} + +JEMALLOC_ALWAYS_INLINE bool +rtree_szind_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, bool dependent, szind_t *r_szind, bool *r_slab) { + rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, + dependent); + if (!dependent && elm == NULL) { + return true; + } + *r_szind = rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent); + *r_slab = rtree_leaf_elm_slab_read(tsdn, rtree, elm, dependent); + return false; +} + +static inline void +rtree_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, szind_t szind, bool slab) { + assert(!slab || szind < NBINS); + + rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true); + rtree_leaf_elm_szind_slab_update(tsdn, rtree, elm, szind, slab); +} + +static inline void +rtree_clear(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key) { + rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true); + assert(rtree_leaf_elm_extent_read(tsdn, rtree, elm, false) != + NULL); + rtree_leaf_elm_write(tsdn, rtree, elm, NULL, NSIZES, false); } -#endif -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_RTREE_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/size_classes.h b/deps/jemalloc/include/jemalloc/internal/size_classes.h index 821102e5c1..0b7d3cd369 100644 --- a/deps/jemalloc/include/jemalloc/internal/size_classes.h +++ b/deps/jemalloc/include/jemalloc/internal/size_classes.h @@ -1,690 +1,1416 @@ -/* This file was automatically generated by size_classes.sh. */ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 12) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 8, 24) \ - SIZE_CLASS(3, 8, 32) \ - SIZE_CLASS(4, 8, 40) \ - SIZE_CLASS(5, 8, 48) \ - SIZE_CLASS(6, 8, 56) \ - SIZE_CLASS(7, 8, 64) \ - SIZE_CLASS(8, 16, 80) \ - SIZE_CLASS(9, 16, 96) \ - SIZE_CLASS(10, 16, 112) \ - SIZE_CLASS(11, 16, 128) \ - SIZE_CLASS(12, 32, 160) \ - SIZE_CLASS(13, 32, 192) \ - SIZE_CLASS(14, 32, 224) \ - SIZE_CLASS(15, 32, 256) \ - SIZE_CLASS(16, 64, 320) \ - SIZE_CLASS(17, 64, 384) \ - SIZE_CLASS(18, 64, 448) \ - SIZE_CLASS(19, 64, 512) \ - SIZE_CLASS(20, 128, 640) \ - SIZE_CLASS(21, 128, 768) \ - SIZE_CLASS(22, 128, 896) \ - SIZE_CLASS(23, 128, 1024) \ - SIZE_CLASS(24, 256, 1280) \ - SIZE_CLASS(25, 256, 1536) \ - SIZE_CLASS(26, 256, 1792) \ - SIZE_CLASS(27, 256, 2048) \ - SIZE_CLASS(28, 512, 2560) \ - SIZE_CLASS(29, 512, 3072) \ - SIZE_CLASS(30, 512, 3584) \ - -#define NBINS 31 -#define SMALL_MAXCLASS 3584 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 13) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 8, 24) \ - SIZE_CLASS(3, 8, 32) \ - SIZE_CLASS(4, 8, 40) \ - SIZE_CLASS(5, 8, 48) \ - SIZE_CLASS(6, 8, 56) \ - SIZE_CLASS(7, 8, 64) \ - SIZE_CLASS(8, 16, 80) \ - SIZE_CLASS(9, 16, 96) \ - SIZE_CLASS(10, 16, 112) \ - SIZE_CLASS(11, 16, 128) \ - SIZE_CLASS(12, 32, 160) \ - SIZE_CLASS(13, 32, 192) \ - SIZE_CLASS(14, 32, 224) \ - SIZE_CLASS(15, 32, 256) \ - SIZE_CLASS(16, 64, 320) \ - SIZE_CLASS(17, 64, 384) \ - SIZE_CLASS(18, 64, 448) \ - SIZE_CLASS(19, 64, 512) \ - SIZE_CLASS(20, 128, 640) \ - SIZE_CLASS(21, 128, 768) \ - SIZE_CLASS(22, 128, 896) \ - SIZE_CLASS(23, 128, 1024) \ - SIZE_CLASS(24, 256, 1280) \ - SIZE_CLASS(25, 256, 1536) \ - SIZE_CLASS(26, 256, 1792) \ - SIZE_CLASS(27, 256, 2048) \ - SIZE_CLASS(28, 512, 2560) \ - SIZE_CLASS(29, 512, 3072) \ - SIZE_CLASS(30, 512, 3584) \ - SIZE_CLASS(31, 512, 4096) \ - SIZE_CLASS(32, 1024, 5120) \ - SIZE_CLASS(33, 1024, 6144) \ - SIZE_CLASS(34, 1024, 7168) \ - -#define NBINS 35 -#define SMALL_MAXCLASS 7168 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 14) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 8, 24) \ - SIZE_CLASS(3, 8, 32) \ - SIZE_CLASS(4, 8, 40) \ - SIZE_CLASS(5, 8, 48) \ - SIZE_CLASS(6, 8, 56) \ - SIZE_CLASS(7, 8, 64) \ - SIZE_CLASS(8, 16, 80) \ - SIZE_CLASS(9, 16, 96) \ - SIZE_CLASS(10, 16, 112) \ - SIZE_CLASS(11, 16, 128) \ - SIZE_CLASS(12, 32, 160) \ - SIZE_CLASS(13, 32, 192) \ - SIZE_CLASS(14, 32, 224) \ - SIZE_CLASS(15, 32, 256) \ - SIZE_CLASS(16, 64, 320) \ - SIZE_CLASS(17, 64, 384) \ - SIZE_CLASS(18, 64, 448) \ - SIZE_CLASS(19, 64, 512) \ - SIZE_CLASS(20, 128, 640) \ - SIZE_CLASS(21, 128, 768) \ - SIZE_CLASS(22, 128, 896) \ - SIZE_CLASS(23, 128, 1024) \ - SIZE_CLASS(24, 256, 1280) \ - SIZE_CLASS(25, 256, 1536) \ - SIZE_CLASS(26, 256, 1792) \ - SIZE_CLASS(27, 256, 2048) \ - SIZE_CLASS(28, 512, 2560) \ - SIZE_CLASS(29, 512, 3072) \ - SIZE_CLASS(30, 512, 3584) \ - SIZE_CLASS(31, 512, 4096) \ - SIZE_CLASS(32, 1024, 5120) \ - SIZE_CLASS(33, 1024, 6144) \ - SIZE_CLASS(34, 1024, 7168) \ - SIZE_CLASS(35, 1024, 8192) \ - SIZE_CLASS(36, 2048, 10240) \ - SIZE_CLASS(37, 2048, 12288) \ - SIZE_CLASS(38, 2048, 14336) \ - -#define NBINS 39 -#define SMALL_MAXCLASS 14336 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 15) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 8, 24) \ - SIZE_CLASS(3, 8, 32) \ - SIZE_CLASS(4, 8, 40) \ - SIZE_CLASS(5, 8, 48) \ - SIZE_CLASS(6, 8, 56) \ - SIZE_CLASS(7, 8, 64) \ - SIZE_CLASS(8, 16, 80) \ - SIZE_CLASS(9, 16, 96) \ - SIZE_CLASS(10, 16, 112) \ - SIZE_CLASS(11, 16, 128) \ - SIZE_CLASS(12, 32, 160) \ - SIZE_CLASS(13, 32, 192) \ - SIZE_CLASS(14, 32, 224) \ - SIZE_CLASS(15, 32, 256) \ - SIZE_CLASS(16, 64, 320) \ - SIZE_CLASS(17, 64, 384) \ - SIZE_CLASS(18, 64, 448) \ - SIZE_CLASS(19, 64, 512) \ - SIZE_CLASS(20, 128, 640) \ - SIZE_CLASS(21, 128, 768) \ - SIZE_CLASS(22, 128, 896) \ - SIZE_CLASS(23, 128, 1024) \ - SIZE_CLASS(24, 256, 1280) \ - SIZE_CLASS(25, 256, 1536) \ - SIZE_CLASS(26, 256, 1792) \ - SIZE_CLASS(27, 256, 2048) \ - SIZE_CLASS(28, 512, 2560) \ - SIZE_CLASS(29, 512, 3072) \ - SIZE_CLASS(30, 512, 3584) \ - SIZE_CLASS(31, 512, 4096) \ - SIZE_CLASS(32, 1024, 5120) \ - SIZE_CLASS(33, 1024, 6144) \ - SIZE_CLASS(34, 1024, 7168) \ - SIZE_CLASS(35, 1024, 8192) \ - SIZE_CLASS(36, 2048, 10240) \ - SIZE_CLASS(37, 2048, 12288) \ - SIZE_CLASS(38, 2048, 14336) \ - SIZE_CLASS(39, 2048, 16384) \ - SIZE_CLASS(40, 4096, 20480) \ - SIZE_CLASS(41, 4096, 24576) \ - SIZE_CLASS(42, 4096, 28672) \ - -#define NBINS 43 -#define SMALL_MAXCLASS 28672 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 16) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 8, 24) \ - SIZE_CLASS(3, 8, 32) \ - SIZE_CLASS(4, 8, 40) \ - SIZE_CLASS(5, 8, 48) \ - SIZE_CLASS(6, 8, 56) \ - SIZE_CLASS(7, 8, 64) \ - SIZE_CLASS(8, 16, 80) \ - SIZE_CLASS(9, 16, 96) \ - SIZE_CLASS(10, 16, 112) \ - SIZE_CLASS(11, 16, 128) \ - SIZE_CLASS(12, 32, 160) \ - SIZE_CLASS(13, 32, 192) \ - SIZE_CLASS(14, 32, 224) \ - SIZE_CLASS(15, 32, 256) \ - SIZE_CLASS(16, 64, 320) \ - SIZE_CLASS(17, 64, 384) \ - SIZE_CLASS(18, 64, 448) \ - SIZE_CLASS(19, 64, 512) \ - SIZE_CLASS(20, 128, 640) \ - SIZE_CLASS(21, 128, 768) \ - SIZE_CLASS(22, 128, 896) \ - SIZE_CLASS(23, 128, 1024) \ - SIZE_CLASS(24, 256, 1280) \ - SIZE_CLASS(25, 256, 1536) \ - SIZE_CLASS(26, 256, 1792) \ - SIZE_CLASS(27, 256, 2048) \ - SIZE_CLASS(28, 512, 2560) \ - SIZE_CLASS(29, 512, 3072) \ - SIZE_CLASS(30, 512, 3584) \ - SIZE_CLASS(31, 512, 4096) \ - SIZE_CLASS(32, 1024, 5120) \ - SIZE_CLASS(33, 1024, 6144) \ - SIZE_CLASS(34, 1024, 7168) \ - SIZE_CLASS(35, 1024, 8192) \ - SIZE_CLASS(36, 2048, 10240) \ - SIZE_CLASS(37, 2048, 12288) \ - SIZE_CLASS(38, 2048, 14336) \ - SIZE_CLASS(39, 2048, 16384) \ - SIZE_CLASS(40, 4096, 20480) \ - SIZE_CLASS(41, 4096, 24576) \ - SIZE_CLASS(42, 4096, 28672) \ - SIZE_CLASS(43, 4096, 32768) \ - SIZE_CLASS(44, 8192, 40960) \ - SIZE_CLASS(45, 8192, 49152) \ - SIZE_CLASS(46, 8192, 57344) \ - -#define NBINS 47 -#define SMALL_MAXCLASS 57344 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 12) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 16, 32) \ - SIZE_CLASS(3, 16, 48) \ - SIZE_CLASS(4, 16, 64) \ - SIZE_CLASS(5, 16, 80) \ - SIZE_CLASS(6, 16, 96) \ - SIZE_CLASS(7, 16, 112) \ - SIZE_CLASS(8, 16, 128) \ - SIZE_CLASS(9, 32, 160) \ - SIZE_CLASS(10, 32, 192) \ - SIZE_CLASS(11, 32, 224) \ - SIZE_CLASS(12, 32, 256) \ - SIZE_CLASS(13, 64, 320) \ - SIZE_CLASS(14, 64, 384) \ - SIZE_CLASS(15, 64, 448) \ - SIZE_CLASS(16, 64, 512) \ - SIZE_CLASS(17, 128, 640) \ - SIZE_CLASS(18, 128, 768) \ - SIZE_CLASS(19, 128, 896) \ - SIZE_CLASS(20, 128, 1024) \ - SIZE_CLASS(21, 256, 1280) \ - SIZE_CLASS(22, 256, 1536) \ - SIZE_CLASS(23, 256, 1792) \ - SIZE_CLASS(24, 256, 2048) \ - SIZE_CLASS(25, 512, 2560) \ - SIZE_CLASS(26, 512, 3072) \ - SIZE_CLASS(27, 512, 3584) \ +#ifndef JEMALLOC_INTERNAL_SIZE_CLASSES_H +#define JEMALLOC_INTERNAL_SIZE_CLASSES_H -#define NBINS 28 -#define SMALL_MAXCLASS 3584 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 13) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 16, 32) \ - SIZE_CLASS(3, 16, 48) \ - SIZE_CLASS(4, 16, 64) \ - SIZE_CLASS(5, 16, 80) \ - SIZE_CLASS(6, 16, 96) \ - SIZE_CLASS(7, 16, 112) \ - SIZE_CLASS(8, 16, 128) \ - SIZE_CLASS(9, 32, 160) \ - SIZE_CLASS(10, 32, 192) \ - SIZE_CLASS(11, 32, 224) \ - SIZE_CLASS(12, 32, 256) \ - SIZE_CLASS(13, 64, 320) \ - SIZE_CLASS(14, 64, 384) \ - SIZE_CLASS(15, 64, 448) \ - SIZE_CLASS(16, 64, 512) \ - SIZE_CLASS(17, 128, 640) \ - SIZE_CLASS(18, 128, 768) \ - SIZE_CLASS(19, 128, 896) \ - SIZE_CLASS(20, 128, 1024) \ - SIZE_CLASS(21, 256, 1280) \ - SIZE_CLASS(22, 256, 1536) \ - SIZE_CLASS(23, 256, 1792) \ - SIZE_CLASS(24, 256, 2048) \ - SIZE_CLASS(25, 512, 2560) \ - SIZE_CLASS(26, 512, 3072) \ - SIZE_CLASS(27, 512, 3584) \ - SIZE_CLASS(28, 512, 4096) \ - SIZE_CLASS(29, 1024, 5120) \ - SIZE_CLASS(30, 1024, 6144) \ - SIZE_CLASS(31, 1024, 7168) \ - -#define NBINS 32 -#define SMALL_MAXCLASS 7168 -#endif - -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 14) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 16, 32) \ - SIZE_CLASS(3, 16, 48) \ - SIZE_CLASS(4, 16, 64) \ - SIZE_CLASS(5, 16, 80) \ - SIZE_CLASS(6, 16, 96) \ - SIZE_CLASS(7, 16, 112) \ - SIZE_CLASS(8, 16, 128) \ - SIZE_CLASS(9, 32, 160) \ - SIZE_CLASS(10, 32, 192) \ - SIZE_CLASS(11, 32, 224) \ - SIZE_CLASS(12, 32, 256) \ - SIZE_CLASS(13, 64, 320) \ - SIZE_CLASS(14, 64, 384) \ - SIZE_CLASS(15, 64, 448) \ - SIZE_CLASS(16, 64, 512) \ - SIZE_CLASS(17, 128, 640) \ - SIZE_CLASS(18, 128, 768) \ - SIZE_CLASS(19, 128, 896) \ - SIZE_CLASS(20, 128, 1024) \ - SIZE_CLASS(21, 256, 1280) \ - SIZE_CLASS(22, 256, 1536) \ - SIZE_CLASS(23, 256, 1792) \ - SIZE_CLASS(24, 256, 2048) \ - SIZE_CLASS(25, 512, 2560) \ - SIZE_CLASS(26, 512, 3072) \ - SIZE_CLASS(27, 512, 3584) \ - SIZE_CLASS(28, 512, 4096) \ - SIZE_CLASS(29, 1024, 5120) \ - SIZE_CLASS(30, 1024, 6144) \ - SIZE_CLASS(31, 1024, 7168) \ - SIZE_CLASS(32, 1024, 8192) \ - SIZE_CLASS(33, 2048, 10240) \ - SIZE_CLASS(34, 2048, 12288) \ - SIZE_CLASS(35, 2048, 14336) \ +/* This file was automatically generated by size_classes.sh. */ -#define NBINS 36 -#define SMALL_MAXCLASS 14336 -#endif +#include "jemalloc/internal/jemalloc_internal_types.h" -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 15) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 16, 32) \ - SIZE_CLASS(3, 16, 48) \ - SIZE_CLASS(4, 16, 64) \ - SIZE_CLASS(5, 16, 80) \ - SIZE_CLASS(6, 16, 96) \ - SIZE_CLASS(7, 16, 112) \ - SIZE_CLASS(8, 16, 128) \ - SIZE_CLASS(9, 32, 160) \ - SIZE_CLASS(10, 32, 192) \ - SIZE_CLASS(11, 32, 224) \ - SIZE_CLASS(12, 32, 256) \ - SIZE_CLASS(13, 64, 320) \ - SIZE_CLASS(14, 64, 384) \ - SIZE_CLASS(15, 64, 448) \ - SIZE_CLASS(16, 64, 512) \ - SIZE_CLASS(17, 128, 640) \ - SIZE_CLASS(18, 128, 768) \ - SIZE_CLASS(19, 128, 896) \ - SIZE_CLASS(20, 128, 1024) \ - SIZE_CLASS(21, 256, 1280) \ - SIZE_CLASS(22, 256, 1536) \ - SIZE_CLASS(23, 256, 1792) \ - SIZE_CLASS(24, 256, 2048) \ - SIZE_CLASS(25, 512, 2560) \ - SIZE_CLASS(26, 512, 3072) \ - SIZE_CLASS(27, 512, 3584) \ - SIZE_CLASS(28, 512, 4096) \ - SIZE_CLASS(29, 1024, 5120) \ - SIZE_CLASS(30, 1024, 6144) \ - SIZE_CLASS(31, 1024, 7168) \ - SIZE_CLASS(32, 1024, 8192) \ - SIZE_CLASS(33, 2048, 10240) \ - SIZE_CLASS(34, 2048, 12288) \ - SIZE_CLASS(35, 2048, 14336) \ - SIZE_CLASS(36, 2048, 16384) \ - SIZE_CLASS(37, 4096, 20480) \ - SIZE_CLASS(38, 4096, 24576) \ - SIZE_CLASS(39, 4096, 28672) \ +/* + * This header file defines: + * + * LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling. + * LG_TINY_MIN: Lg of minimum size class to support. + * SIZE_CLASSES: Complete table of SC(index, lg_grp, lg_delta, ndelta, psz, + * bin, pgs, lg_delta_lookup) tuples. + * index: Size class index. + * lg_grp: Lg group base size (no deltas added). + * lg_delta: Lg delta to previous size class. + * ndelta: Delta multiplier. size == 1<<lg_grp + ndelta<<lg_delta + * psz: 'yes' if a multiple of the page size, 'no' otherwise. + * bin: 'yes' if a small bin size class, 'no' otherwise. + * pgs: Slab page count if a small bin size class, 0 otherwise. + * lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no' + * otherwise. + * NTBINS: Number of tiny bins. + * NLBINS: Number of bins supported by the lookup table. + * NBINS: Number of small size class bins. + * NSIZES: Number of size classes. + * LG_CEIL_NSIZES: Number of bits required to store NSIZES. + * NPSIZES: Number of size classes that are a multiple of (1U << LG_PAGE). + * LG_TINY_MAXCLASS: Lg of maximum tiny size class. + * LOOKUP_MAXCLASS: Maximum size class included in lookup table. + * SMALL_MAXCLASS: Maximum small size class. + * LG_LARGE_MINCLASS: Lg of minimum large size class. + * LARGE_MAXCLASS: Maximum (large) size class. + */ -#define NBINS 40 -#define SMALL_MAXCLASS 28672 -#endif +#define LG_SIZE_CLASS_GROUP 2 +#define LG_TINY_MIN 3 -#if (LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 16) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 8, 8) \ - SIZE_CLASS(1, 8, 16) \ - SIZE_CLASS(2, 16, 32) \ - SIZE_CLASS(3, 16, 48) \ - SIZE_CLASS(4, 16, 64) \ - SIZE_CLASS(5, 16, 80) \ - SIZE_CLASS(6, 16, 96) \ - SIZE_CLASS(7, 16, 112) \ - SIZE_CLASS(8, 16, 128) \ - SIZE_CLASS(9, 32, 160) \ - SIZE_CLASS(10, 32, 192) \ - SIZE_CLASS(11, 32, 224) \ - SIZE_CLASS(12, 32, 256) \ - SIZE_CLASS(13, 64, 320) \ - SIZE_CLASS(14, 64, 384) \ - SIZE_CLASS(15, 64, 448) \ - SIZE_CLASS(16, 64, 512) \ - SIZE_CLASS(17, 128, 640) \ - SIZE_CLASS(18, 128, 768) \ - SIZE_CLASS(19, 128, 896) \ - SIZE_CLASS(20, 128, 1024) \ - SIZE_CLASS(21, 256, 1280) \ - SIZE_CLASS(22, 256, 1536) \ - SIZE_CLASS(23, 256, 1792) \ - SIZE_CLASS(24, 256, 2048) \ - SIZE_CLASS(25, 512, 2560) \ - SIZE_CLASS(26, 512, 3072) \ - SIZE_CLASS(27, 512, 3584) \ - SIZE_CLASS(28, 512, 4096) \ - SIZE_CLASS(29, 1024, 5120) \ - SIZE_CLASS(30, 1024, 6144) \ - SIZE_CLASS(31, 1024, 7168) \ - SIZE_CLASS(32, 1024, 8192) \ - SIZE_CLASS(33, 2048, 10240) \ - SIZE_CLASS(34, 2048, 12288) \ - SIZE_CLASS(35, 2048, 14336) \ - SIZE_CLASS(36, 2048, 16384) \ - SIZE_CLASS(37, 4096, 20480) \ - SIZE_CLASS(38, 4096, 24576) \ - SIZE_CLASS(39, 4096, 28672) \ - SIZE_CLASS(40, 4096, 32768) \ - SIZE_CLASS(41, 8192, 40960) \ - SIZE_CLASS(42, 8192, 49152) \ - SIZE_CLASS(43, 8192, 57344) \ +#if (LG_SIZEOF_PTR == 2 && LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 12) +#define SIZE_CLASSES \ + /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \ + SC( 0, 3, 3, 0, no, yes, 1, 3) \ + SC( 1, 3, 3, 1, no, yes, 1, 3) \ + SC( 2, 3, 3, 2, no, yes, 3, 3) \ + SC( 3, 3, 3, 3, no, yes, 1, 3) \ + \ + SC( 4, 5, 3, 1, no, yes, 5, 3) \ + SC( 5, 5, 3, 2, no, yes, 3, 3) \ + SC( 6, 5, 3, 3, no, yes, 7, 3) \ + SC( 7, 5, 3, 4, no, yes, 1, 3) \ + \ + SC( 8, 6, 4, 1, no, yes, 5, 4) \ + SC( 9, 6, 4, 2, no, yes, 3, 4) \ + SC( 10, 6, 4, 3, no, yes, 7, 4) \ + SC( 11, 6, 4, 4, no, yes, 1, 4) \ + \ + SC( 12, 7, 5, 1, no, yes, 5, 5) \ + SC( 13, 7, 5, 2, no, yes, 3, 5) \ + SC( 14, 7, 5, 3, no, yes, 7, 5) \ + SC( 15, 7, 5, 4, no, yes, 1, 5) \ + \ + SC( 16, 8, 6, 1, no, yes, 5, 6) \ + SC( 17, 8, 6, 2, no, yes, 3, 6) \ + SC( 18, 8, 6, 3, no, yes, 7, 6) \ + SC( 19, 8, 6, 4, no, yes, 1, 6) \ + \ + SC( 20, 9, 7, 1, no, yes, 5, 7) \ + SC( 21, 9, 7, 2, no, yes, 3, 7) \ + SC( 22, 9, 7, 3, no, yes, 7, 7) \ + SC( 23, 9, 7, 4, no, yes, 1, 7) \ + \ + SC( 24, 10, 8, 1, no, yes, 5, 8) \ + SC( 25, 10, 8, 2, no, yes, 3, 8) \ + SC( 26, 10, 8, 3, no, yes, 7, 8) \ + SC( 27, 10, 8, 4, no, yes, 1, 8) \ + \ + SC( 28, 11, 9, 1, no, yes, 5, 9) \ + SC( 29, 11, 9, 2, no, yes, 3, 9) \ + SC( 30, 11, 9, 3, no, yes, 7, 9) \ + SC( 31, 11, 9, 4, yes, yes, 1, 9) \ + \ + SC( 32, 12, 10, 1, no, yes, 5, no) \ + SC( 33, 12, 10, 2, no, yes, 3, no) \ + SC( 34, 12, 10, 3, no, yes, 7, no) \ + SC( 35, 12, 10, 4, yes, yes, 2, no) \ + \ + SC( 36, 13, 11, 1, no, yes, 5, no) \ + SC( 37, 13, 11, 2, yes, yes, 3, no) \ + SC( 38, 13, 11, 3, no, yes, 7, no) \ + SC( 39, 13, 11, 4, yes, no, 0, no) \ + \ + SC( 40, 14, 12, 1, yes, no, 0, no) \ + SC( 41, 14, 12, 2, yes, no, 0, no) \ + SC( 42, 14, 12, 3, yes, no, 0, no) \ + SC( 43, 14, 12, 4, yes, no, 0, no) \ + \ + SC( 44, 15, 13, 1, yes, no, 0, no) \ + SC( 45, 15, 13, 2, yes, no, 0, no) \ + SC( 46, 15, 13, 3, yes, no, 0, no) \ + SC( 47, 15, 13, 4, yes, no, 0, no) \ + \ + SC( 48, 16, 14, 1, yes, no, 0, no) \ + SC( 49, 16, 14, 2, yes, no, 0, no) \ + SC( 50, 16, 14, 3, yes, no, 0, no) \ + SC( 51, 16, 14, 4, yes, no, 0, no) \ + \ + SC( 52, 17, 15, 1, yes, no, 0, no) \ + SC( 53, 17, 15, 2, yes, no, 0, no) \ + SC( 54, 17, 15, 3, yes, no, 0, no) \ + SC( 55, 17, 15, 4, yes, no, 0, no) \ + \ + SC( 56, 18, 16, 1, yes, no, 0, no) \ + SC( 57, 18, 16, 2, yes, no, 0, no) \ + SC( 58, 18, 16, 3, yes, no, 0, no) \ + SC( 59, 18, 16, 4, yes, no, 0, no) \ + \ + SC( 60, 19, 17, 1, yes, no, 0, no) \ + SC( 61, 19, 17, 2, yes, no, 0, no) \ + SC( 62, 19, 17, 3, yes, no, 0, no) \ + SC( 63, 19, 17, 4, yes, no, 0, no) \ + \ + SC( 64, 20, 18, 1, yes, no, 0, no) \ + SC( 65, 20, 18, 2, yes, no, 0, no) \ + SC( 66, 20, 18, 3, yes, no, 0, no) \ + SC( 67, 20, 18, 4, yes, no, 0, no) \ + \ + SC( 68, 21, 19, 1, yes, no, 0, no) \ + SC( 69, 21, 19, 2, yes, no, 0, no) \ + SC( 70, 21, 19, 3, yes, no, 0, no) \ + SC( 71, 21, 19, 4, yes, no, 0, no) \ + \ + SC( 72, 22, 20, 1, yes, no, 0, no) \ + SC( 73, 22, 20, 2, yes, no, 0, no) \ + SC( 74, 22, 20, 3, yes, no, 0, no) \ + SC( 75, 22, 20, 4, yes, no, 0, no) \ + \ + SC( 76, 23, 21, 1, yes, no, 0, no) \ + SC( 77, 23, 21, 2, yes, no, 0, no) \ + SC( 78, 23, 21, 3, yes, no, 0, no) \ + SC( 79, 23, 21, 4, yes, no, 0, no) \ + \ + SC( 80, 24, 22, 1, yes, no, 0, no) \ + SC( 81, 24, 22, 2, yes, no, 0, no) \ + SC( 82, 24, 22, 3, yes, no, 0, no) \ + SC( 83, 24, 22, 4, yes, no, 0, no) \ + \ + SC( 84, 25, 23, 1, yes, no, 0, no) \ + SC( 85, 25, 23, 2, yes, no, 0, no) \ + SC( 86, 25, 23, 3, yes, no, 0, no) \ + SC( 87, 25, 23, 4, yes, no, 0, no) \ + \ + SC( 88, 26, 24, 1, yes, no, 0, no) \ + SC( 89, 26, 24, 2, yes, no, 0, no) \ + SC( 90, 26, 24, 3, yes, no, 0, no) \ + SC( 91, 26, 24, 4, yes, no, 0, no) \ + \ + SC( 92, 27, 25, 1, yes, no, 0, no) \ + SC( 93, 27, 25, 2, yes, no, 0, no) \ + SC( 94, 27, 25, 3, yes, no, 0, no) \ + SC( 95, 27, 25, 4, yes, no, 0, no) \ + \ + SC( 96, 28, 26, 1, yes, no, 0, no) \ + SC( 97, 28, 26, 2, yes, no, 0, no) \ + SC( 98, 28, 26, 3, yes, no, 0, no) \ + SC( 99, 28, 26, 4, yes, no, 0, no) \ + \ + SC(100, 29, 27, 1, yes, no, 0, no) \ + SC(101, 29, 27, 2, yes, no, 0, no) \ + SC(102, 29, 27, 3, yes, no, 0, no) \ + SC(103, 29, 27, 4, yes, no, 0, no) \ + \ + SC(104, 30, 28, 1, yes, no, 0, no) \ + SC(105, 30, 28, 2, yes, no, 0, no) \ + SC(106, 30, 28, 3, yes, no, 0, no) \ -#define NBINS 44 -#define SMALL_MAXCLASS 57344 +#define SIZE_CLASSES_DEFINED +#define NTBINS 0 +#define NLBINS 32 +#define NBINS 39 +#define NSIZES 107 +#define LG_CEIL_NSIZES 7 +#define NPSIZES 71 +#define LG_TINY_MAXCLASS "NA" +#define LOOKUP_MAXCLASS ((((size_t)1) << 11) + (((size_t)4) << 9)) +#define SMALL_MAXCLASS ((((size_t)1) << 13) + (((size_t)3) << 11)) +#define LG_LARGE_MINCLASS 14 +#define LARGE_MINCLASS (ZU(1) << LG_LARGE_MINCLASS) +#define LARGE_MAXCLASS ((((size_t)1) << 30) + (((size_t)3) << 28)) #endif -#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 12) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 16, 16) \ - SIZE_CLASS(1, 16, 32) \ - SIZE_CLASS(2, 16, 48) \ - SIZE_CLASS(3, 16, 64) \ - SIZE_CLASS(4, 16, 80) \ - SIZE_CLASS(5, 16, 96) \ - SIZE_CLASS(6, 16, 112) \ - SIZE_CLASS(7, 16, 128) \ - SIZE_CLASS(8, 32, 160) \ - SIZE_CLASS(9, 32, 192) \ - SIZE_CLASS(10, 32, 224) \ - SIZE_CLASS(11, 32, 256) \ - SIZE_CLASS(12, 64, 320) \ - SIZE_CLASS(13, 64, 384) \ - SIZE_CLASS(14, 64, 448) \ - SIZE_CLASS(15, 64, 512) \ - SIZE_CLASS(16, 128, 640) \ - SIZE_CLASS(17, 128, 768) \ - SIZE_CLASS(18, 128, 896) \ - SIZE_CLASS(19, 128, 1024) \ - SIZE_CLASS(20, 256, 1280) \ - SIZE_CLASS(21, 256, 1536) \ - SIZE_CLASS(22, 256, 1792) \ - SIZE_CLASS(23, 256, 2048) \ - SIZE_CLASS(24, 512, 2560) \ - SIZE_CLASS(25, 512, 3072) \ - SIZE_CLASS(26, 512, 3584) \ +#if (LG_SIZEOF_PTR == 2 && LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 12) +#define SIZE_CLASSES \ + /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \ + SC( 0, 3, 3, 0, no, yes, 1, 3) \ + \ + SC( 1, 3, 3, 1, no, yes, 1, 3) \ + SC( 2, 4, 4, 1, no, yes, 1, 4) \ + SC( 3, 4, 4, 2, no, yes, 3, 4) \ + SC( 4, 4, 4, 3, no, yes, 1, 4) \ + \ + SC( 5, 6, 4, 1, no, yes, 5, 4) \ + SC( 6, 6, 4, 2, no, yes, 3, 4) \ + SC( 7, 6, 4, 3, no, yes, 7, 4) \ + SC( 8, 6, 4, 4, no, yes, 1, 4) \ + \ + SC( 9, 7, 5, 1, no, yes, 5, 5) \ + SC( 10, 7, 5, 2, no, yes, 3, 5) \ + SC( 11, 7, 5, 3, no, yes, 7, 5) \ + SC( 12, 7, 5, 4, no, yes, 1, 5) \ + \ + SC( 13, 8, 6, 1, no, yes, 5, 6) \ + SC( 14, 8, 6, 2, no, yes, 3, 6) \ + SC( 15, 8, 6, 3, no, yes, 7, 6) \ + SC( 16, 8, 6, 4, no, yes, 1, 6) \ + \ + SC( 17, 9, 7, 1, no, yes, 5, 7) \ + SC( 18, 9, 7, 2, no, yes, 3, 7) \ + SC( 19, 9, 7, 3, no, yes, 7, 7) \ + SC( 20, 9, 7, 4, no, yes, 1, 7) \ + \ + SC( 21, 10, 8, 1, no, yes, 5, 8) \ + SC( 22, 10, 8, 2, no, yes, 3, 8) \ + SC( 23, 10, 8, 3, no, yes, 7, 8) \ + SC( 24, 10, 8, 4, no, yes, 1, 8) \ + \ + SC( 25, 11, 9, 1, no, yes, 5, 9) \ + SC( 26, 11, 9, 2, no, yes, 3, 9) \ + SC( 27, 11, 9, 3, no, yes, 7, 9) \ + SC( 28, 11, 9, 4, yes, yes, 1, 9) \ + \ + SC( 29, 12, 10, 1, no, yes, 5, no) \ + SC( 30, 12, 10, 2, no, yes, 3, no) \ + SC( 31, 12, 10, 3, no, yes, 7, no) \ + SC( 32, 12, 10, 4, yes, yes, 2, no) \ + \ + SC( 33, 13, 11, 1, no, yes, 5, no) \ + SC( 34, 13, 11, 2, yes, yes, 3, no) \ + SC( 35, 13, 11, 3, no, yes, 7, no) \ + SC( 36, 13, 11, 4, yes, no, 0, no) \ + \ + SC( 37, 14, 12, 1, yes, no, 0, no) \ + SC( 38, 14, 12, 2, yes, no, 0, no) \ + SC( 39, 14, 12, 3, yes, no, 0, no) \ + SC( 40, 14, 12, 4, yes, no, 0, no) \ + \ + SC( 41, 15, 13, 1, yes, no, 0, no) \ + SC( 42, 15, 13, 2, yes, no, 0, no) \ + SC( 43, 15, 13, 3, yes, no, 0, no) \ + SC( 44, 15, 13, 4, yes, no, 0, no) \ + \ + SC( 45, 16, 14, 1, yes, no, 0, no) \ + SC( 46, 16, 14, 2, yes, no, 0, no) \ + SC( 47, 16, 14, 3, yes, no, 0, no) \ + SC( 48, 16, 14, 4, yes, no, 0, no) \ + \ + SC( 49, 17, 15, 1, yes, no, 0, no) \ + SC( 50, 17, 15, 2, yes, no, 0, no) \ + SC( 51, 17, 15, 3, yes, no, 0, no) \ + SC( 52, 17, 15, 4, yes, no, 0, no) \ + \ + SC( 53, 18, 16, 1, yes, no, 0, no) \ + SC( 54, 18, 16, 2, yes, no, 0, no) \ + SC( 55, 18, 16, 3, yes, no, 0, no) \ + SC( 56, 18, 16, 4, yes, no, 0, no) \ + \ + SC( 57, 19, 17, 1, yes, no, 0, no) \ + SC( 58, 19, 17, 2, yes, no, 0, no) \ + SC( 59, 19, 17, 3, yes, no, 0, no) \ + SC( 60, 19, 17, 4, yes, no, 0, no) \ + \ + SC( 61, 20, 18, 1, yes, no, 0, no) \ + SC( 62, 20, 18, 2, yes, no, 0, no) \ + SC( 63, 20, 18, 3, yes, no, 0, no) \ + SC( 64, 20, 18, 4, yes, no, 0, no) \ + \ + SC( 65, 21, 19, 1, yes, no, 0, no) \ + SC( 66, 21, 19, 2, yes, no, 0, no) \ + SC( 67, 21, 19, 3, yes, no, 0, no) \ + SC( 68, 21, 19, 4, yes, no, 0, no) \ + \ + SC( 69, 22, 20, 1, yes, no, 0, no) \ + SC( 70, 22, 20, 2, yes, no, 0, no) \ + SC( 71, 22, 20, 3, yes, no, 0, no) \ + SC( 72, 22, 20, 4, yes, no, 0, no) \ + \ + SC( 73, 23, 21, 1, yes, no, 0, no) \ + SC( 74, 23, 21, 2, yes, no, 0, no) \ + SC( 75, 23, 21, 3, yes, no, 0, no) \ + SC( 76, 23, 21, 4, yes, no, 0, no) \ + \ + SC( 77, 24, 22, 1, yes, no, 0, no) \ + SC( 78, 24, 22, 2, yes, no, 0, no) \ + SC( 79, 24, 22, 3, yes, no, 0, no) \ + SC( 80, 24, 22, 4, yes, no, 0, no) \ + \ + SC( 81, 25, 23, 1, yes, no, 0, no) \ + SC( 82, 25, 23, 2, yes, no, 0, no) \ + SC( 83, 25, 23, 3, yes, no, 0, no) \ + SC( 84, 25, 23, 4, yes, no, 0, no) \ + \ + SC( 85, 26, 24, 1, yes, no, 0, no) \ + SC( 86, 26, 24, 2, yes, no, 0, no) \ + SC( 87, 26, 24, 3, yes, no, 0, no) \ + SC( 88, 26, 24, 4, yes, no, 0, no) \ + \ + SC( 89, 27, 25, 1, yes, no, 0, no) \ + SC( 90, 27, 25, 2, yes, no, 0, no) \ + SC( 91, 27, 25, 3, yes, no, 0, no) \ + SC( 92, 27, 25, 4, yes, no, 0, no) \ + \ + SC( 93, 28, 26, 1, yes, no, 0, no) \ + SC( 94, 28, 26, 2, yes, no, 0, no) \ + SC( 95, 28, 26, 3, yes, no, 0, no) \ + SC( 96, 28, 26, 4, yes, no, 0, no) \ + \ + SC( 97, 29, 27, 1, yes, no, 0, no) \ + SC( 98, 29, 27, 2, yes, no, 0, no) \ + SC( 99, 29, 27, 3, yes, no, 0, no) \ + SC(100, 29, 27, 4, yes, no, 0, no) \ + \ + SC(101, 30, 28, 1, yes, no, 0, no) \ + SC(102, 30, 28, 2, yes, no, 0, no) \ + SC(103, 30, 28, 3, yes, no, 0, no) \ -#define NBINS 27 -#define SMALL_MAXCLASS 3584 +#define SIZE_CLASSES_DEFINED +#define NTBINS 1 +#define NLBINS 29 +#define NBINS 36 +#define NSIZES 104 +#define LG_CEIL_NSIZES 7 +#define NPSIZES 71 +#define LG_TINY_MAXCLASS 3 +#define LOOKUP_MAXCLASS ((((size_t)1) << 11) + (((size_t)4) << 9)) +#define SMALL_MAXCLASS ((((size_t)1) << 13) + (((size_t)3) << 11)) +#define LG_LARGE_MINCLASS 14 +#define LARGE_MINCLASS (ZU(1) << LG_LARGE_MINCLASS) +#define LARGE_MAXCLASS ((((size_t)1) << 30) + (((size_t)3) << 28)) #endif -#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 13) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 16, 16) \ - SIZE_CLASS(1, 16, 32) \ - SIZE_CLASS(2, 16, 48) \ - SIZE_CLASS(3, 16, 64) \ - SIZE_CLASS(4, 16, 80) \ - SIZE_CLASS(5, 16, 96) \ - SIZE_CLASS(6, 16, 112) \ - SIZE_CLASS(7, 16, 128) \ - SIZE_CLASS(8, 32, 160) \ - SIZE_CLASS(9, 32, 192) \ - SIZE_CLASS(10, 32, 224) \ - SIZE_CLASS(11, 32, 256) \ - SIZE_CLASS(12, 64, 320) \ - SIZE_CLASS(13, 64, 384) \ - SIZE_CLASS(14, 64, 448) \ - SIZE_CLASS(15, 64, 512) \ - SIZE_CLASS(16, 128, 640) \ - SIZE_CLASS(17, 128, 768) \ - SIZE_CLASS(18, 128, 896) \ - SIZE_CLASS(19, 128, 1024) \ - SIZE_CLASS(20, 256, 1280) \ - SIZE_CLASS(21, 256, 1536) \ - SIZE_CLASS(22, 256, 1792) \ - SIZE_CLASS(23, 256, 2048) \ - SIZE_CLASS(24, 512, 2560) \ - SIZE_CLASS(25, 512, 3072) \ - SIZE_CLASS(26, 512, 3584) \ - SIZE_CLASS(27, 512, 4096) \ - SIZE_CLASS(28, 1024, 5120) \ - SIZE_CLASS(29, 1024, 6144) \ - SIZE_CLASS(30, 1024, 7168) \ +#if (LG_SIZEOF_PTR == 2 && LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 12) +#define SIZE_CLASSES \ + /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \ + SC( 0, 4, 4, 0, no, yes, 1, 4) \ + SC( 1, 4, 4, 1, no, yes, 1, 4) \ + SC( 2, 4, 4, 2, no, yes, 3, 4) \ + SC( 3, 4, 4, 3, no, yes, 1, 4) \ + \ + SC( 4, 6, 4, 1, no, yes, 5, 4) \ + SC( 5, 6, 4, 2, no, yes, 3, 4) \ + SC( 6, 6, 4, 3, no, yes, 7, 4) \ + SC( 7, 6, 4, 4, no, yes, 1, 4) \ + \ + SC( 8, 7, 5, 1, no, yes, 5, 5) \ + SC( 9, 7, 5, 2, no, yes, 3, 5) \ + SC( 10, 7, 5, 3, no, yes, 7, 5) \ + SC( 11, 7, 5, 4, no, yes, 1, 5) \ + \ + SC( 12, 8, 6, 1, no, yes, 5, 6) \ + SC( 13, 8, 6, 2, no, yes, 3, 6) \ + SC( 14, 8, 6, 3, no, yes, 7, 6) \ + SC( 15, 8, 6, 4, no, yes, 1, 6) \ + \ + SC( 16, 9, 7, 1, no, yes, 5, 7) \ + SC( 17, 9, 7, 2, no, yes, 3, 7) \ + SC( 18, 9, 7, 3, no, yes, 7, 7) \ + SC( 19, 9, 7, 4, no, yes, 1, 7) \ + \ + SC( 20, 10, 8, 1, no, yes, 5, 8) \ + SC( 21, 10, 8, 2, no, yes, 3, 8) \ + SC( 22, 10, 8, 3, no, yes, 7, 8) \ + SC( 23, 10, 8, 4, no, yes, 1, 8) \ + \ + SC( 24, 11, 9, 1, no, yes, 5, 9) \ + SC( 25, 11, 9, 2, no, yes, 3, 9) \ + SC( 26, 11, 9, 3, no, yes, 7, 9) \ + SC( 27, 11, 9, 4, yes, yes, 1, 9) \ + \ + SC( 28, 12, 10, 1, no, yes, 5, no) \ + SC( 29, 12, 10, 2, no, yes, 3, no) \ + SC( 30, 12, 10, 3, no, yes, 7, no) \ + SC( 31, 12, 10, 4, yes, yes, 2, no) \ + \ + SC( 32, 13, 11, 1, no, yes, 5, no) \ + SC( 33, 13, 11, 2, yes, yes, 3, no) \ + SC( 34, 13, 11, 3, no, yes, 7, no) \ + SC( 35, 13, 11, 4, yes, no, 0, no) \ + \ + SC( 36, 14, 12, 1, yes, no, 0, no) \ + SC( 37, 14, 12, 2, yes, no, 0, no) \ + SC( 38, 14, 12, 3, yes, no, 0, no) \ + SC( 39, 14, 12, 4, yes, no, 0, no) \ + \ + SC( 40, 15, 13, 1, yes, no, 0, no) \ + SC( 41, 15, 13, 2, yes, no, 0, no) \ + SC( 42, 15, 13, 3, yes, no, 0, no) \ + SC( 43, 15, 13, 4, yes, no, 0, no) \ + \ + SC( 44, 16, 14, 1, yes, no, 0, no) \ + SC( 45, 16, 14, 2, yes, no, 0, no) \ + SC( 46, 16, 14, 3, yes, no, 0, no) \ + SC( 47, 16, 14, 4, yes, no, 0, no) \ + \ + SC( 48, 17, 15, 1, yes, no, 0, no) \ + SC( 49, 17, 15, 2, yes, no, 0, no) \ + SC( 50, 17, 15, 3, yes, no, 0, no) \ + SC( 51, 17, 15, 4, yes, no, 0, no) \ + \ + SC( 52, 18, 16, 1, yes, no, 0, no) \ + SC( 53, 18, 16, 2, yes, no, 0, no) \ + SC( 54, 18, 16, 3, yes, no, 0, no) \ + SC( 55, 18, 16, 4, yes, no, 0, no) \ + \ + SC( 56, 19, 17, 1, yes, no, 0, no) \ + SC( 57, 19, 17, 2, yes, no, 0, no) \ + SC( 58, 19, 17, 3, yes, no, 0, no) \ + SC( 59, 19, 17, 4, yes, no, 0, no) \ + \ + SC( 60, 20, 18, 1, yes, no, 0, no) \ + SC( 61, 20, 18, 2, yes, no, 0, no) \ + SC( 62, 20, 18, 3, yes, no, 0, no) \ + SC( 63, 20, 18, 4, yes, no, 0, no) \ + \ + SC( 64, 21, 19, 1, yes, no, 0, no) \ + SC( 65, 21, 19, 2, yes, no, 0, no) \ + SC( 66, 21, 19, 3, yes, no, 0, no) \ + SC( 67, 21, 19, 4, yes, no, 0, no) \ + \ + SC( 68, 22, 20, 1, yes, no, 0, no) \ + SC( 69, 22, 20, 2, yes, no, 0, no) \ + SC( 70, 22, 20, 3, yes, no, 0, no) \ + SC( 71, 22, 20, 4, yes, no, 0, no) \ + \ + SC( 72, 23, 21, 1, yes, no, 0, no) \ + SC( 73, 23, 21, 2, yes, no, 0, no) \ + SC( 74, 23, 21, 3, yes, no, 0, no) \ + SC( 75, 23, 21, 4, yes, no, 0, no) \ + \ + SC( 76, 24, 22, 1, yes, no, 0, no) \ + SC( 77, 24, 22, 2, yes, no, 0, no) \ + SC( 78, 24, 22, 3, yes, no, 0, no) \ + SC( 79, 24, 22, 4, yes, no, 0, no) \ + \ + SC( 80, 25, 23, 1, yes, no, 0, no) \ + SC( 81, 25, 23, 2, yes, no, 0, no) \ + SC( 82, 25, 23, 3, yes, no, 0, no) \ + SC( 83, 25, 23, 4, yes, no, 0, no) \ + \ + SC( 84, 26, 24, 1, yes, no, 0, no) \ + SC( 85, 26, 24, 2, yes, no, 0, no) \ + SC( 86, 26, 24, 3, yes, no, 0, no) \ + SC( 87, 26, 24, 4, yes, no, 0, no) \ + \ + SC( 88, 27, 25, 1, yes, no, 0, no) \ + SC( 89, 27, 25, 2, yes, no, 0, no) \ + SC( 90, 27, 25, 3, yes, no, 0, no) \ + SC( 91, 27, 25, 4, yes, no, 0, no) \ + \ + SC( 92, 28, 26, 1, yes, no, 0, no) \ + SC( 93, 28, 26, 2, yes, no, 0, no) \ + SC( 94, 28, 26, 3, yes, no, 0, no) \ + SC( 95, 28, 26, 4, yes, no, 0, no) \ + \ + SC( 96, 29, 27, 1, yes, no, 0, no) \ + SC( 97, 29, 27, 2, yes, no, 0, no) \ + SC( 98, 29, 27, 3, yes, no, 0, no) \ + SC( 99, 29, 27, 4, yes, no, 0, no) \ + \ + SC(100, 30, 28, 1, yes, no, 0, no) \ + SC(101, 30, 28, 2, yes, no, 0, no) \ + SC(102, 30, 28, 3, yes, no, 0, no) \ -#define NBINS 31 -#define SMALL_MAXCLASS 7168 +#define SIZE_CLASSES_DEFINED +#define NTBINS 0 +#define NLBINS 28 +#define NBINS 35 +#define NSIZES 103 +#define LG_CEIL_NSIZES 7 +#define NPSIZES 71 +#define LG_TINY_MAXCLASS "NA" +#define LOOKUP_MAXCLASS ((((size_t)1) << 11) + (((size_t)4) << 9)) +#define SMALL_MAXCLASS ((((size_t)1) << 13) + (((size_t)3) << 11)) +#define LG_LARGE_MINCLASS 14 +#define LARGE_MINCLASS (ZU(1) << LG_LARGE_MINCLASS) +#define LARGE_MAXCLASS ((((size_t)1) << 30) + (((size_t)3) << 28)) #endif -#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 14) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 16, 16) \ - SIZE_CLASS(1, 16, 32) \ - SIZE_CLASS(2, 16, 48) \ - SIZE_CLASS(3, 16, 64) \ - SIZE_CLASS(4, 16, 80) \ - SIZE_CLASS(5, 16, 96) \ - SIZE_CLASS(6, 16, 112) \ - SIZE_CLASS(7, 16, 128) \ - SIZE_CLASS(8, 32, 160) \ - SIZE_CLASS(9, 32, 192) \ - SIZE_CLASS(10, 32, 224) \ - SIZE_CLASS(11, 32, 256) \ - SIZE_CLASS(12, 64, 320) \ - SIZE_CLASS(13, 64, 384) \ - SIZE_CLASS(14, 64, 448) \ - SIZE_CLASS(15, 64, 512) \ - SIZE_CLASS(16, 128, 640) \ - SIZE_CLASS(17, 128, 768) \ - SIZE_CLASS(18, 128, 896) \ - SIZE_CLASS(19, 128, 1024) \ - SIZE_CLASS(20, 256, 1280) \ - SIZE_CLASS(21, 256, 1536) \ - SIZE_CLASS(22, 256, 1792) \ - SIZE_CLASS(23, 256, 2048) \ - SIZE_CLASS(24, 512, 2560) \ - SIZE_CLASS(25, 512, 3072) \ - SIZE_CLASS(26, 512, 3584) \ - SIZE_CLASS(27, 512, 4096) \ - SIZE_CLASS(28, 1024, 5120) \ - SIZE_CLASS(29, 1024, 6144) \ - SIZE_CLASS(30, 1024, 7168) \ - SIZE_CLASS(31, 1024, 8192) \ - SIZE_CLASS(32, 2048, 10240) \ - SIZE_CLASS(33, 2048, 12288) \ - SIZE_CLASS(34, 2048, 14336) \ +#if (LG_SIZEOF_PTR == 3 && LG_TINY_MIN == 3 && LG_QUANTUM == 3 && LG_PAGE == 12) +#define SIZE_CLASSES \ + /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \ + SC( 0, 3, 3, 0, no, yes, 1, 3) \ + SC( 1, 3, 3, 1, no, yes, 1, 3) \ + SC( 2, 3, 3, 2, no, yes, 3, 3) \ + SC( 3, 3, 3, 3, no, yes, 1, 3) \ + \ + SC( 4, 5, 3, 1, no, yes, 5, 3) \ + SC( 5, 5, 3, 2, no, yes, 3, 3) \ + SC( 6, 5, 3, 3, no, yes, 7, 3) \ + SC( 7, 5, 3, 4, no, yes, 1, 3) \ + \ + SC( 8, 6, 4, 1, no, yes, 5, 4) \ + SC( 9, 6, 4, 2, no, yes, 3, 4) \ + SC( 10, 6, 4, 3, no, yes, 7, 4) \ + SC( 11, 6, 4, 4, no, yes, 1, 4) \ + \ + SC( 12, 7, 5, 1, no, yes, 5, 5) \ + SC( 13, 7, 5, 2, no, yes, 3, 5) \ + SC( 14, 7, 5, 3, no, yes, 7, 5) \ + SC( 15, 7, 5, 4, no, yes, 1, 5) \ + \ + SC( 16, 8, 6, 1, no, yes, 5, 6) \ + SC( 17, 8, 6, 2, no, yes, 3, 6) \ + SC( 18, 8, 6, 3, no, yes, 7, 6) \ + SC( 19, 8, 6, 4, no, yes, 1, 6) \ + \ + SC( 20, 9, 7, 1, no, yes, 5, 7) \ + SC( 21, 9, 7, 2, no, yes, 3, 7) \ + SC( 22, 9, 7, 3, no, yes, 7, 7) \ + SC( 23, 9, 7, 4, no, yes, 1, 7) \ + \ + SC( 24, 10, 8, 1, no, yes, 5, 8) \ + SC( 25, 10, 8, 2, no, yes, 3, 8) \ + SC( 26, 10, 8, 3, no, yes, 7, 8) \ + SC( 27, 10, 8, 4, no, yes, 1, 8) \ + \ + SC( 28, 11, 9, 1, no, yes, 5, 9) \ + SC( 29, 11, 9, 2, no, yes, 3, 9) \ + SC( 30, 11, 9, 3, no, yes, 7, 9) \ + SC( 31, 11, 9, 4, yes, yes, 1, 9) \ + \ + SC( 32, 12, 10, 1, no, yes, 5, no) \ + SC( 33, 12, 10, 2, no, yes, 3, no) \ + SC( 34, 12, 10, 3, no, yes, 7, no) \ + SC( 35, 12, 10, 4, yes, yes, 2, no) \ + \ + SC( 36, 13, 11, 1, no, yes, 5, no) \ + SC( 37, 13, 11, 2, yes, yes, 3, no) \ + SC( 38, 13, 11, 3, no, yes, 7, no) \ + SC( 39, 13, 11, 4, yes, no, 0, no) \ + \ + SC( 40, 14, 12, 1, yes, no, 0, no) \ + SC( 41, 14, 12, 2, yes, no, 0, no) \ + SC( 42, 14, 12, 3, yes, no, 0, no) \ + SC( 43, 14, 12, 4, yes, no, 0, no) \ + \ + SC( 44, 15, 13, 1, yes, no, 0, no) \ + SC( 45, 15, 13, 2, yes, no, 0, no) \ + SC( 46, 15, 13, 3, yes, no, 0, no) \ + SC( 47, 15, 13, 4, yes, no, 0, no) \ + \ + SC( 48, 16, 14, 1, yes, no, 0, no) \ + SC( 49, 16, 14, 2, yes, no, 0, no) \ + SC( 50, 16, 14, 3, yes, no, 0, no) \ + SC( 51, 16, 14, 4, yes, no, 0, no) \ + \ + SC( 52, 17, 15, 1, yes, no, 0, no) \ + SC( 53, 17, 15, 2, yes, no, 0, no) \ + SC( 54, 17, 15, 3, yes, no, 0, no) \ + SC( 55, 17, 15, 4, yes, no, 0, no) \ + \ + SC( 56, 18, 16, 1, yes, no, 0, no) \ + SC( 57, 18, 16, 2, yes, no, 0, no) \ + SC( 58, 18, 16, 3, yes, no, 0, no) \ + SC( 59, 18, 16, 4, yes, no, 0, no) \ + \ + SC( 60, 19, 17, 1, yes, no, 0, no) \ + SC( 61, 19, 17, 2, yes, no, 0, no) \ + SC( 62, 19, 17, 3, yes, no, 0, no) \ + SC( 63, 19, 17, 4, yes, no, 0, no) \ + \ + SC( 64, 20, 18, 1, yes, no, 0, no) \ + SC( 65, 20, 18, 2, yes, no, 0, no) \ + SC( 66, 20, 18, 3, yes, no, 0, no) \ + SC( 67, 20, 18, 4, yes, no, 0, no) \ + \ + SC( 68, 21, 19, 1, yes, no, 0, no) \ + SC( 69, 21, 19, 2, yes, no, 0, no) \ + SC( 70, 21, 19, 3, yes, no, 0, no) \ + SC( 71, 21, 19, 4, yes, no, 0, no) \ + \ + SC( 72, 22, 20, 1, yes, no, 0, no) \ + SC( 73, 22, 20, 2, yes, no, 0, no) \ + SC( 74, 22, 20, 3, yes, no, 0, no) \ + SC( 75, 22, 20, 4, yes, no, 0, no) \ + \ + SC( 76, 23, 21, 1, yes, no, 0, no) \ + SC( 77, 23, 21, 2, yes, no, 0, no) \ + SC( 78, 23, 21, 3, yes, no, 0, no) \ + SC( 79, 23, 21, 4, yes, no, 0, no) \ + \ + SC( 80, 24, 22, 1, yes, no, 0, no) \ + SC( 81, 24, 22, 2, yes, no, 0, no) \ + SC( 82, 24, 22, 3, yes, no, 0, no) \ + SC( 83, 24, 22, 4, yes, no, 0, no) \ + \ + SC( 84, 25, 23, 1, yes, no, 0, no) \ + SC( 85, 25, 23, 2, yes, no, 0, no) \ + SC( 86, 25, 23, 3, yes, no, 0, no) \ + SC( 87, 25, 23, 4, yes, no, 0, no) \ + \ + SC( 88, 26, 24, 1, yes, no, 0, no) \ + SC( 89, 26, 24, 2, yes, no, 0, no) \ + SC( 90, 26, 24, 3, yes, no, 0, no) \ + SC( 91, 26, 24, 4, yes, no, 0, no) \ + \ + SC( 92, 27, 25, 1, yes, no, 0, no) \ + SC( 93, 27, 25, 2, yes, no, 0, no) \ + SC( 94, 27, 25, 3, yes, no, 0, no) \ + SC( 95, 27, 25, 4, yes, no, 0, no) \ + \ + SC( 96, 28, 26, 1, yes, no, 0, no) \ + SC( 97, 28, 26, 2, yes, no, 0, no) \ + SC( 98, 28, 26, 3, yes, no, 0, no) \ + SC( 99, 28, 26, 4, yes, no, 0, no) \ + \ + SC(100, 29, 27, 1, yes, no, 0, no) \ + SC(101, 29, 27, 2, yes, no, 0, no) \ + SC(102, 29, 27, 3, yes, no, 0, no) \ + SC(103, 29, 27, 4, yes, no, 0, no) \ + \ + SC(104, 30, 28, 1, yes, no, 0, no) \ + SC(105, 30, 28, 2, yes, no, 0, no) \ + SC(106, 30, 28, 3, yes, no, 0, no) \ + SC(107, 30, 28, 4, yes, no, 0, no) \ + \ + SC(108, 31, 29, 1, yes, no, 0, no) \ + SC(109, 31, 29, 2, yes, no, 0, no) \ + SC(110, 31, 29, 3, yes, no, 0, no) \ + SC(111, 31, 29, 4, yes, no, 0, no) \ + \ + SC(112, 32, 30, 1, yes, no, 0, no) \ + SC(113, 32, 30, 2, yes, no, 0, no) \ + SC(114, 32, 30, 3, yes, no, 0, no) \ + SC(115, 32, 30, 4, yes, no, 0, no) \ + \ + SC(116, 33, 31, 1, yes, no, 0, no) \ + SC(117, 33, 31, 2, yes, no, 0, no) \ + SC(118, 33, 31, 3, yes, no, 0, no) \ + SC(119, 33, 31, 4, yes, no, 0, no) \ + \ + SC(120, 34, 32, 1, yes, no, 0, no) \ + SC(121, 34, 32, 2, yes, no, 0, no) \ + SC(122, 34, 32, 3, yes, no, 0, no) \ + SC(123, 34, 32, 4, yes, no, 0, no) \ + \ + SC(124, 35, 33, 1, yes, no, 0, no) \ + SC(125, 35, 33, 2, yes, no, 0, no) \ + SC(126, 35, 33, 3, yes, no, 0, no) \ + SC(127, 35, 33, 4, yes, no, 0, no) \ + \ + SC(128, 36, 34, 1, yes, no, 0, no) \ + SC(129, 36, 34, 2, yes, no, 0, no) \ + SC(130, 36, 34, 3, yes, no, 0, no) \ + SC(131, 36, 34, 4, yes, no, 0, no) \ + \ + SC(132, 37, 35, 1, yes, no, 0, no) \ + SC(133, 37, 35, 2, yes, no, 0, no) \ + SC(134, 37, 35, 3, yes, no, 0, no) \ + SC(135, 37, 35, 4, yes, no, 0, no) \ + \ + SC(136, 38, 36, 1, yes, no, 0, no) \ + SC(137, 38, 36, 2, yes, no, 0, no) \ + SC(138, 38, 36, 3, yes, no, 0, no) \ + SC(139, 38, 36, 4, yes, no, 0, no) \ + \ + SC(140, 39, 37, 1, yes, no, 0, no) \ + SC(141, 39, 37, 2, yes, no, 0, no) \ + SC(142, 39, 37, 3, yes, no, 0, no) \ + SC(143, 39, 37, 4, yes, no, 0, no) \ + \ + SC(144, 40, 38, 1, yes, no, 0, no) \ + SC(145, 40, 38, 2, yes, no, 0, no) \ + SC(146, 40, 38, 3, yes, no, 0, no) \ + SC(147, 40, 38, 4, yes, no, 0, no) \ + \ + SC(148, 41, 39, 1, yes, no, 0, no) \ + SC(149, 41, 39, 2, yes, no, 0, no) \ + SC(150, 41, 39, 3, yes, no, 0, no) \ + SC(151, 41, 39, 4, yes, no, 0, no) \ + \ + SC(152, 42, 40, 1, yes, no, 0, no) \ + SC(153, 42, 40, 2, yes, no, 0, no) \ + SC(154, 42, 40, 3, yes, no, 0, no) \ + SC(155, 42, 40, 4, yes, no, 0, no) \ + \ + SC(156, 43, 41, 1, yes, no, 0, no) \ + SC(157, 43, 41, 2, yes, no, 0, no) \ + SC(158, 43, 41, 3, yes, no, 0, no) \ + SC(159, 43, 41, 4, yes, no, 0, no) \ + \ + SC(160, 44, 42, 1, yes, no, 0, no) \ + SC(161, 44, 42, 2, yes, no, 0, no) \ + SC(162, 44, 42, 3, yes, no, 0, no) \ + SC(163, 44, 42, 4, yes, no, 0, no) \ + \ + SC(164, 45, 43, 1, yes, no, 0, no) \ + SC(165, 45, 43, 2, yes, no, 0, no) \ + SC(166, 45, 43, 3, yes, no, 0, no) \ + SC(167, 45, 43, 4, yes, no, 0, no) \ + \ + SC(168, 46, 44, 1, yes, no, 0, no) \ + SC(169, 46, 44, 2, yes, no, 0, no) \ + SC(170, 46, 44, 3, yes, no, 0, no) \ + SC(171, 46, 44, 4, yes, no, 0, no) \ + \ + SC(172, 47, 45, 1, yes, no, 0, no) \ + SC(173, 47, 45, 2, yes, no, 0, no) \ + SC(174, 47, 45, 3, yes, no, 0, no) \ + SC(175, 47, 45, 4, yes, no, 0, no) \ + \ + SC(176, 48, 46, 1, yes, no, 0, no) \ + SC(177, 48, 46, 2, yes, no, 0, no) \ + SC(178, 48, 46, 3, yes, no, 0, no) \ + SC(179, 48, 46, 4, yes, no, 0, no) \ + \ + SC(180, 49, 47, 1, yes, no, 0, no) \ + SC(181, 49, 47, 2, yes, no, 0, no) \ + SC(182, 49, 47, 3, yes, no, 0, no) \ + SC(183, 49, 47, 4, yes, no, 0, no) \ + \ + SC(184, 50, 48, 1, yes, no, 0, no) \ + SC(185, 50, 48, 2, yes, no, 0, no) \ + SC(186, 50, 48, 3, yes, no, 0, no) \ + SC(187, 50, 48, 4, yes, no, 0, no) \ + \ + SC(188, 51, 49, 1, yes, no, 0, no) \ + SC(189, 51, 49, 2, yes, no, 0, no) \ + SC(190, 51, 49, 3, yes, no, 0, no) \ + SC(191, 51, 49, 4, yes, no, 0, no) \ + \ + SC(192, 52, 50, 1, yes, no, 0, no) \ + SC(193, 52, 50, 2, yes, no, 0, no) \ + SC(194, 52, 50, 3, yes, no, 0, no) \ + SC(195, 52, 50, 4, yes, no, 0, no) \ + \ + SC(196, 53, 51, 1, yes, no, 0, no) \ + SC(197, 53, 51, 2, yes, no, 0, no) \ + SC(198, 53, 51, 3, yes, no, 0, no) \ + SC(199, 53, 51, 4, yes, no, 0, no) \ + \ + SC(200, 54, 52, 1, yes, no, 0, no) \ + SC(201, 54, 52, 2, yes, no, 0, no) \ + SC(202, 54, 52, 3, yes, no, 0, no) \ + SC(203, 54, 52, 4, yes, no, 0, no) \ + \ + SC(204, 55, 53, 1, yes, no, 0, no) \ + SC(205, 55, 53, 2, yes, no, 0, no) \ + SC(206, 55, 53, 3, yes, no, 0, no) \ + SC(207, 55, 53, 4, yes, no, 0, no) \ + \ + SC(208, 56, 54, 1, yes, no, 0, no) \ + SC(209, 56, 54, 2, yes, no, 0, no) \ + SC(210, 56, 54, 3, yes, no, 0, no) \ + SC(211, 56, 54, 4, yes, no, 0, no) \ + \ + SC(212, 57, 55, 1, yes, no, 0, no) \ + SC(213, 57, 55, 2, yes, no, 0, no) \ + SC(214, 57, 55, 3, yes, no, 0, no) \ + SC(215, 57, 55, 4, yes, no, 0, no) \ + \ + SC(216, 58, 56, 1, yes, no, 0, no) \ + SC(217, 58, 56, 2, yes, no, 0, no) \ + SC(218, 58, 56, 3, yes, no, 0, no) \ + SC(219, 58, 56, 4, yes, no, 0, no) \ + \ + SC(220, 59, 57, 1, yes, no, 0, no) \ + SC(221, 59, 57, 2, yes, no, 0, no) \ + SC(222, 59, 57, 3, yes, no, 0, no) \ + SC(223, 59, 57, 4, yes, no, 0, no) \ + \ + SC(224, 60, 58, 1, yes, no, 0, no) \ + SC(225, 60, 58, 2, yes, no, 0, no) \ + SC(226, 60, 58, 3, yes, no, 0, no) \ + SC(227, 60, 58, 4, yes, no, 0, no) \ + \ + SC(228, 61, 59, 1, yes, no, 0, no) \ + SC(229, 61, 59, 2, yes, no, 0, no) \ + SC(230, 61, 59, 3, yes, no, 0, no) \ + SC(231, 61, 59, 4, yes, no, 0, no) \ + \ + SC(232, 62, 60, 1, yes, no, 0, no) \ + SC(233, 62, 60, 2, yes, no, 0, no) \ + SC(234, 62, 60, 3, yes, no, 0, no) \ -#define NBINS 35 -#define SMALL_MAXCLASS 14336 +#define SIZE_CLASSES_DEFINED +#define NTBINS 0 +#define NLBINS 32 +#define NBINS 39 +#define NSIZES 235 +#define LG_CEIL_NSIZES 8 +#define NPSIZES 199 +#define LG_TINY_MAXCLASS "NA" +#define LOOKUP_MAXCLASS ((((size_t)1) << 11) + (((size_t)4) << 9)) +#define SMALL_MAXCLASS ((((size_t)1) << 13) + (((size_t)3) << 11)) +#define LG_LARGE_MINCLASS 14 +#define LARGE_MINCLASS (ZU(1) << LG_LARGE_MINCLASS) +#define LARGE_MAXCLASS ((((size_t)1) << 62) + (((size_t)3) << 60)) #endif -#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 15) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 16, 16) \ - SIZE_CLASS(1, 16, 32) \ - SIZE_CLASS(2, 16, 48) \ - SIZE_CLASS(3, 16, 64) \ - SIZE_CLASS(4, 16, 80) \ - SIZE_CLASS(5, 16, 96) \ - SIZE_CLASS(6, 16, 112) \ - SIZE_CLASS(7, 16, 128) \ - SIZE_CLASS(8, 32, 160) \ - SIZE_CLASS(9, 32, 192) \ - SIZE_CLASS(10, 32, 224) \ - SIZE_CLASS(11, 32, 256) \ - SIZE_CLASS(12, 64, 320) \ - SIZE_CLASS(13, 64, 384) \ - SIZE_CLASS(14, 64, 448) \ - SIZE_CLASS(15, 64, 512) \ - SIZE_CLASS(16, 128, 640) \ - SIZE_CLASS(17, 128, 768) \ - SIZE_CLASS(18, 128, 896) \ - SIZE_CLASS(19, 128, 1024) \ - SIZE_CLASS(20, 256, 1280) \ - SIZE_CLASS(21, 256, 1536) \ - SIZE_CLASS(22, 256, 1792) \ - SIZE_CLASS(23, 256, 2048) \ - SIZE_CLASS(24, 512, 2560) \ - SIZE_CLASS(25, 512, 3072) \ - SIZE_CLASS(26, 512, 3584) \ - SIZE_CLASS(27, 512, 4096) \ - SIZE_CLASS(28, 1024, 5120) \ - SIZE_CLASS(29, 1024, 6144) \ - SIZE_CLASS(30, 1024, 7168) \ - SIZE_CLASS(31, 1024, 8192) \ - SIZE_CLASS(32, 2048, 10240) \ - SIZE_CLASS(33, 2048, 12288) \ - SIZE_CLASS(34, 2048, 14336) \ - SIZE_CLASS(35, 2048, 16384) \ - SIZE_CLASS(36, 4096, 20480) \ - SIZE_CLASS(37, 4096, 24576) \ - SIZE_CLASS(38, 4096, 28672) \ +#if (LG_SIZEOF_PTR == 3 && LG_TINY_MIN == 3 && LG_QUANTUM == 4 && LG_PAGE == 12) +#define SIZE_CLASSES \ + /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \ + SC( 0, 3, 3, 0, no, yes, 1, 3) \ + \ + SC( 1, 3, 3, 1, no, yes, 1, 3) \ + SC( 2, 4, 4, 1, no, yes, 1, 4) \ + SC( 3, 4, 4, 2, no, yes, 3, 4) \ + SC( 4, 4, 4, 3, no, yes, 1, 4) \ + \ + SC( 5, 6, 4, 1, no, yes, 5, 4) \ + SC( 6, 6, 4, 2, no, yes, 3, 4) \ + SC( 7, 6, 4, 3, no, yes, 7, 4) \ + SC( 8, 6, 4, 4, no, yes, 1, 4) \ + \ + SC( 9, 7, 5, 1, no, yes, 5, 5) \ + SC( 10, 7, 5, 2, no, yes, 3, 5) \ + SC( 11, 7, 5, 3, no, yes, 7, 5) \ + SC( 12, 7, 5, 4, no, yes, 1, 5) \ + \ + SC( 13, 8, 6, 1, no, yes, 5, 6) \ + SC( 14, 8, 6, 2, no, yes, 3, 6) \ + SC( 15, 8, 6, 3, no, yes, 7, 6) \ + SC( 16, 8, 6, 4, no, yes, 1, 6) \ + \ + SC( 17, 9, 7, 1, no, yes, 5, 7) \ + SC( 18, 9, 7, 2, no, yes, 3, 7) \ + SC( 19, 9, 7, 3, no, yes, 7, 7) \ + SC( 20, 9, 7, 4, no, yes, 1, 7) \ + \ + SC( 21, 10, 8, 1, no, yes, 5, 8) \ + SC( 22, 10, 8, 2, no, yes, 3, 8) \ + SC( 23, 10, 8, 3, no, yes, 7, 8) \ + SC( 24, 10, 8, 4, no, yes, 1, 8) \ + \ + SC( 25, 11, 9, 1, no, yes, 5, 9) \ + SC( 26, 11, 9, 2, no, yes, 3, 9) \ + SC( 27, 11, 9, 3, no, yes, 7, 9) \ + SC( 28, 11, 9, 4, yes, yes, 1, 9) \ + \ + SC( 29, 12, 10, 1, no, yes, 5, no) \ + SC( 30, 12, 10, 2, no, yes, 3, no) \ + SC( 31, 12, 10, 3, no, yes, 7, no) \ + SC( 32, 12, 10, 4, yes, yes, 2, no) \ + \ + SC( 33, 13, 11, 1, no, yes, 5, no) \ + SC( 34, 13, 11, 2, yes, yes, 3, no) \ + SC( 35, 13, 11, 3, no, yes, 7, no) \ + SC( 36, 13, 11, 4, yes, no, 0, no) \ + \ + SC( 37, 14, 12, 1, yes, no, 0, no) \ + SC( 38, 14, 12, 2, yes, no, 0, no) \ + SC( 39, 14, 12, 3, yes, no, 0, no) \ + SC( 40, 14, 12, 4, yes, no, 0, no) \ + \ + SC( 41, 15, 13, 1, yes, no, 0, no) \ + SC( 42, 15, 13, 2, yes, no, 0, no) \ + SC( 43, 15, 13, 3, yes, no, 0, no) \ + SC( 44, 15, 13, 4, yes, no, 0, no) \ + \ + SC( 45, 16, 14, 1, yes, no, 0, no) \ + SC( 46, 16, 14, 2, yes, no, 0, no) \ + SC( 47, 16, 14, 3, yes, no, 0, no) \ + SC( 48, 16, 14, 4, yes, no, 0, no) \ + \ + SC( 49, 17, 15, 1, yes, no, 0, no) \ + SC( 50, 17, 15, 2, yes, no, 0, no) \ + SC( 51, 17, 15, 3, yes, no, 0, no) \ + SC( 52, 17, 15, 4, yes, no, 0, no) \ + \ + SC( 53, 18, 16, 1, yes, no, 0, no) \ + SC( 54, 18, 16, 2, yes, no, 0, no) \ + SC( 55, 18, 16, 3, yes, no, 0, no) \ + SC( 56, 18, 16, 4, yes, no, 0, no) \ + \ + SC( 57, 19, 17, 1, yes, no, 0, no) \ + SC( 58, 19, 17, 2, yes, no, 0, no) \ + SC( 59, 19, 17, 3, yes, no, 0, no) \ + SC( 60, 19, 17, 4, yes, no, 0, no) \ + \ + SC( 61, 20, 18, 1, yes, no, 0, no) \ + SC( 62, 20, 18, 2, yes, no, 0, no) \ + SC( 63, 20, 18, 3, yes, no, 0, no) \ + SC( 64, 20, 18, 4, yes, no, 0, no) \ + \ + SC( 65, 21, 19, 1, yes, no, 0, no) \ + SC( 66, 21, 19, 2, yes, no, 0, no) \ + SC( 67, 21, 19, 3, yes, no, 0, no) \ + SC( 68, 21, 19, 4, yes, no, 0, no) \ + \ + SC( 69, 22, 20, 1, yes, no, 0, no) \ + SC( 70, 22, 20, 2, yes, no, 0, no) \ + SC( 71, 22, 20, 3, yes, no, 0, no) \ + SC( 72, 22, 20, 4, yes, no, 0, no) \ + \ + SC( 73, 23, 21, 1, yes, no, 0, no) \ + SC( 74, 23, 21, 2, yes, no, 0, no) \ + SC( 75, 23, 21, 3, yes, no, 0, no) \ + SC( 76, 23, 21, 4, yes, no, 0, no) \ + \ + SC( 77, 24, 22, 1, yes, no, 0, no) \ + SC( 78, 24, 22, 2, yes, no, 0, no) \ + SC( 79, 24, 22, 3, yes, no, 0, no) \ + SC( 80, 24, 22, 4, yes, no, 0, no) \ + \ + SC( 81, 25, 23, 1, yes, no, 0, no) \ + SC( 82, 25, 23, 2, yes, no, 0, no) \ + SC( 83, 25, 23, 3, yes, no, 0, no) \ + SC( 84, 25, 23, 4, yes, no, 0, no) \ + \ + SC( 85, 26, 24, 1, yes, no, 0, no) \ + SC( 86, 26, 24, 2, yes, no, 0, no) \ + SC( 87, 26, 24, 3, yes, no, 0, no) \ + SC( 88, 26, 24, 4, yes, no, 0, no) \ + \ + SC( 89, 27, 25, 1, yes, no, 0, no) \ + SC( 90, 27, 25, 2, yes, no, 0, no) \ + SC( 91, 27, 25, 3, yes, no, 0, no) \ + SC( 92, 27, 25, 4, yes, no, 0, no) \ + \ + SC( 93, 28, 26, 1, yes, no, 0, no) \ + SC( 94, 28, 26, 2, yes, no, 0, no) \ + SC( 95, 28, 26, 3, yes, no, 0, no) \ + SC( 96, 28, 26, 4, yes, no, 0, no) \ + \ + SC( 97, 29, 27, 1, yes, no, 0, no) \ + SC( 98, 29, 27, 2, yes, no, 0, no) \ + SC( 99, 29, 27, 3, yes, no, 0, no) \ + SC(100, 29, 27, 4, yes, no, 0, no) \ + \ + SC(101, 30, 28, 1, yes, no, 0, no) \ + SC(102, 30, 28, 2, yes, no, 0, no) \ + SC(103, 30, 28, 3, yes, no, 0, no) \ + SC(104, 30, 28, 4, yes, no, 0, no) \ + \ + SC(105, 31, 29, 1, yes, no, 0, no) \ + SC(106, 31, 29, 2, yes, no, 0, no) \ + SC(107, 31, 29, 3, yes, no, 0, no) \ + SC(108, 31, 29, 4, yes, no, 0, no) \ + \ + SC(109, 32, 30, 1, yes, no, 0, no) \ + SC(110, 32, 30, 2, yes, no, 0, no) \ + SC(111, 32, 30, 3, yes, no, 0, no) \ + SC(112, 32, 30, 4, yes, no, 0, no) \ + \ + SC(113, 33, 31, 1, yes, no, 0, no) \ + SC(114, 33, 31, 2, yes, no, 0, no) \ + SC(115, 33, 31, 3, yes, no, 0, no) \ + SC(116, 33, 31, 4, yes, no, 0, no) \ + \ + SC(117, 34, 32, 1, yes, no, 0, no) \ + SC(118, 34, 32, 2, yes, no, 0, no) \ + SC(119, 34, 32, 3, yes, no, 0, no) \ + SC(120, 34, 32, 4, yes, no, 0, no) \ + \ + SC(121, 35, 33, 1, yes, no, 0, no) \ + SC(122, 35, 33, 2, yes, no, 0, no) \ + SC(123, 35, 33, 3, yes, no, 0, no) \ + SC(124, 35, 33, 4, yes, no, 0, no) \ + \ + SC(125, 36, 34, 1, yes, no, 0, no) \ + SC(126, 36, 34, 2, yes, no, 0, no) \ + SC(127, 36, 34, 3, yes, no, 0, no) \ + SC(128, 36, 34, 4, yes, no, 0, no) \ + \ + SC(129, 37, 35, 1, yes, no, 0, no) \ + SC(130, 37, 35, 2, yes, no, 0, no) \ + SC(131, 37, 35, 3, yes, no, 0, no) \ + SC(132, 37, 35, 4, yes, no, 0, no) \ + \ + SC(133, 38, 36, 1, yes, no, 0, no) \ + SC(134, 38, 36, 2, yes, no, 0, no) \ + SC(135, 38, 36, 3, yes, no, 0, no) \ + SC(136, 38, 36, 4, yes, no, 0, no) \ + \ + SC(137, 39, 37, 1, yes, no, 0, no) \ + SC(138, 39, 37, 2, yes, no, 0, no) \ + SC(139, 39, 37, 3, yes, no, 0, no) \ + SC(140, 39, 37, 4, yes, no, 0, no) \ + \ + SC(141, 40, 38, 1, yes, no, 0, no) \ + SC(142, 40, 38, 2, yes, no, 0, no) \ + SC(143, 40, 38, 3, yes, no, 0, no) \ + SC(144, 40, 38, 4, yes, no, 0, no) \ + \ + SC(145, 41, 39, 1, yes, no, 0, no) \ + SC(146, 41, 39, 2, yes, no, 0, no) \ + SC(147, 41, 39, 3, yes, no, 0, no) \ + SC(148, 41, 39, 4, yes, no, 0, no) \ + \ + SC(149, 42, 40, 1, yes, no, 0, no) \ + SC(150, 42, 40, 2, yes, no, 0, no) \ + SC(151, 42, 40, 3, yes, no, 0, no) \ + SC(152, 42, 40, 4, yes, no, 0, no) \ + \ + SC(153, 43, 41, 1, yes, no, 0, no) \ + SC(154, 43, 41, 2, yes, no, 0, no) \ + SC(155, 43, 41, 3, yes, no, 0, no) \ + SC(156, 43, 41, 4, yes, no, 0, no) \ + \ + SC(157, 44, 42, 1, yes, no, 0, no) \ + SC(158, 44, 42, 2, yes, no, 0, no) \ + SC(159, 44, 42, 3, yes, no, 0, no) \ + SC(160, 44, 42, 4, yes, no, 0, no) \ + \ + SC(161, 45, 43, 1, yes, no, 0, no) \ + SC(162, 45, 43, 2, yes, no, 0, no) \ + SC(163, 45, 43, 3, yes, no, 0, no) \ + SC(164, 45, 43, 4, yes, no, 0, no) \ + \ + SC(165, 46, 44, 1, yes, no, 0, no) \ + SC(166, 46, 44, 2, yes, no, 0, no) \ + SC(167, 46, 44, 3, yes, no, 0, no) \ + SC(168, 46, 44, 4, yes, no, 0, no) \ + \ + SC(169, 47, 45, 1, yes, no, 0, no) \ + SC(170, 47, 45, 2, yes, no, 0, no) \ + SC(171, 47, 45, 3, yes, no, 0, no) \ + SC(172, 47, 45, 4, yes, no, 0, no) \ + \ + SC(173, 48, 46, 1, yes, no, 0, no) \ + SC(174, 48, 46, 2, yes, no, 0, no) \ + SC(175, 48, 46, 3, yes, no, 0, no) \ + SC(176, 48, 46, 4, yes, no, 0, no) \ + \ + SC(177, 49, 47, 1, yes, no, 0, no) \ + SC(178, 49, 47, 2, yes, no, 0, no) \ + SC(179, 49, 47, 3, yes, no, 0, no) \ + SC(180, 49, 47, 4, yes, no, 0, no) \ + \ + SC(181, 50, 48, 1, yes, no, 0, no) \ + SC(182, 50, 48, 2, yes, no, 0, no) \ + SC(183, 50, 48, 3, yes, no, 0, no) \ + SC(184, 50, 48, 4, yes, no, 0, no) \ + \ + SC(185, 51, 49, 1, yes, no, 0, no) \ + SC(186, 51, 49, 2, yes, no, 0, no) \ + SC(187, 51, 49, 3, yes, no, 0, no) \ + SC(188, 51, 49, 4, yes, no, 0, no) \ + \ + SC(189, 52, 50, 1, yes, no, 0, no) \ + SC(190, 52, 50, 2, yes, no, 0, no) \ + SC(191, 52, 50, 3, yes, no, 0, no) \ + SC(192, 52, 50, 4, yes, no, 0, no) \ + \ + SC(193, 53, 51, 1, yes, no, 0, no) \ + SC(194, 53, 51, 2, yes, no, 0, no) \ + SC(195, 53, 51, 3, yes, no, 0, no) \ + SC(196, 53, 51, 4, yes, no, 0, no) \ + \ + SC(197, 54, 52, 1, yes, no, 0, no) \ + SC(198, 54, 52, 2, yes, no, 0, no) \ + SC(199, 54, 52, 3, yes, no, 0, no) \ + SC(200, 54, 52, 4, yes, no, 0, no) \ + \ + SC(201, 55, 53, 1, yes, no, 0, no) \ + SC(202, 55, 53, 2, yes, no, 0, no) \ + SC(203, 55, 53, 3, yes, no, 0, no) \ + SC(204, 55, 53, 4, yes, no, 0, no) \ + \ + SC(205, 56, 54, 1, yes, no, 0, no) \ + SC(206, 56, 54, 2, yes, no, 0, no) \ + SC(207, 56, 54, 3, yes, no, 0, no) \ + SC(208, 56, 54, 4, yes, no, 0, no) \ + \ + SC(209, 57, 55, 1, yes, no, 0, no) \ + SC(210, 57, 55, 2, yes, no, 0, no) \ + SC(211, 57, 55, 3, yes, no, 0, no) \ + SC(212, 57, 55, 4, yes, no, 0, no) \ + \ + SC(213, 58, 56, 1, yes, no, 0, no) \ + SC(214, 58, 56, 2, yes, no, 0, no) \ + SC(215, 58, 56, 3, yes, no, 0, no) \ + SC(216, 58, 56, 4, yes, no, 0, no) \ + \ + SC(217, 59, 57, 1, yes, no, 0, no) \ + SC(218, 59, 57, 2, yes, no, 0, no) \ + SC(219, 59, 57, 3, yes, no, 0, no) \ + SC(220, 59, 57, 4, yes, no, 0, no) \ + \ + SC(221, 60, 58, 1, yes, no, 0, no) \ + SC(222, 60, 58, 2, yes, no, 0, no) \ + SC(223, 60, 58, 3, yes, no, 0, no) \ + SC(224, 60, 58, 4, yes, no, 0, no) \ + \ + SC(225, 61, 59, 1, yes, no, 0, no) \ + SC(226, 61, 59, 2, yes, no, 0, no) \ + SC(227, 61, 59, 3, yes, no, 0, no) \ + SC(228, 61, 59, 4, yes, no, 0, no) \ + \ + SC(229, 62, 60, 1, yes, no, 0, no) \ + SC(230, 62, 60, 2, yes, no, 0, no) \ + SC(231, 62, 60, 3, yes, no, 0, no) \ -#define NBINS 39 -#define SMALL_MAXCLASS 28672 +#define SIZE_CLASSES_DEFINED +#define NTBINS 1 +#define NLBINS 29 +#define NBINS 36 +#define NSIZES 232 +#define LG_CEIL_NSIZES 8 +#define NPSIZES 199 +#define LG_TINY_MAXCLASS 3 +#define LOOKUP_MAXCLASS ((((size_t)1) << 11) + (((size_t)4) << 9)) +#define SMALL_MAXCLASS ((((size_t)1) << 13) + (((size_t)3) << 11)) +#define LG_LARGE_MINCLASS 14 +#define LARGE_MINCLASS (ZU(1) << LG_LARGE_MINCLASS) +#define LARGE_MAXCLASS ((((size_t)1) << 62) + (((size_t)3) << 60)) #endif -#if (LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 16) -#define SIZE_CLASSES_DEFINED -/* SIZE_CLASS(bin, delta, sz) */ -#define SIZE_CLASSES \ - SIZE_CLASS(0, 16, 16) \ - SIZE_CLASS(1, 16, 32) \ - SIZE_CLASS(2, 16, 48) \ - SIZE_CLASS(3, 16, 64) \ - SIZE_CLASS(4, 16, 80) \ - SIZE_CLASS(5, 16, 96) \ - SIZE_CLASS(6, 16, 112) \ - SIZE_CLASS(7, 16, 128) \ - SIZE_CLASS(8, 32, 160) \ - SIZE_CLASS(9, 32, 192) \ - SIZE_CLASS(10, 32, 224) \ - SIZE_CLASS(11, 32, 256) \ - SIZE_CLASS(12, 64, 320) \ - SIZE_CLASS(13, 64, 384) \ - SIZE_CLASS(14, 64, 448) \ - SIZE_CLASS(15, 64, 512) \ - SIZE_CLASS(16, 128, 640) \ - SIZE_CLASS(17, 128, 768) \ - SIZE_CLASS(18, 128, 896) \ - SIZE_CLASS(19, 128, 1024) \ - SIZE_CLASS(20, 256, 1280) \ - SIZE_CLASS(21, 256, 1536) \ - SIZE_CLASS(22, 256, 1792) \ - SIZE_CLASS(23, 256, 2048) \ - SIZE_CLASS(24, 512, 2560) \ - SIZE_CLASS(25, 512, 3072) \ - SIZE_CLASS(26, 512, 3584) \ - SIZE_CLASS(27, 512, 4096) \ - SIZE_CLASS(28, 1024, 5120) \ - SIZE_CLASS(29, 1024, 6144) \ - SIZE_CLASS(30, 1024, 7168) \ - SIZE_CLASS(31, 1024, 8192) \ - SIZE_CLASS(32, 2048, 10240) \ - SIZE_CLASS(33, 2048, 12288) \ - SIZE_CLASS(34, 2048, 14336) \ - SIZE_CLASS(35, 2048, 16384) \ - SIZE_CLASS(36, 4096, 20480) \ - SIZE_CLASS(37, 4096, 24576) \ - SIZE_CLASS(38, 4096, 28672) \ - SIZE_CLASS(39, 4096, 32768) \ - SIZE_CLASS(40, 8192, 40960) \ - SIZE_CLASS(41, 8192, 49152) \ - SIZE_CLASS(42, 8192, 57344) \ +#if (LG_SIZEOF_PTR == 3 && LG_TINY_MIN == 4 && LG_QUANTUM == 4 && LG_PAGE == 12) +#define SIZE_CLASSES \ + /* index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup */ \ + SC( 0, 4, 4, 0, no, yes, 1, 4) \ + SC( 1, 4, 4, 1, no, yes, 1, 4) \ + SC( 2, 4, 4, 2, no, yes, 3, 4) \ + SC( 3, 4, 4, 3, no, yes, 1, 4) \ + \ + SC( 4, 6, 4, 1, no, yes, 5, 4) \ + SC( 5, 6, 4, 2, no, yes, 3, 4) \ + SC( 6, 6, 4, 3, no, yes, 7, 4) \ + SC( 7, 6, 4, 4, no, yes, 1, 4) \ + \ + SC( 8, 7, 5, 1, no, yes, 5, 5) \ + SC( 9, 7, 5, 2, no, yes, 3, 5) \ + SC( 10, 7, 5, 3, no, yes, 7, 5) \ + SC( 11, 7, 5, 4, no, yes, 1, 5) \ + \ + SC( 12, 8, 6, 1, no, yes, 5, 6) \ + SC( 13, 8, 6, 2, no, yes, 3, 6) \ + SC( 14, 8, 6, 3, no, yes, 7, 6) \ + SC( 15, 8, 6, 4, no, yes, 1, 6) \ + \ + SC( 16, 9, 7, 1, no, yes, 5, 7) \ + SC( 17, 9, 7, 2, no, yes, 3, 7) \ + SC( 18, 9, 7, 3, no, yes, 7, 7) \ + SC( 19, 9, 7, 4, no, yes, 1, 7) \ + \ + SC( 20, 10, 8, 1, no, yes, 5, 8) \ + SC( 21, 10, 8, 2, no, yes, 3, 8) \ + SC( 22, 10, 8, 3, no, yes, 7, 8) \ + SC( 23, 10, 8, 4, no, yes, 1, 8) \ + \ + SC( 24, 11, 9, 1, no, yes, 5, 9) \ + SC( 25, 11, 9, 2, no, yes, 3, 9) \ + SC( 26, 11, 9, 3, no, yes, 7, 9) \ + SC( 27, 11, 9, 4, yes, yes, 1, 9) \ + \ + SC( 28, 12, 10, 1, no, yes, 5, no) \ + SC( 29, 12, 10, 2, no, yes, 3, no) \ + SC( 30, 12, 10, 3, no, yes, 7, no) \ + SC( 31, 12, 10, 4, yes, yes, 2, no) \ + \ + SC( 32, 13, 11, 1, no, yes, 5, no) \ + SC( 33, 13, 11, 2, yes, yes, 3, no) \ + SC( 34, 13, 11, 3, no, yes, 7, no) \ + SC( 35, 13, 11, 4, yes, no, 0, no) \ + \ + SC( 36, 14, 12, 1, yes, no, 0, no) \ + SC( 37, 14, 12, 2, yes, no, 0, no) \ + SC( 38, 14, 12, 3, yes, no, 0, no) \ + SC( 39, 14, 12, 4, yes, no, 0, no) \ + \ + SC( 40, 15, 13, 1, yes, no, 0, no) \ + SC( 41, 15, 13, 2, yes, no, 0, no) \ + SC( 42, 15, 13, 3, yes, no, 0, no) \ + SC( 43, 15, 13, 4, yes, no, 0, no) \ + \ + SC( 44, 16, 14, 1, yes, no, 0, no) \ + SC( 45, 16, 14, 2, yes, no, 0, no) \ + SC( 46, 16, 14, 3, yes, no, 0, no) \ + SC( 47, 16, 14, 4, yes, no, 0, no) \ + \ + SC( 48, 17, 15, 1, yes, no, 0, no) \ + SC( 49, 17, 15, 2, yes, no, 0, no) \ + SC( 50, 17, 15, 3, yes, no, 0, no) \ + SC( 51, 17, 15, 4, yes, no, 0, no) \ + \ + SC( 52, 18, 16, 1, yes, no, 0, no) \ + SC( 53, 18, 16, 2, yes, no, 0, no) \ + SC( 54, 18, 16, 3, yes, no, 0, no) \ + SC( 55, 18, 16, 4, yes, no, 0, no) \ + \ + SC( 56, 19, 17, 1, yes, no, 0, no) \ + SC( 57, 19, 17, 2, yes, no, 0, no) \ + SC( 58, 19, 17, 3, yes, no, 0, no) \ + SC( 59, 19, 17, 4, yes, no, 0, no) \ + \ + SC( 60, 20, 18, 1, yes, no, 0, no) \ + SC( 61, 20, 18, 2, yes, no, 0, no) \ + SC( 62, 20, 18, 3, yes, no, 0, no) \ + SC( 63, 20, 18, 4, yes, no, 0, no) \ + \ + SC( 64, 21, 19, 1, yes, no, 0, no) \ + SC( 65, 21, 19, 2, yes, no, 0, no) \ + SC( 66, 21, 19, 3, yes, no, 0, no) \ + SC( 67, 21, 19, 4, yes, no, 0, no) \ + \ + SC( 68, 22, 20, 1, yes, no, 0, no) \ + SC( 69, 22, 20, 2, yes, no, 0, no) \ + SC( 70, 22, 20, 3, yes, no, 0, no) \ + SC( 71, 22, 20, 4, yes, no, 0, no) \ + \ + SC( 72, 23, 21, 1, yes, no, 0, no) \ + SC( 73, 23, 21, 2, yes, no, 0, no) \ + SC( 74, 23, 21, 3, yes, no, 0, no) \ + SC( 75, 23, 21, 4, yes, no, 0, no) \ + \ + SC( 76, 24, 22, 1, yes, no, 0, no) \ + SC( 77, 24, 22, 2, yes, no, 0, no) \ + SC( 78, 24, 22, 3, yes, no, 0, no) \ + SC( 79, 24, 22, 4, yes, no, 0, no) \ + \ + SC( 80, 25, 23, 1, yes, no, 0, no) \ + SC( 81, 25, 23, 2, yes, no, 0, no) \ + SC( 82, 25, 23, 3, yes, no, 0, no) \ + SC( 83, 25, 23, 4, yes, no, 0, no) \ + \ + SC( 84, 26, 24, 1, yes, no, 0, no) \ + SC( 85, 26, 24, 2, yes, no, 0, no) \ + SC( 86, 26, 24, 3, yes, no, 0, no) \ + SC( 87, 26, 24, 4, yes, no, 0, no) \ + \ + SC( 88, 27, 25, 1, yes, no, 0, no) \ + SC( 89, 27, 25, 2, yes, no, 0, no) \ + SC( 90, 27, 25, 3, yes, no, 0, no) \ + SC( 91, 27, 25, 4, yes, no, 0, no) \ + \ + SC( 92, 28, 26, 1, yes, no, 0, no) \ + SC( 93, 28, 26, 2, yes, no, 0, no) \ + SC( 94, 28, 26, 3, yes, no, 0, no) \ + SC( 95, 28, 26, 4, yes, no, 0, no) \ + \ + SC( 96, 29, 27, 1, yes, no, 0, no) \ + SC( 97, 29, 27, 2, yes, no, 0, no) \ + SC( 98, 29, 27, 3, yes, no, 0, no) \ + SC( 99, 29, 27, 4, yes, no, 0, no) \ + \ + SC(100, 30, 28, 1, yes, no, 0, no) \ + SC(101, 30, 28, 2, yes, no, 0, no) \ + SC(102, 30, 28, 3, yes, no, 0, no) \ + SC(103, 30, 28, 4, yes, no, 0, no) \ + \ + SC(104, 31, 29, 1, yes, no, 0, no) \ + SC(105, 31, 29, 2, yes, no, 0, no) \ + SC(106, 31, 29, 3, yes, no, 0, no) \ + SC(107, 31, 29, 4, yes, no, 0, no) \ + \ + SC(108, 32, 30, 1, yes, no, 0, no) \ + SC(109, 32, 30, 2, yes, no, 0, no) \ + SC(110, 32, 30, 3, yes, no, 0, no) \ + SC(111, 32, 30, 4, yes, no, 0, no) \ + \ + SC(112, 33, 31, 1, yes, no, 0, no) \ + SC(113, 33, 31, 2, yes, no, 0, no) \ + SC(114, 33, 31, 3, yes, no, 0, no) \ + SC(115, 33, 31, 4, yes, no, 0, no) \ + \ + SC(116, 34, 32, 1, yes, no, 0, no) \ + SC(117, 34, 32, 2, yes, no, 0, no) \ + SC(118, 34, 32, 3, yes, no, 0, no) \ + SC(119, 34, 32, 4, yes, no, 0, no) \ + \ + SC(120, 35, 33, 1, yes, no, 0, no) \ + SC(121, 35, 33, 2, yes, no, 0, no) \ + SC(122, 35, 33, 3, yes, no, 0, no) \ + SC(123, 35, 33, 4, yes, no, 0, no) \ + \ + SC(124, 36, 34, 1, yes, no, 0, no) \ + SC(125, 36, 34, 2, yes, no, 0, no) \ + SC(126, 36, 34, 3, yes, no, 0, no) \ + SC(127, 36, 34, 4, yes, no, 0, no) \ + \ + SC(128, 37, 35, 1, yes, no, 0, no) \ + SC(129, 37, 35, 2, yes, no, 0, no) \ + SC(130, 37, 35, 3, yes, no, 0, no) \ + SC(131, 37, 35, 4, yes, no, 0, no) \ + \ + SC(132, 38, 36, 1, yes, no, 0, no) \ + SC(133, 38, 36, 2, yes, no, 0, no) \ + SC(134, 38, 36, 3, yes, no, 0, no) \ + SC(135, 38, 36, 4, yes, no, 0, no) \ + \ + SC(136, 39, 37, 1, yes, no, 0, no) \ + SC(137, 39, 37, 2, yes, no, 0, no) \ + SC(138, 39, 37, 3, yes, no, 0, no) \ + SC(139, 39, 37, 4, yes, no, 0, no) \ + \ + SC(140, 40, 38, 1, yes, no, 0, no) \ + SC(141, 40, 38, 2, yes, no, 0, no) \ + SC(142, 40, 38, 3, yes, no, 0, no) \ + SC(143, 40, 38, 4, yes, no, 0, no) \ + \ + SC(144, 41, 39, 1, yes, no, 0, no) \ + SC(145, 41, 39, 2, yes, no, 0, no) \ + SC(146, 41, 39, 3, yes, no, 0, no) \ + SC(147, 41, 39, 4, yes, no, 0, no) \ + \ + SC(148, 42, 40, 1, yes, no, 0, no) \ + SC(149, 42, 40, 2, yes, no, 0, no) \ + SC(150, 42, 40, 3, yes, no, 0, no) \ + SC(151, 42, 40, 4, yes, no, 0, no) \ + \ + SC(152, 43, 41, 1, yes, no, 0, no) \ + SC(153, 43, 41, 2, yes, no, 0, no) \ + SC(154, 43, 41, 3, yes, no, 0, no) \ + SC(155, 43, 41, 4, yes, no, 0, no) \ + \ + SC(156, 44, 42, 1, yes, no, 0, no) \ + SC(157, 44, 42, 2, yes, no, 0, no) \ + SC(158, 44, 42, 3, yes, no, 0, no) \ + SC(159, 44, 42, 4, yes, no, 0, no) \ + \ + SC(160, 45, 43, 1, yes, no, 0, no) \ + SC(161, 45, 43, 2, yes, no, 0, no) \ + SC(162, 45, 43, 3, yes, no, 0, no) \ + SC(163, 45, 43, 4, yes, no, 0, no) \ + \ + SC(164, 46, 44, 1, yes, no, 0, no) \ + SC(165, 46, 44, 2, yes, no, 0, no) \ + SC(166, 46, 44, 3, yes, no, 0, no) \ + SC(167, 46, 44, 4, yes, no, 0, no) \ + \ + SC(168, 47, 45, 1, yes, no, 0, no) \ + SC(169, 47, 45, 2, yes, no, 0, no) \ + SC(170, 47, 45, 3, yes, no, 0, no) \ + SC(171, 47, 45, 4, yes, no, 0, no) \ + \ + SC(172, 48, 46, 1, yes, no, 0, no) \ + SC(173, 48, 46, 2, yes, no, 0, no) \ + SC(174, 48, 46, 3, yes, no, 0, no) \ + SC(175, 48, 46, 4, yes, no, 0, no) \ + \ + SC(176, 49, 47, 1, yes, no, 0, no) \ + SC(177, 49, 47, 2, yes, no, 0, no) \ + SC(178, 49, 47, 3, yes, no, 0, no) \ + SC(179, 49, 47, 4, yes, no, 0, no) \ + \ + SC(180, 50, 48, 1, yes, no, 0, no) \ + SC(181, 50, 48, 2, yes, no, 0, no) \ + SC(182, 50, 48, 3, yes, no, 0, no) \ + SC(183, 50, 48, 4, yes, no, 0, no) \ + \ + SC(184, 51, 49, 1, yes, no, 0, no) \ + SC(185, 51, 49, 2, yes, no, 0, no) \ + SC(186, 51, 49, 3, yes, no, 0, no) \ + SC(187, 51, 49, 4, yes, no, 0, no) \ + \ + SC(188, 52, 50, 1, yes, no, 0, no) \ + SC(189, 52, 50, 2, yes, no, 0, no) \ + SC(190, 52, 50, 3, yes, no, 0, no) \ + SC(191, 52, 50, 4, yes, no, 0, no) \ + \ + SC(192, 53, 51, 1, yes, no, 0, no) \ + SC(193, 53, 51, 2, yes, no, 0, no) \ + SC(194, 53, 51, 3, yes, no, 0, no) \ + SC(195, 53, 51, 4, yes, no, 0, no) \ + \ + SC(196, 54, 52, 1, yes, no, 0, no) \ + SC(197, 54, 52, 2, yes, no, 0, no) \ + SC(198, 54, 52, 3, yes, no, 0, no) \ + SC(199, 54, 52, 4, yes, no, 0, no) \ + \ + SC(200, 55, 53, 1, yes, no, 0, no) \ + SC(201, 55, 53, 2, yes, no, 0, no) \ + SC(202, 55, 53, 3, yes, no, 0, no) \ + SC(203, 55, 53, 4, yes, no, 0, no) \ + \ + SC(204, 56, 54, 1, yes, no, 0, no) \ + SC(205, 56, 54, 2, yes, no, 0, no) \ + SC(206, 56, 54, 3, yes, no, 0, no) \ + SC(207, 56, 54, 4, yes, no, 0, no) \ + \ + SC(208, 57, 55, 1, yes, no, 0, no) \ + SC(209, 57, 55, 2, yes, no, 0, no) \ + SC(210, 57, 55, 3, yes, no, 0, no) \ + SC(211, 57, 55, 4, yes, no, 0, no) \ + \ + SC(212, 58, 56, 1, yes, no, 0, no) \ + SC(213, 58, 56, 2, yes, no, 0, no) \ + SC(214, 58, 56, 3, yes, no, 0, no) \ + SC(215, 58, 56, 4, yes, no, 0, no) \ + \ + SC(216, 59, 57, 1, yes, no, 0, no) \ + SC(217, 59, 57, 2, yes, no, 0, no) \ + SC(218, 59, 57, 3, yes, no, 0, no) \ + SC(219, 59, 57, 4, yes, no, 0, no) \ + \ + SC(220, 60, 58, 1, yes, no, 0, no) \ + SC(221, 60, 58, 2, yes, no, 0, no) \ + SC(222, 60, 58, 3, yes, no, 0, no) \ + SC(223, 60, 58, 4, yes, no, 0, no) \ + \ + SC(224, 61, 59, 1, yes, no, 0, no) \ + SC(225, 61, 59, 2, yes, no, 0, no) \ + SC(226, 61, 59, 3, yes, no, 0, no) \ + SC(227, 61, 59, 4, yes, no, 0, no) \ + \ + SC(228, 62, 60, 1, yes, no, 0, no) \ + SC(229, 62, 60, 2, yes, no, 0, no) \ + SC(230, 62, 60, 3, yes, no, 0, no) \ -#define NBINS 43 -#define SMALL_MAXCLASS 57344 +#define SIZE_CLASSES_DEFINED +#define NTBINS 0 +#define NLBINS 28 +#define NBINS 35 +#define NSIZES 231 +#define LG_CEIL_NSIZES 8 +#define NPSIZES 199 +#define LG_TINY_MAXCLASS "NA" +#define LOOKUP_MAXCLASS ((((size_t)1) << 11) + (((size_t)4) << 9)) +#define SMALL_MAXCLASS ((((size_t)1) << 13) + (((size_t)3) << 11)) +#define LG_LARGE_MINCLASS 14 +#define LARGE_MINCLASS (ZU(1) << LG_LARGE_MINCLASS) +#define LARGE_MAXCLASS ((((size_t)1) << 62) + (((size_t)3) << 60)) #endif #ifndef SIZE_CLASSES_DEFINED @@ -692,30 +1418,11 @@ #endif #undef SIZE_CLASSES_DEFINED /* - * The small_size2bin lookup table uses uint8_t to encode each bin index, so we - * cannot support more than 256 small size classes. Further constrain NBINS to - * 255 to support prof_promote, since all small size classes, plus a "not - * small" size class must be stored in 8 bits of arena_chunk_map_t's bits - * field. + * The size2index_tab lookup table uses uint8_t to encode each bin index, so we + * cannot support more than 256 small size classes. */ -#if (NBINS > 255) +#if (NBINS > 256) # error "Too many small size classes" #endif -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - - -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_SIZE_CLASSES_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/stats.h b/deps/jemalloc/include/jemalloc/internal/stats.h index 27f68e3681..1198779ab9 100644 --- a/deps/jemalloc/include/jemalloc/internal/stats.h +++ b/deps/jemalloc/include/jemalloc/internal/stats.h @@ -1,31 +1,51 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES - -typedef struct tcache_bin_stats_s tcache_bin_stats_t; -typedef struct malloc_bin_stats_s malloc_bin_stats_t; -typedef struct malloc_large_stats_s malloc_large_stats_t; -typedef struct arena_stats_s arena_stats_t; -typedef struct chunk_stats_s chunk_stats_t; +#ifndef JEMALLOC_INTERNAL_STATS_H +#define JEMALLOC_INTERNAL_STATS_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/mutex_prof.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/stats_tsd.h" + +/* OPTION(opt, var_name, default, set_value_to) */ +#define STATS_PRINT_OPTIONS \ + OPTION('J', json, false, true) \ + OPTION('g', general, true, false) \ + OPTION('m', merged, config_stats, false) \ + OPTION('d', destroyed, config_stats, false) \ + OPTION('a', unmerged, config_stats, false) \ + OPTION('b', bins, true, false) \ + OPTION('l', large, true, false) \ + OPTION('x', mutex, true, false) + +enum { +#define OPTION(o, v, d, s) stats_print_option_num_##v, + STATS_PRINT_OPTIONS +#undef OPTION + stats_print_tot_num_options +}; -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS +/* Options for stats_print. */ +extern bool opt_stats_print; +extern char opt_stats_print_opts[stats_print_tot_num_options+1]; -struct tcache_bin_stats_s { - /* - * Number of allocation requests that corresponded to the size of this - * bin. - */ - uint64_t nrequests; -}; +/* Implements je_malloc_stats_print. */ +void stats_print(void (*write_cb)(void *, const char *), void *cbopaque, + const char *opts); -struct malloc_bin_stats_s { - /* - * Current number of bytes allocated, including objects currently - * cached by tcache. - */ - size_t allocated; +/* + * In those architectures that support 64-bit atomics, we use atomic updates for + * our 64-bit values. Otherwise, we use a plain uint64_t and synchronize + * externally. + */ +#ifdef JEMALLOC_ATOMIC_U64 +typedef atomic_u64_t arena_stats_u64_t; +#else +/* Must hold the arena stats mutex while reading atomically. */ +typedef uint64_t arena_stats_u64_t; +#endif +typedef struct malloc_bin_stats_s { /* * Total number of allocation/deallocation requests served directly by * the bin. Note that tcache may allocate an object, then recycle it @@ -42,132 +62,103 @@ struct malloc_bin_stats_s { */ uint64_t nrequests; + /* + * Current number of regions of this size class, including regions + * currently cached by tcache. + */ + size_t curregs; + /* Number of tcache fills from this bin. */ uint64_t nfills; /* Number of tcache flushes to this bin. */ uint64_t nflushes; - /* Total number of runs created for this bin's size class. */ - uint64_t nruns; + /* Total number of slabs created for this bin's size class. */ + uint64_t nslabs; /* - * Total number of runs reused by extracting them from the runs tree for - * this bin's size class. + * Total number of slabs reused by extracting them from the slabs heap + * for this bin's size class. */ - uint64_t reruns; + uint64_t reslabs; - /* Current number of runs in this bin. */ - size_t curruns; -}; + /* Current number of slabs in this bin. */ + size_t curslabs; -struct malloc_large_stats_s { + mutex_prof_data_t mutex_data; +} malloc_bin_stats_t; + +typedef struct malloc_large_stats_s { /* * Total number of allocation/deallocation requests served directly by - * the arena. Note that tcache may allocate an object, then recycle it - * many times, resulting many increments to nrequests, but only one - * each to nmalloc and ndalloc. + * the arena. */ - uint64_t nmalloc; - uint64_t ndalloc; + arena_stats_u64_t nmalloc; + arena_stats_u64_t ndalloc; /* * Number of allocation requests that correspond to this size class. * This includes requests served by tcache, though tcache only * periodically merges into this counter. */ - uint64_t nrequests; - - /* Current number of runs of this size class. */ - size_t curruns; -}; - -struct arena_stats_s { - /* Number of bytes currently mapped. */ - size_t mapped; - - /* - * Total number of purge sweeps, total number of madvise calls made, - * and total pages purged in order to keep dirty unused memory under - * control. - */ - uint64_t npurge; - uint64_t nmadvise; - uint64_t purged; - - /* Per-size-category statistics. */ - size_t allocated_large; - uint64_t nmalloc_large; - uint64_t ndalloc_large; - uint64_t nrequests_large; - - /* - * One element for each possible size class, including sizes that - * overlap with bin size classes. This is necessary because ipalloc() - * sometimes has to use such large objects in order to assure proper - * alignment. - */ - malloc_large_stats_t *lstats; -}; - -struct chunk_stats_s { - /* Number of chunks that were allocated. */ - uint64_t nchunks; + arena_stats_u64_t nrequests; /* Partially derived. */ + + /* Current number of allocations of this size class. */ + size_t curlextents; /* Derived. */ +} malloc_large_stats_t; + +typedef struct decay_stats_s { + /* Total number of purge sweeps. */ + arena_stats_u64_t npurge; + /* Total number of madvise calls made. */ + arena_stats_u64_t nmadvise; + /* Total number of pages purged. */ + arena_stats_u64_t purged; +} decay_stats_t; + +/* + * Arena stats. Note that fields marked "derived" are not directly maintained + * within the arena code; rather their values are derived during stats merge + * requests. + */ +typedef struct arena_stats_s { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_t mtx; +#endif - /* High-water mark for number of chunks allocated. */ - size_t highchunks; + /* Number of bytes currently mapped, excluding retained memory. */ + atomic_zu_t mapped; /* Partially derived. */ /* - * Current number of chunks allocated. This value isn't maintained for - * any other purpose, so keep track of it in order to be able to set - * highchunks. + * Number of unused virtual memory bytes currently retained. Retained + * bytes are technically mapped (though always decommitted or purged), + * but they are excluded from the mapped statistic (above). */ - size_t curchunks; -}; - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -extern bool opt_stats_print; - -extern size_t stats_cactive; + atomic_zu_t retained; /* Derived. */ -void stats_print(void (*write)(void *, const char *), void *cbopaque, - const char *opts); - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES + decay_stats_t decay_dirty; + decay_stats_t decay_muzzy; -#ifndef JEMALLOC_ENABLE_INLINE -size_t stats_cactive_get(void); -void stats_cactive_add(size_t size); -void stats_cactive_sub(size_t size); -#endif + atomic_zu_t base; /* Derived. */ + atomic_zu_t internal; + atomic_zu_t resident; /* Derived. */ -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_STATS_C_)) -JEMALLOC_INLINE size_t -stats_cactive_get(void) -{ + atomic_zu_t allocated_large; /* Derived. */ + arena_stats_u64_t nmalloc_large; /* Derived. */ + arena_stats_u64_t ndalloc_large; /* Derived. */ + arena_stats_u64_t nrequests_large; /* Derived. */ - return (atomic_read_z(&stats_cactive)); -} + /* Number of bytes cached in tcache associated with this arena. */ + atomic_zu_t tcache_bytes; /* Derived. */ -JEMALLOC_INLINE void -stats_cactive_add(size_t size) -{ + mutex_prof_data_t mutex_prof_data[mutex_prof_num_arena_mutexes]; - atomic_add_z(&stats_cactive, size); -} + /* One element for each large size class. */ + malloc_large_stats_t lstats[NSIZES - NBINS]; -JEMALLOC_INLINE void -stats_cactive_sub(size_t size) -{ - - atomic_sub_z(&stats_cactive, size); -} -#endif + /* Arena uptime. */ + nstime_t uptime; +} arena_stats_t; -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_STATS_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/tsd.h b/deps/jemalloc/include/jemalloc/internal/tsd.h index 9fb4a23ec6..155a2ec6c4 100644 --- a/deps/jemalloc/include/jemalloc/internal/tsd.h +++ b/deps/jemalloc/include/jemalloc/internal/tsd.h @@ -1,434 +1,324 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES +#ifndef JEMALLOC_INTERNAL_TSD_H +#define JEMALLOC_INTERNAL_TSD_H -/* Maximum number of malloc_tsd users with cleanup functions. */ -#define MALLOC_TSD_CLEANUPS_MAX 8 +#include "jemalloc/internal/arena_types.h" +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/jemalloc_internal_externs.h" +#include "jemalloc/internal/prof_types.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/rtree_tsd.h" +#include "jemalloc/internal/tcache_types.h" +#include "jemalloc/internal/tcache_structs.h" +#include "jemalloc/internal/util.h" +#include "jemalloc/internal/witness.h" -typedef bool (*malloc_tsd_cleanup_t)(void); - -#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \ - !defined(_WIN32)) -typedef struct tsd_init_block_s tsd_init_block_t; -typedef struct tsd_init_head_s tsd_init_head_t; +/* + * Thread-Specific-Data layout + * --- data accessed on tcache fast path: state, rtree_ctx, stats, prof --- + * s: state + * e: tcache_enabled + * m: thread_allocated (config_stats) + * f: thread_deallocated (config_stats) + * p: prof_tdata (config_prof) + * c: rtree_ctx (rtree cache accessed on deallocation) + * t: tcache + * --- data not accessed on tcache fast path: arena-related fields --- + * d: arenas_tdata_bypass + * r: reentrancy_level + * x: narenas_tdata + * i: iarena + * a: arena + * o: arenas_tdata + * Loading TSD data is on the critical path of basically all malloc operations. + * In particular, tcache and rtree_ctx rely on hot CPU cache to be effective. + * Use a compact layout to reduce cache footprint. + * +--- 64-bit and 64B cacheline; 1B each letter; First byte on the left. ---+ + * |---------------------------- 1st cacheline ----------------------------| + * | sedrxxxx mmmmmmmm ffffffff pppppppp [c * 32 ........ ........ .......] | + * |---------------------------- 2nd cacheline ----------------------------| + * | [c * 64 ........ ........ ........ ........ ........ ........ .......] | + * |---------------------------- 3nd cacheline ----------------------------| + * | [c * 32 ........ ........ .......] iiiiiiii aaaaaaaa oooooooo [t...... | + * +-------------------------------------------------------------------------+ + * Note: the entire tcache is embedded into TSD and spans multiple cachelines. + * + * The last 3 members (i, a and o) before tcache isn't really needed on tcache + * fast path. However we have a number of unused tcache bins and witnesses + * (never touched unless config_debug) at the end of tcache, so we place them + * there to avoid breaking the cachelines and possibly paging in an extra page. + */ +#ifdef JEMALLOC_JET +typedef void (*test_callback_t)(int *); +# define MALLOC_TSD_TEST_DATA_INIT 0x72b65c10 +# define MALLOC_TEST_TSD \ + O(test_data, int, int) \ + O(test_callback, test_callback_t, int) +# define MALLOC_TEST_TSD_INITIALIZER , MALLOC_TSD_TEST_DATA_INIT, NULL +#else +# define MALLOC_TEST_TSD +# define MALLOC_TEST_TSD_INITIALIZER #endif +/* O(name, type, nullable type */ +#define MALLOC_TSD \ + O(tcache_enabled, bool, bool) \ + O(arenas_tdata_bypass, bool, bool) \ + O(reentrancy_level, int8_t, int8_t) \ + O(narenas_tdata, uint32_t, uint32_t) \ + O(thread_allocated, uint64_t, uint64_t) \ + O(thread_deallocated, uint64_t, uint64_t) \ + O(prof_tdata, prof_tdata_t *, prof_tdata_t *) \ + O(rtree_ctx, rtree_ctx_t, rtree_ctx_t) \ + O(iarena, arena_t *, arena_t *) \ + O(arena, arena_t *, arena_t *) \ + O(arenas_tdata, arena_tdata_t *, arena_tdata_t *)\ + O(tcache, tcache_t, tcache_t) \ + O(witness_tsd, witness_tsd_t, witness_tsdn_t) \ + MALLOC_TEST_TSD + +#define TSD_INITIALIZER { \ + tsd_state_uninitialized, \ + TCACHE_ENABLED_ZERO_INITIALIZER, \ + false, \ + 0, \ + 0, \ + 0, \ + 0, \ + NULL, \ + RTREE_CTX_ZERO_INITIALIZER, \ + NULL, \ + NULL, \ + NULL, \ + TCACHE_ZERO_INITIALIZER, \ + WITNESS_TSD_INITIALIZER \ + MALLOC_TEST_TSD_INITIALIZER \ +} + +enum { + tsd_state_nominal = 0, /* Common case --> jnz. */ + tsd_state_nominal_slow = 1, /* Initialized but on slow path. */ + /* the above 2 nominal states should be lower values. */ + tsd_state_nominal_max = 1, /* used for comparison only. */ + tsd_state_minimal_initialized = 2, + tsd_state_purgatory = 3, + tsd_state_reincarnated = 4, + tsd_state_uninitialized = 5 +}; + +/* Manually limit tsd_state_t to a single byte. */ +typedef uint8_t tsd_state_t; + +/* The actual tsd. */ +struct tsd_s { + /* + * The contents should be treated as totally opaque outside the tsd + * module. Access any thread-local state through the getters and + * setters below. + */ + tsd_state_t state; +#define O(n, t, nt) \ + t use_a_getter_or_setter_instead_##n; +MALLOC_TSD +#undef O +}; + /* - * TLS/TSD-agnostic macro-based implementation of thread-specific data. There - * are four macros that support (at least) three use cases: file-private, - * library-private, and library-private inlined. Following is an example - * library-private tsd variable: - * - * In example.h: - * typedef struct { - * int x; - * int y; - * } example_t; - * #define EX_INITIALIZER JEMALLOC_CONCAT({0, 0}) - * malloc_tsd_protos(, example, example_t *) - * malloc_tsd_externs(example, example_t *) - * In example.c: - * malloc_tsd_data(, example, example_t *, EX_INITIALIZER) - * malloc_tsd_funcs(, example, example_t *, EX_INITIALIZER, - * example_tsd_cleanup) - * - * The result is a set of generated functions, e.g.: - * - * bool example_tsd_boot(void) {...} - * example_t **example_tsd_get() {...} - * void example_tsd_set(example_t **val) {...} - * - * Note that all of the functions deal in terms of (a_type *) rather than - * (a_type) so that it is possible to support non-pointer types (unlike - * pthreads TSD). example_tsd_cleanup() is passed an (a_type *) pointer that is - * cast to (void *). This means that the cleanup function needs to cast *and* - * dereference the function argument, e.g.: - * - * void - * example_tsd_cleanup(void *arg) - * { - * example_t *example = *(example_t **)arg; - * - * [...] - * if ([want the cleanup function to be called again]) { - * example_tsd_set(&example); - * } - * } - * - * If example_tsd_set() is called within example_tsd_cleanup(), it will be - * called again. This is similar to how pthreads TSD destruction works, except - * that pthreads only calls the cleanup function again if the value was set to - * non-NULL. + * Wrapper around tsd_t that makes it possible to avoid implicit conversion + * between tsd_t and tsdn_t, where tsdn_t is "nullable" and has to be + * explicitly converted to tsd_t, which is non-nullable. */ +struct tsdn_s { + tsd_t tsd; +}; +#define TSDN_NULL ((tsdn_t *)0) +JEMALLOC_ALWAYS_INLINE tsdn_t * +tsd_tsdn(tsd_t *tsd) { + return (tsdn_t *)tsd; +} -/* malloc_tsd_protos(). */ -#define malloc_tsd_protos(a_attr, a_name, a_type) \ -a_attr bool \ -a_name##_tsd_boot(void); \ -a_attr a_type * \ -a_name##_tsd_get(void); \ -a_attr void \ -a_name##_tsd_set(a_type *val); +JEMALLOC_ALWAYS_INLINE bool +tsdn_null(const tsdn_t *tsdn) { + return tsdn == NULL; +} -/* malloc_tsd_externs(). */ -#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP -#define malloc_tsd_externs(a_name, a_type) \ -extern __thread a_type a_name##_tls; \ -extern __thread bool a_name##_initialized; \ -extern bool a_name##_booted; -#elif (defined(JEMALLOC_TLS)) -#define malloc_tsd_externs(a_name, a_type) \ -extern __thread a_type a_name##_tls; \ -extern pthread_key_t a_name##_tsd; \ -extern bool a_name##_booted; -#elif (defined(_WIN32)) -#define malloc_tsd_externs(a_name, a_type) \ -extern DWORD a_name##_tsd; \ -extern bool a_name##_booted; -#else -#define malloc_tsd_externs(a_name, a_type) \ -extern pthread_key_t a_name##_tsd; \ -extern tsd_init_head_t a_name##_tsd_init_head; \ -extern bool a_name##_booted; -#endif +JEMALLOC_ALWAYS_INLINE tsd_t * +tsdn_tsd(tsdn_t *tsdn) { + assert(!tsdn_null(tsdn)); + + return &tsdn->tsd; +} + +void *malloc_tsd_malloc(size_t size); +void malloc_tsd_dalloc(void *wrapper); +void malloc_tsd_cleanup_register(bool (*f)(void)); +tsd_t *malloc_tsd_boot0(void); +void malloc_tsd_boot1(void); +void tsd_cleanup(void *arg); +tsd_t *tsd_fetch_slow(tsd_t *tsd, bool internal); +void tsd_slow_update(tsd_t *tsd); -/* malloc_tsd_data(). */ +/* + * We put the platform-specific data declarations and inlines into their own + * header files to avoid cluttering this file. They define tsd_boot0, + * tsd_boot1, tsd_boot, tsd_booted_get, tsd_get_allocates, tsd_get, and tsd_set. + */ #ifdef JEMALLOC_MALLOC_THREAD_CLEANUP -#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ -a_attr __thread a_type JEMALLOC_TLS_MODEL \ - a_name##_tls = a_initializer; \ -a_attr __thread bool JEMALLOC_TLS_MODEL \ - a_name##_initialized = false; \ -a_attr bool a_name##_booted = false; +#include "jemalloc/internal/tsd_malloc_thread_cleanup.h" #elif (defined(JEMALLOC_TLS)) -#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ -a_attr __thread a_type JEMALLOC_TLS_MODEL \ - a_name##_tls = a_initializer; \ -a_attr pthread_key_t a_name##_tsd; \ -a_attr bool a_name##_booted = false; +#include "jemalloc/internal/tsd_tls.h" #elif (defined(_WIN32)) -#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ -a_attr DWORD a_name##_tsd; \ -a_attr bool a_name##_booted = false; +#include "jemalloc/internal/tsd_win.h" #else -#define malloc_tsd_data(a_attr, a_name, a_type, a_initializer) \ -a_attr pthread_key_t a_name##_tsd; \ -a_attr tsd_init_head_t a_name##_tsd_init_head = { \ - ql_head_initializer(blocks), \ - MALLOC_MUTEX_INITIALIZER \ -}; \ -a_attr bool a_name##_booted = false; +#include "jemalloc/internal/tsd_generic.h" #endif -/* malloc_tsd_funcs(). */ -#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP -#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ - a_cleanup) \ -/* Initialization/cleanup. */ \ -a_attr bool \ -a_name##_tsd_cleanup_wrapper(void) \ -{ \ - \ - if (a_name##_initialized) { \ - a_name##_initialized = false; \ - a_cleanup(&a_name##_tls); \ - } \ - return (a_name##_initialized); \ -} \ -a_attr bool \ -a_name##_tsd_boot(void) \ -{ \ - \ - if (a_cleanup != malloc_tsd_no_cleanup) { \ - malloc_tsd_cleanup_register( \ - &a_name##_tsd_cleanup_wrapper); \ - } \ - a_name##_booted = true; \ - return (false); \ -} \ -/* Get/set. */ \ -a_attr a_type * \ -a_name##_tsd_get(void) \ -{ \ - \ - assert(a_name##_booted); \ - return (&a_name##_tls); \ -} \ -a_attr void \ -a_name##_tsd_set(a_type *val) \ -{ \ - \ - assert(a_name##_booted); \ - a_name##_tls = (*val); \ - if (a_cleanup != malloc_tsd_no_cleanup) \ - a_name##_initialized = true; \ +/* + * tsd_foop_get_unsafe(tsd) returns a pointer to the thread-local instance of + * foo. This omits some safety checks, and so can be used during tsd + * initialization and cleanup. + */ +#define O(n, t, nt) \ +JEMALLOC_ALWAYS_INLINE t * \ +tsd_##n##p_get_unsafe(tsd_t *tsd) { \ + return &tsd->use_a_getter_or_setter_instead_##n; \ } -#elif (defined(JEMALLOC_TLS)) -#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ - a_cleanup) \ -/* Initialization/cleanup. */ \ -a_attr bool \ -a_name##_tsd_boot(void) \ -{ \ - \ - if (a_cleanup != malloc_tsd_no_cleanup) { \ - if (pthread_key_create(&a_name##_tsd, a_cleanup) != 0) \ - return (true); \ - } \ - a_name##_booted = true; \ - return (false); \ -} \ -/* Get/set. */ \ -a_attr a_type * \ -a_name##_tsd_get(void) \ -{ \ - \ - assert(a_name##_booted); \ - return (&a_name##_tls); \ -} \ -a_attr void \ -a_name##_tsd_set(a_type *val) \ -{ \ - \ - assert(a_name##_booted); \ - a_name##_tls = (*val); \ - if (a_cleanup != malloc_tsd_no_cleanup) { \ - if (pthread_setspecific(a_name##_tsd, \ - (void *)(&a_name##_tls))) { \ - malloc_write("<jemalloc>: Error" \ - " setting TSD for "#a_name"\n"); \ - if (opt_abort) \ - abort(); \ - } \ - } \ +MALLOC_TSD +#undef O + +/* tsd_foop_get(tsd) returns a pointer to the thread-local instance of foo. */ +#define O(n, t, nt) \ +JEMALLOC_ALWAYS_INLINE t * \ +tsd_##n##p_get(tsd_t *tsd) { \ + assert(tsd->state == tsd_state_nominal || \ + tsd->state == tsd_state_nominal_slow || \ + tsd->state == tsd_state_reincarnated || \ + tsd->state == tsd_state_minimal_initialized); \ + return tsd_##n##p_get_unsafe(tsd); \ } -#elif (defined(_WIN32)) -#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ - a_cleanup) \ -/* Data structure. */ \ -typedef struct { \ - bool initialized; \ - a_type val; \ -} a_name##_tsd_wrapper_t; \ -/* Initialization/cleanup. */ \ -a_attr bool \ -a_name##_tsd_cleanup_wrapper(void) \ -{ \ - a_name##_tsd_wrapper_t *wrapper; \ - \ - wrapper = (a_name##_tsd_wrapper_t *) TlsGetValue(a_name##_tsd); \ - if (wrapper == NULL) \ - return (false); \ - if (a_cleanup != malloc_tsd_no_cleanup && \ - wrapper->initialized) { \ - a_type val = wrapper->val; \ - a_type tsd_static_data = a_initializer; \ - wrapper->initialized = false; \ - wrapper->val = tsd_static_data; \ - a_cleanup(&val); \ - if (wrapper->initialized) { \ - /* Trigger another cleanup round. */ \ - return (true); \ - } \ - } \ - malloc_tsd_dalloc(wrapper); \ - return (false); \ -} \ -a_attr bool \ -a_name##_tsd_boot(void) \ -{ \ - \ - a_name##_tsd = TlsAlloc(); \ - if (a_name##_tsd == TLS_OUT_OF_INDEXES) \ - return (true); \ - if (a_cleanup != malloc_tsd_no_cleanup) { \ - malloc_tsd_cleanup_register( \ - &a_name##_tsd_cleanup_wrapper); \ - } \ - a_name##_booted = true; \ - return (false); \ -} \ -/* Get/set. */ \ -a_attr a_name##_tsd_wrapper_t * \ -a_name##_tsd_get_wrapper(void) \ -{ \ - a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \ - TlsGetValue(a_name##_tsd); \ - \ - if (wrapper == NULL) { \ - wrapper = (a_name##_tsd_wrapper_t *) \ - malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \ - if (wrapper == NULL) { \ - malloc_write("<jemalloc>: Error allocating" \ - " TSD for "#a_name"\n"); \ - abort(); \ - } else { \ - static a_type tsd_static_data = a_initializer; \ - wrapper->initialized = false; \ - wrapper->val = tsd_static_data; \ - } \ - if (!TlsSetValue(a_name##_tsd, (void *)wrapper)) { \ - malloc_write("<jemalloc>: Error setting" \ - " TSD for "#a_name"\n"); \ - abort(); \ - } \ +MALLOC_TSD +#undef O + +/* + * tsdn_foop_get(tsdn) returns either the thread-local instance of foo (if tsdn + * isn't NULL), or NULL (if tsdn is NULL), cast to the nullable pointer type. + */ +#define O(n, t, nt) \ +JEMALLOC_ALWAYS_INLINE nt * \ +tsdn_##n##p_get(tsdn_t *tsdn) { \ + if (tsdn_null(tsdn)) { \ + return NULL; \ } \ - return (wrapper); \ -} \ -a_attr a_type * \ -a_name##_tsd_get(void) \ -{ \ - a_name##_tsd_wrapper_t *wrapper; \ - \ - assert(a_name##_booted); \ - wrapper = a_name##_tsd_get_wrapper(); \ - return (&wrapper->val); \ -} \ -a_attr void \ -a_name##_tsd_set(a_type *val) \ -{ \ - a_name##_tsd_wrapper_t *wrapper; \ - \ - assert(a_name##_booted); \ - wrapper = a_name##_tsd_get_wrapper(); \ - wrapper->val = *(val); \ - if (a_cleanup != malloc_tsd_no_cleanup) \ - wrapper->initialized = true; \ + tsd_t *tsd = tsdn_tsd(tsdn); \ + return (nt *)tsd_##n##p_get(tsd); \ } -#else -#define malloc_tsd_funcs(a_attr, a_name, a_type, a_initializer, \ - a_cleanup) \ -/* Data structure. */ \ -typedef struct { \ - bool initialized; \ - a_type val; \ -} a_name##_tsd_wrapper_t; \ -/* Initialization/cleanup. */ \ -a_attr void \ -a_name##_tsd_cleanup_wrapper(void *arg) \ -{ \ - a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *)arg;\ - \ - if (a_cleanup != malloc_tsd_no_cleanup && \ - wrapper->initialized) { \ - wrapper->initialized = false; \ - a_cleanup(&wrapper->val); \ - if (wrapper->initialized) { \ - /* Trigger another cleanup round. */ \ - if (pthread_setspecific(a_name##_tsd, \ - (void *)wrapper)) { \ - malloc_write("<jemalloc>: Error" \ - " setting TSD for "#a_name"\n"); \ - if (opt_abort) \ - abort(); \ - } \ - return; \ - } \ - } \ - malloc_tsd_dalloc(wrapper); \ -} \ -a_attr bool \ -a_name##_tsd_boot(void) \ -{ \ - \ - if (pthread_key_create(&a_name##_tsd, \ - a_name##_tsd_cleanup_wrapper) != 0) \ - return (true); \ - a_name##_booted = true; \ - return (false); \ -} \ -/* Get/set. */ \ -a_attr a_name##_tsd_wrapper_t * \ -a_name##_tsd_get_wrapper(void) \ -{ \ - a_name##_tsd_wrapper_t *wrapper = (a_name##_tsd_wrapper_t *) \ - pthread_getspecific(a_name##_tsd); \ - \ - if (wrapper == NULL) { \ - tsd_init_block_t block; \ - wrapper = tsd_init_check_recursion( \ - &a_name##_tsd_init_head, &block); \ - if (wrapper) \ - return (wrapper); \ - wrapper = (a_name##_tsd_wrapper_t *) \ - malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \ - block.data = wrapper; \ - if (wrapper == NULL) { \ - malloc_write("<jemalloc>: Error allocating" \ - " TSD for "#a_name"\n"); \ - abort(); \ - } else { \ - static a_type tsd_static_data = a_initializer; \ - wrapper->initialized = false; \ - wrapper->val = tsd_static_data; \ - } \ - if (pthread_setspecific(a_name##_tsd, \ - (void *)wrapper)) { \ - malloc_write("<jemalloc>: Error setting" \ - " TSD for "#a_name"\n"); \ - abort(); \ - } \ - tsd_init_finish(&a_name##_tsd_init_head, &block); \ - } \ - return (wrapper); \ -} \ -a_attr a_type * \ -a_name##_tsd_get(void) \ -{ \ - a_name##_tsd_wrapper_t *wrapper; \ - \ - assert(a_name##_booted); \ - wrapper = a_name##_tsd_get_wrapper(); \ - return (&wrapper->val); \ -} \ -a_attr void \ -a_name##_tsd_set(a_type *val) \ -{ \ - a_name##_tsd_wrapper_t *wrapper; \ - \ - assert(a_name##_booted); \ - wrapper = a_name##_tsd_get_wrapper(); \ - wrapper->val = *(val); \ - if (a_cleanup != malloc_tsd_no_cleanup) \ - wrapper->initialized = true; \ +MALLOC_TSD +#undef O + +/* tsd_foo_get(tsd) returns the value of the thread-local instance of foo. */ +#define O(n, t, nt) \ +JEMALLOC_ALWAYS_INLINE t \ +tsd_##n##_get(tsd_t *tsd) { \ + return *tsd_##n##p_get(tsd); \ } -#endif +MALLOC_TSD +#undef O -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS +/* tsd_foo_set(tsd, val) updates the thread-local instance of foo to be val. */ +#define O(n, t, nt) \ +JEMALLOC_ALWAYS_INLINE void \ +tsd_##n##_set(tsd_t *tsd, t val) { \ + assert(tsd->state != tsd_state_reincarnated && \ + tsd->state != tsd_state_minimal_initialized); \ + *tsd_##n##p_get(tsd) = val; \ +} +MALLOC_TSD +#undef O -#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \ - !defined(_WIN32)) -struct tsd_init_block_s { - ql_elm(tsd_init_block_t) link; - pthread_t thread; - void *data; -}; -struct tsd_init_head_s { - ql_head(tsd_init_block_t) blocks; - malloc_mutex_t lock; -}; -#endif +JEMALLOC_ALWAYS_INLINE void +tsd_assert_fast(tsd_t *tsd) { + assert(!malloc_slow && tsd_tcache_enabled_get(tsd) && + tsd_reentrancy_level_get(tsd) == 0); +} -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -void *malloc_tsd_malloc(size_t size); -void malloc_tsd_dalloc(void *wrapper); -void malloc_tsd_no_cleanup(void *); -void malloc_tsd_cleanup_register(bool (*f)(void)); -void malloc_tsd_boot(void); -#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \ - !defined(_WIN32)) -void *tsd_init_check_recursion(tsd_init_head_t *head, - tsd_init_block_t *block); -void tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block); -#endif +JEMALLOC_ALWAYS_INLINE bool +tsd_fast(tsd_t *tsd) { + bool fast = (tsd->state == tsd_state_nominal); + if (fast) { + tsd_assert_fast(tsd); + } + + return fast; +} -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_fetch_impl(bool init, bool minimal) { + tsd_t *tsd = tsd_get(init); + + if (!init && tsd_get_allocates() && tsd == NULL) { + return NULL; + } + assert(tsd != NULL); + + if (unlikely(tsd->state != tsd_state_nominal)) { + return tsd_fetch_slow(tsd, minimal); + } + assert(tsd_fast(tsd)); + tsd_assert_fast(tsd); + + return tsd; +} + +/* Get a minimal TSD that requires no cleanup. See comments in free(). */ +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_fetch_min(void) { + return tsd_fetch_impl(true, true); +} + +/* For internal background threads use only. */ +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_internal_fetch(void) { + tsd_t *tsd = tsd_fetch_min(); + /* Use reincarnated state to prevent full initialization. */ + tsd->state = tsd_state_reincarnated; + + return tsd; +} + +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_fetch(void) { + return tsd_fetch_impl(true, false); +} + +static inline bool +tsd_nominal(tsd_t *tsd) { + return (tsd->state <= tsd_state_nominal_max); +} + +JEMALLOC_ALWAYS_INLINE tsdn_t * +tsdn_fetch(void) { + if (!tsd_booted_get()) { + return NULL; + } + + return tsd_tsdn(tsd_fetch_impl(false, false)); +} + +JEMALLOC_ALWAYS_INLINE rtree_ctx_t * +tsd_rtree_ctx(tsd_t *tsd) { + return tsd_rtree_ctxp_get(tsd); +} + +JEMALLOC_ALWAYS_INLINE rtree_ctx_t * +tsdn_rtree_ctx(tsdn_t *tsdn, rtree_ctx_t *fallback) { + /* + * If tsd cannot be accessed, initialize the fallback rtree_ctx and + * return a pointer to it. + */ + if (unlikely(tsdn_null(tsdn))) { + rtree_ctx_data_init(fallback); + return fallback; + } + return tsd_rtree_ctx(tsdn_tsd(tsdn)); +} -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#endif /* JEMALLOC_INTERNAL_TSD_H */ diff --git a/deps/jemalloc/include/jemalloc/internal/util.h b/deps/jemalloc/include/jemalloc/internal/util.h index 6b938f7468..304cb545af 100644 --- a/deps/jemalloc/include/jemalloc/internal/util.h +++ b/deps/jemalloc/include/jemalloc/internal/util.h @@ -1,143 +1,50 @@ -/******************************************************************************/ -#ifdef JEMALLOC_H_TYPES +#ifndef JEMALLOC_INTERNAL_UTIL_H +#define JEMALLOC_INTERNAL_UTIL_H -/* Size of stack-allocated buffer passed to buferror(). */ -#define BUFERROR_BUF 64 +#define UTIL_INLINE static inline -/* - * Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be - * large enough for all possible uses within jemalloc. - */ -#define MALLOC_PRINTF_BUFSIZE 4096 +/* Junk fill patterns. */ +#ifndef JEMALLOC_ALLOC_JUNK +# define JEMALLOC_ALLOC_JUNK ((uint8_t)0xa5) +#endif +#ifndef JEMALLOC_FREE_JUNK +# define JEMALLOC_FREE_JUNK ((uint8_t)0x5a) +#endif /* * Wrap a cpp argument that contains commas such that it isn't broken up into * multiple arguments. */ -#define JEMALLOC_ARG_CONCAT(...) __VA_ARGS__ +#define JEMALLOC_ARG_CONCAT(...) __VA_ARGS__ + +/* cpp macro definition stringification. */ +#define STRINGIFY_HELPER(x) #x +#define STRINGIFY(x) STRINGIFY_HELPER(x) /* * Silence compiler warnings due to uninitialized values. This is used * wherever the compiler fails to recognize that the variable is never used * uninitialized. */ -#ifdef JEMALLOC_CC_SILENCE -# define JEMALLOC_CC_SILENCE_INIT(v) = v -#else -# define JEMALLOC_CC_SILENCE_INIT(v) -#endif - -/* - * Define a custom assert() in order to reduce the chances of deadlock during - * assertion failure. - */ -#ifndef assert -#define assert(e) do { \ - if (config_debug && !(e)) { \ - malloc_printf( \ - "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \ - __FILE__, __LINE__, #e); \ - abort(); \ - } \ -} while (0) -#endif - -#ifndef not_reached -#define not_reached() do { \ - if (config_debug) { \ - malloc_printf( \ - "<jemalloc>: %s:%d: Unreachable code reached\n", \ - __FILE__, __LINE__); \ - abort(); \ - } \ -} while (0) -#endif - -#ifndef not_implemented -#define not_implemented() do { \ - if (config_debug) { \ - malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \ - __FILE__, __LINE__); \ - abort(); \ - } \ -} while (0) -#endif +#define JEMALLOC_CC_SILENCE_INIT(v) = v -#ifndef assert_not_implemented -#define assert_not_implemented(e) do { \ - if (config_debug && !(e)) \ - not_implemented(); \ -} while (0) -#endif - -/* Use to assert a particular configuration, e.g., cassert(config_debug). */ -#define cassert(c) do { \ - if ((c) == false) \ - not_reached(); \ -} while (0) - -#endif /* JEMALLOC_H_TYPES */ -/******************************************************************************/ -#ifdef JEMALLOC_H_STRUCTS - -#endif /* JEMALLOC_H_STRUCTS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_EXTERNS - -int buferror(int err, char *buf, size_t buflen); -uintmax_t malloc_strtoumax(const char *restrict nptr, - char **restrict endptr, int base); -void malloc_write(const char *s); - -/* - * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating - * point math. - */ -int malloc_vsnprintf(char *str, size_t size, const char *format, - va_list ap); -int malloc_snprintf(char *str, size_t size, const char *format, ...) - JEMALLOC_ATTR(format(printf, 3, 4)); -void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, - const char *format, va_list ap); -void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque, - const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4)); -void malloc_printf(const char *format, ...) - JEMALLOC_ATTR(format(printf, 1, 2)); - -#endif /* JEMALLOC_H_EXTERNS */ -/******************************************************************************/ -#ifdef JEMALLOC_H_INLINES - -#ifndef JEMALLOC_ENABLE_INLINE -size_t pow2_ceil(size_t x); -void set_errno(int errnum); -int get_errno(void); +#ifdef __GNUC__ +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) +#else +# define likely(x) !!(x) +# define unlikely(x) !!(x) #endif -#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_)) -/* Compute the smallest power of 2 that is >= x. */ -JEMALLOC_INLINE size_t -pow2_ceil(size_t x) -{ - - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; -#if (LG_SIZEOF_PTR == 3) - x |= x >> 32; +#if !defined(JEMALLOC_INTERNAL_UNREACHABLE) +# error JEMALLOC_INTERNAL_UNREACHABLE should have been defined by configure #endif - x++; - return (x); -} -/* Sets error code */ -JEMALLOC_INLINE void -set_errno(int errnum) -{ +#define unreachable() JEMALLOC_INTERNAL_UNREACHABLE() +/* Set error code. */ +UTIL_INLINE void +set_errno(int errnum) { #ifdef _WIN32 SetLastError(errnum); #else @@ -145,18 +52,16 @@ set_errno(int errnum) #endif } -/* Get last error code */ -JEMALLOC_INLINE int -get_errno(void) -{ - +/* Get last error code. */ +UTIL_INLINE int +get_errno(void) { #ifdef _WIN32 - return (GetLastError()); + return GetLastError(); #else - return (errno); + return errno; #endif } -#endif -#endif /* JEMALLOC_H_INLINES */ -/******************************************************************************/ +#undef UTIL_INLINE + +#endif /* JEMALLOC_INTERNAL_UTIL_H */ diff --git a/deps/jemalloc/include/jemalloc/jemalloc.h b/deps/jemalloc/include/jemalloc/jemalloc.h index b8ea851e52..6ffe5c71b3 100644 --- a/deps/jemalloc/include/jemalloc/jemalloc.h +++ b/deps/jemalloc/include/jemalloc/jemalloc.h @@ -1,45 +1,203 @@ #ifndef JEMALLOC_H_ -#define JEMALLOC_H_ +#define JEMALLOC_H_ #ifdef __cplusplus extern "C" { #endif +/* Defined if __attribute__((...)) syntax is supported. */ +#define JEMALLOC_HAVE_ATTR + +/* Defined if alloc_size attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_ALLOC_SIZE + +/* Defined if format(gnu_printf, ...) attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF + +/* Defined if format(printf, ...) attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF + +/* + * Define overrides for non-standard allocator-related functions if they are + * present on the system. + */ +#define JEMALLOC_OVERRIDE_MEMALIGN +#define JEMALLOC_OVERRIDE_VALLOC + +/* + * At least Linux omits the "const" in: + * + * size_t malloc_usable_size(const void *ptr); + * + * Match the operating system's prototype. + */ +#define JEMALLOC_USABLE_SIZE_CONST + +/* + * If defined, specify throw() for the public function prototypes when compiling + * with C++. The only justification for this is to match the prototypes that + * glibc defines. + */ +#define JEMALLOC_USE_CXX_THROW + +#ifdef _MSC_VER +# ifdef _WIN64 +# define LG_SIZEOF_PTR_WIN 3 +# else +# define LG_SIZEOF_PTR_WIN 2 +# endif +#endif + +/* + * Name mangling for public symbols is controlled by --with-mangling and + * --with-jemalloc-prefix. With default settings the je_ prefix is stripped by + * these macro definitions. + */ +#ifndef JEMALLOC_NO_RENAME +# define je_aligned_alloc aligned_alloc +# define je_calloc calloc +# define je_dallocx dallocx +# define je_free free +# define je_mallctl mallctl +# define je_mallctlbymib mallctlbymib +# define je_mallctlnametomib mallctlnametomib +# define je_malloc malloc +# define je_malloc_conf malloc_conf +# define je_malloc_message malloc_message +# define je_malloc_stats_print malloc_stats_print +# define je_malloc_usable_size malloc_usable_size +# define je_mallocx mallocx +# define je_nallocx nallocx +# define je_posix_memalign posix_memalign +# define je_rallocx rallocx +# define je_realloc realloc +# define je_sallocx sallocx +# define je_sdallocx sdallocx +# define je_xallocx xallocx +# define je_memalign memalign +# define je_valloc valloc +#endif + +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> #include <limits.h> #include <strings.h> -#define JEMALLOC_VERSION "3.6.0-0-g46c0af68bd248b04df75e4f92d5fb804c3d75340" -#define JEMALLOC_VERSION_MAJOR 3 -#define JEMALLOC_VERSION_MINOR 6 -#define JEMALLOC_VERSION_BUGFIX 0 -#define JEMALLOC_VERSION_NREV 0 -#define JEMALLOC_VERSION_GID "46c0af68bd248b04df75e4f92d5fb804c3d75340" +#define JEMALLOC_VERSION "5.0.1-0-g896ed3a8b3f41998d4fb4d625d30ac63ef2d51fb" +#define JEMALLOC_VERSION_MAJOR 5 +#define JEMALLOC_VERSION_MINOR 0 +#define JEMALLOC_VERSION_BUGFIX 1 +#define JEMALLOC_VERSION_NREV 0 +#define JEMALLOC_VERSION_GID "896ed3a8b3f41998d4fb4d625d30ac63ef2d51fb" + +#define MALLOCX_LG_ALIGN(la) ((int)(la)) +#if LG_SIZEOF_PTR == 2 +# define MALLOCX_ALIGN(a) ((int)(ffs((int)(a))-1)) +#else +# define MALLOCX_ALIGN(a) \ + ((int)(((size_t)(a) < (size_t)INT_MAX) ? ffs((int)(a))-1 : \ + ffs((int)(((size_t)(a))>>32))+31)) +#endif +#define MALLOCX_ZERO ((int)0x40) +/* + * Bias tcache index bits so that 0 encodes "automatic tcache management", and 1 + * encodes MALLOCX_TCACHE_NONE. + */ +#define MALLOCX_TCACHE(tc) ((int)(((tc)+2) << 8)) +#define MALLOCX_TCACHE_NONE MALLOCX_TCACHE(-1) +/* + * Bias arena index bits so that 0 encodes "use an automatically chosen arena". + */ +#define MALLOCX_ARENA(a) ((((int)(a))+1) << 20) + +/* + * Use as arena index in "arena.<i>.{purge,decay,dss}" and + * "stats.arenas.<i>.*" mallctl interfaces to select all arenas. This + * definition is intentionally specified in raw decimal format to support + * cpp-based string concatenation, e.g. + * + * #define STRINGIFY_HELPER(x) #x + * #define STRINGIFY(x) STRINGIFY_HELPER(x) + * + * mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", NULL, NULL, NULL, + * 0); + */ +#define MALLCTL_ARENAS_ALL 4096 +/* + * Use as arena index in "stats.arenas.<i>.*" mallctl interfaces to select + * destroyed arenas. + */ +#define MALLCTL_ARENAS_DESTROYED 4097 -# define MALLOCX_LG_ALIGN(la) (la) -# if LG_SIZEOF_PTR == 2 -# define MALLOCX_ALIGN(a) (ffs(a)-1) +#if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW) +# define JEMALLOC_CXX_THROW throw() +#else +# define JEMALLOC_CXX_THROW +#endif + +#if defined(_MSC_VER) +# define JEMALLOC_ATTR(s) +# define JEMALLOC_ALIGNED(s) __declspec(align(s)) +# define JEMALLOC_ALLOC_SIZE(s) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) +# ifndef JEMALLOC_EXPORT +# ifdef DLLEXPORT +# define JEMALLOC_EXPORT __declspec(dllexport) +# else +# define JEMALLOC_EXPORT __declspec(dllimport) +# endif +# endif +# define JEMALLOC_FORMAT_PRINTF(s, i) +# define JEMALLOC_NOINLINE __declspec(noinline) +# ifdef __cplusplus +# define JEMALLOC_NOTHROW __declspec(nothrow) +# else +# define JEMALLOC_NOTHROW +# endif +# define JEMALLOC_SECTION(s) __declspec(allocate(s)) +# define JEMALLOC_RESTRICT_RETURN __declspec(restrict) +# if _MSC_VER >= 1900 && !defined(__EDG__) +# define JEMALLOC_ALLOCATOR __declspec(allocator) +# else +# define JEMALLOC_ALLOCATOR +# endif +#elif defined(JEMALLOC_HAVE_ATTR) +# define JEMALLOC_ATTR(s) __attribute__((s)) +# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) +# ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE +# define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s)) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2)) # else -# define MALLOCX_ALIGN(a) \ - ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31) +# define JEMALLOC_ALLOC_SIZE(s) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) +# endif +# ifndef JEMALLOC_EXPORT +# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) # endif -# define MALLOCX_ZERO ((int)0x40) -/* Bias arena index bits so that 0 encodes "MALLOCX_ARENA() unspecified". */ -# define MALLOCX_ARENA(a) ((int)(((a)+1) << 8)) - -#ifdef JEMALLOC_EXPERIMENTAL -# define ALLOCM_LG_ALIGN(la) (la) -# if LG_SIZEOF_PTR == 2 -# define ALLOCM_ALIGN(a) (ffs(a)-1) +# ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF +# define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i)) +# elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF) +# define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i)) # else -# define ALLOCM_ALIGN(a) \ - ((a < (size_t)INT_MAX) ? ffs(a)-1 : ffs(a>>32)+31) +# define JEMALLOC_FORMAT_PRINTF(s, i) # endif -# define ALLOCM_ZERO ((int)0x40) -# define ALLOCM_NO_MOVE ((int)0x80) -/* Bias arena index bits so that 0 encodes "ALLOCM_ARENA() unspecified". */ -# define ALLOCM_ARENA(a) ((int)(((a)+1) << 8)) -# define ALLOCM_SUCCESS 0 -# define ALLOCM_ERR_OOM 1 -# define ALLOCM_ERR_NOT_MOVED 2 +# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) +# define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow) +# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) +# define JEMALLOC_RESTRICT_RETURN +# define JEMALLOC_ALLOCATOR +#else +# define JEMALLOC_ATTR(s) +# define JEMALLOC_ALIGNED(s) +# define JEMALLOC_ALLOC_SIZE(s) +# define JEMALLOC_ALLOC_SIZE2(s1, s2) +# define JEMALLOC_EXPORT +# define JEMALLOC_FORMAT_PRINTF(s, i) +# define JEMALLOC_NOINLINE +# define JEMALLOC_NOTHROW +# define JEMALLOC_SECTION(s) +# define JEMALLOC_RESTRICT_RETURN +# define JEMALLOC_ALLOCATOR #endif /* @@ -51,55 +209,141 @@ extern JEMALLOC_EXPORT const char *je_malloc_conf; extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque, const char *s); -JEMALLOC_EXPORT void *je_malloc(size_t size) JEMALLOC_ATTR(malloc); -JEMALLOC_EXPORT void *je_calloc(size_t num, size_t size) - JEMALLOC_ATTR(malloc); -JEMALLOC_EXPORT int je_posix_memalign(void **memptr, size_t alignment, - size_t size) JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT void *je_aligned_alloc(size_t alignment, size_t size) - JEMALLOC_ATTR(malloc); -JEMALLOC_EXPORT void *je_realloc(void *ptr, size_t size); -JEMALLOC_EXPORT void je_free(void *ptr); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_malloc(size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_calloc(size_t num, size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2); +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_posix_memalign(void **memptr, + size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_aligned_alloc(size_t alignment, + size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) + JEMALLOC_ALLOC_SIZE(2); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_realloc(void *ptr, size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free(void *ptr) + JEMALLOC_CXX_THROW; -JEMALLOC_EXPORT void *je_mallocx(size_t size, int flags); -JEMALLOC_EXPORT void *je_rallocx(void *ptr, size_t size, int flags); -JEMALLOC_EXPORT size_t je_xallocx(void *ptr, size_t size, size_t extra, +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_mallocx(size_t size, int flags) + JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_rallocx(void *ptr, size_t size, + int flags) JEMALLOC_ALLOC_SIZE(2); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_xallocx(void *ptr, size_t size, + size_t extra, int flags); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_sallocx(const void *ptr, + int flags) JEMALLOC_ATTR(pure); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_dallocx(void *ptr, int flags); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_sdallocx(void *ptr, size_t size, int flags); -JEMALLOC_EXPORT size_t je_sallocx(const void *ptr, int flags); -JEMALLOC_EXPORT void je_dallocx(void *ptr, int flags); -JEMALLOC_EXPORT size_t je_nallocx(size_t size, int flags); - -JEMALLOC_EXPORT int je_mallctl(const char *name, void *oldp, - size_t *oldlenp, void *newp, size_t newlen); -JEMALLOC_EXPORT int je_mallctlnametomib(const char *name, size_t *mibp, - size_t *miblenp); -JEMALLOC_EXPORT int je_mallctlbymib(const size_t *mib, size_t miblen, +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_nallocx(size_t size, int flags) + JEMALLOC_ATTR(pure); + +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen); -JEMALLOC_EXPORT void je_malloc_stats_print(void (*write_cb)(void *, - const char *), void *je_cbopaque, const char *opts); -JEMALLOC_EXPORT size_t je_malloc_usable_size( - JEMALLOC_USABLE_SIZE_CONST void *ptr); +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlnametomib(const char *name, + size_t *mibp, size_t *miblenp); +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlbymib(const size_t *mib, + size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen); +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_malloc_stats_print( + void (*write_cb)(void *, const char *), void *je_cbopaque, + const char *opts); +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_usable_size( + JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW; #ifdef JEMALLOC_OVERRIDE_MEMALIGN -JEMALLOC_EXPORT void * je_memalign(size_t alignment, size_t size) - JEMALLOC_ATTR(malloc); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_memalign(size_t alignment, size_t size) + JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); #endif #ifdef JEMALLOC_OVERRIDE_VALLOC -JEMALLOC_EXPORT void * je_valloc(size_t size) JEMALLOC_ATTR(malloc); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN + void JEMALLOC_NOTHROW *je_valloc(size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(malloc); #endif -#ifdef JEMALLOC_EXPERIMENTAL -JEMALLOC_EXPORT int je_allocm(void **ptr, size_t *rsize, size_t size, - int flags) JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int je_rallocm(void **ptr, size_t *rsize, size_t size, - size_t extra, int flags) JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int je_sallocm(const void *ptr, size_t *rsize, int flags) - JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int je_dallocm(void *ptr, int flags) - JEMALLOC_ATTR(nonnull(1)); -JEMALLOC_EXPORT int je_nallocm(size_t *rsize, size_t size, int flags); -#endif +typedef struct extent_hooks_s extent_hooks_t; + +/* + * void * + * extent_alloc(extent_hooks_t *extent_hooks, void *new_addr, size_t size, + * size_t alignment, bool *zero, bool *commit, unsigned arena_ind); + */ +typedef void *(extent_alloc_t)(extent_hooks_t *, void *, size_t, size_t, bool *, + bool *, unsigned); + +/* + * bool + * extent_dalloc(extent_hooks_t *extent_hooks, void *addr, size_t size, + * bool committed, unsigned arena_ind); + */ +typedef bool (extent_dalloc_t)(extent_hooks_t *, void *, size_t, bool, + unsigned); + +/* + * void + * extent_destroy(extent_hooks_t *extent_hooks, void *addr, size_t size, + * bool committed, unsigned arena_ind); + */ +typedef void (extent_destroy_t)(extent_hooks_t *, void *, size_t, bool, + unsigned); + +/* + * bool + * extent_commit(extent_hooks_t *extent_hooks, void *addr, size_t size, + * size_t offset, size_t length, unsigned arena_ind); + */ +typedef bool (extent_commit_t)(extent_hooks_t *, void *, size_t, size_t, size_t, + unsigned); + +/* + * bool + * extent_decommit(extent_hooks_t *extent_hooks, void *addr, size_t size, + * size_t offset, size_t length, unsigned arena_ind); + */ +typedef bool (extent_decommit_t)(extent_hooks_t *, void *, size_t, size_t, + size_t, unsigned); + +/* + * bool + * extent_purge(extent_hooks_t *extent_hooks, void *addr, size_t size, + * size_t offset, size_t length, unsigned arena_ind); + */ +typedef bool (extent_purge_t)(extent_hooks_t *, void *, size_t, size_t, size_t, + unsigned); + +/* + * bool + * extent_split(extent_hooks_t *extent_hooks, void *addr, size_t size, + * size_t size_a, size_t size_b, bool committed, unsigned arena_ind); + */ +typedef bool (extent_split_t)(extent_hooks_t *, void *, size_t, size_t, size_t, + bool, unsigned); + +/* + * bool + * extent_merge(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a, + * void *addr_b, size_t size_b, bool committed, unsigned arena_ind); + */ +typedef bool (extent_merge_t)(extent_hooks_t *, void *, size_t, void *, size_t, + bool, unsigned); + +struct extent_hooks_s { + extent_alloc_t *alloc; + extent_dalloc_t *dalloc; + extent_destroy_t *destroy; + extent_commit_t *commit; + extent_decommit_t *decommit; + extent_purge_t *purge_lazy; + extent_purge_t *purge_forced; + extent_split_t *split; + extent_merge_t *merge; +}; /* * By default application code must explicitly refer to mangled symbol names, @@ -112,32 +356,28 @@ JEMALLOC_EXPORT int je_nallocm(size_t *rsize, size_t size, int flags); # ifndef JEMALLOC_NO_DEMANGLE # define JEMALLOC_NO_DEMANGLE # endif -# define malloc_conf je_malloc_conf -# define malloc_message je_malloc_message -# define malloc je_malloc -# define calloc je_calloc -# define posix_memalign je_posix_memalign # define aligned_alloc je_aligned_alloc -# define realloc je_realloc -# define free je_free -# define mallocx je_mallocx -# define rallocx je_rallocx -# define xallocx je_xallocx -# define sallocx je_sallocx +# define calloc je_calloc # define dallocx je_dallocx -# define nallocx je_nallocx +# define free je_free # define mallctl je_mallctl -# define mallctlnametomib je_mallctlnametomib # define mallctlbymib je_mallctlbymib +# define mallctlnametomib je_mallctlnametomib +# define malloc je_malloc +# define malloc_conf je_malloc_conf +# define malloc_message je_malloc_message # define malloc_stats_print je_malloc_stats_print # define malloc_usable_size je_malloc_usable_size +# define mallocx je_mallocx +# define nallocx je_nallocx +# define posix_memalign je_posix_memalign +# define rallocx je_rallocx +# define realloc je_realloc +# define sallocx je_sallocx +# define sdallocx je_sdallocx +# define xallocx je_xallocx # define memalign je_memalign # define valloc je_valloc -# define allocm je_allocm -# define dallocm je_dallocm -# define nallocm je_nallocm -# define rallocm je_rallocm -# define sallocm je_sallocm #endif /* @@ -148,35 +388,31 @@ JEMALLOC_EXPORT int je_nallocm(size_t *rsize, size_t size, int flags); * and/or --with-jemalloc-prefix. */ #ifndef JEMALLOC_NO_DEMANGLE -# undef je_malloc_conf -# undef je_malloc_message -# undef je_malloc -# undef je_calloc -# undef je_posix_memalign # undef je_aligned_alloc -# undef je_realloc -# undef je_free -# undef je_mallocx -# undef je_rallocx -# undef je_xallocx -# undef je_sallocx +# undef je_calloc # undef je_dallocx -# undef je_nallocx +# undef je_free # undef je_mallctl -# undef je_mallctlnametomib # undef je_mallctlbymib +# undef je_mallctlnametomib +# undef je_malloc +# undef je_malloc_conf +# undef je_malloc_message # undef je_malloc_stats_print # undef je_malloc_usable_size +# undef je_mallocx +# undef je_nallocx +# undef je_posix_memalign +# undef je_rallocx +# undef je_realloc +# undef je_sallocx +# undef je_sdallocx +# undef je_xallocx # undef je_memalign # undef je_valloc -# undef je_allocm -# undef je_dallocm -# undef je_nallocm -# undef je_rallocm -# undef je_sallocm #endif #ifdef __cplusplus -}; +} #endif #endif /* JEMALLOC_H_ */ diff --git a/deps/jemalloc/include/msvc_compat/strings.h b/deps/jemalloc/include/msvc_compat/strings.h index c84975b6b8..996f256ce8 100644 --- a/deps/jemalloc/include/msvc_compat/strings.h +++ b/deps/jemalloc/include/msvc_compat/strings.h @@ -3,21 +3,56 @@ /* MSVC doesn't define ffs/ffsl. This dummy strings.h header is provided * for both */ -#include <intrin.h> -#pragma intrinsic(_BitScanForward) -static __forceinline int ffsl(long x) -{ +#ifdef _MSC_VER +# include <intrin.h> +# pragma intrinsic(_BitScanForward) +static __forceinline int ffsl(long x) { unsigned long i; - if (_BitScanForward(&i, x)) - return (i + 1); - return (0); + if (_BitScanForward(&i, x)) { + return i + 1; + } + return 0; } -static __forceinline int ffs(int x) -{ +static __forceinline int ffs(int x) { + return ffsl(x); +} + +# ifdef _M_X64 +# pragma intrinsic(_BitScanForward64) +# endif + +static __forceinline int ffsll(unsigned __int64 x) { + unsigned long i; +#ifdef _M_X64 + if (_BitScanForward64(&i, x)) { + return i + 1; + } + return 0; +#else +// Fallback for 32-bit build where 64-bit version not available +// assuming little endian + union { + unsigned __int64 ll; + unsigned long l[2]; + } s; - return (ffsl(x)); + s.ll = x; + + if (_BitScanForward(&i, s.l[0])) { + return i + 1; + } else if(_BitScanForward(&i, s.l[1])) { + return i + 33; + } + return 0; +#endif } +#else +# define ffsll(x) __builtin_ffsll(x) +# define ffsl(x) __builtin_ffsl(x) +# define ffs(x) __builtin_ffs(x) #endif + +#endif /* strings_h */ diff --git a/deps/jemalloc/jemalloc_defs.h.in.cmake b/deps/jemalloc/jemalloc_defs.h.in.cmake index 04512ccf6a..769aa227c7 100644 --- a/deps/jemalloc/jemalloc_defs.h.in.cmake +++ b/deps/jemalloc/jemalloc_defs.h.in.cmake @@ -1,4 +1,6 @@ -/* include/jemalloc/jemalloc_defs.h. Generated from jemalloc_defs.h.in by configure. */ +/* include/jemalloc/internal/jemalloc_internal_defs.h. Generated from jemalloc_internal_defs.h.in by configure. */ +#ifndef JEMALLOC_INTERNAL_DEFS_H_ +#define JEMALLOC_INTERNAL_DEFS_H_ /* * If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all * public APIs to be prefixed. This makes it possible, with some care, to use @@ -8,30 +10,16 @@ /* #undef JEMALLOC_CPREFIX */ /* - * Name mangling for public symbols is controlled by --with-mangling and - * --with-jemalloc-prefix. With default settings the je_ prefix is stripped by - * these macro definitions. - */ -#define je_malloc_conf malloc_conf -#define je_malloc_message malloc_message -#define je_malloc malloc -#define je_calloc calloc -#define je_posix_memalign posix_memalign -#define je_aligned_alloc aligned_alloc -#define je_realloc realloc -#define je_free free -#define je_malloc_usable_size malloc_usable_size -#define je_malloc_stats_print malloc_stats_print -#define je_mallctl mallctl -#define je_mallctlnametomib mallctlnametomib -#define je_mallctlbymib mallctlbymib -#define je_memalign memalign -#define je_valloc valloc -#define je_allocm allocm -#define je_rallocm rallocm -#define je_sallocm sallocm -#define je_dallocm dallocm -#define je_nallocm nallocm + * Define overrides for non-standard allocator-related functions if they are + * present on the system. + */ +#define JEMALLOC_OVERRIDE___LIBC_CALLOC +#define JEMALLOC_OVERRIDE___LIBC_FREE +#define JEMALLOC_OVERRIDE___LIBC_MALLOC +#define JEMALLOC_OVERRIDE___LIBC_MEMALIGN +#define JEMALLOC_OVERRIDE___LIBC_REALLOC +#define JEMALLOC_OVERRIDE___LIBC_VALLOC +/* #undef JEMALLOC_OVERRIDE___POSIX_MEMALIGN */ /* * JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs. @@ -39,8 +27,7 @@ * from being exported, but for static libraries, naming collisions are a real * possibility. */ -#define JEMALLOC_PRIVATE_NAMESPACE "" -#define JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix) string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix +#define JEMALLOC_PRIVATE_NAMESPACE je_ /* * Hyper-threaded CPUs may need a special instruction inside spin loops in @@ -48,20 +35,27 @@ */ #define CPU_SPINWAIT __asm__ volatile("pause") -/* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */ -/* #undef JEMALLOC_ATOMIC9 */ - /* - * Defined if OSAtomic*() functions are available, as provided by Darwin, and - * documented in the atomic(3) manual page. + * Number of significant bits in virtual addresses. This may be less than the + * total number of bits in a pointer, e.g. on x64, for which the uppermost 16 + * bits are the same as bit 47. */ -/* #undef JEMALLOC_OSATOMIC */ +#define LG_VADDR @JEM_VADDRBITS@ + +/* Defined if C11 atomics are available. */ +#define JEMALLOC_C11_ATOMICS 1 + +/* Defined if GCC __atomic atomics are available. */ +#define JEMALLOC_GCC_ATOMIC_ATOMICS 1 + +/* Defined if GCC __sync atomics are available. */ +#define JEMALLOC_GCC_SYNC_ATOMICS 1 /* * Defined if __sync_add_and_fetch(uint32_t *, uint32_t) and * __sync_sub_and_fetch(uint32_t *, uint32_t) are available, despite * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 not being defined (which means the - * functions are defined in libgcc instead of being inlines) + * functions are defined in libgcc instead of being inlines). */ /* #undef JE_FORCE_SYNC_COMPARE_AND_SWAP_4 */ @@ -69,16 +63,60 @@ * Defined if __sync_add_and_fetch(uint64_t *, uint64_t) and * __sync_sub_and_fetch(uint64_t *, uint64_t) are available, despite * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 not being defined (which means the - * functions are defined in libgcc instead of being inlines) + * functions are defined in libgcc instead of being inlines). */ /* #undef JE_FORCE_SYNC_COMPARE_AND_SWAP_8 */ /* + * Defined if __builtin_clz() and __builtin_clzl() are available. + */ +#define JEMALLOC_HAVE_BUILTIN_CLZ + +/* + * Defined if os_unfair_lock_*() functions are available, as provided by Darwin. + */ +/* #undef JEMALLOC_OS_UNFAIR_LOCK */ + +/* * Defined if OSSpin*() functions are available, as provided by Darwin, and * documented in the spinlock(3) manual page. */ /* #undef JEMALLOC_OSSPIN */ +/* Defined if syscall(2) is usable. */ +#define JEMALLOC_USE_SYSCALL + +/* + * Defined if secure_getenv(3) is available. + */ +#define JEMALLOC_HAVE_SECURE_GETENV + +/* + * Defined if issetugid(2) is available. + */ +/* #undef JEMALLOC_HAVE_ISSETUGID */ + +/* Defined if pthread_atfork(3) is available. */ +#define JEMALLOC_HAVE_PTHREAD_ATFORK + +/* Defined if pthread_setname_np(3) is available. */ +#define JEMALLOC_HAVE_PTHREAD_SETNAME_NP + +/* + * Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available. + */ +#define JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE 1 + +/* + * Defined if clock_gettime(CLOCK_MONOTONIC, ...) is available. + */ +#define JEMALLOC_HAVE_CLOCK_MONOTONIC 1 + +/* + * Defined if mach_absolute_time() is available. + */ +/* #undef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME */ + /* * Defined if _malloc_thread_cleanup() exists. At least in the case of * FreeBSD, pthread_key_create() allocates, which if used during malloc @@ -102,41 +140,9 @@ */ /* #undef JEMALLOC_MUTEX_INIT_CB */ -/* Defined if __attribute__((...)) syntax is supported. */ -#define JEMALLOC_HAVE_ATTR -#ifdef JEMALLOC_HAVE_ATTR -# define JEMALLOC_ATTR(s) __attribute__((s)) -# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default")) -# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) -# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) -# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) -#elif _MSC_VER -# define JEMALLOC_ATTR(s) -# ifdef DLLEXPORT -# define JEMALLOC_EXPORT __declspec(dllexport) -# else -# define JEMALLOC_EXPORT __declspec(dllimport) -# endif -# define JEMALLOC_ALIGNED(s) __declspec(align(s)) -# define JEMALLOC_SECTION(s) __declspec(allocate(s)) -# define JEMALLOC_NOINLINE __declspec(noinline) -#else -# define JEMALLOC_ATTR(s) -# define JEMALLOC_EXPORT -# define JEMALLOC_ALIGNED(s) -# define JEMALLOC_SECTION(s) -# define JEMALLOC_NOINLINE -#endif - -/* Defined if sbrk() is supported. */ -#define JEMALLOC_HAVE_SBRK - /* Non-empty if the tls_model attribute is supported. */ #define JEMALLOC_TLS_MODEL @JEM_TLSMODEL@ -/* JEMALLOC_CC_SILENCE enables code that silences unuseful compiler warnings. */ -/* #undef JEMALLOC_CC_SILENCE */ - /* * JEMALLOC_DEBUG enables assertions and other sanity checks, and disables * inline functions. @@ -144,7 +150,7 @@ /* #undef JEMALLOC_DEBUG */ /* JEMALLOC_STATS enables statistics calculation. */ -#define JEMALLOC_STATS +/* #undef JEMALLOC_STATS */ /* JEMALLOC_PROF enables allocation profiling. */ /* #undef JEMALLOC_PROF */ @@ -159,104 +165,127 @@ /* #undef JEMALLOC_PROF_GCC */ /* - * JEMALLOC_TCACHE enables a thread-specific caching layer for small objects. - * This makes it possible to allocate/deallocate objects without any locking - * when the cache is in the steady state. - */ -#define JEMALLOC_TCACHE - -/* - * JEMALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage + * JEMALLOC_DSS enables use of sbrk(2) to allocate extents from the data storage * segment (DSS). */ -/* #undef JEMALLOC_DSS */ +#define JEMALLOC_DSS -/* Support memory filling (junk/zero/quarantine/redzone). */ +/* Support memory filling (junk/zero). */ #define JEMALLOC_FILL -/* Support the experimental API. */ -#define JEMALLOC_EXPERIMENTAL - /* Support utrace(2)-based tracing. */ /* #undef JEMALLOC_UTRACE */ -/* Support Valgrind. */ -/* #undef JEMALLOC_VALGRIND */ - /* Support optional abort() on OOM. */ /* #undef JEMALLOC_XMALLOC */ /* Support lazy locking (avoid locking unless a second thread is launched). */ /* #undef JEMALLOC_LAZY_LOCK */ -/* One page is 2^STATIC_PAGE_SHIFT bytes. */ -#define STATIC_PAGE_SHIFT 12 +/* + * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size + * classes). + */ +/* #undef LG_QUANTUM */ + +/* One page is 2^LG_PAGE bytes. */ +#define LG_PAGE 12 /* - * If defined, use munmap() to unmap freed chunks, rather than storing them for - * later reuse. This is disabled by default on Linux because common sequences - * of mmap()/munmap() calls will cause virtual memory map holes. + * One huge page is 2^LG_HUGEPAGE bytes. Note that this is defined even if the + * system does not explicitly support huge pages; system calls that require + * explicit huge page support are separately configured. */ -/* #undef JEMALLOC_MUNMAP */ +#define LG_HUGEPAGE 21 /* - * If defined, use mremap(...MREMAP_FIXED...) for huge realloc(). This is - * disabled by default because it is Linux-specific and it will cause virtual - * memory map holes, much like munmap(2) does. + * If defined, adjacent virtual memory mappings with identical attributes + * automatically coalesce, and they fragment when changes are made to subranges. + * This is the normal order of things for mmap()/munmap(), but on Windows + * VirtualAlloc()/VirtualFree() operations must be precisely matched, i.e. + * mappings do *not* coalesce/fragment. */ -/* #undef JEMALLOC_MREMAP */ +#define JEMALLOC_MAPS_COALESCE + +/* + * If defined, retain memory for later reuse by default rather than using e.g. + * munmap() to unmap freed extents. This is enabled on 64-bit Linux because + * common sequences of mmap()/munmap() calls will cause virtual memory map + * holes. + */ +#define JEMALLOC_RETAIN /* TLS is used to map arenas and magazine caches to threads. */ #define JEMALLOC_TLS /* - * JEMALLOC_IVSALLOC enables ivsalloc(), which verifies that pointers reside - * within jemalloc-owned chunks before dereferencing them. + * Used to mark unreachable code to quiet "end of non-void" compiler warnings. + * Don't use this directly; instead use unreachable() from util.h */ -/* #undef JEMALLOC_IVSALLOC */ +#define JEMALLOC_INTERNAL_UNREACHABLE __builtin_unreachable /* - * Define overrides for non-standard allocator-related functions if they - * are present on the system. + * ffs*() functions to use for bitmapping. Don't use these directly; instead, + * use ffs_*() from util.h. */ -#define JEMALLOC_OVERRIDE_MEMALIGN -#define JEMALLOC_OVERRIDE_VALLOC +#define JEMALLOC_INTERNAL_FFSLL __builtin_ffsll +#define JEMALLOC_INTERNAL_FFSL __builtin_ffsl +#define JEMALLOC_INTERNAL_FFS __builtin_ffs /* - * At least Linux omits the "const" in: - * - * size_t malloc_usable_size(const void *ptr); - * - * Match the operating system's prototype. + * If defined, explicitly attempt to more uniformly distribute large allocation + * pointer alignments across all cache indices. */ -#define JEMALLOC_USABLE_SIZE_CONST +#define JEMALLOC_CACHE_OBLIVIOUS /* * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings. */ /* #undef JEMALLOC_ZONE */ -/* #undef JEMALLOC_ZONE_VERSION */ + +/* + * Methods for determining whether the OS overcommits. + * JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY: Linux's + * /proc/sys/vm.overcommit_memory file. + * JEMALLOC_SYSCTL_VM_OVERCOMMIT: FreeBSD's vm.overcommit sysctl. + */ +/* #undef JEMALLOC_SYSCTL_VM_OVERCOMMIT */ +#define JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY + +/* Defined if madvise(2) is available. */ +#define JEMALLOC_HAVE_MADVISE /* * Methods for purging unused pages differ between operating systems. * - * madvise(..., MADV_DONTNEED) : On Linux, this immediately discards pages, + * madvise(..., MADV_FREE) : This marks pages as being unused, such that they + * will be discarded rather than swapped out. + * madvise(..., MADV_DONTNEED) : If JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS is + * defined, this immediately discards pages, * such that new pages will be demand-zeroed if - * the address region is later touched. - * madvise(..., MADV_FREE) : On FreeBSD and Darwin, this marks pages as being - * unused, such that they will be discarded rather - * than swapped out. + * the address region is later touched; + * otherwise this behaves similarly to + * MADV_FREE, though typically with higher + * system overhead. */ +@JEM_MADFREE_DEF@ JEMALLOC_PURGE_MADVISE_FREE #define JEMALLOC_PURGE_MADVISE_DONTNEED -/* #undef JEMALLOC_PURGE_MADVISE_FREE */ +#define JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS 1 /* - * Define if operating system has alloca.h header. + * Defined if transparent huge pages (THPs) are supported via the + * MADV_[NO]HUGEPAGE arguments to madvise(2), and THP support is enabled. */ -#define JEMALLOC_HAS_ALLOCA_H +#define JEMALLOC_THP -/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ -#define LG_SIZEOF_PTR @JEM_SIZEDEF@ +/* Define if operating system has alloca.h header. */ +#define JEMALLOC_HAS_ALLOCA_H 1 + +/* C99 restrict keyword supported. */ +#define JEMALLOC_HAS_RESTRICT 1 + +/* For use by hash code. */ +/* #undef JEMALLOC_BIG_ENDIAN */ /* sizeof(int) == 2^LG_SIZEOF_INT. */ #define LG_SIZEOF_INT 2 @@ -264,11 +293,51 @@ /* sizeof(long) == 2^LG_SIZEOF_LONG. */ #define LG_SIZEOF_LONG @JEM_SIZEDEF@ +/* sizeof(long long) == 2^LG_SIZEOF_LONG_LONG. */ +#define LG_SIZEOF_LONG_LONG 3 + /* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */ #define LG_SIZEOF_INTMAX_T 3 -/* C99 restrict keyword supported. */ -/*#define JEMALLOC_HAS_RESTRICT*/ +/* glibc malloc hooks (__malloc_hook, __realloc_hook, __free_hook). */ +#define JEMALLOC_GLIBC_MALLOC_HOOK + +/* glibc memalign hook. */ +#define JEMALLOC_GLIBC_MEMALIGN_HOOK + +/* pthread support */ +#define JEMALLOC_HAVE_PTHREAD + +/* dlsym() support */ +#define JEMALLOC_HAVE_DLSYM + +/* Adaptive mutex support in pthreads. */ +#define JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP + +/* GNU specific sched_getcpu support */ +#define JEMALLOC_HAVE_SCHED_GETCPU + +/* GNU specific sched_setaffinity support */ +#define JEMALLOC_HAVE_SCHED_SETAFFINITY + +/* + * If defined, all the features necessary for background threads are present. + */ +#define JEMALLOC_BACKGROUND_THREAD 1 + +/* + * If defined, jemalloc symbols are not exported (doesn't work when + * JEMALLOC_PREFIX is not defined). + */ +/* #undef JEMALLOC_EXPORT */ + +/* config.malloc_conf options string. */ +#define JEMALLOC_CONFIG_MALLOC_CONF "" + +/* If defined, jemalloc takes the malloc/free/etc. symbol names. */ +#define JEMALLOC_IS_MALLOC 1 + +/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ +#define LG_SIZEOF_PTR @JEM_SIZEDEF@ -/* JEMALLOC_CODE_COVERAGE enables test code coverage analysis. */ -#undef JEMALLOC_CODE_COVERAGE +#endif /* JEMALLOC_INTERNAL_DEFS_H_ */
\ No newline at end of file diff --git a/deps/jemalloc/src/arena.c b/deps/jemalloc/src/arena.c index dad707b63d..632fce5233 100644 --- a/deps/jemalloc/src/arena.c +++ b/deps/jemalloc/src/arena.c @@ -1,40 +1,57 @@ -#define JEMALLOC_ARENA_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_ARENA_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/rtree.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/util.h" /******************************************************************************/ /* Data. */ -ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT; -arena_bin_info_t arena_bin_info[NBINS]; - -JEMALLOC_ALIGNED(CACHELINE) -const uint8_t small_size2bin[] = { -#define S2B_8(i) i, -#define S2B_16(i) S2B_8(i) S2B_8(i) -#define S2B_32(i) S2B_16(i) S2B_16(i) -#define S2B_64(i) S2B_32(i) S2B_32(i) -#define S2B_128(i) S2B_64(i) S2B_64(i) -#define S2B_256(i) S2B_128(i) S2B_128(i) -#define S2B_512(i) S2B_256(i) S2B_256(i) -#define S2B_1024(i) S2B_512(i) S2B_512(i) -#define S2B_2048(i) S2B_1024(i) S2B_1024(i) -#define S2B_4096(i) S2B_2048(i) S2B_2048(i) -#define S2B_8192(i) S2B_4096(i) S2B_4096(i) -#define SIZE_CLASS(bin, delta, size) \ - S2B_##delta(bin) +/* + * Define names for both unininitialized and initialized phases, so that + * options and mallctl processing are straightforward. + */ +const char *percpu_arena_mode_names[] = { + "percpu", + "phycpu", + "disabled", + "percpu", + "phycpu" +}; +percpu_arena_mode_t opt_percpu_arena = PERCPU_ARENA_DEFAULT; + +ssize_t opt_dirty_decay_ms = DIRTY_DECAY_MS_DEFAULT; +ssize_t opt_muzzy_decay_ms = MUZZY_DECAY_MS_DEFAULT; + +static atomic_zd_t dirty_decay_ms_default; +static atomic_zd_t muzzy_decay_ms_default; + +const arena_bin_info_t arena_bin_info[NBINS] = { +#define BIN_INFO_bin_yes(reg_size, slab_size, nregs) \ + {reg_size, slab_size, nregs, BITMAP_INFO_INITIALIZER(nregs)}, +#define BIN_INFO_bin_no(reg_size, slab_size, nregs) +#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, \ + lg_delta_lookup) \ + BIN_INFO_bin_##bin((1U<<lg_grp) + (ndelta<<lg_delta), \ + (pgs << LG_PAGE), (pgs << LG_PAGE) / ((1U<<lg_grp) + \ + (ndelta<<lg_delta))) SIZE_CLASSES -#undef S2B_8 -#undef S2B_16 -#undef S2B_32 -#undef S2B_64 -#undef S2B_128 -#undef S2B_256 -#undef S2B_512 -#undef S2B_1024 -#undef S2B_2048 -#undef S2B_4096 -#undef S2B_8192 -#undef SIZE_CLASS +#undef BIN_INFO_bin_yes +#undef BIN_INFO_bin_no +#undef SC +}; + +const uint64_t h_steps[SMOOTHSTEP_NSTEPS] = { +#define STEP(step, h, x, y) \ + h, + SMOOTHSTEP +#undef STEP }; /******************************************************************************/ @@ -43,2535 +60,2120 @@ const uint8_t small_size2bin[] = { * definition. */ -static void arena_purge(arena_t *arena, bool all); -static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, - bool cleaned); -static void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, - arena_run_t *run, arena_bin_t *bin); -static void arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, - arena_run_t *run, arena_bin_t *bin); +static void arena_decay_to_limit(tsdn_t *tsdn, arena_t *arena, + arena_decay_t *decay, extents_t *extents, bool all, size_t npages_limit, + bool is_background_thread); +static bool arena_decay_dirty(tsdn_t *tsdn, arena_t *arena, + bool is_background_thread, bool all); +static void arena_dalloc_bin_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, + arena_bin_t *bin); +static void arena_bin_lower_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, + arena_bin_t *bin); /******************************************************************************/ -static inline int -arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) -{ - uintptr_t a_mapelm = (uintptr_t)a; - uintptr_t b_mapelm = (uintptr_t)b; - - assert(a != NULL); - assert(b != NULL); - - return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm)); -} - -/* Generate red-black tree functions. */ -rb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, - u.rb_link, arena_run_comp) - -static inline int -arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) -{ - int ret; - size_t a_size = a->bits & ~PAGE_MASK; - size_t b_size = b->bits & ~PAGE_MASK; - - ret = (a_size > b_size) - (a_size < b_size); - if (ret == 0) { - uintptr_t a_mapelm, b_mapelm; - - if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY) - a_mapelm = (uintptr_t)a; - else { - /* - * Treat keys as though they are lower than anything - * else. - */ - a_mapelm = 0; +static bool +arena_stats_init(tsdn_t *tsdn, arena_stats_t *arena_stats) { + if (config_debug) { + for (size_t i = 0; i < sizeof(arena_stats_t); i++) { + assert(((char *)arena_stats)[i] == 0); } - b_mapelm = (uintptr_t)b; - - ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm); } - - return (ret); +#ifndef JEMALLOC_ATOMIC_U64 + if (malloc_mutex_init(&arena_stats->mtx, "arena_stats", + WITNESS_RANK_ARENA_STATS, malloc_mutex_rank_exclusive)) { + return true; + } +#endif + /* Memory is zeroed, so there is no need to clear stats. */ + return false; } -/* Generate red-black tree functions. */ -rb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, - u.rb_link, arena_avail_comp) - -static inline int -arena_chunk_dirty_comp(arena_chunk_t *a, arena_chunk_t *b) -{ - - assert(a != NULL); - assert(b != NULL); - - /* - * Short-circuit for self comparison. The following comparison code - * would come to the same result, but at the cost of executing the slow - * path. - */ - if (a == b) - return (0); - - /* - * Order such that chunks with higher fragmentation are "less than" - * those with lower fragmentation -- purging order is from "least" to - * "greatest". Fragmentation is measured as: - * - * mean current avail run size - * -------------------------------- - * mean defragmented avail run size - * - * navail - * ----------- - * nruns_avail nruns_avail-nruns_adjac - * = ========================= = ----------------------- - * navail nruns_avail - * ----------------------- - * nruns_avail-nruns_adjac - * - * The following code multiplies away the denominator prior to - * comparison, in order to avoid division. - * - */ - { - size_t a_val = (a->nruns_avail - a->nruns_adjac) * - b->nruns_avail; - size_t b_val = (b->nruns_avail - b->nruns_adjac) * - a->nruns_avail; +static void +arena_stats_lock(tsdn_t *tsdn, arena_stats_t *arena_stats) { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_lock(tsdn, &arena_stats->mtx); +#endif +} - if (a_val < b_val) - return (1); - if (a_val > b_val) - return (-1); - } - /* - * Break ties by chunk address. For fragmented chunks, report lower - * addresses as "lower", so that fragmentation reduction happens first - * at lower addresses. However, use the opposite ordering for - * unfragmented chunks, in order to increase the chances of - * re-allocating dirty runs. - */ - { - uintptr_t a_chunk = (uintptr_t)a; - uintptr_t b_chunk = (uintptr_t)b; - int ret = ((a_chunk > b_chunk) - (a_chunk < b_chunk)); - if (a->nruns_adjac == 0) { - assert(b->nruns_adjac == 0); - ret = -ret; - } - return (ret); - } +static void +arena_stats_unlock(tsdn_t *tsdn, arena_stats_t *arena_stats) { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_unlock(tsdn, &arena_stats->mtx); +#endif } -/* Generate red-black tree functions. */ -rb_gen(static UNUSED, arena_chunk_dirty_, arena_chunk_tree_t, arena_chunk_t, - dirty_link, arena_chunk_dirty_comp) +static uint64_t +arena_stats_read_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, + arena_stats_u64_t *p) { +#ifdef JEMALLOC_ATOMIC_U64 + return atomic_load_u64(p, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + return *p; +#endif +} -static inline bool -arena_avail_adjac_pred(arena_chunk_t *chunk, size_t pageind) -{ - bool ret; +static void +arena_stats_add_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, + arena_stats_u64_t *p, uint64_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + atomic_fetch_add_u64(p, x, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + *p += x; +#endif +} - if (pageind-1 < map_bias) - ret = false; - else { - ret = (arena_mapbits_allocated_get(chunk, pageind-1) == 0); - assert(ret == false || arena_mapbits_dirty_get(chunk, - pageind-1) != arena_mapbits_dirty_get(chunk, pageind)); - } - return (ret); +UNUSED static void +arena_stats_sub_u64(tsdn_t *tsdn, arena_stats_t *arena_stats, + arena_stats_u64_t *p, uint64_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + UNUSED uint64_t r = atomic_fetch_sub_u64(p, x, ATOMIC_RELAXED); + assert(r - x <= r); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + *p -= x; + assert(*p + x >= *p); +#endif } -static inline bool -arena_avail_adjac_succ(arena_chunk_t *chunk, size_t pageind, size_t npages) -{ - bool ret; +/* + * Non-atomically sets *dst += src. *dst needs external synchronization. + * This lets us avoid the cost of a fetch_add when its unnecessary (note that + * the types here are atomic). + */ +static void +arena_stats_accum_u64(arena_stats_u64_t *dst, uint64_t src) { +#ifdef JEMALLOC_ATOMIC_U64 + uint64_t cur_dst = atomic_load_u64(dst, ATOMIC_RELAXED); + atomic_store_u64(dst, src + cur_dst, ATOMIC_RELAXED); +#else + *dst += src; +#endif +} - if (pageind+npages == chunk_npages) - ret = false; - else { - assert(pageind+npages < chunk_npages); - ret = (arena_mapbits_allocated_get(chunk, pageind+npages) == 0); - assert(ret == false || arena_mapbits_dirty_get(chunk, pageind) - != arena_mapbits_dirty_get(chunk, pageind+npages)); - } - return (ret); +static size_t +arena_stats_read_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, atomic_zu_t *p) { +#ifdef JEMALLOC_ATOMIC_U64 + return atomic_load_zu(p, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + return atomic_load_zu(p, ATOMIC_RELAXED); +#endif } -static inline bool -arena_avail_adjac(arena_chunk_t *chunk, size_t pageind, size_t npages) -{ +static void +arena_stats_add_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, atomic_zu_t *p, + size_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + atomic_fetch_add_zu(p, x, ATOMIC_RELAXED); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + size_t cur = atomic_load_zu(p, ATOMIC_RELAXED); + atomic_store_zu(p, cur + x, ATOMIC_RELAXED); +#endif +} - return (arena_avail_adjac_pred(chunk, pageind) || - arena_avail_adjac_succ(chunk, pageind, npages)); +static void +arena_stats_sub_zu(tsdn_t *tsdn, arena_stats_t *arena_stats, atomic_zu_t *p, + size_t x) { +#ifdef JEMALLOC_ATOMIC_U64 + UNUSED size_t r = atomic_fetch_sub_zu(p, x, ATOMIC_RELAXED); + assert(r - x <= r); +#else + malloc_mutex_assert_owner(tsdn, &arena_stats->mtx); + size_t cur = atomic_load_zu(p, ATOMIC_RELAXED); + atomic_store_zu(p, cur - x, ATOMIC_RELAXED); +#endif } +/* Like the _u64 variant, needs an externally synchronized *dst. */ static void -arena_avail_insert(arena_t *arena, arena_chunk_t *chunk, size_t pageind, - size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ) -{ +arena_stats_accum_zu(atomic_zu_t *dst, size_t src) { + size_t cur_dst = atomic_load_zu(dst, ATOMIC_RELAXED); + atomic_store_zu(dst, src + cur_dst, ATOMIC_RELAXED); +} - assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >> - LG_PAGE)); +void +arena_stats_large_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats, + szind_t szind, uint64_t nrequests) { + arena_stats_lock(tsdn, arena_stats); + arena_stats_add_u64(tsdn, arena_stats, &arena_stats->lstats[szind - + NBINS].nrequests, nrequests); + arena_stats_unlock(tsdn, arena_stats); +} - /* - * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be - * removed and reinserted even if the run to be inserted is clean. - */ - if (chunk->ndirty != 0) - arena_chunk_dirty_remove(&arena->chunks_dirty, chunk); +void +arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, size_t size) { + arena_stats_lock(tsdn, arena_stats); + arena_stats_add_zu(tsdn, arena_stats, &arena_stats->mapped, size); + arena_stats_unlock(tsdn, arena_stats); +} - if (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind)) - chunk->nruns_adjac++; - if (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages)) - chunk->nruns_adjac++; - chunk->nruns_avail++; - assert(chunk->nruns_avail > chunk->nruns_adjac); +void +arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, + const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, + size_t *nactive, size_t *ndirty, size_t *nmuzzy) { + *nthreads += arena_nthreads_get(arena, false); + *dss = dss_prec_names[arena_dss_prec_get(arena)]; + *dirty_decay_ms = arena_dirty_decay_ms_get(arena); + *muzzy_decay_ms = arena_muzzy_decay_ms_get(arena); + *nactive += atomic_load_zu(&arena->nactive, ATOMIC_RELAXED); + *ndirty += extents_npages_get(&arena->extents_dirty); + *nmuzzy += extents_npages_get(&arena->extents_muzzy); +} - if (arena_mapbits_dirty_get(chunk, pageind) != 0) { - arena->ndirty += npages; - chunk->ndirty += npages; +void +arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, + const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, + size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats, + malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats) { + cassert(config_stats); + + arena_basic_stats_merge(tsdn, arena, nthreads, dss, dirty_decay_ms, + muzzy_decay_ms, nactive, ndirty, nmuzzy); + + size_t base_allocated, base_resident, base_mapped; + base_stats_get(tsdn, arena->base, &base_allocated, &base_resident, + &base_mapped); + + arena_stats_lock(tsdn, &arena->stats); + + arena_stats_accum_zu(&astats->mapped, base_mapped + + arena_stats_read_zu(tsdn, &arena->stats, &arena->stats.mapped)); + arena_stats_accum_zu(&astats->retained, + extents_npages_get(&arena->extents_retained) << LG_PAGE); + + arena_stats_accum_u64(&astats->decay_dirty.npurge, + arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.decay_dirty.npurge)); + arena_stats_accum_u64(&astats->decay_dirty.nmadvise, + arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.decay_dirty.nmadvise)); + arena_stats_accum_u64(&astats->decay_dirty.purged, + arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.decay_dirty.purged)); + + arena_stats_accum_u64(&astats->decay_muzzy.npurge, + arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.decay_muzzy.npurge)); + arena_stats_accum_u64(&astats->decay_muzzy.nmadvise, + arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.decay_muzzy.nmadvise)); + arena_stats_accum_u64(&astats->decay_muzzy.purged, + arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.decay_muzzy.purged)); + + arena_stats_accum_zu(&astats->base, base_allocated); + arena_stats_accum_zu(&astats->internal, arena_internal_get(arena)); + arena_stats_accum_zu(&astats->resident, base_resident + + (((atomic_load_zu(&arena->nactive, ATOMIC_RELAXED) + + extents_npages_get(&arena->extents_dirty) + + extents_npages_get(&arena->extents_muzzy)) << LG_PAGE))); + + for (szind_t i = 0; i < NSIZES - NBINS; i++) { + uint64_t nmalloc = arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.lstats[i].nmalloc); + arena_stats_accum_u64(&lstats[i].nmalloc, nmalloc); + arena_stats_accum_u64(&astats->nmalloc_large, nmalloc); + + uint64_t ndalloc = arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.lstats[i].ndalloc); + arena_stats_accum_u64(&lstats[i].ndalloc, ndalloc); + arena_stats_accum_u64(&astats->ndalloc_large, ndalloc); + + uint64_t nrequests = arena_stats_read_u64(tsdn, &arena->stats, + &arena->stats.lstats[i].nrequests); + arena_stats_accum_u64(&lstats[i].nrequests, + nmalloc + nrequests); + arena_stats_accum_u64(&astats->nrequests_large, + nmalloc + nrequests); + + assert(nmalloc >= ndalloc); + assert(nmalloc - ndalloc <= SIZE_T_MAX); + size_t curlextents = (size_t)(nmalloc - ndalloc); + lstats[i].curlextents += curlextents; + arena_stats_accum_zu(&astats->allocated_large, + curlextents * sz_index2size(NBINS + i)); + } + + arena_stats_unlock(tsdn, &arena->stats); + + /* tcache_bytes counts currently cached bytes. */ + atomic_store_zu(&astats->tcache_bytes, 0, ATOMIC_RELAXED); + malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); + tcache_t *tcache; + ql_foreach(tcache, &arena->tcache_ql, link) { + szind_t i = 0; + for (; i < NBINS; i++) { + tcache_bin_t *tbin = tcache_small_bin_get(tcache, i); + arena_stats_accum_zu(&astats->tcache_bytes, + tbin->ncached * sz_index2size(i)); + } + for (; i < nhbins; i++) { + tcache_bin_t *tbin = tcache_large_bin_get(tcache, i); + arena_stats_accum_zu(&astats->tcache_bytes, + tbin->ncached * sz_index2size(i)); + } } - if (chunk->ndirty != 0) - arena_chunk_dirty_insert(&arena->chunks_dirty, chunk); + malloc_mutex_prof_read(tsdn, + &astats->mutex_prof_data[arena_prof_mutex_tcache_list], + &arena->tcache_ql_mtx); + malloc_mutex_unlock(tsdn, &arena->tcache_ql_mtx); + +#define READ_ARENA_MUTEX_PROF_DATA(mtx, ind) \ + malloc_mutex_lock(tsdn, &arena->mtx); \ + malloc_mutex_prof_read(tsdn, &astats->mutex_prof_data[ind], \ + &arena->mtx); \ + malloc_mutex_unlock(tsdn, &arena->mtx); + + /* Gather per arena mutex profiling data. */ + READ_ARENA_MUTEX_PROF_DATA(large_mtx, arena_prof_mutex_large); + READ_ARENA_MUTEX_PROF_DATA(extent_avail_mtx, + arena_prof_mutex_extent_avail) + READ_ARENA_MUTEX_PROF_DATA(extents_dirty.mtx, + arena_prof_mutex_extents_dirty) + READ_ARENA_MUTEX_PROF_DATA(extents_muzzy.mtx, + arena_prof_mutex_extents_muzzy) + READ_ARENA_MUTEX_PROF_DATA(extents_retained.mtx, + arena_prof_mutex_extents_retained) + READ_ARENA_MUTEX_PROF_DATA(decay_dirty.mtx, + arena_prof_mutex_decay_dirty) + READ_ARENA_MUTEX_PROF_DATA(decay_muzzy.mtx, + arena_prof_mutex_decay_muzzy) + READ_ARENA_MUTEX_PROF_DATA(base->mtx, + arena_prof_mutex_base) +#undef READ_ARENA_MUTEX_PROF_DATA + + nstime_copy(&astats->uptime, &arena->create_time); + nstime_update(&astats->uptime); + nstime_subtract(&astats->uptime, &arena->create_time); + + for (szind_t i = 0; i < NBINS; i++) { + arena_bin_t *bin = &arena->bins[i]; - arena_avail_tree_insert(&arena->runs_avail, arena_mapp_get(chunk, - pageind)); + malloc_mutex_lock(tsdn, &bin->lock); + malloc_mutex_prof_read(tsdn, &bstats[i].mutex_data, &bin->lock); + bstats[i].nmalloc += bin->stats.nmalloc; + bstats[i].ndalloc += bin->stats.ndalloc; + bstats[i].nrequests += bin->stats.nrequests; + bstats[i].curregs += bin->stats.curregs; + bstats[i].nfills += bin->stats.nfills; + bstats[i].nflushes += bin->stats.nflushes; + bstats[i].nslabs += bin->stats.nslabs; + bstats[i].reslabs += bin->stats.reslabs; + bstats[i].curslabs += bin->stats.curslabs; + malloc_mutex_unlock(tsdn, &bin->lock); + } } -static void -arena_avail_remove(arena_t *arena, arena_chunk_t *chunk, size_t pageind, - size_t npages, bool maybe_adjac_pred, bool maybe_adjac_succ) -{ - - assert(npages == (arena_mapbits_unallocated_size_get(chunk, pageind) >> - LG_PAGE)); - - /* - * chunks_dirty is keyed by nruns_{avail,adjac}, so the chunk must be - * removed and reinserted even if the run to be removed is clean. - */ - if (chunk->ndirty != 0) - arena_chunk_dirty_remove(&arena->chunks_dirty, chunk); - - if (maybe_adjac_pred && arena_avail_adjac_pred(chunk, pageind)) - chunk->nruns_adjac--; - if (maybe_adjac_succ && arena_avail_adjac_succ(chunk, pageind, npages)) - chunk->nruns_adjac--; - chunk->nruns_avail--; - assert(chunk->nruns_avail > chunk->nruns_adjac || (chunk->nruns_avail - == 0 && chunk->nruns_adjac == 0)); - - if (arena_mapbits_dirty_get(chunk, pageind) != 0) { - arena->ndirty -= npages; - chunk->ndirty -= npages; +void +arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + extents_dalloc(tsdn, arena, r_extent_hooks, &arena->extents_dirty, + extent); + if (arena_dirty_decay_ms_get(arena) == 0) { + arena_decay_dirty(tsdn, arena, false, true); + } else { + arena_background_thread_inactivity_check(tsdn, arena, false); } - if (chunk->ndirty != 0) - arena_chunk_dirty_insert(&arena->chunks_dirty, chunk); - - arena_avail_tree_remove(&arena->runs_avail, arena_mapp_get(chunk, - pageind)); } -static inline void * -arena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info) -{ +static void * +arena_slab_reg_alloc(tsdn_t *tsdn, extent_t *slab, + const arena_bin_info_t *bin_info) { void *ret; - unsigned regind; - bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + - (uintptr_t)bin_info->bitmap_offset); - - assert(run->nfree > 0); - assert(bitmap_full(bitmap, &bin_info->bitmap_info) == false); - - regind = bitmap_sfu(bitmap, &bin_info->bitmap_info); - ret = (void *)((uintptr_t)run + (uintptr_t)bin_info->reg0_offset + - (uintptr_t)(bin_info->reg_interval * regind)); - run->nfree--; - if (regind == run->nextind) - run->nextind++; - assert(regind < run->nextind); - return (ret); -} - -static inline void -arena_run_reg_dalloc(arena_run_t *run, void *ptr) -{ - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; - size_t mapbits = arena_mapbits_get(chunk, pageind); - size_t binind = arena_ptr_small_binind_get(ptr, mapbits); - arena_bin_info_t *bin_info = &arena_bin_info[binind]; - unsigned regind = arena_run_regind(run, bin_info, ptr); - bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + - (uintptr_t)bin_info->bitmap_offset); - - assert(run->nfree < bin_info->nregs); - /* Freeing an interior pointer can cause assertion failure. */ - assert(((uintptr_t)ptr - ((uintptr_t)run + - (uintptr_t)bin_info->reg0_offset)) % - (uintptr_t)bin_info->reg_interval == 0); - assert((uintptr_t)ptr >= (uintptr_t)run + - (uintptr_t)bin_info->reg0_offset); - /* Freeing an unallocated pointer can cause assertion failure. */ - assert(bitmap_get(bitmap, &bin_info->bitmap_info, regind)); + arena_slab_data_t *slab_data = extent_slab_data_get(slab); + size_t regind; + + assert(extent_nfree_get(slab) > 0); + assert(!bitmap_full(slab_data->bitmap, &bin_info->bitmap_info)); - bitmap_unset(bitmap, &bin_info->bitmap_info, regind); - run->nfree++; + regind = bitmap_sfu(slab_data->bitmap, &bin_info->bitmap_info); + ret = (void *)((uintptr_t)extent_addr_get(slab) + + (uintptr_t)(bin_info->reg_size * regind)); + extent_nfree_dec(slab); + return ret; } -static inline void -arena_run_zero(arena_chunk_t *chunk, size_t run_ind, size_t npages) -{ +#ifndef JEMALLOC_JET +static +#endif +size_t +arena_slab_regind(extent_t *slab, szind_t binind, const void *ptr) { + size_t diff, regind; - VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + (run_ind << - LG_PAGE)), (npages << LG_PAGE)); - memset((void *)((uintptr_t)chunk + (run_ind << LG_PAGE)), 0, - (npages << LG_PAGE)); -} + /* Freeing a pointer outside the slab can cause assertion failure. */ + assert((uintptr_t)ptr >= (uintptr_t)extent_addr_get(slab)); + assert((uintptr_t)ptr < (uintptr_t)extent_past_get(slab)); + /* Freeing an interior pointer can cause assertion failure. */ + assert(((uintptr_t)ptr - (uintptr_t)extent_addr_get(slab)) % + (uintptr_t)arena_bin_info[binind].reg_size == 0); + + /* Avoid doing division with a variable divisor. */ + diff = (size_t)((uintptr_t)ptr - (uintptr_t)extent_addr_get(slab)); + switch (binind) { +#define REGIND_bin_yes(index, reg_size) \ + case index: \ + regind = diff / (reg_size); \ + assert(diff == regind * (reg_size)); \ + break; +#define REGIND_bin_no(index, reg_size) +#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, \ + lg_delta_lookup) \ + REGIND_bin_##bin(index, (1U<<lg_grp) + (ndelta<<lg_delta)) + SIZE_CLASSES +#undef REGIND_bin_yes +#undef REGIND_bin_no +#undef SC + default: not_reached(); + } -static inline void -arena_run_page_mark_zeroed(arena_chunk_t *chunk, size_t run_ind) -{ + assert(regind < arena_bin_info[binind].nregs); - VALGRIND_MAKE_MEM_DEFINED((void *)((uintptr_t)chunk + (run_ind << - LG_PAGE)), PAGE); + return regind; } -static inline void -arena_run_page_validate_zeroed(arena_chunk_t *chunk, size_t run_ind) -{ - size_t i; - UNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE)); +static void +arena_slab_reg_dalloc(tsdn_t *tsdn, extent_t *slab, + arena_slab_data_t *slab_data, void *ptr) { + szind_t binind = extent_szind_get(slab); + const arena_bin_info_t *bin_info = &arena_bin_info[binind]; + size_t regind = arena_slab_regind(slab, binind, ptr); + + assert(extent_nfree_get(slab) < bin_info->nregs); + /* Freeing an unallocated pointer can cause assertion failure. */ + assert(bitmap_get(slab_data->bitmap, &bin_info->bitmap_info, regind)); - arena_run_page_mark_zeroed(chunk, run_ind); - for (i = 0; i < PAGE / sizeof(size_t); i++) - assert(p[i] == 0); + bitmap_unset(slab_data->bitmap, &bin_info->bitmap_info, regind); + extent_nfree_inc(slab); } static void -arena_cactive_update(arena_t *arena, size_t add_pages, size_t sub_pages) -{ +arena_nactive_add(arena_t *arena, size_t add_pages) { + atomic_fetch_add_zu(&arena->nactive, add_pages, ATOMIC_RELAXED); +} - if (config_stats) { - ssize_t cactive_diff = CHUNK_CEILING((arena->nactive + - add_pages) << LG_PAGE) - CHUNK_CEILING((arena->nactive - - sub_pages) << LG_PAGE); - if (cactive_diff != 0) - stats_cactive_add(cactive_diff); - } +static void +arena_nactive_sub(arena_t *arena, size_t sub_pages) { + assert(atomic_load_zu(&arena->nactive, ATOMIC_RELAXED) >= sub_pages); + atomic_fetch_sub_zu(&arena->nactive, sub_pages, ATOMIC_RELAXED); } static void -arena_run_split_remove(arena_t *arena, arena_chunk_t *chunk, size_t run_ind, - size_t flag_dirty, size_t need_pages) -{ - size_t total_pages, rem_pages; - - total_pages = arena_mapbits_unallocated_size_get(chunk, run_ind) >> - LG_PAGE; - assert(arena_mapbits_dirty_get(chunk, run_ind+total_pages-1) == - flag_dirty); - assert(need_pages <= total_pages); - rem_pages = total_pages - need_pages; - - arena_avail_remove(arena, chunk, run_ind, total_pages, true, true); - arena_cactive_update(arena, need_pages, 0); - arena->nactive += need_pages; - - /* Keep track of trailing unused pages for later use. */ - if (rem_pages > 0) { - if (flag_dirty != 0) { - arena_mapbits_unallocated_set(chunk, - run_ind+need_pages, (rem_pages << LG_PAGE), - flag_dirty); - arena_mapbits_unallocated_set(chunk, - run_ind+total_pages-1, (rem_pages << LG_PAGE), - flag_dirty); - } else { - arena_mapbits_unallocated_set(chunk, run_ind+need_pages, - (rem_pages << LG_PAGE), - arena_mapbits_unzeroed_get(chunk, - run_ind+need_pages)); - arena_mapbits_unallocated_set(chunk, - run_ind+total_pages-1, (rem_pages << LG_PAGE), - arena_mapbits_unzeroed_get(chunk, - run_ind+total_pages-1)); - } - arena_avail_insert(arena, chunk, run_ind+need_pages, rem_pages, - false, true); +arena_large_malloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t usize) { + szind_t index, hindex; + + cassert(config_stats); + + if (usize < LARGE_MINCLASS) { + usize = LARGE_MINCLASS; } + index = sz_size2index(usize); + hindex = (index >= NBINS) ? index - NBINS : 0; + + arena_stats_add_u64(tsdn, &arena->stats, + &arena->stats.lstats[hindex].nmalloc, 1); } static void -arena_run_split_large_helper(arena_t *arena, arena_run_t *run, size_t size, - bool remove, bool zero) -{ - arena_chunk_t *chunk; - size_t flag_dirty, run_ind, need_pages, i; +arena_large_dalloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t usize) { + szind_t index, hindex; - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); - flag_dirty = arena_mapbits_dirty_get(chunk, run_ind); - need_pages = (size >> LG_PAGE); - assert(need_pages > 0); + cassert(config_stats); - if (remove) { - arena_run_split_remove(arena, chunk, run_ind, flag_dirty, - need_pages); + if (usize < LARGE_MINCLASS) { + usize = LARGE_MINCLASS; } + index = sz_size2index(usize); + hindex = (index >= NBINS) ? index - NBINS : 0; - if (zero) { - if (flag_dirty == 0) { + arena_stats_add_u64(tsdn, &arena->stats, + &arena->stats.lstats[hindex].ndalloc, 1); +} + +static void +arena_large_ralloc_stats_update(tsdn_t *tsdn, arena_t *arena, size_t oldusize, + size_t usize) { + arena_large_dalloc_stats_update(tsdn, arena, oldusize); + arena_large_malloc_stats_update(tsdn, arena, usize); +} + +extent_t * +arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, + size_t alignment, bool *zero) { + extent_hooks_t *extent_hooks = EXTENT_HOOKS_INITIALIZER; + + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + szind_t szind = sz_size2index(usize); + size_t mapped_add; + bool commit = true; + extent_t *extent = extents_alloc(tsdn, arena, &extent_hooks, + &arena->extents_dirty, NULL, usize, sz_large_pad, alignment, false, + szind, zero, &commit); + if (extent == NULL) { + extent = extents_alloc(tsdn, arena, &extent_hooks, + &arena->extents_muzzy, NULL, usize, sz_large_pad, alignment, + false, szind, zero, &commit); + } + size_t size = usize + sz_large_pad; + if (extent == NULL) { + extent = extent_alloc_wrapper(tsdn, arena, &extent_hooks, NULL, + usize, sz_large_pad, alignment, false, szind, zero, + &commit); + if (config_stats) { /* - * The run is clean, so some pages may be zeroed (i.e. - * never before touched). + * extent may be NULL on OOM, but in that case + * mapped_add isn't used below, so there's no need to + * conditionlly set it to 0 here. */ - for (i = 0; i < need_pages; i++) { - if (arena_mapbits_unzeroed_get(chunk, run_ind+i) - != 0) - arena_run_zero(chunk, run_ind+i, 1); - else if (config_debug) { - arena_run_page_validate_zeroed(chunk, - run_ind+i); - } else { - arena_run_page_mark_zeroed(chunk, - run_ind+i); - } + mapped_add = size; + } + } else if (config_stats) { + mapped_add = 0; + } + + if (extent != NULL) { + if (config_stats) { + arena_stats_lock(tsdn, &arena->stats); + arena_large_malloc_stats_update(tsdn, arena, usize); + if (mapped_add != 0) { + arena_stats_add_zu(tsdn, &arena->stats, + &arena->stats.mapped, mapped_add); } - } else { - /* The run is dirty, so all pages must be zeroed. */ - arena_run_zero(chunk, run_ind, need_pages); + arena_stats_unlock(tsdn, &arena->stats); } - } else { - VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + - (run_ind << LG_PAGE)), (need_pages << LG_PAGE)); + arena_nactive_add(arena, size >> LG_PAGE); } - /* - * Set the last element first, in case the run only contains one page - * (i.e. both statements set the same element). - */ - arena_mapbits_large_set(chunk, run_ind+need_pages-1, 0, flag_dirty); - arena_mapbits_large_set(chunk, run_ind, size, flag_dirty); + return extent; } -static void -arena_run_split_large(arena_t *arena, arena_run_t *run, size_t size, bool zero) -{ - - arena_run_split_large_helper(arena, run, size, true, zero); +void +arena_extent_dalloc_large_prep(tsdn_t *tsdn, arena_t *arena, extent_t *extent) { + if (config_stats) { + arena_stats_lock(tsdn, &arena->stats); + arena_large_dalloc_stats_update(tsdn, arena, + extent_usize_get(extent)); + arena_stats_unlock(tsdn, &arena->stats); + } + arena_nactive_sub(arena, extent_size_get(extent) >> LG_PAGE); } -static void -arena_run_init_large(arena_t *arena, arena_run_t *run, size_t size, bool zero) -{ +void +arena_extent_ralloc_large_shrink(tsdn_t *tsdn, arena_t *arena, extent_t *extent, + size_t oldusize) { + size_t usize = extent_usize_get(extent); + size_t udiff = oldusize - usize; - arena_run_split_large_helper(arena, run, size, false, zero); + if (config_stats) { + arena_stats_lock(tsdn, &arena->stats); + arena_large_ralloc_stats_update(tsdn, arena, oldusize, usize); + arena_stats_unlock(tsdn, &arena->stats); + } + arena_nactive_sub(arena, udiff >> LG_PAGE); } -static void -arena_run_split_small(arena_t *arena, arena_run_t *run, size_t size, - size_t binind) -{ - arena_chunk_t *chunk; - size_t flag_dirty, run_ind, need_pages, i; +void +arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena, extent_t *extent, + size_t oldusize) { + size_t usize = extent_usize_get(extent); + size_t udiff = usize - oldusize; - assert(binind != BININD_INVALID); + if (config_stats) { + arena_stats_lock(tsdn, &arena->stats); + arena_large_ralloc_stats_update(tsdn, arena, oldusize, usize); + arena_stats_unlock(tsdn, &arena->stats); + } + arena_nactive_add(arena, udiff >> LG_PAGE); +} - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); - flag_dirty = arena_mapbits_dirty_get(chunk, run_ind); - need_pages = (size >> LG_PAGE); - assert(need_pages > 0); +static ssize_t +arena_decay_ms_read(arena_decay_t *decay) { + return atomic_load_zd(&decay->time_ms, ATOMIC_RELAXED); +} - arena_run_split_remove(arena, chunk, run_ind, flag_dirty, need_pages); +static void +arena_decay_ms_write(arena_decay_t *decay, ssize_t decay_ms) { + atomic_store_zd(&decay->time_ms, decay_ms, ATOMIC_RELAXED); +} +static void +arena_decay_deadline_init(arena_decay_t *decay) { /* - * Propagate the dirty and unzeroed flags to the allocated small run, - * so that arena_dalloc_bin_run() has the ability to conditionally trim - * clean pages. - */ - arena_mapbits_small_set(chunk, run_ind, 0, binind, flag_dirty); - /* - * The first page will always be dirtied during small run - * initialization, so a validation failure here would not actually - * cause an observable failure. + * Generate a new deadline that is uniformly random within the next + * epoch after the current one. */ - if (config_debug && flag_dirty == 0 && arena_mapbits_unzeroed_get(chunk, - run_ind) == 0) - arena_run_page_validate_zeroed(chunk, run_ind); - for (i = 1; i < need_pages - 1; i++) { - arena_mapbits_small_set(chunk, run_ind+i, i, binind, 0); - if (config_debug && flag_dirty == 0 && - arena_mapbits_unzeroed_get(chunk, run_ind+i) == 0) - arena_run_page_validate_zeroed(chunk, run_ind+i); - } - arena_mapbits_small_set(chunk, run_ind+need_pages-1, need_pages-1, - binind, flag_dirty); - if (config_debug && flag_dirty == 0 && arena_mapbits_unzeroed_get(chunk, - run_ind+need_pages-1) == 0) - arena_run_page_validate_zeroed(chunk, run_ind+need_pages-1); - VALGRIND_MAKE_MEM_UNDEFINED((void *)((uintptr_t)chunk + - (run_ind << LG_PAGE)), (need_pages << LG_PAGE)); -} - -static arena_chunk_t * -arena_chunk_init_spare(arena_t *arena) -{ - arena_chunk_t *chunk; - - assert(arena->spare != NULL); - - chunk = arena->spare; - arena->spare = NULL; - - assert(arena_mapbits_allocated_get(chunk, map_bias) == 0); - assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0); - assert(arena_mapbits_unallocated_size_get(chunk, map_bias) == - arena_maxclass); - assert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) == - arena_maxclass); - assert(arena_mapbits_dirty_get(chunk, map_bias) == - arena_mapbits_dirty_get(chunk, chunk_npages-1)); - - return (chunk); -} - -static arena_chunk_t * -arena_chunk_init_hard(arena_t *arena) -{ - arena_chunk_t *chunk; - bool zero; - size_t unzeroed, i; - - assert(arena->spare == NULL); - - zero = false; - malloc_mutex_unlock(&arena->lock); - chunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize, false, - &zero, arena->dss_prec); - malloc_mutex_lock(&arena->lock); - if (chunk == NULL) - return (NULL); - if (config_stats) - arena->stats.mapped += chunksize; + nstime_copy(&decay->deadline, &decay->epoch); + nstime_add(&decay->deadline, &decay->interval); + if (arena_decay_ms_read(decay) > 0) { + nstime_t jitter; - chunk->arena = arena; + nstime_init(&jitter, prng_range_u64(&decay->jitter_state, + nstime_ns(&decay->interval))); + nstime_add(&decay->deadline, &jitter); + } +} - /* - * Claim that no pages are in use, since the header is merely overhead. - */ - chunk->ndirty = 0; +static bool +arena_decay_deadline_reached(const arena_decay_t *decay, const nstime_t *time) { + return (nstime_compare(&decay->deadline, time) <= 0); +} - chunk->nruns_avail = 0; - chunk->nruns_adjac = 0; +static size_t +arena_decay_backlog_npages_limit(const arena_decay_t *decay) { + uint64_t sum; + size_t npages_limit_backlog; + unsigned i; /* - * Initialize the map to contain one maximal free untouched run. Mark - * the pages as zeroed iff chunk_alloc() returned a zeroed chunk. - */ - unzeroed = zero ? 0 : CHUNK_MAP_UNZEROED; - arena_mapbits_unallocated_set(chunk, map_bias, arena_maxclass, - unzeroed); - /* - * There is no need to initialize the internal page map entries unless - * the chunk is not zeroed. + * For each element of decay_backlog, multiply by the corresponding + * fixed-point smoothstep decay factor. Sum the products, then divide + * to round down to the nearest whole number of pages. */ - if (zero == false) { - VALGRIND_MAKE_MEM_UNDEFINED((void *)arena_mapp_get(chunk, - map_bias+1), (size_t)((uintptr_t) arena_mapp_get(chunk, - chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk, - map_bias+1))); - for (i = map_bias+1; i < chunk_npages-1; i++) - arena_mapbits_unzeroed_set(chunk, i, unzeroed); - } else { - VALGRIND_MAKE_MEM_DEFINED((void *)arena_mapp_get(chunk, - map_bias+1), (size_t)((uintptr_t) arena_mapp_get(chunk, - chunk_npages-1) - (uintptr_t)arena_mapp_get(chunk, - map_bias+1))); - if (config_debug) { - for (i = map_bias+1; i < chunk_npages-1; i++) { - assert(arena_mapbits_unzeroed_get(chunk, i) == - unzeroed); - } - } + sum = 0; + for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) { + sum += decay->backlog[i] * h_steps[i]; } - arena_mapbits_unallocated_set(chunk, chunk_npages-1, arena_maxclass, - unzeroed); + npages_limit_backlog = (size_t)(sum >> SMOOTHSTEP_BFP); - return (chunk); + return npages_limit_backlog; } -static arena_chunk_t * -arena_chunk_alloc(arena_t *arena) -{ - arena_chunk_t *chunk; +static void +arena_decay_backlog_update_last(arena_decay_t *decay, size_t current_npages) { + size_t npages_delta = (current_npages > decay->nunpurged) ? + current_npages - decay->nunpurged : 0; + decay->backlog[SMOOTHSTEP_NSTEPS-1] = npages_delta; - if (arena->spare != NULL) - chunk = arena_chunk_init_spare(arena); - else { - chunk = arena_chunk_init_hard(arena); - if (chunk == NULL) - return (NULL); + if (config_debug) { + if (current_npages > decay->ceil_npages) { + decay->ceil_npages = current_npages; + } + size_t npages_limit = arena_decay_backlog_npages_limit(decay); + assert(decay->ceil_npages >= npages_limit); + if (decay->ceil_npages > npages_limit) { + decay->ceil_npages = npages_limit; + } } - - /* Insert the run into the runs_avail tree. */ - arena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias, - false, false); - - return (chunk); } static void -arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) -{ - assert(arena_mapbits_allocated_get(chunk, map_bias) == 0); - assert(arena_mapbits_allocated_get(chunk, chunk_npages-1) == 0); - assert(arena_mapbits_unallocated_size_get(chunk, map_bias) == - arena_maxclass); - assert(arena_mapbits_unallocated_size_get(chunk, chunk_npages-1) == - arena_maxclass); - assert(arena_mapbits_dirty_get(chunk, map_bias) == - arena_mapbits_dirty_get(chunk, chunk_npages-1)); +arena_decay_backlog_update(arena_decay_t *decay, uint64_t nadvance_u64, + size_t current_npages) { + if (nadvance_u64 >= SMOOTHSTEP_NSTEPS) { + memset(decay->backlog, 0, (SMOOTHSTEP_NSTEPS-1) * + sizeof(size_t)); + } else { + size_t nadvance_z = (size_t)nadvance_u64; - /* - * Remove run from the runs_avail tree, so that the arena does not use - * it. - */ - arena_avail_remove(arena, chunk, map_bias, chunk_npages-map_bias, - false, false); + assert((uint64_t)nadvance_z == nadvance_u64); - if (arena->spare != NULL) { - arena_chunk_t *spare = arena->spare; + memmove(decay->backlog, &decay->backlog[nadvance_z], + (SMOOTHSTEP_NSTEPS - nadvance_z) * sizeof(size_t)); + if (nadvance_z > 1) { + memset(&decay->backlog[SMOOTHSTEP_NSTEPS - + nadvance_z], 0, (nadvance_z-1) * sizeof(size_t)); + } + } - arena->spare = chunk; - malloc_mutex_unlock(&arena->lock); - chunk_dealloc((void *)spare, chunksize, true); - malloc_mutex_lock(&arena->lock); - if (config_stats) - arena->stats.mapped -= chunksize; - } else - arena->spare = chunk; + arena_decay_backlog_update_last(decay, current_npages); } -static arena_run_t * -arena_run_alloc_large_helper(arena_t *arena, size_t size, bool zero) -{ - arena_run_t *run; - arena_chunk_map_t *mapelm, key; - - key.bits = size | CHUNK_MAP_KEY; - mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); - if (mapelm != NULL) { - arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; - - run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << - LG_PAGE)); - arena_run_split_large(arena, run, size, zero); - return (run); +static void +arena_decay_try_purge(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, + extents_t *extents, size_t current_npages, size_t npages_limit, + bool is_background_thread) { + if (current_npages > npages_limit) { + arena_decay_to_limit(tsdn, arena, decay, extents, false, + npages_limit, is_background_thread); } - - return (NULL); } -static arena_run_t * -arena_run_alloc_large(arena_t *arena, size_t size, bool zero) -{ - arena_chunk_t *chunk; - arena_run_t *run; +static void +arena_decay_epoch_advance_helper(arena_decay_t *decay, const nstime_t *time, + size_t current_npages) { + assert(arena_decay_deadline_reached(decay, time)); - assert(size <= arena_maxclass); - assert((size & PAGE_MASK) == 0); + nstime_t delta; + nstime_copy(&delta, time); + nstime_subtract(&delta, &decay->epoch); - /* Search the arena's chunks for the lowest best fit. */ - run = arena_run_alloc_large_helper(arena, size, zero); - if (run != NULL) - return (run); + uint64_t nadvance_u64 = nstime_divide(&delta, &decay->interval); + assert(nadvance_u64 > 0); - /* - * No usable runs. Create a new chunk from which to allocate the run. - */ - chunk = arena_chunk_alloc(arena); - if (chunk != NULL) { - run = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE)); - arena_run_split_large(arena, run, size, zero); - return (run); - } + /* Add nadvance_u64 decay intervals to epoch. */ + nstime_copy(&delta, &decay->interval); + nstime_imultiply(&delta, nadvance_u64); + nstime_add(&decay->epoch, &delta); - /* - * arena_chunk_alloc() failed, but another thread may have made - * sufficient memory available while this one dropped arena->lock in - * arena_chunk_alloc(), so search one more time. - */ - return (arena_run_alloc_large_helper(arena, size, zero)); + /* Set a new deadline. */ + arena_decay_deadline_init(decay); + + /* Update the backlog. */ + arena_decay_backlog_update(decay, nadvance_u64, current_npages); } -static arena_run_t * -arena_run_alloc_small_helper(arena_t *arena, size_t size, size_t binind) -{ - arena_run_t *run; - arena_chunk_map_t *mapelm, key; +static void +arena_decay_epoch_advance(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, + extents_t *extents, const nstime_t *time, bool is_background_thread) { + size_t current_npages = extents_npages_get(extents); + arena_decay_epoch_advance_helper(decay, time, current_npages); - key.bits = size | CHUNK_MAP_KEY; - mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); - if (mapelm != NULL) { - arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = (((uintptr_t)mapelm - - (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) - + map_bias; + size_t npages_limit = arena_decay_backlog_npages_limit(decay); + /* We may unlock decay->mtx when try_purge(). Finish logging first. */ + decay->nunpurged = (npages_limit > current_npages) ? npages_limit : + current_npages; - run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << - LG_PAGE)); - arena_run_split_small(arena, run, size, binind); - return (run); + if (!background_thread_enabled() || is_background_thread) { + arena_decay_try_purge(tsdn, arena, decay, extents, + current_npages, npages_limit, is_background_thread); } - - return (NULL); } -static arena_run_t * -arena_run_alloc_small(arena_t *arena, size_t size, size_t binind) -{ - arena_chunk_t *chunk; - arena_run_t *run; - - assert(size <= arena_maxclass); - assert((size & PAGE_MASK) == 0); - assert(binind != BININD_INVALID); +static void +arena_decay_reinit(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms) { + arena_decay_ms_write(decay, decay_ms); + if (decay_ms > 0) { + nstime_init(&decay->interval, (uint64_t)decay_ms * + KQU(1000000)); + nstime_idivide(&decay->interval, SMOOTHSTEP_NSTEPS); + } - /* Search the arena's chunks for the lowest best fit. */ - run = arena_run_alloc_small_helper(arena, size, binind); - if (run != NULL) - return (run); + nstime_init(&decay->epoch, 0); + nstime_update(&decay->epoch); + decay->jitter_state = (uint64_t)(uintptr_t)decay; + arena_decay_deadline_init(decay); + decay->nunpurged = 0; + memset(decay->backlog, 0, SMOOTHSTEP_NSTEPS * sizeof(size_t)); +} - /* - * No usable runs. Create a new chunk from which to allocate the run. - */ - chunk = arena_chunk_alloc(arena); - if (chunk != NULL) { - run = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE)); - arena_run_split_small(arena, run, size, binind); - return (run); +static bool +arena_decay_init(arena_decay_t *decay, extents_t *extents, ssize_t decay_ms, + decay_stats_t *stats) { + if (config_debug) { + for (size_t i = 0; i < sizeof(arena_decay_t); i++) { + assert(((char *)decay)[i] == 0); + } + decay->ceil_npages = 0; + } + if (malloc_mutex_init(&decay->mtx, "decay", WITNESS_RANK_DECAY, + malloc_mutex_rank_exclusive)) { + return true; + } + decay->purging = false; + arena_decay_reinit(decay, extents, decay_ms); + /* Memory is zeroed, so there is no need to clear stats. */ + if (config_stats) { + decay->stats = stats; } + return false; +} - /* - * arena_chunk_alloc() failed, but another thread may have made - * sufficient memory available while this one dropped arena->lock in - * arena_chunk_alloc(), so search one more time. - */ - return (arena_run_alloc_small_helper(arena, size, binind)); +static bool +arena_decay_ms_valid(ssize_t decay_ms) { + if (decay_ms < -1) { + return false; + } + if (decay_ms == -1 || (uint64_t)decay_ms <= NSTIME_SEC_MAX * + KQU(1000)) { + return true; + } + return false; } -static inline void -arena_maybe_purge(arena_t *arena) -{ - size_t npurgeable, threshold; +static bool +arena_maybe_decay(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, + extents_t *extents, bool is_background_thread) { + malloc_mutex_assert_owner(tsdn, &decay->mtx); + + /* Purge all or nothing if the option is disabled. */ + ssize_t decay_ms = arena_decay_ms_read(decay); + if (decay_ms <= 0) { + if (decay_ms == 0) { + arena_decay_to_limit(tsdn, arena, decay, extents, false, + 0, is_background_thread); + } + return false; + } + + nstime_t time; + nstime_init(&time, 0); + nstime_update(&time); + if (unlikely(!nstime_monotonic() && nstime_compare(&decay->epoch, &time) + > 0)) { + /* + * Time went backwards. Move the epoch back in time and + * generate a new deadline, with the expectation that time + * typically flows forward for long enough periods of time that + * epochs complete. Unfortunately, this strategy is susceptible + * to clock jitter triggering premature epoch advances, but + * clock jitter estimation and compensation isn't feasible here + * because calls into this code are event-driven. + */ + nstime_copy(&decay->epoch, &time); + arena_decay_deadline_init(decay); + } else { + /* Verify that time does not go backwards. */ + assert(nstime_compare(&decay->epoch, &time) <= 0); + } - /* Don't purge if the option is disabled. */ - if (opt_lg_dirty_mult < 0) - return; - /* Don't purge if all dirty pages are already being purged. */ - if (arena->ndirty <= arena->npurgatory) - return; - npurgeable = arena->ndirty - arena->npurgatory; - threshold = (arena->nactive >> opt_lg_dirty_mult); /* - * Don't purge unless the number of purgeable pages exceeds the - * threshold. + * If the deadline has been reached, advance to the current epoch and + * purge to the new limit if necessary. Note that dirty pages created + * during the current epoch are not subject to purge until a future + * epoch, so as a result purging only happens during epoch advances, or + * being triggered by background threads (scheduled event). */ - if (npurgeable <= threshold) - return; + bool advance_epoch = arena_decay_deadline_reached(decay, &time); + if (advance_epoch) { + arena_decay_epoch_advance(tsdn, arena, decay, extents, &time, + is_background_thread); + } else if (is_background_thread) { + arena_decay_try_purge(tsdn, arena, decay, extents, + extents_npages_get(extents), + arena_decay_backlog_npages_limit(decay), + is_background_thread); + } - arena_purge(arena, false); + return advance_epoch; } -static arena_chunk_t * -chunks_dirty_iter_cb(arena_chunk_tree_t *tree, arena_chunk_t *chunk, void *arg) -{ - size_t *ndirty = (size_t *)arg; +static ssize_t +arena_decay_ms_get(arena_decay_t *decay) { + return arena_decay_ms_read(decay); +} - assert(chunk->ndirty != 0); - *ndirty += chunk->ndirty; - return (NULL); +ssize_t +arena_dirty_decay_ms_get(arena_t *arena) { + return arena_decay_ms_get(&arena->decay_dirty); } -static size_t -arena_compute_npurgatory(arena_t *arena, bool all) -{ - size_t npurgatory, npurgeable; +ssize_t +arena_muzzy_decay_ms_get(arena_t *arena) { + return arena_decay_ms_get(&arena->decay_muzzy); +} +static bool +arena_decay_ms_set(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, + extents_t *extents, ssize_t decay_ms) { + if (!arena_decay_ms_valid(decay_ms)) { + return true; + } + + malloc_mutex_lock(tsdn, &decay->mtx); /* - * Compute the minimum number of pages that this thread should try to - * purge. + * Restart decay backlog from scratch, which may cause many dirty pages + * to be immediately purged. It would conceptually be possible to map + * the old backlog onto the new backlog, but there is no justification + * for such complexity since decay_ms changes are intended to be + * infrequent, either between the {-1, 0, >0} states, or a one-time + * arbitrary change during initial arena configuration. */ - npurgeable = arena->ndirty - arena->npurgatory; + arena_decay_reinit(decay, extents, decay_ms); + arena_maybe_decay(tsdn, arena, decay, extents, false); + malloc_mutex_unlock(tsdn, &decay->mtx); - if (all == false) { - size_t threshold = (arena->nactive >> opt_lg_dirty_mult); + return false; +} - npurgatory = npurgeable - threshold; - } else - npurgatory = npurgeable; +bool +arena_dirty_decay_ms_set(tsdn_t *tsdn, arena_t *arena, + ssize_t decay_ms) { + return arena_decay_ms_set(tsdn, arena, &arena->decay_dirty, + &arena->extents_dirty, decay_ms); +} - return (npurgatory); +bool +arena_muzzy_decay_ms_set(tsdn_t *tsdn, arena_t *arena, + ssize_t decay_ms) { + return arena_decay_ms_set(tsdn, arena, &arena->decay_muzzy, + &arena->extents_muzzy, decay_ms); } -static void -arena_chunk_stash_dirty(arena_t *arena, arena_chunk_t *chunk, bool all, - arena_chunk_mapelms_t *mapelms) -{ - size_t pageind, npages; +static size_t +arena_stash_decayed(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extents_t *extents, size_t npages_limit, + extent_list_t *decay_extents) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); - /* - * Temporarily allocate free dirty runs within chunk. If all is false, - * only operate on dirty runs that are fragments; otherwise operate on - * all dirty runs. - */ - for (pageind = map_bias; pageind < chunk_npages; pageind += npages) { - arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); - if (arena_mapbits_allocated_get(chunk, pageind) == 0) { - size_t run_size = - arena_mapbits_unallocated_size_get(chunk, pageind); - - npages = run_size >> LG_PAGE; - assert(pageind + npages <= chunk_npages); - assert(arena_mapbits_dirty_get(chunk, pageind) == - arena_mapbits_dirty_get(chunk, pageind+npages-1)); - - if (arena_mapbits_dirty_get(chunk, pageind) != 0 && - (all || arena_avail_adjac(chunk, pageind, - npages))) { - arena_run_t *run = (arena_run_t *)((uintptr_t) - chunk + (uintptr_t)(pageind << LG_PAGE)); - - arena_run_split_large(arena, run, run_size, - false); - /* Append to list for later processing. */ - ql_elm_new(mapelm, u.ql_link); - ql_tail_insert(mapelms, mapelm, u.ql_link); - } - } else { - /* Skip run. */ - if (arena_mapbits_large_get(chunk, pageind) != 0) { - npages = arena_mapbits_large_size_get(chunk, - pageind) >> LG_PAGE; - } else { - size_t binind; - arena_bin_info_t *bin_info; - arena_run_t *run = (arena_run_t *)((uintptr_t) - chunk + (uintptr_t)(pageind << LG_PAGE)); - - assert(arena_mapbits_small_runind_get(chunk, - pageind) == 0); - binind = arena_bin_index(arena, run->bin); - bin_info = &arena_bin_info[binind]; - npages = bin_info->run_size >> LG_PAGE; - } - } + /* Stash extents according to npages_limit. */ + size_t nstashed = 0; + extent_t *extent; + while ((extent = extents_evict(tsdn, arena, r_extent_hooks, extents, + npages_limit)) != NULL) { + extent_list_append(decay_extents, extent); + nstashed += extent_size_get(extent) >> LG_PAGE; } - assert(pageind == chunk_npages); - assert(chunk->ndirty == 0 || all == false); - assert(chunk->nruns_adjac == 0); + return nstashed; } static size_t -arena_chunk_purge_stashed(arena_t *arena, arena_chunk_t *chunk, - arena_chunk_mapelms_t *mapelms) -{ - size_t npurged, pageind, npages, nmadvise; - arena_chunk_map_t *mapelm; - - malloc_mutex_unlock(&arena->lock); - if (config_stats) +arena_decay_stashed(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, arena_decay_t *decay, extents_t *extents, + bool all, extent_list_t *decay_extents, bool is_background_thread) { + UNUSED size_t nmadvise, nunmapped; + size_t npurged; + + if (config_stats) { nmadvise = 0; + nunmapped = 0; + } npurged = 0; - ql_foreach(mapelm, mapelms, u.ql_link) { - bool unzeroed; - size_t flag_unzeroed, i; - - pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)) + map_bias; - npages = arena_mapbits_large_size_get(chunk, pageind) >> - LG_PAGE; - assert(pageind + npages <= chunk_npages); - unzeroed = pages_purge((void *)((uintptr_t)chunk + (pageind << - LG_PAGE)), (npages << LG_PAGE)); - flag_unzeroed = unzeroed ? CHUNK_MAP_UNZEROED : 0; - /* - * Set the unzeroed flag for all pages, now that pages_purge() - * has returned whether the pages were zeroed as a side effect - * of purging. This chunk map modification is safe even though - * the arena mutex isn't currently owned by this thread, - * because the run is marked as allocated, thus protecting it - * from being modified by any other thread. As long as these - * writes don't perturb the first and last elements' - * CHUNK_MAP_ALLOCATED bits, behavior is well defined. - */ - for (i = 0; i < npages; i++) { - arena_mapbits_unzeroed_set(chunk, pageind+i, - flag_unzeroed); + + ssize_t muzzy_decay_ms = arena_muzzy_decay_ms_get(arena); + for (extent_t *extent = extent_list_first(decay_extents); extent != + NULL; extent = extent_list_first(decay_extents)) { + if (config_stats) { + nmadvise++; } + size_t npages = extent_size_get(extent) >> LG_PAGE; npurged += npages; - if (config_stats) - nmadvise++; + extent_list_remove(decay_extents, extent); + switch (extents_state_get(extents)) { + case extent_state_active: + not_reached(); + case extent_state_dirty: + if (!all && muzzy_decay_ms != 0 && + !extent_purge_lazy_wrapper(tsdn, arena, + r_extent_hooks, extent, 0, + extent_size_get(extent))) { + extents_dalloc(tsdn, arena, r_extent_hooks, + &arena->extents_muzzy, extent); + arena_background_thread_inactivity_check(tsdn, + arena, is_background_thread); + break; + } + /* Fall through. */ + case extent_state_muzzy: + extent_dalloc_wrapper(tsdn, arena, r_extent_hooks, + extent); + if (config_stats) { + nunmapped += npages; + } + break; + case extent_state_retained: + default: + not_reached(); + } } - malloc_mutex_lock(&arena->lock); - if (config_stats) - arena->stats.nmadvise += nmadvise; - return (npurged); + if (config_stats) { + arena_stats_lock(tsdn, &arena->stats); + arena_stats_add_u64(tsdn, &arena->stats, &decay->stats->npurge, + 1); + arena_stats_add_u64(tsdn, &arena->stats, + &decay->stats->nmadvise, nmadvise); + arena_stats_add_u64(tsdn, &arena->stats, &decay->stats->purged, + npurged); + arena_stats_sub_zu(tsdn, &arena->stats, &arena->stats.mapped, + nunmapped << LG_PAGE); + arena_stats_unlock(tsdn, &arena->stats); + } + + return npurged; } +/* + * npages_limit: Decay as many dirty extents as possible without violating the + * invariant: (extents_npages_get(extents) >= npages_limit) + */ static void -arena_chunk_unstash_purged(arena_t *arena, arena_chunk_t *chunk, - arena_chunk_mapelms_t *mapelms) -{ - arena_chunk_map_t *mapelm; - size_t pageind; - - /* Deallocate runs. */ - for (mapelm = ql_first(mapelms); mapelm != NULL; - mapelm = ql_first(mapelms)) { - arena_run_t *run; - - pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)) + map_bias; - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)(pageind << - LG_PAGE)); - ql_remove(mapelms, mapelm, u.ql_link); - arena_run_dalloc(arena, run, false, true); +arena_decay_to_limit(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, + extents_t *extents, bool all, size_t npages_limit, + bool is_background_thread) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 1); + malloc_mutex_assert_owner(tsdn, &decay->mtx); + + if (decay->purging) { + return; } -} + decay->purging = true; + malloc_mutex_unlock(tsdn, &decay->mtx); -static inline size_t -arena_chunk_purge(arena_t *arena, arena_chunk_t *chunk, bool all) -{ - size_t npurged; - arena_chunk_mapelms_t mapelms; + extent_hooks_t *extent_hooks = extent_hooks_get(arena); - ql_new(&mapelms); + extent_list_t decay_extents; + extent_list_init(&decay_extents); - /* - * If chunk is the spare, temporarily re-allocate it, 1) so that its - * run is reinserted into runs_avail, and 2) so that it cannot be - * completely discarded by another thread while arena->lock is dropped - * by this thread. Note that the arena_run_dalloc() call will - * implicitly deallocate the chunk, so no explicit action is required - * in this function to deallocate the chunk. - * - * Note that once a chunk contains dirty pages, it cannot again contain - * a single run unless 1) it is a dirty run, or 2) this function purges - * dirty pages and causes the transition to a single clean run. Thus - * (chunk == arena->spare) is possible, but it is not possible for - * this function to be called on the spare unless it contains a dirty - * run. - */ - if (chunk == arena->spare) { - assert(arena_mapbits_dirty_get(chunk, map_bias) != 0); - assert(arena_mapbits_dirty_get(chunk, chunk_npages-1) != 0); - - arena_chunk_alloc(arena); + size_t npurge = arena_stash_decayed(tsdn, arena, &extent_hooks, extents, + npages_limit, &decay_extents); + if (npurge != 0) { + UNUSED size_t npurged = arena_decay_stashed(tsdn, arena, + &extent_hooks, decay, extents, all, &decay_extents, + is_background_thread); + assert(npurged == npurge); } - if (config_stats) - arena->stats.purged += chunk->ndirty; - - /* - * Operate on all dirty runs if there is no clean/dirty run - * fragmentation. - */ - if (chunk->nruns_adjac == 0) - all = true; - - arena_chunk_stash_dirty(arena, chunk, all, &mapelms); - npurged = arena_chunk_purge_stashed(arena, chunk, &mapelms); - arena_chunk_unstash_purged(arena, chunk, &mapelms); - - return (npurged); + malloc_mutex_lock(tsdn, &decay->mtx); + decay->purging = false; } -static void -arena_purge(arena_t *arena, bool all) -{ - arena_chunk_t *chunk; - size_t npurgatory; - if (config_debug) { - size_t ndirty = 0; +static bool +arena_decay_impl(tsdn_t *tsdn, arena_t *arena, arena_decay_t *decay, + extents_t *extents, bool is_background_thread, bool all) { + if (all) { + malloc_mutex_lock(tsdn, &decay->mtx); + arena_decay_to_limit(tsdn, arena, decay, extents, all, 0, + is_background_thread); + malloc_mutex_unlock(tsdn, &decay->mtx); - arena_chunk_dirty_iter(&arena->chunks_dirty, NULL, - chunks_dirty_iter_cb, (void *)&ndirty); - assert(ndirty == arena->ndirty); + return false; } - assert(arena->ndirty > arena->npurgatory || all); - assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty - - arena->npurgatory) || all); - if (config_stats) - arena->stats.npurge++; + if (malloc_mutex_trylock(tsdn, &decay->mtx)) { + /* No need to wait if another thread is in progress. */ + return true; + } - /* - * Add the minimum number of pages this thread should try to purge to - * arena->npurgatory. This will keep multiple threads from racing to - * reduce ndirty below the threshold. - */ - npurgatory = arena_compute_npurgatory(arena, all); - arena->npurgatory += npurgatory; + bool epoch_advanced = arena_maybe_decay(tsdn, arena, decay, extents, + is_background_thread); + size_t npages_new; + if (epoch_advanced) { + /* Backlog is updated on epoch advance. */ + npages_new = decay->backlog[SMOOTHSTEP_NSTEPS-1]; + } + malloc_mutex_unlock(tsdn, &decay->mtx); - while (npurgatory > 0) { - size_t npurgeable, npurged, nunpurged; + if (have_background_thread && background_thread_enabled() && + epoch_advanced && !is_background_thread) { + background_thread_interval_check(tsdn, arena, decay, npages_new); + } - /* Get next chunk with dirty pages. */ - chunk = arena_chunk_dirty_first(&arena->chunks_dirty); - if (chunk == NULL) { - /* - * This thread was unable to purge as many pages as - * originally intended, due to races with other threads - * that either did some of the purging work, or re-used - * dirty pages. - */ - arena->npurgatory -= npurgatory; - return; - } - npurgeable = chunk->ndirty; - assert(npurgeable != 0); + return false; +} - if (npurgeable > npurgatory && chunk->nruns_adjac == 0) { - /* - * This thread will purge all the dirty pages in chunk, - * so set npurgatory to reflect this thread's intent to - * purge the pages. This tends to reduce the chances - * of the following scenario: - * - * 1) This thread sets arena->npurgatory such that - * (arena->ndirty - arena->npurgatory) is at the - * threshold. - * 2) This thread drops arena->lock. - * 3) Another thread causes one or more pages to be - * dirtied, and immediately determines that it must - * purge dirty pages. - * - * If this scenario *does* play out, that's okay, - * because all of the purging work being done really - * needs to happen. - */ - arena->npurgatory += npurgeable - npurgatory; - npurgatory = npurgeable; - } +static bool +arena_decay_dirty(tsdn_t *tsdn, arena_t *arena, bool is_background_thread, + bool all) { + return arena_decay_impl(tsdn, arena, &arena->decay_dirty, + &arena->extents_dirty, is_background_thread, all); +} - /* - * Keep track of how many pages are purgeable, versus how many - * actually get purged, and adjust counters accordingly. - */ - arena->npurgatory -= npurgeable; - npurgatory -= npurgeable; - npurged = arena_chunk_purge(arena, chunk, all); - nunpurged = npurgeable - npurged; - arena->npurgatory += nunpurged; - npurgatory += nunpurged; - } +static bool +arena_decay_muzzy(tsdn_t *tsdn, arena_t *arena, bool is_background_thread, + bool all) { + return arena_decay_impl(tsdn, arena, &arena->decay_muzzy, + &arena->extents_muzzy, is_background_thread, all); } void -arena_purge_all(arena_t *arena) -{ - - malloc_mutex_lock(&arena->lock); - arena_purge(arena, true); - malloc_mutex_unlock(&arena->lock); +arena_decay(tsdn_t *tsdn, arena_t *arena, bool is_background_thread, bool all) { + if (arena_decay_dirty(tsdn, arena, is_background_thread, all)) { + return; + } + arena_decay_muzzy(tsdn, arena, is_background_thread, all); } static void -arena_run_coalesce(arena_t *arena, arena_chunk_t *chunk, size_t *p_size, - size_t *p_run_ind, size_t *p_run_pages, size_t flag_dirty) -{ - size_t size = *p_size; - size_t run_ind = *p_run_ind; - size_t run_pages = *p_run_pages; - - /* Try to coalesce forward. */ - if (run_ind + run_pages < chunk_npages && - arena_mapbits_allocated_get(chunk, run_ind+run_pages) == 0 && - arena_mapbits_dirty_get(chunk, run_ind+run_pages) == flag_dirty) { - size_t nrun_size = arena_mapbits_unallocated_size_get(chunk, - run_ind+run_pages); - size_t nrun_pages = nrun_size >> LG_PAGE; - - /* - * Remove successor from runs_avail; the coalesced run is - * inserted later. - */ - assert(arena_mapbits_unallocated_size_get(chunk, - run_ind+run_pages+nrun_pages-1) == nrun_size); - assert(arena_mapbits_dirty_get(chunk, - run_ind+run_pages+nrun_pages-1) == flag_dirty); - arena_avail_remove(arena, chunk, run_ind+run_pages, nrun_pages, - false, true); +arena_slab_dalloc(tsdn_t *tsdn, arena_t *arena, extent_t *slab) { + arena_nactive_sub(arena, extent_size_get(slab) >> LG_PAGE); - size += nrun_size; - run_pages += nrun_pages; - - arena_mapbits_unallocated_size_set(chunk, run_ind, size); - arena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1, - size); - } - - /* Try to coalesce backward. */ - if (run_ind > map_bias && arena_mapbits_allocated_get(chunk, - run_ind-1) == 0 && arena_mapbits_dirty_get(chunk, run_ind-1) == - flag_dirty) { - size_t prun_size = arena_mapbits_unallocated_size_get(chunk, - run_ind-1); - size_t prun_pages = prun_size >> LG_PAGE; - - run_ind -= prun_pages; + extent_hooks_t *extent_hooks = EXTENT_HOOKS_INITIALIZER; + arena_extents_dirty_dalloc(tsdn, arena, &extent_hooks, slab); +} - /* - * Remove predecessor from runs_avail; the coalesced run is - * inserted later. - */ - assert(arena_mapbits_unallocated_size_get(chunk, run_ind) == - prun_size); - assert(arena_mapbits_dirty_get(chunk, run_ind) == flag_dirty); - arena_avail_remove(arena, chunk, run_ind, prun_pages, true, - false); +static void +arena_bin_slabs_nonfull_insert(arena_bin_t *bin, extent_t *slab) { + assert(extent_nfree_get(slab) > 0); + extent_heap_insert(&bin->slabs_nonfull, slab); +} - size += prun_size; - run_pages += prun_pages; +static void +arena_bin_slabs_nonfull_remove(arena_bin_t *bin, extent_t *slab) { + extent_heap_remove(&bin->slabs_nonfull, slab); +} - arena_mapbits_unallocated_size_set(chunk, run_ind, size); - arena_mapbits_unallocated_size_set(chunk, run_ind+run_pages-1, - size); +static extent_t * +arena_bin_slabs_nonfull_tryget(arena_bin_t *bin) { + extent_t *slab = extent_heap_remove_first(&bin->slabs_nonfull); + if (slab == NULL) { + return NULL; } - - *p_size = size; - *p_run_ind = run_ind; - *p_run_pages = run_pages; + if (config_stats) { + bin->stats.reslabs++; + } + return slab; } static void -arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty, bool cleaned) -{ - arena_chunk_t *chunk; - size_t size, run_ind, run_pages, flag_dirty; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); - assert(run_ind >= map_bias); - assert(run_ind < chunk_npages); - if (arena_mapbits_large_get(chunk, run_ind) != 0) { - size = arena_mapbits_large_size_get(chunk, run_ind); - assert(size == PAGE || - arena_mapbits_large_size_get(chunk, - run_ind+(size>>LG_PAGE)-1) == 0); - } else { - size_t binind = arena_bin_index(arena, run->bin); - arena_bin_info_t *bin_info = &arena_bin_info[binind]; - size = bin_info->run_size; - } - run_pages = (size >> LG_PAGE); - arena_cactive_update(arena, 0, run_pages); - arena->nactive -= run_pages; - +arena_bin_slabs_full_insert(arena_t *arena, arena_bin_t *bin, extent_t *slab) { + assert(extent_nfree_get(slab) == 0); /* - * The run is dirty if the caller claims to have dirtied it, as well as - * if it was already dirty before being allocated and the caller - * doesn't claim to have cleaned it. + * Tracking extents is required by arena_reset, which is not allowed + * for auto arenas. Bypass this step to avoid touching the extent + * linkage (often results in cache misses) for auto arenas. */ - assert(arena_mapbits_dirty_get(chunk, run_ind) == - arena_mapbits_dirty_get(chunk, run_ind+run_pages-1)); - if (cleaned == false && arena_mapbits_dirty_get(chunk, run_ind) != 0) - dirty = true; - flag_dirty = dirty ? CHUNK_MAP_DIRTY : 0; - - /* Mark pages as unallocated in the chunk map. */ - if (dirty) { - arena_mapbits_unallocated_set(chunk, run_ind, size, - CHUNK_MAP_DIRTY); - arena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size, - CHUNK_MAP_DIRTY); - } else { - arena_mapbits_unallocated_set(chunk, run_ind, size, - arena_mapbits_unzeroed_get(chunk, run_ind)); - arena_mapbits_unallocated_set(chunk, run_ind+run_pages-1, size, - arena_mapbits_unzeroed_get(chunk, run_ind+run_pages-1)); + if (arena_is_auto(arena)) { + return; } + extent_list_append(&bin->slabs_full, slab); +} - arena_run_coalesce(arena, chunk, &size, &run_ind, &run_pages, - flag_dirty); - - /* Insert into runs_avail, now that coalescing is complete. */ - assert(arena_mapbits_unallocated_size_get(chunk, run_ind) == - arena_mapbits_unallocated_size_get(chunk, run_ind+run_pages-1)); - assert(arena_mapbits_dirty_get(chunk, run_ind) == - arena_mapbits_dirty_get(chunk, run_ind+run_pages-1)); - arena_avail_insert(arena, chunk, run_ind, run_pages, true, true); - - /* Deallocate chunk if it is now completely unused. */ - if (size == arena_maxclass) { - assert(run_ind == map_bias); - assert(run_pages == (arena_maxclass >> LG_PAGE)); - arena_chunk_dealloc(arena, chunk); +static void +arena_bin_slabs_full_remove(arena_t *arena, arena_bin_t *bin, extent_t *slab) { + if (arena_is_auto(arena)) { + return; } + extent_list_remove(&bin->slabs_full, slab); +} +void +arena_reset(tsd_t *tsd, arena_t *arena) { /* - * It is okay to do dirty page processing here even if the chunk was - * deallocated above, since in that case it is the spare. Waiting - * until after possible chunk deallocation to do dirty processing - * allows for an old spare to be fully deallocated, thus decreasing the - * chances of spuriously crossing the dirty page purging threshold. + * Locking in this function is unintuitive. The caller guarantees that + * no concurrent operations are happening in this arena, but there are + * still reasons that some locking is necessary: + * + * - Some of the functions in the transitive closure of calls assume + * appropriate locks are held, and in some cases these locks are + * temporarily dropped to avoid lock order reversal or deadlock due to + * reentry. + * - mallctl("epoch", ...) may concurrently refresh stats. While + * strictly speaking this is a "concurrent operation", disallowing + * stats refreshes would impose an inconvenient burden. */ - if (dirty) - arena_maybe_purge(arena); -} -static void -arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - size_t oldsize, size_t newsize) -{ - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; - size_t head_npages = (oldsize - newsize) >> LG_PAGE; - size_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind); + /* Large allocations. */ + malloc_mutex_lock(tsd_tsdn(tsd), &arena->large_mtx); - assert(oldsize > newsize); + for (extent_t *extent = extent_list_first(&arena->large); extent != + NULL; extent = extent_list_first(&arena->large)) { + void *ptr = extent_base_get(extent); + size_t usize; - /* - * Update the chunk map so that arena_run_dalloc() can treat the - * leading run as separately allocated. Set the last element of each - * run first, in case of single-page runs. - */ - assert(arena_mapbits_large_size_get(chunk, pageind) == oldsize); - arena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty); - arena_mapbits_large_set(chunk, pageind, oldsize-newsize, flag_dirty); + malloc_mutex_unlock(tsd_tsdn(tsd), &arena->large_mtx); + alloc_ctx_t alloc_ctx; + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind != NSIZES); - if (config_debug) { - UNUSED size_t tail_npages = newsize >> LG_PAGE; - assert(arena_mapbits_large_size_get(chunk, - pageind+head_npages+tail_npages-1) == 0); - assert(arena_mapbits_dirty_get(chunk, - pageind+head_npages+tail_npages-1) == flag_dirty); + if (config_stats || (config_prof && opt_prof)) { + usize = sz_index2size(alloc_ctx.szind); + assert(usize == isalloc(tsd_tsdn(tsd), ptr)); + } + /* Remove large allocation from prof sample set. */ + if (config_prof && opt_prof) { + prof_free(tsd, ptr, usize, &alloc_ctx); + } + large_dalloc(tsd_tsdn(tsd), extent); + malloc_mutex_lock(tsd_tsdn(tsd), &arena->large_mtx); + } + malloc_mutex_unlock(tsd_tsdn(tsd), &arena->large_mtx); + + /* Bins. */ + for (unsigned i = 0; i < NBINS; i++) { + extent_t *slab; + arena_bin_t *bin = &arena->bins[i]; + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + if (bin->slabcur != NULL) { + slab = bin->slabcur; + bin->slabcur = NULL; + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + } + while ((slab = extent_heap_remove_first(&bin->slabs_nonfull)) != + NULL) { + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + } + for (slab = extent_list_first(&bin->slabs_full); slab != NULL; + slab = extent_list_first(&bin->slabs_full)) { + arena_bin_slabs_full_remove(arena, bin, slab); + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_slab_dalloc(tsd_tsdn(tsd), arena, slab); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + } + if (config_stats) { + bin->stats.curregs = 0; + bin->stats.curslabs = 0; + } + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); } - arena_mapbits_large_set(chunk, pageind+head_npages, newsize, - flag_dirty); - arena_run_dalloc(arena, run, false, false); + atomic_store_zu(&arena->nactive, 0, ATOMIC_RELAXED); } static void -arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - size_t oldsize, size_t newsize, bool dirty) -{ - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; - size_t head_npages = newsize >> LG_PAGE; - size_t flag_dirty = arena_mapbits_dirty_get(chunk, pageind); - - assert(oldsize > newsize); - +arena_destroy_retained(tsdn_t *tsdn, arena_t *arena) { /* - * Update the chunk map so that arena_run_dalloc() can treat the - * trailing run as separately allocated. Set the last element of each - * run first, in case of single-page runs. + * Iterate over the retained extents and destroy them. This gives the + * extent allocator underlying the extent hooks an opportunity to unmap + * all retained memory without having to keep its own metadata + * structures. In practice, virtual memory for dss-allocated extents is + * leaked here, so best practice is to avoid dss for arenas to be + * destroyed, or provide custom extent hooks that track retained + * dss-based extents for later reuse. */ - assert(arena_mapbits_large_size_get(chunk, pageind) == oldsize); - arena_mapbits_large_set(chunk, pageind+head_npages-1, 0, flag_dirty); - arena_mapbits_large_set(chunk, pageind, newsize, flag_dirty); - - if (config_debug) { - UNUSED size_t tail_npages = (oldsize - newsize) >> LG_PAGE; - assert(arena_mapbits_large_size_get(chunk, - pageind+head_npages+tail_npages-1) == 0); - assert(arena_mapbits_dirty_get(chunk, - pageind+head_npages+tail_npages-1) == flag_dirty); + extent_hooks_t *extent_hooks = extent_hooks_get(arena); + extent_t *extent; + while ((extent = extents_evict(tsdn, arena, &extent_hooks, + &arena->extents_retained, 0)) != NULL) { + extent_destroy_wrapper(tsdn, arena, &extent_hooks, extent); } - arena_mapbits_large_set(chunk, pageind+head_npages, oldsize-newsize, - flag_dirty); - - arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), - dirty, false); } -static arena_run_t * -arena_bin_runs_first(arena_bin_t *bin) -{ - arena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs); - if (mapelm != NULL) { - arena_chunk_t *chunk; - size_t pageind; - arena_run_t *run; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); - pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t))) + map_bias; - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - arena_mapbits_small_runind_get(chunk, pageind)) << - LG_PAGE)); - return (run); - } +void +arena_destroy(tsd_t *tsd, arena_t *arena) { + assert(base_ind_get(arena->base) >= narenas_auto); + assert(arena_nthreads_get(arena, false) == 0); + assert(arena_nthreads_get(arena, true) == 0); - return (NULL); -} + /* + * No allocations have occurred since arena_reset() was called. + * Furthermore, the caller (arena_i_destroy_ctl()) purged all cached + * extents, so only retained extents may remain. + */ + assert(extents_npages_get(&arena->extents_dirty) == 0); + assert(extents_npages_get(&arena->extents_muzzy) == 0); -static void -arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run) -{ - arena_chunk_t *chunk = CHUNK_ADDR2BASE(run); - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; - arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); + /* Deallocate retained memory. */ + arena_destroy_retained(tsd_tsdn(tsd), arena); - assert(arena_run_tree_search(&bin->runs, mapelm) == NULL); + /* + * Remove the arena pointer from the arenas array. We rely on the fact + * that there is no way for the application to get a dirty read from the + * arenas array unless there is an inherent race in the application + * involving access of an arena being concurrently destroyed. The + * application must synchronize knowledge of the arena's validity, so as + * long as we use an atomic write to update the arenas array, the + * application will get a clean read any time after it synchronizes + * knowledge that the arena is no longer valid. + */ + arena_set(base_ind_get(arena->base), NULL); - arena_run_tree_insert(&bin->runs, mapelm); + /* + * Destroy the base allocator, which manages all metadata ever mapped by + * this arena. + */ + base_delete(tsd_tsdn(tsd), arena->base); } -static void -arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run) -{ - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; - arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); +static extent_t * +arena_slab_alloc_hard(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, const arena_bin_info_t *bin_info, + szind_t szind) { + extent_t *slab; + bool zero, commit; - assert(arena_run_tree_search(&bin->runs, mapelm) != NULL); - - arena_run_tree_remove(&bin->runs, mapelm); -} + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); -static arena_run_t * -arena_bin_nonfull_run_tryget(arena_bin_t *bin) -{ - arena_run_t *run = arena_bin_runs_first(bin); - if (run != NULL) { - arena_bin_runs_remove(bin, run); - if (config_stats) - bin->stats.reruns++; + zero = false; + commit = true; + slab = extent_alloc_wrapper(tsdn, arena, r_extent_hooks, NULL, + bin_info->slab_size, 0, PAGE, true, szind, &zero, &commit); + + if (config_stats && slab != NULL) { + arena_stats_mapped_add(tsdn, &arena->stats, + bin_info->slab_size); + } + + return slab; +} + +static extent_t * +arena_slab_alloc(tsdn_t *tsdn, arena_t *arena, szind_t binind, + const arena_bin_info_t *bin_info) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + extent_hooks_t *extent_hooks = EXTENT_HOOKS_INITIALIZER; + szind_t szind = sz_size2index(bin_info->reg_size); + bool zero = false; + bool commit = true; + extent_t *slab = extents_alloc(tsdn, arena, &extent_hooks, + &arena->extents_dirty, NULL, bin_info->slab_size, 0, PAGE, true, + binind, &zero, &commit); + if (slab == NULL) { + slab = extents_alloc(tsdn, arena, &extent_hooks, + &arena->extents_muzzy, NULL, bin_info->slab_size, 0, PAGE, + true, binind, &zero, &commit); + } + if (slab == NULL) { + slab = arena_slab_alloc_hard(tsdn, arena, &extent_hooks, + bin_info, szind); + if (slab == NULL) { + return NULL; + } } - return (run); + assert(extent_slab_get(slab)); + + /* Initialize slab internals. */ + arena_slab_data_t *slab_data = extent_slab_data_get(slab); + extent_nfree_set(slab, bin_info->nregs); + bitmap_init(slab_data->bitmap, &bin_info->bitmap_info, false); + + arena_nactive_add(arena, extent_size_get(slab) >> LG_PAGE); + + return slab; } -static arena_run_t * -arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) -{ - arena_run_t *run; - size_t binind; - arena_bin_info_t *bin_info; +static extent_t * +arena_bin_nonfull_slab_get(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, + szind_t binind) { + extent_t *slab; + const arena_bin_info_t *bin_info; - /* Look for a usable run. */ - run = arena_bin_nonfull_run_tryget(bin); - if (run != NULL) - return (run); - /* No existing runs have any space available. */ + /* Look for a usable slab. */ + slab = arena_bin_slabs_nonfull_tryget(bin); + if (slab != NULL) { + return slab; + } + /* No existing slabs have any space available. */ - binind = arena_bin_index(arena, bin); bin_info = &arena_bin_info[binind]; - /* Allocate a new run. */ - malloc_mutex_unlock(&bin->lock); + /* Allocate a new slab. */ + malloc_mutex_unlock(tsdn, &bin->lock); /******************************/ - malloc_mutex_lock(&arena->lock); - run = arena_run_alloc_small(arena, bin_info->run_size, binind); - if (run != NULL) { - bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + - (uintptr_t)bin_info->bitmap_offset); - - /* Initialize run internals. */ - run->bin = bin; - run->nextind = 0; - run->nfree = bin_info->nregs; - bitmap_init(bitmap, &bin_info->bitmap_info); - } - malloc_mutex_unlock(&arena->lock); + slab = arena_slab_alloc(tsdn, arena, binind, bin_info); /********************************/ - malloc_mutex_lock(&bin->lock); - if (run != NULL) { + malloc_mutex_lock(tsdn, &bin->lock); + if (slab != NULL) { if (config_stats) { - bin->stats.nruns++; - bin->stats.curruns++; + bin->stats.nslabs++; + bin->stats.curslabs++; } - return (run); + return slab; } /* - * arena_run_alloc_small() failed, but another thread may have made + * arena_slab_alloc() failed, but another thread may have made * sufficient memory available while this one dropped bin->lock above, * so search one more time. */ - run = arena_bin_nonfull_run_tryget(bin); - if (run != NULL) - return (run); + slab = arena_bin_slabs_nonfull_tryget(bin); + if (slab != NULL) { + return slab; + } - return (NULL); + return NULL; } -/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */ +/* Re-fill bin->slabcur, then call arena_slab_reg_alloc(). */ static void * -arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) -{ - void *ret; - size_t binind; - arena_bin_info_t *bin_info; - arena_run_t *run; +arena_bin_malloc_hard(tsdn_t *tsdn, arena_t *arena, arena_bin_t *bin, + szind_t binind) { + const arena_bin_info_t *bin_info; + extent_t *slab; - binind = arena_bin_index(arena, bin); bin_info = &arena_bin_info[binind]; - bin->runcur = NULL; - run = arena_bin_nonfull_run_get(arena, bin); - if (bin->runcur != NULL && bin->runcur->nfree > 0) { + if (!arena_is_auto(arena) && bin->slabcur != NULL) { + arena_bin_slabs_full_insert(arena, bin, bin->slabcur); + bin->slabcur = NULL; + } + slab = arena_bin_nonfull_slab_get(tsdn, arena, bin, binind); + if (bin->slabcur != NULL) { /* - * Another thread updated runcur while this one ran without the - * bin lock in arena_bin_nonfull_run_get(). + * Another thread updated slabcur while this one ran without the + * bin lock in arena_bin_nonfull_slab_get(). */ - assert(bin->runcur->nfree > 0); - ret = arena_run_reg_alloc(bin->runcur, bin_info); - if (run != NULL) { - arena_chunk_t *chunk; - - /* - * arena_run_alloc_small() may have allocated run, or - * it may have pulled run from the bin's run tree. - * Therefore it is unsafe to make any assumptions about - * how run has previously been used, and - * arena_bin_lower_run() must be called, as if a region - * were just deallocated from the run. - */ - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - if (run->nfree == bin_info->nregs) - arena_dalloc_bin_run(arena, chunk, run, bin); - else - arena_bin_lower_run(arena, chunk, run, bin); + if (extent_nfree_get(bin->slabcur) > 0) { + void *ret = arena_slab_reg_alloc(tsdn, bin->slabcur, + bin_info); + if (slab != NULL) { + /* + * arena_slab_alloc() may have allocated slab, + * or it may have been pulled from + * slabs_nonfull. Therefore it is unsafe to + * make any assumptions about how slab has + * previously been used, and + * arena_bin_lower_slab() must be called, as if + * a region were just deallocated from the slab. + */ + if (extent_nfree_get(slab) == bin_info->nregs) { + arena_dalloc_bin_slab(tsdn, arena, slab, + bin); + } else { + arena_bin_lower_slab(tsdn, arena, slab, + bin); + } + } + return ret; } - return (ret); - } - if (run == NULL) - return (NULL); + arena_bin_slabs_full_insert(arena, bin, bin->slabcur); + bin->slabcur = NULL; + } - bin->runcur = run; + if (slab == NULL) { + return NULL; + } + bin->slabcur = slab; - assert(bin->runcur->nfree > 0); + assert(extent_nfree_get(bin->slabcur) > 0); - return (arena_run_reg_alloc(bin->runcur, bin_info)); + return arena_slab_reg_alloc(tsdn, slab, bin_info); } void -arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind, - uint64_t prof_accumbytes) -{ +arena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, + tcache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes) { unsigned i, nfill; arena_bin_t *bin; - arena_run_t *run; - void *ptr; assert(tbin->ncached == 0); - if (config_prof && arena_prof_accum(arena, prof_accumbytes)) - prof_idump(); + if (config_prof && arena_prof_accum(tsdn, arena, prof_accumbytes)) { + prof_idump(tsdn); + } bin = &arena->bins[binind]; - malloc_mutex_lock(&bin->lock); + malloc_mutex_lock(tsdn, &bin->lock); for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >> - tbin->lg_fill_div); i < nfill; i++) { - if ((run = bin->runcur) != NULL && run->nfree > 0) - ptr = arena_run_reg_alloc(run, &arena_bin_info[binind]); - else - ptr = arena_bin_malloc_hard(arena, bin); - if (ptr == NULL) + tcache->lg_fill_div[binind]); i < nfill; i++) { + extent_t *slab; + void *ptr; + if ((slab = bin->slabcur) != NULL && extent_nfree_get(slab) > + 0) { + ptr = arena_slab_reg_alloc(tsdn, slab, + &arena_bin_info[binind]); + } else { + ptr = arena_bin_malloc_hard(tsdn, arena, bin, binind); + } + if (ptr == NULL) { + /* + * OOM. tbin->avail isn't yet filled down to its first + * element, so the successful allocations (if any) must + * be moved just before tbin->avail before bailing out. + */ + if (i > 0) { + memmove(tbin->avail - i, tbin->avail - nfill, + i * sizeof(void *)); + } break; - if (config_fill && opt_junk) { + } + if (config_fill && unlikely(opt_junk_alloc)) { arena_alloc_junk_small(ptr, &arena_bin_info[binind], true); } /* Insert such that low regions get used first. */ - tbin->avail[nfill - 1 - i] = ptr; + *(tbin->avail - nfill + i) = ptr; } if (config_stats) { - bin->stats.allocated += i * arena_bin_info[binind].reg_size; bin->stats.nmalloc += i; bin->stats.nrequests += tbin->tstats.nrequests; + bin->stats.curregs += i; bin->stats.nfills++; tbin->tstats.nrequests = 0; } - malloc_mutex_unlock(&bin->lock); + malloc_mutex_unlock(tsdn, &bin->lock); tbin->ncached = i; + arena_decay_tick(tsdn, arena); } void -arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero) -{ - - if (zero) { - size_t redzone_size = bin_info->redzone_size; - memset((void *)((uintptr_t)ptr - redzone_size), 0xa5, - redzone_size); - memset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5, - redzone_size); - } else { - memset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5, - bin_info->reg_interval); +arena_alloc_junk_small(void *ptr, const arena_bin_info_t *bin_info, bool zero) { + if (!zero) { + memset(ptr, JEMALLOC_ALLOC_JUNK, bin_info->reg_size); } } -#ifdef JEMALLOC_JET -#undef arena_redzone_corruption -#define arena_redzone_corruption JEMALLOC_N(arena_redzone_corruption_impl) -#endif -static void -arena_redzone_corruption(void *ptr, size_t usize, bool after, - size_t offset, uint8_t byte) -{ - - malloc_printf("<jemalloc>: Corrupt redzone %zu byte%s %s %p " - "(size %zu), byte=%#x\n", offset, (offset == 1) ? "" : "s", - after ? "after" : "before", ptr, usize, byte); -} -#ifdef JEMALLOC_JET -#undef arena_redzone_corruption -#define arena_redzone_corruption JEMALLOC_N(arena_redzone_corruption) -arena_redzone_corruption_t *arena_redzone_corruption = - JEMALLOC_N(arena_redzone_corruption_impl); -#endif - static void -arena_redzones_validate(void *ptr, arena_bin_info_t *bin_info, bool reset) -{ - size_t size = bin_info->reg_size; - size_t redzone_size = bin_info->redzone_size; - size_t i; - bool error = false; - - for (i = 1; i <= redzone_size; i++) { - uint8_t *byte = (uint8_t *)((uintptr_t)ptr - i); - if (*byte != 0xa5) { - error = true; - arena_redzone_corruption(ptr, size, false, i, *byte); - if (reset) - *byte = 0xa5; - } - } - for (i = 0; i < redzone_size; i++) { - uint8_t *byte = (uint8_t *)((uintptr_t)ptr + size + i); - if (*byte != 0xa5) { - error = true; - arena_redzone_corruption(ptr, size, true, i, *byte); - if (reset) - *byte = 0xa5; - } - } - if (opt_abort && error) - abort(); +arena_dalloc_junk_small_impl(void *ptr, const arena_bin_info_t *bin_info) { + memset(ptr, JEMALLOC_FREE_JUNK, bin_info->reg_size); } +arena_dalloc_junk_small_t *JET_MUTABLE arena_dalloc_junk_small = + arena_dalloc_junk_small_impl; -#ifdef JEMALLOC_JET -#undef arena_dalloc_junk_small -#define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small_impl) -#endif -void -arena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info) -{ - size_t redzone_size = bin_info->redzone_size; - - arena_redzones_validate(ptr, bin_info, false); - memset((void *)((uintptr_t)ptr - redzone_size), 0x5a, - bin_info->reg_interval); -} -#ifdef JEMALLOC_JET -#undef arena_dalloc_junk_small -#define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small) -arena_dalloc_junk_small_t *arena_dalloc_junk_small = - JEMALLOC_N(arena_dalloc_junk_small_impl); -#endif - -void -arena_quarantine_junk_small(void *ptr, size_t usize) -{ - size_t binind; - arena_bin_info_t *bin_info; - cassert(config_fill); - assert(opt_junk); - assert(opt_quarantine); - assert(usize <= SMALL_MAXCLASS); - - binind = SMALL_SIZE2BIN(usize); - bin_info = &arena_bin_info[binind]; - arena_redzones_validate(ptr, bin_info, true); -} - -void * -arena_malloc_small(arena_t *arena, size_t size, bool zero) -{ +static void * +arena_malloc_small(tsdn_t *tsdn, arena_t *arena, szind_t binind, bool zero) { void *ret; arena_bin_t *bin; - arena_run_t *run; - size_t binind; + size_t usize; + extent_t *slab; - binind = SMALL_SIZE2BIN(size); assert(binind < NBINS); bin = &arena->bins[binind]; - size = arena_bin_info[binind].reg_size; + usize = sz_index2size(binind); - malloc_mutex_lock(&bin->lock); - if ((run = bin->runcur) != NULL && run->nfree > 0) - ret = arena_run_reg_alloc(run, &arena_bin_info[binind]); - else - ret = arena_bin_malloc_hard(arena, bin); + malloc_mutex_lock(tsdn, &bin->lock); + if ((slab = bin->slabcur) != NULL && extent_nfree_get(slab) > 0) { + ret = arena_slab_reg_alloc(tsdn, slab, &arena_bin_info[binind]); + } else { + ret = arena_bin_malloc_hard(tsdn, arena, bin, binind); + } if (ret == NULL) { - malloc_mutex_unlock(&bin->lock); - return (NULL); + malloc_mutex_unlock(tsdn, &bin->lock); + return NULL; } if (config_stats) { - bin->stats.allocated += size; bin->stats.nmalloc++; bin->stats.nrequests++; + bin->stats.curregs++; + } + malloc_mutex_unlock(tsdn, &bin->lock); + if (config_prof && arena_prof_accum(tsdn, arena, usize)) { + prof_idump(tsdn); } - malloc_mutex_unlock(&bin->lock); - if (config_prof && isthreaded == false && arena_prof_accum(arena, size)) - prof_idump(); - if (zero == false) { + if (!zero) { if (config_fill) { - if (opt_junk) { + if (unlikely(opt_junk_alloc)) { arena_alloc_junk_small(ret, &arena_bin_info[binind], false); - } else if (opt_zero) - memset(ret, 0, size); + } else if (unlikely(opt_zero)) { + memset(ret, 0, usize); + } } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); } else { - if (config_fill && opt_junk) { + if (config_fill && unlikely(opt_junk_alloc)) { arena_alloc_junk_small(ret, &arena_bin_info[binind], true); } - VALGRIND_MAKE_MEM_UNDEFINED(ret, size); - memset(ret, 0, size); + memset(ret, 0, usize); } - return (ret); + arena_decay_tick(tsdn, arena); + return ret; } void * -arena_malloc_large(arena_t *arena, size_t size, bool zero) -{ - void *ret; - UNUSED bool idump; +arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, + bool zero) { + assert(!tsdn_null(tsdn) || arena != NULL); - /* Large allocation. */ - size = PAGE_CEILING(size); - malloc_mutex_lock(&arena->lock); - ret = (void *)arena_run_alloc_large(arena, size, zero); - if (ret == NULL) { - malloc_mutex_unlock(&arena->lock); - return (NULL); + if (likely(!tsdn_null(tsdn))) { + arena = arena_choose(tsdn_tsd(tsdn), arena); } - if (config_stats) { - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; - arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; - arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; - } - if (config_prof) - idump = arena_prof_accum_locked(arena, size); - malloc_mutex_unlock(&arena->lock); - if (config_prof && idump) - prof_idump(); - - if (zero == false) { - if (config_fill) { - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - } + if (unlikely(arena == NULL)) { + return NULL; } - return (ret); + if (likely(size <= SMALL_MAXCLASS)) { + return arena_malloc_small(tsdn, arena, ind, zero); + } + return large_malloc(tsdn, arena, sz_index2size(ind), zero); } -/* Only handles large allocations that require more than page alignment. */ void * -arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero) -{ +arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, + bool zero, tcache_t *tcache) { void *ret; - size_t alloc_size, leadsize, trailsize; - arena_run_t *run; - arena_chunk_t *chunk; - assert((size & PAGE_MASK) == 0); + if (usize <= SMALL_MAXCLASS && (alignment < PAGE || (alignment == PAGE + && (usize & PAGE_MASK) == 0))) { + /* Small; alignment doesn't require special slab placement. */ + ret = arena_malloc(tsdn, arena, usize, sz_size2index(usize), + zero, tcache, true); + } else { + if (likely(alignment <= CACHELINE)) { + ret = large_malloc(tsdn, arena, usize, zero); + } else { + ret = large_palloc(tsdn, arena, usize, alignment, zero); + } + } + return ret; +} - alignment = PAGE_CEILING(alignment); - alloc_size = size + alignment - PAGE; +void +arena_prof_promote(tsdn_t *tsdn, const void *ptr, size_t usize) { + cassert(config_prof); + assert(ptr != NULL); + assert(isalloc(tsdn, ptr) == LARGE_MINCLASS); + assert(usize <= SMALL_MAXCLASS); - malloc_mutex_lock(&arena->lock); - run = arena_run_alloc_large(arena, alloc_size, false); - if (run == NULL) { - malloc_mutex_unlock(&arena->lock); - return (NULL); - } - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); - leadsize = ALIGNMENT_CEILING((uintptr_t)run, alignment) - - (uintptr_t)run; - assert(alloc_size >= leadsize + size); - trailsize = alloc_size - leadsize - size; - ret = (void *)((uintptr_t)run + leadsize); - if (leadsize != 0) { - arena_run_trim_head(arena, chunk, run, alloc_size, alloc_size - - leadsize); - } - if (trailsize != 0) { - arena_run_trim_tail(arena, chunk, ret, size + trailsize, size, - false); - } - arena_run_init_large(arena, (arena_run_t *)ret, size, zero); + extent_t *extent = rtree_extent_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true); + arena_t *arena = extent_arena_get(extent); - if (config_stats) { - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; - arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; - arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; - } - malloc_mutex_unlock(&arena->lock); + szind_t szind = sz_size2index(usize); + extent_szind_set(extent, szind); + rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, + szind, false); - if (config_fill && zero == false) { - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - } - return (ret); -} + prof_accum_cancel(tsdn, &arena->prof_accum, usize); -void -arena_prof_promoted(const void *ptr, size_t size) -{ - arena_chunk_t *chunk; - size_t pageind, binind; + assert(isalloc(tsdn, ptr) == usize); +} +static size_t +arena_prof_demote(tsdn_t *tsdn, extent_t *extent, const void *ptr) { cassert(config_prof); assert(ptr != NULL); - assert(CHUNK_ADDR2BASE(ptr) != ptr); - assert(isalloc(ptr, false) == PAGE); - assert(isalloc(ptr, true) == PAGE); - assert(size <= SMALL_MAXCLASS); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; - binind = SMALL_SIZE2BIN(size); - assert(binind < NBINS); - arena_mapbits_large_binind_set(chunk, pageind, binind); - assert(isalloc(ptr, false) == PAGE); - assert(isalloc(ptr, true) == size); + extent_szind_set(extent, NBINS); + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, + NBINS, false); + + assert(isalloc(tsdn, ptr) == LARGE_MINCLASS); + + return LARGE_MINCLASS; +} + +void +arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, + bool slow_path) { + cassert(config_prof); + assert(opt_prof); + + extent_t *extent = iealloc(tsdn, ptr); + size_t usize = arena_prof_demote(tsdn, extent, ptr); + if (usize <= tcache_maxclass) { + tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, + sz_size2index(usize), slow_path); + } else { + large_dalloc(tsdn, extent); + } } static void -arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run, - arena_bin_t *bin) -{ - - /* Dissociate run from bin. */ - if (run == bin->runcur) - bin->runcur = NULL; - else { - size_t binind = arena_bin_index(chunk->arena, bin); - arena_bin_info_t *bin_info = &arena_bin_info[binind]; - - if (bin_info->nregs != 1) { - /* - * This block's conditional is necessary because if the - * run only contains one region, then it never gets - * inserted into the non-full runs tree. - */ - arena_bin_runs_remove(bin, run); +arena_dissociate_bin_slab(arena_t *arena, extent_t *slab, arena_bin_t *bin) { + /* Dissociate slab from bin. */ + if (slab == bin->slabcur) { + bin->slabcur = NULL; + } else { + szind_t binind = extent_szind_get(slab); + const arena_bin_info_t *bin_info = &arena_bin_info[binind]; + + /* + * The following block's conditional is necessary because if the + * slab only contains one region, then it never gets inserted + * into the non-full slabs heap. + */ + if (bin_info->nregs == 1) { + arena_bin_slabs_full_remove(arena, bin, slab); + } else { + arena_bin_slabs_nonfull_remove(bin, slab); } } } static void -arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - arena_bin_t *bin) -{ - size_t binind; - arena_bin_info_t *bin_info; - size_t npages, run_ind, past; - - assert(run != bin->runcur); - assert(arena_run_tree_search(&bin->runs, - arena_mapp_get(chunk, ((uintptr_t)run-(uintptr_t)chunk)>>LG_PAGE)) - == NULL); - - binind = arena_bin_index(chunk->arena, run->bin); - bin_info = &arena_bin_info[binind]; +arena_dalloc_bin_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, + arena_bin_t *bin) { + assert(slab != bin->slabcur); - malloc_mutex_unlock(&bin->lock); + malloc_mutex_unlock(tsdn, &bin->lock); /******************************/ - npages = bin_info->run_size >> LG_PAGE; - run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); - past = (size_t)(PAGE_CEILING((uintptr_t)run + - (uintptr_t)bin_info->reg0_offset + (uintptr_t)(run->nextind * - bin_info->reg_interval - bin_info->redzone_size) - - (uintptr_t)chunk) >> LG_PAGE); - malloc_mutex_lock(&arena->lock); - - /* - * If the run was originally clean, and some pages were never touched, - * trim the clean pages before deallocating the dirty portion of the - * run. - */ - assert(arena_mapbits_dirty_get(chunk, run_ind) == - arena_mapbits_dirty_get(chunk, run_ind+npages-1)); - if (arena_mapbits_dirty_get(chunk, run_ind) == 0 && past - run_ind < - npages) { - /* Trim clean pages. Convert to large run beforehand. */ - assert(npages > 0); - arena_mapbits_large_set(chunk, run_ind, bin_info->run_size, 0); - arena_mapbits_large_set(chunk, run_ind+npages-1, 0, 0); - arena_run_trim_tail(arena, chunk, run, (npages << LG_PAGE), - ((past - run_ind) << LG_PAGE), false); - /* npages = past - run_ind; */ - } - arena_run_dalloc(arena, run, true, false); - malloc_mutex_unlock(&arena->lock); + arena_slab_dalloc(tsdn, arena, slab); /****************************/ - malloc_mutex_lock(&bin->lock); - if (config_stats) - bin->stats.curruns--; + malloc_mutex_lock(tsdn, &bin->lock); + if (config_stats) { + bin->stats.curslabs--; + } } static void -arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - arena_bin_t *bin) -{ +arena_bin_lower_slab(tsdn_t *tsdn, arena_t *arena, extent_t *slab, + arena_bin_t *bin) { + assert(extent_nfree_get(slab) > 0); /* - * Make sure that if bin->runcur is non-NULL, it refers to the lowest - * non-full run. It is okay to NULL runcur out rather than proactively - * keeping it pointing at the lowest non-full run. + * Make sure that if bin->slabcur is non-NULL, it refers to the + * oldest/lowest non-full slab. It is okay to NULL slabcur out rather + * than proactively keeping it pointing at the oldest/lowest non-full + * slab. */ - if ((uintptr_t)run < (uintptr_t)bin->runcur) { - /* Switch runcur. */ - if (bin->runcur->nfree > 0) - arena_bin_runs_insert(bin, bin->runcur); - bin->runcur = run; - if (config_stats) - bin->stats.reruns++; - } else - arena_bin_runs_insert(bin, run); + if (bin->slabcur != NULL && extent_snad_comp(bin->slabcur, slab) > 0) { + /* Switch slabcur. */ + if (extent_nfree_get(bin->slabcur) > 0) { + arena_bin_slabs_nonfull_insert(bin, bin->slabcur); + } else { + arena_bin_slabs_full_insert(arena, bin, bin->slabcur); + } + bin->slabcur = slab; + if (config_stats) { + bin->stats.reslabs++; + } + } else { + arena_bin_slabs_nonfull_insert(bin, slab); + } } -void -arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr, - arena_chunk_map_t *mapelm) -{ - size_t pageind; - arena_run_t *run; - arena_bin_t *bin; - arena_bin_info_t *bin_info; - size_t size, binind; - - pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE)); - bin = run->bin; - binind = arena_ptr_small_binind_get(ptr, mapelm->bits); - bin_info = &arena_bin_info[binind]; - if (config_fill || config_stats) - size = bin_info->reg_size; - - if (config_fill && opt_junk) +static void +arena_dalloc_bin_locked_impl(tsdn_t *tsdn, arena_t *arena, extent_t *slab, + void *ptr, bool junked) { + arena_slab_data_t *slab_data = extent_slab_data_get(slab); + szind_t binind = extent_szind_get(slab); + arena_bin_t *bin = &arena->bins[binind]; + const arena_bin_info_t *bin_info = &arena_bin_info[binind]; + + if (!junked && config_fill && unlikely(opt_junk_free)) { arena_dalloc_junk_small(ptr, bin_info); + } - arena_run_reg_dalloc(run, ptr); - if (run->nfree == bin_info->nregs) { - arena_dissociate_bin_run(chunk, run, bin); - arena_dalloc_bin_run(arena, chunk, run, bin); - } else if (run->nfree == 1 && run != bin->runcur) - arena_bin_lower_run(arena, chunk, run, bin); + arena_slab_reg_dalloc(tsdn, slab, slab_data, ptr); + unsigned nfree = extent_nfree_get(slab); + if (nfree == bin_info->nregs) { + arena_dissociate_bin_slab(arena, slab, bin); + arena_dalloc_bin_slab(tsdn, arena, slab, bin); + } else if (nfree == 1 && slab != bin->slabcur) { + arena_bin_slabs_full_remove(arena, bin, slab); + arena_bin_lower_slab(tsdn, arena, slab, bin); + } if (config_stats) { - bin->stats.allocated -= size; bin->stats.ndalloc++; + bin->stats.curregs--; } } void -arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, - size_t pageind, arena_chunk_map_t *mapelm) -{ - arena_run_t *run; - arena_bin_t *bin; - - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - arena_mapbits_small_runind_get(chunk, pageind)) << LG_PAGE)); - bin = run->bin; - malloc_mutex_lock(&bin->lock); - arena_dalloc_bin_locked(arena, chunk, ptr, mapelm); - malloc_mutex_unlock(&bin->lock); -} - -void -arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr, - size_t pageind) -{ - arena_chunk_map_t *mapelm; - - if (config_debug) { - /* arena_ptr_small_binind_get() does extra sanity checking. */ - assert(arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk, - pageind)) != BININD_INVALID); - } - mapelm = arena_mapp_get(chunk, pageind); - arena_dalloc_bin(arena, chunk, ptr, pageind, mapelm); +arena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena, extent_t *extent, + void *ptr) { + arena_dalloc_bin_locked_impl(tsdn, arena, extent, ptr, true); } -#ifdef JEMALLOC_JET -#undef arena_dalloc_junk_large -#define arena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large_impl) -#endif static void -arena_dalloc_junk_large(void *ptr, size_t usize) -{ - - if (config_fill && opt_junk) - memset(ptr, 0x5a, usize); -} -#ifdef JEMALLOC_JET -#undef arena_dalloc_junk_large -#define arena_dalloc_junk_large JEMALLOC_N(arena_dalloc_junk_large) -arena_dalloc_junk_large_t *arena_dalloc_junk_large = - JEMALLOC_N(arena_dalloc_junk_large_impl); -#endif - -void -arena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr) -{ +arena_dalloc_bin(tsdn_t *tsdn, arena_t *arena, extent_t *extent, void *ptr) { + szind_t binind = extent_szind_get(extent); + arena_bin_t *bin = &arena->bins[binind]; - if (config_fill || config_stats) { - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; - size_t usize = arena_mapbits_large_size_get(chunk, pageind); - - arena_dalloc_junk_large(ptr, usize); - if (config_stats) { - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= usize; - arena->stats.lstats[(usize >> LG_PAGE) - 1].ndalloc++; - arena->stats.lstats[(usize >> LG_PAGE) - 1].curruns--; - } - } - - arena_run_dalloc(arena, (arena_run_t *)ptr, true, false); + malloc_mutex_lock(tsdn, &bin->lock); + arena_dalloc_bin_locked_impl(tsdn, arena, extent, ptr, false); + malloc_mutex_unlock(tsdn, &bin->lock); } void -arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) -{ +arena_dalloc_small(tsdn_t *tsdn, void *ptr) { + extent_t *extent = iealloc(tsdn, ptr); + arena_t *arena = extent_arena_get(extent); - malloc_mutex_lock(&arena->lock); - arena_dalloc_large_locked(arena, chunk, ptr); - malloc_mutex_unlock(&arena->lock); + arena_dalloc_bin(tsdn, arena, extent, ptr); + arena_decay_tick(tsdn, arena); } -static void -arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, - size_t oldsize, size_t size) -{ - - assert(size < oldsize); - - /* - * Shrink the run, and make trailing pages available for other - * allocations. - */ - malloc_mutex_lock(&arena->lock); - arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size, - true); - if (config_stats) { - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= oldsize; - arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++; - arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--; +bool +arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, + size_t extra, bool zero) { + /* Calls with non-zero extra had to clamp extra. */ + assert(extra == 0 || size + extra <= LARGE_MAXCLASS); - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; - arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; - arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; + if (unlikely(size > LARGE_MAXCLASS)) { + return true; } - malloc_mutex_unlock(&arena->lock); -} -static bool -arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, - size_t oldsize, size_t size, size_t extra, bool zero) -{ - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; - size_t npages = oldsize >> LG_PAGE; - size_t followsize; - - assert(oldsize == arena_mapbits_large_size_get(chunk, pageind)); - - /* Try to extend the run. */ - assert(size + extra > oldsize); - malloc_mutex_lock(&arena->lock); - if (pageind + npages < chunk_npages && - arena_mapbits_allocated_get(chunk, pageind+npages) == 0 && - (followsize = arena_mapbits_unallocated_size_get(chunk, - pageind+npages)) >= size - oldsize) { + extent_t *extent = iealloc(tsdn, ptr); + size_t usize_min = sz_s2u(size); + size_t usize_max = sz_s2u(size + extra); + if (likely(oldsize <= SMALL_MAXCLASS && usize_min <= SMALL_MAXCLASS)) { /* - * The next run is available and sufficiently large. Split the - * following run, then merge the first part with the existing - * allocation. + * Avoid moving the allocation if the size class can be left the + * same. */ - size_t flag_dirty; - size_t splitsize = (oldsize + followsize <= size + extra) - ? followsize : size + extra - oldsize; - arena_run_split_large(arena, (arena_run_t *)((uintptr_t)chunk + - ((pageind+npages) << LG_PAGE)), splitsize, zero); - - size = oldsize + splitsize; - npages = size >> LG_PAGE; - - /* - * Mark the extended run as dirty if either portion of the run - * was dirty before allocation. This is rather pedantic, - * because there's not actually any sequence of events that - * could cause the resulting run to be passed to - * arena_run_dalloc() with the dirty argument set to false - * (which is when dirty flag consistency would really matter). - */ - flag_dirty = arena_mapbits_dirty_get(chunk, pageind) | - arena_mapbits_dirty_get(chunk, pageind+npages-1); - arena_mapbits_large_set(chunk, pageind, size, flag_dirty); - arena_mapbits_large_set(chunk, pageind+npages-1, 0, flag_dirty); - - if (config_stats) { - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= oldsize; - arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++; - arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--; - - arena->stats.nmalloc_large++; - arena->stats.nrequests_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; - arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; - arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; + assert(arena_bin_info[sz_size2index(oldsize)].reg_size == + oldsize); + if ((usize_max > SMALL_MAXCLASS || sz_size2index(usize_max) != + sz_size2index(oldsize)) && (size > oldsize || usize_max < + oldsize)) { + return true; } - malloc_mutex_unlock(&arena->lock); - return (false); + + arena_decay_tick(tsdn, extent_arena_get(extent)); + return false; + } else if (oldsize >= LARGE_MINCLASS && usize_max >= LARGE_MINCLASS) { + return large_ralloc_no_move(tsdn, extent, usize_min, usize_max, + zero); } - malloc_mutex_unlock(&arena->lock); - return (true); + return true; } -#ifdef JEMALLOC_JET -#undef arena_ralloc_junk_large -#define arena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large_impl) -#endif -static void -arena_ralloc_junk_large(void *ptr, size_t old_usize, size_t usize) -{ - - if (config_fill && opt_junk) { - memset((void *)((uintptr_t)ptr + usize), 0x5a, - old_usize - usize); +static void * +arena_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize, + size_t alignment, bool zero, tcache_t *tcache) { + if (alignment == 0) { + return arena_malloc(tsdn, arena, usize, sz_size2index(usize), + zero, tcache, true); } -} -#ifdef JEMALLOC_JET -#undef arena_ralloc_junk_large -#define arena_ralloc_junk_large JEMALLOC_N(arena_ralloc_junk_large) -arena_ralloc_junk_large_t *arena_ralloc_junk_large = - JEMALLOC_N(arena_ralloc_junk_large_impl); -#endif - -/* - * Try to resize a large allocation, in order to avoid copying. This will - * always fail if growing an object, and the following run is already in use. - */ -static bool -arena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra, - bool zero) -{ - size_t psize; - - psize = PAGE_CEILING(size + extra); - if (psize == oldsize) { - /* Same size class. */ - return (false); - } else { - arena_chunk_t *chunk; - arena_t *arena; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - - if (psize < oldsize) { - /* Fill before shrinking in order avoid a race. */ - arena_ralloc_junk_large(ptr, oldsize, psize); - arena_ralloc_large_shrink(arena, chunk, ptr, oldsize, - psize); - return (false); - } else { - bool ret = arena_ralloc_large_grow(arena, chunk, ptr, - oldsize, PAGE_CEILING(size), - psize - PAGE_CEILING(size), zero); - if (config_fill && ret == false && zero == false) { - if (opt_junk) { - memset((void *)((uintptr_t)ptr + - oldsize), 0xa5, isalloc(ptr, - config_prof) - oldsize); - } else if (opt_zero) { - memset((void *)((uintptr_t)ptr + - oldsize), 0, isalloc(ptr, - config_prof) - oldsize); - } - } - return (ret); - } + usize = sz_sa2u(usize, alignment); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + return NULL; } + return ipalloct(tsdn, usize, alignment, zero, tcache, arena); } -bool -arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra, - bool zero) -{ +void * +arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, + size_t size, size_t alignment, bool zero, tcache_t *tcache) { + size_t usize = sz_s2u(size); + if (unlikely(usize == 0 || size > LARGE_MAXCLASS)) { + return NULL; + } - /* - * Avoid moving the allocation if the size class can be left the same. - */ - if (oldsize <= arena_maxclass) { - if (oldsize <= SMALL_MAXCLASS) { - assert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size - == oldsize); - if ((size + extra <= SMALL_MAXCLASS && - SMALL_SIZE2BIN(size + extra) == - SMALL_SIZE2BIN(oldsize)) || (size <= oldsize && - size + extra >= oldsize)) - return (false); - } else { - assert(size <= arena_maxclass); - if (size + extra > SMALL_MAXCLASS) { - if (arena_ralloc_large(ptr, oldsize, size, - extra, zero) == false) - return (false); - } + if (likely(usize <= SMALL_MAXCLASS)) { + /* Try to avoid moving the allocation. */ + if (!arena_ralloc_no_move(tsdn, ptr, oldsize, usize, 0, zero)) { + return ptr; } } - /* Reallocation would require a move. */ - return (true); -} - -void * -arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size, - size_t extra, size_t alignment, bool zero, bool try_tcache_alloc, - bool try_tcache_dalloc) -{ - void *ret; - size_t copysize; - - /* Try to avoid moving the allocation. */ - if (arena_ralloc_no_move(ptr, oldsize, size, extra, zero) == false) - return (ptr); + if (oldsize >= LARGE_MINCLASS && usize >= LARGE_MINCLASS) { + return large_ralloc(tsdn, arena, iealloc(tsdn, ptr), usize, + alignment, zero, tcache); + } /* * size and oldsize are different enough that we need to move the - * object. In that case, fall back to allocating new space and - * copying. + * object. In that case, fall back to allocating new space and copying. */ - if (alignment != 0) { - size_t usize = sa2u(size + extra, alignment); - if (usize == 0) - return (NULL); - ret = ipalloct(usize, alignment, zero, try_tcache_alloc, arena); - } else - ret = arena_malloc(arena, size + extra, zero, try_tcache_alloc); - + void *ret = arena_ralloc_move_helper(tsdn, arena, usize, alignment, + zero, tcache); if (ret == NULL) { - if (extra == 0) - return (NULL); - /* Try again, this time without extra. */ - if (alignment != 0) { - size_t usize = sa2u(size, alignment); - if (usize == 0) - return (NULL); - ret = ipalloct(usize, alignment, zero, try_tcache_alloc, - arena); - } else - ret = arena_malloc(arena, size, zero, try_tcache_alloc); - - if (ret == NULL) - return (NULL); + return NULL; } - /* Junk/zero-filling were already done by ipalloc()/arena_malloc(). */ - /* - * Copy at most size bytes (not size+extra), since the caller has no - * expectation that the extra bytes will be reliably preserved. + * Junk/zero-filling were already done by + * ipalloc()/arena_malloc(). */ - copysize = (size < oldsize) ? size : oldsize; - VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize); + + size_t copysize = (usize < oldsize) ? usize : oldsize; memcpy(ret, ptr, copysize); - iqalloct(ptr, try_tcache_dalloc); - return (ret); + isdalloct(tsdn, ptr, oldsize, tcache, NULL, true); + return ret; } dss_prec_t -arena_dss_prec_get(arena_t *arena) -{ - dss_prec_t ret; +arena_dss_prec_get(arena_t *arena) { + return (dss_prec_t)atomic_load_u(&arena->dss_prec, ATOMIC_ACQUIRE); +} - malloc_mutex_lock(&arena->lock); - ret = arena->dss_prec; - malloc_mutex_unlock(&arena->lock); - return (ret); +bool +arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) { + if (!have_dss) { + return (dss_prec != dss_prec_disabled); + } + atomic_store_u(&arena->dss_prec, (unsigned)dss_prec, ATOMIC_RELEASE); + return false; } -void -arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec) -{ +ssize_t +arena_dirty_decay_ms_default_get(void) { + return atomic_load_zd(&dirty_decay_ms_default, ATOMIC_RELAXED); +} - malloc_mutex_lock(&arena->lock); - arena->dss_prec = dss_prec; - malloc_mutex_unlock(&arena->lock); +bool +arena_dirty_decay_ms_default_set(ssize_t decay_ms) { + if (!arena_decay_ms_valid(decay_ms)) { + return true; + } + atomic_store_zd(&dirty_decay_ms_default, decay_ms, ATOMIC_RELAXED); + return false; } -void -arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive, - size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats, - malloc_large_stats_t *lstats) -{ - unsigned i; +ssize_t +arena_muzzy_decay_ms_default_get(void) { + return atomic_load_zd(&muzzy_decay_ms_default, ATOMIC_RELAXED); +} - malloc_mutex_lock(&arena->lock); - *dss = dss_prec_names[arena->dss_prec]; - *nactive += arena->nactive; - *ndirty += arena->ndirty; +bool +arena_muzzy_decay_ms_default_set(ssize_t decay_ms) { + if (!arena_decay_ms_valid(decay_ms)) { + return true; + } + atomic_store_zd(&muzzy_decay_ms_default, decay_ms, ATOMIC_RELAXED); + return false; +} - astats->mapped += arena->stats.mapped; - astats->npurge += arena->stats.npurge; - astats->nmadvise += arena->stats.nmadvise; - astats->purged += arena->stats.purged; - astats->allocated_large += arena->stats.allocated_large; - astats->nmalloc_large += arena->stats.nmalloc_large; - astats->ndalloc_large += arena->stats.ndalloc_large; - astats->nrequests_large += arena->stats.nrequests_large; +unsigned +arena_nthreads_get(arena_t *arena, bool internal) { + return atomic_load_u(&arena->nthreads[internal], ATOMIC_RELAXED); +} - for (i = 0; i < nlclasses; i++) { - lstats[i].nmalloc += arena->stats.lstats[i].nmalloc; - lstats[i].ndalloc += arena->stats.lstats[i].ndalloc; - lstats[i].nrequests += arena->stats.lstats[i].nrequests; - lstats[i].curruns += arena->stats.lstats[i].curruns; - } - malloc_mutex_unlock(&arena->lock); +void +arena_nthreads_inc(arena_t *arena, bool internal) { + atomic_fetch_add_u(&arena->nthreads[internal], 1, ATOMIC_RELAXED); +} - for (i = 0; i < NBINS; i++) { - arena_bin_t *bin = &arena->bins[i]; +void +arena_nthreads_dec(arena_t *arena, bool internal) { + atomic_fetch_sub_u(&arena->nthreads[internal], 1, ATOMIC_RELAXED); +} - malloc_mutex_lock(&bin->lock); - bstats[i].allocated += bin->stats.allocated; - bstats[i].nmalloc += bin->stats.nmalloc; - bstats[i].ndalloc += bin->stats.ndalloc; - bstats[i].nrequests += bin->stats.nrequests; - if (config_tcache) { - bstats[i].nfills += bin->stats.nfills; - bstats[i].nflushes += bin->stats.nflushes; - } - bstats[i].nruns += bin->stats.nruns; - bstats[i].reruns += bin->stats.reruns; - bstats[i].curruns += bin->stats.curruns; - malloc_mutex_unlock(&bin->lock); - } +size_t +arena_extent_sn_next(arena_t *arena) { + return atomic_fetch_add_zu(&arena->extent_sn_next, 1, ATOMIC_RELAXED); } -bool -arena_new(arena_t *arena, unsigned ind) -{ +arena_t * +arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { + arena_t *arena; + base_t *base; unsigned i; - arena_bin_t *bin; - arena->ind = ind; - arena->nthreads = 0; + if (ind == 0) { + base = b0get(); + } else { + base = base_new(tsdn, ind, extent_hooks); + if (base == NULL) { + return NULL; + } + } + + arena = (arena_t *)base_alloc(tsdn, base, sizeof(arena_t), CACHELINE); + if (arena == NULL) { + goto label_error; + } - if (malloc_mutex_init(&arena->lock)) - return (true); + atomic_store_u(&arena->nthreads[0], 0, ATOMIC_RELAXED); + atomic_store_u(&arena->nthreads[1], 0, ATOMIC_RELAXED); + arena->last_thd = NULL; if (config_stats) { - memset(&arena->stats, 0, sizeof(arena_stats_t)); - arena->stats.lstats = - (malloc_large_stats_t *)base_alloc(nlclasses * - sizeof(malloc_large_stats_t)); - if (arena->stats.lstats == NULL) - return (true); - memset(arena->stats.lstats, 0, nlclasses * - sizeof(malloc_large_stats_t)); - if (config_tcache) - ql_new(&arena->tcache_ql); + if (arena_stats_init(tsdn, &arena->stats)) { + goto label_error; + } + + ql_new(&arena->tcache_ql); + if (malloc_mutex_init(&arena->tcache_ql_mtx, "tcache_ql", + WITNESS_RANK_TCACHE_QL, malloc_mutex_rank_exclusive)) { + goto label_error; + } } - if (config_prof) - arena->prof_accumbytes = 0; + if (config_prof) { + if (prof_accum_init(tsdn, &arena->prof_accum)) { + goto label_error; + } + } - arena->dss_prec = chunk_dss_prec_get(); + if (config_cache_oblivious) { + /* + * A nondeterministic seed based on the address of arena reduces + * the likelihood of lockstep non-uniform cache index + * utilization among identical concurrent processes, but at the + * cost of test repeatability. For debug builds, instead use a + * deterministic seed. + */ + atomic_store_zu(&arena->offset_state, config_debug ? ind : + (size_t)(uintptr_t)arena, ATOMIC_RELAXED); + } - /* Initialize chunks. */ - arena_chunk_dirty_new(&arena->chunks_dirty); - arena->spare = NULL; + atomic_store_zu(&arena->extent_sn_next, 0, ATOMIC_RELAXED); - arena->nactive = 0; - arena->ndirty = 0; - arena->npurgatory = 0; + atomic_store_u(&arena->dss_prec, (unsigned)extent_dss_prec_get(), + ATOMIC_RELAXED); - arena_avail_tree_new(&arena->runs_avail); + atomic_store_zu(&arena->nactive, 0, ATOMIC_RELAXED); - /* Initialize bins. */ - for (i = 0; i < NBINS; i++) { - bin = &arena->bins[i]; - if (malloc_mutex_init(&bin->lock)) - return (true); - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - if (config_stats) - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); + extent_list_init(&arena->large); + if (malloc_mutex_init(&arena->large_mtx, "arena_large", + WITNESS_RANK_ARENA_LARGE, malloc_mutex_rank_exclusive)) { + goto label_error; } - return (false); -} - -/* - * Calculate bin_info->run_size such that it meets the following constraints: - * - * *) bin_info->run_size >= min_run_size - * *) bin_info->run_size <= arena_maxclass - * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). - * *) bin_info->nregs <= RUN_MAXREGS - * - * bin_info->nregs, bin_info->bitmap_offset, and bin_info->reg0_offset are also - * calculated here, since these settings are all interdependent. - */ -static size_t -bin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) -{ - size_t pad_size; - size_t try_run_size, good_run_size; - uint32_t try_nregs, good_nregs; - uint32_t try_hdr_size, good_hdr_size; - uint32_t try_bitmap_offset, good_bitmap_offset; - uint32_t try_ctx0_offset, good_ctx0_offset; - uint32_t try_redzone0_offset, good_redzone0_offset; - - assert(min_run_size >= PAGE); - assert(min_run_size <= arena_maxclass); - /* - * Determine redzone size based on minimum alignment and minimum - * redzone size. Add padding to the end of the run if it is needed to - * align the regions. The padding allows each redzone to be half the - * minimum alignment; without the padding, each redzone would have to - * be twice as large in order to maintain alignment. + * Delay coalescing for dirty extents despite the disruptive effect on + * memory layout for best-fit extent allocation, since cached extents + * are likely to be reused soon after deallocation, and the cost of + * merging/splitting extents is non-trivial. */ - if (config_fill && opt_redzone) { - size_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1); - if (align_min <= REDZONE_MINSIZE) { - bin_info->redzone_size = REDZONE_MINSIZE; - pad_size = 0; - } else { - bin_info->redzone_size = align_min >> 1; - pad_size = bin_info->redzone_size; - } - } else { - bin_info->redzone_size = 0; - pad_size = 0; + if (extents_init(tsdn, &arena->extents_dirty, extent_state_dirty, + true)) { + goto label_error; } - bin_info->reg_interval = bin_info->reg_size + - (bin_info->redzone_size << 1); - /* - * Calculate known-valid settings before entering the run_size - * expansion loop, so that the first part of the loop always copies - * valid settings. - * - * The do..while loop iteratively reduces the number of regions until - * the run header and the regions no longer overlap. A closed formula - * would be quite messy, since there is an interdependency between the - * header's mask length and the number of regions. + * Coalesce muzzy extents immediately, because operations on them are in + * the critical path much less often than for dirty extents. */ - try_run_size = min_run_size; - try_nregs = ((try_run_size - sizeof(arena_run_t)) / - bin_info->reg_interval) - + 1; /* Counter-act try_nregs-- in loop. */ - if (try_nregs > RUN_MAXREGS) { - try_nregs = RUN_MAXREGS - + 1; /* Counter-act try_nregs-- in loop. */ - } - do { - try_nregs--; - try_hdr_size = sizeof(arena_run_t); - /* Pad to a long boundary. */ - try_hdr_size = LONG_CEILING(try_hdr_size); - try_bitmap_offset = try_hdr_size; - /* Add space for bitmap. */ - try_hdr_size += bitmap_size(try_nregs); - if (config_prof && opt_prof && prof_promote == false) { - /* Pad to a quantum boundary. */ - try_hdr_size = QUANTUM_CEILING(try_hdr_size); - try_ctx0_offset = try_hdr_size; - /* Add space for one (prof_ctx_t *) per region. */ - try_hdr_size += try_nregs * sizeof(prof_ctx_t *); - } else - try_ctx0_offset = 0; - try_redzone0_offset = try_run_size - (try_nregs * - bin_info->reg_interval) - pad_size; - } while (try_hdr_size > try_redzone0_offset); - - /* run_size expansion loop. */ - do { - /* - * Copy valid settings before trying more aggressive settings. - */ - good_run_size = try_run_size; - good_nregs = try_nregs; - good_hdr_size = try_hdr_size; - good_bitmap_offset = try_bitmap_offset; - good_ctx0_offset = try_ctx0_offset; - good_redzone0_offset = try_redzone0_offset; - - /* Try more aggressive settings. */ - try_run_size += PAGE; - try_nregs = ((try_run_size - sizeof(arena_run_t) - pad_size) / - bin_info->reg_interval) - + 1; /* Counter-act try_nregs-- in loop. */ - if (try_nregs > RUN_MAXREGS) { - try_nregs = RUN_MAXREGS - + 1; /* Counter-act try_nregs-- in loop. */ + if (extents_init(tsdn, &arena->extents_muzzy, extent_state_muzzy, + false)) { + goto label_error; + } + /* + * Coalesce retained extents immediately, in part because they will + * never be evicted (and therefore there's no opportunity for delayed + * coalescing), but also because operations on retained extents are not + * in the critical path. + */ + if (extents_init(tsdn, &arena->extents_retained, extent_state_retained, + false)) { + goto label_error; + } + + if (arena_decay_init(&arena->decay_dirty, &arena->extents_dirty, + arena_dirty_decay_ms_default_get(), &arena->stats.decay_dirty)) { + goto label_error; + } + if (arena_decay_init(&arena->decay_muzzy, &arena->extents_muzzy, + arena_muzzy_decay_ms_default_get(), &arena->stats.decay_muzzy)) { + goto label_error; + } + + arena->extent_grow_next = sz_psz2ind(HUGEPAGE); + if (malloc_mutex_init(&arena->extent_grow_mtx, "extent_grow", + WITNESS_RANK_EXTENT_GROW, malloc_mutex_rank_exclusive)) { + goto label_error; + } + + extent_avail_new(&arena->extent_avail); + if (malloc_mutex_init(&arena->extent_avail_mtx, "extent_avail", + WITNESS_RANK_EXTENT_AVAIL, malloc_mutex_rank_exclusive)) { + goto label_error; + } + + /* Initialize bins. */ + for (i = 0; i < NBINS; i++) { + arena_bin_t *bin = &arena->bins[i]; + if (malloc_mutex_init(&bin->lock, "arena_bin", + WITNESS_RANK_ARENA_BIN, malloc_mutex_rank_exclusive)) { + goto label_error; } - do { - try_nregs--; - try_hdr_size = sizeof(arena_run_t); - /* Pad to a long boundary. */ - try_hdr_size = LONG_CEILING(try_hdr_size); - try_bitmap_offset = try_hdr_size; - /* Add space for bitmap. */ - try_hdr_size += bitmap_size(try_nregs); - if (config_prof && opt_prof && prof_promote == false) { - /* Pad to a quantum boundary. */ - try_hdr_size = QUANTUM_CEILING(try_hdr_size); - try_ctx0_offset = try_hdr_size; - /* - * Add space for one (prof_ctx_t *) per region. - */ - try_hdr_size += try_nregs * - sizeof(prof_ctx_t *); - } - try_redzone0_offset = try_run_size - (try_nregs * - bin_info->reg_interval) - pad_size; - } while (try_hdr_size > try_redzone0_offset); - } while (try_run_size <= arena_maxclass - && RUN_MAX_OVRHD * (bin_info->reg_interval << 3) > - RUN_MAX_OVRHD_RELAX - && (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size - && try_nregs < RUN_MAXREGS); + bin->slabcur = NULL; + extent_heap_new(&bin->slabs_nonfull); + extent_list_init(&bin->slabs_full); + if (config_stats) { + memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); + } + } - assert(good_hdr_size <= good_redzone0_offset); + arena->base = base; + /* Set arena before creating background threads. */ + arena_set(ind, arena); - /* Copy final settings. */ - bin_info->run_size = good_run_size; - bin_info->nregs = good_nregs; - bin_info->bitmap_offset = good_bitmap_offset; - bin_info->ctx0_offset = good_ctx0_offset; - bin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size; + nstime_init(&arena->create_time, 0); + nstime_update(&arena->create_time); - assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs - * bin_info->reg_interval) + pad_size == bin_info->run_size); + /* We don't support reentrancy for arena 0 bootstrapping. */ + if (ind != 0) { + /* + * If we're here, then arena 0 already exists, so bootstrapping + * is done enough that we should have tsd. + */ + assert(!tsdn_null(tsdn)); + pre_reentrancy(tsdn_tsd(tsdn), arena); + if (hooks_arena_new_hook) { + hooks_arena_new_hook(); + } + post_reentrancy(tsdn_tsd(tsdn)); + } - return (good_run_size); + return arena; +label_error: + if (ind != 0) { + base_delete(tsdn, base); + } + return NULL; } -static void -bin_info_init(void) -{ - arena_bin_info_t *bin_info; - size_t prev_run_size = PAGE; - -#define SIZE_CLASS(bin, delta, size) \ - bin_info = &arena_bin_info[bin]; \ - bin_info->reg_size = size; \ - prev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\ - bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs); - SIZE_CLASSES -#undef SIZE_CLASS +void +arena_boot(void) { + arena_dirty_decay_ms_default_set(opt_dirty_decay_ms); + arena_muzzy_decay_ms_default_set(opt_muzzy_decay_ms); } void -arena_boot(void) -{ - size_t header_size; - unsigned i; +arena_prefork0(tsdn_t *tsdn, arena_t *arena) { + malloc_mutex_prefork(tsdn, &arena->decay_dirty.mtx); + malloc_mutex_prefork(tsdn, &arena->decay_muzzy.mtx); +} - /* - * Compute the header size such that it is large enough to contain the - * page map. The page map is biased to omit entries for the header - * itself, so some iteration is necessary to compute the map bias. - * - * 1) Compute safe header_size and map_bias values that include enough - * space for an unbiased page map. - * 2) Refine map_bias based on (1) to omit the header pages in the page - * map. The resulting map_bias may be one too small. - * 3) Refine map_bias based on (2). The result will be >= the result - * from (2), and will always be correct. - */ - map_bias = 0; - for (i = 0; i < 3; i++) { - header_size = offsetof(arena_chunk_t, map) + - (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias)); - map_bias = (header_size >> LG_PAGE) + ((header_size & PAGE_MASK) - != 0); +void +arena_prefork1(tsdn_t *tsdn, arena_t *arena) { + if (config_stats) { + malloc_mutex_prefork(tsdn, &arena->tcache_ql_mtx); } - assert(map_bias > 0); +} - arena_maxclass = chunksize - (map_bias << LG_PAGE); +void +arena_prefork2(tsdn_t *tsdn, arena_t *arena) { + malloc_mutex_prefork(tsdn, &arena->extent_grow_mtx); +} - bin_info_init(); +void +arena_prefork3(tsdn_t *tsdn, arena_t *arena) { + extents_prefork(tsdn, &arena->extents_dirty); + extents_prefork(tsdn, &arena->extents_muzzy); + extents_prefork(tsdn, &arena->extents_retained); } void -arena_prefork(arena_t *arena) -{ - unsigned i; +arena_prefork4(tsdn_t *tsdn, arena_t *arena) { + malloc_mutex_prefork(tsdn, &arena->extent_avail_mtx); +} - malloc_mutex_prefork(&arena->lock); - for (i = 0; i < NBINS; i++) - malloc_mutex_prefork(&arena->bins[i].lock); +void +arena_prefork5(tsdn_t *tsdn, arena_t *arena) { + base_prefork(tsdn, arena->base); +} + +void +arena_prefork6(tsdn_t *tsdn, arena_t *arena) { + malloc_mutex_prefork(tsdn, &arena->large_mtx); +} + +void +arena_prefork7(tsdn_t *tsdn, arena_t *arena) { + for (unsigned i = 0; i < NBINS; i++) { + malloc_mutex_prefork(tsdn, &arena->bins[i].lock); + } } void -arena_postfork_parent(arena_t *arena) -{ +arena_postfork_parent(tsdn_t *tsdn, arena_t *arena) { unsigned i; - for (i = 0; i < NBINS; i++) - malloc_mutex_postfork_parent(&arena->bins[i].lock); - malloc_mutex_postfork_parent(&arena->lock); + for (i = 0; i < NBINS; i++) { + malloc_mutex_postfork_parent(tsdn, &arena->bins[i].lock); + } + malloc_mutex_postfork_parent(tsdn, &arena->large_mtx); + base_postfork_parent(tsdn, arena->base); + malloc_mutex_postfork_parent(tsdn, &arena->extent_avail_mtx); + extents_postfork_parent(tsdn, &arena->extents_dirty); + extents_postfork_parent(tsdn, &arena->extents_muzzy); + extents_postfork_parent(tsdn, &arena->extents_retained); + malloc_mutex_postfork_parent(tsdn, &arena->extent_grow_mtx); + malloc_mutex_postfork_parent(tsdn, &arena->decay_dirty.mtx); + malloc_mutex_postfork_parent(tsdn, &arena->decay_muzzy.mtx); + if (config_stats) { + malloc_mutex_postfork_parent(tsdn, &arena->tcache_ql_mtx); + } } void -arena_postfork_child(arena_t *arena) -{ +arena_postfork_child(tsdn_t *tsdn, arena_t *arena) { unsigned i; - for (i = 0; i < NBINS; i++) - malloc_mutex_postfork_child(&arena->bins[i].lock); - malloc_mutex_postfork_child(&arena->lock); + atomic_store_u(&arena->nthreads[0], 0, ATOMIC_RELAXED); + atomic_store_u(&arena->nthreads[1], 0, ATOMIC_RELAXED); + if (tsd_arena_get(tsdn_tsd(tsdn)) == arena) { + arena_nthreads_inc(arena, false); + } + if (tsd_iarena_get(tsdn_tsd(tsdn)) == arena) { + arena_nthreads_inc(arena, true); + } + if (config_stats) { + ql_new(&arena->tcache_ql); + tcache_t *tcache = tcache_get(tsdn_tsd(tsdn)); + if (tcache != NULL && tcache->arena == arena) { + ql_elm_new(tcache, link); + ql_tail_insert(&arena->tcache_ql, tcache, link); + } + } + + for (i = 0; i < NBINS; i++) { + malloc_mutex_postfork_child(tsdn, &arena->bins[i].lock); + } + malloc_mutex_postfork_child(tsdn, &arena->large_mtx); + base_postfork_child(tsdn, arena->base); + malloc_mutex_postfork_child(tsdn, &arena->extent_avail_mtx); + extents_postfork_child(tsdn, &arena->extents_dirty); + extents_postfork_child(tsdn, &arena->extents_muzzy); + extents_postfork_child(tsdn, &arena->extents_retained); + malloc_mutex_postfork_child(tsdn, &arena->extent_grow_mtx); + malloc_mutex_postfork_child(tsdn, &arena->decay_dirty.mtx); + malloc_mutex_postfork_child(tsdn, &arena->decay_muzzy.mtx); + if (config_stats) { + malloc_mutex_postfork_child(tsdn, &arena->tcache_ql_mtx); + } } diff --git a/deps/jemalloc/src/base.c b/deps/jemalloc/src/base.c index 4e62e8fa91..97078b134d 100644 --- a/deps/jemalloc/src/base.c +++ b/deps/jemalloc/src/base.c @@ -1,142 +1,402 @@ -#define JEMALLOC_BASE_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_BASE_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/sz.h" /******************************************************************************/ /* Data. */ -static malloc_mutex_t base_mtx; - -/* - * Current pages that are being used for internal memory allocations. These - * pages are carved up in cacheline-size quanta, so that there is no chance of - * false cache line sharing. - */ -static void *base_pages; -static void *base_next_addr; -static void *base_past_addr; /* Addr immediately past base_pages. */ -static extent_node_t *base_nodes; +static base_t *b0; /******************************************************************************/ -/* Function prototypes for non-inline static functions. */ -static bool base_pages_alloc(size_t minsize); +static void * +base_map(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, size_t size) { + void *addr; + bool zero = true; + bool commit = true; -/******************************************************************************/ + assert(size == HUGEPAGE_CEILING(size)); + + if (extent_hooks == &extent_hooks_default) { + addr = extent_alloc_mmap(NULL, size, PAGE, &zero, &commit); + } else { + /* No arena context as we are creating new arenas. */ + tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn); + pre_reentrancy(tsd, NULL); + addr = extent_hooks->alloc(extent_hooks, NULL, size, PAGE, + &zero, &commit, ind); + post_reentrancy(tsd); + } + + return addr; +} + +static void +base_unmap(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, void *addr, + size_t size) { + /* + * Cascade through dalloc, decommit, purge_forced, and purge_lazy, + * stopping at first success. This cascade is performed for consistency + * with the cascade in extent_dalloc_wrapper() because an application's + * custom hooks may not support e.g. dalloc. This function is only ever + * called as a side effect of arena destruction, so although it might + * seem pointless to do anything besides dalloc here, the application + * may in fact want the end state of all associated virtual memory to be + * in some consistent-but-allocated state. + */ + if (extent_hooks == &extent_hooks_default) { + if (!extent_dalloc_mmap(addr, size)) { + return; + } + if (!pages_decommit(addr, size)) { + return; + } + if (!pages_purge_forced(addr, size)) { + return; + } + if (!pages_purge_lazy(addr, size)) { + return; + } + /* Nothing worked. This should never happen. */ + not_reached(); + } else { + tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn); + pre_reentrancy(tsd, NULL); + if (extent_hooks->dalloc != NULL && + !extent_hooks->dalloc(extent_hooks, addr, size, true, + ind)) { + goto label_done; + } + if (extent_hooks->decommit != NULL && + !extent_hooks->decommit(extent_hooks, addr, size, 0, size, + ind)) { + goto label_done; + } + if (extent_hooks->purge_forced != NULL && + !extent_hooks->purge_forced(extent_hooks, addr, size, 0, + size, ind)) { + goto label_done; + } + if (extent_hooks->purge_lazy != NULL && + !extent_hooks->purge_lazy(extent_hooks, addr, size, 0, size, + ind)) { + goto label_done; + } + /* Nothing worked. That's the application's problem. */ + label_done: + post_reentrancy(tsd); + return; + } +} -static bool -base_pages_alloc(size_t minsize) -{ - size_t csize; - bool zero; +static void +base_extent_init(size_t *extent_sn_next, extent_t *extent, void *addr, + size_t size) { + size_t sn; - assert(minsize != 0); - csize = CHUNK_CEILING(minsize); - zero = false; - base_pages = chunk_alloc(csize, chunksize, true, &zero, - chunk_dss_prec_get()); - if (base_pages == NULL) - return (true); - base_next_addr = base_pages; - base_past_addr = (void *)((uintptr_t)base_pages + csize); + sn = *extent_sn_next; + (*extent_sn_next)++; - return (false); + extent_binit(extent, addr, size, sn); } -void * -base_alloc(size_t size) -{ +static void * +base_extent_bump_alloc_helper(extent_t *extent, size_t *gap_size, size_t size, + size_t alignment) { void *ret; - size_t csize; - /* Round size up to nearest multiple of the cacheline size. */ - csize = CACHELINE_CEILING(size); + assert(alignment == ALIGNMENT_CEILING(alignment, QUANTUM)); + assert(size == ALIGNMENT_CEILING(size, alignment)); - malloc_mutex_lock(&base_mtx); - /* Make sure there's enough space for the allocation. */ - if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) { - if (base_pages_alloc(csize)) { - malloc_mutex_unlock(&base_mtx); - return (NULL); - } + *gap_size = ALIGNMENT_CEILING((uintptr_t)extent_addr_get(extent), + alignment) - (uintptr_t)extent_addr_get(extent); + ret = (void *)((uintptr_t)extent_addr_get(extent) + *gap_size); + assert(extent_bsize_get(extent) >= *gap_size + size); + extent_binit(extent, (void *)((uintptr_t)extent_addr_get(extent) + + *gap_size + size), extent_bsize_get(extent) - *gap_size - size, + extent_sn_get(extent)); + return ret; +} + +static void +base_extent_bump_alloc_post(tsdn_t *tsdn, base_t *base, extent_t *extent, + size_t gap_size, void *addr, size_t size) { + if (extent_bsize_get(extent) > 0) { + /* + * Compute the index for the largest size class that does not + * exceed extent's size. + */ + szind_t index_floor = + sz_size2index(extent_bsize_get(extent) + 1) - 1; + extent_heap_insert(&base->avail[index_floor], extent); } - /* Allocate. */ - ret = base_next_addr; - base_next_addr = (void *)((uintptr_t)base_next_addr + csize); - malloc_mutex_unlock(&base_mtx); - VALGRIND_MAKE_MEM_UNDEFINED(ret, csize); - return (ret); + if (config_stats) { + base->allocated += size; + /* + * Add one PAGE to base_resident for every page boundary that is + * crossed by the new allocation. + */ + base->resident += PAGE_CEILING((uintptr_t)addr + size) - + PAGE_CEILING((uintptr_t)addr - gap_size); + assert(base->allocated <= base->resident); + assert(base->resident <= base->mapped); + } } -void * -base_calloc(size_t number, size_t size) -{ - void *ret = base_alloc(number * size); +static void * +base_extent_bump_alloc(tsdn_t *tsdn, base_t *base, extent_t *extent, + size_t size, size_t alignment) { + void *ret; + size_t gap_size; + + ret = base_extent_bump_alloc_helper(extent, &gap_size, size, alignment); + base_extent_bump_alloc_post(tsdn, base, extent, gap_size, ret, size); + return ret; +} + +/* + * Allocate a block of virtual memory that is large enough to start with a + * base_block_t header, followed by an object of specified size and alignment. + * On success a pointer to the initialized base_block_t header is returned. + */ +static base_block_t * +base_block_alloc(tsdn_t *tsdn, extent_hooks_t *extent_hooks, unsigned ind, + pszind_t *pind_last, size_t *extent_sn_next, size_t size, + size_t alignment) { + alignment = ALIGNMENT_CEILING(alignment, QUANTUM); + size_t usize = ALIGNMENT_CEILING(size, alignment); + size_t header_size = sizeof(base_block_t); + size_t gap_size = ALIGNMENT_CEILING(header_size, alignment) - + header_size; + /* + * Create increasingly larger blocks in order to limit the total number + * of disjoint virtual memory ranges. Choose the next size in the page + * size class series (skipping size classes that are not a multiple of + * HUGEPAGE), or a size large enough to satisfy the requested size and + * alignment, whichever is larger. + */ + size_t min_block_size = HUGEPAGE_CEILING(sz_psz2u(header_size + gap_size + + usize)); + pszind_t pind_next = (*pind_last + 1 < NPSIZES) ? *pind_last + 1 : + *pind_last; + size_t next_block_size = HUGEPAGE_CEILING(sz_pind2sz(pind_next)); + size_t block_size = (min_block_size > next_block_size) ? min_block_size + : next_block_size; + base_block_t *block = (base_block_t *)base_map(tsdn, extent_hooks, ind, + block_size); + if (block == NULL) { + return NULL; + } + *pind_last = sz_psz2ind(block_size); + block->size = block_size; + block->next = NULL; + assert(block_size >= header_size); + base_extent_init(extent_sn_next, &block->extent, + (void *)((uintptr_t)block + header_size), block_size - header_size); + return block; +} - if (ret != NULL) - memset(ret, 0, number * size); +/* + * Allocate an extent that is at least as large as specified size, with + * specified alignment. + */ +static extent_t * +base_extent_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) { + malloc_mutex_assert_owner(tsdn, &base->mtx); - return (ret); + extent_hooks_t *extent_hooks = base_extent_hooks_get(base); + /* + * Drop mutex during base_block_alloc(), because an extent hook will be + * called. + */ + malloc_mutex_unlock(tsdn, &base->mtx); + base_block_t *block = base_block_alloc(tsdn, extent_hooks, + base_ind_get(base), &base->pind_last, &base->extent_sn_next, size, + alignment); + malloc_mutex_lock(tsdn, &base->mtx); + if (block == NULL) { + return NULL; + } + block->next = base->blocks; + base->blocks = block; + if (config_stats) { + base->allocated += sizeof(base_block_t); + base->resident += PAGE_CEILING(sizeof(base_block_t)); + base->mapped += block->size; + assert(base->allocated <= base->resident); + assert(base->resident <= base->mapped); + } + return &block->extent; } -extent_node_t * -base_node_alloc(void) -{ - extent_node_t *ret; +base_t * +b0get(void) { + return b0; +} - malloc_mutex_lock(&base_mtx); - if (base_nodes != NULL) { - ret = base_nodes; - base_nodes = *(extent_node_t **)ret; - malloc_mutex_unlock(&base_mtx); - VALGRIND_MAKE_MEM_UNDEFINED(ret, sizeof(extent_node_t)); - } else { - malloc_mutex_unlock(&base_mtx); - ret = (extent_node_t *)base_alloc(sizeof(extent_node_t)); +base_t * +base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { + pszind_t pind_last = 0; + size_t extent_sn_next = 0; + base_block_t *block = base_block_alloc(tsdn, extent_hooks, ind, + &pind_last, &extent_sn_next, sizeof(base_t), QUANTUM); + if (block == NULL) { + return NULL; } - return (ret); + size_t gap_size; + size_t base_alignment = CACHELINE; + size_t base_size = ALIGNMENT_CEILING(sizeof(base_t), base_alignment); + base_t *base = (base_t *)base_extent_bump_alloc_helper(&block->extent, + &gap_size, base_size, base_alignment); + base->ind = ind; + atomic_store_p(&base->extent_hooks, extent_hooks, ATOMIC_RELAXED); + if (malloc_mutex_init(&base->mtx, "base", WITNESS_RANK_BASE, + malloc_mutex_rank_exclusive)) { + base_unmap(tsdn, extent_hooks, ind, block, block->size); + return NULL; + } + base->pind_last = pind_last; + base->extent_sn_next = extent_sn_next; + base->blocks = block; + for (szind_t i = 0; i < NSIZES; i++) { + extent_heap_new(&base->avail[i]); + } + if (config_stats) { + base->allocated = sizeof(base_block_t); + base->resident = PAGE_CEILING(sizeof(base_block_t)); + base->mapped = block->size; + assert(base->allocated <= base->resident); + assert(base->resident <= base->mapped); + } + base_extent_bump_alloc_post(tsdn, base, &block->extent, gap_size, base, + base_size); + + return base; } void -base_node_dealloc(extent_node_t *node) -{ +base_delete(tsdn_t *tsdn, base_t *base) { + extent_hooks_t *extent_hooks = base_extent_hooks_get(base); + base_block_t *next = base->blocks; + do { + base_block_t *block = next; + next = block->next; + base_unmap(tsdn, extent_hooks, base_ind_get(base), block, + block->size); + } while (next != NULL); +} - VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t)); - malloc_mutex_lock(&base_mtx); - *(extent_node_t **)node = base_nodes; - base_nodes = node; - malloc_mutex_unlock(&base_mtx); +extent_hooks_t * +base_extent_hooks_get(base_t *base) { + return (extent_hooks_t *)atomic_load_p(&base->extent_hooks, + ATOMIC_ACQUIRE); } -bool -base_boot(void) -{ +extent_hooks_t * +base_extent_hooks_set(base_t *base, extent_hooks_t *extent_hooks) { + extent_hooks_t *old_extent_hooks = base_extent_hooks_get(base); + atomic_store_p(&base->extent_hooks, extent_hooks, ATOMIC_RELEASE); + return old_extent_hooks; +} + +static void * +base_alloc_impl(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment, + size_t *esn) { + alignment = QUANTUM_CEILING(alignment); + size_t usize = ALIGNMENT_CEILING(size, alignment); + size_t asize = usize + alignment - QUANTUM; + + extent_t *extent = NULL; + malloc_mutex_lock(tsdn, &base->mtx); + for (szind_t i = sz_size2index(asize); i < NSIZES; i++) { + extent = extent_heap_remove_first(&base->avail[i]); + if (extent != NULL) { + /* Use existing space. */ + break; + } + } + if (extent == NULL) { + /* Try to allocate more space. */ + extent = base_extent_alloc(tsdn, base, usize, alignment); + } + void *ret; + if (extent == NULL) { + ret = NULL; + goto label_return; + } - base_nodes = NULL; - if (malloc_mutex_init(&base_mtx)) - return (true); + ret = base_extent_bump_alloc(tsdn, base, extent, usize, alignment); + if (esn != NULL) { + *esn = extent_sn_get(extent); + } +label_return: + malloc_mutex_unlock(tsdn, &base->mtx); + return ret; +} - return (false); +/* + * base_alloc() returns zeroed memory, which is always demand-zeroed for the + * auto arenas, in order to make multi-page sparse data structures such as radix + * tree nodes efficient with respect to physical memory usage. Upon success a + * pointer to at least size bytes with specified alignment is returned. Note + * that size is rounded up to the nearest multiple of alignment to avoid false + * sharing. + */ +void * +base_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment) { + return base_alloc_impl(tsdn, base, size, alignment, NULL); +} + +extent_t * +base_alloc_extent(tsdn_t *tsdn, base_t *base) { + size_t esn; + extent_t *extent = base_alloc_impl(tsdn, base, sizeof(extent_t), + CACHELINE, &esn); + if (extent == NULL) { + return NULL; + } + extent_esn_set(extent, esn); + return extent; } void -base_prefork(void) -{ +base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, size_t *resident, + size_t *mapped) { + cassert(config_stats); - malloc_mutex_prefork(&base_mtx); + malloc_mutex_lock(tsdn, &base->mtx); + assert(base->allocated <= base->resident); + assert(base->resident <= base->mapped); + *allocated = base->allocated; + *resident = base->resident; + *mapped = base->mapped; + malloc_mutex_unlock(tsdn, &base->mtx); } void -base_postfork_parent(void) -{ +base_prefork(tsdn_t *tsdn, base_t *base) { + malloc_mutex_prefork(tsdn, &base->mtx); +} - malloc_mutex_postfork_parent(&base_mtx); +void +base_postfork_parent(tsdn_t *tsdn, base_t *base) { + malloc_mutex_postfork_parent(tsdn, &base->mtx); } void -base_postfork_child(void) -{ +base_postfork_child(tsdn_t *tsdn, base_t *base) { + malloc_mutex_postfork_child(tsdn, &base->mtx); +} - malloc_mutex_postfork_child(&base_mtx); +bool +base_boot(tsdn_t *tsdn) { + b0 = base_new(tsdn, 0, (extent_hooks_t *)&extent_hooks_default); + return (b0 == NULL); } diff --git a/deps/jemalloc/src/bitmap.c b/deps/jemalloc/src/bitmap.c index e2bd907d55..468b3178eb 100644 --- a/deps/jemalloc/src/bitmap.c +++ b/deps/jemalloc/src/bitmap.c @@ -1,24 +1,15 @@ -#define JEMALLOC_BITMAP_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_BITMAP_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" -/******************************************************************************/ -/* Function prototypes for non-inline static functions. */ - -static size_t bits2groups(size_t nbits); +#include "jemalloc/internal/assert.h" /******************************************************************************/ -static size_t -bits2groups(size_t nbits) -{ - - return ((nbits >> LG_BITMAP_GROUP_NBITS) + - !!(nbits & BITMAP_GROUP_NBITS_MASK)); -} +#ifdef BITMAP_USE_TREE void -bitmap_info_init(bitmap_info_t *binfo, size_t nbits) -{ +bitmap_info_init(bitmap_info_t *binfo, size_t nbits) { unsigned i; size_t group_count; @@ -31,60 +22,100 @@ bitmap_info_init(bitmap_info_t *binfo, size_t nbits) * that requires only one group. */ binfo->levels[0].group_offset = 0; - group_count = bits2groups(nbits); + group_count = BITMAP_BITS2GROUPS(nbits); for (i = 1; group_count > 1; i++) { assert(i < BITMAP_MAX_LEVELS); binfo->levels[i].group_offset = binfo->levels[i-1].group_offset + group_count; - group_count = bits2groups(group_count); + group_count = BITMAP_BITS2GROUPS(group_count); } binfo->levels[i].group_offset = binfo->levels[i-1].group_offset + group_count; + assert(binfo->levels[i].group_offset <= BITMAP_GROUPS_MAX); binfo->nlevels = i; binfo->nbits = nbits; } -size_t -bitmap_info_ngroups(const bitmap_info_t *binfo) -{ - - return (binfo->levels[binfo->nlevels].group_offset << LG_SIZEOF_BITMAP); -} - -size_t -bitmap_size(size_t nbits) -{ - bitmap_info_t binfo; - - bitmap_info_init(&binfo, nbits); - return (bitmap_info_ngroups(&binfo)); +static size_t +bitmap_info_ngroups(const bitmap_info_t *binfo) { + return binfo->levels[binfo->nlevels].group_offset; } void -bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo) -{ +bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo, bool fill) { size_t extra; unsigned i; /* * Bits are actually inverted with regard to the external bitmap - * interface, so the bitmap starts out with all 1 bits, except for - * trailing unused bits (if any). Note that each group uses bit 0 to - * correspond to the first logical bit in the group, so extra bits - * are the most significant bits of the last group. + * interface. + */ + + if (fill) { + /* The "filled" bitmap starts out with all 0 bits. */ + memset(bitmap, 0, bitmap_size(binfo)); + return; + } + + /* + * The "empty" bitmap starts out with all 1 bits, except for trailing + * unused bits (if any). Note that each group uses bit 0 to correspond + * to the first logical bit in the group, so extra bits are the most + * significant bits of the last group. */ - memset(bitmap, 0xffU, binfo->levels[binfo->nlevels].group_offset << - LG_SIZEOF_BITMAP); + memset(bitmap, 0xffU, bitmap_size(binfo)); extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK; - if (extra != 0) + if (extra != 0) { bitmap[binfo->levels[1].group_offset - 1] >>= extra; + } for (i = 1; i < binfo->nlevels; i++) { size_t group_count = binfo->levels[i].group_offset - binfo->levels[i-1].group_offset; extra = (BITMAP_GROUP_NBITS - (group_count & BITMAP_GROUP_NBITS_MASK)) & BITMAP_GROUP_NBITS_MASK; - if (extra != 0) + if (extra != 0) { bitmap[binfo->levels[i+1].group_offset - 1] >>= extra; + } } } + +#else /* BITMAP_USE_TREE */ + +void +bitmap_info_init(bitmap_info_t *binfo, size_t nbits) { + assert(nbits > 0); + assert(nbits <= (ZU(1) << LG_BITMAP_MAXBITS)); + + binfo->ngroups = BITMAP_BITS2GROUPS(nbits); + binfo->nbits = nbits; +} + +static size_t +bitmap_info_ngroups(const bitmap_info_t *binfo) { + return binfo->ngroups; +} + +void +bitmap_init(bitmap_t *bitmap, const bitmap_info_t *binfo, bool fill) { + size_t extra; + + if (fill) { + memset(bitmap, 0, bitmap_size(binfo)); + return; + } + + memset(bitmap, 0xffU, bitmap_size(binfo)); + extra = (BITMAP_GROUP_NBITS - (binfo->nbits & BITMAP_GROUP_NBITS_MASK)) + & BITMAP_GROUP_NBITS_MASK; + if (extra != 0) { + bitmap[binfo->ngroups - 1] >>= extra; + } +} + +#endif /* BITMAP_USE_TREE */ + +size_t +bitmap_size(const bitmap_info_t *binfo) { + return (bitmap_info_ngroups(binfo) << LG_SIZEOF_BITMAP); +} diff --git a/deps/jemalloc/src/ckh.c b/deps/jemalloc/src/ckh.c index 04c5296619..e95e0a3ed5 100644 --- a/deps/jemalloc/src/ckh.c +++ b/deps/jemalloc/src/ckh.c @@ -34,14 +34,24 @@ * respectively. * ******************************************************************************/ -#define JEMALLOC_CKH_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_CKH_C_ +#include "jemalloc/internal/jemalloc_preamble.h" + +#include "jemalloc/internal/ckh.h" + +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/hash.h" +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/prng.h" +#include "jemalloc/internal/util.h" /******************************************************************************/ /* Function prototypes for non-inline static functions. */ -static bool ckh_grow(ckh_t *ckh); -static void ckh_shrink(ckh_t *ckh); +static bool ckh_grow(tsd_t *tsd, ckh_t *ckh); +static void ckh_shrink(tsd_t *tsd, ckh_t *ckh); /******************************************************************************/ @@ -49,27 +59,26 @@ static void ckh_shrink(ckh_t *ckh); * Search bucket for key and return the cell number if found; SIZE_T_MAX * otherwise. */ -JEMALLOC_INLINE_C size_t -ckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key) -{ +static size_t +ckh_bucket_search(ckh_t *ckh, size_t bucket, const void *key) { ckhc_t *cell; unsigned i; for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) { cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i]; - if (cell->key != NULL && ckh->keycomp(key, cell->key)) - return ((bucket << LG_CKH_BUCKET_CELLS) + i); + if (cell->key != NULL && ckh->keycomp(key, cell->key)) { + return (bucket << LG_CKH_BUCKET_CELLS) + i; + } } - return (SIZE_T_MAX); + return SIZE_T_MAX; } /* * Search table for key and return cell number if found; SIZE_T_MAX otherwise. */ -JEMALLOC_INLINE_C size_t -ckh_isearch(ckh_t *ckh, const void *key) -{ +static size_t +ckh_isearch(ckh_t *ckh, const void *key) { size_t hashes[2], bucket, cell; assert(ckh != NULL); @@ -79,19 +88,19 @@ ckh_isearch(ckh_t *ckh, const void *key) /* Search primary bucket. */ bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1); cell = ckh_bucket_search(ckh, bucket, key); - if (cell != SIZE_T_MAX) - return (cell); + if (cell != SIZE_T_MAX) { + return cell; + } /* Search secondary bucket. */ bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1); cell = ckh_bucket_search(ckh, bucket, key); - return (cell); + return cell; } -JEMALLOC_INLINE_C bool +static bool ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key, - const void *data) -{ + const void *data) { ckhc_t *cell; unsigned offset, i; @@ -99,7 +108,8 @@ ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key, * Cycle through the cells in the bucket, starting at a random position. * The randomness avoids worst-case search overhead as buckets fill up. */ - prng32(offset, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C); + offset = (unsigned)prng_lg_range_u64(&ckh->prng_state, + LG_CKH_BUCKET_CELLS); for (i = 0; i < (ZU(1) << LG_CKH_BUCKET_CELLS); i++) { cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + ((i + offset) & ((ZU(1) << LG_CKH_BUCKET_CELLS) - 1))]; @@ -107,11 +117,11 @@ ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key, cell->key = key; cell->data = data; ckh->count++; - return (false); + return false; } } - return (true); + return true; } /* @@ -120,10 +130,9 @@ ckh_try_bucket_insert(ckh_t *ckh, size_t bucket, const void *key, * eviction/relocation procedure until either success or detection of an * eviction/relocation bucket cycle. */ -JEMALLOC_INLINE_C bool +static bool ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, - void const **argdata) -{ + void const **argdata) { const void *key, *data, *tkey, *tdata; ckhc_t *cell; size_t hashes[2], bucket, tbucket; @@ -141,7 +150,8 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, * were an item for which both hashes indicated the same * bucket. */ - prng32(i, LG_CKH_BUCKET_CELLS, ckh->prng_state, CKH_A, CKH_C); + i = (unsigned)prng_lg_range_u64(&ckh->prng_state, + LG_CKH_BUCKET_CELLS); cell = &ckh->tab[(bucket << LG_CKH_BUCKET_CELLS) + i]; assert(cell->key != NULL); @@ -181,18 +191,18 @@ ckh_evict_reloc_insert(ckh_t *ckh, size_t argbucket, void const **argkey, if (tbucket == argbucket) { *argkey = key; *argdata = data; - return (true); + return true; } bucket = tbucket; - if (ckh_try_bucket_insert(ckh, bucket, key, data) == false) - return (false); + if (!ckh_try_bucket_insert(ckh, bucket, key, data)) { + return false; + } } } -JEMALLOC_INLINE_C bool -ckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata) -{ +static bool +ckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata) { size_t hashes[2], bucket; const void *key = *argkey; const void *data = *argdata; @@ -201,27 +211,28 @@ ckh_try_insert(ckh_t *ckh, void const**argkey, void const**argdata) /* Try to insert in primary bucket. */ bucket = hashes[0] & ((ZU(1) << ckh->lg_curbuckets) - 1); - if (ckh_try_bucket_insert(ckh, bucket, key, data) == false) - return (false); + if (!ckh_try_bucket_insert(ckh, bucket, key, data)) { + return false; + } /* Try to insert in secondary bucket. */ bucket = hashes[1] & ((ZU(1) << ckh->lg_curbuckets) - 1); - if (ckh_try_bucket_insert(ckh, bucket, key, data) == false) - return (false); + if (!ckh_try_bucket_insert(ckh, bucket, key, data)) { + return false; + } /* * Try to find a place for this item via iterative eviction/relocation. */ - return (ckh_evict_reloc_insert(ckh, bucket, argkey, argdata)); + return ckh_evict_reloc_insert(ckh, bucket, argkey, argdata); } /* * Try to rebuild the hash table from scratch by inserting all items from the * old table into the new. */ -JEMALLOC_INLINE_C bool -ckh_rebuild(ckh_t *ckh, ckhc_t *aTab) -{ +static bool +ckh_rebuild(ckh_t *ckh, ckhc_t *aTab) { size_t count, i, nins; const void *key, *data; @@ -233,22 +244,20 @@ ckh_rebuild(ckh_t *ckh, ckhc_t *aTab) data = aTab[i].data; if (ckh_try_insert(ckh, &key, &data)) { ckh->count = count; - return (true); + return true; } nins++; } } - return (false); + return false; } static bool -ckh_grow(ckh_t *ckh) -{ +ckh_grow(tsd_t *tsd, ckh_t *ckh) { bool ret; ckhc_t *tab, *ttab; - size_t lg_curcells; - unsigned lg_prevbuckets; + unsigned lg_prevbuckets, lg_curcells; #ifdef CKH_COUNT ckh->ngrows++; @@ -265,12 +274,13 @@ ckh_grow(ckh_t *ckh) size_t usize; lg_curcells++; - usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); - if (usize == 0) { + usize = sz_sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { ret = true; goto label_return; } - tab = (ckhc_t *)ipalloc(usize, CACHELINE, true); + tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, + true, NULL, true, arena_ichoose(tsd, NULL)); if (tab == NULL) { ret = true; goto label_return; @@ -281,28 +291,27 @@ ckh_grow(ckh_t *ckh) tab = ttab; ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS; - if (ckh_rebuild(ckh, tab) == false) { - idalloc(tab); + if (!ckh_rebuild(ckh, tab)) { + idalloctm(tsd_tsdn(tsd), tab, NULL, NULL, true, true); break; } /* Rebuilding failed, so back out partially rebuilt table. */ - idalloc(ckh->tab); + idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, NULL, true, true); ckh->tab = tab; ckh->lg_curbuckets = lg_prevbuckets; } ret = false; label_return: - return (ret); + return ret; } static void -ckh_shrink(ckh_t *ckh) -{ +ckh_shrink(tsd_t *tsd, ckh_t *ckh) { ckhc_t *tab, *ttab; - size_t lg_curcells, usize; - unsigned lg_prevbuckets; + size_t usize; + unsigned lg_prevbuckets, lg_curcells; /* * It is possible (though unlikely, given well behaved hashes) that the @@ -310,10 +319,12 @@ ckh_shrink(ckh_t *ckh) */ lg_prevbuckets = ckh->lg_curbuckets; lg_curcells = ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS - 1; - usize = sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); - if (usize == 0) + usize = sz_sa2u(sizeof(ckhc_t) << lg_curcells, CACHELINE); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { return; - tab = (ckhc_t *)ipalloc(usize, CACHELINE, true); + } + tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true, NULL, + true, arena_ichoose(tsd, NULL)); if (tab == NULL) { /* * An OOM error isn't worth propagating, since it doesn't @@ -327,8 +338,8 @@ ckh_shrink(ckh_t *ckh) tab = ttab; ckh->lg_curbuckets = lg_curcells - LG_CKH_BUCKET_CELLS; - if (ckh_rebuild(ckh, tab) == false) { - idalloc(tab); + if (!ckh_rebuild(ckh, tab)) { + idalloctm(tsd_tsdn(tsd), tab, NULL, NULL, true, true); #ifdef CKH_COUNT ckh->nshrinks++; #endif @@ -336,7 +347,7 @@ ckh_shrink(ckh_t *ckh) } /* Rebuilding failed, so back out partially rebuilt table. */ - idalloc(ckh->tab); + idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, NULL, true, true); ckh->tab = tab; ckh->lg_curbuckets = lg_prevbuckets; #ifdef CKH_COUNT @@ -345,8 +356,8 @@ ckh_shrink(ckh_t *ckh) } bool -ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp) -{ +ckh_new(tsd_t *tsd, ckh_t *ckh, size_t minitems, ckh_hash_t *hash, + ckh_keycomp_t *keycomp) { bool ret; size_t mincells, usize; unsigned lg_mincells; @@ -366,29 +377,31 @@ ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp) ckh->count = 0; /* - * Find the minimum power of 2 that is large enough to fit aBaseCount + * Find the minimum power of 2 that is large enough to fit minitems * entries. We are using (2+,2) cuckoo hashing, which has an expected * maximum load factor of at least ~0.86, so 0.75 is a conservative load - * factor that will typically allow 2^aLgMinItems to fit without ever + * factor that will typically allow mincells items to fit without ever * growing the table. */ assert(LG_CKH_BUCKET_CELLS > 0); mincells = ((minitems + (3 - (minitems % 3))) / 3) << 2; for (lg_mincells = LG_CKH_BUCKET_CELLS; (ZU(1) << lg_mincells) < mincells; - lg_mincells++) - ; /* Do nothing. */ + lg_mincells++) { + /* Do nothing. */ + } ckh->lg_minbuckets = lg_mincells - LG_CKH_BUCKET_CELLS; ckh->lg_curbuckets = lg_mincells - LG_CKH_BUCKET_CELLS; ckh->hash = hash; ckh->keycomp = keycomp; - usize = sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE); - if (usize == 0) { + usize = sz_sa2u(sizeof(ckhc_t) << lg_mincells, CACHELINE); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { ret = true; goto label_return; } - ckh->tab = (ckhc_t *)ipalloc(usize, CACHELINE, true); + ckh->tab = (ckhc_t *)ipallocztm(tsd_tsdn(tsd), usize, CACHELINE, true, + NULL, true, arena_ichoose(tsd, NULL)); if (ckh->tab == NULL) { ret = true; goto label_return; @@ -396,20 +409,18 @@ ckh_new(ckh_t *ckh, size_t minitems, ckh_hash_t *hash, ckh_keycomp_t *keycomp) ret = false; label_return: - return (ret); + return ret; } void -ckh_delete(ckh_t *ckh) -{ - +ckh_delete(tsd_t *tsd, ckh_t *ckh) { assert(ckh != NULL); #ifdef CKH_VERBOSE malloc_printf( - "%s(%p): ngrows: %"PRIu64", nshrinks: %"PRIu64"," - " nshrinkfails: %"PRIu64", ninserts: %"PRIu64"," - " nrelocs: %"PRIu64"\n", __func__, ckh, + "%s(%p): ngrows: %"FMTu64", nshrinks: %"FMTu64"," + " nshrinkfails: %"FMTu64", ninserts: %"FMTu64"," + " nrelocs: %"FMTu64"\n", __func__, ckh, (unsigned long long)ckh->ngrows, (unsigned long long)ckh->nshrinks, (unsigned long long)ckh->nshrinkfails, @@ -417,43 +428,42 @@ ckh_delete(ckh_t *ckh) (unsigned long long)ckh->nrelocs); #endif - idalloc(ckh->tab); - if (config_debug) - memset(ckh, 0x5a, sizeof(ckh_t)); + idalloctm(tsd_tsdn(tsd), ckh->tab, NULL, NULL, true, true); + if (config_debug) { + memset(ckh, JEMALLOC_FREE_JUNK, sizeof(ckh_t)); + } } size_t -ckh_count(ckh_t *ckh) -{ - +ckh_count(ckh_t *ckh) { assert(ckh != NULL); - return (ckh->count); + return ckh->count; } bool -ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data) -{ +ckh_iter(ckh_t *ckh, size_t *tabind, void **key, void **data) { size_t i, ncells; for (i = *tabind, ncells = (ZU(1) << (ckh->lg_curbuckets + LG_CKH_BUCKET_CELLS)); i < ncells; i++) { if (ckh->tab[i].key != NULL) { - if (key != NULL) + if (key != NULL) { *key = (void *)ckh->tab[i].key; - if (data != NULL) + } + if (data != NULL) { *data = (void *)ckh->tab[i].data; + } *tabind = i + 1; - return (false); + return false; } } - return (true); + return true; } bool -ckh_insert(ckh_t *ckh, const void *key, const void *data) -{ +ckh_insert(tsd_t *tsd, ckh_t *ckh, const void *key, const void *data) { bool ret; assert(ckh != NULL); @@ -464,7 +474,7 @@ ckh_insert(ckh_t *ckh, const void *key, const void *data) #endif while (ckh_try_insert(ckh, &key, &data)) { - if (ckh_grow(ckh)) { + if (ckh_grow(tsd, ckh)) { ret = true; goto label_return; } @@ -472,22 +482,24 @@ ckh_insert(ckh_t *ckh, const void *key, const void *data) ret = false; label_return: - return (ret); + return ret; } bool -ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data) -{ +ckh_remove(tsd_t *tsd, ckh_t *ckh, const void *searchkey, void **key, + void **data) { size_t cell; assert(ckh != NULL); cell = ckh_isearch(ckh, searchkey); if (cell != SIZE_T_MAX) { - if (key != NULL) + if (key != NULL) { *key = (void *)ckh->tab[cell].key; - if (data != NULL) + } + if (data != NULL) { *data = (void *)ckh->tab[cell].data; + } ckh->tab[cell].key = NULL; ckh->tab[cell].data = NULL; /* Not necessary. */ @@ -497,54 +509,50 @@ ckh_remove(ckh_t *ckh, const void *searchkey, void **key, void **data) + LG_CKH_BUCKET_CELLS - 2)) && ckh->lg_curbuckets > ckh->lg_minbuckets) { /* Ignore error due to OOM. */ - ckh_shrink(ckh); + ckh_shrink(tsd, ckh); } - return (false); + return false; } - return (true); + return true; } bool -ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data) -{ +ckh_search(ckh_t *ckh, const void *searchkey, void **key, void **data) { size_t cell; assert(ckh != NULL); cell = ckh_isearch(ckh, searchkey); if (cell != SIZE_T_MAX) { - if (key != NULL) + if (key != NULL) { *key = (void *)ckh->tab[cell].key; - if (data != NULL) + } + if (data != NULL) { *data = (void *)ckh->tab[cell].data; - return (false); + } + return false; } - return (true); + return true; } void -ckh_string_hash(const void *key, size_t r_hash[2]) -{ - +ckh_string_hash(const void *key, size_t r_hash[2]) { hash(key, strlen((const char *)key), 0x94122f33U, r_hash); } bool -ckh_string_keycomp(const void *k1, const void *k2) -{ - - assert(k1 != NULL); - assert(k2 != NULL); +ckh_string_keycomp(const void *k1, const void *k2) { + assert(k1 != NULL); + assert(k2 != NULL); - return (strcmp((char *)k1, (char *)k2) ? false : true); + return !strcmp((char *)k1, (char *)k2); } void -ckh_pointer_hash(const void *key, size_t r_hash[2]) -{ +ckh_pointer_hash(const void *key, size_t r_hash[2]) { union { const void *v; size_t i; @@ -556,8 +564,6 @@ ckh_pointer_hash(const void *key, size_t r_hash[2]) } bool -ckh_pointer_keycomp(const void *k1, const void *k2) -{ - - return ((k1 == k2) ? true : false); +ckh_pointer_keycomp(const void *k1, const void *k2) { + return (k1 == k2); } diff --git a/deps/jemalloc/src/ctl.c b/deps/jemalloc/src/ctl.c index cc2c5aef57..36bc8fb5b7 100644 --- a/deps/jemalloc/src/ctl.c +++ b/deps/jemalloc/src/ctl.c @@ -1,146 +1,146 @@ -#define JEMALLOC_CTL_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_CTL_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/ctl.h" +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/nstime.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/util.h" /******************************************************************************/ /* Data. */ /* * ctl_mtx protects the following: - * - ctl_stats.* - * - opt_prof_active + * - ctl_stats->* */ static malloc_mutex_t ctl_mtx; static bool ctl_initialized; -static uint64_t ctl_epoch; -static ctl_stats_t ctl_stats; +static ctl_stats_t *ctl_stats; +static ctl_arenas_t *ctl_arenas; /******************************************************************************/ /* Helpers for named and indexed nodes. */ -static inline const ctl_named_node_t * -ctl_named_node(const ctl_node_t *node) -{ - +static const ctl_named_node_t * +ctl_named_node(const ctl_node_t *node) { return ((node->named) ? (const ctl_named_node_t *)node : NULL); } -static inline const ctl_named_node_t * -ctl_named_children(const ctl_named_node_t *node, int index) -{ +static const ctl_named_node_t * +ctl_named_children(const ctl_named_node_t *node, size_t index) { const ctl_named_node_t *children = ctl_named_node(node->children); return (children ? &children[index] : NULL); } -static inline const ctl_indexed_node_t * -ctl_indexed_node(const ctl_node_t *node) -{ - - return ((node->named == false) ? (const ctl_indexed_node_t *)node : - NULL); +static const ctl_indexed_node_t * +ctl_indexed_node(const ctl_node_t *node) { + return (!node->named ? (const ctl_indexed_node_t *)node : NULL); } /******************************************************************************/ /* Function prototypes for non-inline static functions. */ -#define CTL_PROTO(n) \ -static int n##_ctl(const size_t *mib, size_t miblen, void *oldp, \ - size_t *oldlenp, void *newp, size_t newlen); - -#define INDEX_PROTO(n) \ -static const ctl_named_node_t *n##_index(const size_t *mib, \ - size_t miblen, size_t i); - -static bool ctl_arena_init(ctl_arena_stats_t *astats); -static void ctl_arena_clear(ctl_arena_stats_t *astats); -static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, - arena_t *arena); -static void ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, - ctl_arena_stats_t *astats); -static void ctl_arena_refresh(arena_t *arena, unsigned i); -static bool ctl_grow(void); -static void ctl_refresh(void); -static bool ctl_init(void); -static int ctl_lookup(const char *name, ctl_node_t const **nodesp, - size_t *mibp, size_t *depthp); +#define CTL_PROTO(n) \ +static int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \ + void *oldp, size_t *oldlenp, void *newp, size_t newlen); + +#define INDEX_PROTO(n) \ +static const ctl_named_node_t *n##_index(tsdn_t *tsdn, \ + const size_t *mib, size_t miblen, size_t i); CTL_PROTO(version) CTL_PROTO(epoch) +CTL_PROTO(background_thread) CTL_PROTO(thread_tcache_enabled) CTL_PROTO(thread_tcache_flush) +CTL_PROTO(thread_prof_name) +CTL_PROTO(thread_prof_active) CTL_PROTO(thread_arena) CTL_PROTO(thread_allocated) CTL_PROTO(thread_allocatedp) CTL_PROTO(thread_deallocated) CTL_PROTO(thread_deallocatedp) +CTL_PROTO(config_cache_oblivious) CTL_PROTO(config_debug) -CTL_PROTO(config_dss) CTL_PROTO(config_fill) CTL_PROTO(config_lazy_lock) -CTL_PROTO(config_mremap) -CTL_PROTO(config_munmap) +CTL_PROTO(config_malloc_conf) CTL_PROTO(config_prof) CTL_PROTO(config_prof_libgcc) CTL_PROTO(config_prof_libunwind) CTL_PROTO(config_stats) -CTL_PROTO(config_tcache) -CTL_PROTO(config_tls) +CTL_PROTO(config_thp) CTL_PROTO(config_utrace) -CTL_PROTO(config_valgrind) CTL_PROTO(config_xmalloc) CTL_PROTO(opt_abort) +CTL_PROTO(opt_abort_conf) +CTL_PROTO(opt_retain) CTL_PROTO(opt_dss) -CTL_PROTO(opt_lg_chunk) CTL_PROTO(opt_narenas) -CTL_PROTO(opt_lg_dirty_mult) +CTL_PROTO(opt_percpu_arena) +CTL_PROTO(opt_background_thread) +CTL_PROTO(opt_dirty_decay_ms) +CTL_PROTO(opt_muzzy_decay_ms) CTL_PROTO(opt_stats_print) +CTL_PROTO(opt_stats_print_opts) CTL_PROTO(opt_junk) CTL_PROTO(opt_zero) -CTL_PROTO(opt_quarantine) -CTL_PROTO(opt_redzone) CTL_PROTO(opt_utrace) -CTL_PROTO(opt_valgrind) CTL_PROTO(opt_xmalloc) CTL_PROTO(opt_tcache) CTL_PROTO(opt_lg_tcache_max) CTL_PROTO(opt_prof) CTL_PROTO(opt_prof_prefix) CTL_PROTO(opt_prof_active) +CTL_PROTO(opt_prof_thread_active_init) CTL_PROTO(opt_lg_prof_sample) CTL_PROTO(opt_lg_prof_interval) CTL_PROTO(opt_prof_gdump) CTL_PROTO(opt_prof_final) CTL_PROTO(opt_prof_leak) CTL_PROTO(opt_prof_accum) +CTL_PROTO(tcache_create) +CTL_PROTO(tcache_flush) +CTL_PROTO(tcache_destroy) +CTL_PROTO(arena_i_initialized) +CTL_PROTO(arena_i_decay) CTL_PROTO(arena_i_purge) -static void arena_purge(unsigned arena_ind); +CTL_PROTO(arena_i_reset) +CTL_PROTO(arena_i_destroy) CTL_PROTO(arena_i_dss) +CTL_PROTO(arena_i_dirty_decay_ms) +CTL_PROTO(arena_i_muzzy_decay_ms) +CTL_PROTO(arena_i_extent_hooks) INDEX_PROTO(arena_i) CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_nregs) -CTL_PROTO(arenas_bin_i_run_size) +CTL_PROTO(arenas_bin_i_slab_size) INDEX_PROTO(arenas_bin_i) -CTL_PROTO(arenas_lrun_i_size) -INDEX_PROTO(arenas_lrun_i) +CTL_PROTO(arenas_lextent_i_size) +INDEX_PROTO(arenas_lextent_i) CTL_PROTO(arenas_narenas) -CTL_PROTO(arenas_initialized) +CTL_PROTO(arenas_dirty_decay_ms) +CTL_PROTO(arenas_muzzy_decay_ms) CTL_PROTO(arenas_quantum) CTL_PROTO(arenas_page) CTL_PROTO(arenas_tcache_max) CTL_PROTO(arenas_nbins) CTL_PROTO(arenas_nhbins) -CTL_PROTO(arenas_nlruns) -CTL_PROTO(arenas_purge) -CTL_PROTO(arenas_extend) +CTL_PROTO(arenas_nlextents) +CTL_PROTO(arenas_create) +CTL_PROTO(prof_thread_active_init) CTL_PROTO(prof_active) CTL_PROTO(prof_dump) +CTL_PROTO(prof_gdump) +CTL_PROTO(prof_reset) CTL_PROTO(prof_interval) -CTL_PROTO(stats_chunks_current) -CTL_PROTO(stats_chunks_total) -CTL_PROTO(stats_chunks_high) -CTL_PROTO(stats_huge_allocated) -CTL_PROTO(stats_huge_nmalloc) -CTL_PROTO(stats_huge_ndalloc) +CTL_PROTO(lg_prof_sample) CTL_PROTO(stats_arenas_i_small_allocated) CTL_PROTO(stats_arenas_i_small_nmalloc) CTL_PROTO(stats_arenas_i_small_ndalloc) @@ -149,119 +149,177 @@ CTL_PROTO(stats_arenas_i_large_allocated) CTL_PROTO(stats_arenas_i_large_nmalloc) CTL_PROTO(stats_arenas_i_large_ndalloc) CTL_PROTO(stats_arenas_i_large_nrequests) -CTL_PROTO(stats_arenas_i_bins_j_allocated) CTL_PROTO(stats_arenas_i_bins_j_nmalloc) CTL_PROTO(stats_arenas_i_bins_j_ndalloc) CTL_PROTO(stats_arenas_i_bins_j_nrequests) +CTL_PROTO(stats_arenas_i_bins_j_curregs) CTL_PROTO(stats_arenas_i_bins_j_nfills) CTL_PROTO(stats_arenas_i_bins_j_nflushes) -CTL_PROTO(stats_arenas_i_bins_j_nruns) -CTL_PROTO(stats_arenas_i_bins_j_nreruns) -CTL_PROTO(stats_arenas_i_bins_j_curruns) +CTL_PROTO(stats_arenas_i_bins_j_nslabs) +CTL_PROTO(stats_arenas_i_bins_j_nreslabs) +CTL_PROTO(stats_arenas_i_bins_j_curslabs) INDEX_PROTO(stats_arenas_i_bins_j) -CTL_PROTO(stats_arenas_i_lruns_j_nmalloc) -CTL_PROTO(stats_arenas_i_lruns_j_ndalloc) -CTL_PROTO(stats_arenas_i_lruns_j_nrequests) -CTL_PROTO(stats_arenas_i_lruns_j_curruns) -INDEX_PROTO(stats_arenas_i_lruns_j) +CTL_PROTO(stats_arenas_i_lextents_j_nmalloc) +CTL_PROTO(stats_arenas_i_lextents_j_ndalloc) +CTL_PROTO(stats_arenas_i_lextents_j_nrequests) +CTL_PROTO(stats_arenas_i_lextents_j_curlextents) +INDEX_PROTO(stats_arenas_i_lextents_j) CTL_PROTO(stats_arenas_i_nthreads) +CTL_PROTO(stats_arenas_i_uptime) CTL_PROTO(stats_arenas_i_dss) +CTL_PROTO(stats_arenas_i_dirty_decay_ms) +CTL_PROTO(stats_arenas_i_muzzy_decay_ms) CTL_PROTO(stats_arenas_i_pactive) CTL_PROTO(stats_arenas_i_pdirty) +CTL_PROTO(stats_arenas_i_pmuzzy) CTL_PROTO(stats_arenas_i_mapped) -CTL_PROTO(stats_arenas_i_npurge) -CTL_PROTO(stats_arenas_i_nmadvise) -CTL_PROTO(stats_arenas_i_purged) +CTL_PROTO(stats_arenas_i_retained) +CTL_PROTO(stats_arenas_i_dirty_npurge) +CTL_PROTO(stats_arenas_i_dirty_nmadvise) +CTL_PROTO(stats_arenas_i_dirty_purged) +CTL_PROTO(stats_arenas_i_muzzy_npurge) +CTL_PROTO(stats_arenas_i_muzzy_nmadvise) +CTL_PROTO(stats_arenas_i_muzzy_purged) +CTL_PROTO(stats_arenas_i_base) +CTL_PROTO(stats_arenas_i_internal) +CTL_PROTO(stats_arenas_i_tcache_bytes) +CTL_PROTO(stats_arenas_i_resident) INDEX_PROTO(stats_arenas_i) -CTL_PROTO(stats_cactive) CTL_PROTO(stats_allocated) CTL_PROTO(stats_active) +CTL_PROTO(stats_background_thread_num_threads) +CTL_PROTO(stats_background_thread_num_runs) +CTL_PROTO(stats_background_thread_run_interval) +CTL_PROTO(stats_metadata) +CTL_PROTO(stats_resident) CTL_PROTO(stats_mapped) +CTL_PROTO(stats_retained) + +#define MUTEX_STATS_CTL_PROTO_GEN(n) \ +CTL_PROTO(stats_##n##_num_ops) \ +CTL_PROTO(stats_##n##_num_wait) \ +CTL_PROTO(stats_##n##_num_spin_acq) \ +CTL_PROTO(stats_##n##_num_owner_switch) \ +CTL_PROTO(stats_##n##_total_wait_time) \ +CTL_PROTO(stats_##n##_max_wait_time) \ +CTL_PROTO(stats_##n##_max_num_thds) + +/* Global mutexes. */ +#define OP(mtx) MUTEX_STATS_CTL_PROTO_GEN(mutexes_##mtx) +MUTEX_PROF_GLOBAL_MUTEXES +#undef OP + +/* Per arena mutexes. */ +#define OP(mtx) MUTEX_STATS_CTL_PROTO_GEN(arenas_i_mutexes_##mtx) +MUTEX_PROF_ARENA_MUTEXES +#undef OP + +/* Arena bin mutexes. */ +MUTEX_STATS_CTL_PROTO_GEN(arenas_i_bins_j_mutex) +#undef MUTEX_STATS_CTL_PROTO_GEN + +CTL_PROTO(stats_mutexes_reset) /******************************************************************************/ /* mallctl tree. */ -/* Maximum tree depth. */ -#define CTL_MAX_DEPTH 6 - -#define NAME(n) {true}, n -#define CHILD(t, c) \ +#define NAME(n) {true}, n +#define CHILD(t, c) \ sizeof(c##_node) / sizeof(ctl_##t##_node_t), \ (ctl_node_t *)c##_node, \ NULL -#define CTL(c) 0, NULL, c##_ctl +#define CTL(c) 0, NULL, c##_ctl /* * Only handles internal indexed nodes, since there are currently no external * ones. */ -#define INDEX(i) {false}, i##_index +#define INDEX(i) {false}, i##_index -static const ctl_named_node_t tcache_node[] = { +static const ctl_named_node_t thread_tcache_node[] = { {NAME("enabled"), CTL(thread_tcache_enabled)}, {NAME("flush"), CTL(thread_tcache_flush)} }; +static const ctl_named_node_t thread_prof_node[] = { + {NAME("name"), CTL(thread_prof_name)}, + {NAME("active"), CTL(thread_prof_active)} +}; + static const ctl_named_node_t thread_node[] = { {NAME("arena"), CTL(thread_arena)}, {NAME("allocated"), CTL(thread_allocated)}, {NAME("allocatedp"), CTL(thread_allocatedp)}, {NAME("deallocated"), CTL(thread_deallocated)}, {NAME("deallocatedp"), CTL(thread_deallocatedp)}, - {NAME("tcache"), CHILD(named, tcache)} + {NAME("tcache"), CHILD(named, thread_tcache)}, + {NAME("prof"), CHILD(named, thread_prof)} }; static const ctl_named_node_t config_node[] = { - {NAME("debug"), CTL(config_debug)}, - {NAME("dss"), CTL(config_dss)}, - {NAME("fill"), CTL(config_fill)}, - {NAME("lazy_lock"), CTL(config_lazy_lock)}, - {NAME("mremap"), CTL(config_mremap)}, - {NAME("munmap"), CTL(config_munmap)}, - {NAME("prof"), CTL(config_prof)}, - {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, - {NAME("prof_libunwind"), CTL(config_prof_libunwind)}, - {NAME("stats"), CTL(config_stats)}, - {NAME("tcache"), CTL(config_tcache)}, - {NAME("tls"), CTL(config_tls)}, - {NAME("utrace"), CTL(config_utrace)}, - {NAME("valgrind"), CTL(config_valgrind)}, - {NAME("xmalloc"), CTL(config_xmalloc)} + {NAME("cache_oblivious"), CTL(config_cache_oblivious)}, + {NAME("debug"), CTL(config_debug)}, + {NAME("fill"), CTL(config_fill)}, + {NAME("lazy_lock"), CTL(config_lazy_lock)}, + {NAME("malloc_conf"), CTL(config_malloc_conf)}, + {NAME("prof"), CTL(config_prof)}, + {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, + {NAME("prof_libunwind"), CTL(config_prof_libunwind)}, + {NAME("stats"), CTL(config_stats)}, + {NAME("thp"), CTL(config_thp)}, + {NAME("utrace"), CTL(config_utrace)}, + {NAME("xmalloc"), CTL(config_xmalloc)} }; static const ctl_named_node_t opt_node[] = { - {NAME("abort"), CTL(opt_abort)}, - {NAME("dss"), CTL(opt_dss)}, - {NAME("lg_chunk"), CTL(opt_lg_chunk)}, - {NAME("narenas"), CTL(opt_narenas)}, - {NAME("lg_dirty_mult"), CTL(opt_lg_dirty_mult)}, - {NAME("stats_print"), CTL(opt_stats_print)}, - {NAME("junk"), CTL(opt_junk)}, - {NAME("zero"), CTL(opt_zero)}, - {NAME("quarantine"), CTL(opt_quarantine)}, - {NAME("redzone"), CTL(opt_redzone)}, - {NAME("utrace"), CTL(opt_utrace)}, - {NAME("valgrind"), CTL(opt_valgrind)}, - {NAME("xmalloc"), CTL(opt_xmalloc)}, - {NAME("tcache"), CTL(opt_tcache)}, - {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)}, - {NAME("prof"), CTL(opt_prof)}, - {NAME("prof_prefix"), CTL(opt_prof_prefix)}, - {NAME("prof_active"), CTL(opt_prof_active)}, - {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)}, - {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)}, - {NAME("prof_gdump"), CTL(opt_prof_gdump)}, - {NAME("prof_final"), CTL(opt_prof_final)}, - {NAME("prof_leak"), CTL(opt_prof_leak)}, - {NAME("prof_accum"), CTL(opt_prof_accum)} + {NAME("abort"), CTL(opt_abort)}, + {NAME("abort_conf"), CTL(opt_abort_conf)}, + {NAME("retain"), CTL(opt_retain)}, + {NAME("dss"), CTL(opt_dss)}, + {NAME("narenas"), CTL(opt_narenas)}, + {NAME("percpu_arena"), CTL(opt_percpu_arena)}, + {NAME("background_thread"), CTL(opt_background_thread)}, + {NAME("dirty_decay_ms"), CTL(opt_dirty_decay_ms)}, + {NAME("muzzy_decay_ms"), CTL(opt_muzzy_decay_ms)}, + {NAME("stats_print"), CTL(opt_stats_print)}, + {NAME("stats_print_opts"), CTL(opt_stats_print_opts)}, + {NAME("junk"), CTL(opt_junk)}, + {NAME("zero"), CTL(opt_zero)}, + {NAME("utrace"), CTL(opt_utrace)}, + {NAME("xmalloc"), CTL(opt_xmalloc)}, + {NAME("tcache"), CTL(opt_tcache)}, + {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)}, + {NAME("prof"), CTL(opt_prof)}, + {NAME("prof_prefix"), CTL(opt_prof_prefix)}, + {NAME("prof_active"), CTL(opt_prof_active)}, + {NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)}, + {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)}, + {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)}, + {NAME("prof_gdump"), CTL(opt_prof_gdump)}, + {NAME("prof_final"), CTL(opt_prof_final)}, + {NAME("prof_leak"), CTL(opt_prof_leak)}, + {NAME("prof_accum"), CTL(opt_prof_accum)} +}; + +static const ctl_named_node_t tcache_node[] = { + {NAME("create"), CTL(tcache_create)}, + {NAME("flush"), CTL(tcache_flush)}, + {NAME("destroy"), CTL(tcache_destroy)} }; static const ctl_named_node_t arena_i_node[] = { - {NAME("purge"), CTL(arena_i_purge)}, - {NAME("dss"), CTL(arena_i_dss)} + {NAME("initialized"), CTL(arena_i_initialized)}, + {NAME("decay"), CTL(arena_i_decay)}, + {NAME("purge"), CTL(arena_i_purge)}, + {NAME("reset"), CTL(arena_i_reset)}, + {NAME("destroy"), CTL(arena_i_destroy)}, + {NAME("dss"), CTL(arena_i_dss)}, + {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)}, + {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)}, + {NAME("extent_hooks"), CTL(arena_i_extent_hooks)} }; static const ctl_named_node_t super_arena_i_node[] = { - {NAME(""), CHILD(named, arena_i)} + {NAME(""), CHILD(named, arena_i)} }; static const ctl_indexed_node_t arena_node[] = { @@ -269,147 +327,208 @@ static const ctl_indexed_node_t arena_node[] = { }; static const ctl_named_node_t arenas_bin_i_node[] = { - {NAME("size"), CTL(arenas_bin_i_size)}, - {NAME("nregs"), CTL(arenas_bin_i_nregs)}, - {NAME("run_size"), CTL(arenas_bin_i_run_size)} + {NAME("size"), CTL(arenas_bin_i_size)}, + {NAME("nregs"), CTL(arenas_bin_i_nregs)}, + {NAME("slab_size"), CTL(arenas_bin_i_slab_size)} }; static const ctl_named_node_t super_arenas_bin_i_node[] = { - {NAME(""), CHILD(named, arenas_bin_i)} + {NAME(""), CHILD(named, arenas_bin_i)} }; static const ctl_indexed_node_t arenas_bin_node[] = { {INDEX(arenas_bin_i)} }; -static const ctl_named_node_t arenas_lrun_i_node[] = { - {NAME("size"), CTL(arenas_lrun_i_size)} +static const ctl_named_node_t arenas_lextent_i_node[] = { + {NAME("size"), CTL(arenas_lextent_i_size)} }; -static const ctl_named_node_t super_arenas_lrun_i_node[] = { - {NAME(""), CHILD(named, arenas_lrun_i)} +static const ctl_named_node_t super_arenas_lextent_i_node[] = { + {NAME(""), CHILD(named, arenas_lextent_i)} }; -static const ctl_indexed_node_t arenas_lrun_node[] = { - {INDEX(arenas_lrun_i)} +static const ctl_indexed_node_t arenas_lextent_node[] = { + {INDEX(arenas_lextent_i)} }; static const ctl_named_node_t arenas_node[] = { - {NAME("narenas"), CTL(arenas_narenas)}, - {NAME("initialized"), CTL(arenas_initialized)}, - {NAME("quantum"), CTL(arenas_quantum)}, - {NAME("page"), CTL(arenas_page)}, - {NAME("tcache_max"), CTL(arenas_tcache_max)}, - {NAME("nbins"), CTL(arenas_nbins)}, - {NAME("nhbins"), CTL(arenas_nhbins)}, - {NAME("bin"), CHILD(indexed, arenas_bin)}, - {NAME("nlruns"), CTL(arenas_nlruns)}, - {NAME("lrun"), CHILD(indexed, arenas_lrun)}, - {NAME("purge"), CTL(arenas_purge)}, - {NAME("extend"), CTL(arenas_extend)} + {NAME("narenas"), CTL(arenas_narenas)}, + {NAME("dirty_decay_ms"), CTL(arenas_dirty_decay_ms)}, + {NAME("muzzy_decay_ms"), CTL(arenas_muzzy_decay_ms)}, + {NAME("quantum"), CTL(arenas_quantum)}, + {NAME("page"), CTL(arenas_page)}, + {NAME("tcache_max"), CTL(arenas_tcache_max)}, + {NAME("nbins"), CTL(arenas_nbins)}, + {NAME("nhbins"), CTL(arenas_nhbins)}, + {NAME("bin"), CHILD(indexed, arenas_bin)}, + {NAME("nlextents"), CTL(arenas_nlextents)}, + {NAME("lextent"), CHILD(indexed, arenas_lextent)}, + {NAME("create"), CTL(arenas_create)} }; static const ctl_named_node_t prof_node[] = { + {NAME("thread_active_init"), CTL(prof_thread_active_init)}, {NAME("active"), CTL(prof_active)}, {NAME("dump"), CTL(prof_dump)}, - {NAME("interval"), CTL(prof_interval)} + {NAME("gdump"), CTL(prof_gdump)}, + {NAME("reset"), CTL(prof_reset)}, + {NAME("interval"), CTL(prof_interval)}, + {NAME("lg_sample"), CTL(lg_prof_sample)} }; -static const ctl_named_node_t stats_chunks_node[] = { - {NAME("current"), CTL(stats_chunks_current)}, - {NAME("total"), CTL(stats_chunks_total)}, - {NAME("high"), CTL(stats_chunks_high)} +static const ctl_named_node_t stats_arenas_i_small_node[] = { + {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, + {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, + {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)}, + {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)} }; -static const ctl_named_node_t stats_huge_node[] = { - {NAME("allocated"), CTL(stats_huge_allocated)}, - {NAME("nmalloc"), CTL(stats_huge_nmalloc)}, - {NAME("ndalloc"), CTL(stats_huge_ndalloc)} +static const ctl_named_node_t stats_arenas_i_large_node[] = { + {NAME("allocated"), CTL(stats_arenas_i_large_allocated)}, + {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)}, + {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)}, + {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)} }; -static const ctl_named_node_t stats_arenas_i_small_node[] = { - {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, - {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, - {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)}, - {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)} +#define MUTEX_PROF_DATA_NODE(prefix) \ +static const ctl_named_node_t stats_##prefix##_node[] = { \ + {NAME("num_ops"), \ + CTL(stats_##prefix##_num_ops)}, \ + {NAME("num_wait"), \ + CTL(stats_##prefix##_num_wait)}, \ + {NAME("num_spin_acq"), \ + CTL(stats_##prefix##_num_spin_acq)}, \ + {NAME("num_owner_switch"), \ + CTL(stats_##prefix##_num_owner_switch)}, \ + {NAME("total_wait_time"), \ + CTL(stats_##prefix##_total_wait_time)}, \ + {NAME("max_wait_time"), \ + CTL(stats_##prefix##_max_wait_time)}, \ + {NAME("max_num_thds"), \ + CTL(stats_##prefix##_max_num_thds)} \ + /* Note that # of current waiting thread not provided. */ \ }; -static const ctl_named_node_t stats_arenas_i_large_node[] = { - {NAME("allocated"), CTL(stats_arenas_i_large_allocated)}, - {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)}, - {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)}, - {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)} -}; +MUTEX_PROF_DATA_NODE(arenas_i_bins_j_mutex) static const ctl_named_node_t stats_arenas_i_bins_j_node[] = { - {NAME("allocated"), CTL(stats_arenas_i_bins_j_allocated)}, - {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)}, - {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)}, - {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)}, - {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)}, - {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)}, - {NAME("nruns"), CTL(stats_arenas_i_bins_j_nruns)}, - {NAME("nreruns"), CTL(stats_arenas_i_bins_j_nreruns)}, - {NAME("curruns"), CTL(stats_arenas_i_bins_j_curruns)} + {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)}, + {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)}, + {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)}, + {NAME("curregs"), CTL(stats_arenas_i_bins_j_curregs)}, + {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)}, + {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)}, + {NAME("nslabs"), CTL(stats_arenas_i_bins_j_nslabs)}, + {NAME("nreslabs"), CTL(stats_arenas_i_bins_j_nreslabs)}, + {NAME("curslabs"), CTL(stats_arenas_i_bins_j_curslabs)}, + {NAME("mutex"), CHILD(named, stats_arenas_i_bins_j_mutex)} }; + static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = { - {NAME(""), CHILD(named, stats_arenas_i_bins_j)} + {NAME(""), CHILD(named, stats_arenas_i_bins_j)} }; static const ctl_indexed_node_t stats_arenas_i_bins_node[] = { {INDEX(stats_arenas_i_bins_j)} }; -static const ctl_named_node_t stats_arenas_i_lruns_j_node[] = { - {NAME("nmalloc"), CTL(stats_arenas_i_lruns_j_nmalloc)}, - {NAME("ndalloc"), CTL(stats_arenas_i_lruns_j_ndalloc)}, - {NAME("nrequests"), CTL(stats_arenas_i_lruns_j_nrequests)}, - {NAME("curruns"), CTL(stats_arenas_i_lruns_j_curruns)} +static const ctl_named_node_t stats_arenas_i_lextents_j_node[] = { + {NAME("nmalloc"), CTL(stats_arenas_i_lextents_j_nmalloc)}, + {NAME("ndalloc"), CTL(stats_arenas_i_lextents_j_ndalloc)}, + {NAME("nrequests"), CTL(stats_arenas_i_lextents_j_nrequests)}, + {NAME("curlextents"), CTL(stats_arenas_i_lextents_j_curlextents)} }; -static const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = { - {NAME(""), CHILD(named, stats_arenas_i_lruns_j)} +static const ctl_named_node_t super_stats_arenas_i_lextents_j_node[] = { + {NAME(""), CHILD(named, stats_arenas_i_lextents_j)} }; -static const ctl_indexed_node_t stats_arenas_i_lruns_node[] = { - {INDEX(stats_arenas_i_lruns_j)} +static const ctl_indexed_node_t stats_arenas_i_lextents_node[] = { + {INDEX(stats_arenas_i_lextents_j)} +}; + +#define OP(mtx) MUTEX_PROF_DATA_NODE(arenas_i_mutexes_##mtx) +MUTEX_PROF_ARENA_MUTEXES +#undef OP + +static const ctl_named_node_t stats_arenas_i_mutexes_node[] = { +#define OP(mtx) {NAME(#mtx), CHILD(named, stats_arenas_i_mutexes_##mtx)}, +MUTEX_PROF_ARENA_MUTEXES +#undef OP }; static const ctl_named_node_t stats_arenas_i_node[] = { - {NAME("nthreads"), CTL(stats_arenas_i_nthreads)}, - {NAME("dss"), CTL(stats_arenas_i_dss)}, - {NAME("pactive"), CTL(stats_arenas_i_pactive)}, - {NAME("pdirty"), CTL(stats_arenas_i_pdirty)}, - {NAME("mapped"), CTL(stats_arenas_i_mapped)}, - {NAME("npurge"), CTL(stats_arenas_i_npurge)}, - {NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)}, - {NAME("purged"), CTL(stats_arenas_i_purged)}, - {NAME("small"), CHILD(named, stats_arenas_i_small)}, - {NAME("large"), CHILD(named, stats_arenas_i_large)}, - {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)}, - {NAME("lruns"), CHILD(indexed, stats_arenas_i_lruns)} + {NAME("nthreads"), CTL(stats_arenas_i_nthreads)}, + {NAME("uptime"), CTL(stats_arenas_i_uptime)}, + {NAME("dss"), CTL(stats_arenas_i_dss)}, + {NAME("dirty_decay_ms"), CTL(stats_arenas_i_dirty_decay_ms)}, + {NAME("muzzy_decay_ms"), CTL(stats_arenas_i_muzzy_decay_ms)}, + {NAME("pactive"), CTL(stats_arenas_i_pactive)}, + {NAME("pdirty"), CTL(stats_arenas_i_pdirty)}, + {NAME("pmuzzy"), CTL(stats_arenas_i_pmuzzy)}, + {NAME("mapped"), CTL(stats_arenas_i_mapped)}, + {NAME("retained"), CTL(stats_arenas_i_retained)}, + {NAME("dirty_npurge"), CTL(stats_arenas_i_dirty_npurge)}, + {NAME("dirty_nmadvise"), CTL(stats_arenas_i_dirty_nmadvise)}, + {NAME("dirty_purged"), CTL(stats_arenas_i_dirty_purged)}, + {NAME("muzzy_npurge"), CTL(stats_arenas_i_muzzy_npurge)}, + {NAME("muzzy_nmadvise"), CTL(stats_arenas_i_muzzy_nmadvise)}, + {NAME("muzzy_purged"), CTL(stats_arenas_i_muzzy_purged)}, + {NAME("base"), CTL(stats_arenas_i_base)}, + {NAME("internal"), CTL(stats_arenas_i_internal)}, + {NAME("tcache_bytes"), CTL(stats_arenas_i_tcache_bytes)}, + {NAME("resident"), CTL(stats_arenas_i_resident)}, + {NAME("small"), CHILD(named, stats_arenas_i_small)}, + {NAME("large"), CHILD(named, stats_arenas_i_large)}, + {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)}, + {NAME("lextents"), CHILD(indexed, stats_arenas_i_lextents)}, + {NAME("mutexes"), CHILD(named, stats_arenas_i_mutexes)} }; static const ctl_named_node_t super_stats_arenas_i_node[] = { - {NAME(""), CHILD(named, stats_arenas_i)} + {NAME(""), CHILD(named, stats_arenas_i)} }; static const ctl_indexed_node_t stats_arenas_node[] = { {INDEX(stats_arenas_i)} }; +static const ctl_named_node_t stats_background_thread_node[] = { + {NAME("num_threads"), CTL(stats_background_thread_num_threads)}, + {NAME("num_runs"), CTL(stats_background_thread_num_runs)}, + {NAME("run_interval"), CTL(stats_background_thread_run_interval)} +}; + +#define OP(mtx) MUTEX_PROF_DATA_NODE(mutexes_##mtx) +MUTEX_PROF_GLOBAL_MUTEXES +#undef OP + +static const ctl_named_node_t stats_mutexes_node[] = { +#define OP(mtx) {NAME(#mtx), CHILD(named, stats_mutexes_##mtx)}, +MUTEX_PROF_GLOBAL_MUTEXES +#undef OP + {NAME("reset"), CTL(stats_mutexes_reset)} +}; +#undef MUTEX_PROF_DATA_NODE + static const ctl_named_node_t stats_node[] = { - {NAME("cactive"), CTL(stats_cactive)}, - {NAME("allocated"), CTL(stats_allocated)}, - {NAME("active"), CTL(stats_active)}, - {NAME("mapped"), CTL(stats_mapped)}, - {NAME("chunks"), CHILD(named, stats_chunks)}, - {NAME("huge"), CHILD(named, stats_huge)}, - {NAME("arenas"), CHILD(indexed, stats_arenas)} + {NAME("allocated"), CTL(stats_allocated)}, + {NAME("active"), CTL(stats_active)}, + {NAME("metadata"), CTL(stats_metadata)}, + {NAME("resident"), CTL(stats_resident)}, + {NAME("mapped"), CTL(stats_mapped)}, + {NAME("retained"), CTL(stats_retained)}, + {NAME("background_thread"), + CHILD(named, stats_background_thread)}, + {NAME("mutexes"), CHILD(named, stats_mutexes)}, + {NAME("arenas"), CHILD(indexed, stats_arenas)} }; static const ctl_named_node_t root_node[] = { {NAME("version"), CTL(version)}, {NAME("epoch"), CTL(epoch)}, + {NAME("background_thread"), CTL(background_thread)}, {NAME("thread"), CHILD(named, thread)}, {NAME("config"), CHILD(named, config)}, {NAME("opt"), CHILD(named, opt)}, + {NAME("tcache"), CHILD(named, tcache)}, {NAME("arena"), CHILD(indexed, arena)}, {NAME("arenas"), CHILD(named, arenas)}, {NAME("prof"), CHILD(named, prof)}, @@ -426,303 +545,514 @@ static const ctl_named_node_t super_root_node[] = { /******************************************************************************/ -static bool -ctl_arena_init(ctl_arena_stats_t *astats) -{ +/* + * Sets *dst + *src non-atomically. This is safe, since everything is + * synchronized by the ctl mutex. + */ +static void +accum_arena_stats_u64(arena_stats_u64_t *dst, arena_stats_u64_t *src) { +#ifdef JEMALLOC_ATOMIC_U64 + uint64_t cur_dst = atomic_load_u64(dst, ATOMIC_RELAXED); + uint64_t cur_src = atomic_load_u64(src, ATOMIC_RELAXED); + atomic_store_u64(dst, cur_dst + cur_src, ATOMIC_RELAXED); +#else + *dst += *src; +#endif +} - if (astats->lstats == NULL) { - astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses * - sizeof(malloc_large_stats_t)); - if (astats->lstats == NULL) - return (true); +/* Likewise: with ctl mutex synchronization, reading is simple. */ +static uint64_t +arena_stats_read_u64(arena_stats_u64_t *p) { +#ifdef JEMALLOC_ATOMIC_U64 + return atomic_load_u64(p, ATOMIC_RELAXED); +#else + return *p; +#endif +} + +static void accum_atomic_zu(atomic_zu_t *dst, atomic_zu_t *src) { + size_t cur_dst = atomic_load_zu(dst, ATOMIC_RELAXED); + size_t cur_src = atomic_load_zu(src, ATOMIC_RELAXED); + atomic_store_zu(dst, cur_dst + cur_src, ATOMIC_RELAXED); +} + +/******************************************************************************/ + +static unsigned +arenas_i2a_impl(size_t i, bool compat, bool validate) { + unsigned a; + + switch (i) { + case MALLCTL_ARENAS_ALL: + a = 0; + break; + case MALLCTL_ARENAS_DESTROYED: + a = 1; + break; + default: + if (compat && i == ctl_arenas->narenas) { + /* + * Provide deprecated backward compatibility for + * accessing the merged stats at index narenas rather + * than via MALLCTL_ARENAS_ALL. This is scheduled for + * removal in 6.0.0. + */ + a = 0; + } else if (validate && i >= ctl_arenas->narenas) { + a = UINT_MAX; + } else { + /* + * This function should never be called for an index + * more than one past the range of indices that have + * initialized ctl data. + */ + assert(i < ctl_arenas->narenas || (!validate && i == + ctl_arenas->narenas)); + a = (unsigned)i + 2; + } + break; } - return (false); + return a; } -static void -ctl_arena_clear(ctl_arena_stats_t *astats) -{ +static unsigned +arenas_i2a(size_t i) { + return arenas_i2a_impl(i, true, false); +} + +static ctl_arena_t * +arenas_i_impl(tsd_t *tsd, size_t i, bool compat, bool init) { + ctl_arena_t *ret; - astats->dss = dss_prec_names[dss_prec_limit]; - astats->pactive = 0; - astats->pdirty = 0; + assert(!compat || !init); + + ret = ctl_arenas->arenas[arenas_i2a_impl(i, compat, false)]; + if (init && ret == NULL) { + if (config_stats) { + struct container_s { + ctl_arena_t ctl_arena; + ctl_arena_stats_t astats; + }; + struct container_s *cont = + (struct container_s *)base_alloc(tsd_tsdn(tsd), + b0get(), sizeof(struct container_s), QUANTUM); + if (cont == NULL) { + return NULL; + } + ret = &cont->ctl_arena; + ret->astats = &cont->astats; + } else { + ret = (ctl_arena_t *)base_alloc(tsd_tsdn(tsd), b0get(), + sizeof(ctl_arena_t), QUANTUM); + if (ret == NULL) { + return NULL; + } + } + ret->arena_ind = (unsigned)i; + ctl_arenas->arenas[arenas_i2a_impl(i, compat, false)] = ret; + } + + assert(ret == NULL || arenas_i2a(ret->arena_ind) == arenas_i2a(i)); + return ret; +} + +static ctl_arena_t * +arenas_i(size_t i) { + ctl_arena_t *ret = arenas_i_impl(tsd_fetch(), i, true, false); + assert(ret != NULL); + return ret; +} + +static void +ctl_arena_clear(ctl_arena_t *ctl_arena) { + ctl_arena->nthreads = 0; + ctl_arena->dss = dss_prec_names[dss_prec_limit]; + ctl_arena->dirty_decay_ms = -1; + ctl_arena->muzzy_decay_ms = -1; + ctl_arena->pactive = 0; + ctl_arena->pdirty = 0; + ctl_arena->pmuzzy = 0; if (config_stats) { - memset(&astats->astats, 0, sizeof(arena_stats_t)); - astats->allocated_small = 0; - astats->nmalloc_small = 0; - astats->ndalloc_small = 0; - astats->nrequests_small = 0; - memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t)); - memset(astats->lstats, 0, nlclasses * + memset(&ctl_arena->astats->astats, 0, sizeof(arena_stats_t)); + ctl_arena->astats->allocated_small = 0; + ctl_arena->astats->nmalloc_small = 0; + ctl_arena->astats->ndalloc_small = 0; + ctl_arena->astats->nrequests_small = 0; + memset(ctl_arena->astats->bstats, 0, NBINS * + sizeof(malloc_bin_stats_t)); + memset(ctl_arena->astats->lstats, 0, (NSIZES - NBINS) * sizeof(malloc_large_stats_t)); } } static void -ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena) -{ +ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_t *ctl_arena, arena_t *arena) { unsigned i; - arena_stats_merge(arena, &cstats->dss, &cstats->pactive, - &cstats->pdirty, &cstats->astats, cstats->bstats, cstats->lstats); - - for (i = 0; i < NBINS; i++) { - cstats->allocated_small += cstats->bstats[i].allocated; - cstats->nmalloc_small += cstats->bstats[i].nmalloc; - cstats->ndalloc_small += cstats->bstats[i].ndalloc; - cstats->nrequests_small += cstats->bstats[i].nrequests; + if (config_stats) { + arena_stats_merge(tsdn, arena, &ctl_arena->nthreads, + &ctl_arena->dss, &ctl_arena->dirty_decay_ms, + &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive, + &ctl_arena->pdirty, &ctl_arena->pmuzzy, + &ctl_arena->astats->astats, ctl_arena->astats->bstats, + ctl_arena->astats->lstats); + + for (i = 0; i < NBINS; i++) { + ctl_arena->astats->allocated_small += + ctl_arena->astats->bstats[i].curregs * + sz_index2size(i); + ctl_arena->astats->nmalloc_small += + ctl_arena->astats->bstats[i].nmalloc; + ctl_arena->astats->ndalloc_small += + ctl_arena->astats->bstats[i].ndalloc; + ctl_arena->astats->nrequests_small += + ctl_arena->astats->bstats[i].nrequests; + } + } else { + arena_basic_stats_merge(tsdn, arena, &ctl_arena->nthreads, + &ctl_arena->dss, &ctl_arena->dirty_decay_ms, + &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive, + &ctl_arena->pdirty, &ctl_arena->pmuzzy); } } static void -ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats) -{ +ctl_arena_stats_sdmerge(ctl_arena_t *ctl_sdarena, ctl_arena_t *ctl_arena, + bool destroyed) { unsigned i; - sstats->pactive += astats->pactive; - sstats->pdirty += astats->pdirty; - - sstats->astats.mapped += astats->astats.mapped; - sstats->astats.npurge += astats->astats.npurge; - sstats->astats.nmadvise += astats->astats.nmadvise; - sstats->astats.purged += astats->astats.purged; - - sstats->allocated_small += astats->allocated_small; - sstats->nmalloc_small += astats->nmalloc_small; - sstats->ndalloc_small += astats->ndalloc_small; - sstats->nrequests_small += astats->nrequests_small; - - sstats->astats.allocated_large += astats->astats.allocated_large; - sstats->astats.nmalloc_large += astats->astats.nmalloc_large; - sstats->astats.ndalloc_large += astats->astats.ndalloc_large; - sstats->astats.nrequests_large += astats->astats.nrequests_large; - - for (i = 0; i < nlclasses; i++) { - sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc; - sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc; - sstats->lstats[i].nrequests += astats->lstats[i].nrequests; - sstats->lstats[i].curruns += astats->lstats[i].curruns; - } - - for (i = 0; i < NBINS; i++) { - sstats->bstats[i].allocated += astats->bstats[i].allocated; - sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc; - sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc; - sstats->bstats[i].nrequests += astats->bstats[i].nrequests; - if (config_tcache) { - sstats->bstats[i].nfills += astats->bstats[i].nfills; - sstats->bstats[i].nflushes += + if (!destroyed) { + ctl_sdarena->nthreads += ctl_arena->nthreads; + ctl_sdarena->pactive += ctl_arena->pactive; + ctl_sdarena->pdirty += ctl_arena->pdirty; + ctl_sdarena->pmuzzy += ctl_arena->pmuzzy; + } else { + assert(ctl_arena->nthreads == 0); + assert(ctl_arena->pactive == 0); + assert(ctl_arena->pdirty == 0); + assert(ctl_arena->pmuzzy == 0); + } + + if (config_stats) { + ctl_arena_stats_t *sdstats = ctl_sdarena->astats; + ctl_arena_stats_t *astats = ctl_arena->astats; + + if (!destroyed) { + accum_atomic_zu(&sdstats->astats.mapped, + &astats->astats.mapped); + accum_atomic_zu(&sdstats->astats.retained, + &astats->astats.retained); + } + + accum_arena_stats_u64(&sdstats->astats.decay_dirty.npurge, + &astats->astats.decay_dirty.npurge); + accum_arena_stats_u64(&sdstats->astats.decay_dirty.nmadvise, + &astats->astats.decay_dirty.nmadvise); + accum_arena_stats_u64(&sdstats->astats.decay_dirty.purged, + &astats->astats.decay_dirty.purged); + + accum_arena_stats_u64(&sdstats->astats.decay_muzzy.npurge, + &astats->astats.decay_muzzy.npurge); + accum_arena_stats_u64(&sdstats->astats.decay_muzzy.nmadvise, + &astats->astats.decay_muzzy.nmadvise); + accum_arena_stats_u64(&sdstats->astats.decay_muzzy.purged, + &astats->astats.decay_muzzy.purged); + +#define OP(mtx) malloc_mutex_prof_merge( \ + &(sdstats->astats.mutex_prof_data[ \ + arena_prof_mutex_##mtx]), \ + &(astats->astats.mutex_prof_data[ \ + arena_prof_mutex_##mtx])); +MUTEX_PROF_ARENA_MUTEXES +#undef OP + if (!destroyed) { + accum_atomic_zu(&sdstats->astats.base, + &astats->astats.base); + accum_atomic_zu(&sdstats->astats.internal, + &astats->astats.internal); + accum_atomic_zu(&sdstats->astats.resident, + &astats->astats.resident); + } else { + assert(atomic_load_zu( + &astats->astats.internal, ATOMIC_RELAXED) == 0); + } + + if (!destroyed) { + sdstats->allocated_small += astats->allocated_small; + } else { + assert(astats->allocated_small == 0); + } + sdstats->nmalloc_small += astats->nmalloc_small; + sdstats->ndalloc_small += astats->ndalloc_small; + sdstats->nrequests_small += astats->nrequests_small; + + if (!destroyed) { + accum_atomic_zu(&sdstats->astats.allocated_large, + &astats->astats.allocated_large); + } else { + assert(atomic_load_zu(&astats->astats.allocated_large, + ATOMIC_RELAXED) == 0); + } + accum_arena_stats_u64(&sdstats->astats.nmalloc_large, + &astats->astats.nmalloc_large); + accum_arena_stats_u64(&sdstats->astats.ndalloc_large, + &astats->astats.ndalloc_large); + accum_arena_stats_u64(&sdstats->astats.nrequests_large, + &astats->astats.nrequests_large); + + accum_atomic_zu(&sdstats->astats.tcache_bytes, + &astats->astats.tcache_bytes); + + if (ctl_arena->arena_ind == 0) { + sdstats->astats.uptime = astats->astats.uptime; + } + + for (i = 0; i < NBINS; i++) { + sdstats->bstats[i].nmalloc += astats->bstats[i].nmalloc; + sdstats->bstats[i].ndalloc += astats->bstats[i].ndalloc; + sdstats->bstats[i].nrequests += + astats->bstats[i].nrequests; + if (!destroyed) { + sdstats->bstats[i].curregs += + astats->bstats[i].curregs; + } else { + assert(astats->bstats[i].curregs == 0); + } + sdstats->bstats[i].nfills += astats->bstats[i].nfills; + sdstats->bstats[i].nflushes += astats->bstats[i].nflushes; + sdstats->bstats[i].nslabs += astats->bstats[i].nslabs; + sdstats->bstats[i].reslabs += astats->bstats[i].reslabs; + if (!destroyed) { + sdstats->bstats[i].curslabs += + astats->bstats[i].curslabs; + } else { + assert(astats->bstats[i].curslabs == 0); + } + malloc_mutex_prof_merge(&sdstats->bstats[i].mutex_data, + &astats->bstats[i].mutex_data); + } + + for (i = 0; i < NSIZES - NBINS; i++) { + accum_arena_stats_u64(&sdstats->lstats[i].nmalloc, + &astats->lstats[i].nmalloc); + accum_arena_stats_u64(&sdstats->lstats[i].ndalloc, + &astats->lstats[i].ndalloc); + accum_arena_stats_u64(&sdstats->lstats[i].nrequests, + &astats->lstats[i].nrequests); + if (!destroyed) { + sdstats->lstats[i].curlextents += + astats->lstats[i].curlextents; + } else { + assert(astats->lstats[i].curlextents == 0); + } } - sstats->bstats[i].nruns += astats->bstats[i].nruns; - sstats->bstats[i].reruns += astats->bstats[i].reruns; - sstats->bstats[i].curruns += astats->bstats[i].curruns; } } static void -ctl_arena_refresh(arena_t *arena, unsigned i) -{ - ctl_arena_stats_t *astats = &ctl_stats.arenas[i]; - ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas]; +ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, ctl_arena_t *ctl_sdarena, + unsigned i, bool destroyed) { + ctl_arena_t *ctl_arena = arenas_i(i); + + ctl_arena_clear(ctl_arena); + ctl_arena_stats_amerge(tsdn, ctl_arena, arena); + /* Merge into sum stats as well. */ + ctl_arena_stats_sdmerge(ctl_sdarena, ctl_arena, destroyed); +} - ctl_arena_clear(astats); +static unsigned +ctl_arena_init(tsd_t *tsd, extent_hooks_t *extent_hooks) { + unsigned arena_ind; + ctl_arena_t *ctl_arena; - sstats->nthreads += astats->nthreads; - if (config_stats) { - ctl_arena_stats_amerge(astats, arena); - /* Merge into sum stats as well. */ - ctl_arena_stats_smerge(sstats, astats); + if ((ctl_arena = ql_last(&ctl_arenas->destroyed, destroyed_link)) != + NULL) { + ql_remove(&ctl_arenas->destroyed, ctl_arena, destroyed_link); + arena_ind = ctl_arena->arena_ind; } else { - astats->pactive += arena->nactive; - astats->pdirty += arena->ndirty; - /* Merge into sum stats as well. */ - sstats->pactive += arena->nactive; - sstats->pdirty += arena->ndirty; + arena_ind = ctl_arenas->narenas; } -} -static bool -ctl_grow(void) -{ - ctl_arena_stats_t *astats; - arena_t **tarenas; - - /* Allocate extended arena stats and arenas arrays. */ - astats = (ctl_arena_stats_t *)imalloc((ctl_stats.narenas + 2) * - sizeof(ctl_arena_stats_t)); - if (astats == NULL) - return (true); - tarenas = (arena_t **)imalloc((ctl_stats.narenas + 1) * - sizeof(arena_t *)); - if (tarenas == NULL) { - idalloc(astats); - return (true); - } - - /* Initialize the new astats element. */ - memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) * - sizeof(ctl_arena_stats_t)); - memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t)); - if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) { - idalloc(tarenas); - idalloc(astats); - return (true); - } - /* Swap merged stats to their new location. */ - { - ctl_arena_stats_t tstats; - memcpy(&tstats, &astats[ctl_stats.narenas], - sizeof(ctl_arena_stats_t)); - memcpy(&astats[ctl_stats.narenas], - &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t)); - memcpy(&astats[ctl_stats.narenas + 1], &tstats, - sizeof(ctl_arena_stats_t)); - } - /* Initialize the new arenas element. */ - tarenas[ctl_stats.narenas] = NULL; - { - arena_t **arenas_old = arenas; - /* - * Swap extended arenas array into place. Although ctl_mtx - * protects this function from other threads extending the - * array, it does not protect from other threads mutating it - * (i.e. initializing arenas and setting array elements to - * point to them). Therefore, array copying must happen under - * the protection of arenas_lock. - */ - malloc_mutex_lock(&arenas_lock); - arenas = tarenas; - memcpy(arenas, arenas_old, ctl_stats.narenas * - sizeof(arena_t *)); - narenas_total++; - arenas_extend(narenas_total - 1); - malloc_mutex_unlock(&arenas_lock); - /* - * Deallocate arenas_old only if it came from imalloc() (not - * base_alloc()). - */ - if (ctl_stats.narenas != narenas_auto) - idalloc(arenas_old); + /* Trigger stats allocation. */ + if (arenas_i_impl(tsd, arena_ind, false, true) == NULL) { + return UINT_MAX; } - ctl_stats.arenas = astats; - ctl_stats.narenas++; - return (false); -} + /* Initialize new arena. */ + if (arena_init(tsd_tsdn(tsd), arena_ind, extent_hooks) == NULL) { + return UINT_MAX; + } -static void -ctl_refresh(void) -{ - unsigned i; - VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); + if (arena_ind == ctl_arenas->narenas) { + ctl_arenas->narenas++; + } - if (config_stats) { - malloc_mutex_lock(&chunks_mtx); - ctl_stats.chunks.current = stats_chunks.curchunks; - ctl_stats.chunks.total = stats_chunks.nchunks; - ctl_stats.chunks.high = stats_chunks.highchunks; - malloc_mutex_unlock(&chunks_mtx); + return arena_ind; +} - malloc_mutex_lock(&huge_mtx); - ctl_stats.huge.allocated = huge_allocated; - ctl_stats.huge.nmalloc = huge_nmalloc; - ctl_stats.huge.ndalloc = huge_ndalloc; - malloc_mutex_unlock(&huge_mtx); +static void +ctl_background_thread_stats_read(tsdn_t *tsdn) { + background_thread_stats_t *stats = &ctl_stats->background_thread; + if (!have_background_thread || + background_thread_stats_read(tsdn, stats)) { + memset(stats, 0, sizeof(background_thread_stats_t)); + nstime_init(&stats->run_interval, 0); } +} + +static void +ctl_refresh(tsdn_t *tsdn) { + unsigned i; + ctl_arena_t *ctl_sarena = arenas_i(MALLCTL_ARENAS_ALL); + VARIABLE_ARRAY(arena_t *, tarenas, ctl_arenas->narenas); /* * Clear sum stats, since they will be merged into by * ctl_arena_refresh(). */ - ctl_stats.arenas[ctl_stats.narenas].nthreads = 0; - ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]); - - malloc_mutex_lock(&arenas_lock); - memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); - for (i = 0; i < ctl_stats.narenas; i++) { - if (arenas[i] != NULL) - ctl_stats.arenas[i].nthreads = arenas[i]->nthreads; - else - ctl_stats.arenas[i].nthreads = 0; - } - malloc_mutex_unlock(&arenas_lock); - for (i = 0; i < ctl_stats.narenas; i++) { + ctl_arena_clear(ctl_sarena); + + for (i = 0; i < ctl_arenas->narenas; i++) { + tarenas[i] = arena_get(tsdn, i, false); + } + + for (i = 0; i < ctl_arenas->narenas; i++) { + ctl_arena_t *ctl_arena = arenas_i(i); bool initialized = (tarenas[i] != NULL); - ctl_stats.arenas[i].initialized = initialized; - if (initialized) - ctl_arena_refresh(tarenas[i], i); + ctl_arena->initialized = initialized; + if (initialized) { + ctl_arena_refresh(tsdn, tarenas[i], ctl_sarena, i, + false); + } } if (config_stats) { - ctl_stats.allocated = - ctl_stats.arenas[ctl_stats.narenas].allocated_small - + ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large - + ctl_stats.huge.allocated; - ctl_stats.active = - (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE) - + ctl_stats.huge.allocated; - ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk); + ctl_stats->allocated = ctl_sarena->astats->allocated_small + + atomic_load_zu(&ctl_sarena->astats->astats.allocated_large, + ATOMIC_RELAXED); + ctl_stats->active = (ctl_sarena->pactive << LG_PAGE); + ctl_stats->metadata = atomic_load_zu( + &ctl_sarena->astats->astats.base, ATOMIC_RELAXED) + + atomic_load_zu(&ctl_sarena->astats->astats.internal, + ATOMIC_RELAXED); + ctl_stats->resident = atomic_load_zu( + &ctl_sarena->astats->astats.resident, ATOMIC_RELAXED); + ctl_stats->mapped = atomic_load_zu( + &ctl_sarena->astats->astats.mapped, ATOMIC_RELAXED); + ctl_stats->retained = atomic_load_zu( + &ctl_sarena->astats->astats.retained, ATOMIC_RELAXED); + + ctl_background_thread_stats_read(tsdn); + +#define READ_GLOBAL_MUTEX_PROF_DATA(i, mtx) \ + malloc_mutex_lock(tsdn, &mtx); \ + malloc_mutex_prof_read(tsdn, &ctl_stats->mutex_prof_data[i], &mtx); \ + malloc_mutex_unlock(tsdn, &mtx); + + if (config_prof && opt_prof) { + READ_GLOBAL_MUTEX_PROF_DATA(global_prof_mutex_prof, + bt2gctx_mtx); + } + if (have_background_thread) { + READ_GLOBAL_MUTEX_PROF_DATA( + global_prof_mutex_background_thread, + background_thread_lock); + } else { + memset(&ctl_stats->mutex_prof_data[ + global_prof_mutex_background_thread], 0, + sizeof(mutex_prof_data_t)); + } + /* We own ctl mutex already. */ + malloc_mutex_prof_read(tsdn, + &ctl_stats->mutex_prof_data[global_prof_mutex_ctl], + &ctl_mtx); +#undef READ_GLOBAL_MUTEX_PROF_DATA } - - ctl_epoch++; + ctl_arenas->epoch++; } static bool -ctl_init(void) -{ +ctl_init(tsd_t *tsd) { bool ret; + tsdn_t *tsdn = tsd_tsdn(tsd); + + malloc_mutex_lock(tsdn, &ctl_mtx); + if (!ctl_initialized) { + ctl_arena_t *ctl_sarena, *ctl_darena; + unsigned i; - malloc_mutex_lock(&ctl_mtx); - if (ctl_initialized == false) { /* - * Allocate space for one extra arena stats element, which - * contains summed stats across all arenas. + * Allocate demand-zeroed space for pointers to the full + * range of supported arena indices. */ - assert(narenas_auto == narenas_total_get()); - ctl_stats.narenas = narenas_auto; - ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc( - (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t)); - if (ctl_stats.arenas == NULL) { + if (ctl_arenas == NULL) { + ctl_arenas = (ctl_arenas_t *)base_alloc(tsdn, + b0get(), sizeof(ctl_arenas_t), QUANTUM); + if (ctl_arenas == NULL) { + ret = true; + goto label_return; + } + } + + if (config_stats && ctl_stats == NULL) { + ctl_stats = (ctl_stats_t *)base_alloc(tsdn, b0get(), + sizeof(ctl_stats_t), QUANTUM); + if (ctl_stats == NULL) { + ret = true; + goto label_return; + } + } + + /* + * Allocate space for the current full range of arenas + * here rather than doing it lazily elsewhere, in order + * to limit when OOM-caused errors can occur. + */ + if ((ctl_sarena = arenas_i_impl(tsd, MALLCTL_ARENAS_ALL, false, + true)) == NULL) { ret = true; goto label_return; } - memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) * - sizeof(ctl_arena_stats_t)); + ctl_sarena->initialized = true; + if ((ctl_darena = arenas_i_impl(tsd, MALLCTL_ARENAS_DESTROYED, + false, true)) == NULL) { + ret = true; + goto label_return; + } + ctl_arena_clear(ctl_darena); /* - * Initialize all stats structures, regardless of whether they - * ever get used. Lazy initialization would allow errors to - * cause inconsistent state to be viewable by the application. + * Don't toggle ctl_darena to initialized until an arena is + * actually destroyed, so that arena.<i>.initialized can be used + * to query whether the stats are relevant. */ - if (config_stats) { - unsigned i; - for (i = 0; i <= ctl_stats.narenas; i++) { - if (ctl_arena_init(&ctl_stats.arenas[i])) { - ret = true; - goto label_return; - } + + ctl_arenas->narenas = narenas_total_get(); + for (i = 0; i < ctl_arenas->narenas; i++) { + if (arenas_i_impl(tsd, i, false, true) == NULL) { + ret = true; + goto label_return; } } - ctl_stats.arenas[ctl_stats.narenas].initialized = true; - ctl_epoch = 0; - ctl_refresh(); + ql_new(&ctl_arenas->destroyed); + ctl_refresh(tsdn); + ctl_initialized = true; } ret = false; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + malloc_mutex_unlock(tsdn, &ctl_mtx); + return ret; } static int -ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, - size_t *depthp) -{ +ctl_lookup(tsdn_t *tsdn, const char *name, ctl_node_t const **nodesp, + size_t *mibp, size_t *depthp) { int ret; const char *elm, *tdot, *dot; size_t elen, i, j; @@ -750,9 +1080,10 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, if (strlen(child->name) == elen && strncmp(elm, child->name, elen) == 0) { node = child; - if (nodesp != NULL) + if (nodesp != NULL) { nodesp[i] = (const ctl_node_t *)node; + } mibp[i] = j; break; } @@ -773,14 +1104,15 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, } inode = ctl_indexed_node(node->children); - node = inode->index(mibp, *depthp, (size_t)index); + node = inode->index(tsdn, mibp, *depthp, (size_t)index); if (node == NULL) { ret = ENOENT; goto label_return; } - if (nodesp != NULL) + if (nodesp != NULL) { nodesp[i] = (const ctl_node_t *)node; + } mibp[i] = (size_t)index; } @@ -813,33 +1145,33 @@ ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, ret = 0; label_return: - return (ret); + return ret; } int -ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp, - size_t newlen) -{ +ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) { int ret; size_t depth; ctl_node_t const *nodes[CTL_MAX_DEPTH]; size_t mib[CTL_MAX_DEPTH]; const ctl_named_node_t *node; - if (ctl_initialized == false && ctl_init()) { + if (!ctl_initialized && ctl_init(tsd)) { ret = EAGAIN; goto label_return; } depth = CTL_MAX_DEPTH; - ret = ctl_lookup(name, nodes, mib, &depth); - if (ret != 0) + ret = ctl_lookup(tsd_tsdn(tsd), name, nodes, mib, &depth); + if (ret != 0) { goto label_return; + } node = ctl_named_node(nodes[depth-1]); - if (node != NULL && node->ctl) - ret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen); - else { + if (node != NULL && node->ctl) { + ret = node->ctl(tsd, mib, depth, oldp, oldlenp, newp, newlen); + } else { /* The name refers to a partial path through the ctl tree. */ ret = ENOENT; } @@ -849,29 +1181,27 @@ label_return: } int -ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp) -{ +ctl_nametomib(tsd_t *tsd, const char *name, size_t *mibp, size_t *miblenp) { int ret; - if (ctl_initialized == false && ctl_init()) { + if (!ctl_initialized && ctl_init(tsd)) { ret = EAGAIN; goto label_return; } - ret = ctl_lookup(name, NULL, mibp, miblenp); + ret = ctl_lookup(tsd_tsdn(tsd), name, NULL, mibp, miblenp); label_return: return(ret); } int -ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; const ctl_named_node_t *node; size_t i; - if (ctl_initialized == false && ctl_init()) { + if (!ctl_initialized && ctl_init(tsd)) { ret = EAGAIN; goto label_return; } @@ -893,7 +1223,7 @@ ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, /* Indexed element. */ inode = ctl_indexed_node(node->children); - node = inode->index(mib, miblen, mib[i]); + node = inode->index(tsd_tsdn(tsd), mib, miblen, mib[i]); if (node == NULL) { ret = ENOENT; goto label_return; @@ -902,9 +1232,9 @@ ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, } /* Call the ctl function. */ - if (node && node->ctl) - ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen); - else { + if (node && node->ctl) { + ret = node->ctl(tsd, mib, miblen, oldp, oldlenp, newp, newlen); + } else { /* Partial MIB. */ ret = ENOENT; } @@ -914,56 +1244,58 @@ label_return: } bool -ctl_boot(void) -{ - - if (malloc_mutex_init(&ctl_mtx)) - return (true); +ctl_boot(void) { + if (malloc_mutex_init(&ctl_mtx, "ctl", WITNESS_RANK_CTL, + malloc_mutex_rank_exclusive)) { + return true; + } ctl_initialized = false; - return (false); + return false; } void -ctl_prefork(void) -{ - - malloc_mutex_prefork(&ctl_mtx); +ctl_prefork(tsdn_t *tsdn) { + malloc_mutex_prefork(tsdn, &ctl_mtx); } void -ctl_postfork_parent(void) -{ - - malloc_mutex_postfork_parent(&ctl_mtx); +ctl_postfork_parent(tsdn_t *tsdn) { + malloc_mutex_postfork_parent(tsdn, &ctl_mtx); } void -ctl_postfork_child(void) -{ - - malloc_mutex_postfork_child(&ctl_mtx); +ctl_postfork_child(tsdn_t *tsdn) { + malloc_mutex_postfork_child(tsdn, &ctl_mtx); } /******************************************************************************/ /* *_ctl() functions. */ -#define READONLY() do { \ +#define READONLY() do { \ if (newp != NULL || newlen != 0) { \ ret = EPERM; \ goto label_return; \ } \ } while (0) -#define WRITEONLY() do { \ +#define WRITEONLY() do { \ if (oldp != NULL || oldlenp != NULL) { \ ret = EPERM; \ goto label_return; \ } \ } while (0) -#define READ(v, t) do { \ +#define READ_XOR_WRITE() do { \ + if ((oldp != NULL && oldlenp != NULL) && (newp != NULL || \ + newlen != 0)) { \ + ret = EPERM; \ + goto label_return; \ + } \ +} while (0) + +#define READ(v, t) do { \ if (oldp != NULL && oldlenp != NULL) { \ if (*oldlenp != sizeof(t)) { \ size_t copylen = (sizeof(t) <= *oldlenp) \ @@ -971,12 +1303,12 @@ ctl_postfork_child(void) memcpy(oldp, (void *)&(v), copylen); \ ret = EINVAL; \ goto label_return; \ - } else \ - *(t *)oldp = (v); \ + } \ + *(t *)oldp = (v); \ } \ } while (0) -#define WRITE(v, t) do { \ +#define WRITE(v, t) do { \ if (newp != NULL) { \ if (newlen != sizeof(t)) { \ ret = EINVAL; \ @@ -986,101 +1318,109 @@ ctl_postfork_child(void) } \ } while (0) +#define MIB_UNSIGNED(v, i) do { \ + if (mib[i] > UINT_MAX) { \ + ret = EFAULT; \ + goto label_return; \ + } \ + v = (unsigned)mib[i]; \ +} while (0) + /* * There's a lot of code duplication in the following macros due to limitations * in how nested cpp macros are expanded. */ -#define CTL_RO_CLGEN(c, l, n, v, t) \ +#define CTL_RO_CLGEN(c, l, n, v, t) \ static int \ -n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ - void *newp, size_t newlen) \ -{ \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ - if ((c) == false) \ - return (ENOENT); \ - if (l) \ - malloc_mutex_lock(&ctl_mtx); \ + if (!(c)) { \ + return ENOENT; \ + } \ + if (l) { \ + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \ + } \ READONLY(); \ oldval = (v); \ READ(oldval, t); \ \ ret = 0; \ label_return: \ - if (l) \ - malloc_mutex_unlock(&ctl_mtx); \ - return (ret); \ + if (l) { \ + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \ + } \ + return ret; \ } -#define CTL_RO_CGEN(c, n, v, t) \ +#define CTL_RO_CGEN(c, n, v, t) \ static int \ -n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ - void *newp, size_t newlen) \ -{ \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ - if ((c) == false) \ - return (ENOENT); \ - malloc_mutex_lock(&ctl_mtx); \ + if (!(c)) { \ + return ENOENT; \ + } \ + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \ READONLY(); \ oldval = (v); \ READ(oldval, t); \ \ ret = 0; \ label_return: \ - malloc_mutex_unlock(&ctl_mtx); \ - return (ret); \ + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \ + return ret; \ } -#define CTL_RO_GEN(n, v, t) \ +#define CTL_RO_GEN(n, v, t) \ static int \ -n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ - void *newp, size_t newlen) \ -{ \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ - malloc_mutex_lock(&ctl_mtx); \ + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \ READONLY(); \ oldval = (v); \ READ(oldval, t); \ \ ret = 0; \ label_return: \ - malloc_mutex_unlock(&ctl_mtx); \ - return (ret); \ + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \ + return ret; \ } /* * ctl_mtx is not acquired, under the assumption that no pertinent data will * mutate during the call. */ -#define CTL_RO_NL_CGEN(c, n, v, t) \ +#define CTL_RO_NL_CGEN(c, n, v, t) \ static int \ -n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ - void *newp, size_t newlen) \ -{ \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ - if ((c) == false) \ - return (ENOENT); \ + if (!(c)) { \ + return ENOENT; \ + } \ READONLY(); \ oldval = (v); \ READ(oldval, t); \ \ ret = 0; \ label_return: \ - return (ret); \ + return ret; \ } -#define CTL_RO_NL_GEN(n, v, t) \ +#define CTL_RO_NL_GEN(n, v, t) \ static int \ -n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ - void *newp, size_t newlen) \ -{ \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ t oldval; \ \ @@ -1090,24 +1430,42 @@ n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ \ ret = 0; \ label_return: \ - return (ret); \ + return ret; \ } -#define CTL_RO_BOOL_CONFIG_GEN(n) \ +#define CTL_TSD_RO_NL_CGEN(c, n, m, t) \ static int \ -n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ - void *newp, size_t newlen) \ -{ \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ int ret; \ - bool oldval; \ + t oldval; \ + \ + if (!(c)) { \ + return ENOENT; \ + } \ + READONLY(); \ + oldval = (m(tsd)); \ + READ(oldval, t); \ + \ + ret = 0; \ +label_return: \ + return ret; \ +} + +#define CTL_RO_CONFIG_GEN(n, t) \ +static int \ +n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \ + size_t *oldlenp, void *newp, size_t newlen) { \ + int ret; \ + t oldval; \ \ READONLY(); \ oldval = n; \ - READ(oldval, bool); \ + READ(oldval, t); \ \ ret = 0; \ label_return: \ - return (ret); \ + return ret; \ } /******************************************************************************/ @@ -1115,62 +1473,122 @@ label_return: \ CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *) static int -epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; UNUSED uint64_t newval; - malloc_mutex_lock(&ctl_mtx); + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); WRITE(newval, uint64_t); - if (newp != NULL) - ctl_refresh(); - READ(ctl_epoch, uint64_t); + if (newp != NULL) { + ctl_refresh(tsd_tsdn(tsd)); + } + READ(ctl_arenas->epoch, uint64_t); ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; +} + +static int +background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + bool oldval; + + if (!have_background_thread) { + return ENOENT; + } + background_thread_ctl_init(tsd_tsdn(tsd)); + + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); + if (newp == NULL) { + oldval = background_thread_enabled(); + READ(oldval, bool); + } else { + if (newlen != sizeof(bool)) { + ret = EINVAL; + goto label_return; + } + oldval = background_thread_enabled(); + READ(oldval, bool); + + bool newval = *(bool *)newp; + if (newval == oldval) { + ret = 0; + goto label_return; + } + + background_thread_enabled_set(tsd_tsdn(tsd), newval); + if (newval) { + if (!can_enable_background_thread) { + malloc_printf("<jemalloc>: Error in dlsym(" + "RTLD_NEXT, \"pthread_create\"). Cannot " + "enable background_thread\n"); + ret = EFAULT; + goto label_return; + } + if (background_threads_enable(tsd)) { + ret = EFAULT; + goto label_return; + } + } else { + if (background_threads_disable(tsd)) { + ret = EFAULT; + goto label_return; + } + } + } + ret = 0; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + + return ret; } /******************************************************************************/ -CTL_RO_BOOL_CONFIG_GEN(config_debug) -CTL_RO_BOOL_CONFIG_GEN(config_dss) -CTL_RO_BOOL_CONFIG_GEN(config_fill) -CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock) -CTL_RO_BOOL_CONFIG_GEN(config_mremap) -CTL_RO_BOOL_CONFIG_GEN(config_munmap) -CTL_RO_BOOL_CONFIG_GEN(config_prof) -CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc) -CTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind) -CTL_RO_BOOL_CONFIG_GEN(config_stats) -CTL_RO_BOOL_CONFIG_GEN(config_tcache) -CTL_RO_BOOL_CONFIG_GEN(config_tls) -CTL_RO_BOOL_CONFIG_GEN(config_utrace) -CTL_RO_BOOL_CONFIG_GEN(config_valgrind) -CTL_RO_BOOL_CONFIG_GEN(config_xmalloc) +CTL_RO_CONFIG_GEN(config_cache_oblivious, bool) +CTL_RO_CONFIG_GEN(config_debug, bool) +CTL_RO_CONFIG_GEN(config_fill, bool) +CTL_RO_CONFIG_GEN(config_lazy_lock, bool) +CTL_RO_CONFIG_GEN(config_malloc_conf, const char *) +CTL_RO_CONFIG_GEN(config_prof, bool) +CTL_RO_CONFIG_GEN(config_prof_libgcc, bool) +CTL_RO_CONFIG_GEN(config_prof_libunwind, bool) +CTL_RO_CONFIG_GEN(config_stats, bool) +CTL_RO_CONFIG_GEN(config_thp, bool) +CTL_RO_CONFIG_GEN(config_utrace, bool) +CTL_RO_CONFIG_GEN(config_xmalloc, bool) /******************************************************************************/ CTL_RO_NL_GEN(opt_abort, opt_abort, bool) +CTL_RO_NL_GEN(opt_abort_conf, opt_abort_conf, bool) +CTL_RO_NL_GEN(opt_retain, opt_retain, bool) CTL_RO_NL_GEN(opt_dss, opt_dss, const char *) -CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t) -CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t) -CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t) +CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned) +CTL_RO_NL_GEN(opt_percpu_arena, percpu_arena_mode_names[opt_percpu_arena], + const char *) +CTL_RO_NL_GEN(opt_background_thread, opt_background_thread, bool) +CTL_RO_NL_GEN(opt_dirty_decay_ms, opt_dirty_decay_ms, ssize_t) +CTL_RO_NL_GEN(opt_muzzy_decay_ms, opt_muzzy_decay_ms, ssize_t) CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool) -CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool) -CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t) -CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool) +CTL_RO_NL_GEN(opt_stats_print_opts, opt_stats_print_opts, const char *) +CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *) CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool) CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool) -CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool) CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool) -CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool) -CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t) +CTL_RO_NL_GEN(opt_tcache, opt_tcache, bool) +CTL_RO_NL_GEN(opt_lg_tcache_max, opt_lg_tcache_max, ssize_t) CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *) -CTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */ +CTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) +CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init, + opt_prof_thread_active_init, bool) CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t) CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool) CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t) @@ -1181,504 +1599,1100 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool) /******************************************************************************/ static int -thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; + arena_t *oldarena; unsigned newind, oldind; - malloc_mutex_lock(&ctl_mtx); - newind = oldind = choose_arena(NULL)->ind; + oldarena = arena_choose(tsd, NULL); + if (oldarena == NULL) { + return EAGAIN; + } + newind = oldind = arena_ind_get(oldarena); WRITE(newind, unsigned); READ(oldind, unsigned); + if (newind != oldind) { - arena_t *arena; + arena_t *newarena; - if (newind >= ctl_stats.narenas) { + if (newind >= narenas_total_get()) { /* New arena index is out of range. */ ret = EFAULT; goto label_return; } + if (have_percpu_arena && + PERCPU_ARENA_ENABLED(opt_percpu_arena)) { + if (newind < percpu_arena_ind_limit(opt_percpu_arena)) { + /* + * If perCPU arena is enabled, thread_arena + * control is not allowed for the auto arena + * range. + */ + ret = EPERM; + goto label_return; + } + } + /* Initialize arena if necessary. */ - malloc_mutex_lock(&arenas_lock); - if ((arena = arenas[newind]) == NULL && (arena = - arenas_extend(newind)) == NULL) { - malloc_mutex_unlock(&arenas_lock); + newarena = arena_get(tsd_tsdn(tsd), newind, true); + if (newarena == NULL) { ret = EAGAIN; goto label_return; } - assert(arena == arenas[newind]); - arenas[oldind]->nthreads--; - arenas[newind]->nthreads++; - malloc_mutex_unlock(&arenas_lock); - - /* Set new arena association. */ - if (config_tcache) { - tcache_t *tcache; - if ((uintptr_t)(tcache = *tcache_tsd_get()) > - (uintptr_t)TCACHE_STATE_MAX) { - tcache_arena_dissociate(tcache); - tcache_arena_associate(tcache, arena); - } + /* Set new arena/tcache associations. */ + arena_migrate(tsd, oldind, newind); + if (tcache_available(tsd)) { + tcache_arena_reassociate(tsd_tsdn(tsd), + tsd_tcachep_get(tsd), newarena); } - arenas_tsd_set(&arena); } ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + return ret; } -CTL_RO_NL_CGEN(config_stats, thread_allocated, - thread_allocated_tsd_get()->allocated, uint64_t) -CTL_RO_NL_CGEN(config_stats, thread_allocatedp, - &thread_allocated_tsd_get()->allocated, uint64_t *) -CTL_RO_NL_CGEN(config_stats, thread_deallocated, - thread_allocated_tsd_get()->deallocated, uint64_t) -CTL_RO_NL_CGEN(config_stats, thread_deallocatedp, - &thread_allocated_tsd_get()->deallocated, uint64_t *) +CTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get, + uint64_t) +CTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get, + uint64_t *) +CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get, + uint64_t) +CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp, + tsd_thread_deallocatedp_get, uint64_t *) static int -thread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) -{ +thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; bool oldval; - if (config_tcache == false) - return (ENOENT); - - oldval = tcache_enabled_get(); + oldval = tcache_enabled_get(tsd); if (newp != NULL) { if (newlen != sizeof(bool)) { ret = EINVAL; goto label_return; } - tcache_enabled_set(*(bool *)newp); + tcache_enabled_set(tsd, *(bool *)newp); } READ(oldval, bool); ret = 0; label_return: - return (ret); + return ret; +} + +static int +thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + + if (!tcache_available(tsd)) { + ret = EFAULT; + goto label_return; + } + + READONLY(); + WRITEONLY(); + + tcache_flush(tsd); + + ret = 0; +label_return: + return ret; +} + +static int +thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + + if (!config_prof) { + return ENOENT; + } + + READ_XOR_WRITE(); + + if (newp != NULL) { + if (newlen != sizeof(const char *)) { + ret = EINVAL; + goto label_return; + } + + if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) != + 0) { + goto label_return; + } + } else { + const char *oldname = prof_thread_name_get(tsd); + READ(oldname, const char *); + } + + ret = 0; +label_return: + return ret; } static int -thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) -{ +thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; + bool oldval; - if (config_tcache == false) - return (ENOENT); + if (!config_prof) { + return ENOENT; + } + + oldval = prof_thread_active_get(tsd); + if (newp != NULL) { + if (newlen != sizeof(bool)) { + ret = EINVAL; + goto label_return; + } + if (prof_thread_active_set(tsd, *(bool *)newp)) { + ret = EAGAIN; + goto label_return; + } + } + READ(oldval, bool); + + ret = 0; +label_return: + return ret; +} + +/******************************************************************************/ + +static int +tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned tcache_ind; READONLY(); + if (tcaches_create(tsd, &tcache_ind)) { + ret = EFAULT; + goto label_return; + } + READ(tcache_ind, unsigned); + + ret = 0; +label_return: + return ret; +} + +static int +tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned tcache_ind; + WRITEONLY(); + tcache_ind = UINT_MAX; + WRITE(tcache_ind, unsigned); + if (tcache_ind == UINT_MAX) { + ret = EFAULT; + goto label_return; + } + tcaches_flush(tsd, tcache_ind); + + ret = 0; +label_return: + return ret; +} + +static int +tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned tcache_ind; - tcache_flush(); + WRITEONLY(); + tcache_ind = UINT_MAX; + WRITE(tcache_ind, unsigned); + if (tcache_ind == UINT_MAX) { + ret = EFAULT; + goto label_return; + } + tcaches_destroy(tsd, tcache_ind); ret = 0; label_return: - return (ret); + return ret; } /******************************************************************************/ -/* ctl_mutex must be held during execution of this function. */ +static int +arena_i_initialized_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + tsdn_t *tsdn = tsd_tsdn(tsd); + unsigned arena_ind; + bool initialized; + + READONLY(); + MIB_UNSIGNED(arena_ind, 1); + + malloc_mutex_lock(tsdn, &ctl_mtx); + initialized = arenas_i(arena_ind)->initialized; + malloc_mutex_unlock(tsdn, &ctl_mtx); + + READ(initialized, bool); + + ret = 0; +label_return: + return ret; +} + static void -arena_purge(unsigned arena_ind) -{ - VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); +arena_i_decay(tsdn_t *tsdn, unsigned arena_ind, bool all) { + malloc_mutex_lock(tsdn, &ctl_mtx); + { + unsigned narenas = ctl_arenas->narenas; - malloc_mutex_lock(&arenas_lock); - memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); - malloc_mutex_unlock(&arenas_lock); + /* + * Access via index narenas is deprecated, and scheduled for + * removal in 6.0.0. + */ + if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind == narenas) { + unsigned i; + VARIABLE_ARRAY(arena_t *, tarenas, narenas); - if (arena_ind == ctl_stats.narenas) { - unsigned i; - for (i = 0; i < ctl_stats.narenas; i++) { - if (tarenas[i] != NULL) - arena_purge_all(tarenas[i]); + for (i = 0; i < narenas; i++) { + tarenas[i] = arena_get(tsdn, i, false); + } + + /* + * No further need to hold ctl_mtx, since narenas and + * tarenas contain everything needed below. + */ + malloc_mutex_unlock(tsdn, &ctl_mtx); + + for (i = 0; i < narenas; i++) { + if (tarenas[i] != NULL) { + arena_decay(tsdn, tarenas[i], false, + all); + } + } + } else { + arena_t *tarena; + + assert(arena_ind < narenas); + + tarena = arena_get(tsdn, arena_ind, false); + + /* No further need to hold ctl_mtx. */ + malloc_mutex_unlock(tsdn, &ctl_mtx); + + if (tarena != NULL) { + arena_decay(tsdn, tarena, false, all); + } } - } else { - assert(arena_ind < ctl_stats.narenas); - if (tarenas[arena_ind] != NULL) - arena_purge_all(tarenas[arena_ind]); } } static int -arena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +arena_i_decay_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; + unsigned arena_ind; READONLY(); WRITEONLY(); - malloc_mutex_lock(&ctl_mtx); - arena_purge(mib[1]); - malloc_mutex_unlock(&ctl_mtx); + MIB_UNSIGNED(arena_ind, 1); + arena_i_decay(tsd_tsdn(tsd), arena_ind, false); ret = 0; label_return: - return (ret); + return ret; } static int -arena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ - int ret, i; - bool match, err; - const char *dss; - unsigned arena_ind = mib[1]; +arena_i_purge_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned arena_ind; + + READONLY(); + WRITEONLY(); + MIB_UNSIGNED(arena_ind, 1); + arena_i_decay(tsd_tsdn(tsd), arena_ind, true); + + ret = 0; +label_return: + return ret; +} + +static int +arena_i_reset_destroy_helper(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen, unsigned *arena_ind, + arena_t **arena) { + int ret; + + READONLY(); + WRITEONLY(); + MIB_UNSIGNED(*arena_ind, 1); + + *arena = arena_get(tsd_tsdn(tsd), *arena_ind, false); + if (*arena == NULL || arena_is_auto(*arena)) { + ret = EFAULT; + goto label_return; + } + + ret = 0; +label_return: + return ret; +} + +static void +arena_reset_prepare_background_thread(tsd_t *tsd, unsigned arena_ind) { + /* Temporarily disable the background thread during arena reset. */ + if (have_background_thread) { + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); + if (background_thread_enabled()) { + unsigned ind = arena_ind % ncpus; + background_thread_info_t *info = + &background_thread_info[ind]; + assert(info->state == background_thread_started); + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + info->state = background_thread_paused; + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + } + } +} + +static void +arena_reset_finish_background_thread(tsd_t *tsd, unsigned arena_ind) { + if (have_background_thread) { + if (background_thread_enabled()) { + unsigned ind = arena_ind % ncpus; + background_thread_info_t *info = + &background_thread_info[ind]; + assert(info->state == background_thread_paused); + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + info->state = background_thread_started; + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + } + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + } +} + +static int +arena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned arena_ind; + arena_t *arena; + + ret = arena_i_reset_destroy_helper(tsd, mib, miblen, oldp, oldlenp, + newp, newlen, &arena_ind, &arena); + if (ret != 0) { + return ret; + } + + arena_reset_prepare_background_thread(tsd, arena_ind); + arena_reset(tsd, arena); + arena_reset_finish_background_thread(tsd, arena_ind); + + return ret; +} + +static int +arena_i_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned arena_ind; + arena_t *arena; + ctl_arena_t *ctl_darena, *ctl_arena; + + ret = arena_i_reset_destroy_helper(tsd, mib, miblen, oldp, oldlenp, + newp, newlen, &arena_ind, &arena); + if (ret != 0) { + goto label_return; + } + + if (arena_nthreads_get(arena, false) != 0 || arena_nthreads_get(arena, + true) != 0) { + ret = EFAULT; + goto label_return; + } + + arena_reset_prepare_background_thread(tsd, arena_ind); + /* Merge stats after resetting and purging arena. */ + arena_reset(tsd, arena); + arena_decay(tsd_tsdn(tsd), arena, false, true); + ctl_darena = arenas_i(MALLCTL_ARENAS_DESTROYED); + ctl_darena->initialized = true; + ctl_arena_refresh(tsd_tsdn(tsd), arena, ctl_darena, arena_ind, true); + /* Destroy arena. */ + arena_destroy(tsd, arena); + ctl_arena = arenas_i(arena_ind); + ctl_arena->initialized = false; + /* Record arena index for later recycling via arenas.create. */ + ql_elm_new(ctl_arena, destroyed_link); + ql_tail_insert(&ctl_arenas->destroyed, ctl_arena, destroyed_link); + arena_reset_finish_background_thread(tsd, arena_ind); + + assert(ret == 0); +label_return: + return ret; +} + +static int +arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + const char *dss = NULL; + unsigned arena_ind; dss_prec_t dss_prec_old = dss_prec_limit; dss_prec_t dss_prec = dss_prec_limit; - malloc_mutex_lock(&ctl_mtx); + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); WRITE(dss, const char *); - match = false; - for (i = 0; i < dss_prec_limit; i++) { - if (strcmp(dss_prec_names[i], dss) == 0) { - dss_prec = i; - match = true; - break; + MIB_UNSIGNED(arena_ind, 1); + if (dss != NULL) { + int i; + bool match = false; + + for (i = 0; i < dss_prec_limit; i++) { + if (strcmp(dss_prec_names[i], dss) == 0) { + dss_prec = i; + match = true; + break; + } + } + + if (!match) { + ret = EINVAL; + goto label_return; } - } - if (match == false) { - ret = EINVAL; - goto label_return; } - if (arena_ind < ctl_stats.narenas) { - arena_t *arena = arenas[arena_ind]; - if (arena != NULL) { - dss_prec_old = arena_dss_prec_get(arena); - arena_dss_prec_set(arena, dss_prec); - err = false; - } else - err = true; + /* + * Access via index narenas is deprecated, and scheduled for removal in + * 6.0.0. + */ + if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind == + ctl_arenas->narenas) { + if (dss_prec != dss_prec_limit && + extent_dss_prec_set(dss_prec)) { + ret = EFAULT; + goto label_return; + } + dss_prec_old = extent_dss_prec_get(); } else { - dss_prec_old = chunk_dss_prec_get(); - err = chunk_dss_prec_set(dss_prec); + arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false); + if (arena == NULL || (dss_prec != dss_prec_limit && + arena_dss_prec_set(arena, dss_prec))) { + ret = EFAULT; + goto label_return; + } + dss_prec_old = arena_dss_prec_get(arena); } + dss = dss_prec_names[dss_prec_old]; READ(dss, const char *); - if (err) { + + ret = 0; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; +} + +static int +arena_i_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) { + int ret; + unsigned arena_ind; + arena_t *arena; + + MIB_UNSIGNED(arena_ind, 1); + arena = arena_get(tsd_tsdn(tsd), arena_ind, false); + if (arena == NULL) { ret = EFAULT; goto label_return; } + if (oldp != NULL && oldlenp != NULL) { + size_t oldval = dirty ? arena_dirty_decay_ms_get(arena) : + arena_muzzy_decay_ms_get(arena); + READ(oldval, ssize_t); + } + if (newp != NULL) { + if (newlen != sizeof(ssize_t)) { + ret = EINVAL; + goto label_return; + } + if (dirty ? arena_dirty_decay_ms_set(tsd_tsdn(tsd), arena, + *(ssize_t *)newp) : arena_muzzy_decay_ms_set(tsd_tsdn(tsd), + arena, *(ssize_t *)newp)) { + ret = EFAULT; + goto label_return; + } + } + ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + return ret; } -static const ctl_named_node_t * -arena_i_index(const size_t *mib, size_t miblen, size_t i) -{ - const ctl_named_node_t * ret; +static int +arena_i_dirty_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + return arena_i_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp, + newlen, true); +} - malloc_mutex_lock(&ctl_mtx); - if (i > ctl_stats.narenas) { - ret = NULL; +static int +arena_i_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + return arena_i_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp, + newlen, false); +} + +static int +arena_i_extent_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + int ret; + unsigned arena_ind; + arena_t *arena; + + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + MIB_UNSIGNED(arena_ind, 1); + if (arena_ind < narenas_total_get() && (arena = + arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) { + if (newp != NULL) { + extent_hooks_t *old_extent_hooks; + extent_hooks_t *new_extent_hooks + JEMALLOC_CC_SILENCE_INIT(NULL); + WRITE(new_extent_hooks, extent_hooks_t *); + old_extent_hooks = extent_hooks_set(tsd, arena, + new_extent_hooks); + READ(old_extent_hooks, extent_hooks_t *); + } else { + extent_hooks_t *old_extent_hooks = + extent_hooks_get(arena); + READ(old_extent_hooks, extent_hooks_t *); + } + } else { + ret = EFAULT; goto label_return; } + ret = 0; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; +} + +static const ctl_named_node_t * +arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { + const ctl_named_node_t *ret; + + malloc_mutex_lock(tsdn, &ctl_mtx); + switch (i) { + case MALLCTL_ARENAS_ALL: + case MALLCTL_ARENAS_DESTROYED: + break; + default: + if (i > ctl_arenas->narenas) { + ret = NULL; + goto label_return; + } + break; + } ret = super_arena_i_node; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + malloc_mutex_unlock(tsdn, &ctl_mtx); + return ret; } /******************************************************************************/ static int -arenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) -{ +arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; unsigned narenas; - malloc_mutex_lock(&ctl_mtx); + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); READONLY(); if (*oldlenp != sizeof(unsigned)) { ret = EINVAL; goto label_return; } - narenas = ctl_stats.narenas; + narenas = ctl_arenas->narenas; READ(narenas, unsigned); ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; } static int -arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp, - size_t *oldlenp, void *newp, size_t newlen) -{ +arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) { int ret; - unsigned nread, i; - malloc_mutex_lock(&ctl_mtx); - READONLY(); - if (*oldlenp != ctl_stats.narenas * sizeof(bool)) { - ret = EINVAL; - nread = (*oldlenp < ctl_stats.narenas * sizeof(bool)) - ? (*oldlenp / sizeof(bool)) : ctl_stats.narenas; - } else { - ret = 0; - nread = ctl_stats.narenas; + if (oldp != NULL && oldlenp != NULL) { + size_t oldval = (dirty ? arena_dirty_decay_ms_default_get() : + arena_muzzy_decay_ms_default_get()); + READ(oldval, ssize_t); + } + if (newp != NULL) { + if (newlen != sizeof(ssize_t)) { + ret = EINVAL; + goto label_return; + } + if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp) + : arena_muzzy_decay_ms_default_set(*(ssize_t *)newp)) { + ret = EFAULT; + goto label_return; + } } - for (i = 0; i < nread; i++) - ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized; - + ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + return ret; +} + +static int +arenas_dirty_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + return arenas_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp, + newlen, true); +} + +static int +arenas_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + return arenas_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp, + newlen, false); } CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t) CTL_RO_NL_GEN(arenas_page, PAGE, size_t) -CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t) +CTL_RO_NL_GEN(arenas_tcache_max, tcache_maxclass, size_t) CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned) -CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned) +CTL_RO_NL_GEN(arenas_nhbins, nhbins, unsigned) CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t) CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t) -CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t) +CTL_RO_NL_GEN(arenas_bin_i_slab_size, arena_bin_info[mib[2]].slab_size, size_t) static const ctl_named_node_t * -arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i) -{ - - if (i > NBINS) - return (NULL); - return (super_arenas_bin_i_node); +arenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { + if (i > NBINS) { + return NULL; + } + return super_arenas_bin_i_node; } -CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t) -CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t) +CTL_RO_NL_GEN(arenas_nlextents, NSIZES - NBINS, unsigned) +CTL_RO_NL_GEN(arenas_lextent_i_size, sz_index2size(NBINS+(szind_t)mib[2]), + size_t) static const ctl_named_node_t * -arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i) -{ - - if (i > nlclasses) - return (NULL); - return (super_arenas_lrun_i_node); +arenas_lextent_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, + size_t i) { + if (i > NSIZES - NBINS) { + return NULL; + } + return super_arenas_lextent_i_node; } static int -arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; + extent_hooks_t *extent_hooks; unsigned arena_ind; - malloc_mutex_lock(&ctl_mtx); - WRITEONLY(); - arena_ind = UINT_MAX; - WRITE(arena_ind, unsigned); - if (newp != NULL && arena_ind >= ctl_stats.narenas) - ret = EFAULT; - else { - if (arena_ind == UINT_MAX) - arena_ind = ctl_stats.narenas; - arena_purge(arena_ind); - ret = 0; + malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); + + extent_hooks = (extent_hooks_t *)&extent_hooks_default; + WRITE(extent_hooks, extent_hooks_t *); + if ((arena_ind = ctl_arena_init(tsd, extent_hooks)) == UINT_MAX) { + ret = EAGAIN; + goto label_return; } + READ(arena_ind, unsigned); + ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); + return ret; } +/******************************************************************************/ + static int -arenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { int ret; - unsigned narenas; + bool oldval; - malloc_mutex_lock(&ctl_mtx); - READONLY(); - if (ctl_grow()) { - ret = EAGAIN; - goto label_return; + if (!config_prof) { + return ENOENT; } - narenas = ctl_stats.narenas - 1; - READ(narenas, unsigned); + + if (newp != NULL) { + if (newlen != sizeof(bool)) { + ret = EINVAL; + goto label_return; + } + oldval = prof_thread_active_init_set(tsd_tsdn(tsd), + *(bool *)newp); + } else { + oldval = prof_thread_active_init_get(tsd_tsdn(tsd)); + } + READ(oldval, bool); ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + return ret; } -/******************************************************************************/ - static int -prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; bool oldval; - if (config_prof == false) - return (ENOENT); + if (!config_prof) { + return ENOENT; + } - malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */ - oldval = opt_prof_active; if (newp != NULL) { - /* - * The memory barriers will tend to make opt_prof_active - * propagate faster on systems with weak memory ordering. - */ - mb_write(); - WRITE(opt_prof_active, bool); - mb_write(); + if (newlen != sizeof(bool)) { + ret = EINVAL; + goto label_return; + } + oldval = prof_active_set(tsd_tsdn(tsd), *(bool *)newp); + } else { + oldval = prof_active_get(tsd_tsdn(tsd)); } READ(oldval, bool); ret = 0; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + return ret; } static int -prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ +prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { int ret; const char *filename = NULL; - if (config_prof == false) - return (ENOENT); + if (!config_prof) { + return ENOENT; + } WRITEONLY(); WRITE(filename, const char *); - if (prof_mdump(filename)) { + if (prof_mdump(tsd, filename)) { ret = EFAULT; goto label_return; } ret = 0; label_return: - return (ret); + return ret; +} + +static int +prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + bool oldval; + + if (!config_prof) { + return ENOENT; + } + + if (newp != NULL) { + if (newlen != sizeof(bool)) { + ret = EINVAL; + goto label_return; + } + oldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp); + } else { + oldval = prof_gdump_get(tsd_tsdn(tsd)); + } + READ(oldval, bool); + + ret = 0; +label_return: + return ret; +} + +static int +prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, + size_t *oldlenp, void *newp, size_t newlen) { + int ret; + size_t lg_sample = lg_prof_sample; + + if (!config_prof) { + return ENOENT; + } + + WRITEONLY(); + WRITE(lg_sample, size_t); + if (lg_sample >= (sizeof(uint64_t) << 3)) { + lg_sample = (sizeof(uint64_t) << 3) - 1; + } + + prof_reset(tsd, lg_sample); + + ret = 0; +label_return: + return ret; } CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t) +CTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t) /******************************************************************************/ -CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *) -CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t) -CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t) -CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t) +CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats->allocated, size_t) +CTL_RO_CGEN(config_stats, stats_active, ctl_stats->active, size_t) +CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats->metadata, size_t) +CTL_RO_CGEN(config_stats, stats_resident, ctl_stats->resident, size_t) +CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats->mapped, size_t) +CTL_RO_CGEN(config_stats, stats_retained, ctl_stats->retained, size_t) + +CTL_RO_CGEN(config_stats, stats_background_thread_num_threads, + ctl_stats->background_thread.num_threads, size_t) +CTL_RO_CGEN(config_stats, stats_background_thread_num_runs, + ctl_stats->background_thread.num_runs, uint64_t) +CTL_RO_CGEN(config_stats, stats_background_thread_run_interval, + nstime_ns(&ctl_stats->background_thread.run_interval), uint64_t) + +CTL_RO_GEN(stats_arenas_i_dss, arenas_i(mib[2])->dss, const char *) +CTL_RO_GEN(stats_arenas_i_dirty_decay_ms, arenas_i(mib[2])->dirty_decay_ms, + ssize_t) +CTL_RO_GEN(stats_arenas_i_muzzy_decay_ms, arenas_i(mib[2])->muzzy_decay_ms, + ssize_t) +CTL_RO_GEN(stats_arenas_i_nthreads, arenas_i(mib[2])->nthreads, unsigned) +CTL_RO_GEN(stats_arenas_i_uptime, + nstime_ns(&arenas_i(mib[2])->astats->astats.uptime), uint64_t) +CTL_RO_GEN(stats_arenas_i_pactive, arenas_i(mib[2])->pactive, size_t) +CTL_RO_GEN(stats_arenas_i_pdirty, arenas_i(mib[2])->pdirty, size_t) +CTL_RO_GEN(stats_arenas_i_pmuzzy, arenas_i(mib[2])->pmuzzy, size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_mapped, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.mapped, ATOMIC_RELAXED), + size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_retained, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.retained, ATOMIC_RELAXED), + size_t) -CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current, +CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_npurge, + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_dirty.npurge), + uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_nmadvise, + arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.decay_dirty.nmadvise), uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_purged, + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_dirty.purged), + uint64_t) + +CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_npurge, + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_muzzy.npurge), + uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_nmadvise, + arena_stats_read_u64( + &arenas_i(mib[2])->astats->astats.decay_muzzy.nmadvise), uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_purged, + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.decay_muzzy.purged), + uint64_t) + +CTL_RO_CGEN(config_stats, stats_arenas_i_base, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.base, ATOMIC_RELAXED), + size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_internal, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.internal, ATOMIC_RELAXED), + size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_tcache_bytes, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.tcache_bytes, + ATOMIC_RELAXED), size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_resident, + atomic_load_zu(&arenas_i(mib[2])->astats->astats.resident, ATOMIC_RELAXED), size_t) -CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t) -CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t) -CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t) -CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t) -CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t) - -CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *) -CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned) -CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t) -CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_mapped, - ctl_stats.arenas[mib[2]].astats.mapped, size_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_npurge, - ctl_stats.arenas[mib[2]].astats.npurge, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise, - ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_purged, - ctl_stats.arenas[mib[2]].astats.purged, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated, - ctl_stats.arenas[mib[2]].allocated_small, size_t) + arenas_i(mib[2])->astats->allocated_small, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc, - ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t) + arenas_i(mib[2])->astats->nmalloc_small, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc, - ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t) + arenas_i(mib[2])->astats->ndalloc_small, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests, - ctl_stats.arenas[mib[2]].nrequests_small, uint64_t) + arenas_i(mib[2])->astats->nrequests_small, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated, - ctl_stats.arenas[mib[2]].astats.allocated_large, size_t) + atomic_load_zu(&arenas_i(mib[2])->astats->astats.allocated_large, + ATOMIC_RELAXED), size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc, - ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t) + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.nmalloc_large), + uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc, - ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t) + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.ndalloc_large), + uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests, - ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t) + arena_stats_read_u64(&arenas_i(mib[2])->astats->astats.nmalloc_large), + uint64_t) /* Intentional. */ + +/* Lock profiling related APIs below. */ +#define RO_MUTEX_CTL_GEN(n, l) \ +CTL_RO_CGEN(config_stats, stats_##n##_num_ops, \ + l.n_lock_ops, uint64_t) \ +CTL_RO_CGEN(config_stats, stats_##n##_num_wait, \ + l.n_wait_times, uint64_t) \ +CTL_RO_CGEN(config_stats, stats_##n##_num_spin_acq, \ + l.n_spin_acquired, uint64_t) \ +CTL_RO_CGEN(config_stats, stats_##n##_num_owner_switch, \ + l.n_owner_switches, uint64_t) \ +CTL_RO_CGEN(config_stats, stats_##n##_total_wait_time, \ + nstime_ns(&l.tot_wait_time), uint64_t) \ +CTL_RO_CGEN(config_stats, stats_##n##_max_wait_time, \ + nstime_ns(&l.max_wait_time), uint64_t) \ +CTL_RO_CGEN(config_stats, stats_##n##_max_num_thds, \ + l.max_n_thds, uint32_t) + +/* Global mutexes. */ +#define OP(mtx) \ + RO_MUTEX_CTL_GEN(mutexes_##mtx, \ + ctl_stats->mutex_prof_data[global_prof_mutex_##mtx]) +MUTEX_PROF_GLOBAL_MUTEXES +#undef OP + +/* Per arena mutexes */ +#define OP(mtx) RO_MUTEX_CTL_GEN(arenas_i_mutexes_##mtx, \ + arenas_i(mib[2])->astats->astats.mutex_prof_data[arena_prof_mutex_##mtx]) +MUTEX_PROF_ARENA_MUTEXES +#undef OP + +/* tcache bin mutex */ +RO_MUTEX_CTL_GEN(arenas_i_bins_j_mutex, + arenas_i(mib[2])->astats->bstats[mib[4]].mutex_data) +#undef RO_MUTEX_CTL_GEN + +/* Resets all mutex stats, including global, arena and bin mutexes. */ +static int +stats_mutexes_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, + void *oldp, size_t *oldlenp, void *newp, size_t newlen) { + if (!config_stats) { + return ENOENT; + } + + tsdn_t *tsdn = tsd_tsdn(tsd); + +#define MUTEX_PROF_RESET(mtx) \ + malloc_mutex_lock(tsdn, &mtx); \ + malloc_mutex_prof_data_reset(tsdn, &mtx); \ + malloc_mutex_unlock(tsdn, &mtx); + + /* Global mutexes: ctl and prof. */ + MUTEX_PROF_RESET(ctl_mtx); + if (have_background_thread) { + MUTEX_PROF_RESET(background_thread_lock); + } + if (config_prof && opt_prof) { + MUTEX_PROF_RESET(bt2gctx_mtx); + } + + + /* Per arena mutexes. */ + unsigned n = narenas_total_get(); + + for (unsigned i = 0; i < n; i++) { + arena_t *arena = arena_get(tsdn, i, false); + if (!arena) { + continue; + } + MUTEX_PROF_RESET(arena->large_mtx); + MUTEX_PROF_RESET(arena->extent_avail_mtx); + MUTEX_PROF_RESET(arena->extents_dirty.mtx); + MUTEX_PROF_RESET(arena->extents_muzzy.mtx); + MUTEX_PROF_RESET(arena->extents_retained.mtx); + MUTEX_PROF_RESET(arena->decay_dirty.mtx); + MUTEX_PROF_RESET(arena->decay_muzzy.mtx); + MUTEX_PROF_RESET(arena->tcache_ql_mtx); + MUTEX_PROF_RESET(arena->base->mtx); + + for (szind_t i = 0; i < NBINS; i++) { + arena_bin_t *bin = &arena->bins[i]; + MUTEX_PROF_RESET(bin->lock); + } + } +#undef MUTEX_PROF_RESET + return 0; +} -CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated, - ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t) + arenas_i(mib[2])->astats->bstats[mib[4]].nmalloc, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc, - ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t) + arenas_i(mib[2])->astats->bstats[mib[4]].ndalloc, uint64_t) CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t) -CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t) -CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns, - ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t) + arenas_i(mib[2])->astats->bstats[mib[4]].nrequests, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs, + arenas_i(mib[2])->astats->bstats[mib[4]].curregs, size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nfills, + arenas_i(mib[2])->astats->bstats[mib[4]].nfills, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nflushes, + arenas_i(mib[2])->astats->bstats[mib[4]].nflushes, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nslabs, + arenas_i(mib[2])->astats->bstats[mib[4]].nslabs, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreslabs, + arenas_i(mib[2])->astats->bstats[mib[4]].reslabs, uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curslabs, + arenas_i(mib[2])->astats->bstats[mib[4]].curslabs, size_t) static const ctl_named_node_t * -stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j) -{ - - if (j > NBINS) - return (NULL); - return (super_stats_arenas_i_bins_j_node); +stats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, + size_t j) { + if (j > NBINS) { + return NULL; + } + return super_stats_arenas_i_bins_j_node; } -CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc, - ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc, - ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests, - ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t) -CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns, - ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_nmalloc, + arena_stats_read_u64(&arenas_i(mib[2])->astats->lstats[mib[4]].nmalloc), + uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_ndalloc, + arena_stats_read_u64(&arenas_i(mib[2])->astats->lstats[mib[4]].ndalloc), + uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_nrequests, + arena_stats_read_u64(&arenas_i(mib[2])->astats->lstats[mib[4]].nrequests), + uint64_t) +CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_curlextents, + arenas_i(mib[2])->astats->lstats[mib[4]].curlextents, size_t) static const ctl_named_node_t * -stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j) -{ - - if (j > nlclasses) - return (NULL); - return (super_stats_arenas_i_lruns_j_node); +stats_arenas_i_lextents_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, + size_t j) { + if (j > NSIZES - NBINS) { + return NULL; + } + return super_stats_arenas_i_lextents_j_node; } static const ctl_named_node_t * -stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i) -{ - const ctl_named_node_t * ret; +stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i) { + const ctl_named_node_t *ret; + size_t a; - malloc_mutex_lock(&ctl_mtx); - if (i > ctl_stats.narenas || ctl_stats.arenas[i].initialized == false) { + malloc_mutex_lock(tsdn, &ctl_mtx); + a = arenas_i2a_impl(i, true, true); + if (a == UINT_MAX || !ctl_arenas->arenas[a]->initialized) { ret = NULL; goto label_return; } ret = super_stats_arenas_i_node; label_return: - malloc_mutex_unlock(&ctl_mtx); - return (ret); + malloc_mutex_unlock(tsdn, &ctl_mtx); + return ret; } diff --git a/deps/jemalloc/src/extent.c b/deps/jemalloc/src/extent.c index 8c09b486ed..fa45c84d34 100644 --- a/deps/jemalloc/src/extent.c +++ b/deps/jemalloc/src/extent.c @@ -1,39 +1,1987 @@ -#define JEMALLOC_EXTENT_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_EXTENT_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/ph.h" +#include "jemalloc/internal/rtree.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/mutex_pool.h" + +/******************************************************************************/ +/* Data. */ + +rtree_t extents_rtree; +/* Keyed by the address of the extent_t being protected. */ +mutex_pool_t extent_mutex_pool; + +static const bitmap_info_t extents_bitmap_info = + BITMAP_INFO_INITIALIZER(NPSIZES+1); + +static void *extent_alloc_default(extent_hooks_t *extent_hooks, void *new_addr, + size_t size, size_t alignment, bool *zero, bool *commit, + unsigned arena_ind); +static bool extent_dalloc_default(extent_hooks_t *extent_hooks, void *addr, + size_t size, bool committed, unsigned arena_ind); +static void extent_destroy_default(extent_hooks_t *extent_hooks, void *addr, + size_t size, bool committed, unsigned arena_ind); +static bool extent_commit_default(extent_hooks_t *extent_hooks, void *addr, + size_t size, size_t offset, size_t length, unsigned arena_ind); +static bool extent_commit_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length, bool growing_retained); +static bool extent_decommit_default(extent_hooks_t *extent_hooks, + void *addr, size_t size, size_t offset, size_t length, unsigned arena_ind); +#ifdef PAGES_CAN_PURGE_LAZY +static bool extent_purge_lazy_default(extent_hooks_t *extent_hooks, void *addr, + size_t size, size_t offset, size_t length, unsigned arena_ind); +#endif +static bool extent_purge_lazy_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length, bool growing_retained); +#ifdef PAGES_CAN_PURGE_FORCED +static bool extent_purge_forced_default(extent_hooks_t *extent_hooks, + void *addr, size_t size, size_t offset, size_t length, unsigned arena_ind); +#endif +static bool extent_purge_forced_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length, bool growing_retained); +#ifdef JEMALLOC_MAPS_COALESCE +static bool extent_split_default(extent_hooks_t *extent_hooks, void *addr, + size_t size, size_t size_a, size_t size_b, bool committed, + unsigned arena_ind); +#endif +static extent_t *extent_split_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t size_a, + szind_t szind_a, bool slab_a, size_t size_b, szind_t szind_b, bool slab_b, + bool growing_retained); +#ifdef JEMALLOC_MAPS_COALESCE +static bool extent_merge_default(extent_hooks_t *extent_hooks, void *addr_a, + size_t size_a, void *addr_b, size_t size_b, bool committed, + unsigned arena_ind); +#endif +static bool extent_merge_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *a, extent_t *b, + bool growing_retained); + +const extent_hooks_t extent_hooks_default = { + extent_alloc_default, + extent_dalloc_default, + extent_destroy_default, + extent_commit_default, + extent_decommit_default +#ifdef PAGES_CAN_PURGE_LAZY + , + extent_purge_lazy_default +#else + , + NULL +#endif +#ifdef PAGES_CAN_PURGE_FORCED + , + extent_purge_forced_default +#else + , + NULL +#endif +#ifdef JEMALLOC_MAPS_COALESCE + , + extent_split_default, + extent_merge_default +#endif +}; + +/* Used exclusively for gdump triggering. */ +static atomic_zu_t curpages; +static atomic_zu_t highpages; + +/******************************************************************************/ +/* + * Function prototypes for static functions that are referenced prior to + * definition. + */ + +static void extent_deregister(tsdn_t *tsdn, extent_t *extent); +static extent_t *extent_recycle(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extents_t *extents, void *new_addr, + size_t usize, size_t pad, size_t alignment, bool slab, szind_t szind, + bool *zero, bool *commit, bool growing_retained); +static extent_t *extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + extent_t *extent, bool *coalesced, bool growing_retained); +static void extent_record(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extents_t *extents, extent_t *extent, + bool growing_retained); /******************************************************************************/ -static inline int -extent_szad_comp(extent_node_t *a, extent_node_t *b) -{ - int ret; - size_t a_size = a->size; - size_t b_size = b->size; +rb_gen(UNUSED, extent_avail_, extent_tree_t, extent_t, rb_link, + extent_esnead_comp) + +typedef enum { + lock_result_success, + lock_result_failure, + lock_result_no_extent +} lock_result_t; + +static lock_result_t +extent_rtree_leaf_elm_try_lock(tsdn_t *tsdn, rtree_leaf_elm_t *elm, + extent_t **result) { + extent_t *extent1 = rtree_leaf_elm_extent_read(tsdn, &extents_rtree, + elm, true); + + if (extent1 == NULL) { + return lock_result_no_extent; + } + /* + * It's possible that the extent changed out from under us, and with it + * the leaf->extent mapping. We have to recheck while holding the lock. + */ + extent_lock(tsdn, extent1); + extent_t *extent2 = rtree_leaf_elm_extent_read(tsdn, + &extents_rtree, elm, true); + + if (extent1 == extent2) { + *result = extent1; + return lock_result_success; + } else { + extent_unlock(tsdn, extent1); + return lock_result_failure; + } +} + +/* + * Returns a pool-locked extent_t * if there's one associated with the given + * address, and NULL otherwise. + */ +static extent_t * +extent_lock_from_addr(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, void *addr) { + extent_t *ret = NULL; + rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, &extents_rtree, + rtree_ctx, (uintptr_t)addr, false, false); + if (elm == NULL) { + return NULL; + } + lock_result_t lock_result; + do { + lock_result = extent_rtree_leaf_elm_try_lock(tsdn, elm, &ret); + } while (lock_result == lock_result_failure); + return ret; +} + +extent_t * +extent_alloc(tsdn_t *tsdn, arena_t *arena) { + malloc_mutex_lock(tsdn, &arena->extent_avail_mtx); + extent_t *extent = extent_avail_first(&arena->extent_avail); + if (extent == NULL) { + malloc_mutex_unlock(tsdn, &arena->extent_avail_mtx); + return base_alloc_extent(tsdn, arena->base); + } + extent_avail_remove(&arena->extent_avail, extent); + malloc_mutex_unlock(tsdn, &arena->extent_avail_mtx); + return extent; +} + +void +extent_dalloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent) { + malloc_mutex_lock(tsdn, &arena->extent_avail_mtx); + extent_avail_insert(&arena->extent_avail, extent); + malloc_mutex_unlock(tsdn, &arena->extent_avail_mtx); +} + +extent_hooks_t * +extent_hooks_get(arena_t *arena) { + return base_extent_hooks_get(arena->base); +} + +extent_hooks_t * +extent_hooks_set(tsd_t *tsd, arena_t *arena, extent_hooks_t *extent_hooks) { + background_thread_info_t *info; + if (have_background_thread) { + info = arena_background_thread_info_get(arena); + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + } + extent_hooks_t *ret = base_extent_hooks_set(arena->base, extent_hooks); + if (have_background_thread) { + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + } + + return ret; +} + +static void +extent_hooks_assure_initialized(arena_t *arena, + extent_hooks_t **r_extent_hooks) { + if (*r_extent_hooks == EXTENT_HOOKS_INITIALIZER) { + *r_extent_hooks = extent_hooks_get(arena); + } +} + +#ifndef JEMALLOC_JET +static +#endif +size_t +extent_size_quantize_floor(size_t size) { + size_t ret; + pszind_t pind; + + assert(size > 0); + assert((size & PAGE_MASK) == 0); + + pind = sz_psz2ind(size - sz_large_pad + 1); + if (pind == 0) { + /* + * Avoid underflow. This short-circuit would also do the right + * thing for all sizes in the range for which there are + * PAGE-spaced size classes, but it's simplest to just handle + * the one case that would cause erroneous results. + */ + return size; + } + ret = sz_pind2sz(pind - 1) + sz_large_pad; + assert(ret <= size); + return ret; +} + +#ifndef JEMALLOC_JET +static +#endif +size_t +extent_size_quantize_ceil(size_t size) { + size_t ret; - ret = (a_size > b_size) - (a_size < b_size); - if (ret == 0) { - uintptr_t a_addr = (uintptr_t)a->addr; - uintptr_t b_addr = (uintptr_t)b->addr; + assert(size > 0); + assert(size - sz_large_pad <= LARGE_MAXCLASS); + assert((size & PAGE_MASK) == 0); - ret = (a_addr > b_addr) - (a_addr < b_addr); + ret = extent_size_quantize_floor(size); + if (ret < size) { + /* + * Skip a quantization that may have an adequately large extent, + * because under-sized extents may be mixed in. This only + * happens when an unusual size is requested, i.e. for aligned + * allocation, and is just one of several places where linear + * search would potentially find sufficiently aligned available + * memory somewhere lower. + */ + ret = sz_pind2sz(sz_psz2ind(ret - sz_large_pad + 1)) + + sz_large_pad; } + return ret; +} + +/* Generate pairing heap functions. */ +ph_gen(, extent_heap_, extent_heap_t, extent_t, ph_link, extent_snad_comp) + +bool +extents_init(tsdn_t *tsdn, extents_t *extents, extent_state_t state, + bool delay_coalesce) { + if (malloc_mutex_init(&extents->mtx, "extents", WITNESS_RANK_EXTENTS, + malloc_mutex_rank_exclusive)) { + return true; + } + for (unsigned i = 0; i < NPSIZES+1; i++) { + extent_heap_new(&extents->heaps[i]); + } + bitmap_init(extents->bitmap, &extents_bitmap_info, true); + extent_list_init(&extents->lru); + atomic_store_zu(&extents->npages, 0, ATOMIC_RELAXED); + extents->state = state; + extents->delay_coalesce = delay_coalesce; + return false; +} + +extent_state_t +extents_state_get(const extents_t *extents) { + return extents->state; +} - return (ret); +size_t +extents_npages_get(extents_t *extents) { + return atomic_load_zu(&extents->npages, ATOMIC_RELAXED); } -/* Generate red-black tree functions. */ -rb_gen(, extent_tree_szad_, extent_tree_t, extent_node_t, link_szad, - extent_szad_comp) +static void +extents_insert_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, + bool preserve_lru) { + malloc_mutex_assert_owner(tsdn, &extents->mtx); + assert(extent_state_get(extent) == extents->state); -static inline int -extent_ad_comp(extent_node_t *a, extent_node_t *b) -{ - uintptr_t a_addr = (uintptr_t)a->addr; - uintptr_t b_addr = (uintptr_t)b->addr; + size_t size = extent_size_get(extent); + size_t psz = extent_size_quantize_floor(size); + pszind_t pind = sz_psz2ind(psz); + if (extent_heap_empty(&extents->heaps[pind])) { + bitmap_unset(extents->bitmap, &extents_bitmap_info, + (size_t)pind); + } + extent_heap_insert(&extents->heaps[pind], extent); + if (!preserve_lru) { + extent_list_append(&extents->lru, extent); + } + size_t npages = size >> LG_PAGE; + /* + * All modifications to npages hold the mutex (as asserted above), so we + * don't need an atomic fetch-add; we can get by with a load followed by + * a store. + */ + size_t cur_extents_npages = + atomic_load_zu(&extents->npages, ATOMIC_RELAXED); + atomic_store_zu(&extents->npages, cur_extents_npages + npages, + ATOMIC_RELAXED); +} - return ((a_addr > b_addr) - (a_addr < b_addr)); +static void +extents_remove_locked(tsdn_t *tsdn, extents_t *extents, extent_t *extent, + bool preserve_lru) { + malloc_mutex_assert_owner(tsdn, &extents->mtx); + assert(extent_state_get(extent) == extents->state); + + size_t size = extent_size_get(extent); + size_t psz = extent_size_quantize_floor(size); + pszind_t pind = sz_psz2ind(psz); + extent_heap_remove(&extents->heaps[pind], extent); + if (extent_heap_empty(&extents->heaps[pind])) { + bitmap_set(extents->bitmap, &extents_bitmap_info, + (size_t)pind); + } + if (!preserve_lru) { + extent_list_remove(&extents->lru, extent); + } + size_t npages = size >> LG_PAGE; + /* + * As in extents_insert_locked, we hold extents->mtx and so don't need + * atomic operations for updating extents->npages. + */ + size_t cur_extents_npages = + atomic_load_zu(&extents->npages, ATOMIC_RELAXED); + assert(cur_extents_npages >= npages); + atomic_store_zu(&extents->npages, + cur_extents_npages - (size >> LG_PAGE), ATOMIC_RELAXED); } -/* Generate red-black tree functions. */ -rb_gen(, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad, - extent_ad_comp) +/* Do any-best-fit extent selection, i.e. select any extent that best fits. */ +static extent_t * +extents_best_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + size_t size) { + pszind_t pind = sz_psz2ind(extent_size_quantize_ceil(size)); + pszind_t i = (pszind_t)bitmap_ffu(extents->bitmap, &extents_bitmap_info, + (size_t)pind); + if (i < NPSIZES+1) { + assert(!extent_heap_empty(&extents->heaps[i])); + extent_t *extent = extent_heap_any(&extents->heaps[i]); + assert(extent_size_get(extent) >= size); + return extent; + } + + return NULL; +} + +/* + * Do first-fit extent selection, i.e. select the oldest/lowest extent that is + * large enough. + */ +static extent_t * +extents_first_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + size_t size) { + extent_t *ret = NULL; + + pszind_t pind = sz_psz2ind(extent_size_quantize_ceil(size)); + for (pszind_t i = (pszind_t)bitmap_ffu(extents->bitmap, + &extents_bitmap_info, (size_t)pind); i < NPSIZES+1; i = + (pszind_t)bitmap_ffu(extents->bitmap, &extents_bitmap_info, + (size_t)i+1)) { + assert(!extent_heap_empty(&extents->heaps[i])); + extent_t *extent = extent_heap_first(&extents->heaps[i]); + assert(extent_size_get(extent) >= size); + if (ret == NULL || extent_snad_comp(extent, ret) < 0) { + ret = extent; + } + if (i == NPSIZES) { + break; + } + assert(i < NPSIZES); + } + + return ret; +} + +/* + * Do {best,first}-fit extent selection, where the selection policy choice is + * based on extents->delay_coalesce. Best-fit selection requires less + * searching, but its layout policy is less stable and may cause higher virtual + * memory fragmentation as a side effect. + */ +static extent_t * +extents_fit_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + size_t size) { + malloc_mutex_assert_owner(tsdn, &extents->mtx); + + return extents->delay_coalesce ? extents_best_fit_locked(tsdn, arena, + extents, size) : extents_first_fit_locked(tsdn, arena, extents, + size); +} + +static bool +extent_try_delayed_coalesce(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + extent_t *extent) { + extent_state_set(extent, extent_state_active); + bool coalesced; + extent = extent_try_coalesce(tsdn, arena, r_extent_hooks, rtree_ctx, + extents, extent, &coalesced, false); + extent_state_set(extent, extents_state_get(extents)); + + if (!coalesced) { + return true; + } + extents_insert_locked(tsdn, extents, extent, true); + return false; +} + +extent_t * +extents_alloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, void *new_addr, size_t size, size_t pad, + size_t alignment, bool slab, szind_t szind, bool *zero, bool *commit) { + assert(size + pad != 0); + assert(alignment != 0); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + return extent_recycle(tsdn, arena, r_extent_hooks, extents, new_addr, + size, pad, alignment, slab, szind, zero, commit, false); +} + +void +extents_dalloc(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, extent_t *extent) { + assert(extent_base_get(extent) != NULL); + assert(extent_size_get(extent) != 0); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + extent_addr_set(extent, extent_base_get(extent)); + extent_zeroed_set(extent, false); + + extent_record(tsdn, arena, r_extent_hooks, extents, extent, false); +} + +extent_t * +extents_evict(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, size_t npages_min) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + malloc_mutex_lock(tsdn, &extents->mtx); + + /* + * Get the LRU coalesced extent, if any. If coalescing was delayed, + * the loop will iterate until the LRU extent is fully coalesced. + */ + extent_t *extent; + while (true) { + /* Get the LRU extent, if any. */ + extent = extent_list_first(&extents->lru); + if (extent == NULL) { + goto label_return; + } + /* Check the eviction limit. */ + size_t npages = extent_size_get(extent) >> LG_PAGE; + size_t extents_npages = atomic_load_zu(&extents->npages, + ATOMIC_RELAXED); + if (extents_npages - npages < npages_min) { + extent = NULL; + goto label_return; + } + extents_remove_locked(tsdn, extents, extent, false); + if (!extents->delay_coalesce) { + break; + } + /* Try to coalesce. */ + if (extent_try_delayed_coalesce(tsdn, arena, r_extent_hooks, + rtree_ctx, extents, extent)) { + break; + } + /* + * The LRU extent was just coalesced and the result placed in + * the LRU at its neighbor's position. Start over. + */ + } + + /* + * Either mark the extent active or deregister it to protect against + * concurrent operations. + */ + switch (extents_state_get(extents)) { + case extent_state_active: + not_reached(); + case extent_state_dirty: + case extent_state_muzzy: + extent_state_set(extent, extent_state_active); + break; + case extent_state_retained: + extent_deregister(tsdn, extent); + break; + default: + not_reached(); + } + +label_return: + malloc_mutex_unlock(tsdn, &extents->mtx); + return extent; +} + +static void +extents_leak(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, extent_t *extent, bool growing_retained) { + /* + * Leak extent after making sure its pages have already been purged, so + * that this is only a virtual memory leak. + */ + if (extents_state_get(extents) == extent_state_dirty) { + if (extent_purge_lazy_impl(tsdn, arena, r_extent_hooks, + extent, 0, extent_size_get(extent), growing_retained)) { + extent_purge_forced_impl(tsdn, arena, r_extent_hooks, + extent, 0, extent_size_get(extent), + growing_retained); + } + } + extent_dalloc(tsdn, arena, extent); +} + +void +extents_prefork(tsdn_t *tsdn, extents_t *extents) { + malloc_mutex_prefork(tsdn, &extents->mtx); +} + +void +extents_postfork_parent(tsdn_t *tsdn, extents_t *extents) { + malloc_mutex_postfork_parent(tsdn, &extents->mtx); +} + +void +extents_postfork_child(tsdn_t *tsdn, extents_t *extents) { + malloc_mutex_postfork_child(tsdn, &extents->mtx); +} + +static void +extent_deactivate_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + extent_t *extent, bool preserve_lru) { + assert(extent_arena_get(extent) == arena); + assert(extent_state_get(extent) == extent_state_active); + + extent_state_set(extent, extents_state_get(extents)); + extents_insert_locked(tsdn, extents, extent, preserve_lru); +} + +static void +extent_deactivate(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + extent_t *extent, bool preserve_lru) { + malloc_mutex_lock(tsdn, &extents->mtx); + extent_deactivate_locked(tsdn, arena, extents, extent, preserve_lru); + malloc_mutex_unlock(tsdn, &extents->mtx); +} + +static void +extent_activate_locked(tsdn_t *tsdn, arena_t *arena, extents_t *extents, + extent_t *extent, bool preserve_lru) { + assert(extent_arena_get(extent) == arena); + assert(extent_state_get(extent) == extents_state_get(extents)); + + extents_remove_locked(tsdn, extents, extent, preserve_lru); + extent_state_set(extent, extent_state_active); +} + +static bool +extent_rtree_leaf_elms_lookup(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, + const extent_t *extent, bool dependent, bool init_missing, + rtree_leaf_elm_t **r_elm_a, rtree_leaf_elm_t **r_elm_b) { + *r_elm_a = rtree_leaf_elm_lookup(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_base_get(extent), dependent, init_missing); + if (!dependent && *r_elm_a == NULL) { + return true; + } + assert(*r_elm_a != NULL); + + *r_elm_b = rtree_leaf_elm_lookup(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_last_get(extent), dependent, init_missing); + if (!dependent && *r_elm_b == NULL) { + return true; + } + assert(*r_elm_b != NULL); + + return false; +} + +static void +extent_rtree_write_acquired(tsdn_t *tsdn, rtree_leaf_elm_t *elm_a, + rtree_leaf_elm_t *elm_b, extent_t *extent, szind_t szind, bool slab) { + rtree_leaf_elm_write(tsdn, &extents_rtree, elm_a, extent, szind, slab); + if (elm_b != NULL) { + rtree_leaf_elm_write(tsdn, &extents_rtree, elm_b, extent, szind, + slab); + } +} + +static void +extent_interior_register(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, extent_t *extent, + szind_t szind) { + assert(extent_slab_get(extent)); + + /* Register interior. */ + for (size_t i = 1; i < (extent_size_get(extent) >> LG_PAGE) - 1; i++) { + rtree_write(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_base_get(extent) + (uintptr_t)(i << + LG_PAGE), extent, szind, true); + } +} + +static void +extent_gdump_add(tsdn_t *tsdn, const extent_t *extent) { + cassert(config_prof); + /* prof_gdump() requirement. */ + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + if (opt_prof && extent_state_get(extent) == extent_state_active) { + size_t nadd = extent_size_get(extent) >> LG_PAGE; + size_t cur = atomic_fetch_add_zu(&curpages, nadd, + ATOMIC_RELAXED) + nadd; + size_t high = atomic_load_zu(&highpages, ATOMIC_RELAXED); + while (cur > high && !atomic_compare_exchange_weak_zu( + &highpages, &high, cur, ATOMIC_RELAXED, ATOMIC_RELAXED)) { + /* + * Don't refresh cur, because it may have decreased + * since this thread lost the highpages update race. + * Note that high is updated in case of CAS failure. + */ + } + if (cur > high && prof_gdump_get_unlocked()) { + prof_gdump(tsdn); + } + } +} + +static void +extent_gdump_sub(tsdn_t *tsdn, const extent_t *extent) { + cassert(config_prof); + + if (opt_prof && extent_state_get(extent) == extent_state_active) { + size_t nsub = extent_size_get(extent) >> LG_PAGE; + assert(atomic_load_zu(&curpages, ATOMIC_RELAXED) >= nsub); + atomic_fetch_sub_zu(&curpages, nsub, ATOMIC_RELAXED); + } +} + +static bool +extent_register_impl(tsdn_t *tsdn, extent_t *extent, bool gdump_add) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + rtree_leaf_elm_t *elm_a, *elm_b; + + /* + * We need to hold the lock to protect against a concurrent coalesce + * operation that sees us in a partial state. + */ + extent_lock(tsdn, extent); + + if (extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, extent, false, true, + &elm_a, &elm_b)) { + return true; + } + + szind_t szind = extent_szind_get_maybe_invalid(extent); + bool slab = extent_slab_get(extent); + extent_rtree_write_acquired(tsdn, elm_a, elm_b, extent, szind, slab); + if (slab) { + extent_interior_register(tsdn, rtree_ctx, extent, szind); + } + + extent_unlock(tsdn, extent); + + if (config_prof && gdump_add) { + extent_gdump_add(tsdn, extent); + } + + return false; +} + +static bool +extent_register(tsdn_t *tsdn, extent_t *extent) { + return extent_register_impl(tsdn, extent, true); +} + +static bool +extent_register_no_gdump_add(tsdn_t *tsdn, extent_t *extent) { + return extent_register_impl(tsdn, extent, false); +} + +static void +extent_reregister(tsdn_t *tsdn, extent_t *extent) { + bool err = extent_register(tsdn, extent); + assert(!err); +} + +static void +extent_interior_deregister(tsdn_t *tsdn, rtree_ctx_t *rtree_ctx, + extent_t *extent) { + size_t i; + + assert(extent_slab_get(extent)); + + for (i = 1; i < (extent_size_get(extent) >> LG_PAGE) - 1; i++) { + rtree_clear(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_base_get(extent) + (uintptr_t)(i << + LG_PAGE)); + } +} + +static void +extent_deregister(tsdn_t *tsdn, extent_t *extent) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + rtree_leaf_elm_t *elm_a, *elm_b; + extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, extent, true, false, + &elm_a, &elm_b); + + extent_lock(tsdn, extent); + + extent_rtree_write_acquired(tsdn, elm_a, elm_b, NULL, NSIZES, false); + if (extent_slab_get(extent)) { + extent_interior_deregister(tsdn, rtree_ctx, extent); + extent_slab_set(extent, false); + } + + extent_unlock(tsdn, extent); + + if (config_prof) { + extent_gdump_sub(tsdn, extent); + } +} + +static extent_t * +extent_recycle_extract(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, + bool *zero, bool *commit, bool growing_retained) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + assert(alignment > 0); + if (config_debug && new_addr != NULL) { + /* + * Non-NULL new_addr has two use cases: + * + * 1) Recycle a known-extant extent, e.g. during purging. + * 2) Perform in-place expanding reallocation. + * + * Regardless of use case, new_addr must either refer to a + * non-existing extent, or to the base of an extant extent, + * since only active slabs support interior lookups (which of + * course cannot be recycled). + */ + assert(PAGE_ADDR2BASE(new_addr) == new_addr); + assert(pad == 0); + assert(alignment <= PAGE); + } + + size_t esize = size + pad; + size_t alloc_size = esize + PAGE_CEILING(alignment) - PAGE; + /* Beware size_t wrap-around. */ + if (alloc_size < esize) { + return NULL; + } + malloc_mutex_lock(tsdn, &extents->mtx); + extent_hooks_assure_initialized(arena, r_extent_hooks); + extent_t *extent; + if (new_addr != NULL) { + extent = extent_lock_from_addr(tsdn, rtree_ctx, new_addr); + if (extent != NULL) { + /* + * We might null-out extent to report an error, but we + * still need to unlock the associated mutex after. + */ + extent_t *unlock_extent = extent; + assert(extent_base_get(extent) == new_addr); + if (extent_arena_get(extent) != arena || + extent_size_get(extent) < esize || + extent_state_get(extent) != + extents_state_get(extents)) { + extent = NULL; + } + extent_unlock(tsdn, unlock_extent); + } + } else { + extent = extents_fit_locked(tsdn, arena, extents, alloc_size); + } + if (extent == NULL) { + malloc_mutex_unlock(tsdn, &extents->mtx); + return NULL; + } + + extent_activate_locked(tsdn, arena, extents, extent, false); + malloc_mutex_unlock(tsdn, &extents->mtx); + + if (extent_zeroed_get(extent)) { + *zero = true; + } + if (extent_committed_get(extent)) { + *commit = true; + } + + return extent; +} + +static extent_t * +extent_recycle_split(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + void *new_addr, size_t size, size_t pad, size_t alignment, bool slab, + szind_t szind, extent_t *extent, bool growing_retained) { + size_t esize = size + pad; + size_t leadsize = ALIGNMENT_CEILING((uintptr_t)extent_base_get(extent), + PAGE_CEILING(alignment)) - (uintptr_t)extent_base_get(extent); + assert(new_addr == NULL || leadsize == 0); + assert(extent_size_get(extent) >= leadsize + esize); + size_t trailsize = extent_size_get(extent) - leadsize - esize; + + /* Split the lead. */ + if (leadsize != 0) { + extent_t *lead = extent; + extent = extent_split_impl(tsdn, arena, r_extent_hooks, + lead, leadsize, NSIZES, false, esize + trailsize, szind, + slab, growing_retained); + if (extent == NULL) { + extent_deregister(tsdn, lead); + extents_leak(tsdn, arena, r_extent_hooks, extents, + lead, growing_retained); + return NULL; + } + extent_deactivate(tsdn, arena, extents, lead, false); + } + + /* Split the trail. */ + if (trailsize != 0) { + extent_t *trail = extent_split_impl(tsdn, arena, + r_extent_hooks, extent, esize, szind, slab, trailsize, + NSIZES, false, growing_retained); + if (trail == NULL) { + extent_deregister(tsdn, extent); + extents_leak(tsdn, arena, r_extent_hooks, extents, + extent, growing_retained); + return NULL; + } + extent_deactivate(tsdn, arena, extents, trail, false); + } else if (leadsize == 0) { + /* + * Splitting causes szind to be set as a side effect, but no + * splitting occurred. + */ + extent_szind_set(extent, szind); + if (szind != NSIZES) { + rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_addr_get(extent), szind, slab); + if (slab && extent_size_get(extent) > PAGE) { + rtree_szind_slab_update(tsdn, &extents_rtree, + rtree_ctx, + (uintptr_t)extent_past_get(extent) - + (uintptr_t)PAGE, szind, slab); + } + } + } + + return extent; +} + +static extent_t * +extent_recycle(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, void *new_addr, size_t size, size_t pad, + size_t alignment, bool slab, szind_t szind, bool *zero, bool *commit, + bool growing_retained) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + assert(new_addr == NULL || !slab); + assert(pad == 0 || !slab); + assert(!*zero || !slab); + + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + bool committed = false; + extent_t *extent = extent_recycle_extract(tsdn, arena, r_extent_hooks, + rtree_ctx, extents, new_addr, size, pad, alignment, slab, zero, + &committed, growing_retained); + if (extent == NULL) { + return NULL; + } + if (committed) { + *commit = true; + } + + extent = extent_recycle_split(tsdn, arena, r_extent_hooks, rtree_ctx, + extents, new_addr, size, pad, alignment, slab, szind, extent, + growing_retained); + if (extent == NULL) { + return NULL; + } + + if (*commit && !extent_committed_get(extent)) { + if (extent_commit_impl(tsdn, arena, r_extent_hooks, extent, + 0, extent_size_get(extent), growing_retained)) { + extent_record(tsdn, arena, r_extent_hooks, extents, + extent, growing_retained); + return NULL; + } + extent_zeroed_set(extent, true); + } + + if (pad != 0) { + extent_addr_randomize(tsdn, extent, alignment); + } + assert(extent_state_get(extent) == extent_state_active); + if (slab) { + extent_slab_set(extent, slab); + extent_interior_register(tsdn, rtree_ctx, extent, szind); + } + + if (*zero) { + void *addr = extent_base_get(extent); + size_t size = extent_size_get(extent); + if (!extent_zeroed_get(extent)) { + if (pages_purge_forced(addr, size)) { + memset(addr, 0, size); + } + } else if (config_debug) { + size_t *p = (size_t *)(uintptr_t)addr; + for (size_t i = 0; i < size / sizeof(size_t); i++) { + assert(p[i] == 0); + } + } + } + return extent; +} + +/* + * If the caller specifies (!*zero), it is still possible to receive zeroed + * memory, in which case *zero is toggled to true. arena_extent_alloc() takes + * advantage of this to avoid demanding zeroed extents, but taking advantage of + * them if they are returned. + */ +static void * +extent_alloc_core(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, + size_t alignment, bool *zero, bool *commit, dss_prec_t dss_prec) { + void *ret; + + assert(size != 0); + assert(alignment != 0); + + /* "primary" dss. */ + if (have_dss && dss_prec == dss_prec_primary && (ret = + extent_alloc_dss(tsdn, arena, new_addr, size, alignment, zero, + commit)) != NULL) { + return ret; + } + /* mmap. */ + if ((ret = extent_alloc_mmap(new_addr, size, alignment, zero, commit)) + != NULL) { + return ret; + } + /* "secondary" dss. */ + if (have_dss && dss_prec == dss_prec_secondary && (ret = + extent_alloc_dss(tsdn, arena, new_addr, size, alignment, zero, + commit)) != NULL) { + return ret; + } + + /* All strategies for allocation failed. */ + return NULL; +} + +static void * +extent_alloc_default_impl(tsdn_t *tsdn, arena_t *arena, void *new_addr, + size_t size, size_t alignment, bool *zero, bool *commit) { + void *ret; + + ret = extent_alloc_core(tsdn, arena, new_addr, size, alignment, zero, + commit, (dss_prec_t)atomic_load_u(&arena->dss_prec, + ATOMIC_RELAXED)); + return ret; +} + +static void * +extent_alloc_default(extent_hooks_t *extent_hooks, void *new_addr, size_t size, + size_t alignment, bool *zero, bool *commit, unsigned arena_ind) { + tsdn_t *tsdn; + arena_t *arena; + + tsdn = tsdn_fetch(); + arena = arena_get(tsdn, arena_ind, false); + /* + * The arena we're allocating on behalf of must have been initialized + * already. + */ + assert(arena != NULL); + + return extent_alloc_default_impl(tsdn, arena, new_addr, size, + alignment, zero, commit); +} + +static void +extent_hook_pre_reentrancy(tsdn_t *tsdn, arena_t *arena) { + tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn); + pre_reentrancy(tsd, arena); +} + +static void +extent_hook_post_reentrancy(tsdn_t *tsdn) { + tsd_t *tsd = tsdn_null(tsdn) ? tsd_fetch() : tsdn_tsd(tsdn); + post_reentrancy(tsd); +} + +/* + * If virtual memory is retained, create increasingly larger extents from which + * to split requested extents in order to limit the total number of disjoint + * virtual memory ranges retained by each arena. + */ +static extent_t * +extent_grow_retained(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, size_t size, size_t pad, size_t alignment, + bool slab, szind_t szind, bool *zero, bool *commit) { + malloc_mutex_assert_owner(tsdn, &arena->extent_grow_mtx); + assert(pad == 0 || !slab); + assert(!*zero || !slab); + + size_t esize = size + pad; + size_t alloc_size_min = esize + PAGE_CEILING(alignment) - PAGE; + /* Beware size_t wrap-around. */ + if (alloc_size_min < esize) { + goto label_err; + } + /* + * Find the next extent size in the series that would be large enough to + * satisfy this request. + */ + pszind_t egn_skip = 0; + size_t alloc_size = sz_pind2sz(arena->extent_grow_next + egn_skip); + while (alloc_size < alloc_size_min) { + egn_skip++; + if (arena->extent_grow_next + egn_skip == NPSIZES) { + /* Outside legal range. */ + goto label_err; + } + assert(arena->extent_grow_next + egn_skip < NPSIZES); + alloc_size = sz_pind2sz(arena->extent_grow_next + egn_skip); + } + + extent_t *extent = extent_alloc(tsdn, arena); + if (extent == NULL) { + goto label_err; + } + bool zeroed = false; + bool committed = false; + + void *ptr; + if (*r_extent_hooks == &extent_hooks_default) { + ptr = extent_alloc_core(tsdn, arena, NULL, alloc_size, PAGE, + &zeroed, &committed, (dss_prec_t)atomic_load_u( + &arena->dss_prec, ATOMIC_RELAXED)); + } else { + extent_hook_pre_reentrancy(tsdn, arena); + ptr = (*r_extent_hooks)->alloc(*r_extent_hooks, NULL, + alloc_size, PAGE, &zeroed, &committed, + arena_ind_get(arena)); + extent_hook_post_reentrancy(tsdn); + } + + extent_init(extent, arena, ptr, alloc_size, false, NSIZES, + arena_extent_sn_next(arena), extent_state_active, zeroed, + committed); + if (ptr == NULL) { + extent_dalloc(tsdn, arena, extent); + goto label_err; + } + if (extent_register_no_gdump_add(tsdn, extent)) { + extents_leak(tsdn, arena, r_extent_hooks, + &arena->extents_retained, extent, true); + goto label_err; + } + + size_t leadsize = ALIGNMENT_CEILING((uintptr_t)ptr, + PAGE_CEILING(alignment)) - (uintptr_t)ptr; + assert(alloc_size >= leadsize + esize); + size_t trailsize = alloc_size - leadsize - esize; + if (extent_zeroed_get(extent) && extent_committed_get(extent)) { + *zero = true; + } + if (extent_committed_get(extent)) { + *commit = true; + } + + /* Split the lead. */ + if (leadsize != 0) { + extent_t *lead = extent; + extent = extent_split_impl(tsdn, arena, r_extent_hooks, lead, + leadsize, NSIZES, false, esize + trailsize, szind, slab, + true); + if (extent == NULL) { + extent_deregister(tsdn, lead); + extents_leak(tsdn, arena, r_extent_hooks, + &arena->extents_retained, lead, true); + goto label_err; + } + extent_record(tsdn, arena, r_extent_hooks, + &arena->extents_retained, lead, true); + } + + /* Split the trail. */ + if (trailsize != 0) { + extent_t *trail = extent_split_impl(tsdn, arena, r_extent_hooks, + extent, esize, szind, slab, trailsize, NSIZES, false, true); + if (trail == NULL) { + extent_deregister(tsdn, extent); + extents_leak(tsdn, arena, r_extent_hooks, + &arena->extents_retained, extent, true); + goto label_err; + } + extent_record(tsdn, arena, r_extent_hooks, + &arena->extents_retained, trail, true); + } else if (leadsize == 0) { + /* + * Splitting causes szind to be set as a side effect, but no + * splitting occurred. + */ + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, + &rtree_ctx_fallback); + + extent_szind_set(extent, szind); + if (szind != NSIZES) { + rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_addr_get(extent), szind, slab); + if (slab && extent_size_get(extent) > PAGE) { + rtree_szind_slab_update(tsdn, &extents_rtree, + rtree_ctx, + (uintptr_t)extent_past_get(extent) - + (uintptr_t)PAGE, szind, slab); + } + } + } + + if (*commit && !extent_committed_get(extent)) { + if (extent_commit_impl(tsdn, arena, r_extent_hooks, extent, 0, + extent_size_get(extent), true)) { + extent_record(tsdn, arena, r_extent_hooks, + &arena->extents_retained, extent, true); + goto label_err; + } + extent_zeroed_set(extent, true); + } + + /* + * Increment extent_grow_next if doing so wouldn't exceed the legal + * range. + */ + if (arena->extent_grow_next + egn_skip + 1 < NPSIZES) { + arena->extent_grow_next += egn_skip + 1; + } else { + arena->extent_grow_next = NPSIZES - 1; + } + /* All opportunities for failure are past. */ + malloc_mutex_unlock(tsdn, &arena->extent_grow_mtx); + + if (config_prof) { + /* Adjust gdump stats now that extent is final size. */ + extent_gdump_add(tsdn, extent); + } + if (pad != 0) { + extent_addr_randomize(tsdn, extent, alignment); + } + if (slab) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, + &rtree_ctx_fallback); + + extent_slab_set(extent, true); + extent_interior_register(tsdn, rtree_ctx, extent, szind); + } + if (*zero && !extent_zeroed_get(extent)) { + void *addr = extent_base_get(extent); + size_t size = extent_size_get(extent); + if (pages_purge_forced(addr, size)) { + memset(addr, 0, size); + } + } + + return extent; +label_err: + malloc_mutex_unlock(tsdn, &arena->extent_grow_mtx); + return NULL; +} + +static extent_t * +extent_alloc_retained(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, void *new_addr, size_t size, size_t pad, + size_t alignment, bool slab, szind_t szind, bool *zero, bool *commit) { + assert(size != 0); + assert(alignment != 0); + + malloc_mutex_lock(tsdn, &arena->extent_grow_mtx); + + extent_t *extent = extent_recycle(tsdn, arena, r_extent_hooks, + &arena->extents_retained, new_addr, size, pad, alignment, slab, + szind, zero, commit, true); + if (extent != NULL) { + malloc_mutex_unlock(tsdn, &arena->extent_grow_mtx); + if (config_prof) { + extent_gdump_add(tsdn, extent); + } + } else if (opt_retain && new_addr == NULL) { + extent = extent_grow_retained(tsdn, arena, r_extent_hooks, size, + pad, alignment, slab, szind, zero, commit); + /* extent_grow_retained() always releases extent_grow_mtx. */ + } else { + malloc_mutex_unlock(tsdn, &arena->extent_grow_mtx); + } + malloc_mutex_assert_not_owner(tsdn, &arena->extent_grow_mtx); + + return extent; +} + +static extent_t * +extent_alloc_wrapper_hard(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, void *new_addr, size_t size, size_t pad, + size_t alignment, bool slab, szind_t szind, bool *zero, bool *commit) { + size_t esize = size + pad; + extent_t *extent = extent_alloc(tsdn, arena); + if (extent == NULL) { + return NULL; + } + void *addr; + if (*r_extent_hooks == &extent_hooks_default) { + /* Call directly to propagate tsdn. */ + addr = extent_alloc_default_impl(tsdn, arena, new_addr, esize, + alignment, zero, commit); + } else { + extent_hook_pre_reentrancy(tsdn, arena); + addr = (*r_extent_hooks)->alloc(*r_extent_hooks, new_addr, + esize, alignment, zero, commit, arena_ind_get(arena)); + extent_hook_post_reentrancy(tsdn); + } + if (addr == NULL) { + extent_dalloc(tsdn, arena, extent); + return NULL; + } + extent_init(extent, arena, addr, esize, slab, szind, + arena_extent_sn_next(arena), extent_state_active, zero, commit); + if (pad != 0) { + extent_addr_randomize(tsdn, extent, alignment); + } + if (extent_register(tsdn, extent)) { + extents_leak(tsdn, arena, r_extent_hooks, + &arena->extents_retained, extent, false); + return NULL; + } + + return extent; +} + +extent_t * +extent_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, void *new_addr, size_t size, size_t pad, + size_t alignment, bool slab, szind_t szind, bool *zero, bool *commit) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + + extent_t *extent = extent_alloc_retained(tsdn, arena, r_extent_hooks, + new_addr, size, pad, alignment, slab, szind, zero, commit); + if (extent == NULL) { + extent = extent_alloc_wrapper_hard(tsdn, arena, r_extent_hooks, + new_addr, size, pad, alignment, slab, szind, zero, commit); + } + + return extent; +} + +static bool +extent_can_coalesce(arena_t *arena, extents_t *extents, const extent_t *inner, + const extent_t *outer) { + assert(extent_arena_get(inner) == arena); + if (extent_arena_get(outer) != arena) { + return false; + } + + assert(extent_state_get(inner) == extent_state_active); + if (extent_state_get(outer) != extents->state) { + return false; + } + + if (extent_committed_get(inner) != extent_committed_get(outer)) { + return false; + } + + return true; +} + +static bool +extent_coalesce(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, extent_t *inner, extent_t *outer, bool forward, + bool growing_retained) { + assert(extent_can_coalesce(arena, extents, inner, outer)); + + if (forward && extents->delay_coalesce) { + /* + * The extent that remains after coalescing must occupy the + * outer extent's position in the LRU. For forward coalescing, + * swap the inner extent into the LRU. + */ + extent_list_replace(&extents->lru, outer, inner); + } + extent_activate_locked(tsdn, arena, extents, outer, + extents->delay_coalesce); + + malloc_mutex_unlock(tsdn, &extents->mtx); + bool err = extent_merge_impl(tsdn, arena, r_extent_hooks, + forward ? inner : outer, forward ? outer : inner, growing_retained); + malloc_mutex_lock(tsdn, &extents->mtx); + + if (err) { + if (forward && extents->delay_coalesce) { + extent_list_replace(&extents->lru, inner, outer); + } + extent_deactivate_locked(tsdn, arena, extents, outer, + extents->delay_coalesce); + } + + return err; +} + +static extent_t * +extent_try_coalesce(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, rtree_ctx_t *rtree_ctx, extents_t *extents, + extent_t *extent, bool *coalesced, bool growing_retained) { + /* + * Continue attempting to coalesce until failure, to protect against + * races with other threads that are thwarted by this one. + */ + bool again; + do { + again = false; + + /* Try to coalesce forward. */ + extent_t *next = extent_lock_from_addr(tsdn, rtree_ctx, + extent_past_get(extent)); + if (next != NULL) { + /* + * extents->mtx only protects against races for + * like-state extents, so call extent_can_coalesce() + * before releasing next's pool lock. + */ + bool can_coalesce = extent_can_coalesce(arena, extents, + extent, next); + + extent_unlock(tsdn, next); + + if (can_coalesce && !extent_coalesce(tsdn, arena, + r_extent_hooks, extents, extent, next, true, + growing_retained)) { + if (extents->delay_coalesce) { + /* Do minimal coalescing. */ + *coalesced = true; + return extent; + } + again = true; + } + } + + /* Try to coalesce backward. */ + extent_t *prev = extent_lock_from_addr(tsdn, rtree_ctx, + extent_before_get(extent)); + if (prev != NULL) { + bool can_coalesce = extent_can_coalesce(arena, extents, + extent, prev); + extent_unlock(tsdn, prev); + + if (can_coalesce && !extent_coalesce(tsdn, arena, + r_extent_hooks, extents, extent, prev, false, + growing_retained)) { + extent = prev; + if (extents->delay_coalesce) { + /* Do minimal coalescing. */ + *coalesced = true; + return extent; + } + again = true; + } + } + } while (again); + + if (extents->delay_coalesce) { + *coalesced = false; + } + return extent; +} + +static void +extent_record(tsdn_t *tsdn, arena_t *arena, extent_hooks_t **r_extent_hooks, + extents_t *extents, extent_t *extent, bool growing_retained) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + assert((extents_state_get(extents) != extent_state_dirty && + extents_state_get(extents) != extent_state_muzzy) || + !extent_zeroed_get(extent)); + + malloc_mutex_lock(tsdn, &extents->mtx); + extent_hooks_assure_initialized(arena, r_extent_hooks); + + extent_szind_set(extent, NSIZES); + if (extent_slab_get(extent)) { + extent_interior_deregister(tsdn, rtree_ctx, extent); + extent_slab_set(extent, false); + } + + assert(rtree_extent_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_base_get(extent), true) == extent); + + if (!extents->delay_coalesce) { + extent = extent_try_coalesce(tsdn, arena, r_extent_hooks, + rtree_ctx, extents, extent, NULL, growing_retained); + } + + extent_deactivate_locked(tsdn, arena, extents, extent, false); + + malloc_mutex_unlock(tsdn, &extents->mtx); +} + +void +extent_dalloc_gap(tsdn_t *tsdn, arena_t *arena, extent_t *extent) { + extent_hooks_t *extent_hooks = EXTENT_HOOKS_INITIALIZER; + + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + if (extent_register(tsdn, extent)) { + extents_leak(tsdn, arena, &extent_hooks, + &arena->extents_retained, extent, false); + return; + } + extent_dalloc_wrapper(tsdn, arena, &extent_hooks, extent); +} + +static bool +extent_dalloc_default_impl(void *addr, size_t size) { + if (!have_dss || !extent_in_dss(addr)) { + return extent_dalloc_mmap(addr, size); + } + return true; +} + +static bool +extent_dalloc_default(extent_hooks_t *extent_hooks, void *addr, size_t size, + bool committed, unsigned arena_ind) { + return extent_dalloc_default_impl(addr, size); +} + +static bool +extent_dalloc_wrapper_try(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent) { + bool err; + + assert(extent_base_get(extent) != NULL); + assert(extent_size_get(extent) != 0); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + extent_addr_set(extent, extent_base_get(extent)); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + /* Try to deallocate. */ + if (*r_extent_hooks == &extent_hooks_default) { + /* Call directly to propagate tsdn. */ + err = extent_dalloc_default_impl(extent_base_get(extent), + extent_size_get(extent)); + } else { + extent_hook_pre_reentrancy(tsdn, arena); + err = ((*r_extent_hooks)->dalloc == NULL || + (*r_extent_hooks)->dalloc(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), + extent_committed_get(extent), arena_ind_get(arena))); + extent_hook_post_reentrancy(tsdn); + } + + if (!err) { + extent_dalloc(tsdn, arena, extent); + } + + return err; +} + +void +extent_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + /* + * Deregister first to avoid a race with other allocating threads, and + * reregister if deallocation fails. + */ + extent_deregister(tsdn, extent); + if (!extent_dalloc_wrapper_try(tsdn, arena, r_extent_hooks, extent)) { + return; + } + + extent_reregister(tsdn, extent); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_pre_reentrancy(tsdn, arena); + } + /* Try to decommit; purge if that fails. */ + bool zeroed; + if (!extent_committed_get(extent)) { + zeroed = true; + } else if (!extent_decommit_wrapper(tsdn, arena, r_extent_hooks, extent, + 0, extent_size_get(extent))) { + zeroed = true; + } else if ((*r_extent_hooks)->purge_forced != NULL && + !(*r_extent_hooks)->purge_forced(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), 0, + extent_size_get(extent), arena_ind_get(arena))) { + zeroed = true; + } else if (extent_state_get(extent) == extent_state_muzzy || + ((*r_extent_hooks)->purge_lazy != NULL && + !(*r_extent_hooks)->purge_lazy(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), 0, + extent_size_get(extent), arena_ind_get(arena)))) { + zeroed = false; + } else { + zeroed = false; + } + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_post_reentrancy(tsdn); + } + extent_zeroed_set(extent, zeroed); + + if (config_prof) { + extent_gdump_sub(tsdn, extent); + } + + extent_record(tsdn, arena, r_extent_hooks, &arena->extents_retained, + extent, false); +} + +static void +extent_destroy_default_impl(void *addr, size_t size) { + if (!have_dss || !extent_in_dss(addr)) { + pages_unmap(addr, size); + } +} + +static void +extent_destroy_default(extent_hooks_t *extent_hooks, void *addr, size_t size, + bool committed, unsigned arena_ind) { + extent_destroy_default_impl(addr, size); +} + +void +extent_destroy_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent) { + assert(extent_base_get(extent) != NULL); + assert(extent_size_get(extent) != 0); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + /* Deregister first to avoid a race with other allocating threads. */ + extent_deregister(tsdn, extent); + + extent_addr_set(extent, extent_base_get(extent)); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + /* Try to destroy; silently fail otherwise. */ + if (*r_extent_hooks == &extent_hooks_default) { + /* Call directly to propagate tsdn. */ + extent_destroy_default_impl(extent_base_get(extent), + extent_size_get(extent)); + } else if ((*r_extent_hooks)->destroy != NULL) { + extent_hook_pre_reentrancy(tsdn, arena); + (*r_extent_hooks)->destroy(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), + extent_committed_get(extent), arena_ind_get(arena)); + extent_hook_post_reentrancy(tsdn); + } + + extent_dalloc(tsdn, arena, extent); +} + +static bool +extent_commit_default(extent_hooks_t *extent_hooks, void *addr, size_t size, + size_t offset, size_t length, unsigned arena_ind) { + return pages_commit((void *)((uintptr_t)addr + (uintptr_t)offset), + length); +} + +static bool +extent_commit_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length, bool growing_retained) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_pre_reentrancy(tsdn, arena); + } + bool err = ((*r_extent_hooks)->commit == NULL || + (*r_extent_hooks)->commit(*r_extent_hooks, extent_base_get(extent), + extent_size_get(extent), offset, length, arena_ind_get(arena))); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_post_reentrancy(tsdn); + } + extent_committed_set(extent, extent_committed_get(extent) || !err); + return err; +} + +bool +extent_commit_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length) { + return extent_commit_impl(tsdn, arena, r_extent_hooks, extent, offset, + length, false); +} + +static bool +extent_decommit_default(extent_hooks_t *extent_hooks, void *addr, size_t size, + size_t offset, size_t length, unsigned arena_ind) { + return pages_decommit((void *)((uintptr_t)addr + (uintptr_t)offset), + length); +} + +bool +extent_decommit_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_pre_reentrancy(tsdn, arena); + } + bool err = ((*r_extent_hooks)->decommit == NULL || + (*r_extent_hooks)->decommit(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), offset, length, + arena_ind_get(arena))); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_post_reentrancy(tsdn); + } + extent_committed_set(extent, extent_committed_get(extent) && err); + return err; +} + +#ifdef PAGES_CAN_PURGE_LAZY +static bool +extent_purge_lazy_default(extent_hooks_t *extent_hooks, void *addr, size_t size, + size_t offset, size_t length, unsigned arena_ind) { + assert(addr != NULL); + assert((offset & PAGE_MASK) == 0); + assert(length != 0); + assert((length & PAGE_MASK) == 0); + + return pages_purge_lazy((void *)((uintptr_t)addr + (uintptr_t)offset), + length); +} +#endif + +static bool +extent_purge_lazy_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length, bool growing_retained) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + + if ((*r_extent_hooks)->purge_lazy == NULL) { + return true; + } + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_pre_reentrancy(tsdn, arena); + } + bool err = (*r_extent_hooks)->purge_lazy(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), offset, length, + arena_ind_get(arena)); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_post_reentrancy(tsdn); + } + + return err; +} + +bool +extent_purge_lazy_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length) { + return extent_purge_lazy_impl(tsdn, arena, r_extent_hooks, extent, + offset, length, false); +} + +#ifdef PAGES_CAN_PURGE_FORCED +static bool +extent_purge_forced_default(extent_hooks_t *extent_hooks, void *addr, + size_t size, size_t offset, size_t length, unsigned arena_ind) { + assert(addr != NULL); + assert((offset & PAGE_MASK) == 0); + assert(length != 0); + assert((length & PAGE_MASK) == 0); + + return pages_purge_forced((void *)((uintptr_t)addr + + (uintptr_t)offset), length); +} +#endif + +static bool +extent_purge_forced_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length, bool growing_retained) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + + if ((*r_extent_hooks)->purge_forced == NULL) { + return true; + } + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_pre_reentrancy(tsdn, arena); + } + bool err = (*r_extent_hooks)->purge_forced(*r_extent_hooks, + extent_base_get(extent), extent_size_get(extent), offset, length, + arena_ind_get(arena)); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_post_reentrancy(tsdn); + } + return err; +} + +bool +extent_purge_forced_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length) { + return extent_purge_forced_impl(tsdn, arena, r_extent_hooks, extent, + offset, length, false); +} + +#ifdef JEMALLOC_MAPS_COALESCE +static bool +extent_split_default(extent_hooks_t *extent_hooks, void *addr, size_t size, + size_t size_a, size_t size_b, bool committed, unsigned arena_ind) { + return !maps_coalesce; +} +#endif + +static extent_t * +extent_split_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t size_a, + szind_t szind_a, bool slab_a, size_t size_b, szind_t szind_b, bool slab_b, + bool growing_retained) { + assert(extent_size_get(extent) == size_a + size_b); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + + if ((*r_extent_hooks)->split == NULL) { + return NULL; + } + + extent_t *trail = extent_alloc(tsdn, arena); + if (trail == NULL) { + goto label_error_a; + } + + extent_init(trail, arena, (void *)((uintptr_t)extent_base_get(extent) + + size_a), size_b, slab_b, szind_b, extent_sn_get(extent), + extent_state_get(extent), extent_zeroed_get(extent), + extent_committed_get(extent)); + + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + rtree_leaf_elm_t *lead_elm_a, *lead_elm_b; + { + extent_t lead; + + extent_init(&lead, arena, extent_addr_get(extent), size_a, + slab_a, szind_a, extent_sn_get(extent), + extent_state_get(extent), extent_zeroed_get(extent), + extent_committed_get(extent)); + + extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, &lead, false, + true, &lead_elm_a, &lead_elm_b); + } + rtree_leaf_elm_t *trail_elm_a, *trail_elm_b; + extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, trail, false, true, + &trail_elm_a, &trail_elm_b); + + if (lead_elm_a == NULL || lead_elm_b == NULL || trail_elm_a == NULL + || trail_elm_b == NULL) { + goto label_error_b; + } + + extent_lock2(tsdn, extent, trail); + + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_pre_reentrancy(tsdn, arena); + } + bool err = (*r_extent_hooks)->split(*r_extent_hooks, extent_base_get(extent), + size_a + size_b, size_a, size_b, extent_committed_get(extent), + arena_ind_get(arena)); + if (*r_extent_hooks != &extent_hooks_default) { + extent_hook_post_reentrancy(tsdn); + } + if (err) { + goto label_error_c; + } + + extent_size_set(extent, size_a); + extent_szind_set(extent, szind_a); + + extent_rtree_write_acquired(tsdn, lead_elm_a, lead_elm_b, extent, + szind_a, slab_a); + extent_rtree_write_acquired(tsdn, trail_elm_a, trail_elm_b, trail, + szind_b, slab_b); + + extent_unlock2(tsdn, extent, trail); + + return trail; +label_error_c: + extent_unlock2(tsdn, extent, trail); +label_error_b: + extent_dalloc(tsdn, arena, trail); +label_error_a: + return NULL; +} + +extent_t * +extent_split_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t size_a, + szind_t szind_a, bool slab_a, size_t size_b, szind_t szind_b, bool slab_b) { + return extent_split_impl(tsdn, arena, r_extent_hooks, extent, size_a, + szind_a, slab_a, size_b, szind_b, slab_b, false); +} + +static bool +extent_merge_default_impl(void *addr_a, void *addr_b) { + if (!maps_coalesce) { + return true; + } + if (have_dss && !extent_dss_mergeable(addr_a, addr_b)) { + return true; + } + + return false; +} + +#ifdef JEMALLOC_MAPS_COALESCE +static bool +extent_merge_default(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a, + void *addr_b, size_t size_b, bool committed, unsigned arena_ind) { + return extent_merge_default_impl(addr_a, addr_b); +} +#endif + +static bool +extent_merge_impl(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *a, extent_t *b, + bool growing_retained) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, growing_retained ? 1 : 0); + + extent_hooks_assure_initialized(arena, r_extent_hooks); + + if ((*r_extent_hooks)->merge == NULL) { + return true; + } + + bool err; + if (*r_extent_hooks == &extent_hooks_default) { + /* Call directly to propagate tsdn. */ + err = extent_merge_default_impl(extent_base_get(a), + extent_base_get(b)); + } else { + extent_hook_pre_reentrancy(tsdn, arena); + err = (*r_extent_hooks)->merge(*r_extent_hooks, + extent_base_get(a), extent_size_get(a), extent_base_get(b), + extent_size_get(b), extent_committed_get(a), + arena_ind_get(arena)); + extent_hook_post_reentrancy(tsdn); + } + + if (err) { + return true; + } + + /* + * The rtree writes must happen while all the relevant elements are + * owned, so the following code uses decomposed helper functions rather + * than extent_{,de}register() to do things in the right order. + */ + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + rtree_leaf_elm_t *a_elm_a, *a_elm_b, *b_elm_a, *b_elm_b; + extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, a, true, false, &a_elm_a, + &a_elm_b); + extent_rtree_leaf_elms_lookup(tsdn, rtree_ctx, b, true, false, &b_elm_a, + &b_elm_b); + + extent_lock2(tsdn, a, b); + + if (a_elm_b != NULL) { + rtree_leaf_elm_write(tsdn, &extents_rtree, a_elm_b, NULL, + NSIZES, false); + } + if (b_elm_b != NULL) { + rtree_leaf_elm_write(tsdn, &extents_rtree, b_elm_a, NULL, + NSIZES, false); + } else { + b_elm_b = b_elm_a; + } + + extent_size_set(a, extent_size_get(a) + extent_size_get(b)); + extent_szind_set(a, NSIZES); + extent_sn_set(a, (extent_sn_get(a) < extent_sn_get(b)) ? + extent_sn_get(a) : extent_sn_get(b)); + extent_zeroed_set(a, extent_zeroed_get(a) && extent_zeroed_get(b)); + + extent_rtree_write_acquired(tsdn, a_elm_a, b_elm_b, a, NSIZES, false); + + extent_unlock2(tsdn, a, b); + + extent_dalloc(tsdn, extent_arena_get(b), b); + + return false; +} + +bool +extent_merge_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *a, extent_t *b) { + return extent_merge_impl(tsdn, arena, r_extent_hooks, a, b, false); +} + +bool +extent_boot(void) { + if (rtree_new(&extents_rtree, true)) { + return true; + } + + if (mutex_pool_init(&extent_mutex_pool, "extent_mutex_pool", + WITNESS_RANK_EXTENT_POOL)) { + return true; + } + + if (have_dss) { + extent_dss_boot(); + } + + return false; +} diff --git a/deps/jemalloc/src/hash.c b/deps/jemalloc/src/hash.c index cfa4da0275..7b2bdc2bd6 100644 --- a/deps/jemalloc/src/hash.c +++ b/deps/jemalloc/src/hash.c @@ -1,2 +1,3 @@ -#define JEMALLOC_HASH_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_HASH_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" diff --git a/deps/jemalloc/src/jemalloc.c b/deps/jemalloc/src/jemalloc.c index 204778bc89..0ee8ad48b9 100644 --- a/deps/jemalloc/src/jemalloc.c +++ b/deps/jemalloc/src/jemalloc.c @@ -1,15 +1,31 @@ -#define JEMALLOC_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/ctl.h" +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/rtree.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/spin.h" +#include "jemalloc/internal/sz.h" +#include "jemalloc/internal/ticker.h" +#include "jemalloc/internal/util.h" /******************************************************************************/ /* Data. */ -malloc_tsd_data(, arenas, arena_t *, NULL) -malloc_tsd_data(, thread_allocated, thread_allocated_t, - THREAD_ALLOCATED_INITIALIZER) - /* Runtime configuration options. */ -const char *je_malloc_conf; +const char *je_malloc_conf +#ifndef _WIN32 + JEMALLOC_ATTR(weak) +#endif + ; bool opt_abort = #ifdef JEMALLOC_DEBUG true @@ -17,30 +33,80 @@ bool opt_abort = false #endif ; -bool opt_junk = +bool opt_abort_conf = +#ifdef JEMALLOC_DEBUG + true +#else + false +#endif + ; +const char *opt_junk = +#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) + "true" +#else + "false" +#endif + ; +bool opt_junk_alloc = +#if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) + true +#else + false +#endif + ; +bool opt_junk_free = #if (defined(JEMALLOC_DEBUG) && defined(JEMALLOC_FILL)) true #else false #endif ; -size_t opt_quarantine = ZU(0); -bool opt_redzone = false; + bool opt_utrace = false; -bool opt_valgrind = false; bool opt_xmalloc = false; bool opt_zero = false; -size_t opt_narenas = 0; +unsigned opt_narenas = 0; unsigned ncpus; -malloc_mutex_t arenas_lock; -arena_t **arenas; -unsigned narenas_total; -unsigned narenas_auto; - -/* Set to true once the allocator has been initialized. */ -static bool malloc_initialized = false; +/* Protects arenas initialization. */ +malloc_mutex_t arenas_lock; +/* + * Arenas that are used to service external requests. Not all elements of the + * arenas array are necessarily used; arenas are created lazily as needed. + * + * arenas[0..narenas_auto) are used for automatic multiplexing of threads and + * arenas. arenas[narenas_auto..narenas_total) are only used if the application + * takes some action to create them and allocate from them. + * + * Points to an arena_t. + */ +JEMALLOC_ALIGNED(CACHELINE) +atomic_p_t arenas[MALLOCX_ARENA_LIMIT]; +static atomic_u_t narenas_total; /* Use narenas_total_*(). */ +static arena_t *a0; /* arenas[0]; read-only after initialization. */ +unsigned narenas_auto; /* Read-only after initialization. */ + +typedef enum { + malloc_init_uninitialized = 3, + malloc_init_a0_initialized = 2, + malloc_init_recursible = 1, + malloc_init_initialized = 0 /* Common case --> jnz. */ +} malloc_init_t; +static malloc_init_t malloc_init_state = malloc_init_uninitialized; + +/* False should be the common case. Set to true to trigger initialization. */ +bool malloc_slow = true; + +/* When malloc_slow is true, set the corresponding bits for sanity check. */ +enum { + flag_opt_junk_alloc = (1U), + flag_opt_junk_free = (1U << 1), + flag_opt_zero = (1U << 2), + flag_opt_utrace = (1U << 3), + flag_opt_xmalloc = (1U << 4) +}; +static uint8_t malloc_slow_flags; #ifdef JEMALLOC_THREADED_INIT /* Used to let the initializing thread recursively allocate. */ @@ -57,14 +123,30 @@ static bool malloc_initializer = NO_INITIALIZER; /* Used to avoid initialization races. */ #ifdef _WIN32 +#if _WIN32_WINNT >= 0x0600 +static malloc_mutex_t init_lock = SRWLOCK_INIT; +#else static malloc_mutex_t init_lock; +static bool init_lock_initialized = false; JEMALLOC_ATTR(constructor) static void WINAPI -_init_init_lock(void) -{ - - malloc_mutex_init(&init_lock); +_init_init_lock(void) { + /* + * If another constructor in the same binary is using mallctl to e.g. + * set up extent hooks, it may end up running before this one, and + * malloc_init_hard will crash trying to lock the uninitialized lock. So + * we force an initialization of the lock in malloc_init_hard as well. + * We don't try to care about atomicity of the accessed to the + * init_lock_initialized boolean, since it really only matters early in + * the process creation, before any separate thread normally starts + * doing anything. + */ + if (!init_lock_initialized) { + malloc_mutex_init(&init_lock, "init", WITNESS_RANK_INIT, + malloc_mutex_rank_exclusive); + } + init_lock_initialized = true; } #ifdef _MSC_VER @@ -72,7 +154,7 @@ _init_init_lock(void) JEMALLOC_SECTION(".CRT$XCU") JEMALLOC_ATTR(used) static const void (WINAPI *init_init_lock)(void) = _init_init_lock; #endif - +#endif #else static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER; #endif @@ -85,7 +167,7 @@ typedef struct { #ifdef JEMALLOC_UTRACE # define UTRACE(a, b, c) do { \ - if (opt_utrace) { \ + if (unlikely(opt_utrace)) { \ int utrace_serrno = errno; \ malloc_utrace_t ut; \ ut.p = (a); \ @@ -99,12 +181,16 @@ typedef struct { # define UTRACE(a, b, c) #endif +/* Whether encountered any invalid config options. */ +static bool had_conf_error = false; + /******************************************************************************/ /* * Function prototypes for static functions that are referenced prior to * definition. */ +static bool malloc_init_hard_a0(void); static bool malloc_init_hard(void); /******************************************************************************/ @@ -112,54 +198,337 @@ static bool malloc_init_hard(void); * Begin miscellaneous support functions. */ +bool +malloc_initialized(void) { + return (malloc_init_state == malloc_init_initialized); +} + +JEMALLOC_ALWAYS_INLINE bool +malloc_init_a0(void) { + if (unlikely(malloc_init_state == malloc_init_uninitialized)) { + return malloc_init_hard_a0(); + } + return false; +} + +JEMALLOC_ALWAYS_INLINE bool +malloc_init(void) { + if (unlikely(!malloc_initialized()) && malloc_init_hard()) { + return true; + } + return false; +} + +/* + * The a0*() functions are used instead of i{d,}alloc() in situations that + * cannot tolerate TLS variable access. + */ + +static void * +a0ialloc(size_t size, bool zero, bool is_internal) { + if (unlikely(malloc_init_a0())) { + return NULL; + } + + return iallocztm(TSDN_NULL, size, sz_size2index(size), zero, NULL, + is_internal, arena_get(TSDN_NULL, 0, true), true); +} + +static void +a0idalloc(void *ptr, bool is_internal) { + idalloctm(TSDN_NULL, ptr, NULL, NULL, is_internal, true); +} + +void * +a0malloc(size_t size) { + return a0ialloc(size, false, true); +} + +void +a0dalloc(void *ptr) { + a0idalloc(ptr, true); +} + +/* + * FreeBSD's libc uses the bootstrap_*() functions in bootstrap-senstive + * situations that cannot tolerate TLS variable access (TLS allocation and very + * early internal data structure initialization). + */ + +void * +bootstrap_malloc(size_t size) { + if (unlikely(size == 0)) { + size = 1; + } + + return a0ialloc(size, false, false); +} + +void * +bootstrap_calloc(size_t num, size_t size) { + size_t num_size; + + num_size = num * size; + if (unlikely(num_size == 0)) { + assert(num == 0 || size == 0); + num_size = 1; + } + + return a0ialloc(num_size, true, false); +} + +void +bootstrap_free(void *ptr) { + if (unlikely(ptr == NULL)) { + return; + } + + a0idalloc(ptr, false); +} + +void +arena_set(unsigned ind, arena_t *arena) { + atomic_store_p(&arenas[ind], arena, ATOMIC_RELEASE); +} + +static void +narenas_total_set(unsigned narenas) { + atomic_store_u(&narenas_total, narenas, ATOMIC_RELEASE); +} + +static void +narenas_total_inc(void) { + atomic_fetch_add_u(&narenas_total, 1, ATOMIC_RELEASE); +} + +unsigned +narenas_total_get(void) { + return atomic_load_u(&narenas_total, ATOMIC_ACQUIRE); +} + /* Create a new arena and insert it into the arenas array at index ind. */ +static arena_t * +arena_init_locked(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { + arena_t *arena; + + assert(ind <= narenas_total_get()); + if (ind >= MALLOCX_ARENA_LIMIT) { + return NULL; + } + if (ind == narenas_total_get()) { + narenas_total_inc(); + } + + /* + * Another thread may have already initialized arenas[ind] if it's an + * auto arena. + */ + arena = arena_get(tsdn, ind, false); + if (arena != NULL) { + assert(ind < narenas_auto); + return arena; + } + + /* Actually initialize the arena. */ + arena = arena_new(tsdn, ind, extent_hooks); + + return arena; +} + +static void +arena_new_create_background_thread(tsdn_t *tsdn, unsigned ind) { + if (ind == 0) { + return; + } + if (have_background_thread) { + bool err; + malloc_mutex_lock(tsdn, &background_thread_lock); + err = background_thread_create(tsdn_tsd(tsdn), ind); + malloc_mutex_unlock(tsdn, &background_thread_lock); + if (err) { + malloc_printf("<jemalloc>: error in background thread " + "creation for arena %u. Abort.\n", ind); + abort(); + } + } +} + arena_t * -arenas_extend(unsigned ind) -{ - arena_t *ret; +arena_init(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks) { + arena_t *arena; + + malloc_mutex_lock(tsdn, &arenas_lock); + arena = arena_init_locked(tsdn, ind, extent_hooks); + malloc_mutex_unlock(tsdn, &arenas_lock); + + arena_new_create_background_thread(tsdn, ind); + + return arena; +} + +static void +arena_bind(tsd_t *tsd, unsigned ind, bool internal) { + arena_t *arena = arena_get(tsd_tsdn(tsd), ind, false); + arena_nthreads_inc(arena, internal); + + if (internal) { + tsd_iarena_set(tsd, arena); + } else { + tsd_arena_set(tsd, arena); + } +} - ret = (arena_t *)base_alloc(sizeof(arena_t)); - if (ret != NULL && arena_new(ret, ind) == false) { - arenas[ind] = ret; - return (ret); +void +arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind) { + arena_t *oldarena, *newarena; + + oldarena = arena_get(tsd_tsdn(tsd), oldind, false); + newarena = arena_get(tsd_tsdn(tsd), newind, false); + arena_nthreads_dec(oldarena, false); + arena_nthreads_inc(newarena, false); + tsd_arena_set(tsd, newarena); +} + +static void +arena_unbind(tsd_t *tsd, unsigned ind, bool internal) { + arena_t *arena; + + arena = arena_get(tsd_tsdn(tsd), ind, false); + arena_nthreads_dec(arena, internal); + + if (internal) { + tsd_iarena_set(tsd, NULL); + } else { + tsd_arena_set(tsd, NULL); } - /* Only reached if there is an OOM error. */ +} + +arena_tdata_t * +arena_tdata_get_hard(tsd_t *tsd, unsigned ind) { + arena_tdata_t *tdata, *arenas_tdata_old; + arena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd); + unsigned narenas_tdata_old, i; + unsigned narenas_tdata = tsd_narenas_tdata_get(tsd); + unsigned narenas_actual = narenas_total_get(); /* - * OOM here is quite inconvenient to propagate, since dealing with it - * would require a check for failure in the fast path. Instead, punt - * by using arenas[0]. In practice, this is an extremely unlikely - * failure. + * Dissociate old tdata array (and set up for deallocation upon return) + * if it's too small. */ - malloc_write("<jemalloc>: Error initializing arena\n"); - if (opt_abort) - abort(); + if (arenas_tdata != NULL && narenas_tdata < narenas_actual) { + arenas_tdata_old = arenas_tdata; + narenas_tdata_old = narenas_tdata; + arenas_tdata = NULL; + narenas_tdata = 0; + tsd_arenas_tdata_set(tsd, arenas_tdata); + tsd_narenas_tdata_set(tsd, narenas_tdata); + } else { + arenas_tdata_old = NULL; + narenas_tdata_old = 0; + } + + /* Allocate tdata array if it's missing. */ + if (arenas_tdata == NULL) { + bool *arenas_tdata_bypassp = tsd_arenas_tdata_bypassp_get(tsd); + narenas_tdata = (ind < narenas_actual) ? narenas_actual : ind+1; - return (arenas[0]); + if (tsd_nominal(tsd) && !*arenas_tdata_bypassp) { + *arenas_tdata_bypassp = true; + arenas_tdata = (arena_tdata_t *)a0malloc( + sizeof(arena_tdata_t) * narenas_tdata); + *arenas_tdata_bypassp = false; + } + if (arenas_tdata == NULL) { + tdata = NULL; + goto label_return; + } + assert(tsd_nominal(tsd) && !*arenas_tdata_bypassp); + tsd_arenas_tdata_set(tsd, arenas_tdata); + tsd_narenas_tdata_set(tsd, narenas_tdata); + } + + /* + * Copy to tdata array. It's possible that the actual number of arenas + * has increased since narenas_total_get() was called above, but that + * causes no correctness issues unless two threads concurrently execute + * the arenas.create mallctl, which we trust mallctl synchronization to + * prevent. + */ + + /* Copy/initialize tickers. */ + for (i = 0; i < narenas_actual; i++) { + if (i < narenas_tdata_old) { + ticker_copy(&arenas_tdata[i].decay_ticker, + &arenas_tdata_old[i].decay_ticker); + } else { + ticker_init(&arenas_tdata[i].decay_ticker, + DECAY_NTICKS_PER_UPDATE); + } + } + if (narenas_tdata > narenas_actual) { + memset(&arenas_tdata[narenas_actual], 0, sizeof(arena_tdata_t) + * (narenas_tdata - narenas_actual)); + } + + /* Read the refreshed tdata array. */ + tdata = &arenas_tdata[ind]; +label_return: + if (arenas_tdata_old != NULL) { + a0dalloc(arenas_tdata_old); + } + return tdata; } -/* Slow path, called only by choose_arena(). */ +/* Slow path, called only by arena_choose(). */ arena_t * -choose_arena_hard(void) -{ - arena_t *ret; +arena_choose_hard(tsd_t *tsd, bool internal) { + arena_t *ret JEMALLOC_CC_SILENCE_INIT(NULL); + + if (have_percpu_arena && PERCPU_ARENA_ENABLED(opt_percpu_arena)) { + unsigned choose = percpu_arena_choose(); + ret = arena_get(tsd_tsdn(tsd), choose, true); + assert(ret != NULL); + arena_bind(tsd, arena_ind_get(ret), false); + arena_bind(tsd, arena_ind_get(ret), true); + + return ret; + } if (narenas_auto > 1) { - unsigned i, choose, first_null; + unsigned i, j, choose[2], first_null; + bool is_new_arena[2]; + + /* + * Determine binding for both non-internal and internal + * allocation. + * + * choose[0]: For application allocation. + * choose[1]: For internal metadata allocation. + */ + + for (j = 0; j < 2; j++) { + choose[j] = 0; + is_new_arena[j] = false; + } - choose = 0; first_null = narenas_auto; - malloc_mutex_lock(&arenas_lock); - assert(arenas[0] != NULL); + malloc_mutex_lock(tsd_tsdn(tsd), &arenas_lock); + assert(arena_get(tsd_tsdn(tsd), 0, false) != NULL); for (i = 1; i < narenas_auto; i++) { - if (arenas[i] != NULL) { + if (arena_get(tsd_tsdn(tsd), i, false) != NULL) { /* * Choose the first arena that has the lowest * number of threads assigned to it. */ - if (arenas[i]->nthreads < - arenas[choose]->nthreads) - choose = i; + for (j = 0; j < 2; j++) { + if (arena_nthreads_get(arena_get( + tsd_tsdn(tsd), i, false), !!j) < + arena_nthreads_get(arena_get( + tsd_tsdn(tsd), choose[j], false), + !!j)) { + choose[j] = i; + } + } } else if (first_null == narenas_auto) { /* * Record the index of the first uninitialized @@ -174,38 +543,99 @@ choose_arena_hard(void) } } - if (arenas[choose]->nthreads == 0 - || first_null == narenas_auto) { - /* - * Use an unloaded arena, or the least loaded arena if - * all arenas are already initialized. - */ - ret = arenas[choose]; - } else { - /* Initialize a new arena. */ - ret = arenas_extend(first_null); + for (j = 0; j < 2; j++) { + if (arena_nthreads_get(arena_get(tsd_tsdn(tsd), + choose[j], false), !!j) == 0 || first_null == + narenas_auto) { + /* + * Use an unloaded arena, or the least loaded + * arena if all arenas are already initialized. + */ + if (!!j == internal) { + ret = arena_get(tsd_tsdn(tsd), + choose[j], false); + } + } else { + arena_t *arena; + + /* Initialize a new arena. */ + choose[j] = first_null; + arena = arena_init_locked(tsd_tsdn(tsd), + choose[j], + (extent_hooks_t *)&extent_hooks_default); + if (arena == NULL) { + malloc_mutex_unlock(tsd_tsdn(tsd), + &arenas_lock); + return NULL; + } + is_new_arena[j] = true; + if (!!j == internal) { + ret = arena; + } + } + arena_bind(tsd, choose[j], !!j); + } + malloc_mutex_unlock(tsd_tsdn(tsd), &arenas_lock); + + for (j = 0; j < 2; j++) { + if (is_new_arena[j]) { + assert(choose[j] > 0); + arena_new_create_background_thread( + tsd_tsdn(tsd), choose[j]); + } } - ret->nthreads++; - malloc_mutex_unlock(&arenas_lock); + } else { - ret = arenas[0]; - malloc_mutex_lock(&arenas_lock); - ret->nthreads++; - malloc_mutex_unlock(&arenas_lock); + ret = arena_get(tsd_tsdn(tsd), 0, false); + arena_bind(tsd, 0, false); + arena_bind(tsd, 0, true); + } + + return ret; +} + +void +iarena_cleanup(tsd_t *tsd) { + arena_t *iarena; + + iarena = tsd_iarena_get(tsd); + if (iarena != NULL) { + arena_unbind(tsd, arena_ind_get(iarena), true); } +} - arenas_tsd_set(&ret); +void +arena_cleanup(tsd_t *tsd) { + arena_t *arena; - return (ret); + arena = tsd_arena_get(tsd); + if (arena != NULL) { + arena_unbind(tsd, arena_ind_get(arena), false); + } } -static void -stats_print_atexit(void) -{ +void +arenas_tdata_cleanup(tsd_t *tsd) { + arena_tdata_t *arenas_tdata; - if (config_tcache && config_stats) { + /* Prevent tsd->arenas_tdata from being (re)created. */ + *tsd_arenas_tdata_bypassp_get(tsd) = true; + + arenas_tdata = tsd_arenas_tdata_get(tsd); + if (arenas_tdata != NULL) { + tsd_arenas_tdata_set(tsd, NULL); + a0dalloc(arenas_tdata); + } +} + +static void +stats_print_atexit(void) { + if (config_stats) { + tsdn_t *tsdn; unsigned narenas, i; + tsdn = tsdn_fetch(); + /* * Merge stats from extant threads. This is racy, since * individual threads do not lock when recording tcache stats @@ -214,25 +644,45 @@ stats_print_atexit(void) * continue to allocate. */ for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { - arena_t *arena = arenas[i]; + arena_t *arena = arena_get(tsdn, i, false); if (arena != NULL) { tcache_t *tcache; - /* - * tcache_stats_merge() locks bins, so if any - * code is introduced that acquires both arena - * and bin locks in the opposite order, - * deadlocks may result. - */ - malloc_mutex_lock(&arena->lock); + malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); ql_foreach(tcache, &arena->tcache_ql, link) { - tcache_stats_merge(tcache, arena); + tcache_stats_merge(tsdn, tcache, arena); } - malloc_mutex_unlock(&arena->lock); + malloc_mutex_unlock(tsdn, + &arena->tcache_ql_mtx); } } } - je_malloc_stats_print(NULL, NULL, NULL); + je_malloc_stats_print(NULL, NULL, opt_stats_print_opts); +} + +/* + * Ensure that we don't hold any locks upon entry to or exit from allocator + * code (in a "broad" sense that doesn't count a reentrant allocation as an + * entrance or exit). + */ +JEMALLOC_ALWAYS_INLINE void +check_entry_exit_locking(tsdn_t *tsdn) { + if (!config_debug) { + return; + } + if (tsdn_null(tsdn)) { + return; + } + tsd_t *tsd = tsdn_tsd(tsdn); + /* + * It's possible we hold locks at entry/exit if we're in a nested + * allocation. + */ + int8_t reentrancy_level = tsd_reentrancy_level_get(tsd); + if (reentrancy_level != 0) { + return; + } + witness_assert_lockless(tsdn_witness_tsdp_get(tsdn)); } /* @@ -243,69 +693,82 @@ stats_print_atexit(void) * Begin initialization functions. */ +static char * +jemalloc_secure_getenv(const char *name) { +#ifdef JEMALLOC_HAVE_SECURE_GETENV + return secure_getenv(name); +#else +# ifdef JEMALLOC_HAVE_ISSETUGID + if (issetugid() != 0) { + return NULL; + } +# endif + return getenv(name); +#endif +} + static unsigned -malloc_ncpus(void) -{ +malloc_ncpus(void) { long result; #ifdef _WIN32 SYSTEM_INFO si; GetSystemInfo(&si); result = si.dwNumberOfProcessors; +#elif defined(JEMALLOC_GLIBC_MALLOC_HOOK) && defined(CPU_COUNT) + /* + * glibc >= 2.6 has the CPU_COUNT macro. + * + * glibc's sysconf() uses isspace(). glibc allocates for the first time + * *before* setting up the isspace tables. Therefore we need a + * different method to get the number of CPUs. + */ + { + cpu_set_t set; + + pthread_getaffinity_np(pthread_self(), sizeof(set), &set); + result = CPU_COUNT(&set); + } #else result = sysconf(_SC_NPROCESSORS_ONLN); #endif return ((result == -1) ? 1 : (unsigned)result); } -void -arenas_cleanup(void *arg) -{ - arena_t *arena = *(arena_t **)arg; - - malloc_mutex_lock(&arenas_lock); - arena->nthreads--; - malloc_mutex_unlock(&arenas_lock); -} - -JEMALLOC_ALWAYS_INLINE_C void -malloc_thread_init(void) -{ - - /* - * TSD initialization can't be safely done as a side effect of - * deallocation, because it is possible for a thread to do nothing but - * deallocate its TLS data via free(), in which case writing to TLS - * would cause write-after-free memory corruption. The quarantine - * facility *only* gets used as a side effect of deallocation, so make - * a best effort attempt at initializing its TSD by hooking all - * allocation events. - */ - if (config_fill && opt_quarantine) - quarantine_alloc_hook(); -} - -JEMALLOC_ALWAYS_INLINE_C bool -malloc_init(void) -{ +static void +init_opt_stats_print_opts(const char *v, size_t vlen) { + size_t opts_len = strlen(opt_stats_print_opts); + assert(opts_len <= stats_print_tot_num_options); + + for (size_t i = 0; i < vlen; i++) { + switch (v[i]) { +#define OPTION(o, v, d, s) case o: break; + STATS_PRINT_OPTIONS +#undef OPTION + default: continue; + } - if (malloc_initialized == false && malloc_init_hard()) - return (true); - malloc_thread_init(); + if (strchr(opt_stats_print_opts, v[i]) != NULL) { + /* Ignore repeated. */ + continue; + } - return (false); + opt_stats_print_opts[opts_len++] = v[i]; + opt_stats_print_opts[opts_len] = '\0'; + assert(opts_len <= stats_print_tot_num_options); + } + assert(opts_len == strlen(opt_stats_print_opts)); } static bool malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, - char const **v_p, size_t *vlen_p) -{ + char const **v_p, size_t *vlen_p) { bool accept; const char *opts = *opts_p; *k_p = opts; - for (accept = false; accept == false;) { + for (accept = false; !accept;) { switch (*opts) { case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': @@ -333,14 +796,14 @@ malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, malloc_write("<jemalloc>: Conf string ends " "with key\n"); } - return (true); + return true; default: malloc_write("<jemalloc>: Malformed conf string\n"); - return (true); + return true; } } - for (accept = false; accept == false;) { + for (accept = false; !accept;) { switch (*opts) { case ',': opts++; @@ -369,46 +832,57 @@ malloc_conf_next(char const **opts_p, char const **k_p, size_t *klen_p, } *opts_p = opts; - return (false); + return false; } static void -malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v, - size_t vlen) -{ +malloc_abort_invalid_conf(void) { + assert(opt_abort_conf); + malloc_printf("<jemalloc>: Abort (abort_conf:true) on invalid conf " + "value (see above).\n"); + abort(); +} +static void +malloc_conf_error(const char *msg, const char *k, size_t klen, const char *v, + size_t vlen) { malloc_printf("<jemalloc>: %s: %.*s:%.*s\n", msg, (int)klen, k, (int)vlen, v); + had_conf_error = true; + if (opt_abort_conf) { + malloc_abort_invalid_conf(); + } } static void -malloc_conf_init(void) -{ +malloc_slow_flag_init(void) { + /* + * Combine the runtime options into malloc_slow for fast path. Called + * after processing all the options. + */ + malloc_slow_flags |= (opt_junk_alloc ? flag_opt_junk_alloc : 0) + | (opt_junk_free ? flag_opt_junk_free : 0) + | (opt_zero ? flag_opt_zero : 0) + | (opt_utrace ? flag_opt_utrace : 0) + | (opt_xmalloc ? flag_opt_xmalloc : 0); + + malloc_slow = (malloc_slow_flags != 0); +} + +static void +malloc_conf_init(void) { unsigned i; char buf[PATH_MAX + 1]; const char *opts, *k, *v; size_t klen, vlen; - /* - * Automatically configure valgrind before processing options. The - * valgrind option remains in jemalloc 3.x for compatibility reasons. - */ - if (config_valgrind) { - opt_valgrind = (RUNNING_ON_VALGRIND != 0) ? true : false; - if (config_fill && opt_valgrind) { - opt_junk = false; - assert(opt_zero == false); - opt_quarantine = JEMALLOC_VALGRIND_QUARANTINE_DEFAULT; - opt_redzone = true; - } - if (config_tcache && opt_valgrind) - opt_tcache = false; - } - - for (i = 0; i < 3; i++) { + for (i = 0; i < 4; i++) { /* Get runtime configuration. */ switch (i) { case 0: + opts = config_malloc_conf; + break; + case 1: if (je_malloc_conf != NULL) { /* * Use options that were compiled into the @@ -421,8 +895,8 @@ malloc_conf_init(void) opts = buf; } break; - case 1: { - int linklen = 0; + case 2: { + ssize_t linklen = 0; #ifndef _WIN32 int saved_errno = errno; const char *linkname = @@ -441,14 +915,14 @@ malloc_conf_init(void) if (linklen == -1) { /* No configuration specified. */ linklen = 0; - /* restore errno */ + /* Restore errno. */ set_errno(saved_errno); } #endif buf[linklen] = '\0'; opts = buf; break; - } case 2: { + } case 3: { const char *envname = #ifdef JEMALLOC_PREFIX JEMALLOC_CPREFIX"MALLOC_CONF" @@ -457,7 +931,7 @@ malloc_conf_init(void) #endif ; - if ((opts = getenv(envname)) != NULL) { + if ((opts = jemalloc_secure_getenv(envname)) != NULL) { /* * Do nothing; opts is already initialized to * the value of the MALLOC_CONF environment @@ -475,27 +949,31 @@ malloc_conf_init(void) opts = buf; } - while (*opts != '\0' && malloc_conf_next(&opts, &k, &klen, &v, - &vlen) == false) { -#define CONF_HANDLE_BOOL(o, n) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ - if (strncmp("true", v, vlen) == 0 && \ - vlen == sizeof("true")-1) \ + while (*opts != '\0' && !malloc_conf_next(&opts, &k, &klen, &v, + &vlen)) { +#define CONF_MATCH(n) \ + (sizeof(n)-1 == klen && strncmp(n, k, klen) == 0) +#define CONF_MATCH_VALUE(n) \ + (sizeof(n)-1 == vlen && strncmp(n, v, vlen) == 0) +#define CONF_HANDLE_BOOL(o, n) \ + if (CONF_MATCH(n)) { \ + if (CONF_MATCH_VALUE("true")) { \ o = true; \ - else if (strncmp("false", v, vlen) == \ - 0 && vlen == sizeof("false")-1) \ + } else if (CONF_MATCH_VALUE("false")) { \ o = false; \ - else { \ + } else { \ malloc_conf_error( \ "Invalid conf value", \ k, klen, v, vlen); \ } \ continue; \ } -#define CONF_HANDLE_SIZE_T(o, n, min, max, clip) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ +#define CONF_MIN_no(um, min) false +#define CONF_MIN_yes(um, min) ((um) < (min)) +#define CONF_MAX_no(um, max) false +#define CONF_MAX_yes(um, max) ((um) > (max)) +#define CONF_HANDLE_T_U(t, o, n, min, max, check_min, check_max, clip) \ + if (CONF_MATCH(n)) { \ uintmax_t um; \ char *end; \ \ @@ -507,27 +985,40 @@ malloc_conf_init(void) "Invalid conf value", \ k, klen, v, vlen); \ } else if (clip) { \ - if (min != 0 && um < min) \ - o = min; \ - else if (um > max) \ - o = max; \ - else \ - o = um; \ + if (CONF_MIN_##check_min(um, \ + (t)(min))) { \ + o = (t)(min); \ + } else if ( \ + CONF_MAX_##check_max(um, \ + (t)(max))) { \ + o = (t)(max); \ + } else { \ + o = (t)um; \ + } \ } else { \ - if ((min != 0 && um < min) || \ - um > max) { \ + if (CONF_MIN_##check_min(um, \ + (t)(min)) || \ + CONF_MAX_##check_max(um, \ + (t)(max))) { \ malloc_conf_error( \ "Out-of-range " \ "conf value", \ k, klen, v, vlen); \ - } else \ - o = um; \ + } else { \ + o = (t)um; \ + } \ } \ continue; \ } -#define CONF_HANDLE_SSIZE_T(o, n, min, max) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ +#define CONF_HANDLE_UNSIGNED(o, n, min, max, check_min, check_max, \ + clip) \ + CONF_HANDLE_T_U(unsigned, o, n, min, max, \ + check_min, check_max, clip) +#define CONF_HANDLE_SIZE_T(o, n, min, max, check_min, check_max, clip) \ + CONF_HANDLE_T_U(size_t, o, n, min, max, \ + check_min, check_max, clip) +#define CONF_HANDLE_SSIZE_T(o, n, min, max) \ + if (CONF_MATCH(n)) { \ long l; \ char *end; \ \ @@ -538,18 +1029,18 @@ malloc_conf_init(void) malloc_conf_error( \ "Invalid conf value", \ k, klen, v, vlen); \ - } else if (l < (ssize_t)min || l > \ - (ssize_t)max) { \ + } else if (l < (ssize_t)(min) || l > \ + (ssize_t)(max)) { \ malloc_conf_error( \ "Out-of-range conf value", \ k, klen, v, vlen); \ - } else \ + } else { \ o = l; \ + } \ continue; \ } -#define CONF_HANDLE_CHAR_P(o, n, d) \ - if (sizeof(n)-1 == klen && strncmp(n, k, \ - klen) == 0) { \ +#define CONF_HANDLE_CHAR_P(o, n, d) \ + if (CONF_MATCH(n)) { \ size_t cpylen = (vlen <= \ sizeof(o)-1) ? vlen : \ sizeof(o)-1; \ @@ -559,23 +1050,18 @@ malloc_conf_init(void) } CONF_HANDLE_BOOL(opt_abort, "abort") - /* - * Chunks always require at least one header page, plus - * one data page in the absence of redzones, or three - * pages in the presence of redzones. In order to - * simplify options processing, fix the limit based on - * config_fill. - */ - CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE + - (config_fill ? 2 : 1), (sizeof(size_t) << 3) - 1, - true) + CONF_HANDLE_BOOL(opt_abort_conf, "abort_conf") + if (opt_abort_conf && had_conf_error) { + malloc_abort_invalid_conf(); + } + CONF_HANDLE_BOOL(opt_retain, "retain") if (strncmp("dss", k, klen) == 0) { int i; bool match = false; for (i = 0; i < dss_prec_limit; i++) { if (strncmp(dss_prec_names[i], v, vlen) == 0) { - if (chunk_dss_prec_set(i)) { + if (extent_dss_prec_set(i)) { malloc_conf_error( "Error setting dss", k, klen, v, vlen); @@ -587,47 +1073,98 @@ malloc_conf_init(void) } } } - if (match == false) { + if (!match) { malloc_conf_error("Invalid conf value", k, klen, v, vlen); } continue; } - CONF_HANDLE_SIZE_T(opt_narenas, "narenas", 1, - SIZE_T_MAX, false) - CONF_HANDLE_SSIZE_T(opt_lg_dirty_mult, "lg_dirty_mult", - -1, (sizeof(size_t) << 3) - 1) + CONF_HANDLE_UNSIGNED(opt_narenas, "narenas", 1, + UINT_MAX, yes, no, false) + CONF_HANDLE_SSIZE_T(opt_dirty_decay_ms, + "dirty_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) < + QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) : + SSIZE_MAX); + CONF_HANDLE_SSIZE_T(opt_muzzy_decay_ms, + "muzzy_decay_ms", -1, NSTIME_SEC_MAX * KQU(1000) < + QU(SSIZE_MAX) ? NSTIME_SEC_MAX * KQU(1000) : + SSIZE_MAX); CONF_HANDLE_BOOL(opt_stats_print, "stats_print") + if (CONF_MATCH("stats_print_opts")) { + init_opt_stats_print_opts(v, vlen); + continue; + } if (config_fill) { - CONF_HANDLE_BOOL(opt_junk, "junk") - CONF_HANDLE_SIZE_T(opt_quarantine, "quarantine", - 0, SIZE_T_MAX, false) - CONF_HANDLE_BOOL(opt_redzone, "redzone") + if (CONF_MATCH("junk")) { + if (CONF_MATCH_VALUE("true")) { + opt_junk = "true"; + opt_junk_alloc = opt_junk_free = + true; + } else if (CONF_MATCH_VALUE("false")) { + opt_junk = "false"; + opt_junk_alloc = opt_junk_free = + false; + } else if (CONF_MATCH_VALUE("alloc")) { + opt_junk = "alloc"; + opt_junk_alloc = true; + opt_junk_free = false; + } else if (CONF_MATCH_VALUE("free")) { + opt_junk = "free"; + opt_junk_alloc = false; + opt_junk_free = true; + } else { + malloc_conf_error( + "Invalid conf value", k, + klen, v, vlen); + } + continue; + } CONF_HANDLE_BOOL(opt_zero, "zero") } if (config_utrace) { CONF_HANDLE_BOOL(opt_utrace, "utrace") } - if (config_valgrind) { - CONF_HANDLE_BOOL(opt_valgrind, "valgrind") - } if (config_xmalloc) { CONF_HANDLE_BOOL(opt_xmalloc, "xmalloc") } - if (config_tcache) { - CONF_HANDLE_BOOL(opt_tcache, "tcache") - CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, - "lg_tcache_max", -1, - (sizeof(size_t) << 3) - 1) + CONF_HANDLE_BOOL(opt_tcache, "tcache") + CONF_HANDLE_SSIZE_T(opt_lg_tcache_max, "lg_tcache_max", + -1, (sizeof(size_t) << 3) - 1) + if (strncmp("percpu_arena", k, klen) == 0) { + int i; + bool match = false; + for (i = percpu_arena_mode_names_base; i < + percpu_arena_mode_names_limit; i++) { + if (strncmp(percpu_arena_mode_names[i], + v, vlen) == 0) { + if (!have_percpu_arena) { + malloc_conf_error( + "No getcpu support", + k, klen, v, vlen); + } + opt_percpu_arena = i; + match = true; + break; + } + } + if (!match) { + malloc_conf_error("Invalid conf value", + k, klen, v, vlen); + } + continue; } + CONF_HANDLE_BOOL(opt_background_thread, + "background_thread"); if (config_prof) { CONF_HANDLE_BOOL(opt_prof, "prof") CONF_HANDLE_CHAR_P(opt_prof_prefix, "prof_prefix", "jeprof") CONF_HANDLE_BOOL(opt_prof_active, "prof_active") - CONF_HANDLE_SSIZE_T(opt_lg_prof_sample, - "lg_prof_sample", 0, - (sizeof(uint64_t) << 3) - 1) + CONF_HANDLE_BOOL(opt_prof_thread_active_init, + "prof_thread_active_init") + CONF_HANDLE_SIZE_T(opt_lg_prof_sample, + "lg_prof_sample", 0, (sizeof(uint64_t) << 3) + - 1, no, yes, true) CONF_HANDLE_BOOL(opt_prof_accum, "prof_accum") CONF_HANDLE_SSIZE_T(opt_lg_prof_interval, "lg_prof_interval", -1, @@ -638,7 +1175,15 @@ malloc_conf_init(void) } malloc_conf_error("Invalid conf pair", k, klen, v, vlen); +#undef CONF_MATCH +#undef CONF_MATCH_VALUE #undef CONF_HANDLE_BOOL +#undef CONF_MIN_no +#undef CONF_MIN_yes +#undef CONF_MAX_no +#undef CONF_MAX_yes +#undef CONF_HANDLE_T_U +#undef CONF_HANDLE_UNSIGNED #undef CONF_HANDLE_SIZE_T #undef CONF_HANDLE_SSIZE_T #undef CONF_HANDLE_CHAR_P @@ -647,195 +1192,325 @@ malloc_conf_init(void) } static bool -malloc_init_hard(void) -{ - arena_t *init_arenas[1]; - - malloc_mutex_lock(&init_lock); - if (malloc_initialized || IS_INITIALIZER) { +malloc_init_hard_needed(void) { + if (malloc_initialized() || (IS_INITIALIZER && malloc_init_state == + malloc_init_recursible)) { /* * Another thread initialized the allocator before this one * acquired init_lock, or this thread is the initializing * thread, and it is recursively allocating. */ - malloc_mutex_unlock(&init_lock); - return (false); + return false; } #ifdef JEMALLOC_THREADED_INIT - if (malloc_initializer != NO_INITIALIZER && IS_INITIALIZER == false) { + if (malloc_initializer != NO_INITIALIZER && !IS_INITIALIZER) { /* Busy-wait until the initializing thread completes. */ + spin_t spinner = SPIN_INITIALIZER; do { - malloc_mutex_unlock(&init_lock); - CPU_SPINWAIT; - malloc_mutex_lock(&init_lock); - } while (malloc_initialized == false); - malloc_mutex_unlock(&init_lock); - return (false); + malloc_mutex_unlock(TSDN_NULL, &init_lock); + spin_adaptive(&spinner); + malloc_mutex_lock(TSDN_NULL, &init_lock); + } while (!malloc_initialized()); + return false; } #endif + return true; +} + +static bool +malloc_init_hard_a0_locked() { malloc_initializer = INITIALIZER; - malloc_tsd_boot(); - if (config_prof) + if (config_prof) { prof_boot0(); - + } malloc_conf_init(); - if (opt_stats_print) { /* Print statistics at exit. */ if (atexit(stats_print_atexit) != 0) { malloc_write("<jemalloc>: Error in atexit()\n"); - if (opt_abort) + if (opt_abort) { abort(); + } } } - - if (base_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); + if (pages_boot()) { + return true; } - - if (chunk_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); + if (base_boot(TSDN_NULL)) { + return true; + } + if (extent_boot()) { + return true; } - if (ctl_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); + return true; } - - if (config_prof) + if (config_prof) { prof_boot1(); - - arena_boot(); - - if (config_tcache && tcache_boot0()) { - malloc_mutex_unlock(&init_lock); - return (true); } - - if (huge_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); + arena_boot(); + if (tcache_boot(TSDN_NULL)) { + return true; } - - if (malloc_mutex_init(&arenas_lock)) { - malloc_mutex_unlock(&init_lock); - return (true); + if (malloc_mutex_init(&arenas_lock, "arenas", WITNESS_RANK_ARENAS, + malloc_mutex_rank_exclusive)) { + return true; } - /* * Create enough scaffolding to allow recursive allocation in * malloc_ncpus(). */ - narenas_total = narenas_auto = 1; - arenas = init_arenas; + narenas_auto = 1; memset(arenas, 0, sizeof(arena_t *) * narenas_auto); - /* * Initialize one arena here. The rest are lazily created in - * choose_arena_hard(). + * arena_choose_hard(). */ - arenas_extend(0); - if (arenas[0] == NULL) { - malloc_mutex_unlock(&init_lock); - return (true); - } - - /* Initialize allocation counters before any allocations can occur. */ - if (config_stats && thread_allocated_tsd_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); + if (arena_init(TSDN_NULL, 0, (extent_hooks_t *)&extent_hooks_default) + == NULL) { + return true; } + a0 = arena_get(TSDN_NULL, 0, false); + malloc_init_state = malloc_init_a0_initialized; - if (arenas_tsd_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } - - if (config_tcache && tcache_boot1()) { - malloc_mutex_unlock(&init_lock); - return (true); - } + return false; +} - if (config_fill && quarantine_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); - } +static bool +malloc_init_hard_a0(void) { + bool ret; - if (config_prof && prof_boot2()) { - malloc_mutex_unlock(&init_lock); - return (true); - } + malloc_mutex_lock(TSDN_NULL, &init_lock); + ret = malloc_init_hard_a0_locked(); + malloc_mutex_unlock(TSDN_NULL, &init_lock); + return ret; +} - malloc_mutex_unlock(&init_lock); - /**********************************************************************/ - /* Recursive allocation may follow. */ +/* Initialize data structures which may trigger recursive allocation. */ +static bool +malloc_init_hard_recursible(void) { + malloc_init_state = malloc_init_recursible; ncpus = malloc_ncpus(); -#if (!defined(JEMALLOC_MUTEX_INIT_CB) && !defined(JEMALLOC_ZONE) \ - && !defined(_WIN32)) - /* LinuxThreads's pthread_atfork() allocates. */ +#if (defined(JEMALLOC_HAVE_PTHREAD_ATFORK) && !defined(JEMALLOC_MUTEX_INIT_CB) \ + && !defined(JEMALLOC_ZONE) && !defined(_WIN32) && \ + !defined(__native_client__)) + /* LinuxThreads' pthread_atfork() allocates. */ if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, jemalloc_postfork_child) != 0) { malloc_write("<jemalloc>: Error in pthread_atfork()\n"); - if (opt_abort) + if (opt_abort) { abort(); + } + return true; } #endif - /* Done recursively allocating. */ - /**********************************************************************/ - malloc_mutex_lock(&init_lock); + if (background_thread_boot0()) { + return true; + } + + return false; +} + +static unsigned +malloc_narenas_default(void) { + assert(ncpus > 0); + /* + * For SMP systems, create more than one arena per CPU by + * default. + */ + if (ncpus > 1) { + return ncpus << 2; + } else { + return 1; + } +} + +static percpu_arena_mode_t +percpu_arena_as_initialized(percpu_arena_mode_t mode) { + assert(!malloc_initialized()); + assert(mode <= percpu_arena_disabled); - if (mutex_boot()) { - malloc_mutex_unlock(&init_lock); - return (true); + if (mode != percpu_arena_disabled) { + mode += percpu_arena_mode_enabled_base; } + return mode; +} + +static bool +malloc_init_narenas(void) { + assert(ncpus > 0); + + if (opt_percpu_arena != percpu_arena_disabled) { + if (!have_percpu_arena || malloc_getcpu() < 0) { + opt_percpu_arena = percpu_arena_disabled; + malloc_printf("<jemalloc>: perCPU arena getcpu() not " + "available. Setting narenas to %u.\n", opt_narenas ? + opt_narenas : malloc_narenas_default()); + if (opt_abort) { + abort(); + } + } else { + if (ncpus >= MALLOCX_ARENA_LIMIT) { + malloc_printf("<jemalloc>: narenas w/ percpu" + "arena beyond limit (%d)\n", ncpus); + if (opt_abort) { + abort(); + } + return true; + } + /* NB: opt_percpu_arena isn't fully initialized yet. */ + if (percpu_arena_as_initialized(opt_percpu_arena) == + per_phycpu_arena && ncpus % 2 != 0) { + malloc_printf("<jemalloc>: invalid " + "configuration -- per physical CPU arena " + "with odd number (%u) of CPUs (no hyper " + "threading?).\n", ncpus); + if (opt_abort) + abort(); + } + unsigned n = percpu_arena_ind_limit( + percpu_arena_as_initialized(opt_percpu_arena)); + if (opt_narenas < n) { + /* + * If narenas is specified with percpu_arena + * enabled, actual narenas is set as the greater + * of the two. percpu_arena_choose will be free + * to use any of the arenas based on CPU + * id. This is conservative (at a small cost) + * but ensures correctness. + * + * If for some reason the ncpus determined at + * boot is not the actual number (e.g. because + * of affinity setting from numactl), reserving + * narenas this way provides a workaround for + * percpu_arena. + */ + opt_narenas = n; + } + } + } if (opt_narenas == 0) { - /* - * For SMP systems, create more than one arena per CPU by - * default. - */ - if (ncpus > 1) - opt_narenas = ncpus << 2; - else - opt_narenas = 1; + opt_narenas = malloc_narenas_default(); } + assert(opt_narenas > 0); + narenas_auto = opt_narenas; /* - * Make sure that the arenas array can be allocated. In practice, this - * limit is enough to allow the allocator to function, but the ctl - * machinery will fail to allocate memory at far lower limits. + * Limit the number of arenas to the indexing range of MALLOCX_ARENA(). */ - if (narenas_auto > chunksize / sizeof(arena_t *)) { - narenas_auto = chunksize / sizeof(arena_t *); + if (narenas_auto >= MALLOCX_ARENA_LIMIT) { + narenas_auto = MALLOCX_ARENA_LIMIT - 1; malloc_printf("<jemalloc>: Reducing narenas to limit (%d)\n", narenas_auto); } - narenas_total = narenas_auto; + narenas_total_set(narenas_auto); - /* Allocate and initialize arenas. */ - arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas_total); - if (arenas == NULL) { - malloc_mutex_unlock(&init_lock); - return (true); + return false; +} + +static void +malloc_init_percpu(void) { + opt_percpu_arena = percpu_arena_as_initialized(opt_percpu_arena); +} + +static bool +malloc_init_hard_finish(void) { + if (malloc_mutex_boot()) { + return true; + } + + malloc_init_state = malloc_init_initialized; + malloc_slow_flag_init(); + + return false; +} + +static void +malloc_init_hard_cleanup(tsdn_t *tsdn, bool reentrancy_set) { + malloc_mutex_assert_owner(tsdn, &init_lock); + malloc_mutex_unlock(tsdn, &init_lock); + if (reentrancy_set) { + assert(!tsdn_null(tsdn)); + tsd_t *tsd = tsdn_tsd(tsdn); + assert(tsd_reentrancy_level_get(tsd) > 0); + post_reentrancy(tsd); + } +} + +static bool +malloc_init_hard(void) { + tsd_t *tsd; + +#if defined(_WIN32) && _WIN32_WINNT < 0x0600 + _init_init_lock(); +#endif + malloc_mutex_lock(TSDN_NULL, &init_lock); + +#define UNLOCK_RETURN(tsdn, ret, reentrancy) \ + malloc_init_hard_cleanup(tsdn, reentrancy); \ + return ret; + + if (!malloc_init_hard_needed()) { + UNLOCK_RETURN(TSDN_NULL, false, false) + } + + if (malloc_init_state != malloc_init_a0_initialized && + malloc_init_hard_a0_locked()) { + UNLOCK_RETURN(TSDN_NULL, true, false) + } + + malloc_mutex_unlock(TSDN_NULL, &init_lock); + /* Recursive allocation relies on functional tsd. */ + tsd = malloc_tsd_boot0(); + if (tsd == NULL) { + return true; + } + if (malloc_init_hard_recursible()) { + return true; + } + + malloc_mutex_lock(tsd_tsdn(tsd), &init_lock); + /* Set reentrancy level to 1 during init. */ + pre_reentrancy(tsd, NULL); + /* Initialize narenas before prof_boot2 (for allocation). */ + if (malloc_init_narenas() || background_thread_boot1(tsd_tsdn(tsd))) { + UNLOCK_RETURN(tsd_tsdn(tsd), true, true) + } + if (config_prof && prof_boot2(tsd)) { + UNLOCK_RETURN(tsd_tsdn(tsd), true, true) } - /* - * Zero the array. In practice, this should always be pre-zeroed, - * since it was just mmap()ed, but let's be sure. - */ - memset(arenas, 0, sizeof(arena_t *) * narenas_total); - /* Copy the pointer to the one arena that was already initialized. */ - arenas[0] = init_arenas[0]; - malloc_initialized = true; - malloc_mutex_unlock(&init_lock); + malloc_init_percpu(); - return (false); + if (malloc_init_hard_finish()) { + UNLOCK_RETURN(tsd_tsdn(tsd), true, true) + } + post_reentrancy(tsd); + malloc_mutex_unlock(tsd_tsdn(tsd), &init_lock); + + malloc_tsd_boot1(); + /* Update TSD after tsd_boot1. */ + tsd = tsd_fetch(); + if (opt_background_thread) { + assert(have_background_thread); + /* + * Need to finish init & unlock first before creating background + * threads (pthread_create depends on malloc). + */ + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); + bool err = background_thread_create(tsd, 0); + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + if (err) { + return true; + } + } +#undef UNLOCK_RETURN + return false; } /* @@ -843,469 +1518,779 @@ malloc_init_hard(void) */ /******************************************************************************/ /* - * Begin malloc(3)-compatible functions. + * Begin allocation-path internal functions and data structures. */ -static void * -imalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt) -{ - void *p; - - if (cnt == NULL) - return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - p = imalloc(SMALL_MAXCLASS+1); - if (p == NULL) - return (NULL); - arena_prof_promoted(p, usize); - } else - p = imalloc(usize); +/* + * Settings determined by the documented behavior of the allocation functions. + */ +typedef struct static_opts_s static_opts_t; +struct static_opts_s { + /* Whether or not allocation size may overflow. */ + bool may_overflow; + /* Whether or not allocations of size 0 should be treated as size 1. */ + bool bump_empty_alloc; + /* + * Whether to assert that allocations are not of size 0 (after any + * bumping). + */ + bool assert_nonempty_alloc; - return (p); -} + /* + * Whether or not to modify the 'result' argument to malloc in case of + * error. + */ + bool null_out_result_on_error; + /* Whether to set errno when we encounter an error condition. */ + bool set_errno_on_error; -JEMALLOC_ALWAYS_INLINE_C void * -imalloc_prof(size_t usize, prof_thr_cnt_t *cnt) -{ - void *p; + /* + * The minimum valid alignment for functions requesting aligned storage. + */ + size_t min_alignment; - if ((uintptr_t)cnt != (uintptr_t)1U) - p = imalloc_prof_sample(usize, cnt); - else - p = imalloc(usize); - if (p == NULL) - return (NULL); - prof_malloc(p, usize, cnt); + /* The error string to use if we oom. */ + const char *oom_string; + /* The error string to use if the passed-in alignment is invalid. */ + const char *invalid_alignment_string; - return (p); + /* + * False if we're configured to skip some time-consuming operations. + * + * This isn't really a malloc "behavior", but it acts as a useful + * summary of several other static (or at least, static after program + * initialization) options. + */ + bool slow; +}; + +JEMALLOC_ALWAYS_INLINE void +static_opts_init(static_opts_t *static_opts) { + static_opts->may_overflow = false; + static_opts->bump_empty_alloc = false; + static_opts->assert_nonempty_alloc = false; + static_opts->null_out_result_on_error = false; + static_opts->set_errno_on_error = false; + static_opts->min_alignment = 0; + static_opts->oom_string = ""; + static_opts->invalid_alignment_string = ""; + static_opts->slow = false; } /* - * MALLOC_BODY() is a macro rather than a function because its contents are in - * the fast path, but inlining would cause reliability issues when determining - * how many frames to discard from heap profiling backtraces. + * These correspond to the macros in jemalloc/jemalloc_macros.h. Broadly, we + * should have one constant here per magic value there. Note however that the + * representations need not be related. */ -#define MALLOC_BODY(ret, size, usize) do { \ - if (malloc_init()) \ - ret = NULL; \ - else { \ - if (config_prof && opt_prof) { \ - prof_thr_cnt_t *cnt; \ - \ - usize = s2u(size); \ - /* \ - * Call PROF_ALLOC_PREP() here rather than in \ - * imalloc_prof() so that imalloc_prof() can be \ - * inlined without introducing uncertainty \ - * about the number of backtrace frames to \ - * ignore. imalloc_prof() is in the fast path \ - * when heap profiling is enabled, so inlining \ - * is critical to performance. (For \ - * consistency all callers of PROF_ALLOC_PREP() \ - * are structured similarly, even though e.g. \ - * realloc() isn't called enough for inlining \ - * to be critical.) \ - */ \ - PROF_ALLOC_PREP(1, usize, cnt); \ - ret = imalloc_prof(usize, cnt); \ - } else { \ - if (config_stats || (config_valgrind && \ - opt_valgrind)) \ - usize = s2u(size); \ - ret = imalloc(size); \ - } \ - } \ -} while (0) - -void * -je_malloc(size_t size) -{ - void *ret; - size_t usize JEMALLOC_CC_SILENCE_INIT(0); - - if (size == 0) - size = 1; +#define TCACHE_IND_NONE ((unsigned)-1) +#define TCACHE_IND_AUTOMATIC ((unsigned)-2) +#define ARENA_IND_AUTOMATIC ((unsigned)-1) + +typedef struct dynamic_opts_s dynamic_opts_t; +struct dynamic_opts_s { + void **result; + size_t num_items; + size_t item_size; + size_t alignment; + bool zero; + unsigned tcache_ind; + unsigned arena_ind; +}; + +JEMALLOC_ALWAYS_INLINE void +dynamic_opts_init(dynamic_opts_t *dynamic_opts) { + dynamic_opts->result = NULL; + dynamic_opts->num_items = 0; + dynamic_opts->item_size = 0; + dynamic_opts->alignment = 0; + dynamic_opts->zero = false; + dynamic_opts->tcache_ind = TCACHE_IND_AUTOMATIC; + dynamic_opts->arena_ind = ARENA_IND_AUTOMATIC; +} - MALLOC_BODY(ret, size, usize); +/* ind is ignored if dopts->alignment > 0. */ +JEMALLOC_ALWAYS_INLINE void * +imalloc_no_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd, + size_t size, size_t usize, szind_t ind) { + tcache_t *tcache; + arena_t *arena; - if (ret == NULL) { - if (config_xmalloc && opt_xmalloc) { - malloc_write("<jemalloc>: Error in malloc(): " - "out of memory\n"); - abort(); + /* Fill in the tcache. */ + if (dopts->tcache_ind == TCACHE_IND_AUTOMATIC) { + if (likely(!sopts->slow)) { + /* Getting tcache ptr unconditionally. */ + tcache = tsd_tcachep_get(tsd); + assert(tcache == tcache_get(tsd)); + } else { + tcache = tcache_get(tsd); } - set_errno(ENOMEM); - } - if (config_stats && ret != NULL) { - assert(usize == isalloc(ret, config_prof)); - thread_allocated_tsd_get()->allocated += usize; + } else if (dopts->tcache_ind == TCACHE_IND_NONE) { + tcache = NULL; + } else { + tcache = tcaches_get(tsd, dopts->tcache_ind); } - UTRACE(0, size, ret); - JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, false); - return (ret); -} -static void * -imemalign_prof_sample(size_t alignment, size_t usize, prof_thr_cnt_t *cnt) -{ - void *p; + /* Fill in the arena. */ + if (dopts->arena_ind == ARENA_IND_AUTOMATIC) { + /* + * In case of automatic arena management, we defer arena + * computation until as late as we can, hoping to fill the + * allocation out of the tcache. + */ + arena = NULL; + } else { + arena = arena_get(tsd_tsdn(tsd), dopts->arena_ind, true); + } - if (cnt == NULL) - return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - assert(sa2u(SMALL_MAXCLASS+1, alignment) != 0); - p = ipalloc(sa2u(SMALL_MAXCLASS+1, alignment), alignment, - false); - if (p == NULL) - return (NULL); - arena_prof_promoted(p, usize); - } else - p = ipalloc(usize, alignment, false); + if (unlikely(dopts->alignment != 0)) { + return ipalloct(tsd_tsdn(tsd), usize, dopts->alignment, + dopts->zero, tcache, arena); + } - return (p); + return iallocztm(tsd_tsdn(tsd), size, ind, dopts->zero, tcache, false, + arena, sopts->slow); } -JEMALLOC_ALWAYS_INLINE_C void * -imemalign_prof(size_t alignment, size_t usize, prof_thr_cnt_t *cnt) -{ - void *p; +JEMALLOC_ALWAYS_INLINE void * +imalloc_sample(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd, + size_t usize, szind_t ind) { + void *ret; - if ((uintptr_t)cnt != (uintptr_t)1U) - p = imemalign_prof_sample(alignment, usize, cnt); - else - p = ipalloc(usize, alignment, false); - if (p == NULL) - return (NULL); - prof_malloc(p, usize, cnt); + /* + * For small allocations, sampling bumps the usize. If so, we allocate + * from the ind_large bucket. + */ + szind_t ind_large; + size_t bumped_usize = usize; + + if (usize <= SMALL_MAXCLASS) { + assert(((dopts->alignment == 0) ? sz_s2u(LARGE_MINCLASS) : + sz_sa2u(LARGE_MINCLASS, dopts->alignment)) + == LARGE_MINCLASS); + ind_large = sz_size2index(LARGE_MINCLASS); + bumped_usize = sz_s2u(LARGE_MINCLASS); + ret = imalloc_no_sample(sopts, dopts, tsd, bumped_usize, + bumped_usize, ind_large); + if (unlikely(ret == NULL)) { + return NULL; + } + arena_prof_promote(tsd_tsdn(tsd), ret, usize); + } else { + ret = imalloc_no_sample(sopts, dopts, tsd, usize, usize, ind); + } - return (p); + return ret; } -JEMALLOC_ATTR(nonnull(1)) -#ifdef JEMALLOC_PROF /* - * Avoid any uncertainty as to how many backtrace frames to ignore in - * PROF_ALLOC_PREP(). + * Returns true if the allocation will overflow, and false otherwise. Sets + * *size to the product either way. */ -JEMALLOC_NOINLINE -#endif -static int -imemalign(void **memptr, size_t alignment, size_t size, size_t min_alignment) -{ - int ret; - size_t usize; - void *result; +JEMALLOC_ALWAYS_INLINE bool +compute_size_with_overflow(bool may_overflow, dynamic_opts_t *dopts, + size_t *size) { + /* + * This function is just num_items * item_size, except that we may have + * to check for overflow. + */ - assert(min_alignment != 0); + if (!may_overflow) { + assert(dopts->num_items == 1); + *size = dopts->item_size; + return false; + } + + /* A size_t with its high-half bits all set to 1. */ + const static size_t high_bits = SIZE_T_MAX << (sizeof(size_t) * 8 / 2); + + *size = dopts->item_size * dopts->num_items; + + if (unlikely(*size == 0)) { + return (dopts->num_items != 0 && dopts->item_size != 0); + } + + /* + * We got a non-zero size, but we don't know if we overflowed to get + * there. To avoid having to do a divide, we'll be clever and note that + * if both A and B can be represented in N/2 bits, then their product + * can be represented in N bits (without the possibility of overflow). + */ + if (likely((high_bits & (dopts->num_items | dopts->item_size)) == 0)) { + return false; + } + if (likely(*size / dopts->item_size == dopts->num_items)) { + return false; + } + return true; +} + +JEMALLOC_ALWAYS_INLINE int +imalloc_body(static_opts_t *sopts, dynamic_opts_t *dopts, tsd_t *tsd) { + /* Where the actual allocated memory will live. */ + void *allocation = NULL; + /* Filled in by compute_size_with_overflow below. */ + size_t size = 0; + /* + * For unaligned allocations, we need only ind. For aligned + * allocations, or in case of stats or profiling we need usize. + * + * These are actually dead stores, in that their values are reset before + * any branch on their value is taken. Sometimes though, it's + * convenient to pass them as arguments before this point. To avoid + * undefined behavior then, we initialize them with dummy stores. + */ + szind_t ind = 0; + size_t usize = 0; - if (malloc_init()) { - result = NULL; + /* Reentrancy is only checked on slow path. */ + int8_t reentrancy_level; + + /* Compute the amount of memory the user wants. */ + if (unlikely(compute_size_with_overflow(sopts->may_overflow, dopts, + &size))) { goto label_oom; - } else { - if (size == 0) - size = 1; + } - /* Make sure that alignment is a large enough power of 2. */ - if (((alignment - 1) & alignment) != 0 - || (alignment < min_alignment)) { - if (config_xmalloc && opt_xmalloc) { - malloc_write("<jemalloc>: Error allocating " - "aligned memory: invalid alignment\n"); - abort(); - } - result = NULL; - ret = EINVAL; - goto label_return; + /* Validate the user input. */ + if (sopts->bump_empty_alloc) { + if (unlikely(size == 0)) { + size = 1; } + } + + if (sopts->assert_nonempty_alloc) { + assert (size != 0); + } + + if (unlikely(dopts->alignment < sopts->min_alignment + || (dopts->alignment & (dopts->alignment - 1)) != 0)) { + goto label_invalid_alignment; + } + + /* This is the beginning of the "core" algorithm. */ - usize = sa2u(size, alignment); - if (usize == 0) { - result = NULL; + if (dopts->alignment == 0) { + ind = sz_size2index(size); + if (unlikely(ind >= NSIZES)) { goto label_oom; } + if (config_stats || (config_prof && opt_prof)) { + usize = sz_index2size(ind); + assert(usize > 0 && usize <= LARGE_MAXCLASS); + } + } else { + usize = sz_sa2u(size, dopts->alignment); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + goto label_oom; + } + } - if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; + check_entry_exit_locking(tsd_tsdn(tsd)); + + /* + * If we need to handle reentrancy, we can do it out of a + * known-initialized arena (i.e. arena 0). + */ + reentrancy_level = tsd_reentrancy_level_get(tsd); + if (sopts->slow && unlikely(reentrancy_level > 0)) { + /* + * We should never specify particular arenas or tcaches from + * within our internal allocations. + */ + assert(dopts->tcache_ind == TCACHE_IND_AUTOMATIC || + dopts->tcache_ind == TCACHE_IND_NONE); + assert(dopts->arena_ind == ARENA_IND_AUTOMATIC); + dopts->tcache_ind = TCACHE_IND_NONE; + /* We know that arena 0 has already been initialized. */ + dopts->arena_ind = 0; + } + + /* If profiling is on, get our profiling context. */ + if (config_prof && opt_prof) { + /* + * Note that if we're going down this path, usize must have been + * initialized in the previous if statement. + */ + prof_tctx_t *tctx = prof_alloc_prep( + tsd, usize, prof_active_get_unlocked(), true); + + alloc_ctx_t alloc_ctx; + if (likely((uintptr_t)tctx == (uintptr_t)1U)) { + alloc_ctx.slab = (usize <= SMALL_MAXCLASS); + allocation = imalloc_no_sample( + sopts, dopts, tsd, usize, usize, ind); + } else if ((uintptr_t)tctx > (uintptr_t)1U) { + /* + * Note that ind might still be 0 here. This is fine; + * imalloc_sample ignores ind if dopts->alignment > 0. + */ + allocation = imalloc_sample( + sopts, dopts, tsd, usize, ind); + alloc_ctx.slab = false; + } else { + allocation = NULL; + } - PROF_ALLOC_PREP(2, usize, cnt); - result = imemalign_prof(alignment, usize, cnt); - } else - result = ipalloc(usize, alignment, false); - if (result == NULL) + if (unlikely(allocation == NULL)) { + prof_alloc_rollback(tsd, tctx, true); + goto label_oom; + } + prof_malloc(tsd_tsdn(tsd), allocation, usize, &alloc_ctx, tctx); + } else { + /* + * If dopts->alignment > 0, then ind is still 0, but usize was + * computed in the previous if statement. Down the positive + * alignment path, imalloc_no_sample ignores ind and size + * (relying only on usize). + */ + allocation = imalloc_no_sample(sopts, dopts, tsd, size, usize, + ind); + if (unlikely(allocation == NULL)) { goto label_oom; + } } - *memptr = result; - ret = 0; -label_return: - if (config_stats && result != NULL) { - assert(usize == isalloc(result, config_prof)); - thread_allocated_tsd_get()->allocated += usize; + /* + * Allocation has been done at this point. We still have some + * post-allocation work to do though. + */ + assert(dopts->alignment == 0 + || ((uintptr_t)allocation & (dopts->alignment - 1)) == ZU(0)); + + if (config_stats) { + assert(usize == isalloc(tsd_tsdn(tsd), allocation)); + *tsd_thread_allocatedp_get(tsd) += usize; } - UTRACE(0, size, result); - return (ret); + + if (sopts->slow) { + UTRACE(0, size, allocation); + } + + /* Success! */ + check_entry_exit_locking(tsd_tsdn(tsd)); + *dopts->result = allocation; + return 0; + label_oom: - assert(result == NULL); - if (config_xmalloc && opt_xmalloc) { - malloc_write("<jemalloc>: Error allocating aligned memory: " - "out of memory\n"); + if (unlikely(sopts->slow) && config_xmalloc && unlikely(opt_xmalloc)) { + malloc_write(sopts->oom_string); abort(); } - ret = ENOMEM; - goto label_return; -} -int -je_posix_memalign(void **memptr, size_t alignment, size_t size) -{ - int ret = imemalign(memptr, alignment, size, sizeof(void *)); - JEMALLOC_VALGRIND_MALLOC(ret == 0, *memptr, isalloc(*memptr, - config_prof), false); - return (ret); + if (sopts->slow) { + UTRACE(NULL, size, NULL); + } + + check_entry_exit_locking(tsd_tsdn(tsd)); + + if (sopts->set_errno_on_error) { + set_errno(ENOMEM); + } + + if (sopts->null_out_result_on_error) { + *dopts->result = NULL; + } + + return ENOMEM; + + /* + * This label is only jumped to by one goto; we move it out of line + * anyways to avoid obscuring the non-error paths, and for symmetry with + * the oom case. + */ +label_invalid_alignment: + if (config_xmalloc && unlikely(opt_xmalloc)) { + malloc_write(sopts->invalid_alignment_string); + abort(); + } + + if (sopts->set_errno_on_error) { + set_errno(EINVAL); + } + + if (sopts->slow) { + UTRACE(NULL, size, NULL); + } + + check_entry_exit_locking(tsd_tsdn(tsd)); + + if (sopts->null_out_result_on_error) { + *dopts->result = NULL; + } + + return EINVAL; } -void * -je_aligned_alloc(size_t alignment, size_t size) -{ - void *ret; - int err; +/* Returns the errno-style error code of the allocation. */ +JEMALLOC_ALWAYS_INLINE int +imalloc(static_opts_t *sopts, dynamic_opts_t *dopts) { + if (unlikely(!malloc_initialized()) && unlikely(malloc_init())) { + if (config_xmalloc && unlikely(opt_xmalloc)) { + malloc_write(sopts->oom_string); + abort(); + } + UTRACE(NULL, dopts->num_items * dopts->item_size, NULL); + set_errno(ENOMEM); + *dopts->result = NULL; + + return ENOMEM; + } - if ((err = imemalign(&ret, alignment, size, 1)) != 0) { - ret = NULL; - set_errno(err); + /* We always need the tsd. Let's grab it right away. */ + tsd_t *tsd = tsd_fetch(); + assert(tsd); + if (likely(tsd_fast(tsd))) { + /* Fast and common path. */ + tsd_assert_fast(tsd); + sopts->slow = false; + return imalloc_body(sopts, dopts, tsd); + } else { + sopts->slow = true; + return imalloc_body(sopts, dopts, tsd); } - JEMALLOC_VALGRIND_MALLOC(err == 0, ret, isalloc(ret, config_prof), - false); - return (ret); } +/******************************************************************************/ +/* + * Begin malloc(3)-compatible functions. + */ -static void * -icalloc_prof_sample(size_t usize, prof_thr_cnt_t *cnt) -{ - void *p; +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) +je_malloc(size_t size) { + void *ret; + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.bump_empty_alloc = true; + sopts.null_out_result_on_error = true; + sopts.set_errno_on_error = true; + sopts.oom_string = "<jemalloc>: Error in malloc(): out of memory\n"; - if (cnt == NULL) - return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - p = icalloc(SMALL_MAXCLASS+1); - if (p == NULL) - return (NULL); - arena_prof_promoted(p, usize); - } else - p = icalloc(usize); + dopts.result = &ret; + dopts.num_items = 1; + dopts.item_size = size; - return (p); + imalloc(&sopts, &dopts); + + return ret; } -JEMALLOC_ALWAYS_INLINE_C void * -icalloc_prof(size_t usize, prof_thr_cnt_t *cnt) -{ - void *p; +JEMALLOC_EXPORT int JEMALLOC_NOTHROW +JEMALLOC_ATTR(nonnull(1)) +je_posix_memalign(void **memptr, size_t alignment, size_t size) { + int ret; + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.bump_empty_alloc = true; + sopts.min_alignment = sizeof(void *); + sopts.oom_string = + "<jemalloc>: Error allocating aligned memory: out of memory\n"; + sopts.invalid_alignment_string = + "<jemalloc>: Error allocating aligned memory: invalid alignment\n"; + + dopts.result = memptr; + dopts.num_items = 1; + dopts.item_size = size; + dopts.alignment = alignment; + + ret = imalloc(&sopts, &dopts); + return ret; +} - if ((uintptr_t)cnt != (uintptr_t)1U) - p = icalloc_prof_sample(usize, cnt); - else - p = icalloc(usize); - if (p == NULL) - return (NULL); - prof_malloc(p, usize, cnt); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2) +je_aligned_alloc(size_t alignment, size_t size) { + void *ret; - return (p); + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.bump_empty_alloc = true; + sopts.null_out_result_on_error = true; + sopts.set_errno_on_error = true; + sopts.min_alignment = 1; + sopts.oom_string = + "<jemalloc>: Error allocating aligned memory: out of memory\n"; + sopts.invalid_alignment_string = + "<jemalloc>: Error allocating aligned memory: invalid alignment\n"; + + dopts.result = &ret; + dopts.num_items = 1; + dopts.item_size = size; + dopts.alignment = alignment; + + imalloc(&sopts, &dopts); + return ret; } -void * -je_calloc(size_t num, size_t size) -{ +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2) +je_calloc(size_t num, size_t size) { void *ret; - size_t num_size; - size_t usize JEMALLOC_CC_SILENCE_INIT(0); + static_opts_t sopts; + dynamic_opts_t dopts; - if (malloc_init()) { - num_size = 0; - ret = NULL; - goto label_return; - } + static_opts_init(&sopts); + dynamic_opts_init(&dopts); - num_size = num * size; - if (num_size == 0) { - if (num == 0 || size == 0) - num_size = 1; - else { - ret = NULL; - goto label_return; - } - /* - * Try to avoid division here. We know that it isn't possible to - * overflow during multiplication if neither operand uses any of the - * most significant half of the bits in a size_t. - */ - } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2))) - && (num_size / size != num)) { - /* size_t overflow. */ - ret = NULL; - goto label_return; - } + sopts.may_overflow = true; + sopts.bump_empty_alloc = true; + sopts.null_out_result_on_error = true; + sopts.set_errno_on_error = true; + sopts.oom_string = "<jemalloc>: Error in calloc(): out of memory\n"; - if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; + dopts.result = &ret; + dopts.num_items = num; + dopts.item_size = size; + dopts.zero = true; - usize = s2u(num_size); - PROF_ALLOC_PREP(1, usize, cnt); - ret = icalloc_prof(usize, cnt); - } else { - if (config_stats || (config_valgrind && opt_valgrind)) - usize = s2u(num_size); - ret = icalloc(num_size); - } + imalloc(&sopts, &dopts); -label_return: - if (ret == NULL) { - if (config_xmalloc && opt_xmalloc) { - malloc_write("<jemalloc>: Error in calloc(): out of " - "memory\n"); - abort(); - } - set_errno(ENOMEM); - } - if (config_stats && ret != NULL) { - assert(usize == isalloc(ret, config_prof)); - thread_allocated_tsd_get()->allocated += usize; - } - UTRACE(0, num_size, ret); - JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, usize, true); - return (ret); + return ret; } static void * -irealloc_prof_sample(void *oldptr, size_t usize, prof_thr_cnt_t *cnt) -{ +irealloc_prof_sample(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize, + prof_tctx_t *tctx) { void *p; - if (cnt == NULL) - return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - p = iralloc(oldptr, SMALL_MAXCLASS+1, 0, 0, false); - if (p == NULL) - return (NULL); - arena_prof_promoted(p, usize); - } else - p = iralloc(oldptr, usize, 0, 0, false); + if (tctx == NULL) { + return NULL; + } + if (usize <= SMALL_MAXCLASS) { + p = iralloc(tsd, old_ptr, old_usize, LARGE_MINCLASS, 0, false); + if (p == NULL) { + return NULL; + } + arena_prof_promote(tsd_tsdn(tsd), p, usize); + } else { + p = iralloc(tsd, old_ptr, old_usize, usize, 0, false); + } - return (p); + return p; } -JEMALLOC_ALWAYS_INLINE_C void * -irealloc_prof(void *oldptr, size_t old_usize, size_t usize, prof_thr_cnt_t *cnt) -{ +JEMALLOC_ALWAYS_INLINE void * +irealloc_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t usize, + alloc_ctx_t *alloc_ctx) { void *p; - prof_ctx_t *old_ctx; - - old_ctx = prof_ctx_get(oldptr); - if ((uintptr_t)cnt != (uintptr_t)1U) - p = irealloc_prof_sample(oldptr, usize, cnt); - else - p = iralloc(oldptr, usize, 0, 0, false); - if (p == NULL) - return (NULL); - prof_realloc(p, usize, cnt, old_usize, old_ctx); + bool prof_active; + prof_tctx_t *old_tctx, *tctx; + + prof_active = prof_active_get_unlocked(); + old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr, alloc_ctx); + tctx = prof_alloc_prep(tsd, usize, prof_active, true); + if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { + p = irealloc_prof_sample(tsd, old_ptr, old_usize, usize, tctx); + } else { + p = iralloc(tsd, old_ptr, old_usize, usize, 0, false); + } + if (unlikely(p == NULL)) { + prof_alloc_rollback(tsd, tctx, true); + return NULL; + } + prof_realloc(tsd, p, usize, tctx, prof_active, true, old_ptr, old_usize, + old_tctx); - return (p); + return p; } -JEMALLOC_INLINE_C void -ifree(void *ptr) -{ +JEMALLOC_ALWAYS_INLINE void +ifree(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path) { + if (!slow_path) { + tsd_assert_fast(tsd); + } + check_entry_exit_locking(tsd_tsdn(tsd)); + if (tsd_reentrancy_level_get(tsd) != 0) { + assert(slow_path); + } + + assert(ptr != NULL); + assert(malloc_initialized() || IS_INITIALIZER); + + alloc_ctx_t alloc_ctx; + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind != NSIZES); + size_t usize; - UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); + if (config_prof && opt_prof) { + usize = sz_index2size(alloc_ctx.szind); + prof_free(tsd, ptr, usize, &alloc_ctx); + } else if (config_stats) { + usize = sz_index2size(alloc_ctx.szind); + } + if (config_stats) { + *tsd_thread_deallocatedp_get(tsd) += usize; + } + + if (likely(!slow_path)) { + idalloctm(tsd_tsdn(tsd), ptr, tcache, &alloc_ctx, false, + false); + } else { + idalloctm(tsd_tsdn(tsd), ptr, tcache, &alloc_ctx, false, + true); + } +} + +JEMALLOC_ALWAYS_INLINE void +isfree(tsd_t *tsd, void *ptr, size_t usize, tcache_t *tcache, bool slow_path) { + if (!slow_path) { + tsd_assert_fast(tsd); + } + check_entry_exit_locking(tsd_tsdn(tsd)); + if (tsd_reentrancy_level_get(tsd) != 0) { + assert(slow_path); + } assert(ptr != NULL); - assert(malloc_initialized || IS_INITIALIZER); + assert(malloc_initialized() || IS_INITIALIZER); + alloc_ctx_t alloc_ctx, *ctx; if (config_prof && opt_prof) { - usize = isalloc(ptr, config_prof); - prof_free(ptr, usize); - } else if (config_stats || config_valgrind) - usize = isalloc(ptr, config_prof); - if (config_stats) - thread_allocated_tsd_get()->deallocated += usize; - if (config_valgrind && opt_valgrind) - rzsize = p2rz(ptr); - iqalloc(ptr); - JEMALLOC_VALGRIND_FREE(ptr, rzsize); + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind == sz_size2index(usize)); + ctx = &alloc_ctx; + prof_free(tsd, ptr, usize, ctx); + } else { + ctx = NULL; + } + + if (config_stats) { + *tsd_thread_deallocatedp_get(tsd) += usize; + } + + if (likely(!slow_path)) { + isdalloct(tsd_tsdn(tsd), ptr, usize, tcache, ctx, false); + } else { + isdalloct(tsd_tsdn(tsd), ptr, usize, tcache, ctx, true); + } } -void * -je_realloc(void *ptr, size_t size) -{ +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ALLOC_SIZE(2) +je_realloc(void *ptr, size_t size) { void *ret; + tsdn_t *tsdn JEMALLOC_CC_SILENCE_INIT(NULL); size_t usize JEMALLOC_CC_SILENCE_INIT(0); size_t old_usize = 0; - UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); - if (size == 0) { + if (unlikely(size == 0)) { if (ptr != NULL) { /* realloc(ptr, 0) is equivalent to free(ptr). */ UTRACE(ptr, 0, 0); - ifree(ptr); - return (NULL); + tcache_t *tcache; + tsd_t *tsd = tsd_fetch(); + if (tsd_reentrancy_level_get(tsd) == 0) { + tcache = tcache_get(tsd); + } else { + tcache = NULL; + } + ifree(tsd, ptr, tcache, true); + return NULL; } size = 1; } - if (ptr != NULL) { - assert(malloc_initialized || IS_INITIALIZER); - malloc_thread_init(); + if (likely(ptr != NULL)) { + assert(malloc_initialized() || IS_INITIALIZER); + tsd_t *tsd = tsd_fetch(); - if ((config_prof && opt_prof) || config_stats || - (config_valgrind && opt_valgrind)) - old_usize = isalloc(ptr, config_prof); - if (config_valgrind && opt_valgrind) - old_rzsize = config_prof ? p2rz(ptr) : u2rz(old_usize); + check_entry_exit_locking(tsd_tsdn(tsd)); + alloc_ctx_t alloc_ctx; + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind != NSIZES); + old_usize = sz_index2size(alloc_ctx.szind); + assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; - - usize = s2u(size); - PROF_ALLOC_PREP(1, usize, cnt); - ret = irealloc_prof(ptr, old_usize, usize, cnt); + usize = sz_s2u(size); + ret = unlikely(usize == 0 || usize > LARGE_MAXCLASS) ? + NULL : irealloc_prof(tsd, ptr, old_usize, usize, + &alloc_ctx); } else { - if (config_stats || (config_valgrind && opt_valgrind)) - usize = s2u(size); - ret = iralloc(ptr, size, 0, 0, false); + if (config_stats) { + usize = sz_s2u(size); + } + ret = iralloc(tsd, ptr, old_usize, size, 0, false); } + tsdn = tsd_tsdn(tsd); } else { /* realloc(NULL, size) is equivalent to malloc(size). */ - MALLOC_BODY(ret, size, usize); + return je_malloc(size); } - if (ret == NULL) { - if (config_xmalloc && opt_xmalloc) { + if (unlikely(ret == NULL)) { + if (config_xmalloc && unlikely(opt_xmalloc)) { malloc_write("<jemalloc>: Error in realloc(): " "out of memory\n"); abort(); } set_errno(ENOMEM); } - if (config_stats && ret != NULL) { - thread_allocated_t *ta; - assert(usize == isalloc(ret, config_prof)); - ta = thread_allocated_tsd_get(); - ta->allocated += usize; - ta->deallocated += old_usize; + if (config_stats && likely(ret != NULL)) { + tsd_t *tsd; + + assert(usize == isalloc(tsdn, ret)); + tsd = tsdn_tsd(tsdn); + *tsd_thread_allocatedp_get(tsd) += usize; + *tsd_thread_deallocatedp_get(tsd) += old_usize; } UTRACE(ptr, size, ret); - JEMALLOC_VALGRIND_REALLOC(ret, usize, ptr, old_usize, old_rzsize, - false); - return (ret); + check_entry_exit_locking(tsdn); + return ret; } -void -je_free(void *ptr) -{ - +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_free(void *ptr) { UTRACE(ptr, 0, 0); - if (ptr != NULL) - ifree(ptr); + if (likely(ptr != NULL)) { + /* + * We avoid setting up tsd fully (e.g. tcache, arena binding) + * based on only free() calls -- other activities trigger the + * minimal to full transition. This is because free() may + * happen during thread shutdown after tls deallocation: if a + * thread never had any malloc activities until then, a + * fully-setup tsd won't be destructed properly. + */ + tsd_t *tsd = tsd_fetch_min(); + check_entry_exit_locking(tsd_tsdn(tsd)); + + tcache_t *tcache; + if (likely(tsd_fast(tsd))) { + tsd_assert_fast(tsd); + /* Unconditionally get tcache ptr on fast path. */ + tcache = tsd_tcachep_get(tsd); + ifree(tsd, ptr, tcache, false); + } else { + if (likely(tsd_reentrancy_level_get(tsd) == 0)) { + tcache = tcache_get(tsd); + } else { + tcache = NULL; + } + ifree(tsd, ptr, tcache, true); + } + check_entry_exit_locking(tsd_tsdn(tsd)); + } } /* @@ -1317,36 +2302,68 @@ je_free(void *ptr) */ #ifdef JEMALLOC_OVERRIDE_MEMALIGN -void * -je_memalign(size_t alignment, size_t size) -{ - void *ret JEMALLOC_CC_SILENCE_INIT(NULL); - imemalign(&ret, alignment, size, 1); - JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false); - return (ret); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) +je_memalign(size_t alignment, size_t size) { + void *ret; + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.bump_empty_alloc = true; + sopts.min_alignment = 1; + sopts.oom_string = + "<jemalloc>: Error allocating aligned memory: out of memory\n"; + sopts.invalid_alignment_string = + "<jemalloc>: Error allocating aligned memory: invalid alignment\n"; + sopts.null_out_result_on_error = true; + + dopts.result = &ret; + dopts.num_items = 1; + dopts.item_size = size; + dopts.alignment = alignment; + + imalloc(&sopts, &dopts); + return ret; } #endif #ifdef JEMALLOC_OVERRIDE_VALLOC -void * -je_valloc(size_t size) -{ - void *ret JEMALLOC_CC_SILENCE_INIT(NULL); - imemalign(&ret, PAGE, size, 1); - JEMALLOC_VALGRIND_MALLOC(ret != NULL, ret, size, false); - return (ret); +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) +je_valloc(size_t size) { + void *ret; + + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.bump_empty_alloc = true; + sopts.null_out_result_on_error = true; + sopts.min_alignment = PAGE; + sopts.oom_string = + "<jemalloc>: Error allocating aligned memory: out of memory\n"; + sopts.invalid_alignment_string = + "<jemalloc>: Error allocating aligned memory: invalid alignment\n"; + + dopts.result = &ret; + dopts.num_items = 1; + dopts.item_size = size; + dopts.alignment = PAGE; + + imalloc(&sopts, &dopts); + + return ret; } #endif -/* - * is_malloc(je_malloc) is some macro magic to detect if jemalloc_defs.h has - * #define je_malloc malloc - */ -#define malloc_is_malloc 1 -#define is_malloc_(a) malloc_is_ ## a -#define is_malloc(a) is_malloc_(a) - -#if ((is_malloc(je_malloc) == 1) && defined(__GLIBC__) && !defined(__UCLIBC__)) +#if defined(JEMALLOC_IS_MALLOC) && defined(JEMALLOC_GLIBC_MALLOC_HOOK) /* * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible * to inconsistently reference libc's malloc(3)-compatible functions @@ -1356,11 +2373,47 @@ je_valloc(size_t size) * passed an extra argument for the caller return address, which will be * ignored. */ -JEMALLOC_EXPORT void (* __free_hook)(void *ptr) = je_free; -JEMALLOC_EXPORT void *(* __malloc_hook)(size_t size) = je_malloc; -JEMALLOC_EXPORT void *(* __realloc_hook)(void *ptr, size_t size) = je_realloc; -JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) = +JEMALLOC_EXPORT void (*__free_hook)(void *ptr) = je_free; +JEMALLOC_EXPORT void *(*__malloc_hook)(size_t size) = je_malloc; +JEMALLOC_EXPORT void *(*__realloc_hook)(void *ptr, size_t size) = je_realloc; +# ifdef JEMALLOC_GLIBC_MEMALIGN_HOOK +JEMALLOC_EXPORT void *(*__memalign_hook)(size_t alignment, size_t size) = je_memalign; +# endif + +# ifdef CPU_COUNT +/* + * To enable static linking with glibc, the libc specific malloc interface must + * be implemented also, so none of glibc's malloc.o functions are added to the + * link. + */ +# define ALIAS(je_fn) __attribute__((alias (#je_fn), used)) +/* To force macro expansion of je_ prefix before stringification. */ +# define PREALIAS(je_fn) ALIAS(je_fn) +# ifdef JEMALLOC_OVERRIDE___LIBC_CALLOC +void *__libc_calloc(size_t n, size_t size) PREALIAS(je_calloc); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_FREE +void __libc_free(void* ptr) PREALIAS(je_free); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_MALLOC +void *__libc_malloc(size_t size) PREALIAS(je_malloc); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_MEMALIGN +void *__libc_memalign(size_t align, size_t s) PREALIAS(je_memalign); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_REALLOC +void *__libc_realloc(void* ptr, size_t size) PREALIAS(je_realloc); +# endif +# ifdef JEMALLOC_OVERRIDE___LIBC_VALLOC +void *__libc_valloc(size_t size) PREALIAS(je_valloc); +# endif +# ifdef JEMALLOC_OVERRIDE___POSIX_MEMALIGN +int __posix_memalign(void** r, size_t a, size_t s) PREALIAS(je_posix_memalign); +# endif +# undef PREALIAS +# undef ALIAS +# endif #endif /* @@ -1371,162 +2424,98 @@ JEMALLOC_EXPORT void *(* __memalign_hook)(size_t alignment, size_t size) = * Begin non-standard functions. */ -JEMALLOC_ALWAYS_INLINE_C void * -imallocx(size_t usize, size_t alignment, bool zero, bool try_tcache, - arena_t *arena) -{ - - assert(usize == ((alignment == 0) ? s2u(usize) : sa2u(usize, - alignment))); - - if (alignment != 0) - return (ipalloct(usize, alignment, zero, try_tcache, arena)); - else if (zero) - return (icalloct(usize, try_tcache, arena)); - else - return (imalloct(usize, try_tcache, arena)); -} - -static void * -imallocx_prof_sample(size_t usize, size_t alignment, bool zero, bool try_tcache, - arena_t *arena, prof_thr_cnt_t *cnt) -{ - void *p; - - if (cnt == NULL) - return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - size_t usize_promoted = (alignment == 0) ? - s2u(SMALL_MAXCLASS+1) : sa2u(SMALL_MAXCLASS+1, alignment); - assert(usize_promoted != 0); - p = imallocx(usize_promoted, alignment, zero, try_tcache, - arena); - if (p == NULL) - return (NULL); - arena_prof_promoted(p, usize); - } else - p = imallocx(usize, alignment, zero, try_tcache, arena); - - return (p); -} - -JEMALLOC_ALWAYS_INLINE_C void * -imallocx_prof(size_t usize, size_t alignment, bool zero, bool try_tcache, - arena_t *arena, prof_thr_cnt_t *cnt) -{ - void *p; - - if ((uintptr_t)cnt != (uintptr_t)1U) { - p = imallocx_prof_sample(usize, alignment, zero, try_tcache, - arena, cnt); - } else - p = imallocx(usize, alignment, zero, try_tcache, arena); - if (p == NULL) - return (NULL); - prof_malloc(p, usize, cnt); - - return (p); -} - -void * -je_mallocx(size_t size, int flags) -{ - void *p; - size_t usize; - size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK) - & (SIZE_T_MAX-1)); - bool zero = flags & MALLOCX_ZERO; - unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; - arena_t *arena; - bool try_tcache; +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1) +je_mallocx(size_t size, int flags) { + void *ret; + static_opts_t sopts; + dynamic_opts_t dopts; + + static_opts_init(&sopts); + dynamic_opts_init(&dopts); + + sopts.assert_nonempty_alloc = true; + sopts.null_out_result_on_error = true; + sopts.oom_string = "<jemalloc>: Error in mallocx(): out of memory\n"; + + dopts.result = &ret; + dopts.num_items = 1; + dopts.item_size = size; + if (unlikely(flags != 0)) { + if ((flags & MALLOCX_LG_ALIGN_MASK) != 0) { + dopts.alignment = MALLOCX_ALIGN_GET_SPECIFIED(flags); + } - assert(size != 0); + dopts.zero = MALLOCX_ZERO_GET(flags); - if (malloc_init()) - goto label_oom; + if ((flags & MALLOCX_TCACHE_MASK) != 0) { + if ((flags & MALLOCX_TCACHE_MASK) + == MALLOCX_TCACHE_NONE) { + dopts.tcache_ind = TCACHE_IND_NONE; + } else { + dopts.tcache_ind = MALLOCX_TCACHE_GET(flags); + } + } else { + dopts.tcache_ind = TCACHE_IND_AUTOMATIC; + } - if (arena_ind != UINT_MAX) { - arena = arenas[arena_ind]; - try_tcache = false; - } else { - arena = NULL; - try_tcache = true; + if ((flags & MALLOCX_ARENA_MASK) != 0) + dopts.arena_ind = MALLOCX_ARENA_GET(flags); } - usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); - assert(usize != 0); - - if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; - - PROF_ALLOC_PREP(1, usize, cnt); - p = imallocx_prof(usize, alignment, zero, try_tcache, arena, - cnt); - } else - p = imallocx(usize, alignment, zero, try_tcache, arena); - if (p == NULL) - goto label_oom; - - if (config_stats) { - assert(usize == isalloc(p, config_prof)); - thread_allocated_tsd_get()->allocated += usize; - } - UTRACE(0, size, p); - JEMALLOC_VALGRIND_MALLOC(true, p, usize, zero); - return (p); -label_oom: - if (config_xmalloc && opt_xmalloc) { - malloc_write("<jemalloc>: Error in mallocx(): out of memory\n"); - abort(); - } - UTRACE(0, size, 0); - return (NULL); + imalloc(&sopts, &dopts); + return ret; } static void * -irallocx_prof_sample(void *oldptr, size_t size, size_t alignment, size_t usize, - bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, arena_t *arena, - prof_thr_cnt_t *cnt) -{ +irallocx_prof_sample(tsdn_t *tsdn, void *old_ptr, size_t old_usize, + size_t usize, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena, + prof_tctx_t *tctx) { void *p; - if (cnt == NULL) - return (NULL); - if (prof_promote && usize <= SMALL_MAXCLASS) { - p = iralloct(oldptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >= - size) ? 0 : size - (SMALL_MAXCLASS+1), alignment, zero, - try_tcache_alloc, try_tcache_dalloc, arena); - if (p == NULL) - return (NULL); - arena_prof_promoted(p, usize); + if (tctx == NULL) { + return NULL; + } + if (usize <= SMALL_MAXCLASS) { + p = iralloct(tsdn, old_ptr, old_usize, LARGE_MINCLASS, + alignment, zero, tcache, arena); + if (p == NULL) { + return NULL; + } + arena_prof_promote(tsdn, p, usize); } else { - p = iralloct(oldptr, size, 0, alignment, zero, - try_tcache_alloc, try_tcache_dalloc, arena); + p = iralloct(tsdn, old_ptr, old_usize, usize, alignment, zero, + tcache, arena); } - return (p); + return p; } -JEMALLOC_ALWAYS_INLINE_C void * -irallocx_prof(void *oldptr, size_t old_usize, size_t size, size_t alignment, - size_t *usize, bool zero, bool try_tcache_alloc, bool try_tcache_dalloc, - arena_t *arena, prof_thr_cnt_t *cnt) -{ +JEMALLOC_ALWAYS_INLINE void * +irallocx_prof(tsd_t *tsd, void *old_ptr, size_t old_usize, size_t size, + size_t alignment, size_t *usize, bool zero, tcache_t *tcache, + arena_t *arena, alloc_ctx_t *alloc_ctx) { void *p; - prof_ctx_t *old_ctx; - - old_ctx = prof_ctx_get(oldptr); - if ((uintptr_t)cnt != (uintptr_t)1U) - p = irallocx_prof_sample(oldptr, size, alignment, *usize, zero, - try_tcache_alloc, try_tcache_dalloc, arena, cnt); - else { - p = iralloct(oldptr, size, 0, alignment, zero, - try_tcache_alloc, try_tcache_dalloc, arena); + bool prof_active; + prof_tctx_t *old_tctx, *tctx; + + prof_active = prof_active_get_unlocked(); + old_tctx = prof_tctx_get(tsd_tsdn(tsd), old_ptr, alloc_ctx); + tctx = prof_alloc_prep(tsd, *usize, prof_active, false); + if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { + p = irallocx_prof_sample(tsd_tsdn(tsd), old_ptr, old_usize, + *usize, alignment, zero, tcache, arena, tctx); + } else { + p = iralloct(tsd_tsdn(tsd), old_ptr, old_usize, size, alignment, + zero, tcache, arena); + } + if (unlikely(p == NULL)) { + prof_alloc_rollback(tsd, tctx, false); + return NULL; } - if (p == NULL) - return (NULL); - if (p == oldptr && alignment != 0) { + if (p == old_ptr && alignment != 0) { /* * The allocation did not move, so it is possible that the size * class is smaller than would guarantee the requested @@ -1535,421 +2524,467 @@ irallocx_prof(void *oldptr, size_t old_usize, size_t size, size_t alignment, * be the same as the current usize because of in-place large * reallocation. Therefore, query the actual value of usize. */ - *usize = isalloc(p, config_prof); + *usize = isalloc(tsd_tsdn(tsd), p); } - prof_realloc(p, *usize, cnt, old_usize, old_ctx); + prof_realloc(tsd, p, *usize, tctx, prof_active, false, old_ptr, + old_usize, old_tctx); - return (p); + return p; } -void * -je_rallocx(void *ptr, size_t size, int flags) -{ +JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN +void JEMALLOC_NOTHROW * +JEMALLOC_ALLOC_SIZE(2) +je_rallocx(void *ptr, size_t size, int flags) { void *p; - size_t usize, old_usize; - UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); - size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK) - & (SIZE_T_MAX-1)); + tsd_t *tsd; + size_t usize; + size_t old_usize; + size_t alignment = MALLOCX_ALIGN_GET(flags); bool zero = flags & MALLOCX_ZERO; - unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; - bool try_tcache_alloc, try_tcache_dalloc; arena_t *arena; + tcache_t *tcache; assert(ptr != NULL); assert(size != 0); - assert(malloc_initialized || IS_INITIALIZER); - malloc_thread_init(); - - if (arena_ind != UINT_MAX) { - arena_chunk_t *chunk; - try_tcache_alloc = false; - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - try_tcache_dalloc = (chunk == ptr || chunk->arena != - arenas[arena_ind]); - arena = arenas[arena_ind]; + assert(malloc_initialized() || IS_INITIALIZER); + tsd = tsd_fetch(); + check_entry_exit_locking(tsd_tsdn(tsd)); + + if (unlikely((flags & MALLOCX_ARENA_MASK) != 0)) { + unsigned arena_ind = MALLOCX_ARENA_GET(flags); + arena = arena_get(tsd_tsdn(tsd), arena_ind, true); + if (unlikely(arena == NULL)) { + goto label_oom; + } } else { - try_tcache_alloc = true; - try_tcache_dalloc = true; arena = NULL; } - if ((config_prof && opt_prof) || config_stats || - (config_valgrind && opt_valgrind)) - old_usize = isalloc(ptr, config_prof); - if (config_valgrind && opt_valgrind) - old_rzsize = u2rz(old_usize); + if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) { + if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) { + tcache = NULL; + } else { + tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); + } + } else { + tcache = tcache_get(tsd); + } + alloc_ctx_t alloc_ctx; + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind != NSIZES); + old_usize = sz_index2size(alloc_ctx.szind); + assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; - - usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); - assert(usize != 0); - PROF_ALLOC_PREP(1, usize, cnt); - p = irallocx_prof(ptr, old_usize, size, alignment, &usize, zero, - try_tcache_alloc, try_tcache_dalloc, arena, cnt); - if (p == NULL) + usize = (alignment == 0) ? + sz_s2u(size) : sz_sa2u(size, alignment); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + goto label_oom; + } + p = irallocx_prof(tsd, ptr, old_usize, size, alignment, &usize, + zero, tcache, arena, &alloc_ctx); + if (unlikely(p == NULL)) { goto label_oom; + } } else { - p = iralloct(ptr, size, 0, alignment, zero, try_tcache_alloc, - try_tcache_dalloc, arena); - if (p == NULL) + p = iralloct(tsd_tsdn(tsd), ptr, old_usize, size, alignment, + zero, tcache, arena); + if (unlikely(p == NULL)) { goto label_oom; - if (config_stats || (config_valgrind && opt_valgrind)) - usize = isalloc(p, config_prof); + } + if (config_stats) { + usize = isalloc(tsd_tsdn(tsd), p); + } } + assert(alignment == 0 || ((uintptr_t)p & (alignment - 1)) == ZU(0)); if (config_stats) { - thread_allocated_t *ta; - ta = thread_allocated_tsd_get(); - ta->allocated += usize; - ta->deallocated += old_usize; + *tsd_thread_allocatedp_get(tsd) += usize; + *tsd_thread_deallocatedp_get(tsd) += old_usize; } UTRACE(ptr, size, p); - JEMALLOC_VALGRIND_REALLOC(p, usize, ptr, old_usize, old_rzsize, zero); - return (p); + check_entry_exit_locking(tsd_tsdn(tsd)); + return p; label_oom: - if (config_xmalloc && opt_xmalloc) { + if (config_xmalloc && unlikely(opt_xmalloc)) { malloc_write("<jemalloc>: Error in rallocx(): out of memory\n"); abort(); } UTRACE(ptr, size, 0); - return (NULL); + check_entry_exit_locking(tsd_tsdn(tsd)); + return NULL; } -JEMALLOC_ALWAYS_INLINE_C size_t -ixallocx_helper(void *ptr, size_t old_usize, size_t size, size_t extra, - size_t alignment, bool zero, arena_t *arena) -{ +JEMALLOC_ALWAYS_INLINE size_t +ixallocx_helper(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size, + size_t extra, size_t alignment, bool zero) { size_t usize; - if (ixalloc(ptr, size, extra, alignment, zero)) - return (old_usize); - usize = isalloc(ptr, config_prof); + if (ixalloc(tsdn, ptr, old_usize, size, extra, alignment, zero)) { + return old_usize; + } + usize = isalloc(tsdn, ptr); - return (usize); + return usize; } static size_t -ixallocx_prof_sample(void *ptr, size_t old_usize, size_t size, size_t extra, - size_t alignment, size_t max_usize, bool zero, arena_t *arena, - prof_thr_cnt_t *cnt) -{ +ixallocx_prof_sample(tsdn_t *tsdn, void *ptr, size_t old_usize, size_t size, + size_t extra, size_t alignment, bool zero, prof_tctx_t *tctx) { size_t usize; - if (cnt == NULL) - return (old_usize); - /* Use minimum usize to determine whether promotion may happen. */ - if (prof_promote && ((alignment == 0) ? s2u(size) : sa2u(size, - alignment)) <= SMALL_MAXCLASS) { - if (ixalloc(ptr, SMALL_MAXCLASS+1, (SMALL_MAXCLASS+1 >= - size+extra) ? 0 : size+extra - (SMALL_MAXCLASS+1), - alignment, zero)) - return (old_usize); - usize = isalloc(ptr, config_prof); - if (max_usize < PAGE) - arena_prof_promoted(ptr, usize); - } else { - usize = ixallocx_helper(ptr, old_usize, size, extra, alignment, - zero, arena); + if (tctx == NULL) { + return old_usize; } + usize = ixallocx_helper(tsdn, ptr, old_usize, size, extra, alignment, + zero); - return (usize); + return usize; } -JEMALLOC_ALWAYS_INLINE_C size_t -ixallocx_prof(void *ptr, size_t old_usize, size_t size, size_t extra, - size_t alignment, size_t max_usize, bool zero, arena_t *arena, - prof_thr_cnt_t *cnt) -{ - size_t usize; - prof_ctx_t *old_ctx; +JEMALLOC_ALWAYS_INLINE size_t +ixallocx_prof(tsd_t *tsd, void *ptr, size_t old_usize, size_t size, + size_t extra, size_t alignment, bool zero, alloc_ctx_t *alloc_ctx) { + size_t usize_max, usize; + bool prof_active; + prof_tctx_t *old_tctx, *tctx; - old_ctx = prof_ctx_get(ptr); - if ((uintptr_t)cnt != (uintptr_t)1U) { - usize = ixallocx_prof_sample(ptr, old_usize, size, extra, - alignment, zero, max_usize, arena, cnt); + prof_active = prof_active_get_unlocked(); + old_tctx = prof_tctx_get(tsd_tsdn(tsd), ptr, alloc_ctx); + /* + * usize isn't knowable before ixalloc() returns when extra is non-zero. + * Therefore, compute its maximum possible value and use that in + * prof_alloc_prep() to decide whether to capture a backtrace. + * prof_realloc() will use the actual usize to decide whether to sample. + */ + if (alignment == 0) { + usize_max = sz_s2u(size+extra); + assert(usize_max > 0 && usize_max <= LARGE_MAXCLASS); + } else { + usize_max = sz_sa2u(size+extra, alignment); + if (unlikely(usize_max == 0 || usize_max > LARGE_MAXCLASS)) { + /* + * usize_max is out of range, and chances are that + * allocation will fail, but use the maximum possible + * value and carry on with prof_alloc_prep(), just in + * case allocation succeeds. + */ + usize_max = LARGE_MAXCLASS; + } + } + tctx = prof_alloc_prep(tsd, usize_max, prof_active, false); + + if (unlikely((uintptr_t)tctx != (uintptr_t)1U)) { + usize = ixallocx_prof_sample(tsd_tsdn(tsd), ptr, old_usize, + size, extra, alignment, zero, tctx); } else { - usize = ixallocx_helper(ptr, old_usize, size, extra, alignment, - zero, arena); + usize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size, + extra, alignment, zero); } - if (usize == old_usize) - return (usize); - prof_realloc(ptr, usize, cnt, old_usize, old_ctx); + if (usize == old_usize) { + prof_alloc_rollback(tsd, tctx, false); + return usize; + } + prof_realloc(tsd, ptr, usize, tctx, prof_active, false, ptr, old_usize, + old_tctx); - return (usize); + return usize; } -size_t -je_xallocx(void *ptr, size_t size, size_t extra, int flags) -{ +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +je_xallocx(void *ptr, size_t size, size_t extra, int flags) { + tsd_t *tsd; size_t usize, old_usize; - UNUSED size_t old_rzsize JEMALLOC_CC_SILENCE_INIT(0); - size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK) - & (SIZE_T_MAX-1)); + size_t alignment = MALLOCX_ALIGN_GET(flags); bool zero = flags & MALLOCX_ZERO; - unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; - arena_t *arena; assert(ptr != NULL); assert(size != 0); assert(SIZE_T_MAX - size >= extra); - assert(malloc_initialized || IS_INITIALIZER); - malloc_thread_init(); - - if (arena_ind != UINT_MAX) - arena = arenas[arena_ind]; - else - arena = NULL; - - old_usize = isalloc(ptr, config_prof); - if (config_valgrind && opt_valgrind) - old_rzsize = u2rz(old_usize); + assert(malloc_initialized() || IS_INITIALIZER); + tsd = tsd_fetch(); + check_entry_exit_locking(tsd_tsdn(tsd)); + + alloc_ctx_t alloc_ctx; + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsd); + rtree_szind_slab_read(tsd_tsdn(tsd), &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &alloc_ctx.szind, &alloc_ctx.slab); + assert(alloc_ctx.szind != NSIZES); + old_usize = sz_index2size(alloc_ctx.szind); + assert(old_usize == isalloc(tsd_tsdn(tsd), ptr)); + /* + * The API explicitly absolves itself of protecting against (size + + * extra) numerical overflow, but we may need to clamp extra to avoid + * exceeding LARGE_MAXCLASS. + * + * Ordinarily, size limit checking is handled deeper down, but here we + * have to check as part of (size + extra) clamping, since we need the + * clamped value in the above helper functions. + */ + if (unlikely(size > LARGE_MAXCLASS)) { + usize = old_usize; + goto label_not_resized; + } + if (unlikely(LARGE_MAXCLASS - size < extra)) { + extra = LARGE_MAXCLASS - size; + } if (config_prof && opt_prof) { - prof_thr_cnt_t *cnt; - /* - * usize isn't knowable before ixalloc() returns when extra is - * non-zero. Therefore, compute its maximum possible value and - * use that in PROF_ALLOC_PREP() to decide whether to capture a - * backtrace. prof_realloc() will use the actual usize to - * decide whether to sample. - */ - size_t max_usize = (alignment == 0) ? s2u(size+extra) : - sa2u(size+extra, alignment); - PROF_ALLOC_PREP(1, max_usize, cnt); - usize = ixallocx_prof(ptr, old_usize, size, extra, alignment, - max_usize, zero, arena, cnt); + usize = ixallocx_prof(tsd, ptr, old_usize, size, extra, + alignment, zero, &alloc_ctx); } else { - usize = ixallocx_helper(ptr, old_usize, size, extra, alignment, - zero, arena); + usize = ixallocx_helper(tsd_tsdn(tsd), ptr, old_usize, size, + extra, alignment, zero); } - if (usize == old_usize) + if (unlikely(usize == old_usize)) { goto label_not_resized; + } if (config_stats) { - thread_allocated_t *ta; - ta = thread_allocated_tsd_get(); - ta->allocated += usize; - ta->deallocated += old_usize; + *tsd_thread_allocatedp_get(tsd) += usize; + *tsd_thread_deallocatedp_get(tsd) += old_usize; } - JEMALLOC_VALGRIND_REALLOC(ptr, usize, ptr, old_usize, old_rzsize, zero); label_not_resized: UTRACE(ptr, size, ptr); - return (usize); + check_entry_exit_locking(tsd_tsdn(tsd)); + return usize; } -size_t -je_sallocx(const void *ptr, int flags) -{ +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +JEMALLOC_ATTR(pure) +je_sallocx(const void *ptr, int flags) { size_t usize; + tsdn_t *tsdn; + + assert(malloc_initialized() || IS_INITIALIZER); + assert(ptr != NULL); - assert(malloc_initialized || IS_INITIALIZER); - malloc_thread_init(); + tsdn = tsdn_fetch(); + check_entry_exit_locking(tsdn); - if (config_ivsalloc) - usize = ivsalloc(ptr, config_prof); - else { - assert(ptr != NULL); - usize = isalloc(ptr, config_prof); + if (config_debug || force_ivsalloc) { + usize = ivsalloc(tsdn, ptr); + assert(force_ivsalloc || usize != 0); + } else { + usize = isalloc(tsdn, ptr); } - return (usize); + check_entry_exit_locking(tsdn); + return usize; } -void -je_dallocx(void *ptr, int flags) -{ +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_dallocx(void *ptr, int flags) { + assert(ptr != NULL); + assert(malloc_initialized() || IS_INITIALIZER); + + tsd_t *tsd = tsd_fetch(); + bool fast = tsd_fast(tsd); + check_entry_exit_locking(tsd_tsdn(tsd)); + + tcache_t *tcache; + if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) { + /* Not allowed to be reentrant and specify a custom tcache. */ + assert(tsd_reentrancy_level_get(tsd) == 0); + if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) { + tcache = NULL; + } else { + tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); + } + } else { + if (likely(fast)) { + tcache = tsd_tcachep_get(tsd); + assert(tcache == tcache_get(tsd)); + } else { + if (likely(tsd_reentrancy_level_get(tsd) == 0)) { + tcache = tcache_get(tsd); + } else { + tcache = NULL; + } + } + } + + UTRACE(ptr, 0, 0); + if (likely(fast)) { + tsd_assert_fast(tsd); + ifree(tsd, ptr, tcache, false); + } else { + ifree(tsd, ptr, tcache, true); + } + check_entry_exit_locking(tsd_tsdn(tsd)); +} + +JEMALLOC_ALWAYS_INLINE size_t +inallocx(tsdn_t *tsdn, size_t size, int flags) { + check_entry_exit_locking(tsdn); + size_t usize; - UNUSED size_t rzsize JEMALLOC_CC_SILENCE_INIT(0); - unsigned arena_ind = ((unsigned)(flags >> 8)) - 1; - bool try_tcache; + if (likely((flags & MALLOCX_LG_ALIGN_MASK) == 0)) { + usize = sz_s2u(size); + } else { + usize = sz_sa2u(size, MALLOCX_ALIGN_GET_SPECIFIED(flags)); + } + check_entry_exit_locking(tsdn); + return usize; +} +JEMALLOC_EXPORT void JEMALLOC_NOTHROW +je_sdallocx(void *ptr, size_t size, int flags) { assert(ptr != NULL); - assert(malloc_initialized || IS_INITIALIZER); - - if (arena_ind != UINT_MAX) { - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - try_tcache = (chunk == ptr || chunk->arena != - arenas[arena_ind]); - } else - try_tcache = true; + assert(malloc_initialized() || IS_INITIALIZER); + + tsd_t *tsd = tsd_fetch(); + bool fast = tsd_fast(tsd); + size_t usize = inallocx(tsd_tsdn(tsd), size, flags); + assert(usize == isalloc(tsd_tsdn(tsd), ptr)); + check_entry_exit_locking(tsd_tsdn(tsd)); + + tcache_t *tcache; + if (unlikely((flags & MALLOCX_TCACHE_MASK) != 0)) { + /* Not allowed to be reentrant and specify a custom tcache. */ + assert(tsd_reentrancy_level_get(tsd) == 0); + if ((flags & MALLOCX_TCACHE_MASK) == MALLOCX_TCACHE_NONE) { + tcache = NULL; + } else { + tcache = tcaches_get(tsd, MALLOCX_TCACHE_GET(flags)); + } + } else { + if (likely(fast)) { + tcache = tsd_tcachep_get(tsd); + assert(tcache == tcache_get(tsd)); + } else { + if (likely(tsd_reentrancy_level_get(tsd) == 0)) { + tcache = tcache_get(tsd); + } else { + tcache = NULL; + } + } + } UTRACE(ptr, 0, 0); - if (config_stats || config_valgrind) - usize = isalloc(ptr, config_prof); - if (config_prof && opt_prof) { - if (config_stats == false && config_valgrind == false) - usize = isalloc(ptr, config_prof); - prof_free(ptr, usize); + if (likely(fast)) { + tsd_assert_fast(tsd); + isfree(tsd, ptr, usize, tcache, false); + } else { + isfree(tsd, ptr, usize, tcache, true); } - if (config_stats) - thread_allocated_tsd_get()->deallocated += usize; - if (config_valgrind && opt_valgrind) - rzsize = p2rz(ptr); - iqalloct(ptr, try_tcache); - JEMALLOC_VALGRIND_FREE(ptr, rzsize); + check_entry_exit_locking(tsd_tsdn(tsd)); } -size_t -je_nallocx(size_t size, int flags) -{ +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +JEMALLOC_ATTR(pure) +je_nallocx(size_t size, int flags) { size_t usize; - size_t alignment = (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK) - & (SIZE_T_MAX-1)); + tsdn_t *tsdn; assert(size != 0); - if (malloc_init()) - return (0); + if (unlikely(malloc_init())) { + return 0; + } + + tsdn = tsdn_fetch(); + check_entry_exit_locking(tsdn); - usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment); - assert(usize != 0); - return (usize); + usize = inallocx(tsdn, size, flags); + if (unlikely(usize > LARGE_MAXCLASS)) { + return 0; + } + + check_entry_exit_locking(tsdn); + return usize; } -int +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, - size_t newlen) -{ + size_t newlen) { + int ret; + tsd_t *tsd; - if (malloc_init()) - return (EAGAIN); + if (unlikely(malloc_init())) { + return EAGAIN; + } - return (ctl_byname(name, oldp, oldlenp, newp, newlen)); + tsd = tsd_fetch(); + check_entry_exit_locking(tsd_tsdn(tsd)); + ret = ctl_byname(tsd, name, oldp, oldlenp, newp, newlen); + check_entry_exit_locking(tsd_tsdn(tsd)); + return ret; } -int -je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) -{ +JEMALLOC_EXPORT int JEMALLOC_NOTHROW +je_mallctlnametomib(const char *name, size_t *mibp, size_t *miblenp) { + int ret; - if (malloc_init()) - return (EAGAIN); + if (unlikely(malloc_init())) { + return EAGAIN; + } - return (ctl_nametomib(name, mibp, miblenp)); + tsd_t *tsd = tsd_fetch(); + check_entry_exit_locking(tsd_tsdn(tsd)); + ret = ctl_nametomib(tsd, name, mibp, miblenp); + check_entry_exit_locking(tsd_tsdn(tsd)); + return ret; } -int +JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_mallctlbymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, - void *newp, size_t newlen) -{ + void *newp, size_t newlen) { + int ret; + tsd_t *tsd; - if (malloc_init()) - return (EAGAIN); + if (unlikely(malloc_init())) { + return EAGAIN; + } - return (ctl_bymib(mib, miblen, oldp, oldlenp, newp, newlen)); + tsd = tsd_fetch(); + check_entry_exit_locking(tsd_tsdn(tsd)); + ret = ctl_bymib(tsd, mib, miblen, oldp, oldlenp, newp, newlen); + check_entry_exit_locking(tsd_tsdn(tsd)); + return ret; } -void +JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_malloc_stats_print(void (*write_cb)(void *, const char *), void *cbopaque, - const char *opts) -{ + const char *opts) { + tsdn_t *tsdn; + tsdn = tsdn_fetch(); + check_entry_exit_locking(tsdn); stats_print(write_cb, cbopaque, opts); + check_entry_exit_locking(tsdn); } -size_t -je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) -{ +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW +je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr) { size_t ret; + tsdn_t *tsdn; - assert(malloc_initialized || IS_INITIALIZER); - malloc_thread_init(); - - if (config_ivsalloc) - ret = ivsalloc(ptr, config_prof); - else - ret = (ptr != NULL) ? isalloc(ptr, config_prof) : 0; - - return (ret); -} - -/* - * End non-standard functions. - */ -/******************************************************************************/ -/* - * Begin experimental functions. - */ -#ifdef JEMALLOC_EXPERIMENTAL - -int -je_allocm(void **ptr, size_t *rsize, size_t size, int flags) -{ - void *p; - - assert(ptr != NULL); - - p = je_mallocx(size, flags); - if (p == NULL) - return (ALLOCM_ERR_OOM); - if (rsize != NULL) - *rsize = isalloc(p, config_prof); - *ptr = p; - return (ALLOCM_SUCCESS); -} - -int -je_rallocm(void **ptr, size_t *rsize, size_t size, size_t extra, int flags) -{ - int ret; - bool no_move = flags & ALLOCM_NO_MOVE; + assert(malloc_initialized() || IS_INITIALIZER); - assert(ptr != NULL); - assert(*ptr != NULL); - assert(size != 0); - assert(SIZE_T_MAX - size >= extra); + tsdn = tsdn_fetch(); + check_entry_exit_locking(tsdn); - if (no_move) { - size_t usize = je_xallocx(*ptr, size, extra, flags); - ret = (usize >= size) ? ALLOCM_SUCCESS : ALLOCM_ERR_NOT_MOVED; - if (rsize != NULL) - *rsize = usize; + if (unlikely(ptr == NULL)) { + ret = 0; } else { - void *p = je_rallocx(*ptr, size+extra, flags); - if (p != NULL) { - *ptr = p; - ret = ALLOCM_SUCCESS; - } else - ret = ALLOCM_ERR_OOM; - if (rsize != NULL) - *rsize = isalloc(*ptr, config_prof); + if (config_debug || force_ivsalloc) { + ret = ivsalloc(tsdn, ptr); + assert(force_ivsalloc || ret != 0); + } else { + ret = isalloc(tsdn, ptr); + } } - return (ret); -} - -int -je_sallocm(const void *ptr, size_t *rsize, int flags) -{ - - assert(rsize != NULL); - *rsize = je_sallocx(ptr, flags); - return (ALLOCM_SUCCESS); -} - -int -je_dallocm(void *ptr, int flags) -{ - je_dallocx(ptr, flags); - return (ALLOCM_SUCCESS); + check_entry_exit_locking(tsdn); + return ret; } -int -je_nallocm(size_t *rsize, size_t size, int flags) -{ - size_t usize; - - usize = je_nallocx(size, flags); - if (usize == 0) - return (ALLOCM_ERR_OOM); - if (rsize != NULL) - *rsize = usize; - return (ALLOCM_SUCCESS); -} - -#endif /* - * End experimental functions. + * End non-standard functions. */ /******************************************************************************/ /* @@ -1966,17 +3001,17 @@ je_nallocm(size_t *rsize, size_t size, int flags) * fork/malloc races via the following functions it registers during * initialization using pthread_atfork(), but of course that does no good if * the allocator isn't fully initialized at fork time. The following library - * constructor is a partial solution to this problem. It may still possible to - * trigger the deadlock described above, but doing so would involve forking via - * a library constructor that runs before jemalloc's runs. + * constructor is a partial solution to this problem. It may still be possible + * to trigger the deadlock described above, but doing so would involve forking + * via a library constructor that runs before jemalloc's runs. */ +#ifndef JEMALLOC_JET JEMALLOC_ATTR(constructor) static void -jemalloc_constructor(void) -{ - +jemalloc_constructor(void) { malloc_init(); } +#endif #ifndef JEMALLOC_MUTEX_INIT_CB void @@ -1986,25 +3021,69 @@ JEMALLOC_EXPORT void _malloc_prefork(void) #endif { - unsigned i; + tsd_t *tsd; + unsigned i, j, narenas; + arena_t *arena; #ifdef JEMALLOC_MUTEX_INIT_CB - if (malloc_initialized == false) + if (!malloc_initialized()) { return; + } #endif - assert(malloc_initialized); + assert(malloc_initialized()); + tsd = tsd_fetch(); + + narenas = narenas_total_get(); + + witness_prefork(tsd_witness_tsdp_get(tsd)); /* Acquire all mutexes in a safe order. */ - ctl_prefork(); - prof_prefork(); - malloc_mutex_prefork(&arenas_lock); - for (i = 0; i < narenas_total; i++) { - if (arenas[i] != NULL) - arena_prefork(arenas[i]); + ctl_prefork(tsd_tsdn(tsd)); + tcache_prefork(tsd_tsdn(tsd)); + malloc_mutex_prefork(tsd_tsdn(tsd), &arenas_lock); + if (have_background_thread) { + background_thread_prefork0(tsd_tsdn(tsd)); + } + prof_prefork0(tsd_tsdn(tsd)); + if (have_background_thread) { + background_thread_prefork1(tsd_tsdn(tsd)); + } + /* Break arena prefork into stages to preserve lock order. */ + for (i = 0; i < 8; i++) { + for (j = 0; j < narenas; j++) { + if ((arena = arena_get(tsd_tsdn(tsd), j, false)) != + NULL) { + switch (i) { + case 0: + arena_prefork0(tsd_tsdn(tsd), arena); + break; + case 1: + arena_prefork1(tsd_tsdn(tsd), arena); + break; + case 2: + arena_prefork2(tsd_tsdn(tsd), arena); + break; + case 3: + arena_prefork3(tsd_tsdn(tsd), arena); + break; + case 4: + arena_prefork4(tsd_tsdn(tsd), arena); + break; + case 5: + arena_prefork5(tsd_tsdn(tsd), arena); + break; + case 6: + arena_prefork6(tsd_tsdn(tsd), arena); + break; + case 7: + arena_prefork7(tsd_tsdn(tsd), arena); + break; + default: not_reached(); + } + } + } } - chunk_prefork(); - base_prefork(); - huge_prefork(); + prof_prefork1(tsd_tsdn(tsd)); } #ifndef JEMALLOC_MUTEX_INIT_CB @@ -2015,97 +3094,61 @@ JEMALLOC_EXPORT void _malloc_postfork(void) #endif { - unsigned i; + tsd_t *tsd; + unsigned i, narenas; #ifdef JEMALLOC_MUTEX_INIT_CB - if (malloc_initialized == false) + if (!malloc_initialized()) { return; -#endif - assert(malloc_initialized); - - /* Release all mutexes, now that fork() has completed. */ - huge_postfork_parent(); - base_postfork_parent(); - chunk_postfork_parent(); - for (i = 0; i < narenas_total; i++) { - if (arenas[i] != NULL) - arena_postfork_parent(arenas[i]); } - malloc_mutex_postfork_parent(&arenas_lock); - prof_postfork_parent(); - ctl_postfork_parent(); -} - -void -jemalloc_postfork_child(void) -{ - unsigned i; +#endif + assert(malloc_initialized()); - assert(malloc_initialized); + tsd = tsd_fetch(); + witness_postfork_parent(tsd_witness_tsdp_get(tsd)); /* Release all mutexes, now that fork() has completed. */ - huge_postfork_child(); - base_postfork_child(); - chunk_postfork_child(); - for (i = 0; i < narenas_total; i++) { - if (arenas[i] != NULL) - arena_postfork_child(arenas[i]); - } - malloc_mutex_postfork_child(&arenas_lock); - prof_postfork_child(); - ctl_postfork_child(); -} + for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { + arena_t *arena; -/******************************************************************************/ -/* - * The following functions are used for TLS allocation/deallocation in static - * binaries on FreeBSD. The primary difference between these and i[mcd]alloc() - * is that these avoid accessing TLS variables. - */ - -static void * -a0alloc(size_t size, bool zero) -{ - - if (malloc_init()) - return (NULL); - - if (size == 0) - size = 1; - - if (size <= arena_maxclass) - return (arena_malloc(arenas[0], size, zero, false)); - else - return (huge_malloc(size, zero, huge_dss_prec_get(arenas[0]))); -} - -void * -a0malloc(size_t size) -{ - - return (a0alloc(size, false)); + if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL) { + arena_postfork_parent(tsd_tsdn(tsd), arena); + } + } + prof_postfork_parent(tsd_tsdn(tsd)); + if (have_background_thread) { + background_thread_postfork_parent(tsd_tsdn(tsd)); + } + malloc_mutex_postfork_parent(tsd_tsdn(tsd), &arenas_lock); + tcache_postfork_parent(tsd_tsdn(tsd)); + ctl_postfork_parent(tsd_tsdn(tsd)); } -void * -a0calloc(size_t num, size_t size) -{ +void +jemalloc_postfork_child(void) { + tsd_t *tsd; + unsigned i, narenas; - return (a0alloc(num * size, true)); -} + assert(malloc_initialized()); -void -a0free(void *ptr) -{ - arena_chunk_t *chunk; + tsd = tsd_fetch(); - if (ptr == NULL) - return; + witness_postfork_child(tsd_witness_tsdp_get(tsd)); + /* Release all mutexes, now that fork() has completed. */ + for (i = 0, narenas = narenas_total_get(); i < narenas; i++) { + arena_t *arena; - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk != ptr) - arena_dalloc(chunk->arena, chunk, ptr, false); - else - huge_dalloc(ptr, true); + if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL) { + arena_postfork_child(tsd_tsdn(tsd), arena); + } + } + prof_postfork_child(tsd_tsdn(tsd)); + if (have_background_thread) { + background_thread_postfork_child(tsd_tsdn(tsd)); + } + malloc_mutex_postfork_child(tsd_tsdn(tsd), &arenas_lock); + tcache_postfork_child(tsd_tsdn(tsd)); + ctl_postfork_child(tsd_tsdn(tsd)); } /******************************************************************************/ diff --git a/deps/jemalloc/src/mutex.c b/deps/jemalloc/src/mutex.c index 788eca3870..a528ef0c24 100644 --- a/deps/jemalloc/src/mutex.c +++ b/deps/jemalloc/src/mutex.c @@ -1,12 +1,12 @@ -#define JEMALLOC_MUTEX_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_MUTEX_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" -#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) -#include <dlfcn.h> -#endif +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/malloc_io.h" #ifndef _CRT_SPINCOUNT -#define _CRT_SPINCOUNT 4000 +#define _CRT_SPINCOUNT 4000 #endif /******************************************************************************/ @@ -20,10 +20,6 @@ static bool postpone_init = true; static malloc_mutex_t *postponed_mutexes = NULL; #endif -#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) -static void pthread_create_once(void); -#endif - /******************************************************************************/ /* * We intercept pthread_create() calls in order to toggle isthreaded if the @@ -31,33 +27,11 @@ static void pthread_create_once(void); */ #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) -static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, - void *(*)(void *), void *__restrict); - -static void -pthread_create_once(void) -{ - - pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); - if (pthread_create_fptr == NULL) { - malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, " - "\"pthread_create\")\n"); - abort(); - } - - isthreaded = true; -} - JEMALLOC_EXPORT int pthread_create(pthread_t *__restrict thread, const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), - void *__restrict arg) -{ - static pthread_once_t once_control = PTHREAD_ONCE_INIT; - - pthread_once(&once_control, pthread_create_once); - - return (pthread_create_fptr(thread, attr, start_routine, arg)); + void *__restrict arg) { + return pthread_create_wrapper(thread, attr, start_routine, arg); } #endif @@ -68,14 +42,108 @@ JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, void *(calloc_cb)(size_t, size_t)); #endif -bool -malloc_mutex_init(malloc_mutex_t *mutex) -{ +void +malloc_mutex_lock_slow(malloc_mutex_t *mutex) { + mutex_prof_data_t *data = &mutex->prof_data; + UNUSED nstime_t before = NSTIME_ZERO_INITIALIZER; + + if (ncpus == 1) { + goto label_spin_done; + } + + int cnt = 0, max_cnt = MALLOC_MUTEX_MAX_SPIN; + do { + CPU_SPINWAIT; + if (!malloc_mutex_trylock_final(mutex)) { + data->n_spin_acquired++; + return; + } + } while (cnt++ < max_cnt); + + if (!config_stats) { + /* Only spin is useful when stats is off. */ + malloc_mutex_lock_final(mutex); + return; + } +label_spin_done: + nstime_update(&before); + /* Copy before to after to avoid clock skews. */ + nstime_t after; + nstime_copy(&after, &before); + uint32_t n_thds = atomic_fetch_add_u32(&data->n_waiting_thds, 1, + ATOMIC_RELAXED) + 1; + /* One last try as above two calls may take quite some cycles. */ + if (!malloc_mutex_trylock_final(mutex)) { + atomic_fetch_sub_u32(&data->n_waiting_thds, 1, ATOMIC_RELAXED); + data->n_spin_acquired++; + return; + } + + /* True slow path. */ + malloc_mutex_lock_final(mutex); + /* Update more slow-path only counters. */ + atomic_fetch_sub_u32(&data->n_waiting_thds, 1, ATOMIC_RELAXED); + nstime_update(&after); + + nstime_t delta; + nstime_copy(&delta, &after); + nstime_subtract(&delta, &before); + data->n_wait_times++; + nstime_add(&data->tot_wait_time, &delta); + if (nstime_compare(&data->max_wait_time, &delta) < 0) { + nstime_copy(&data->max_wait_time, &delta); + } + if (n_thds > data->max_n_thds) { + data->max_n_thds = n_thds; + } +} + +static void +mutex_prof_data_init(mutex_prof_data_t *data) { + memset(data, 0, sizeof(mutex_prof_data_t)); + nstime_init(&data->max_wait_time, 0); + nstime_init(&data->tot_wait_time, 0); + data->prev_owner = NULL; +} + +void +malloc_mutex_prof_data_reset(tsdn_t *tsdn, malloc_mutex_t *mutex) { + malloc_mutex_assert_owner(tsdn, mutex); + mutex_prof_data_init(&mutex->prof_data); +} + +static int +mutex_addr_comp(const witness_t *witness1, void *mutex1, + const witness_t *witness2, void *mutex2) { + assert(mutex1 != NULL); + assert(mutex2 != NULL); + uintptr_t mu1int = (uintptr_t)mutex1; + uintptr_t mu2int = (uintptr_t)mutex2; + if (mu1int < mu2int) { + return -1; + } else if (mu1int == mu2int) { + return 0; + } else { + return 1; + } +} + +bool +malloc_mutex_init(malloc_mutex_t *mutex, const char *name, + witness_rank_t rank, malloc_mutex_lock_order_t lock_order) { + mutex_prof_data_init(&mutex->prof_data); #ifdef _WIN32 +# if _WIN32_WINNT >= 0x0600 + InitializeSRWLock(&mutex->lock); +# else if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, - _CRT_SPINCOUNT)) - return (true); + _CRT_SPINCOUNT)) { + return true; + } +# endif +#elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) + mutex->lock = OS_UNFAIR_LOCK_INIT; #elif (defined(JEMALLOC_OSSPIN)) mutex->lock = 0; #elif (defined(JEMALLOC_MUTEX_INIT_CB)) @@ -83,67 +151,73 @@ malloc_mutex_init(malloc_mutex_t *mutex) mutex->postponed_next = postponed_mutexes; postponed_mutexes = mutex; } else { - if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) != - 0) - return (true); + if (_pthread_mutex_init_calloc_cb(&mutex->lock, + bootstrap_calloc) != 0) { + return true; + } } #else pthread_mutexattr_t attr; - if (pthread_mutexattr_init(&attr) != 0) - return (true); + if (pthread_mutexattr_init(&attr) != 0) { + return true; + } pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); if (pthread_mutex_init(&mutex->lock, &attr) != 0) { pthread_mutexattr_destroy(&attr); - return (true); + return true; } pthread_mutexattr_destroy(&attr); #endif - return (false); + if (config_debug) { + mutex->lock_order = lock_order; + if (lock_order == malloc_mutex_address_ordered) { + witness_init(&mutex->witness, name, rank, + mutex_addr_comp, &mutex); + } else { + witness_init(&mutex->witness, name, rank, NULL, NULL); + } + } + return false; } void -malloc_mutex_prefork(malloc_mutex_t *mutex) -{ - - malloc_mutex_lock(mutex); +malloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex) { + malloc_mutex_lock(tsdn, mutex); } void -malloc_mutex_postfork_parent(malloc_mutex_t *mutex) -{ - - malloc_mutex_unlock(mutex); +malloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex) { + malloc_mutex_unlock(tsdn, mutex); } void -malloc_mutex_postfork_child(malloc_mutex_t *mutex) -{ - +malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex) { #ifdef JEMALLOC_MUTEX_INIT_CB - malloc_mutex_unlock(mutex); + malloc_mutex_unlock(tsdn, mutex); #else - if (malloc_mutex_init(mutex)) { + if (malloc_mutex_init(mutex, mutex->witness.name, + mutex->witness.rank, mutex->lock_order)) { malloc_printf("<jemalloc>: Error re-initializing mutex in " "child\n"); - if (opt_abort) + if (opt_abort) { abort(); + } } #endif } bool -mutex_boot(void) -{ - +malloc_mutex_boot(void) { #ifdef JEMALLOC_MUTEX_INIT_CB postpone_init = false; while (postponed_mutexes != NULL) { if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, - base_calloc) != 0) - return (true); + bootstrap_calloc) != 0) { + return true; + } postponed_mutexes = postponed_mutexes->postponed_next; } #endif - return (false); + return false; } diff --git a/deps/jemalloc/src/prof.c b/deps/jemalloc/src/prof.c index 7722b7b437..975722c4c3 100644 --- a/deps/jemalloc/src/prof.c +++ b/deps/jemalloc/src/prof.c @@ -1,27 +1,41 @@ -#define JEMALLOC_PROF_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_PROF_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/hash.h" +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/mutex.h" + /******************************************************************************/ #ifdef JEMALLOC_PROF_LIBUNWIND -#define UNW_LOCAL_ONLY +#define UNW_LOCAL_ONLY #include <libunwind.h> #endif #ifdef JEMALLOC_PROF_LIBGCC +/* + * We have a circular dependency -- jemalloc_internal.h tells us if we should + * use libgcc's unwinding functionality, but after we've included that, we've + * already hooked _Unwind_Backtrace. We'll temporarily disable hooking. + */ +#undef _Unwind_Backtrace #include <unwind.h> +#define _Unwind_Backtrace JEMALLOC_HOOK(_Unwind_Backtrace, hooks_libc_hook) #endif /******************************************************************************/ /* Data. */ -malloc_tsd_data(, prof_tdata, prof_tdata_t *, NULL) - bool opt_prof = false; bool opt_prof_active = true; +bool opt_prof_thread_active_init = true; size_t opt_lg_prof_sample = LG_PROF_SAMPLE_DEFAULT; ssize_t opt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT; bool opt_prof_gdump = false; -bool opt_prof_final = true; +bool opt_prof_final = false; bool opt_prof_leak = false; bool opt_prof_accum = false; char opt_prof_prefix[ @@ -31,25 +45,66 @@ char opt_prof_prefix[ #endif 1]; +/* + * Initialized as opt_prof_active, and accessed via + * prof_active_[gs]et{_unlocked,}(). + */ +bool prof_active; +static malloc_mutex_t prof_active_mtx; + +/* + * Initialized as opt_prof_thread_active_init, and accessed via + * prof_thread_active_init_[gs]et(). + */ +static bool prof_thread_active_init; +static malloc_mutex_t prof_thread_active_init_mtx; + +/* + * Initialized as opt_prof_gdump, and accessed via + * prof_gdump_[gs]et{_unlocked,}(). + */ +bool prof_gdump_val; +static malloc_mutex_t prof_gdump_mtx; + uint64_t prof_interval = 0; -bool prof_promote; + +size_t lg_prof_sample; /* - * Table of mutexes that are shared among ctx's. These are leaf locks, so - * there is no problem with using them for more than one ctx at the same time. - * The primary motivation for this sharing though is that ctx's are ephemeral, + * Table of mutexes that are shared among gctx's. These are leaf locks, so + * there is no problem with using them for more than one gctx at the same time. + * The primary motivation for this sharing though is that gctx's are ephemeral, * and destroying mutexes causes complications for systems that allocate when * creating/destroying mutexes. */ -static malloc_mutex_t *ctx_locks; -static unsigned cum_ctxs; /* Atomic counter. */ +static malloc_mutex_t *gctx_locks; +static atomic_u_t cum_gctxs; /* Atomic counter. */ /* - * Global hash of (prof_bt_t *)-->(prof_ctx_t *). This is the master data + * Table of mutexes that are shared among tdata's. No operations require + * holding multiple tdata locks, so there is no problem with using them for more + * than one tdata at the same time, even though a gctx lock may be acquired + * while holding a tdata lock. + */ +static malloc_mutex_t *tdata_locks; + +/* + * Global hash of (prof_bt_t *)-->(prof_gctx_t *). This is the master data * structure that knows about all backtraces currently captured. */ -static ckh_t bt2ctx; -static malloc_mutex_t bt2ctx_mtx; +static ckh_t bt2gctx; +/* Non static to enable profiling. */ +malloc_mutex_t bt2gctx_mtx; + +/* + * Tree of all extant prof_tdata_t structures, regardless of state, + * {attached,detached,expired}. + */ +static prof_tdata_tree_t tdatas; +static malloc_mutex_t tdatas_mtx; + +static uint64_t next_thr_uid; +static malloc_mutex_t next_thr_uid_mtx; static malloc_mutex_t prof_dump_seq_mtx; static uint64_t prof_dump_seq; @@ -70,161 +125,242 @@ static char prof_dump_buf[ 1 #endif ]; -static unsigned prof_dump_buf_end; +static size_t prof_dump_buf_end; static int prof_dump_fd; /* Do not dump any profiles until bootstrapping is complete. */ static bool prof_booted = false; /******************************************************************************/ +/* + * Function prototypes for static functions that are referenced prior to + * definition. + */ -void -bt_init(prof_bt_t *bt, void **vec) -{ +static bool prof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx); +static void prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx); +static bool prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata, + bool even_if_attached); +static void prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata, + bool even_if_attached); +static char *prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name); - cassert(config_prof); +/******************************************************************************/ +/* Red-black trees. */ - bt->vec = vec; - bt->len = 0; +static int +prof_tctx_comp(const prof_tctx_t *a, const prof_tctx_t *b) { + uint64_t a_thr_uid = a->thr_uid; + uint64_t b_thr_uid = b->thr_uid; + int ret = (a_thr_uid > b_thr_uid) - (a_thr_uid < b_thr_uid); + if (ret == 0) { + uint64_t a_thr_discrim = a->thr_discrim; + uint64_t b_thr_discrim = b->thr_discrim; + ret = (a_thr_discrim > b_thr_discrim) - (a_thr_discrim < + b_thr_discrim); + if (ret == 0) { + uint64_t a_tctx_uid = a->tctx_uid; + uint64_t b_tctx_uid = b->tctx_uid; + ret = (a_tctx_uid > b_tctx_uid) - (a_tctx_uid < + b_tctx_uid); + } + } + return ret; } -static void -bt_destroy(prof_bt_t *bt) -{ +rb_gen(static UNUSED, tctx_tree_, prof_tctx_tree_t, prof_tctx_t, + tctx_link, prof_tctx_comp) - cassert(config_prof); +static int +prof_gctx_comp(const prof_gctx_t *a, const prof_gctx_t *b) { + unsigned a_len = a->bt.len; + unsigned b_len = b->bt.len; + unsigned comp_len = (a_len < b_len) ? a_len : b_len; + int ret = memcmp(a->bt.vec, b->bt.vec, comp_len * sizeof(void *)); + if (ret == 0) { + ret = (a_len > b_len) - (a_len < b_len); + } + return ret; +} + +rb_gen(static UNUSED, gctx_tree_, prof_gctx_tree_t, prof_gctx_t, dump_link, + prof_gctx_comp) + +static int +prof_tdata_comp(const prof_tdata_t *a, const prof_tdata_t *b) { + int ret; + uint64_t a_uid = a->thr_uid; + uint64_t b_uid = b->thr_uid; + + ret = ((a_uid > b_uid) - (a_uid < b_uid)); + if (ret == 0) { + uint64_t a_discrim = a->thr_discrim; + uint64_t b_discrim = b->thr_discrim; - idalloc(bt); + ret = ((a_discrim > b_discrim) - (a_discrim < b_discrim)); + } + return ret; } -static prof_bt_t * -bt_dup(prof_bt_t *bt) -{ - prof_bt_t *ret; +rb_gen(static UNUSED, tdata_tree_, prof_tdata_tree_t, prof_tdata_t, tdata_link, + prof_tdata_comp) + +/******************************************************************************/ + +void +prof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated) { + prof_tdata_t *tdata; cassert(config_prof); - /* - * Create a single allocation that has space for vec immediately - * following the prof_bt_t structure. The backtraces that get - * stored in the backtrace caches are copied from stack-allocated - * temporary variables, so size is known at creation time. Making this - * a contiguous object improves cache locality. - */ - ret = (prof_bt_t *)imalloc(QUANTUM_CEILING(sizeof(prof_bt_t)) + - (bt->len * sizeof(void *))); - if (ret == NULL) - return (NULL); - ret->vec = (void **)((uintptr_t)ret + - QUANTUM_CEILING(sizeof(prof_bt_t))); - memcpy(ret->vec, bt->vec, bt->len * sizeof(void *)); - ret->len = bt->len; + if (updated) { + /* + * Compute a new sample threshold. This isn't very important in + * practice, because this function is rarely executed, so the + * potential for sample bias is minimal except in contrived + * programs. + */ + tdata = prof_tdata_get(tsd, true); + if (tdata != NULL) { + prof_sample_threshold_update(tdata); + } + } - return (ret); + if ((uintptr_t)tctx > (uintptr_t)1U) { + malloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock); + tctx->prepared = false; + if (prof_tctx_should_destroy(tsd_tsdn(tsd), tctx)) { + prof_tctx_destroy(tsd, tctx); + } else { + malloc_mutex_unlock(tsd_tsdn(tsd), tctx->tdata->lock); + } + } } -static inline void -prof_enter(prof_tdata_t *prof_tdata) -{ +void +prof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize, + prof_tctx_t *tctx) { + prof_tctx_set(tsdn, ptr, usize, NULL, tctx); - cassert(config_prof); + malloc_mutex_lock(tsdn, tctx->tdata->lock); + tctx->cnts.curobjs++; + tctx->cnts.curbytes += usize; + if (opt_prof_accum) { + tctx->cnts.accumobjs++; + tctx->cnts.accumbytes += usize; + } + tctx->prepared = false; + malloc_mutex_unlock(tsdn, tctx->tdata->lock); +} + +void +prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx) { + malloc_mutex_lock(tsd_tsdn(tsd), tctx->tdata->lock); + assert(tctx->cnts.curobjs > 0); + assert(tctx->cnts.curbytes >= usize); + tctx->cnts.curobjs--; + tctx->cnts.curbytes -= usize; + + if (prof_tctx_should_destroy(tsd_tsdn(tsd), tctx)) { + prof_tctx_destroy(tsd, tctx); + } else { + malloc_mutex_unlock(tsd_tsdn(tsd), tctx->tdata->lock); + } +} - assert(prof_tdata->enq == false); - prof_tdata->enq = true; +void +bt_init(prof_bt_t *bt, void **vec) { + cassert(config_prof); - malloc_mutex_lock(&bt2ctx_mtx); + bt->vec = vec; + bt->len = 0; } -static inline void -prof_leave(prof_tdata_t *prof_tdata) -{ - bool idump, gdump; +static void +prof_enter(tsd_t *tsd, prof_tdata_t *tdata) { + cassert(config_prof); + assert(tdata == prof_tdata_get(tsd, false)); + + if (tdata != NULL) { + assert(!tdata->enq); + tdata->enq = true; + } + malloc_mutex_lock(tsd_tsdn(tsd), &bt2gctx_mtx); +} + +static void +prof_leave(tsd_t *tsd, prof_tdata_t *tdata) { cassert(config_prof); + assert(tdata == prof_tdata_get(tsd, false)); - malloc_mutex_unlock(&bt2ctx_mtx); + malloc_mutex_unlock(tsd_tsdn(tsd), &bt2gctx_mtx); - assert(prof_tdata->enq); - prof_tdata->enq = false; - idump = prof_tdata->enq_idump; - prof_tdata->enq_idump = false; - gdump = prof_tdata->enq_gdump; - prof_tdata->enq_gdump = false; + if (tdata != NULL) { + bool idump, gdump; - if (idump) - prof_idump(); - if (gdump) - prof_gdump(); + assert(tdata->enq); + tdata->enq = false; + idump = tdata->enq_idump; + tdata->enq_idump = false; + gdump = tdata->enq_gdump; + tdata->enq_gdump = false; + + if (idump) { + prof_idump(tsd_tsdn(tsd)); + } + if (gdump) { + prof_gdump(tsd_tsdn(tsd)); + } + } } #ifdef JEMALLOC_PROF_LIBUNWIND void -prof_backtrace(prof_bt_t *bt, unsigned nignore) -{ - unw_context_t uc; - unw_cursor_t cursor; - unsigned i; - int err; +prof_backtrace(prof_bt_t *bt) { + int nframes; cassert(config_prof); assert(bt->len == 0); assert(bt->vec != NULL); - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - - /* Throw away (nignore+1) stack frames, if that many exist. */ - for (i = 0; i < nignore + 1; i++) { - err = unw_step(&cursor); - if (err <= 0) - return; - } - - /* - * Iterate over stack frames until there are no more, or until no space - * remains in bt. - */ - for (i = 0; i < PROF_BT_MAX; i++) { - unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *)&bt->vec[i]); - bt->len++; - err = unw_step(&cursor); - if (err <= 0) - break; + nframes = unw_backtrace(bt->vec, PROF_BT_MAX); + if (nframes <= 0) { + return; } + bt->len = nframes; } #elif (defined(JEMALLOC_PROF_LIBGCC)) static _Unwind_Reason_Code -prof_unwind_init_callback(struct _Unwind_Context *context, void *arg) -{ - +prof_unwind_init_callback(struct _Unwind_Context *context, void *arg) { cassert(config_prof); - return (_URC_NO_REASON); + return _URC_NO_REASON; } static _Unwind_Reason_Code -prof_unwind_callback(struct _Unwind_Context *context, void *arg) -{ +prof_unwind_callback(struct _Unwind_Context *context, void *arg) { prof_unwind_data_t *data = (prof_unwind_data_t *)arg; + void *ip; cassert(config_prof); - if (data->nignore > 0) - data->nignore--; - else { - data->bt->vec[data->bt->len] = (void *)_Unwind_GetIP(context); - data->bt->len++; - if (data->bt->len == data->max) - return (_URC_END_OF_STACK); + ip = (void *)_Unwind_GetIP(context); + if (ip == NULL) { + return _URC_END_OF_STACK; + } + data->bt->vec[data->bt->len] = ip; + data->bt->len++; + if (data->bt->len == data->max) { + return _URC_END_OF_STACK; } - return (_URC_NO_REASON); + return _URC_NO_REASON; } void -prof_backtrace(prof_bt_t *bt, unsigned nignore) -{ - prof_unwind_data_t data = {bt, nignore, PROF_BT_MAX}; +prof_backtrace(prof_bt_t *bt) { + prof_unwind_data_t data = {bt, PROF_BT_MAX}; cassert(config_prof); @@ -232,25 +368,24 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore) } #elif (defined(JEMALLOC_PROF_GCC)) void -prof_backtrace(prof_bt_t *bt, unsigned nignore) -{ -#define BT_FRAME(i) \ - if ((i) < nignore + PROF_BT_MAX) { \ +prof_backtrace(prof_bt_t *bt) { +#define BT_FRAME(i) \ + if ((i) < PROF_BT_MAX) { \ void *p; \ - if (__builtin_frame_address(i) == 0) \ + if (__builtin_frame_address(i) == 0) { \ return; \ + } \ p = __builtin_return_address(i); \ - if (p == NULL) \ + if (p == NULL) { \ return; \ - if (i >= nignore) { \ - bt->vec[(i) - nignore] = p; \ - bt->len = (i) - nignore + 1; \ } \ - } else \ - return; + bt->vec[(i)] = p; \ + bt->len = (i) + 1; \ + } else { \ + return; \ + } cassert(config_prof); - assert(nignore <= 3); BT_FRAME(0) BT_FRAME(1) @@ -392,307 +527,452 @@ prof_backtrace(prof_bt_t *bt, unsigned nignore) BT_FRAME(125) BT_FRAME(126) BT_FRAME(127) - - /* Extras to compensate for nignore. */ - BT_FRAME(128) - BT_FRAME(129) - BT_FRAME(130) #undef BT_FRAME } #else void -prof_backtrace(prof_bt_t *bt, unsigned nignore) -{ - +prof_backtrace(prof_bt_t *bt) { cassert(config_prof); not_reached(); } #endif static malloc_mutex_t * -prof_ctx_mutex_choose(void) -{ - unsigned nctxs = atomic_add_u(&cum_ctxs, 1); +prof_gctx_mutex_choose(void) { + unsigned ngctxs = atomic_fetch_add_u(&cum_gctxs, 1, ATOMIC_RELAXED); - return (&ctx_locks[(nctxs - 1) % PROF_NCTX_LOCKS]); + return &gctx_locks[(ngctxs - 1) % PROF_NCTX_LOCKS]; } -static void -prof_ctx_init(prof_ctx_t *ctx, prof_bt_t *bt) -{ +static malloc_mutex_t * +prof_tdata_mutex_choose(uint64_t thr_uid) { + return &tdata_locks[thr_uid % PROF_NTDATA_LOCKS]; +} - ctx->bt = bt; - ctx->lock = prof_ctx_mutex_choose(); +static prof_gctx_t * +prof_gctx_create(tsdn_t *tsdn, prof_bt_t *bt) { + /* + * Create a single allocation that has space for vec of length bt->len. + */ + size_t size = offsetof(prof_gctx_t, vec) + (bt->len * sizeof(void *)); + prof_gctx_t *gctx = (prof_gctx_t *)iallocztm(tsdn, size, + sz_size2index(size), false, NULL, true, arena_get(TSDN_NULL, 0, true), + true); + if (gctx == NULL) { + return NULL; + } + gctx->lock = prof_gctx_mutex_choose(); /* * Set nlimbo to 1, in order to avoid a race condition with - * prof_ctx_merge()/prof_ctx_destroy(). + * prof_tctx_destroy()/prof_gctx_try_destroy(). */ - ctx->nlimbo = 1; - ql_elm_new(ctx, dump_link); - memset(&ctx->cnt_merged, 0, sizeof(prof_cnt_t)); - ql_new(&ctx->cnts_ql); + gctx->nlimbo = 1; + tctx_tree_new(&gctx->tctxs); + /* Duplicate bt. */ + memcpy(gctx->vec, bt->vec, bt->len * sizeof(void *)); + gctx->bt.vec = gctx->vec; + gctx->bt.len = bt->len; + return gctx; } static void -prof_ctx_destroy(prof_ctx_t *ctx) -{ - prof_tdata_t *prof_tdata; - +prof_gctx_try_destroy(tsd_t *tsd, prof_tdata_t *tdata_self, prof_gctx_t *gctx, + prof_tdata_t *tdata) { cassert(config_prof); /* - * Check that ctx is still unused by any thread cache before destroying - * it. prof_lookup() increments ctx->nlimbo in order to avoid a race - * condition with this function, as does prof_ctx_merge() in order to - * avoid a race between the main body of prof_ctx_merge() and entry + * Check that gctx is still unused by any thread cache before destroying + * it. prof_lookup() increments gctx->nlimbo in order to avoid a race + * condition with this function, as does prof_tctx_destroy() in order to + * avoid a race between the main body of prof_tctx_destroy() and entry * into this function. */ - prof_tdata = prof_tdata_get(false); - assert((uintptr_t)prof_tdata > (uintptr_t)PROF_TDATA_STATE_MAX); - prof_enter(prof_tdata); - malloc_mutex_lock(ctx->lock); - if (ql_first(&ctx->cnts_ql) == NULL && ctx->cnt_merged.curobjs == 0 && - ctx->nlimbo == 1) { - assert(ctx->cnt_merged.curbytes == 0); - assert(ctx->cnt_merged.accumobjs == 0); - assert(ctx->cnt_merged.accumbytes == 0); - /* Remove ctx from bt2ctx. */ - if (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL)) + prof_enter(tsd, tdata_self); + malloc_mutex_lock(tsd_tsdn(tsd), gctx->lock); + assert(gctx->nlimbo != 0); + if (tctx_tree_empty(&gctx->tctxs) && gctx->nlimbo == 1) { + /* Remove gctx from bt2gctx. */ + if (ckh_remove(tsd, &bt2gctx, &gctx->bt, NULL, NULL)) { not_reached(); - prof_leave(prof_tdata); - /* Destroy ctx. */ - malloc_mutex_unlock(ctx->lock); - bt_destroy(ctx->bt); - idalloc(ctx); + } + prof_leave(tsd, tdata_self); + /* Destroy gctx. */ + malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); + idalloctm(tsd_tsdn(tsd), gctx, NULL, NULL, true, true); } else { /* - * Compensate for increment in prof_ctx_merge() or + * Compensate for increment in prof_tctx_destroy() or * prof_lookup(). */ - ctx->nlimbo--; - malloc_mutex_unlock(ctx->lock); - prof_leave(prof_tdata); + gctx->nlimbo--; + malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); + prof_leave(tsd, tdata_self); } } -static void -prof_ctx_merge(prof_ctx_t *ctx, prof_thr_cnt_t *cnt) -{ - bool destroy; +static bool +prof_tctx_should_destroy(tsdn_t *tsdn, prof_tctx_t *tctx) { + malloc_mutex_assert_owner(tsdn, tctx->tdata->lock); - cassert(config_prof); + if (opt_prof_accum) { + return false; + } + if (tctx->cnts.curobjs != 0) { + return false; + } + if (tctx->prepared) { + return false; + } + return true; +} + +static bool +prof_gctx_should_destroy(prof_gctx_t *gctx) { + if (opt_prof_accum) { + return false; + } + if (!tctx_tree_empty(&gctx->tctxs)) { + return false; + } + if (gctx->nlimbo != 0) { + return false; + } + return true; +} - /* Merge cnt stats and detach from ctx. */ - malloc_mutex_lock(ctx->lock); - ctx->cnt_merged.curobjs += cnt->cnts.curobjs; - ctx->cnt_merged.curbytes += cnt->cnts.curbytes; - ctx->cnt_merged.accumobjs += cnt->cnts.accumobjs; - ctx->cnt_merged.accumbytes += cnt->cnts.accumbytes; - ql_remove(&ctx->cnts_ql, cnt, cnts_link); - if (opt_prof_accum == false && ql_first(&ctx->cnts_ql) == NULL && - ctx->cnt_merged.curobjs == 0 && ctx->nlimbo == 0) { +static void +prof_tctx_destroy(tsd_t *tsd, prof_tctx_t *tctx) { + prof_tdata_t *tdata = tctx->tdata; + prof_gctx_t *gctx = tctx->gctx; + bool destroy_tdata, destroy_tctx, destroy_gctx; + + malloc_mutex_assert_owner(tsd_tsdn(tsd), tctx->tdata->lock); + + assert(tctx->cnts.curobjs == 0); + assert(tctx->cnts.curbytes == 0); + assert(!opt_prof_accum); + assert(tctx->cnts.accumobjs == 0); + assert(tctx->cnts.accumbytes == 0); + + ckh_remove(tsd, &tdata->bt2tctx, &gctx->bt, NULL, NULL); + destroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata, false); + malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock); + + malloc_mutex_lock(tsd_tsdn(tsd), gctx->lock); + switch (tctx->state) { + case prof_tctx_state_nominal: + tctx_tree_remove(&gctx->tctxs, tctx); + destroy_tctx = true; + if (prof_gctx_should_destroy(gctx)) { + /* + * Increment gctx->nlimbo in order to keep another + * thread from winning the race to destroy gctx while + * this one has gctx->lock dropped. Without this, it + * would be possible for another thread to: + * + * 1) Sample an allocation associated with gctx. + * 2) Deallocate the sampled object. + * 3) Successfully prof_gctx_try_destroy(gctx). + * + * The result would be that gctx no longer exists by the + * time this thread accesses it in + * prof_gctx_try_destroy(). + */ + gctx->nlimbo++; + destroy_gctx = true; + } else { + destroy_gctx = false; + } + break; + case prof_tctx_state_dumping: /* - * Increment ctx->nlimbo in order to keep another thread from - * winning the race to destroy ctx while this one has ctx->lock - * dropped. Without this, it would be possible for another - * thread to: - * - * 1) Sample an allocation associated with ctx. - * 2) Deallocate the sampled object. - * 3) Successfully prof_ctx_destroy(ctx). - * - * The result would be that ctx no longer exists by the time - * this thread accesses it in prof_ctx_destroy(). + * A dumping thread needs tctx to remain valid until dumping + * has finished. Change state such that the dumping thread will + * complete destruction during a late dump iteration phase. */ - ctx->nlimbo++; - destroy = true; - } else - destroy = false; - malloc_mutex_unlock(ctx->lock); - if (destroy) - prof_ctx_destroy(ctx); + tctx->state = prof_tctx_state_purgatory; + destroy_tctx = false; + destroy_gctx = false; + break; + default: + not_reached(); + destroy_tctx = false; + destroy_gctx = false; + } + malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); + if (destroy_gctx) { + prof_gctx_try_destroy(tsd, prof_tdata_get(tsd, false), gctx, + tdata); + } + + malloc_mutex_assert_not_owner(tsd_tsdn(tsd), tctx->tdata->lock); + + if (destroy_tdata) { + prof_tdata_destroy(tsd, tdata, false); + } + + if (destroy_tctx) { + idalloctm(tsd_tsdn(tsd), tctx, NULL, NULL, true, true); + } } static bool -prof_lookup_global(prof_bt_t *bt, prof_tdata_t *prof_tdata, void **p_btkey, - prof_ctx_t **p_ctx, bool *p_new_ctx) -{ +prof_lookup_global(tsd_t *tsd, prof_bt_t *bt, prof_tdata_t *tdata, + void **p_btkey, prof_gctx_t **p_gctx, bool *p_new_gctx) { union { - prof_ctx_t *p; + prof_gctx_t *p; void *v; - } ctx; + } gctx, tgctx; union { prof_bt_t *p; void *v; } btkey; - bool new_ctx; + bool new_gctx; - prof_enter(prof_tdata); - if (ckh_search(&bt2ctx, bt, &btkey.v, &ctx.v)) { + prof_enter(tsd, tdata); + if (ckh_search(&bt2gctx, bt, &btkey.v, &gctx.v)) { /* bt has never been seen before. Insert it. */ - ctx.v = imalloc(sizeof(prof_ctx_t)); - if (ctx.v == NULL) { - prof_leave(prof_tdata); - return (true); - } - btkey.p = bt_dup(bt); - if (btkey.v == NULL) { - prof_leave(prof_tdata); - idalloc(ctx.v); - return (true); + prof_leave(tsd, tdata); + tgctx.p = prof_gctx_create(tsd_tsdn(tsd), bt); + if (tgctx.v == NULL) { + return true; } - prof_ctx_init(ctx.p, btkey.p); - if (ckh_insert(&bt2ctx, btkey.v, ctx.v)) { - /* OOM. */ - prof_leave(prof_tdata); - idalloc(btkey.v); - idalloc(ctx.v); - return (true); + prof_enter(tsd, tdata); + if (ckh_search(&bt2gctx, bt, &btkey.v, &gctx.v)) { + gctx.p = tgctx.p; + btkey.p = &gctx.p->bt; + if (ckh_insert(tsd, &bt2gctx, btkey.v, gctx.v)) { + /* OOM. */ + prof_leave(tsd, tdata); + idalloctm(tsd_tsdn(tsd), gctx.v, NULL, NULL, + true, true); + return true; + } + new_gctx = true; + } else { + new_gctx = false; } - new_ctx = true; } else { + tgctx.v = NULL; + new_gctx = false; + } + + if (!new_gctx) { /* * Increment nlimbo, in order to avoid a race condition with - * prof_ctx_merge()/prof_ctx_destroy(). + * prof_tctx_destroy()/prof_gctx_try_destroy(). */ - malloc_mutex_lock(ctx.p->lock); - ctx.p->nlimbo++; - malloc_mutex_unlock(ctx.p->lock); - new_ctx = false; + malloc_mutex_lock(tsd_tsdn(tsd), gctx.p->lock); + gctx.p->nlimbo++; + malloc_mutex_unlock(tsd_tsdn(tsd), gctx.p->lock); + new_gctx = false; + + if (tgctx.v != NULL) { + /* Lost race to insert. */ + idalloctm(tsd_tsdn(tsd), tgctx.v, NULL, NULL, true, + true); + } } - prof_leave(prof_tdata); + prof_leave(tsd, tdata); *p_btkey = btkey.v; - *p_ctx = ctx.p; - *p_new_ctx = new_ctx; - return (false); + *p_gctx = gctx.p; + *p_new_gctx = new_gctx; + return false; } -prof_thr_cnt_t * -prof_lookup(prof_bt_t *bt) -{ +prof_tctx_t * +prof_lookup(tsd_t *tsd, prof_bt_t *bt) { union { - prof_thr_cnt_t *p; + prof_tctx_t *p; void *v; } ret; - prof_tdata_t *prof_tdata; + prof_tdata_t *tdata; + bool not_found; cassert(config_prof); - prof_tdata = prof_tdata_get(false); - if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) - return (NULL); + tdata = prof_tdata_get(tsd, false); + if (tdata == NULL) { + return NULL; + } - if (ckh_search(&prof_tdata->bt2cnt, bt, NULL, &ret.v)) { + malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock); + not_found = ckh_search(&tdata->bt2tctx, bt, NULL, &ret.v); + if (!not_found) { /* Note double negative! */ + ret.p->prepared = true; + } + malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock); + if (not_found) { void *btkey; - prof_ctx_t *ctx; - bool new_ctx; + prof_gctx_t *gctx; + bool new_gctx, error; /* * This thread's cache lacks bt. Look for it in the global * cache. */ - if (prof_lookup_global(bt, prof_tdata, &btkey, &ctx, &new_ctx)) - return (NULL); + if (prof_lookup_global(tsd, bt, tdata, &btkey, &gctx, + &new_gctx)) { + return NULL; + } - /* Link a prof_thd_cnt_t into ctx for this thread. */ - if (ckh_count(&prof_tdata->bt2cnt) == PROF_TCMAX) { - assert(ckh_count(&prof_tdata->bt2cnt) > 0); - /* - * Flush the least recently used cnt in order to keep - * bt2cnt from becoming too large. - */ - ret.p = ql_last(&prof_tdata->lru_ql, lru_link); - assert(ret.v != NULL); - if (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt, - NULL, NULL)) - not_reached(); - ql_remove(&prof_tdata->lru_ql, ret.p, lru_link); - prof_ctx_merge(ret.p->ctx, ret.p); - /* ret can now be re-used. */ - } else { - assert(ckh_count(&prof_tdata->bt2cnt) < PROF_TCMAX); - /* Allocate and partially initialize a new cnt. */ - ret.v = imalloc(sizeof(prof_thr_cnt_t)); - if (ret.p == NULL) { - if (new_ctx) - prof_ctx_destroy(ctx); - return (NULL); + /* Link a prof_tctx_t into gctx for this thread. */ + ret.v = iallocztm(tsd_tsdn(tsd), sizeof(prof_tctx_t), + sz_size2index(sizeof(prof_tctx_t)), false, NULL, true, + arena_ichoose(tsd, NULL), true); + if (ret.p == NULL) { + if (new_gctx) { + prof_gctx_try_destroy(tsd, tdata, gctx, tdata); } - ql_elm_new(ret.p, cnts_link); - ql_elm_new(ret.p, lru_link); + return NULL; } - /* Finish initializing ret. */ - ret.p->ctx = ctx; - ret.p->epoch = 0; + ret.p->tdata = tdata; + ret.p->thr_uid = tdata->thr_uid; + ret.p->thr_discrim = tdata->thr_discrim; memset(&ret.p->cnts, 0, sizeof(prof_cnt_t)); - if (ckh_insert(&prof_tdata->bt2cnt, btkey, ret.v)) { - if (new_ctx) - prof_ctx_destroy(ctx); - idalloc(ret.v); - return (NULL); + ret.p->gctx = gctx; + ret.p->tctx_uid = tdata->tctx_uid_next++; + ret.p->prepared = true; + ret.p->state = prof_tctx_state_initializing; + malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock); + error = ckh_insert(tsd, &tdata->bt2tctx, btkey, ret.v); + malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock); + if (error) { + if (new_gctx) { + prof_gctx_try_destroy(tsd, tdata, gctx, tdata); + } + idalloctm(tsd_tsdn(tsd), ret.v, NULL, NULL, true, true); + return NULL; } - ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link); - malloc_mutex_lock(ctx->lock); - ql_tail_insert(&ctx->cnts_ql, ret.p, cnts_link); - ctx->nlimbo--; - malloc_mutex_unlock(ctx->lock); - } else { - /* Move ret to the front of the LRU. */ - ql_remove(&prof_tdata->lru_ql, ret.p, lru_link); - ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link); + malloc_mutex_lock(tsd_tsdn(tsd), gctx->lock); + ret.p->state = prof_tctx_state_nominal; + tctx_tree_insert(&gctx->tctxs, ret.p); + gctx->nlimbo--; + malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); } - return (ret.p); + return ret.p; +} + +/* + * The bodies of this function and prof_leakcheck() are compiled out unless heap + * profiling is enabled, so that it is possible to compile jemalloc with + * floating point support completely disabled. Avoiding floating point code is + * important on memory-constrained systems, but it also enables a workaround for + * versions of glibc that don't properly save/restore floating point registers + * during dynamic lazy symbol loading (which internally calls into whatever + * malloc implementation happens to be integrated into the application). Note + * that some compilers (e.g. gcc 4.8) may use floating point registers for fast + * memory moves, so jemalloc must be compiled with such optimizations disabled + * (e.g. + * -mno-sse) in order for the workaround to be complete. + */ +void +prof_sample_threshold_update(prof_tdata_t *tdata) { +#ifdef JEMALLOC_PROF + uint64_t r; + double u; + + if (!config_prof) { + return; + } + + if (lg_prof_sample == 0) { + tdata->bytes_until_sample = 0; + return; + } + + /* + * Compute sample interval as a geometrically distributed random + * variable with mean (2^lg_prof_sample). + * + * __ __ + * | log(u) | 1 + * tdata->bytes_until_sample = | -------- |, where p = --------------- + * | log(1-p) | lg_prof_sample + * 2 + * + * For more information on the math, see: + * + * Non-Uniform Random Variate Generation + * Luc Devroye + * Springer-Verlag, New York, 1986 + * pp 500 + * (http://luc.devroye.org/rnbookindex.html) + */ + r = prng_lg_range_u64(&tdata->prng_state, 53); + u = (double)r * (1.0/9007199254740992.0L); + tdata->bytes_until_sample = (uint64_t)(log(u) / + log(1.0 - (1.0 / (double)((uint64_t)1U << lg_prof_sample)))) + + (uint64_t)1U; +#endif } #ifdef JEMALLOC_JET +static prof_tdata_t * +prof_tdata_count_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, + void *arg) { + size_t *tdata_count = (size_t *)arg; + + (*tdata_count)++; + + return NULL; +} + size_t -prof_bt_count(void) -{ +prof_tdata_count(void) { + size_t tdata_count = 0; + tsdn_t *tsdn; + + tsdn = tsdn_fetch(); + malloc_mutex_lock(tsdn, &tdatas_mtx); + tdata_tree_iter(&tdatas, NULL, prof_tdata_count_iter, + (void *)&tdata_count); + malloc_mutex_unlock(tsdn, &tdatas_mtx); + + return tdata_count; +} + +size_t +prof_bt_count(void) { size_t bt_count; - prof_tdata_t *prof_tdata; + tsd_t *tsd; + prof_tdata_t *tdata; - prof_tdata = prof_tdata_get(false); - if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) - return (0); + tsd = tsd_fetch(); + tdata = prof_tdata_get(tsd, false); + if (tdata == NULL) { + return 0; + } - prof_enter(prof_tdata); - bt_count = ckh_count(&bt2ctx); - prof_leave(prof_tdata); + malloc_mutex_lock(tsd_tsdn(tsd), &bt2gctx_mtx); + bt_count = ckh_count(&bt2gctx); + malloc_mutex_unlock(tsd_tsdn(tsd), &bt2gctx_mtx); - return (bt_count); + return bt_count; } #endif -#ifdef JEMALLOC_JET -#undef prof_dump_open -#define prof_dump_open JEMALLOC_N(prof_dump_open_impl) -#endif static int -prof_dump_open(bool propagate_err, const char *filename) -{ +prof_dump_open_impl(bool propagate_err, const char *filename) { int fd; fd = creat(filename, 0644); - if (fd == -1 && propagate_err == false) { + if (fd == -1 && !propagate_err) { malloc_printf("<jemalloc>: creat(\"%s\"), 0644) failed\n", filename); - if (opt_abort) + if (opt_abort) { abort(); + } } - return (fd); + return fd; } -#ifdef JEMALLOC_JET -#undef prof_dump_open -#define prof_dump_open JEMALLOC_N(prof_dump_open) -prof_dump_open_t *prof_dump_open = JEMALLOC_N(prof_dump_open_impl); -#endif +prof_dump_open_t *JET_MUTABLE prof_dump_open = prof_dump_open_impl; static bool -prof_dump_flush(bool propagate_err) -{ +prof_dump_flush(bool propagate_err) { bool ret = false; ssize_t err; @@ -700,22 +980,22 @@ prof_dump_flush(bool propagate_err) err = write(prof_dump_fd, prof_dump_buf, prof_dump_buf_end); if (err == -1) { - if (propagate_err == false) { + if (!propagate_err) { malloc_write("<jemalloc>: write() failed during heap " "profile flush\n"); - if (opt_abort) + if (opt_abort) { abort(); + } } ret = true; } prof_dump_buf_end = 0; - return (ret); + return ret; } static bool -prof_dump_close(bool propagate_err) -{ +prof_dump_close(bool propagate_err) { bool ret; assert(prof_dump_fd != -1); @@ -723,13 +1003,12 @@ prof_dump_close(bool propagate_err) close(prof_dump_fd); prof_dump_fd = -1; - return (ret); + return ret; } static bool -prof_dump_write(bool propagate_err, const char *s) -{ - unsigned i, slen, n; +prof_dump_write(bool propagate_err, const char *s) { + size_t i, slen, n; cassert(config_prof); @@ -737,9 +1016,11 @@ prof_dump_write(bool propagate_err, const char *s) slen = strlen(s); while (i < slen) { /* Flush the buffer if it is full. */ - if (prof_dump_buf_end == PROF_DUMP_BUFSIZE) - if (prof_dump_flush(propagate_err) && propagate_err) - return (true); + if (prof_dump_buf_end == PROF_DUMP_BUFSIZE) { + if (prof_dump_flush(propagate_err) && propagate_err) { + return true; + } + } if (prof_dump_buf_end + slen <= PROF_DUMP_BUFSIZE) { /* Finish writing. */ @@ -753,13 +1034,12 @@ prof_dump_write(bool propagate_err, const char *s) i += n; } - return (false); + return false; } -JEMALLOC_ATTR(format(printf, 2, 3)) +JEMALLOC_FORMAT_PRINTF(2, 3) static bool -prof_dump_printf(bool propagate_err, const char *format, ...) -{ +prof_dump_printf(bool propagate_err, const char *format, ...) { bool ret; va_list ap; char buf[PROF_PRINTF_BUFSIZE]; @@ -769,179 +1049,401 @@ prof_dump_printf(bool propagate_err, const char *format, ...) va_end(ap); ret = prof_dump_write(propagate_err, buf); - return (ret); + return ret; +} + +static void +prof_tctx_merge_tdata(tsdn_t *tsdn, prof_tctx_t *tctx, prof_tdata_t *tdata) { + malloc_mutex_assert_owner(tsdn, tctx->tdata->lock); + + malloc_mutex_lock(tsdn, tctx->gctx->lock); + + switch (tctx->state) { + case prof_tctx_state_initializing: + malloc_mutex_unlock(tsdn, tctx->gctx->lock); + return; + case prof_tctx_state_nominal: + tctx->state = prof_tctx_state_dumping; + malloc_mutex_unlock(tsdn, tctx->gctx->lock); + + memcpy(&tctx->dump_cnts, &tctx->cnts, sizeof(prof_cnt_t)); + + tdata->cnt_summed.curobjs += tctx->dump_cnts.curobjs; + tdata->cnt_summed.curbytes += tctx->dump_cnts.curbytes; + if (opt_prof_accum) { + tdata->cnt_summed.accumobjs += + tctx->dump_cnts.accumobjs; + tdata->cnt_summed.accumbytes += + tctx->dump_cnts.accumbytes; + } + break; + case prof_tctx_state_dumping: + case prof_tctx_state_purgatory: + not_reached(); + } } static void -prof_dump_ctx_prep(prof_ctx_t *ctx, prof_cnt_t *cnt_all, size_t *leak_nctx, - prof_ctx_list_t *ctx_ql) -{ - prof_thr_cnt_t *thr_cnt; - prof_cnt_t tcnt; +prof_tctx_merge_gctx(tsdn_t *tsdn, prof_tctx_t *tctx, prof_gctx_t *gctx) { + malloc_mutex_assert_owner(tsdn, gctx->lock); + + gctx->cnt_summed.curobjs += tctx->dump_cnts.curobjs; + gctx->cnt_summed.curbytes += tctx->dump_cnts.curbytes; + if (opt_prof_accum) { + gctx->cnt_summed.accumobjs += tctx->dump_cnts.accumobjs; + gctx->cnt_summed.accumbytes += tctx->dump_cnts.accumbytes; + } +} + +static prof_tctx_t * +prof_tctx_merge_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) { + tsdn_t *tsdn = (tsdn_t *)arg; + + malloc_mutex_assert_owner(tsdn, tctx->gctx->lock); + + switch (tctx->state) { + case prof_tctx_state_nominal: + /* New since dumping started; ignore. */ + break; + case prof_tctx_state_dumping: + case prof_tctx_state_purgatory: + prof_tctx_merge_gctx(tsdn, tctx, tctx->gctx); + break; + default: + not_reached(); + } + + return NULL; +} + +struct prof_tctx_dump_iter_arg_s { + tsdn_t *tsdn; + bool propagate_err; +}; + +static prof_tctx_t * +prof_tctx_dump_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *opaque) { + struct prof_tctx_dump_iter_arg_s *arg = + (struct prof_tctx_dump_iter_arg_s *)opaque; + + malloc_mutex_assert_owner(arg->tsdn, tctx->gctx->lock); + + switch (tctx->state) { + case prof_tctx_state_initializing: + case prof_tctx_state_nominal: + /* Not captured by this dump. */ + break; + case prof_tctx_state_dumping: + case prof_tctx_state_purgatory: + if (prof_dump_printf(arg->propagate_err, + " t%"FMTu64": %"FMTu64": %"FMTu64" [%"FMTu64": " + "%"FMTu64"]\n", tctx->thr_uid, tctx->dump_cnts.curobjs, + tctx->dump_cnts.curbytes, tctx->dump_cnts.accumobjs, + tctx->dump_cnts.accumbytes)) { + return tctx; + } + break; + default: + not_reached(); + } + return NULL; +} +static prof_tctx_t * +prof_tctx_finish_iter(prof_tctx_tree_t *tctxs, prof_tctx_t *tctx, void *arg) { + tsdn_t *tsdn = (tsdn_t *)arg; + prof_tctx_t *ret; + + malloc_mutex_assert_owner(tsdn, tctx->gctx->lock); + + switch (tctx->state) { + case prof_tctx_state_nominal: + /* New since dumping started; ignore. */ + break; + case prof_tctx_state_dumping: + tctx->state = prof_tctx_state_nominal; + break; + case prof_tctx_state_purgatory: + ret = tctx; + goto label_return; + default: + not_reached(); + } + + ret = NULL; +label_return: + return ret; +} + +static void +prof_dump_gctx_prep(tsdn_t *tsdn, prof_gctx_t *gctx, prof_gctx_tree_t *gctxs) { cassert(config_prof); - malloc_mutex_lock(ctx->lock); + malloc_mutex_lock(tsdn, gctx->lock); /* - * Increment nlimbo so that ctx won't go away before dump. - * Additionally, link ctx into the dump list so that it is included in + * Increment nlimbo so that gctx won't go away before dump. + * Additionally, link gctx into the dump list so that it is included in * prof_dump()'s second pass. */ - ctx->nlimbo++; - ql_tail_insert(ctx_ql, ctx, dump_link); + gctx->nlimbo++; + gctx_tree_insert(gctxs, gctx); - memcpy(&ctx->cnt_summed, &ctx->cnt_merged, sizeof(prof_cnt_t)); - ql_foreach(thr_cnt, &ctx->cnts_ql, cnts_link) { - volatile unsigned *epoch = &thr_cnt->epoch; + memset(&gctx->cnt_summed, 0, sizeof(prof_cnt_t)); - while (true) { - unsigned epoch0 = *epoch; + malloc_mutex_unlock(tsdn, gctx->lock); +} - /* Make sure epoch is even. */ - if (epoch0 & 1U) - continue; +struct prof_gctx_merge_iter_arg_s { + tsdn_t *tsdn; + size_t leak_ngctx; +}; + +static prof_gctx_t * +prof_gctx_merge_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque) { + struct prof_gctx_merge_iter_arg_s *arg = + (struct prof_gctx_merge_iter_arg_s *)opaque; + + malloc_mutex_lock(arg->tsdn, gctx->lock); + tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_merge_iter, + (void *)arg->tsdn); + if (gctx->cnt_summed.curobjs != 0) { + arg->leak_ngctx++; + } + malloc_mutex_unlock(arg->tsdn, gctx->lock); - memcpy(&tcnt, &thr_cnt->cnts, sizeof(prof_cnt_t)); + return NULL; +} - /* Terminate if epoch didn't change while reading. */ - if (*epoch == epoch0) - break; - } +static void +prof_gctx_finish(tsd_t *tsd, prof_gctx_tree_t *gctxs) { + prof_tdata_t *tdata = prof_tdata_get(tsd, false); + prof_gctx_t *gctx; - ctx->cnt_summed.curobjs += tcnt.curobjs; - ctx->cnt_summed.curbytes += tcnt.curbytes; - if (opt_prof_accum) { - ctx->cnt_summed.accumobjs += tcnt.accumobjs; - ctx->cnt_summed.accumbytes += tcnt.accumbytes; + /* + * Standard tree iteration won't work here, because as soon as we + * decrement gctx->nlimbo and unlock gctx, another thread can + * concurrently destroy it, which will corrupt the tree. Therefore, + * tear down the tree one node at a time during iteration. + */ + while ((gctx = gctx_tree_first(gctxs)) != NULL) { + gctx_tree_remove(gctxs, gctx); + malloc_mutex_lock(tsd_tsdn(tsd), gctx->lock); + { + prof_tctx_t *next; + + next = NULL; + do { + prof_tctx_t *to_destroy = + tctx_tree_iter(&gctx->tctxs, next, + prof_tctx_finish_iter, + (void *)tsd_tsdn(tsd)); + if (to_destroy != NULL) { + next = tctx_tree_next(&gctx->tctxs, + to_destroy); + tctx_tree_remove(&gctx->tctxs, + to_destroy); + idalloctm(tsd_tsdn(tsd), to_destroy, + NULL, NULL, true, true); + } else { + next = NULL; + } + } while (next != NULL); + } + gctx->nlimbo--; + if (prof_gctx_should_destroy(gctx)) { + gctx->nlimbo++; + malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); + prof_gctx_try_destroy(tsd, tdata, gctx, tdata); + } else { + malloc_mutex_unlock(tsd_tsdn(tsd), gctx->lock); } } +} - if (ctx->cnt_summed.curobjs != 0) - (*leak_nctx)++; +struct prof_tdata_merge_iter_arg_s { + tsdn_t *tsdn; + prof_cnt_t cnt_all; +}; + +static prof_tdata_t * +prof_tdata_merge_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, + void *opaque) { + struct prof_tdata_merge_iter_arg_s *arg = + (struct prof_tdata_merge_iter_arg_s *)opaque; + + malloc_mutex_lock(arg->tsdn, tdata->lock); + if (!tdata->expired) { + size_t tabind; + union { + prof_tctx_t *p; + void *v; + } tctx; + + tdata->dumping = true; + memset(&tdata->cnt_summed, 0, sizeof(prof_cnt_t)); + for (tabind = 0; !ckh_iter(&tdata->bt2tctx, &tabind, NULL, + &tctx.v);) { + prof_tctx_merge_tdata(arg->tsdn, tctx.p, tdata); + } - /* Add to cnt_all. */ - cnt_all->curobjs += ctx->cnt_summed.curobjs; - cnt_all->curbytes += ctx->cnt_summed.curbytes; - if (opt_prof_accum) { - cnt_all->accumobjs += ctx->cnt_summed.accumobjs; - cnt_all->accumbytes += ctx->cnt_summed.accumbytes; + arg->cnt_all.curobjs += tdata->cnt_summed.curobjs; + arg->cnt_all.curbytes += tdata->cnt_summed.curbytes; + if (opt_prof_accum) { + arg->cnt_all.accumobjs += tdata->cnt_summed.accumobjs; + arg->cnt_all.accumbytes += tdata->cnt_summed.accumbytes; + } + } else { + tdata->dumping = false; } + malloc_mutex_unlock(arg->tsdn, tdata->lock); - malloc_mutex_unlock(ctx->lock); + return NULL; } -static bool -prof_dump_header(bool propagate_err, const prof_cnt_t *cnt_all) -{ - - if (opt_lg_prof_sample == 0) { - if (prof_dump_printf(propagate_err, - "heap profile: %"PRId64": %"PRId64 - " [%"PRIu64": %"PRIu64"] @ heapprofile\n", - cnt_all->curobjs, cnt_all->curbytes, - cnt_all->accumobjs, cnt_all->accumbytes)) - return (true); - } else { - if (prof_dump_printf(propagate_err, - "heap profile: %"PRId64": %"PRId64 - " [%"PRIu64": %"PRIu64"] @ heap_v2/%"PRIu64"\n", - cnt_all->curobjs, cnt_all->curbytes, - cnt_all->accumobjs, cnt_all->accumbytes, - ((uint64_t)1U << opt_lg_prof_sample))) - return (true); +static prof_tdata_t * +prof_tdata_dump_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, + void *arg) { + bool propagate_err = *(bool *)arg; + + if (!tdata->dumping) { + return NULL; } - return (false); + if (prof_dump_printf(propagate_err, + " t%"FMTu64": %"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]%s%s\n", + tdata->thr_uid, tdata->cnt_summed.curobjs, + tdata->cnt_summed.curbytes, tdata->cnt_summed.accumobjs, + tdata->cnt_summed.accumbytes, + (tdata->thread_name != NULL) ? " " : "", + (tdata->thread_name != NULL) ? tdata->thread_name : "")) { + return tdata; + } + return NULL; } -static void -prof_dump_ctx_cleanup_locked(prof_ctx_t *ctx, prof_ctx_list_t *ctx_ql) -{ - - ctx->nlimbo--; - ql_remove(ctx_ql, ctx, dump_link); -} +static bool +prof_dump_header_impl(tsdn_t *tsdn, bool propagate_err, + const prof_cnt_t *cnt_all) { + bool ret; -static void -prof_dump_ctx_cleanup(prof_ctx_t *ctx, prof_ctx_list_t *ctx_ql) -{ + if (prof_dump_printf(propagate_err, + "heap_v2/%"FMTu64"\n" + " t*: %"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]\n", + ((uint64_t)1U << lg_prof_sample), cnt_all->curobjs, + cnt_all->curbytes, cnt_all->accumobjs, cnt_all->accumbytes)) { + return true; + } - malloc_mutex_lock(ctx->lock); - prof_dump_ctx_cleanup_locked(ctx, ctx_ql); - malloc_mutex_unlock(ctx->lock); + malloc_mutex_lock(tsdn, &tdatas_mtx); + ret = (tdata_tree_iter(&tdatas, NULL, prof_tdata_dump_iter, + (void *)&propagate_err) != NULL); + malloc_mutex_unlock(tsdn, &tdatas_mtx); + return ret; } +prof_dump_header_t *JET_MUTABLE prof_dump_header = prof_dump_header_impl; static bool -prof_dump_ctx(bool propagate_err, prof_ctx_t *ctx, const prof_bt_t *bt, - prof_ctx_list_t *ctx_ql) -{ +prof_dump_gctx(tsdn_t *tsdn, bool propagate_err, prof_gctx_t *gctx, + const prof_bt_t *bt, prof_gctx_tree_t *gctxs) { bool ret; unsigned i; + struct prof_tctx_dump_iter_arg_s prof_tctx_dump_iter_arg; cassert(config_prof); - - /* - * Current statistics can sum to 0 as a result of unmerged per thread - * statistics. Additionally, interval- and growth-triggered dumps can - * occur between the time a ctx is created and when its statistics are - * filled in. Avoid dumping any ctx that is an artifact of either - * implementation detail. - */ - malloc_mutex_lock(ctx->lock); - if ((opt_prof_accum == false && ctx->cnt_summed.curobjs == 0) || - (opt_prof_accum && ctx->cnt_summed.accumobjs == 0)) { - assert(ctx->cnt_summed.curobjs == 0); - assert(ctx->cnt_summed.curbytes == 0); - assert(ctx->cnt_summed.accumobjs == 0); - assert(ctx->cnt_summed.accumbytes == 0); + malloc_mutex_assert_owner(tsdn, gctx->lock); + + /* Avoid dumping such gctx's that have no useful data. */ + if ((!opt_prof_accum && gctx->cnt_summed.curobjs == 0) || + (opt_prof_accum && gctx->cnt_summed.accumobjs == 0)) { + assert(gctx->cnt_summed.curobjs == 0); + assert(gctx->cnt_summed.curbytes == 0); + assert(gctx->cnt_summed.accumobjs == 0); + assert(gctx->cnt_summed.accumbytes == 0); ret = false; goto label_return; } - if (prof_dump_printf(propagate_err, "%"PRId64": %"PRId64 - " [%"PRIu64": %"PRIu64"] @", - ctx->cnt_summed.curobjs, ctx->cnt_summed.curbytes, - ctx->cnt_summed.accumobjs, ctx->cnt_summed.accumbytes)) { + if (prof_dump_printf(propagate_err, "@")) { ret = true; goto label_return; } - for (i = 0; i < bt->len; i++) { - if (prof_dump_printf(propagate_err, " %#"PRIxPTR, + if (prof_dump_printf(propagate_err, " %#"FMTxPTR, (uintptr_t)bt->vec[i])) { ret = true; goto label_return; } } - if (prof_dump_write(propagate_err, "\n")) { + if (prof_dump_printf(propagate_err, + "\n" + " t*: %"FMTu64": %"FMTu64" [%"FMTu64": %"FMTu64"]\n", + gctx->cnt_summed.curobjs, gctx->cnt_summed.curbytes, + gctx->cnt_summed.accumobjs, gctx->cnt_summed.accumbytes)) { + ret = true; + goto label_return; + } + + prof_tctx_dump_iter_arg.tsdn = tsdn; + prof_tctx_dump_iter_arg.propagate_err = propagate_err; + if (tctx_tree_iter(&gctx->tctxs, NULL, prof_tctx_dump_iter, + (void *)&prof_tctx_dump_iter_arg) != NULL) { ret = true; goto label_return; } ret = false; label_return: - prof_dump_ctx_cleanup_locked(ctx, ctx_ql); - malloc_mutex_unlock(ctx->lock); - return (ret); + return ret; +} + +#ifndef _WIN32 +JEMALLOC_FORMAT_PRINTF(1, 2) +static int +prof_open_maps(const char *format, ...) { + int mfd; + va_list ap; + char filename[PATH_MAX + 1]; + + va_start(ap, format); + malloc_vsnprintf(filename, sizeof(filename), format, ap); + va_end(ap); + mfd = open(filename, O_RDONLY | O_CLOEXEC); + + return mfd; +} +#endif + +static int +prof_getpid(void) { +#ifdef _WIN32 + return GetCurrentProcessId(); +#else + return getpid(); +#endif } static bool -prof_dump_maps(bool propagate_err) -{ +prof_dump_maps(bool propagate_err) { bool ret; int mfd; - char filename[PATH_MAX + 1]; cassert(config_prof); #ifdef __FreeBSD__ - malloc_snprintf(filename, sizeof(filename), "/proc/curproc/map"); + mfd = prof_open_maps("/proc/curproc/map"); +#elif defined(_WIN32) + mfd = -1; // Not implemented #else - malloc_snprintf(filename, sizeof(filename), "/proc/%d/maps", - (int)getpid()); + { + int pid = prof_getpid(); + + mfd = prof_open_maps("/proc/%d/task/%d/maps", pid, pid); + if (mfd == -1) { + mfd = prof_open_maps("/proc/%d/maps", pid); + } + } #endif - mfd = open(filename, O_RDONLY); if (mfd != -1) { ssize_t nread; @@ -971,214 +1473,391 @@ prof_dump_maps(bool propagate_err) ret = false; label_return: - if (mfd != -1) + if (mfd != -1) { close(mfd); - return (ret); + } + return ret; } +/* + * See prof_sample_threshold_update() comment for why the body of this function + * is conditionally compiled. + */ static void -prof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_nctx, - const char *filename) -{ - +prof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx, + const char *filename) { +#ifdef JEMALLOC_PROF + /* + * Scaling is equivalent AdjustSamples() in jeprof, but the result may + * differ slightly from what jeprof reports, because here we scale the + * summary values, whereas jeprof scales each context individually and + * reports the sums of the scaled values. + */ if (cnt_all->curbytes != 0) { - malloc_printf("<jemalloc>: Leak summary: %"PRId64" byte%s, %" - PRId64" object%s, %zu context%s\n", - cnt_all->curbytes, (cnt_all->curbytes != 1) ? "s" : "", - cnt_all->curobjs, (cnt_all->curobjs != 1) ? "s" : "", - leak_nctx, (leak_nctx != 1) ? "s" : ""); + double sample_period = (double)((uint64_t)1 << lg_prof_sample); + double ratio = (((double)cnt_all->curbytes) / + (double)cnt_all->curobjs) / sample_period; + double scale_factor = 1.0 / (1.0 - exp(-ratio)); + uint64_t curbytes = (uint64_t)round(((double)cnt_all->curbytes) + * scale_factor); + uint64_t curobjs = (uint64_t)round(((double)cnt_all->curobjs) * + scale_factor); + + malloc_printf("<jemalloc>: Leak approximation summary: ~%"FMTu64 + " byte%s, ~%"FMTu64" object%s, >= %zu context%s\n", + curbytes, (curbytes != 1) ? "s" : "", curobjs, (curobjs != + 1) ? "s" : "", leak_ngctx, (leak_ngctx != 1) ? "s" : ""); malloc_printf( - "<jemalloc>: Run pprof on \"%s\" for leak detail\n", + "<jemalloc>: Run jeprof on \"%s\" for leak detail\n", filename); } +#endif } -static bool -prof_dump(bool propagate_err, const char *filename, bool leakcheck) -{ - prof_tdata_t *prof_tdata; - prof_cnt_t cnt_all; +struct prof_gctx_dump_iter_arg_s { + tsdn_t *tsdn; + bool propagate_err; +}; + +static prof_gctx_t * +prof_gctx_dump_iter(prof_gctx_tree_t *gctxs, prof_gctx_t *gctx, void *opaque) { + prof_gctx_t *ret; + struct prof_gctx_dump_iter_arg_s *arg = + (struct prof_gctx_dump_iter_arg_s *)opaque; + + malloc_mutex_lock(arg->tsdn, gctx->lock); + + if (prof_dump_gctx(arg->tsdn, arg->propagate_err, gctx, &gctx->bt, + gctxs)) { + ret = gctx; + goto label_return; + } + + ret = NULL; +label_return: + malloc_mutex_unlock(arg->tsdn, gctx->lock); + return ret; +} + +static void +prof_dump_prep(tsd_t *tsd, prof_tdata_t *tdata, + struct prof_tdata_merge_iter_arg_s *prof_tdata_merge_iter_arg, + struct prof_gctx_merge_iter_arg_s *prof_gctx_merge_iter_arg, + prof_gctx_tree_t *gctxs) { size_t tabind; union { - prof_ctx_t *p; + prof_gctx_t *p; void *v; - } ctx; - size_t leak_nctx; - prof_ctx_list_t ctx_ql; - - cassert(config_prof); + } gctx; - prof_tdata = prof_tdata_get(false); - if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) - return (true); + prof_enter(tsd, tdata); - malloc_mutex_lock(&prof_dump_mtx); + /* + * Put gctx's in limbo and clear their counters in preparation for + * summing. + */ + gctx_tree_new(gctxs); + for (tabind = 0; !ckh_iter(&bt2gctx, &tabind, NULL, &gctx.v);) { + prof_dump_gctx_prep(tsd_tsdn(tsd), gctx.p, gctxs); + } - /* Merge per thread profile stats, and sum them in cnt_all. */ - memset(&cnt_all, 0, sizeof(prof_cnt_t)); - leak_nctx = 0; - ql_new(&ctx_ql); - prof_enter(prof_tdata); - for (tabind = 0; ckh_iter(&bt2ctx, &tabind, NULL, &ctx.v) == false;) - prof_dump_ctx_prep(ctx.p, &cnt_all, &leak_nctx, &ctx_ql); - prof_leave(prof_tdata); + /* + * Iterate over tdatas, and for the non-expired ones snapshot their tctx + * stats and merge them into the associated gctx's. + */ + prof_tdata_merge_iter_arg->tsdn = tsd_tsdn(tsd); + memset(&prof_tdata_merge_iter_arg->cnt_all, 0, sizeof(prof_cnt_t)); + malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx); + tdata_tree_iter(&tdatas, NULL, prof_tdata_merge_iter, + (void *)prof_tdata_merge_iter_arg); + malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx); + + /* Merge tctx stats into gctx's. */ + prof_gctx_merge_iter_arg->tsdn = tsd_tsdn(tsd); + prof_gctx_merge_iter_arg->leak_ngctx = 0; + gctx_tree_iter(gctxs, NULL, prof_gctx_merge_iter, + (void *)prof_gctx_merge_iter_arg); + + prof_leave(tsd, tdata); +} +static bool +prof_dump_file(tsd_t *tsd, bool propagate_err, const char *filename, + bool leakcheck, prof_tdata_t *tdata, + struct prof_tdata_merge_iter_arg_s *prof_tdata_merge_iter_arg, + struct prof_gctx_merge_iter_arg_s *prof_gctx_merge_iter_arg, + struct prof_gctx_dump_iter_arg_s *prof_gctx_dump_iter_arg, + prof_gctx_tree_t *gctxs) { /* Create dump file. */ - if ((prof_dump_fd = prof_dump_open(propagate_err, filename)) == -1) - goto label_open_close_error; + if ((prof_dump_fd = prof_dump_open(propagate_err, filename)) == -1) { + return true; + } /* Dump profile header. */ - if (prof_dump_header(propagate_err, &cnt_all)) + if (prof_dump_header(tsd_tsdn(tsd), propagate_err, + &prof_tdata_merge_iter_arg->cnt_all)) { goto label_write_error; + } - /* Dump per ctx profile stats. */ - while ((ctx.p = ql_first(&ctx_ql)) != NULL) { - if (prof_dump_ctx(propagate_err, ctx.p, ctx.p->bt, &ctx_ql)) - goto label_write_error; + /* Dump per gctx profile stats. */ + prof_gctx_dump_iter_arg->tsdn = tsd_tsdn(tsd); + prof_gctx_dump_iter_arg->propagate_err = propagate_err; + if (gctx_tree_iter(gctxs, NULL, prof_gctx_dump_iter, + (void *)prof_gctx_dump_iter_arg) != NULL) { + goto label_write_error; } /* Dump /proc/<pid>/maps if possible. */ - if (prof_dump_maps(propagate_err)) + if (prof_dump_maps(propagate_err)) { goto label_write_error; + } - if (prof_dump_close(propagate_err)) - goto label_open_close_error; - - malloc_mutex_unlock(&prof_dump_mtx); - - if (leakcheck) - prof_leakcheck(&cnt_all, leak_nctx, filename); + if (prof_dump_close(propagate_err)) { + return true; + } - return (false); + return false; label_write_error: prof_dump_close(propagate_err); -label_open_close_error: - while ((ctx.p = ql_first(&ctx_ql)) != NULL) - prof_dump_ctx_cleanup(ctx.p, &ctx_ql); - malloc_mutex_unlock(&prof_dump_mtx); - return (true); + return true; } -#define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1) -#define VSEQ_INVALID UINT64_C(0xffffffffffffffff) -static void -prof_dump_filename(char *filename, char v, int64_t vseq) -{ +static bool +prof_dump(tsd_t *tsd, bool propagate_err, const char *filename, + bool leakcheck) { + cassert(config_prof); + assert(tsd_reentrancy_level_get(tsd) == 0); + + prof_tdata_t * tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return true; + } + + pre_reentrancy(tsd, NULL); + malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_mtx); + + prof_gctx_tree_t gctxs; + struct prof_tdata_merge_iter_arg_s prof_tdata_merge_iter_arg; + struct prof_gctx_merge_iter_arg_s prof_gctx_merge_iter_arg; + struct prof_gctx_dump_iter_arg_s prof_gctx_dump_iter_arg; + prof_dump_prep(tsd, tdata, &prof_tdata_merge_iter_arg, + &prof_gctx_merge_iter_arg, &gctxs); + bool err = prof_dump_file(tsd, propagate_err, filename, leakcheck, tdata, + &prof_tdata_merge_iter_arg, &prof_gctx_merge_iter_arg, + &prof_gctx_dump_iter_arg, &gctxs); + prof_gctx_finish(tsd, &gctxs); + + malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx); + post_reentrancy(tsd); + + if (err) { + return true; + } + + if (leakcheck) { + prof_leakcheck(&prof_tdata_merge_iter_arg.cnt_all, + prof_gctx_merge_iter_arg.leak_ngctx, filename); + } + return false; +} + +#ifdef JEMALLOC_JET +void +prof_cnt_all(uint64_t *curobjs, uint64_t *curbytes, uint64_t *accumobjs, + uint64_t *accumbytes) { + tsd_t *tsd; + prof_tdata_t *tdata; + struct prof_tdata_merge_iter_arg_s prof_tdata_merge_iter_arg; + struct prof_gctx_merge_iter_arg_s prof_gctx_merge_iter_arg; + prof_gctx_tree_t gctxs; + + tsd = tsd_fetch(); + tdata = prof_tdata_get(tsd, false); + if (tdata == NULL) { + if (curobjs != NULL) { + *curobjs = 0; + } + if (curbytes != NULL) { + *curbytes = 0; + } + if (accumobjs != NULL) { + *accumobjs = 0; + } + if (accumbytes != NULL) { + *accumbytes = 0; + } + return; + } + + prof_dump_prep(tsd, tdata, &prof_tdata_merge_iter_arg, + &prof_gctx_merge_iter_arg, &gctxs); + prof_gctx_finish(tsd, &gctxs); + + if (curobjs != NULL) { + *curobjs = prof_tdata_merge_iter_arg.cnt_all.curobjs; + } + if (curbytes != NULL) { + *curbytes = prof_tdata_merge_iter_arg.cnt_all.curbytes; + } + if (accumobjs != NULL) { + *accumobjs = prof_tdata_merge_iter_arg.cnt_all.accumobjs; + } + if (accumbytes != NULL) { + *accumbytes = prof_tdata_merge_iter_arg.cnt_all.accumbytes; + } +} +#endif +#define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1) +#define VSEQ_INVALID UINT64_C(0xffffffffffffffff) +static void +prof_dump_filename(char *filename, char v, uint64_t vseq) { cassert(config_prof); if (vseq != VSEQ_INVALID) { /* "<prefix>.<pid>.<seq>.v<vseq>.heap" */ malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, - "%s.%d.%"PRIu64".%c%"PRId64".heap", - opt_prof_prefix, (int)getpid(), prof_dump_seq, v, vseq); + "%s.%d.%"FMTu64".%c%"FMTu64".heap", + opt_prof_prefix, prof_getpid(), prof_dump_seq, v, vseq); } else { /* "<prefix>.<pid>.<seq>.<v>.heap" */ malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, - "%s.%d.%"PRIu64".%c.heap", - opt_prof_prefix, (int)getpid(), prof_dump_seq, v); + "%s.%d.%"FMTu64".%c.heap", + opt_prof_prefix, prof_getpid(), prof_dump_seq, v); } prof_dump_seq++; } static void -prof_fdump(void) -{ +prof_fdump(void) { + tsd_t *tsd; char filename[DUMP_FILENAME_BUFSIZE]; cassert(config_prof); + assert(opt_prof_final); + assert(opt_prof_prefix[0] != '\0'); - if (prof_booted == false) + if (!prof_booted) { return; + } + tsd = tsd_fetch(); + assert(tsd_reentrancy_level_get(tsd) == 0); + + malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_seq_mtx); + prof_dump_filename(filename, 'f', VSEQ_INVALID); + malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_seq_mtx); + prof_dump(tsd, false, filename, opt_prof_leak); +} - if (opt_prof_final && opt_prof_prefix[0] != '\0') { - malloc_mutex_lock(&prof_dump_seq_mtx); - prof_dump_filename(filename, 'f', VSEQ_INVALID); - malloc_mutex_unlock(&prof_dump_seq_mtx); - prof_dump(false, filename, opt_prof_leak); +bool +prof_accum_init(tsdn_t *tsdn, prof_accum_t *prof_accum) { + cassert(config_prof); + +#ifndef JEMALLOC_ATOMIC_U64 + if (malloc_mutex_init(&prof_accum->mtx, "prof_accum", + WITNESS_RANK_PROF_ACCUM, malloc_mutex_rank_exclusive)) { + return true; } + prof_accum->accumbytes = 0; +#else + atomic_store_u64(&prof_accum->accumbytes, 0, ATOMIC_RELAXED); +#endif + return false; } void -prof_idump(void) -{ - prof_tdata_t *prof_tdata; - char filename[PATH_MAX + 1]; +prof_idump(tsdn_t *tsdn) { + tsd_t *tsd; + prof_tdata_t *tdata; cassert(config_prof); - if (prof_booted == false) + if (!prof_booted || tsdn_null(tsdn)) { + return; + } + tsd = tsdn_tsd(tsdn); + if (tsd_reentrancy_level_get(tsd) > 0) { return; - prof_tdata = prof_tdata_get(false); - if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + } + + tdata = prof_tdata_get(tsd, false); + if (tdata == NULL) { return; - if (prof_tdata->enq) { - prof_tdata->enq_idump = true; + } + if (tdata->enq) { + tdata->enq_idump = true; return; } if (opt_prof_prefix[0] != '\0') { - malloc_mutex_lock(&prof_dump_seq_mtx); + char filename[PATH_MAX + 1]; + malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_seq_mtx); prof_dump_filename(filename, 'i', prof_dump_iseq); prof_dump_iseq++; - malloc_mutex_unlock(&prof_dump_seq_mtx); - prof_dump(false, filename, false); + malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_seq_mtx); + prof_dump(tsd, false, filename, false); } } bool -prof_mdump(const char *filename) -{ - char filename_buf[DUMP_FILENAME_BUFSIZE]; - +prof_mdump(tsd_t *tsd, const char *filename) { cassert(config_prof); + assert(tsd_reentrancy_level_get(tsd) == 0); - if (opt_prof == false || prof_booted == false) - return (true); - + if (!opt_prof || !prof_booted) { + return true; + } + char filename_buf[DUMP_FILENAME_BUFSIZE]; if (filename == NULL) { /* No filename specified, so automatically generate one. */ - if (opt_prof_prefix[0] == '\0') - return (true); - malloc_mutex_lock(&prof_dump_seq_mtx); + if (opt_prof_prefix[0] == '\0') { + return true; + } + malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_seq_mtx); prof_dump_filename(filename_buf, 'm', prof_dump_mseq); prof_dump_mseq++; - malloc_mutex_unlock(&prof_dump_seq_mtx); + malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_seq_mtx); filename = filename_buf; } - return (prof_dump(true, filename, false)); + return prof_dump(tsd, true, filename, false); } void -prof_gdump(void) -{ - prof_tdata_t *prof_tdata; - char filename[DUMP_FILENAME_BUFSIZE]; +prof_gdump(tsdn_t *tsdn) { + tsd_t *tsd; + prof_tdata_t *tdata; cassert(config_prof); - if (prof_booted == false) + if (!prof_booted || tsdn_null(tsdn)) { + return; + } + tsd = tsdn_tsd(tsdn); + if (tsd_reentrancy_level_get(tsd) > 0) { return; - prof_tdata = prof_tdata_get(false); - if ((uintptr_t)prof_tdata <= (uintptr_t)PROF_TDATA_STATE_MAX) + } + + tdata = prof_tdata_get(tsd, false); + if (tdata == NULL) { return; - if (prof_tdata->enq) { - prof_tdata->enq_gdump = true; + } + if (tdata->enq) { + tdata->enq_gdump = true; return; } if (opt_prof_prefix[0] != '\0') { - malloc_mutex_lock(&prof_dump_seq_mtx); + char filename[DUMP_FILENAME_BUFSIZE]; + malloc_mutex_lock(tsdn, &prof_dump_seq_mtx); prof_dump_filename(filename, 'u', prof_dump_useq); prof_dump_useq++; - malloc_mutex_unlock(&prof_dump_seq_mtx); - prof_dump(false, filename, false); + malloc_mutex_unlock(tsdn, &prof_dump_seq_mtx); + prof_dump(tsd, false, filename, false); } } static void -prof_bt_hash(const void *key, size_t r_hash[2]) -{ +prof_bt_hash(const void *key, size_t r_hash[2]) { prof_bt_t *bt = (prof_bt_t *)key; cassert(config_prof); @@ -1187,106 +1866,389 @@ prof_bt_hash(const void *key, size_t r_hash[2]) } static bool -prof_bt_keycomp(const void *k1, const void *k2) -{ +prof_bt_keycomp(const void *k1, const void *k2) { const prof_bt_t *bt1 = (prof_bt_t *)k1; const prof_bt_t *bt2 = (prof_bt_t *)k2; cassert(config_prof); - if (bt1->len != bt2->len) - return (false); + if (bt1->len != bt2->len) { + return false; + } return (memcmp(bt1->vec, bt2->vec, bt1->len * sizeof(void *)) == 0); } -prof_tdata_t * -prof_tdata_init(void) -{ - prof_tdata_t *prof_tdata; +static uint64_t +prof_thr_uid_alloc(tsdn_t *tsdn) { + uint64_t thr_uid; + + malloc_mutex_lock(tsdn, &next_thr_uid_mtx); + thr_uid = next_thr_uid; + next_thr_uid++; + malloc_mutex_unlock(tsdn, &next_thr_uid_mtx); + + return thr_uid; +} + +static prof_tdata_t * +prof_tdata_init_impl(tsd_t *tsd, uint64_t thr_uid, uint64_t thr_discrim, + char *thread_name, bool active) { + prof_tdata_t *tdata; cassert(config_prof); /* Initialize an empty cache for this thread. */ - prof_tdata = (prof_tdata_t *)imalloc(sizeof(prof_tdata_t)); - if (prof_tdata == NULL) - return (NULL); + tdata = (prof_tdata_t *)iallocztm(tsd_tsdn(tsd), sizeof(prof_tdata_t), + sz_size2index(sizeof(prof_tdata_t)), false, NULL, true, + arena_get(TSDN_NULL, 0, true), true); + if (tdata == NULL) { + return NULL; + } - if (ckh_new(&prof_tdata->bt2cnt, PROF_CKH_MINITEMS, - prof_bt_hash, prof_bt_keycomp)) { - idalloc(prof_tdata); - return (NULL); + tdata->lock = prof_tdata_mutex_choose(thr_uid); + tdata->thr_uid = thr_uid; + tdata->thr_discrim = thr_discrim; + tdata->thread_name = thread_name; + tdata->attached = true; + tdata->expired = false; + tdata->tctx_uid_next = 0; + + if (ckh_new(tsd, &tdata->bt2tctx, PROF_CKH_MINITEMS, prof_bt_hash, + prof_bt_keycomp)) { + idalloctm(tsd_tsdn(tsd), tdata, NULL, NULL, true, true); + return NULL; } - ql_new(&prof_tdata->lru_ql); - prof_tdata->vec = imalloc(sizeof(void *) * PROF_BT_MAX); - if (prof_tdata->vec == NULL) { - ckh_delete(&prof_tdata->bt2cnt); - idalloc(prof_tdata); - return (NULL); + tdata->prng_state = (uint64_t)(uintptr_t)tdata; + prof_sample_threshold_update(tdata); + + tdata->enq = false; + tdata->enq_idump = false; + tdata->enq_gdump = false; + + tdata->dumping = false; + tdata->active = active; + + malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx); + tdata_tree_insert(&tdatas, tdata); + malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx); + + return tdata; +} + +prof_tdata_t * +prof_tdata_init(tsd_t *tsd) { + return prof_tdata_init_impl(tsd, prof_thr_uid_alloc(tsd_tsdn(tsd)), 0, + NULL, prof_thread_active_init_get(tsd_tsdn(tsd))); +} + +static bool +prof_tdata_should_destroy_unlocked(prof_tdata_t *tdata, bool even_if_attached) { + if (tdata->attached && !even_if_attached) { + return false; } + if (ckh_count(&tdata->bt2tctx) != 0) { + return false; + } + return true; +} + +static bool +prof_tdata_should_destroy(tsdn_t *tsdn, prof_tdata_t *tdata, + bool even_if_attached) { + malloc_mutex_assert_owner(tsdn, tdata->lock); - prof_tdata->prng_state = 0; - prof_tdata->threshold = 0; - prof_tdata->accum = 0; + return prof_tdata_should_destroy_unlocked(tdata, even_if_attached); +} + +static void +prof_tdata_destroy_locked(tsd_t *tsd, prof_tdata_t *tdata, + bool even_if_attached) { + malloc_mutex_assert_owner(tsd_tsdn(tsd), &tdatas_mtx); - prof_tdata->enq = false; - prof_tdata->enq_idump = false; - prof_tdata->enq_gdump = false; + tdata_tree_remove(&tdatas, tdata); - prof_tdata_tsd_set(&prof_tdata); + assert(prof_tdata_should_destroy_unlocked(tdata, even_if_attached)); - return (prof_tdata); + if (tdata->thread_name != NULL) { + idalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, NULL, true, + true); + } + ckh_delete(tsd, &tdata->bt2tctx); + idalloctm(tsd_tsdn(tsd), tdata, NULL, NULL, true, true); } -void -prof_tdata_cleanup(void *arg) -{ - prof_thr_cnt_t *cnt; - prof_tdata_t *prof_tdata = *(prof_tdata_t **)arg; +static void +prof_tdata_destroy(tsd_t *tsd, prof_tdata_t *tdata, bool even_if_attached) { + malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx); + prof_tdata_destroy_locked(tsd, tdata, even_if_attached); + malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx); +} - cassert(config_prof); +static void +prof_tdata_detach(tsd_t *tsd, prof_tdata_t *tdata) { + bool destroy_tdata; - if (prof_tdata == PROF_TDATA_STATE_REINCARNATED) { - /* - * Another destructor deallocated memory after this destructor - * was called. Reset prof_tdata to PROF_TDATA_STATE_PURGATORY - * in order to receive another callback. - */ - prof_tdata = PROF_TDATA_STATE_PURGATORY; - prof_tdata_tsd_set(&prof_tdata); - } else if (prof_tdata == PROF_TDATA_STATE_PURGATORY) { - /* - * The previous time this destructor was called, we set the key - * to PROF_TDATA_STATE_PURGATORY so that other destructors - * wouldn't cause re-creation of the prof_tdata. This time, do - * nothing, so that the destructor will not be called again. - */ - } else if (prof_tdata != NULL) { - /* - * Delete the hash table. All of its contents can still be - * iterated over via the LRU. - */ - ckh_delete(&prof_tdata->bt2cnt); + malloc_mutex_lock(tsd_tsdn(tsd), tdata->lock); + if (tdata->attached) { + destroy_tdata = prof_tdata_should_destroy(tsd_tsdn(tsd), tdata, + true); /* - * Iteratively merge cnt's into the global stats and delete - * them. + * Only detach if !destroy_tdata, because detaching would allow + * another thread to win the race to destroy tdata. */ - while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) { - ql_remove(&prof_tdata->lru_ql, cnt, lru_link); - prof_ctx_merge(cnt->ctx, cnt); - idalloc(cnt); + if (!destroy_tdata) { + tdata->attached = false; } - idalloc(prof_tdata->vec); - idalloc(prof_tdata); - prof_tdata = PROF_TDATA_STATE_PURGATORY; - prof_tdata_tsd_set(&prof_tdata); + tsd_prof_tdata_set(tsd, NULL); + } else { + destroy_tdata = false; + } + malloc_mutex_unlock(tsd_tsdn(tsd), tdata->lock); + if (destroy_tdata) { + prof_tdata_destroy(tsd, tdata, true); } } +prof_tdata_t * +prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata) { + uint64_t thr_uid = tdata->thr_uid; + uint64_t thr_discrim = tdata->thr_discrim + 1; + char *thread_name = (tdata->thread_name != NULL) ? + prof_thread_name_alloc(tsd_tsdn(tsd), tdata->thread_name) : NULL; + bool active = tdata->active; + + prof_tdata_detach(tsd, tdata); + return prof_tdata_init_impl(tsd, thr_uid, thr_discrim, thread_name, + active); +} + +static bool +prof_tdata_expire(tsdn_t *tsdn, prof_tdata_t *tdata) { + bool destroy_tdata; + + malloc_mutex_lock(tsdn, tdata->lock); + if (!tdata->expired) { + tdata->expired = true; + destroy_tdata = tdata->attached ? false : + prof_tdata_should_destroy(tsdn, tdata, false); + } else { + destroy_tdata = false; + } + malloc_mutex_unlock(tsdn, tdata->lock); + + return destroy_tdata; +} + +static prof_tdata_t * +prof_tdata_reset_iter(prof_tdata_tree_t *tdatas, prof_tdata_t *tdata, + void *arg) { + tsdn_t *tsdn = (tsdn_t *)arg; + + return (prof_tdata_expire(tsdn, tdata) ? tdata : NULL); +} + void -prof_boot0(void) -{ +prof_reset(tsd_t *tsd, size_t lg_sample) { + prof_tdata_t *next; + + assert(lg_sample < (sizeof(uint64_t) << 3)); + + malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_mtx); + malloc_mutex_lock(tsd_tsdn(tsd), &tdatas_mtx); + + lg_prof_sample = lg_sample; + + next = NULL; + do { + prof_tdata_t *to_destroy = tdata_tree_iter(&tdatas, next, + prof_tdata_reset_iter, (void *)tsd); + if (to_destroy != NULL) { + next = tdata_tree_next(&tdatas, to_destroy); + prof_tdata_destroy_locked(tsd, to_destroy, false); + } else { + next = NULL; + } + } while (next != NULL); + + malloc_mutex_unlock(tsd_tsdn(tsd), &tdatas_mtx); + malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx); +} + +void +prof_tdata_cleanup(tsd_t *tsd) { + prof_tdata_t *tdata; + + if (!config_prof) { + return; + } + + tdata = tsd_prof_tdata_get(tsd); + if (tdata != NULL) { + prof_tdata_detach(tsd, tdata); + } +} + +bool +prof_active_get(tsdn_t *tsdn) { + bool prof_active_current; + + malloc_mutex_lock(tsdn, &prof_active_mtx); + prof_active_current = prof_active; + malloc_mutex_unlock(tsdn, &prof_active_mtx); + return prof_active_current; +} +bool +prof_active_set(tsdn_t *tsdn, bool active) { + bool prof_active_old; + + malloc_mutex_lock(tsdn, &prof_active_mtx); + prof_active_old = prof_active; + prof_active = active; + malloc_mutex_unlock(tsdn, &prof_active_mtx); + return prof_active_old; +} + +const char * +prof_thread_name_get(tsd_t *tsd) { + prof_tdata_t *tdata; + + tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return ""; + } + return (tdata->thread_name != NULL ? tdata->thread_name : ""); +} + +static char * +prof_thread_name_alloc(tsdn_t *tsdn, const char *thread_name) { + char *ret; + size_t size; + + if (thread_name == NULL) { + return NULL; + } + + size = strlen(thread_name) + 1; + if (size == 1) { + return ""; + } + + ret = iallocztm(tsdn, size, sz_size2index(size), false, NULL, true, + arena_get(TSDN_NULL, 0, true), true); + if (ret == NULL) { + return NULL; + } + memcpy(ret, thread_name, size); + return ret; +} + +int +prof_thread_name_set(tsd_t *tsd, const char *thread_name) { + prof_tdata_t *tdata; + unsigned i; + char *s; + + tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return EAGAIN; + } + + /* Validate input. */ + if (thread_name == NULL) { + return EFAULT; + } + for (i = 0; thread_name[i] != '\0'; i++) { + char c = thread_name[i]; + if (!isgraph(c) && !isblank(c)) { + return EFAULT; + } + } + + s = prof_thread_name_alloc(tsd_tsdn(tsd), thread_name); + if (s == NULL) { + return EAGAIN; + } + + if (tdata->thread_name != NULL) { + idalloctm(tsd_tsdn(tsd), tdata->thread_name, NULL, NULL, true, + true); + tdata->thread_name = NULL; + } + if (strlen(s) > 0) { + tdata->thread_name = s; + } + return 0; +} + +bool +prof_thread_active_get(tsd_t *tsd) { + prof_tdata_t *tdata; + + tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return false; + } + return tdata->active; +} + +bool +prof_thread_active_set(tsd_t *tsd, bool active) { + prof_tdata_t *tdata; + + tdata = prof_tdata_get(tsd, true); + if (tdata == NULL) { + return true; + } + tdata->active = active; + return false; +} + +bool +prof_thread_active_init_get(tsdn_t *tsdn) { + bool active_init; + + malloc_mutex_lock(tsdn, &prof_thread_active_init_mtx); + active_init = prof_thread_active_init; + malloc_mutex_unlock(tsdn, &prof_thread_active_init_mtx); + return active_init; +} + +bool +prof_thread_active_init_set(tsdn_t *tsdn, bool active_init) { + bool active_init_old; + + malloc_mutex_lock(tsdn, &prof_thread_active_init_mtx); + active_init_old = prof_thread_active_init; + prof_thread_active_init = active_init; + malloc_mutex_unlock(tsdn, &prof_thread_active_init_mtx); + return active_init_old; +} + +bool +prof_gdump_get(tsdn_t *tsdn) { + bool prof_gdump_current; + + malloc_mutex_lock(tsdn, &prof_gdump_mtx); + prof_gdump_current = prof_gdump_val; + malloc_mutex_unlock(tsdn, &prof_gdump_mtx); + return prof_gdump_current; +} + +bool +prof_gdump_set(tsdn_t *tsdn, bool gdump) { + bool prof_gdump_old; + + malloc_mutex_lock(tsdn, &prof_gdump_mtx); + prof_gdump_old = prof_gdump_val; + prof_gdump_val = gdump; + malloc_mutex_unlock(tsdn, &prof_gdump_mtx); + return prof_gdump_old; +} + +void +prof_boot0(void) { cassert(config_prof); memcpy(opt_prof_prefix, PROF_PREFIX_DEFAULT, @@ -1294,17 +2256,15 @@ prof_boot0(void) } void -prof_boot1(void) -{ - +prof_boot1(void) { cassert(config_prof); /* - * opt_prof and prof_promote must be in their final state before any - * arenas are initialized, so this function must be executed early. + * opt_prof must be in its final state before any arenas are + * initialized, so this function must be executed early. */ - if (opt_prof_leak && opt_prof == false) { + if (opt_prof_leak && !opt_prof) { /* * Enable opt_prof, but in such a way that profiles are never * automatically dumped. @@ -1317,48 +2277,101 @@ prof_boot1(void) opt_lg_prof_interval); } } - - prof_promote = (opt_prof && opt_lg_prof_sample > LG_PAGE); } bool -prof_boot2(void) -{ - +prof_boot2(tsd_t *tsd) { cassert(config_prof); if (opt_prof) { unsigned i; - if (ckh_new(&bt2ctx, PROF_CKH_MINITEMS, prof_bt_hash, - prof_bt_keycomp)) - return (true); - if (malloc_mutex_init(&bt2ctx_mtx)) - return (true); - if (prof_tdata_tsd_boot()) { - malloc_write( - "<jemalloc>: Error in pthread_key_create()\n"); - abort(); + lg_prof_sample = opt_lg_prof_sample; + + prof_active = opt_prof_active; + if (malloc_mutex_init(&prof_active_mtx, "prof_active", + WITNESS_RANK_PROF_ACTIVE, malloc_mutex_rank_exclusive)) { + return true; + } + + prof_gdump_val = opt_prof_gdump; + if (malloc_mutex_init(&prof_gdump_mtx, "prof_gdump", + WITNESS_RANK_PROF_GDUMP, malloc_mutex_rank_exclusive)) { + return true; + } + + prof_thread_active_init = opt_prof_thread_active_init; + if (malloc_mutex_init(&prof_thread_active_init_mtx, + "prof_thread_active_init", + WITNESS_RANK_PROF_THREAD_ACTIVE_INIT, + malloc_mutex_rank_exclusive)) { + return true; + } + + if (ckh_new(tsd, &bt2gctx, PROF_CKH_MINITEMS, prof_bt_hash, + prof_bt_keycomp)) { + return true; + } + if (malloc_mutex_init(&bt2gctx_mtx, "prof_bt2gctx", + WITNESS_RANK_PROF_BT2GCTX, malloc_mutex_rank_exclusive)) { + return true; + } + + tdata_tree_new(&tdatas); + if (malloc_mutex_init(&tdatas_mtx, "prof_tdatas", + WITNESS_RANK_PROF_TDATAS, malloc_mutex_rank_exclusive)) { + return true; } - if (malloc_mutex_init(&prof_dump_seq_mtx)) - return (true); - if (malloc_mutex_init(&prof_dump_mtx)) - return (true); + next_thr_uid = 0; + if (malloc_mutex_init(&next_thr_uid_mtx, "prof_next_thr_uid", + WITNESS_RANK_PROF_NEXT_THR_UID, malloc_mutex_rank_exclusive)) { + return true; + } + + if (malloc_mutex_init(&prof_dump_seq_mtx, "prof_dump_seq", + WITNESS_RANK_PROF_DUMP_SEQ, malloc_mutex_rank_exclusive)) { + return true; + } + if (malloc_mutex_init(&prof_dump_mtx, "prof_dump", + WITNESS_RANK_PROF_DUMP, malloc_mutex_rank_exclusive)) { + return true; + } - if (atexit(prof_fdump) != 0) { + if (opt_prof_final && opt_prof_prefix[0] != '\0' && + atexit(prof_fdump) != 0) { malloc_write("<jemalloc>: Error in atexit()\n"); - if (opt_abort) + if (opt_abort) { abort(); + } } - ctx_locks = (malloc_mutex_t *)base_alloc(PROF_NCTX_LOCKS * - sizeof(malloc_mutex_t)); - if (ctx_locks == NULL) - return (true); + gctx_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd), + b0get(), PROF_NCTX_LOCKS * sizeof(malloc_mutex_t), + CACHELINE); + if (gctx_locks == NULL) { + return true; + } for (i = 0; i < PROF_NCTX_LOCKS; i++) { - if (malloc_mutex_init(&ctx_locks[i])) - return (true); + if (malloc_mutex_init(&gctx_locks[i], "prof_gctx", + WITNESS_RANK_PROF_GCTX, + malloc_mutex_rank_exclusive)) { + return true; + } + } + + tdata_locks = (malloc_mutex_t *)base_alloc(tsd_tsdn(tsd), + b0get(), PROF_NTDATA_LOCKS * sizeof(malloc_mutex_t), + CACHELINE); + if (tdata_locks == NULL) { + return true; + } + for (i = 0; i < PROF_NTDATA_LOCKS; i++) { + if (malloc_mutex_init(&tdata_locks[i], "prof_tdata", + WITNESS_RANK_PROF_TDATA, + malloc_mutex_rank_exclusive)) { + return true; + } } } @@ -1372,48 +2385,79 @@ prof_boot2(void) prof_booted = true; - return (false); + return false; } void -prof_prefork(void) -{ - - if (opt_prof) { +prof_prefork0(tsdn_t *tsdn) { + if (config_prof && opt_prof) { unsigned i; - malloc_mutex_prefork(&bt2ctx_mtx); - malloc_mutex_prefork(&prof_dump_seq_mtx); - for (i = 0; i < PROF_NCTX_LOCKS; i++) - malloc_mutex_prefork(&ctx_locks[i]); + malloc_mutex_prefork(tsdn, &prof_dump_mtx); + malloc_mutex_prefork(tsdn, &bt2gctx_mtx); + malloc_mutex_prefork(tsdn, &tdatas_mtx); + for (i = 0; i < PROF_NTDATA_LOCKS; i++) { + malloc_mutex_prefork(tsdn, &tdata_locks[i]); + } + for (i = 0; i < PROF_NCTX_LOCKS; i++) { + malloc_mutex_prefork(tsdn, &gctx_locks[i]); + } } } void -prof_postfork_parent(void) -{ +prof_prefork1(tsdn_t *tsdn) { + if (config_prof && opt_prof) { + malloc_mutex_prefork(tsdn, &prof_active_mtx); + malloc_mutex_prefork(tsdn, &prof_dump_seq_mtx); + malloc_mutex_prefork(tsdn, &prof_gdump_mtx); + malloc_mutex_prefork(tsdn, &next_thr_uid_mtx); + malloc_mutex_prefork(tsdn, &prof_thread_active_init_mtx); + } +} - if (opt_prof) { +void +prof_postfork_parent(tsdn_t *tsdn) { + if (config_prof && opt_prof) { unsigned i; - for (i = 0; i < PROF_NCTX_LOCKS; i++) - malloc_mutex_postfork_parent(&ctx_locks[i]); - malloc_mutex_postfork_parent(&prof_dump_seq_mtx); - malloc_mutex_postfork_parent(&bt2ctx_mtx); + malloc_mutex_postfork_parent(tsdn, + &prof_thread_active_init_mtx); + malloc_mutex_postfork_parent(tsdn, &next_thr_uid_mtx); + malloc_mutex_postfork_parent(tsdn, &prof_gdump_mtx); + malloc_mutex_postfork_parent(tsdn, &prof_dump_seq_mtx); + malloc_mutex_postfork_parent(tsdn, &prof_active_mtx); + for (i = 0; i < PROF_NCTX_LOCKS; i++) { + malloc_mutex_postfork_parent(tsdn, &gctx_locks[i]); + } + for (i = 0; i < PROF_NTDATA_LOCKS; i++) { + malloc_mutex_postfork_parent(tsdn, &tdata_locks[i]); + } + malloc_mutex_postfork_parent(tsdn, &tdatas_mtx); + malloc_mutex_postfork_parent(tsdn, &bt2gctx_mtx); + malloc_mutex_postfork_parent(tsdn, &prof_dump_mtx); } } void -prof_postfork_child(void) -{ - - if (opt_prof) { +prof_postfork_child(tsdn_t *tsdn) { + if (config_prof && opt_prof) { unsigned i; - for (i = 0; i < PROF_NCTX_LOCKS; i++) - malloc_mutex_postfork_child(&ctx_locks[i]); - malloc_mutex_postfork_child(&prof_dump_seq_mtx); - malloc_mutex_postfork_child(&bt2ctx_mtx); + malloc_mutex_postfork_child(tsdn, &prof_thread_active_init_mtx); + malloc_mutex_postfork_child(tsdn, &next_thr_uid_mtx); + malloc_mutex_postfork_child(tsdn, &prof_gdump_mtx); + malloc_mutex_postfork_child(tsdn, &prof_dump_seq_mtx); + malloc_mutex_postfork_child(tsdn, &prof_active_mtx); + for (i = 0; i < PROF_NCTX_LOCKS; i++) { + malloc_mutex_postfork_child(tsdn, &gctx_locks[i]); + } + for (i = 0; i < PROF_NTDATA_LOCKS; i++) { + malloc_mutex_postfork_child(tsdn, &tdata_locks[i]); + } + malloc_mutex_postfork_child(tsdn, &tdatas_mtx); + malloc_mutex_postfork_child(tsdn, &bt2gctx_mtx); + malloc_mutex_postfork_child(tsdn, &prof_dump_mtx); } } diff --git a/deps/jemalloc/src/rtree.c b/deps/jemalloc/src/rtree.c index 205957ac4e..53702cf723 100644 --- a/deps/jemalloc/src/rtree.c +++ b/deps/jemalloc/src/rtree.c @@ -1,105 +1,320 @@ -#define JEMALLOC_RTREE_C_ -#include "jemalloc/internal/jemalloc_internal.h" - -rtree_t * -rtree_new(unsigned bits, rtree_alloc_t *alloc, rtree_dalloc_t *dalloc) -{ - rtree_t *ret; - unsigned bits_per_level, bits_in_leaf, height, i; - - assert(bits > 0 && bits <= (sizeof(uintptr_t) << 3)); - - bits_per_level = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(void *)))) - 1; - bits_in_leaf = ffs(pow2_ceil((RTREE_NODESIZE / sizeof(uint8_t)))) - 1; - if (bits > bits_in_leaf) { - height = 1 + (bits - bits_in_leaf) / bits_per_level; - if ((height-1) * bits_per_level + bits_in_leaf != bits) - height++; - } else { - height = 1; - } - assert((height-1) * bits_per_level + bits_in_leaf >= bits); - - ret = (rtree_t*)alloc(offsetof(rtree_t, level2bits) + - (sizeof(unsigned) * height)); - if (ret == NULL) - return (NULL); - memset(ret, 0, offsetof(rtree_t, level2bits) + (sizeof(unsigned) * - height)); - - ret->alloc = alloc; - ret->dalloc = dalloc; - if (malloc_mutex_init(&ret->mutex)) { - if (dalloc != NULL) - dalloc(ret); - return (NULL); - } - ret->height = height; - if (height > 1) { - if ((height-1) * bits_per_level + bits_in_leaf > bits) { - ret->level2bits[0] = (bits - bits_in_leaf) % - bits_per_level; - } else - ret->level2bits[0] = bits_per_level; - for (i = 1; i < height-1; i++) - ret->level2bits[i] = bits_per_level; - ret->level2bits[height-1] = bits_in_leaf; - } else - ret->level2bits[0] = bits; - - ret->root = (void**)alloc(sizeof(void *) << ret->level2bits[0]); - if (ret->root == NULL) { - if (dalloc != NULL) - dalloc(ret); - return (NULL); - } - memset(ret->root, 0, sizeof(void *) << ret->level2bits[0]); - - return (ret); +#define JEMALLOC_RTREE_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/mutex.h" + +/* + * Only the most significant bits of keys passed to rtree_{read,write}() are + * used. + */ +bool +rtree_new(rtree_t *rtree, bool zeroed) { +#ifdef JEMALLOC_JET + if (!zeroed) { + memset(rtree, 0, sizeof(rtree_t)); /* Clear root. */ + } +#else + assert(zeroed); +#endif + + if (malloc_mutex_init(&rtree->init_lock, "rtree", WITNESS_RANK_RTREE, + malloc_mutex_rank_exclusive)) { + return true; + } + + return false; +} + +static rtree_node_elm_t * +rtree_node_alloc_impl(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) { + return (rtree_node_elm_t *)base_alloc(tsdn, b0get(), nelms * + sizeof(rtree_node_elm_t), CACHELINE); } +rtree_node_alloc_t *JET_MUTABLE rtree_node_alloc = rtree_node_alloc_impl; static void -rtree_delete_subtree(rtree_t *rtree, void **node, unsigned level) -{ +rtree_node_dalloc_impl(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *node) { + /* Nodes are never deleted during normal operation. */ + not_reached(); +} +UNUSED rtree_node_dalloc_t *JET_MUTABLE rtree_node_dalloc = + rtree_node_dalloc_impl; + +static rtree_leaf_elm_t * +rtree_leaf_alloc_impl(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) { + return (rtree_leaf_elm_t *)base_alloc(tsdn, b0get(), nelms * + sizeof(rtree_leaf_elm_t), CACHELINE); +} +rtree_leaf_alloc_t *JET_MUTABLE rtree_leaf_alloc = rtree_leaf_alloc_impl; - if (level < rtree->height - 1) { - size_t nchildren, i; +static void +rtree_leaf_dalloc_impl(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *leaf) { + /* Leaves are never deleted during normal operation. */ + not_reached(); +} +UNUSED rtree_leaf_dalloc_t *JET_MUTABLE rtree_leaf_dalloc = + rtree_leaf_dalloc_impl; - nchildren = ZU(1) << rtree->level2bits[level]; - for (i = 0; i < nchildren; i++) { - void **child = (void **)node[i]; - if (child != NULL) - rtree_delete_subtree(rtree, child, level + 1); +#ifdef JEMALLOC_JET +# if RTREE_HEIGHT > 1 +static void +rtree_delete_subtree(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *subtree, + unsigned level) { + size_t nchildren = ZU(1) << rtree_levels[level].bits; + if (level + 2 < RTREE_HEIGHT) { + for (size_t i = 0; i < nchildren; i++) { + rtree_node_elm_t *node = + (rtree_node_elm_t *)atomic_load_p(&subtree[i].child, + ATOMIC_RELAXED); + if (node != NULL) { + rtree_delete_subtree(tsdn, rtree, node, level + + 1); + } + } + } else { + for (size_t i = 0; i < nchildren; i++) { + rtree_leaf_elm_t *leaf = + (rtree_leaf_elm_t *)atomic_load_p(&subtree[i].child, + ATOMIC_RELAXED); + if (leaf != NULL) { + rtree_leaf_dalloc(tsdn, rtree, leaf); + } } } - rtree->dalloc(node); + + if (subtree != rtree->root) { + rtree_node_dalloc(tsdn, rtree, subtree); + } } +# endif void -rtree_delete(rtree_t *rtree) -{ +rtree_delete(tsdn_t *tsdn, rtree_t *rtree) { +# if RTREE_HEIGHT > 1 + rtree_delete_subtree(tsdn, rtree, rtree->root, 0); +# endif +} +#endif - rtree_delete_subtree(rtree, rtree->root, 0); - rtree->dalloc(rtree); +static rtree_node_elm_t * +rtree_node_init(tsdn_t *tsdn, rtree_t *rtree, unsigned level, + atomic_p_t *elmp) { + malloc_mutex_lock(tsdn, &rtree->init_lock); + /* + * If *elmp is non-null, then it was initialized with the init lock + * held, so we can get by with 'relaxed' here. + */ + rtree_node_elm_t *node = atomic_load_p(elmp, ATOMIC_RELAXED); + if (node == NULL) { + node = rtree_node_alloc(tsdn, rtree, ZU(1) << + rtree_levels[level].bits); + if (node == NULL) { + malloc_mutex_unlock(tsdn, &rtree->init_lock); + return NULL; + } + /* + * Even though we hold the lock, a later reader might not; we + * need release semantics. + */ + atomic_store_p(elmp, node, ATOMIC_RELEASE); + } + malloc_mutex_unlock(tsdn, &rtree->init_lock); + + return node; } -void -rtree_prefork(rtree_t *rtree) -{ +static rtree_leaf_elm_t * +rtree_leaf_init(tsdn_t *tsdn, rtree_t *rtree, atomic_p_t *elmp) { + malloc_mutex_lock(tsdn, &rtree->init_lock); + /* + * If *elmp is non-null, then it was initialized with the init lock + * held, so we can get by with 'relaxed' here. + */ + rtree_leaf_elm_t *leaf = atomic_load_p(elmp, ATOMIC_RELAXED); + if (leaf == NULL) { + leaf = rtree_leaf_alloc(tsdn, rtree, ZU(1) << + rtree_levels[RTREE_HEIGHT-1].bits); + if (leaf == NULL) { + malloc_mutex_unlock(tsdn, &rtree->init_lock); + return NULL; + } + /* + * Even though we hold the lock, a later reader might not; we + * need release semantics. + */ + atomic_store_p(elmp, leaf, ATOMIC_RELEASE); + } + malloc_mutex_unlock(tsdn, &rtree->init_lock); - malloc_mutex_prefork(&rtree->mutex); + return leaf; } -void -rtree_postfork_parent(rtree_t *rtree) -{ +static bool +rtree_node_valid(rtree_node_elm_t *node) { + return ((uintptr_t)node != (uintptr_t)0); +} - malloc_mutex_postfork_parent(&rtree->mutex); +static bool +rtree_leaf_valid(rtree_leaf_elm_t *leaf) { + return ((uintptr_t)leaf != (uintptr_t)0); } -void -rtree_postfork_child(rtree_t *rtree) -{ +static rtree_node_elm_t * +rtree_child_node_tryread(rtree_node_elm_t *elm, bool dependent) { + rtree_node_elm_t *node; + + if (dependent) { + node = (rtree_node_elm_t *)atomic_load_p(&elm->child, + ATOMIC_RELAXED); + } else { + node = (rtree_node_elm_t *)atomic_load_p(&elm->child, + ATOMIC_ACQUIRE); + } - malloc_mutex_postfork_child(&rtree->mutex); + assert(!dependent || node != NULL); + return node; +} + +static rtree_node_elm_t * +rtree_child_node_read(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *elm, + unsigned level, bool dependent) { + rtree_node_elm_t *node; + + node = rtree_child_node_tryread(elm, dependent); + if (!dependent && unlikely(!rtree_node_valid(node))) { + node = rtree_node_init(tsdn, rtree, level + 1, &elm->child); + } + assert(!dependent || node != NULL); + return node; +} + +static rtree_leaf_elm_t * +rtree_child_leaf_tryread(rtree_node_elm_t *elm, bool dependent) { + rtree_leaf_elm_t *leaf; + + if (dependent) { + leaf = (rtree_leaf_elm_t *)atomic_load_p(&elm->child, + ATOMIC_RELAXED); + } else { + leaf = (rtree_leaf_elm_t *)atomic_load_p(&elm->child, + ATOMIC_ACQUIRE); + } + + assert(!dependent || leaf != NULL); + return leaf; +} + +static rtree_leaf_elm_t * +rtree_child_leaf_read(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *elm, + unsigned level, bool dependent) { + rtree_leaf_elm_t *leaf; + + leaf = rtree_child_leaf_tryread(elm, dependent); + if (!dependent && unlikely(!rtree_leaf_valid(leaf))) { + leaf = rtree_leaf_init(tsdn, rtree, &elm->child); + } + assert(!dependent || leaf != NULL); + return leaf; +} + +rtree_leaf_elm_t * +rtree_leaf_elm_lookup_hard(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, + uintptr_t key, bool dependent, bool init_missing) { + rtree_node_elm_t *node; + rtree_leaf_elm_t *leaf; +#if RTREE_HEIGHT > 1 + node = rtree->root; +#else + leaf = rtree->root; +#endif + + if (config_debug) { + uintptr_t leafkey = rtree_leafkey(key); + for (unsigned i = 0; i < RTREE_CTX_NCACHE; i++) { + assert(rtree_ctx->cache[i].leafkey != leafkey); + } + for (unsigned i = 0; i < RTREE_CTX_NCACHE_L2; i++) { + assert(rtree_ctx->l2_cache[i].leafkey != leafkey); + } + } + +#define RTREE_GET_CHILD(level) { \ + assert(level < RTREE_HEIGHT-1); \ + if (level != 0 && !dependent && \ + unlikely(!rtree_node_valid(node))) { \ + return NULL; \ + } \ + uintptr_t subkey = rtree_subkey(key, level); \ + if (level + 2 < RTREE_HEIGHT) { \ + node = init_missing ? \ + rtree_child_node_read(tsdn, rtree, \ + &node[subkey], level, dependent) : \ + rtree_child_node_tryread(&node[subkey], \ + dependent); \ + } else { \ + leaf = init_missing ? \ + rtree_child_leaf_read(tsdn, rtree, \ + &node[subkey], level, dependent) : \ + rtree_child_leaf_tryread(&node[subkey], \ + dependent); \ + } \ + } + /* + * Cache replacement upon hard lookup (i.e. L1 & L2 rtree cache miss): + * (1) evict last entry in L2 cache; (2) move the collision slot from L1 + * cache down to L2; and 3) fill L1. + */ +#define RTREE_GET_LEAF(level) { \ + assert(level == RTREE_HEIGHT-1); \ + if (!dependent && unlikely(!rtree_leaf_valid(leaf))) { \ + return NULL; \ + } \ + if (RTREE_CTX_NCACHE_L2 > 1) { \ + memmove(&rtree_ctx->l2_cache[1], \ + &rtree_ctx->l2_cache[0], \ + sizeof(rtree_ctx_cache_elm_t) * \ + (RTREE_CTX_NCACHE_L2 - 1)); \ + } \ + size_t slot = rtree_cache_direct_map(key); \ + rtree_ctx->l2_cache[0].leafkey = \ + rtree_ctx->cache[slot].leafkey; \ + rtree_ctx->l2_cache[0].leaf = \ + rtree_ctx->cache[slot].leaf; \ + uintptr_t leafkey = rtree_leafkey(key); \ + rtree_ctx->cache[slot].leafkey = leafkey; \ + rtree_ctx->cache[slot].leaf = leaf; \ + uintptr_t subkey = rtree_subkey(key, level); \ + return &leaf[subkey]; \ + } + if (RTREE_HEIGHT > 1) { + RTREE_GET_CHILD(0) + } + if (RTREE_HEIGHT > 2) { + RTREE_GET_CHILD(1) + } + if (RTREE_HEIGHT > 3) { + for (unsigned i = 2; i < RTREE_HEIGHT-1; i++) { + RTREE_GET_CHILD(i) + } + } + RTREE_GET_LEAF(RTREE_HEIGHT-1) +#undef RTREE_GET_CHILD +#undef RTREE_GET_LEAF + not_reached(); +} + +void +rtree_ctx_data_init(rtree_ctx_t *ctx) { + for (unsigned i = 0; i < RTREE_CTX_NCACHE; i++) { + rtree_ctx_cache_elm_t *cache = &ctx->cache[i]; + cache->leafkey = RTREE_LEAFKEY_INVALID; + cache->leaf = NULL; + } + for (unsigned i = 0; i < RTREE_CTX_NCACHE_L2; i++) { + rtree_ctx_cache_elm_t *cache = &ctx->l2_cache[i]; + cache->leafkey = RTREE_LEAFKEY_INVALID; + cache->leaf = NULL; + } } diff --git a/deps/jemalloc/src/stats.c b/deps/jemalloc/src/stats.c index bef2ab33cd..087df7676e 100644 --- a/deps/jemalloc/src/stats.c +++ b/deps/jemalloc/src/stats.c @@ -1,549 +1,1285 @@ -#define JEMALLOC_STATS_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_STATS_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" -#define CTL_GET(n, v, t) do { \ - size_t sz = sizeof(t); \ - xmallctl(n, v, &sz, NULL, 0); \ -} while (0) +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/ctl.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/mutex_prof.h" -#define CTL_I_GET(n, v, t) do { \ - size_t mib[6]; \ - size_t miblen = sizeof(mib) / sizeof(size_t); \ +const char *global_mutex_names[mutex_prof_num_global_mutexes] = { +#define OP(mtx) #mtx, + MUTEX_PROF_GLOBAL_MUTEXES +#undef OP +}; + +const char *arena_mutex_names[mutex_prof_num_arena_mutexes] = { +#define OP(mtx) #mtx, + MUTEX_PROF_ARENA_MUTEXES +#undef OP +}; + +#define CTL_GET(n, v, t) do { \ size_t sz = sizeof(t); \ - xmallctlnametomib(n, mib, &miblen); \ - mib[2] = i; \ - xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ + xmallctl(n, (void *)v, &sz, NULL, 0); \ } while (0) -#define CTL_J_GET(n, v, t) do { \ - size_t mib[6]; \ +#define CTL_M2_GET(n, i, v, t) do { \ + size_t mib[CTL_MAX_DEPTH]; \ size_t miblen = sizeof(mib) / sizeof(size_t); \ size_t sz = sizeof(t); \ xmallctlnametomib(n, mib, &miblen); \ - mib[2] = j; \ - xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ + mib[2] = (i); \ + xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \ } while (0) -#define CTL_IJ_GET(n, v, t) do { \ - size_t mib[6]; \ +#define CTL_M2_M4_GET(n, i, j, v, t) do { \ + size_t mib[CTL_MAX_DEPTH]; \ size_t miblen = sizeof(mib) / sizeof(size_t); \ size_t sz = sizeof(t); \ xmallctlnametomib(n, mib, &miblen); \ - mib[2] = i; \ - mib[4] = j; \ - xmallctlbymib(mib, miblen, v, &sz, NULL, 0); \ + mib[2] = (i); \ + mib[4] = (j); \ + xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \ } while (0) /******************************************************************************/ /* Data. */ -bool opt_stats_print = false; - -size_t stats_cactive = 0; +bool opt_stats_print = false; +char opt_stats_print_opts[stats_print_tot_num_options+1] = ""; /******************************************************************************/ -/* Function prototypes for non-inline static functions. */ -static void stats_arena_bins_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i); -static void stats_arena_lruns_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i); -static void stats_arena_print(void (*write_cb)(void *, const char *), - void *cbopaque, unsigned i, bool bins, bool large); +/* Calculate x.yyy and output a string (takes a fixed sized char array). */ +static bool +get_rate_str(uint64_t dividend, uint64_t divisor, char str[6]) { + if (divisor == 0 || dividend > divisor) { + /* The rate is not supposed to be greater than 1. */ + return true; + } + if (dividend > 0) { + assert(UINT64_MAX / dividend >= 1000); + } -/******************************************************************************/ + unsigned n = (unsigned)((dividend * 1000) / divisor); + if (n < 10) { + malloc_snprintf(str, 6, "0.00%u", n); + } else if (n < 100) { + malloc_snprintf(str, 6, "0.0%u", n); + } else if (n < 1000) { + malloc_snprintf(str, 6, "0.%u", n); + } else { + malloc_snprintf(str, 6, "1"); + } + + return false; +} + +#define MUTEX_CTL_STR_MAX_LENGTH 128 +static void +gen_mutex_ctl_str(char *str, size_t buf_len, const char *prefix, + const char *mutex, const char *counter) { + malloc_snprintf(str, buf_len, "stats.%s.%s.%s", prefix, mutex, counter); +} + +static void +read_arena_bin_mutex_stats(unsigned arena_ind, unsigned bin_ind, + uint64_t results[mutex_prof_num_counters]) { + char cmd[MUTEX_CTL_STR_MAX_LENGTH]; +#define OP(c, t) \ + gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ + "arenas.0.bins.0","mutex", #c); \ + CTL_M2_M4_GET(cmd, arena_ind, bin_ind, \ + (t *)&results[mutex_counter_##c], t); +MUTEX_PROF_COUNTERS +#undef OP +} + +static void +mutex_stats_output_json(void (*write_cb)(void *, const char *), void *cbopaque, + const char *name, uint64_t stats[mutex_prof_num_counters], + const char *json_indent, bool last) { + malloc_cprintf(write_cb, cbopaque, "%s\"%s\": {\n", json_indent, name); + + mutex_prof_counter_ind_t k = 0; + char *fmt_str[2] = {"%s\t\"%s\": %"FMTu32"%s\n", + "%s\t\"%s\": %"FMTu64"%s\n"}; +#define OP(c, t) \ + malloc_cprintf(write_cb, cbopaque, \ + fmt_str[sizeof(t) / sizeof(uint32_t) - 1], \ + json_indent, #c, (t)stats[mutex_counter_##c], \ + (++k == mutex_prof_num_counters) ? "" : ","); +MUTEX_PROF_COUNTERS +#undef OP + malloc_cprintf(write_cb, cbopaque, "%s}%s\n", json_indent, + last ? "" : ","); +} static void stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i) -{ + bool json, bool large, bool mutex, unsigned i) { size_t page; - bool config_tcache; - unsigned nbins, j, gap_start; + bool in_gap, in_gap_prev; + unsigned nbins, j; CTL_GET("arenas.page", &page, size_t); - CTL_GET("config.tcache", &config_tcache, bool); - if (config_tcache) { + CTL_GET("arenas.nbins", &nbins, unsigned); + if (json) { malloc_cprintf(write_cb, cbopaque, - "bins: bin size regs pgs allocated nmalloc" - " ndalloc nrequests nfills nflushes" - " newruns reruns curruns\n"); + "\t\t\t\t\"bins\": [\n"); } else { + char *mutex_counters = " n_lock_ops n_waiting" + " n_spin_acq total_wait_ns max_wait_ns\n"; malloc_cprintf(write_cb, cbopaque, - "bins: bin size regs pgs allocated nmalloc" - " ndalloc newruns reruns curruns\n"); + "bins: size ind allocated nmalloc" + " ndalloc nrequests curregs curslabs regs" + " pgs util nfills nflushes newslabs" + " reslabs%s", mutex ? mutex_counters : "\n"); } - CTL_GET("arenas.nbins", &nbins, unsigned); - for (j = 0, gap_start = UINT_MAX; j < nbins; j++) { - uint64_t nruns; + for (j = 0, in_gap = false; j < nbins; j++) { + uint64_t nslabs; + size_t reg_size, slab_size, curregs; + size_t curslabs; + uint32_t nregs; + uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; + uint64_t nreslabs; - CTL_IJ_GET("stats.arenas.0.bins.0.nruns", &nruns, uint64_t); - if (nruns == 0) { - if (gap_start == UINT_MAX) - gap_start = j; - } else { - size_t reg_size, run_size, allocated; - uint32_t nregs; - uint64_t nmalloc, ndalloc, nrequests, nfills, nflushes; - uint64_t reruns; - size_t curruns; - - if (gap_start != UINT_MAX) { - if (j > gap_start + 1) { - /* Gap of more than one size class. */ - malloc_cprintf(write_cb, cbopaque, - "[%u..%u]\n", gap_start, - j - 1); + CTL_M2_M4_GET("stats.arenas.0.bins.0.nslabs", i, j, &nslabs, + uint64_t); + in_gap_prev = in_gap; + in_gap = (nslabs == 0); + + if (!json && in_gap_prev && !in_gap) { + malloc_cprintf(write_cb, cbopaque, + " ---\n"); + } + + CTL_M2_GET("arenas.bin.0.size", j, ®_size, size_t); + CTL_M2_GET("arenas.bin.0.nregs", j, &nregs, uint32_t); + CTL_M2_GET("arenas.bin.0.slab_size", j, &slab_size, size_t); + + CTL_M2_M4_GET("stats.arenas.0.bins.0.nmalloc", i, j, &nmalloc, + uint64_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.ndalloc", i, j, &ndalloc, + uint64_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.curregs", i, j, &curregs, + size_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.nrequests", i, j, + &nrequests, uint64_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.nfills", i, j, &nfills, + uint64_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.nflushes", i, j, &nflushes, + uint64_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.nreslabs", i, j, &nreslabs, + uint64_t); + CTL_M2_M4_GET("stats.arenas.0.bins.0.curslabs", i, j, &curslabs, + size_t); + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t{\n" + "\t\t\t\t\t\t\"nmalloc\": %"FMTu64",\n" + "\t\t\t\t\t\t\"ndalloc\": %"FMTu64",\n" + "\t\t\t\t\t\t\"curregs\": %zu,\n" + "\t\t\t\t\t\t\"nrequests\": %"FMTu64",\n" + "\t\t\t\t\t\t\"nfills\": %"FMTu64",\n" + "\t\t\t\t\t\t\"nflushes\": %"FMTu64",\n" + "\t\t\t\t\t\t\"nreslabs\": %"FMTu64",\n" + "\t\t\t\t\t\t\"curslabs\": %zu%s\n", + nmalloc, ndalloc, curregs, nrequests, nfills, + nflushes, nreslabs, curslabs, mutex ? "," : ""); + if (mutex) { + uint64_t mutex_stats[mutex_prof_num_counters]; + read_arena_bin_mutex_stats(i, j, mutex_stats); + mutex_stats_output_json(write_cb, cbopaque, + "mutex", mutex_stats, "\t\t\t\t\t\t", true); + } + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t}%s\n", + (j + 1 < nbins) ? "," : ""); + } else if (!in_gap) { + size_t availregs = nregs * curslabs; + char util[6]; + if (get_rate_str((uint64_t)curregs, (uint64_t)availregs, + util)) { + if (availregs == 0) { + malloc_snprintf(util, sizeof(util), + "1"); + } else if (curregs > availregs) { + /* + * Race detected: the counters were read + * in separate mallctl calls and + * concurrent operations happened in + * between. In this case no meaningful + * utilization can be computed. + */ + malloc_snprintf(util, sizeof(util), + " race"); } else { - /* Gap of one size class. */ - malloc_cprintf(write_cb, cbopaque, - "[%u]\n", gap_start); + not_reached(); } - gap_start = UINT_MAX; } - CTL_J_GET("arenas.bin.0.size", ®_size, size_t); - CTL_J_GET("arenas.bin.0.nregs", &nregs, uint32_t); - CTL_J_GET("arenas.bin.0.run_size", &run_size, size_t); - CTL_IJ_GET("stats.arenas.0.bins.0.allocated", - &allocated, size_t); - CTL_IJ_GET("stats.arenas.0.bins.0.nmalloc", - &nmalloc, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.ndalloc", - &ndalloc, uint64_t); - if (config_tcache) { - CTL_IJ_GET("stats.arenas.0.bins.0.nrequests", - &nrequests, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.nfills", - &nfills, uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.nflushes", - &nflushes, uint64_t); + uint64_t mutex_stats[mutex_prof_num_counters]; + if (mutex) { + read_arena_bin_mutex_stats(i, j, mutex_stats); } - CTL_IJ_GET("stats.arenas.0.bins.0.nreruns", &reruns, - uint64_t); - CTL_IJ_GET("stats.arenas.0.bins.0.curruns", &curruns, - size_t); - if (config_tcache) { + + malloc_cprintf(write_cb, cbopaque, "%20zu %3u %12zu %12" + FMTu64" %12"FMTu64" %12"FMTu64" %12zu %12zu %4u" + " %3zu %-5s %12"FMTu64" %12"FMTu64" %12"FMTu64 + " %12"FMTu64, reg_size, j, curregs * reg_size, + nmalloc, ndalloc, nrequests, curregs, curslabs, + nregs, slab_size / page, util, nfills, nflushes, + nslabs, nreslabs); + + /* Output less info for bin mutexes to save space. */ + if (mutex) { malloc_cprintf(write_cb, cbopaque, - "%13u %5zu %4u %3zu %12zu %12"PRIu64 - " %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12zu\n", - j, reg_size, nregs, run_size / page, - allocated, nmalloc, ndalloc, nrequests, - nfills, nflushes, nruns, reruns, curruns); + " %12"FMTu64" %12"FMTu64" %12"FMTu64 + " %14"FMTu64" %12"FMTu64"\n", + mutex_stats[mutex_counter_num_ops], + mutex_stats[mutex_counter_num_wait], + mutex_stats[mutex_counter_num_spin_acq], + mutex_stats[mutex_counter_total_wait_time], + mutex_stats[mutex_counter_max_wait_time]); } else { - malloc_cprintf(write_cb, cbopaque, - "%13u %5zu %4u %3zu %12zu %12"PRIu64 - " %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12zu\n", - j, reg_size, nregs, run_size / page, - allocated, nmalloc, ndalloc, nruns, reruns, - curruns); + malloc_cprintf(write_cb, cbopaque, "\n"); } } } - if (gap_start != UINT_MAX) { - if (j > gap_start + 1) { - /* Gap of more than one size class. */ - malloc_cprintf(write_cb, cbopaque, "[%u..%u]\n", - gap_start, j - 1); - } else { - /* Gap of one size class. */ - malloc_cprintf(write_cb, cbopaque, "[%u]\n", gap_start); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t]%s\n", large ? "," : ""); + } else { + if (in_gap) { + malloc_cprintf(write_cb, cbopaque, + " ---\n"); } } } static void -stats_arena_lruns_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i) -{ - size_t page, nlruns, j; - ssize_t gap_start; - - CTL_GET("arenas.page", &page, size_t); +stats_arena_lextents_print(void (*write_cb)(void *, const char *), + void *cbopaque, bool json, unsigned i) { + unsigned nbins, nlextents, j; + bool in_gap, in_gap_prev; - malloc_cprintf(write_cb, cbopaque, - "large: size pages nmalloc ndalloc nrequests" - " curruns\n"); - CTL_GET("arenas.nlruns", &nlruns, size_t); - for (j = 0, gap_start = -1; j < nlruns; j++) { + CTL_GET("arenas.nbins", &nbins, unsigned); + CTL_GET("arenas.nlextents", &nlextents, unsigned); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"lextents\": [\n"); + } else { + malloc_cprintf(write_cb, cbopaque, + "large: size ind allocated nmalloc" + " ndalloc nrequests curlextents\n"); + } + for (j = 0, in_gap = false; j < nlextents; j++) { uint64_t nmalloc, ndalloc, nrequests; - size_t run_size, curruns; + size_t lextent_size, curlextents; - CTL_IJ_GET("stats.arenas.0.lruns.0.nmalloc", &nmalloc, - uint64_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.ndalloc", &ndalloc, - uint64_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.nrequests", &nrequests, - uint64_t); - if (nrequests == 0) { - if (gap_start == -1) - gap_start = j; - } else { - CTL_J_GET("arenas.lrun.0.size", &run_size, size_t); - CTL_IJ_GET("stats.arenas.0.lruns.0.curruns", &curruns, - size_t); - if (gap_start != -1) { - malloc_cprintf(write_cb, cbopaque, "[%zu]\n", - j - gap_start); - gap_start = -1; - } + CTL_M2_M4_GET("stats.arenas.0.lextents.0.nmalloc", i, j, + &nmalloc, uint64_t); + CTL_M2_M4_GET("stats.arenas.0.lextents.0.ndalloc", i, j, + &ndalloc, uint64_t); + CTL_M2_M4_GET("stats.arenas.0.lextents.0.nrequests", i, j, + &nrequests, uint64_t); + in_gap_prev = in_gap; + in_gap = (nrequests == 0); + + if (!json && in_gap_prev && !in_gap) { + malloc_cprintf(write_cb, cbopaque, + " ---\n"); + } + + CTL_M2_GET("arenas.lextent.0.size", j, &lextent_size, size_t); + CTL_M2_M4_GET("stats.arenas.0.lextents.0.curlextents", i, j, + &curlextents, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t{\n" + "\t\t\t\t\t\t\"curlextents\": %zu\n" + "\t\t\t\t\t}%s\n", + curlextents, + (j + 1 < nlextents) ? "," : ""); + } else if (!in_gap) { + malloc_cprintf(write_cb, cbopaque, + "%20zu %3u %12zu %12"FMTu64" %12"FMTu64 + " %12"FMTu64" %12zu\n", + lextent_size, nbins + j, + curlextents * lextent_size, nmalloc, ndalloc, + nrequests, curlextents); + } + } + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t]\n"); + } else { + if (in_gap) { malloc_cprintf(write_cb, cbopaque, - "%13zu %5zu %12"PRIu64" %12"PRIu64" %12"PRIu64 - " %12zu\n", - run_size, run_size / page, nmalloc, ndalloc, - nrequests, curruns); + " ---\n"); + } + } +} + +static void +read_arena_mutex_stats(unsigned arena_ind, + uint64_t results[mutex_prof_num_arena_mutexes][mutex_prof_num_counters]) { + char cmd[MUTEX_CTL_STR_MAX_LENGTH]; + + mutex_prof_arena_ind_t i; + for (i = 0; i < mutex_prof_num_arena_mutexes; i++) { +#define OP(c, t) \ + gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ + "arenas.0.mutexes", arena_mutex_names[i], #c); \ + CTL_M2_GET(cmd, arena_ind, \ + (t *)&results[i][mutex_counter_##c], t); +MUTEX_PROF_COUNTERS +#undef OP + } +} + +static void +mutex_stats_output(void (*write_cb)(void *, const char *), void *cbopaque, + const char *name, uint64_t stats[mutex_prof_num_counters], + bool first_mutex) { + if (first_mutex) { + /* Print title. */ + malloc_cprintf(write_cb, cbopaque, + " n_lock_ops n_waiting" + " n_spin_acq n_owner_switch total_wait_ns" + " max_wait_ns max_n_thds\n"); + } + + malloc_cprintf(write_cb, cbopaque, "%s", name); + malloc_cprintf(write_cb, cbopaque, ":%*c", + (int)(20 - strlen(name)), ' '); + + char *fmt_str[2] = {"%12"FMTu32, "%16"FMTu64}; +#define OP(c, t) \ + malloc_cprintf(write_cb, cbopaque, \ + fmt_str[sizeof(t) / sizeof(uint32_t) - 1], \ + (t)stats[mutex_counter_##c]); +MUTEX_PROF_COUNTERS +#undef OP + malloc_cprintf(write_cb, cbopaque, "\n"); +} + +static void +stats_arena_mutexes_print(void (*write_cb)(void *, const char *), + void *cbopaque, bool json, bool json_end, unsigned arena_ind) { + uint64_t mutex_stats[mutex_prof_num_arena_mutexes][mutex_prof_num_counters]; + read_arena_mutex_stats(arena_ind, mutex_stats); + + /* Output mutex stats. */ + if (json) { + malloc_cprintf(write_cb, cbopaque, "\t\t\t\t\"mutexes\": {\n"); + mutex_prof_arena_ind_t i, last_mutex; + last_mutex = mutex_prof_num_arena_mutexes - 1; + for (i = 0; i < mutex_prof_num_arena_mutexes; i++) { + mutex_stats_output_json(write_cb, cbopaque, + arena_mutex_names[i], mutex_stats[i], + "\t\t\t\t\t", (i == last_mutex)); + } + malloc_cprintf(write_cb, cbopaque, "\t\t\t\t}%s\n", + json_end ? "" : ","); + } else { + mutex_prof_arena_ind_t i; + for (i = 0; i < mutex_prof_num_arena_mutexes; i++) { + mutex_stats_output(write_cb, cbopaque, + arena_mutex_names[i], mutex_stats[i], i == 0); } } - if (gap_start != -1) - malloc_cprintf(write_cb, cbopaque, "[%zu]\n", j - gap_start); } static void stats_arena_print(void (*write_cb)(void *, const char *), void *cbopaque, - unsigned i, bool bins, bool large) -{ + bool json, unsigned i, bool bins, bool large, bool mutex) { unsigned nthreads; const char *dss; - size_t page, pactive, pdirty, mapped; - uint64_t npurge, nmadvise, purged; + ssize_t dirty_decay_ms, muzzy_decay_ms; + size_t page, pactive, pdirty, pmuzzy, mapped, retained; + size_t base, internal, resident; + uint64_t dirty_npurge, dirty_nmadvise, dirty_purged; + uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged; size_t small_allocated; uint64_t small_nmalloc, small_ndalloc, small_nrequests; size_t large_allocated; uint64_t large_nmalloc, large_ndalloc, large_nrequests; + size_t tcache_bytes; + uint64_t uptime; CTL_GET("arenas.page", &page, size_t); - CTL_I_GET("stats.arenas.0.nthreads", &nthreads, unsigned); - malloc_cprintf(write_cb, cbopaque, - "assigned threads: %u\n", nthreads); - CTL_I_GET("stats.arenas.0.dss", &dss, const char *); - malloc_cprintf(write_cb, cbopaque, "dss allocation precedence: %s\n", - dss); - CTL_I_GET("stats.arenas.0.pactive", &pactive, size_t); - CTL_I_GET("stats.arenas.0.pdirty", &pdirty, size_t); - CTL_I_GET("stats.arenas.0.npurge", &npurge, uint64_t); - CTL_I_GET("stats.arenas.0.nmadvise", &nmadvise, uint64_t); - CTL_I_GET("stats.arenas.0.purged", &purged, uint64_t); - malloc_cprintf(write_cb, cbopaque, - "dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s," - " %"PRIu64" madvise%s, %"PRIu64" purged\n", - pactive, pdirty, npurge, npurge == 1 ? "" : "s", - nmadvise, nmadvise == 1 ? "" : "s", purged); - - malloc_cprintf(write_cb, cbopaque, - " allocated nmalloc ndalloc nrequests\n"); - CTL_I_GET("stats.arenas.0.small.allocated", &small_allocated, size_t); - CTL_I_GET("stats.arenas.0.small.nmalloc", &small_nmalloc, uint64_t); - CTL_I_GET("stats.arenas.0.small.ndalloc", &small_ndalloc, uint64_t); - CTL_I_GET("stats.arenas.0.small.nrequests", &small_nrequests, uint64_t); - malloc_cprintf(write_cb, cbopaque, - "small: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", - small_allocated, small_nmalloc, small_ndalloc, small_nrequests); - CTL_I_GET("stats.arenas.0.large.allocated", &large_allocated, size_t); - CTL_I_GET("stats.arenas.0.large.nmalloc", &large_nmalloc, uint64_t); - CTL_I_GET("stats.arenas.0.large.ndalloc", &large_ndalloc, uint64_t); - CTL_I_GET("stats.arenas.0.large.nrequests", &large_nrequests, uint64_t); - malloc_cprintf(write_cb, cbopaque, - "large: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", - large_allocated, large_nmalloc, large_ndalloc, large_nrequests); - malloc_cprintf(write_cb, cbopaque, - "total: %12zu %12"PRIu64" %12"PRIu64" %12"PRIu64"\n", - small_allocated + large_allocated, - small_nmalloc + large_nmalloc, - small_ndalloc + large_ndalloc, - small_nrequests + large_nrequests); - malloc_cprintf(write_cb, cbopaque, "active: %12zu\n", pactive * page); - CTL_I_GET("stats.arenas.0.mapped", &mapped, size_t); - malloc_cprintf(write_cb, cbopaque, "mapped: %12zu\n", mapped); - - if (bins) - stats_arena_bins_print(write_cb, cbopaque, i); - if (large) - stats_arena_lruns_print(write_cb, cbopaque, i); -} + CTL_M2_GET("stats.arenas.0.nthreads", i, &nthreads, unsigned); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"nthreads\": %u,\n", nthreads); + } else { + malloc_cprintf(write_cb, cbopaque, + "assigned threads: %u\n", nthreads); + } -void -stats_print(void (*write_cb)(void *, const char *), void *cbopaque, - const char *opts) -{ - int err; - uint64_t epoch; - size_t u64sz; - bool general = true; - bool merged = true; - bool unmerged = true; - bool bins = true; - bool large = true; + CTL_M2_GET("stats.arenas.0.uptime", i, &uptime, uint64_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"uptime_ns\": %"FMTu64",\n", uptime); + } else { + malloc_cprintf(write_cb, cbopaque, + "uptime: %"FMTu64"\n", uptime); + } - /* - * Refresh stats, in case mallctl() was called by the application. - * - * Check for OOM here, since refreshing the ctl cache can trigger - * allocation. In practice, none of the subsequent mallctl()-related - * calls in this function will cause OOM if this one succeeds. - * */ - epoch = 1; - u64sz = sizeof(uint64_t); - err = je_mallctl("epoch", &epoch, &u64sz, &epoch, sizeof(uint64_t)); - if (err != 0) { - if (err == EAGAIN) { - malloc_write("<jemalloc>: Memory allocation failure in " - "mallctl(\"epoch\", ...)\n"); - return; + CTL_M2_GET("stats.arenas.0.dss", i, &dss, const char *); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"dss\": \"%s\",\n", dss); + } else { + malloc_cprintf(write_cb, cbopaque, + "dss allocation precedence: %s\n", dss); + } + + CTL_M2_GET("stats.arenas.0.dirty_decay_ms", i, &dirty_decay_ms, + ssize_t); + CTL_M2_GET("stats.arenas.0.muzzy_decay_ms", i, &muzzy_decay_ms, + ssize_t); + CTL_M2_GET("stats.arenas.0.pactive", i, &pactive, size_t); + CTL_M2_GET("stats.arenas.0.pdirty", i, &pdirty, size_t); + CTL_M2_GET("stats.arenas.0.pmuzzy", i, &pmuzzy, size_t); + CTL_M2_GET("stats.arenas.0.dirty_npurge", i, &dirty_npurge, uint64_t); + CTL_M2_GET("stats.arenas.0.dirty_nmadvise", i, &dirty_nmadvise, + uint64_t); + CTL_M2_GET("stats.arenas.0.dirty_purged", i, &dirty_purged, uint64_t); + CTL_M2_GET("stats.arenas.0.muzzy_npurge", i, &muzzy_npurge, uint64_t); + CTL_M2_GET("stats.arenas.0.muzzy_nmadvise", i, &muzzy_nmadvise, + uint64_t); + CTL_M2_GET("stats.arenas.0.muzzy_purged", i, &muzzy_purged, uint64_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"dirty_decay_ms\": %zd,\n", dirty_decay_ms); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"muzzy_decay_ms\": %zd,\n", muzzy_decay_ms); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"pactive\": %zu,\n", pactive); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"pdirty\": %zu,\n", pdirty); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"pmuzzy\": %zu,\n", pmuzzy); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"dirty_npurge\": %"FMTu64",\n", dirty_npurge); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"dirty_nmadvise\": %"FMTu64",\n", dirty_nmadvise); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"dirty_purged\": %"FMTu64",\n", dirty_purged); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"muzzy_npurge\": %"FMTu64",\n", muzzy_npurge); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"muzzy_nmadvise\": %"FMTu64",\n", muzzy_nmadvise); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"muzzy_purged\": %"FMTu64",\n", muzzy_purged); + } else { + malloc_cprintf(write_cb, cbopaque, + "decaying: time npages sweeps madvises" + " purged\n"); + if (dirty_decay_ms >= 0) { + malloc_cprintf(write_cb, cbopaque, + " dirty: %5zd %12zu %12"FMTu64" %12"FMTu64" %12" + FMTu64"\n", dirty_decay_ms, pdirty, dirty_npurge, + dirty_nmadvise, dirty_purged); + } else { + malloc_cprintf(write_cb, cbopaque, + " dirty: N/A %12zu %12"FMTu64" %12"FMTu64" %12" + FMTu64"\n", pdirty, dirty_npurge, dirty_nmadvise, + dirty_purged); + } + if (muzzy_decay_ms >= 0) { + malloc_cprintf(write_cb, cbopaque, + " muzzy: %5zd %12zu %12"FMTu64" %12"FMTu64" %12" + FMTu64"\n", muzzy_decay_ms, pmuzzy, muzzy_npurge, + muzzy_nmadvise, muzzy_purged); + } else { + malloc_cprintf(write_cb, cbopaque, + " muzzy: N/A %12zu %12"FMTu64" %12"FMTu64" %12" + FMTu64"\n", pmuzzy, muzzy_npurge, muzzy_nmadvise, + muzzy_purged); } - malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", " - "...)\n"); - abort(); } - if (opts != NULL) { - unsigned i; + CTL_M2_GET("stats.arenas.0.small.allocated", i, &small_allocated, + size_t); + CTL_M2_GET("stats.arenas.0.small.nmalloc", i, &small_nmalloc, uint64_t); + CTL_M2_GET("stats.arenas.0.small.ndalloc", i, &small_ndalloc, uint64_t); + CTL_M2_GET("stats.arenas.0.small.nrequests", i, &small_nrequests, + uint64_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"small\": {\n"); - for (i = 0; opts[i] != '\0'; i++) { - switch (opts[i]) { - case 'g': - general = false; - break; - case 'm': - merged = false; - break; - case 'a': - unmerged = false; - break; - case 'b': - bins = false; - break; - case 'l': - large = false; - break; - default:; - } - } + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"allocated\": %zu,\n", small_allocated); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", small_nmalloc); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", small_ndalloc); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", small_nrequests); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t},\n"); + } else { + malloc_cprintf(write_cb, cbopaque, + " allocated nmalloc" + " ndalloc nrequests\n"); + malloc_cprintf(write_cb, cbopaque, + "small: %12zu %12"FMTu64" %12"FMTu64 + " %12"FMTu64"\n", + small_allocated, small_nmalloc, small_ndalloc, + small_nrequests); } - malloc_cprintf(write_cb, cbopaque, - "___ Begin jemalloc statistics ___\n"); - if (general) { - int err; - const char *cpv; - bool bv; - unsigned uv; - ssize_t ssv; - size_t sv, bsz, ssz, sssz, cpsz; - - bsz = sizeof(bool); - ssz = sizeof(size_t); - sssz = sizeof(ssize_t); - cpsz = sizeof(const char *); - - CTL_GET("version", &cpv, const char *); + CTL_M2_GET("stats.arenas.0.large.allocated", i, &large_allocated, + size_t); + CTL_M2_GET("stats.arenas.0.large.nmalloc", i, &large_nmalloc, uint64_t); + CTL_M2_GET("stats.arenas.0.large.ndalloc", i, &large_ndalloc, uint64_t); + CTL_M2_GET("stats.arenas.0.large.nrequests", i, &large_nrequests, + uint64_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"large\": {\n"); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"allocated\": %zu,\n", large_allocated); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"nmalloc\": %"FMTu64",\n", large_nmalloc); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"ndalloc\": %"FMTu64",\n", large_ndalloc); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"nrequests\": %"FMTu64"\n", large_nrequests); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t},\n"); + } else { + malloc_cprintf(write_cb, cbopaque, + "large: %12zu %12"FMTu64" %12"FMTu64 + " %12"FMTu64"\n", + large_allocated, large_nmalloc, large_ndalloc, + large_nrequests); + malloc_cprintf(write_cb, cbopaque, + "total: %12zu %12"FMTu64" %12"FMTu64 + " %12"FMTu64"\n", + small_allocated + large_allocated, small_nmalloc + + large_nmalloc, small_ndalloc + large_ndalloc, + small_nrequests + large_nrequests); + } + if (!json) { + malloc_cprintf(write_cb, cbopaque, + "active: %12zu\n", pactive * page); + } + + CTL_M2_GET("stats.arenas.0.mapped", i, &mapped, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"mapped\": %zu,\n", mapped); + } else { + malloc_cprintf(write_cb, cbopaque, + "mapped: %12zu\n", mapped); + } + + CTL_M2_GET("stats.arenas.0.retained", i, &retained, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"retained\": %zu,\n", retained); + } else { + malloc_cprintf(write_cb, cbopaque, + "retained: %12zu\n", retained); + } + + CTL_M2_GET("stats.arenas.0.base", i, &base, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"base\": %zu,\n", base); + } else { + malloc_cprintf(write_cb, cbopaque, + "base: %12zu\n", base); + } + + CTL_M2_GET("stats.arenas.0.internal", i, &internal, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"internal\": %zu,\n", internal); + } else { + malloc_cprintf(write_cb, cbopaque, + "internal: %12zu\n", internal); + } + + CTL_M2_GET("stats.arenas.0.tcache_bytes", i, &tcache_bytes, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"tcache\": %zu,\n", tcache_bytes); + } else { + malloc_cprintf(write_cb, cbopaque, + "tcache: %12zu\n", tcache_bytes); + } + + CTL_M2_GET("stats.arenas.0.resident", i, &resident, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"resident\": %zu%s\n", resident, + (bins || large || mutex) ? "," : ""); + } else { + malloc_cprintf(write_cb, cbopaque, + "resident: %12zu\n", resident); + } + + if (mutex) { + stats_arena_mutexes_print(write_cb, cbopaque, json, + !(bins || large), i); + } + if (bins) { + stats_arena_bins_print(write_cb, cbopaque, json, large, mutex, + i); + } + if (large) { + stats_arena_lextents_print(write_cb, cbopaque, json, i); + } +} + +static void +stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque, + bool json, bool more) { + const char *cpv; + bool bv; + unsigned uv; + uint32_t u32v; + uint64_t u64v; + ssize_t ssv; + size_t sv, bsz, usz, ssz, sssz, cpsz; + + bsz = sizeof(bool); + usz = sizeof(unsigned); + ssz = sizeof(size_t); + sssz = sizeof(ssize_t); + cpsz = sizeof(const char *); + + CTL_GET("version", &cpv, const char *); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"version\": \"%s\",\n", cpv); + } else { malloc_cprintf(write_cb, cbopaque, "Version: %s\n", cpv); - CTL_GET("config.debug", &bv, bool); + } + + /* config. */ +#define CONFIG_WRITE_BOOL_JSON(n, c) \ + if (json) { \ + CTL_GET("config."#n, &bv, bool); \ + malloc_cprintf(write_cb, cbopaque, \ + "\t\t\t\""#n"\": %s%s\n", bv ? "true" : "false", \ + (c)); \ + } + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"config\": {\n"); + } + + CONFIG_WRITE_BOOL_JSON(cache_oblivious, ",") + + CTL_GET("config.debug", &bv, bool); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"debug\": %s,\n", bv ? "true" : "false"); + } else { malloc_cprintf(write_cb, cbopaque, "Assertions %s\n", bv ? "enabled" : "disabled"); + } + + CONFIG_WRITE_BOOL_JSON(fill, ",") + CONFIG_WRITE_BOOL_JSON(lazy_lock, ",") + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"malloc_conf\": \"%s\",\n", + config_malloc_conf); + } else { + malloc_cprintf(write_cb, cbopaque, + "config.malloc_conf: \"%s\"\n", config_malloc_conf); + } + + CONFIG_WRITE_BOOL_JSON(prof, ",") + CONFIG_WRITE_BOOL_JSON(prof_libgcc, ",") + CONFIG_WRITE_BOOL_JSON(prof_libunwind, ",") + CONFIG_WRITE_BOOL_JSON(stats, ",") + CONFIG_WRITE_BOOL_JSON(thp, ",") + CONFIG_WRITE_BOOL_JSON(utrace, ",") + CONFIG_WRITE_BOOL_JSON(xmalloc, "") + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t},\n"); + } +#undef CONFIG_WRITE_BOOL_JSON -#define OPT_WRITE_BOOL(n) \ - if ((err = je_mallctl("opt."#n, &bv, &bsz, NULL, 0)) \ - == 0) { \ + /* opt. */ +#define OPT_WRITE_BOOL(n, c) \ + if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0) { \ + if (json) { \ + malloc_cprintf(write_cb, cbopaque, \ + "\t\t\t\""#n"\": %s%s\n", bv ? "true" : \ + "false", (c)); \ + } else { \ malloc_cprintf(write_cb, cbopaque, \ " opt."#n": %s\n", bv ? "true" : "false"); \ - } -#define OPT_WRITE_SIZE_T(n) \ - if ((err = je_mallctl("opt."#n, &sv, &ssz, NULL, 0)) \ - == 0) { \ + } \ + } +#define OPT_WRITE_BOOL_MUTABLE(n, m, c) { \ + bool bv2; \ + if (je_mallctl("opt."#n, (void *)&bv, &bsz, NULL, 0) == 0 && \ + je_mallctl(#m, (void *)&bv2, &bsz, NULL, 0) == 0) { \ + if (json) { \ malloc_cprintf(write_cb, cbopaque, \ - " opt."#n": %zu\n", sv); \ - } -#define OPT_WRITE_SSIZE_T(n) \ - if ((err = je_mallctl("opt."#n, &ssv, &sssz, NULL, 0)) \ - == 0) { \ + "\t\t\t\""#n"\": %s%s\n", bv ? "true" : \ + "false", (c)); \ + } else { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": %s ("#m": %s)\n", bv ? "true" \ + : "false", bv2 ? "true" : "false"); \ + } \ + } \ +} +#define OPT_WRITE_UNSIGNED(n, c) \ + if (je_mallctl("opt."#n, (void *)&uv, &usz, NULL, 0) == 0) { \ + if (json) { \ + malloc_cprintf(write_cb, cbopaque, \ + "\t\t\t\""#n"\": %u%s\n", uv, (c)); \ + } else { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": %u\n", uv); \ + } \ + } +#define OPT_WRITE_SSIZE_T(n, c) \ + if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0) { \ + if (json) { \ + malloc_cprintf(write_cb, cbopaque, \ + "\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \ + } else { \ malloc_cprintf(write_cb, cbopaque, \ " opt."#n": %zd\n", ssv); \ - } -#define OPT_WRITE_CHAR_P(n) \ - if ((err = je_mallctl("opt."#n, &cpv, &cpsz, NULL, 0)) \ - == 0) { \ + } \ + } +#define OPT_WRITE_SSIZE_T_MUTABLE(n, m, c) { \ + ssize_t ssv2; \ + if (je_mallctl("opt."#n, (void *)&ssv, &sssz, NULL, 0) == 0 && \ + je_mallctl(#m, (void *)&ssv2, &sssz, NULL, 0) == 0) { \ + if (json) { \ + malloc_cprintf(write_cb, cbopaque, \ + "\t\t\t\""#n"\": %zd%s\n", ssv, (c)); \ + } else { \ + malloc_cprintf(write_cb, cbopaque, \ + " opt."#n": %zd ("#m": %zd)\n", \ + ssv, ssv2); \ + } \ + } \ +} +#define OPT_WRITE_CHAR_P(n, c) \ + if (je_mallctl("opt."#n, (void *)&cpv, &cpsz, NULL, 0) == 0) { \ + if (json) { \ + malloc_cprintf(write_cb, cbopaque, \ + "\t\t\t\""#n"\": \"%s\"%s\n", cpv, (c)); \ + } else { \ malloc_cprintf(write_cb, cbopaque, \ " opt."#n": \"%s\"\n", cpv); \ - } + } \ + } + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"opt\": {\n"); + } else { malloc_cprintf(write_cb, cbopaque, "Run-time option settings:\n"); - OPT_WRITE_BOOL(abort) - OPT_WRITE_SIZE_T(lg_chunk) - OPT_WRITE_CHAR_P(dss) - OPT_WRITE_SIZE_T(narenas) - OPT_WRITE_SSIZE_T(lg_dirty_mult) - OPT_WRITE_BOOL(stats_print) - OPT_WRITE_BOOL(junk) - OPT_WRITE_SIZE_T(quarantine) - OPT_WRITE_BOOL(redzone) - OPT_WRITE_BOOL(zero) - OPT_WRITE_BOOL(utrace) - OPT_WRITE_BOOL(valgrind) - OPT_WRITE_BOOL(xmalloc) - OPT_WRITE_BOOL(tcache) - OPT_WRITE_SSIZE_T(lg_tcache_max) - OPT_WRITE_BOOL(prof) - OPT_WRITE_CHAR_P(prof_prefix) - OPT_WRITE_BOOL(prof_active) - OPT_WRITE_SSIZE_T(lg_prof_sample) - OPT_WRITE_BOOL(prof_accum) - OPT_WRITE_SSIZE_T(lg_prof_interval) - OPT_WRITE_BOOL(prof_gdump) - OPT_WRITE_BOOL(prof_final) - OPT_WRITE_BOOL(prof_leak) + } + OPT_WRITE_BOOL(abort, ",") + OPT_WRITE_BOOL(abort_conf, ",") + OPT_WRITE_BOOL(retain, ",") + OPT_WRITE_CHAR_P(dss, ",") + OPT_WRITE_UNSIGNED(narenas, ",") + OPT_WRITE_CHAR_P(percpu_arena, ",") + OPT_WRITE_BOOL_MUTABLE(background_thread, background_thread, ",") + OPT_WRITE_SSIZE_T_MUTABLE(dirty_decay_ms, arenas.dirty_decay_ms, ",") + OPT_WRITE_SSIZE_T_MUTABLE(muzzy_decay_ms, arenas.muzzy_decay_ms, ",") + OPT_WRITE_CHAR_P(junk, ",") + OPT_WRITE_BOOL(zero, ",") + OPT_WRITE_BOOL(utrace, ",") + OPT_WRITE_BOOL(xmalloc, ",") + OPT_WRITE_BOOL(tcache, ",") + OPT_WRITE_SSIZE_T(lg_tcache_max, ",") + OPT_WRITE_BOOL(prof, ",") + OPT_WRITE_CHAR_P(prof_prefix, ",") + OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active, ",") + OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init, prof.thread_active_init, + ",") + OPT_WRITE_SSIZE_T_MUTABLE(lg_prof_sample, prof.lg_sample, ",") + OPT_WRITE_BOOL(prof_accum, ",") + OPT_WRITE_SSIZE_T(lg_prof_interval, ",") + OPT_WRITE_BOOL(prof_gdump, ",") + OPT_WRITE_BOOL(prof_final, ",") + OPT_WRITE_BOOL(prof_leak, ",") + OPT_WRITE_BOOL(stats_print, ",") + if (json || opt_stats_print) { + /* + * stats_print_opts is always emitted for JSON, so as long as it + * comes last it's safe to unconditionally omit the comma here + * (rather than having to conditionally omit it elsewhere + * depending on configuration). + */ + OPT_WRITE_CHAR_P(stats_print_opts, "") + } + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t},\n"); + } #undef OPT_WRITE_BOOL -#undef OPT_WRITE_SIZE_T +#undef OPT_WRITE_BOOL_MUTABLE #undef OPT_WRITE_SSIZE_T #undef OPT_WRITE_CHAR_P - malloc_cprintf(write_cb, cbopaque, "CPUs: %u\n", ncpus); + /* arenas. */ + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"arenas\": {\n"); + } - CTL_GET("arenas.narenas", &uv, unsigned); + CTL_GET("arenas.narenas", &uv, unsigned); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"narenas\": %u,\n", uv); + } else { malloc_cprintf(write_cb, cbopaque, "Arenas: %u\n", uv); + } + + if (json) { + CTL_GET("arenas.dirty_decay_ms", &ssv, ssize_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"dirty_decay_ms\": %zd,\n", ssv); - malloc_cprintf(write_cb, cbopaque, "Pointer size: %zu\n", - sizeof(void *)); + CTL_GET("arenas.muzzy_decay_ms", &ssv, ssize_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"muzzy_decay_ms\": %zd,\n", ssv); + } - CTL_GET("arenas.quantum", &sv, size_t); + CTL_GET("arenas.quantum", &sv, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"quantum\": %zu,\n", sv); + } else { malloc_cprintf(write_cb, cbopaque, "Quantum size: %zu\n", sv); + } - CTL_GET("arenas.page", &sv, size_t); + CTL_GET("arenas.page", &sv, size_t); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"page\": %zu,\n", sv); + } else { malloc_cprintf(write_cb, cbopaque, "Page size: %zu\n", sv); + } - CTL_GET("opt.lg_dirty_mult", &ssv, ssize_t); - if (ssv >= 0) { + if (je_mallctl("arenas.tcache_max", (void *)&sv, &ssz, NULL, 0) == 0) { + if (json) { malloc_cprintf(write_cb, cbopaque, - "Min active:dirty page ratio per arena: %u:1\n", - (1U << ssv)); + "\t\t\t\"tcache_max\": %zu,\n", sv); } else { malloc_cprintf(write_cb, cbopaque, - "Min active:dirty page ratio per arena: N/A\n"); + "Maximum thread-cached size class: %zu\n", sv); } - if ((err = je_mallctl("arenas.tcache_max", &sv, &ssz, NULL, 0)) - == 0) { + } + + if (json) { + unsigned nbins, nlextents, i; + + CTL_GET("arenas.nbins", &nbins, unsigned); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"nbins\": %u,\n", nbins); + + CTL_GET("arenas.nhbins", &uv, unsigned); + malloc_cprintf(write_cb, cbopaque, "\t\t\t\"nhbins\": %u,\n", + uv); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"bin\": [\n"); + for (i = 0; i < nbins; i++) { malloc_cprintf(write_cb, cbopaque, - "Maximum thread-cached size class: %zu\n", sv); + "\t\t\t\t{\n"); + + CTL_M2_GET("arenas.bin.0.size", i, &sv, size_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"size\": %zu,\n", sv); + + CTL_M2_GET("arenas.bin.0.nregs", i, &u32v, uint32_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"nregs\": %"FMTu32",\n", u32v); + + CTL_M2_GET("arenas.bin.0.slab_size", i, &sv, size_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"slab_size\": %zu\n", sv); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t}%s\n", (i + 1 < nbins) ? "," : ""); } - if ((err = je_mallctl("opt.prof", &bv, &bsz, NULL, 0)) == 0 && - bv) { - CTL_GET("opt.lg_prof_sample", &sv, size_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t],\n"); + + CTL_GET("arenas.nlextents", &nlextents, unsigned); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"nlextents\": %u,\n", nlextents); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"lextent\": [\n"); + for (i = 0; i < nlextents; i++) { malloc_cprintf(write_cb, cbopaque, - "Average profile sample interval: %"PRIu64 - " (2^%zu)\n", (((uint64_t)1U) << sv), sv); + "\t\t\t\t{\n"); - CTL_GET("opt.lg_prof_interval", &ssv, ssize_t); - if (ssv >= 0) { - malloc_cprintf(write_cb, cbopaque, - "Average profile dump interval: %"PRIu64 - " (2^%zd)\n", - (((uint64_t)1U) << ssv), ssv); - } else { - malloc_cprintf(write_cb, cbopaque, - "Average profile dump interval: N/A\n"); + CTL_M2_GET("arenas.lextent.0.size", i, &sv, size_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\t\"size\": %zu\n", sv); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t}%s\n", (i + 1 < nlextents) ? "," : ""); + } + malloc_cprintf(write_cb, cbopaque, + "\t\t\t]\n"); + + malloc_cprintf(write_cb, cbopaque, + "\t\t}%s\n", (config_prof || more) ? "," : ""); + } + + /* prof. */ + if (config_prof && json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"prof\": {\n"); + + CTL_GET("prof.thread_active_init", &bv, bool); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"thread_active_init\": %s,\n", bv ? "true" : + "false"); + + CTL_GET("prof.active", &bv, bool); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"active\": %s,\n", bv ? "true" : "false"); + + CTL_GET("prof.gdump", &bv, bool); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"gdump\": %s,\n", bv ? "true" : "false"); + + CTL_GET("prof.interval", &u64v, uint64_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"interval\": %"FMTu64",\n", u64v); + + CTL_GET("prof.lg_sample", &ssv, ssize_t); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"lg_sample\": %zd\n", ssv); + + malloc_cprintf(write_cb, cbopaque, + "\t\t}%s\n", more ? "," : ""); + } +} + +static void +read_global_mutex_stats( + uint64_t results[mutex_prof_num_global_mutexes][mutex_prof_num_counters]) { + char cmd[MUTEX_CTL_STR_MAX_LENGTH]; + + mutex_prof_global_ind_t i; + for (i = 0; i < mutex_prof_num_global_mutexes; i++) { +#define OP(c, t) \ + gen_mutex_ctl_str(cmd, MUTEX_CTL_STR_MAX_LENGTH, \ + "mutexes", global_mutex_names[i], #c); \ + CTL_GET(cmd, (t *)&results[i][mutex_counter_##c], t); +MUTEX_PROF_COUNTERS +#undef OP + } +} + +static void +stats_print_helper(void (*write_cb)(void *, const char *), void *cbopaque, + bool json, bool merged, bool destroyed, bool unmerged, bool bins, + bool large, bool mutex) { + size_t allocated, active, metadata, resident, mapped, retained; + size_t num_background_threads; + uint64_t background_thread_num_runs, background_thread_run_interval; + + CTL_GET("stats.allocated", &allocated, size_t); + CTL_GET("stats.active", &active, size_t); + CTL_GET("stats.metadata", &metadata, size_t); + CTL_GET("stats.resident", &resident, size_t); + CTL_GET("stats.mapped", &mapped, size_t); + CTL_GET("stats.retained", &retained, size_t); + + uint64_t mutex_stats[mutex_prof_num_global_mutexes][mutex_prof_num_counters]; + if (mutex) { + read_global_mutex_stats(mutex_stats); + } + + if (have_background_thread) { + CTL_GET("stats.background_thread.num_threads", + &num_background_threads, size_t); + CTL_GET("stats.background_thread.num_runs", + &background_thread_num_runs, uint64_t); + CTL_GET("stats.background_thread.run_interval", + &background_thread_run_interval, uint64_t); + } else { + num_background_threads = 0; + background_thread_num_runs = 0; + background_thread_run_interval = 0; + } + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"stats\": {\n"); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"allocated\": %zu,\n", allocated); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"active\": %zu,\n", active); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"metadata\": %zu,\n", metadata); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"resident\": %zu,\n", resident); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"mapped\": %zu,\n", mapped); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"retained\": %zu,\n", retained); + + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"background_thread\": {\n"); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"num_threads\": %zu,\n", num_background_threads); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"num_runs\": %"FMTu64",\n", + background_thread_num_runs); + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\t\"run_interval\": %"FMTu64"\n", + background_thread_run_interval); + malloc_cprintf(write_cb, cbopaque, "\t\t\t}%s\n", + mutex ? "," : ""); + + if (mutex) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"mutexes\": {\n"); + mutex_prof_global_ind_t i; + for (i = 0; i < mutex_prof_num_global_mutexes; i++) { + mutex_stats_output_json(write_cb, cbopaque, + global_mutex_names[i], mutex_stats[i], + "\t\t\t\t", + i == mutex_prof_num_global_mutexes - 1); + } + malloc_cprintf(write_cb, cbopaque, "\t\t\t}\n"); + } + malloc_cprintf(write_cb, cbopaque, + "\t\t}%s\n", (merged || unmerged || destroyed) ? "," : ""); + } else { + malloc_cprintf(write_cb, cbopaque, + "Allocated: %zu, active: %zu, metadata: %zu," + " resident: %zu, mapped: %zu, retained: %zu\n", + allocated, active, metadata, resident, mapped, retained); + + if (have_background_thread && num_background_threads > 0) { + malloc_cprintf(write_cb, cbopaque, + "Background threads: %zu, num_runs: %"FMTu64", " + "run_interval: %"FMTu64" ns\n", + num_background_threads, + background_thread_num_runs, + background_thread_run_interval); + } + if (mutex) { + mutex_prof_global_ind_t i; + for (i = 0; i < mutex_prof_num_global_mutexes; i++) { + mutex_stats_output(write_cb, cbopaque, + global_mutex_names[i], mutex_stats[i], + i == 0); } } - CTL_GET("opt.lg_chunk", &sv, size_t); - malloc_cprintf(write_cb, cbopaque, "Chunk size: %zu (2^%zu)\n", - (ZU(1) << sv), sv); } - if (config_stats) { - size_t *cactive; - size_t allocated, active, mapped; - size_t chunks_current, chunks_high; - uint64_t chunks_total; - size_t huge_allocated; - uint64_t huge_nmalloc, huge_ndalloc; - - CTL_GET("stats.cactive", &cactive, size_t *); - CTL_GET("stats.allocated", &allocated, size_t); - CTL_GET("stats.active", &active, size_t); - CTL_GET("stats.mapped", &mapped, size_t); - malloc_cprintf(write_cb, cbopaque, - "Allocated: %zu, active: %zu, mapped: %zu\n", - allocated, active, mapped); - malloc_cprintf(write_cb, cbopaque, - "Current active ceiling: %zu\n", atomic_read_z(cactive)); - - /* Print chunk stats. */ - CTL_GET("stats.chunks.total", &chunks_total, uint64_t); - CTL_GET("stats.chunks.high", &chunks_high, size_t); - CTL_GET("stats.chunks.current", &chunks_current, size_t); - malloc_cprintf(write_cb, cbopaque, "chunks: nchunks " - "highchunks curchunks\n"); - malloc_cprintf(write_cb, cbopaque, - " %13"PRIu64" %12zu %12zu\n", - chunks_total, chunks_high, chunks_current); - - /* Print huge stats. */ - CTL_GET("stats.huge.nmalloc", &huge_nmalloc, uint64_t); - CTL_GET("stats.huge.ndalloc", &huge_ndalloc, uint64_t); - CTL_GET("stats.huge.allocated", &huge_allocated, size_t); - malloc_cprintf(write_cb, cbopaque, - "huge: nmalloc ndalloc allocated\n"); - malloc_cprintf(write_cb, cbopaque, - " %12"PRIu64" %12"PRIu64" %12zu\n", - huge_nmalloc, huge_ndalloc, huge_allocated); - - if (merged) { - unsigned narenas; - - CTL_GET("arenas.narenas", &narenas, unsigned); - { - VARIABLE_ARRAY(bool, initialized, narenas); - size_t isz; - unsigned i, ninitialized; - - isz = sizeof(bool) * narenas; - xmallctl("arenas.initialized", initialized, - &isz, NULL, 0); - for (i = ninitialized = 0; i < narenas; i++) { - if (initialized[i]) - ninitialized++; + if (merged || destroyed || unmerged) { + unsigned narenas; + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\"stats.arenas\": {\n"); + } + + CTL_GET("arenas.narenas", &narenas, unsigned); + { + size_t mib[3]; + size_t miblen = sizeof(mib) / sizeof(size_t); + size_t sz; + VARIABLE_ARRAY(bool, initialized, narenas); + bool destroyed_initialized; + unsigned i, j, ninitialized; + + xmallctlnametomib("arena.0.initialized", mib, &miblen); + for (i = ninitialized = 0; i < narenas; i++) { + mib[1] = i; + sz = sizeof(bool); + xmallctlbymib(mib, miblen, &initialized[i], &sz, + NULL, 0); + if (initialized[i]) { + ninitialized++; } + } + mib[1] = MALLCTL_ARENAS_DESTROYED; + sz = sizeof(bool); + xmallctlbymib(mib, miblen, &destroyed_initialized, &sz, + NULL, 0); - if (ninitialized > 1 || unmerged == false) { - /* Print merged arena stats. */ + /* Merged stats. */ + if (merged && (ninitialized > 1 || !unmerged)) { + /* Print merged arena stats. */ + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"merged\": {\n"); + } else { malloc_cprintf(write_cb, cbopaque, "\nMerged arenas stats:\n"); - stats_arena_print(write_cb, cbopaque, - narenas, bins, large); + } + stats_arena_print(write_cb, cbopaque, json, + MALLCTL_ARENAS_ALL, bins, large, mutex); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t}%s\n", + ((destroyed_initialized && + destroyed) || unmerged) ? "," : + ""); } } - } - - if (unmerged) { - unsigned narenas; - /* Print stats for each arena. */ - - CTL_GET("arenas.narenas", &narenas, unsigned); - { - VARIABLE_ARRAY(bool, initialized, narenas); - size_t isz; - unsigned i; - - isz = sizeof(bool) * narenas; - xmallctl("arenas.initialized", initialized, - &isz, NULL, 0); + /* Destroyed stats. */ + if (destroyed_initialized && destroyed) { + /* Print destroyed arena stats. */ + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t\"destroyed\": {\n"); + } else { + malloc_cprintf(write_cb, cbopaque, + "\nDestroyed arenas stats:\n"); + } + stats_arena_print(write_cb, cbopaque, json, + MALLCTL_ARENAS_DESTROYED, bins, large, + mutex); + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t\t}%s\n", unmerged ? "," : + ""); + } + } - for (i = 0; i < narenas; i++) { + /* Unmerged stats. */ + if (unmerged) { + for (i = j = 0; i < narenas; i++) { if (initialized[i]) { - malloc_cprintf(write_cb, - cbopaque, - "\narenas[%u]:\n", i); + if (json) { + j++; + malloc_cprintf(write_cb, + cbopaque, + "\t\t\t\"%u\": {\n", + i); + } else { + malloc_cprintf(write_cb, + cbopaque, + "\narenas[%u]:\n", + i); + } stats_arena_print(write_cb, - cbopaque, i, bins, large); + cbopaque, json, i, bins, + large, mutex); + if (json) { + malloc_cprintf(write_cb, + cbopaque, + "\t\t\t}%s\n", (j < + ninitialized) ? "," + : ""); + } } } } } + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t\t}\n"); + } + } +} + +void +stats_print(void (*write_cb)(void *, const char *), void *cbopaque, + const char *opts) { + int err; + uint64_t epoch; + size_t u64sz; +#define OPTION(o, v, d, s) bool v = d; + STATS_PRINT_OPTIONS +#undef OPTION + + /* + * Refresh stats, in case mallctl() was called by the application. + * + * Check for OOM here, since refreshing the ctl cache can trigger + * allocation. In practice, none of the subsequent mallctl()-related + * calls in this function will cause OOM if this one succeeds. + * */ + epoch = 1; + u64sz = sizeof(uint64_t); + err = je_mallctl("epoch", (void *)&epoch, &u64sz, (void *)&epoch, + sizeof(uint64_t)); + if (err != 0) { + if (err == EAGAIN) { + malloc_write("<jemalloc>: Memory allocation failure in " + "mallctl(\"epoch\", ...)\n"); + return; + } + malloc_write("<jemalloc>: Failure in mallctl(\"epoch\", " + "...)\n"); + abort(); + } + + if (opts != NULL) { + for (unsigned i = 0; opts[i] != '\0'; i++) { + switch (opts[i]) { +#define OPTION(o, v, d, s) case o: v = s; break; + STATS_PRINT_OPTIONS +#undef OPTION + default:; + } + } + } + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "{\n" + "\t\"jemalloc\": {\n"); + } else { + malloc_cprintf(write_cb, cbopaque, + "___ Begin jemalloc statistics ___\n"); + } + + if (general) { + stats_general_print(write_cb, cbopaque, json, config_stats); + } + if (config_stats) { + stats_print_helper(write_cb, cbopaque, json, merged, destroyed, + unmerged, bins, large, mutex); + } + + if (json) { + malloc_cprintf(write_cb, cbopaque, + "\t}\n" + "}\n"); + } else { + malloc_cprintf(write_cb, cbopaque, + "--- End jemalloc statistics ---\n"); } - malloc_cprintf(write_cb, cbopaque, "--- End jemalloc statistics ---\n"); } diff --git a/deps/jemalloc/src/tcache.c b/deps/jemalloc/src/tcache.c index 6de92960b2..936ef3140d 100644 --- a/deps/jemalloc/src/tcache.c +++ b/deps/jemalloc/src/tcache.c @@ -1,131 +1,153 @@ -#define JEMALLOC_TCACHE_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_TCACHE_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/size_classes.h" /******************************************************************************/ /* Data. */ -malloc_tsd_data(, tcache, tcache_t *, NULL) -malloc_tsd_data(, tcache_enabled, tcache_enabled_t, tcache_enabled_default) - bool opt_tcache = true; ssize_t opt_lg_tcache_max = LG_TCACHE_MAXCLASS_DEFAULT; tcache_bin_info_t *tcache_bin_info; static unsigned stack_nelms; /* Total stack elms per tcache. */ -size_t nhbins; +unsigned nhbins; size_t tcache_maxclass; -/******************************************************************************/ +tcaches_t *tcaches; + +/* Index of first element within tcaches that has never been used. */ +static unsigned tcaches_past; + +/* Head of singly linked list tracking available tcaches elements. */ +static tcaches_t *tcaches_avail; -size_t tcache_salloc(const void *ptr) -{ +/* Protects tcaches{,_past,_avail}. */ +static malloc_mutex_t tcaches_mtx; - return (arena_salloc(ptr, false)); +/******************************************************************************/ + +size_t +tcache_salloc(tsdn_t *tsdn, const void *ptr) { + return arena_salloc(tsdn, ptr); } void -tcache_event_hard(tcache_t *tcache) -{ - size_t binind = tcache->next_gc_bin; - tcache_bin_t *tbin = &tcache->tbins[binind]; - tcache_bin_info_t *tbin_info = &tcache_bin_info[binind]; - +tcache_event_hard(tsd_t *tsd, tcache_t *tcache) { + szind_t binind = tcache->next_gc_bin; + + tcache_bin_t *tbin; + if (binind < NBINS) { + tbin = tcache_small_bin_get(tcache, binind); + } else { + tbin = tcache_large_bin_get(tcache, binind); + } if (tbin->low_water > 0) { /* * Flush (ceiling) 3/4 of the objects below the low water mark. */ if (binind < NBINS) { - tcache_bin_flush_small(tbin, binind, tbin->ncached - - tbin->low_water + (tbin->low_water >> 2), tcache); + tcache_bin_flush_small(tsd, tcache, tbin, binind, + tbin->ncached - tbin->low_water + (tbin->low_water + >> 2)); + /* + * Reduce fill count by 2X. Limit lg_fill_div such that + * the fill count is always at least 1. + */ + tcache_bin_info_t *tbin_info = &tcache_bin_info[binind]; + if ((tbin_info->ncached_max >> + (tcache->lg_fill_div[binind] + 1)) >= 1) { + tcache->lg_fill_div[binind]++; + } } else { - tcache_bin_flush_large(tbin, binind, tbin->ncached - - tbin->low_water + (tbin->low_water >> 2), tcache); + tcache_bin_flush_large(tsd, tbin, binind, tbin->ncached + - tbin->low_water + (tbin->low_water >> 2), tcache); } - /* - * Reduce fill count by 2X. Limit lg_fill_div such that the - * fill count is always at least 1. - */ - if ((tbin_info->ncached_max >> (tbin->lg_fill_div+1)) >= 1) - tbin->lg_fill_div++; } else if (tbin->low_water < 0) { /* - * Increase fill count by 2X. Make sure lg_fill_div stays - * greater than 0. + * Increase fill count by 2X for small bins. Make sure + * lg_fill_div stays greater than 0. */ - if (tbin->lg_fill_div > 1) - tbin->lg_fill_div--; + if (binind < NBINS && tcache->lg_fill_div[binind] > 1) { + tcache->lg_fill_div[binind]--; + } } tbin->low_water = tbin->ncached; tcache->next_gc_bin++; - if (tcache->next_gc_bin == nhbins) + if (tcache->next_gc_bin == nhbins) { tcache->next_gc_bin = 0; - tcache->ev_cnt = 0; + } } void * -tcache_alloc_small_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind) -{ +tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, + tcache_bin_t *tbin, szind_t binind, bool *tcache_success) { void *ret; - arena_tcache_fill_small(tcache->arena, tbin, binind, + assert(tcache->arena != NULL); + arena_tcache_fill_small(tsdn, arena, tcache, tbin, binind, config_prof ? tcache->prof_accumbytes : 0); - if (config_prof) + if (config_prof) { tcache->prof_accumbytes = 0; - ret = tcache_alloc_easy(tbin); + } + ret = tcache_alloc_easy(tbin, tcache_success); - return (ret); + return ret; } void -tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem, - tcache_t *tcache) -{ - void *ptr; - unsigned i, nflush, ndeferred; +tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, + szind_t binind, unsigned rem) { bool merged_stats = false; assert(binind < NBINS); assert(rem <= tbin->ncached); - for (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) { - /* Lock the arena bin associated with the first object. */ - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE( - tbin->avail[0]); - arena_t *arena = chunk->arena; - arena_bin_t *bin = &arena->bins[binind]; + arena_t *arena = tcache->arena; + assert(arena != NULL); + unsigned nflush = tbin->ncached - rem; + VARIABLE_ARRAY(extent_t *, item_extent, nflush); + /* Look up extent once per item. */ + for (unsigned i = 0 ; i < nflush; i++) { + item_extent[i] = iealloc(tsd_tsdn(tsd), *(tbin->avail - 1 - i)); + } - if (config_prof && arena == tcache->arena) { - if (arena_prof_accum(arena, tcache->prof_accumbytes)) - prof_idump(); + while (nflush > 0) { + /* Lock the arena bin associated with the first object. */ + extent_t *extent = item_extent[0]; + arena_t *bin_arena = extent_arena_get(extent); + arena_bin_t *bin = &bin_arena->bins[binind]; + + if (config_prof && bin_arena == arena) { + if (arena_prof_accum(tsd_tsdn(tsd), arena, + tcache->prof_accumbytes)) { + prof_idump(tsd_tsdn(tsd)); + } tcache->prof_accumbytes = 0; } - malloc_mutex_lock(&bin->lock); - if (config_stats && arena == tcache->arena) { - assert(merged_stats == false); + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); + if (config_stats && bin_arena == arena) { + assert(!merged_stats); merged_stats = true; bin->stats.nflushes++; bin->stats.nrequests += tbin->tstats.nrequests; tbin->tstats.nrequests = 0; } - ndeferred = 0; - for (i = 0; i < nflush; i++) { - ptr = tbin->avail[i]; - assert(ptr != NULL); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk->arena == arena) { - size_t pageind = ((uintptr_t)ptr - - (uintptr_t)chunk) >> LG_PAGE; - arena_chunk_map_t *mapelm = - arena_mapp_get(chunk, pageind); - if (config_fill && opt_junk) { - arena_alloc_junk_small(ptr, - &arena_bin_info[binind], true); - } - arena_dalloc_bin_locked(arena, chunk, ptr, - mapelm); + unsigned ndeferred = 0; + for (unsigned i = 0; i < nflush; i++) { + void *ptr = *(tbin->avail - 1 - i); + extent = item_extent[i]; + assert(ptr != NULL && extent != NULL); + + if (extent_arena_get(extent) == bin_arena) { + arena_dalloc_bin_junked_locked(tsd_tsdn(tsd), + bin_arena, extent, ptr); } else { /* * This object was allocated via a different @@ -133,276 +155,369 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem, * locked. Stash the object, so that it can be * handled in a future pass. */ - tbin->avail[ndeferred] = ptr; + *(tbin->avail - 1 - ndeferred) = ptr; + item_extent[ndeferred] = extent; ndeferred++; } } - malloc_mutex_unlock(&bin->lock); + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); + arena_decay_ticks(tsd_tsdn(tsd), bin_arena, nflush - ndeferred); + nflush = ndeferred; } - if (config_stats && merged_stats == false) { + if (config_stats && !merged_stats) { /* * The flush loop didn't happen to flush to this thread's * arena, so the stats didn't get merged. Manually do so now. */ - arena_bin_t *bin = &tcache->arena->bins[binind]; - malloc_mutex_lock(&bin->lock); + arena_bin_t *bin = &arena->bins[binind]; + malloc_mutex_lock(tsd_tsdn(tsd), &bin->lock); bin->stats.nflushes++; bin->stats.nrequests += tbin->tstats.nrequests; tbin->tstats.nrequests = 0; - malloc_mutex_unlock(&bin->lock); + malloc_mutex_unlock(tsd_tsdn(tsd), &bin->lock); } - memmove(tbin->avail, &tbin->avail[tbin->ncached - rem], - rem * sizeof(void *)); + memmove(tbin->avail - rem, tbin->avail - tbin->ncached, rem * + sizeof(void *)); tbin->ncached = rem; - if ((int)tbin->ncached < tbin->low_water) + if ((low_water_t)tbin->ncached < tbin->low_water) { tbin->low_water = tbin->ncached; + } } void -tcache_bin_flush_large(tcache_bin_t *tbin, size_t binind, unsigned rem, - tcache_t *tcache) -{ - void *ptr; - unsigned i, nflush, ndeferred; +tcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind, + unsigned rem, tcache_t *tcache) { bool merged_stats = false; assert(binind < nhbins); assert(rem <= tbin->ncached); - for (nflush = tbin->ncached - rem; nflush > 0; nflush = ndeferred) { + arena_t *arena = tcache->arena; + assert(arena != NULL); + unsigned nflush = tbin->ncached - rem; + VARIABLE_ARRAY(extent_t *, item_extent, nflush); + /* Look up extent once per item. */ + for (unsigned i = 0 ; i < nflush; i++) { + item_extent[i] = iealloc(tsd_tsdn(tsd), *(tbin->avail - 1 - i)); + } + + while (nflush > 0) { /* Lock the arena associated with the first object. */ - arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE( - tbin->avail[0]); - arena_t *arena = chunk->arena; + extent_t *extent = item_extent[0]; + arena_t *locked_arena = extent_arena_get(extent); UNUSED bool idump; - if (config_prof) + if (config_prof) { idump = false; - malloc_mutex_lock(&arena->lock); - if ((config_prof || config_stats) && arena == tcache->arena) { + } + + malloc_mutex_lock(tsd_tsdn(tsd), &locked_arena->large_mtx); + for (unsigned i = 0; i < nflush; i++) { + void *ptr = *(tbin->avail - 1 - i); + assert(ptr != NULL); + extent = item_extent[i]; + if (extent_arena_get(extent) == locked_arena) { + large_dalloc_prep_junked_locked(tsd_tsdn(tsd), + extent); + } + } + if ((config_prof || config_stats) && locked_arena == arena) { if (config_prof) { - idump = arena_prof_accum_locked(arena, + idump = arena_prof_accum(tsd_tsdn(tsd), arena, tcache->prof_accumbytes); tcache->prof_accumbytes = 0; } if (config_stats) { merged_stats = true; - arena->stats.nrequests_large += - tbin->tstats.nrequests; - arena->stats.lstats[binind - NBINS].nrequests += - tbin->tstats.nrequests; + arena_stats_large_nrequests_add(tsd_tsdn(tsd), + &arena->stats, binind, + tbin->tstats.nrequests); tbin->tstats.nrequests = 0; } } - ndeferred = 0; - for (i = 0; i < nflush; i++) { - ptr = tbin->avail[i]; - assert(ptr != NULL); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk->arena == arena) - arena_dalloc_large_locked(arena, chunk, ptr); - else { + malloc_mutex_unlock(tsd_tsdn(tsd), &locked_arena->large_mtx); + + unsigned ndeferred = 0; + for (unsigned i = 0; i < nflush; i++) { + void *ptr = *(tbin->avail - 1 - i); + extent = item_extent[i]; + assert(ptr != NULL && extent != NULL); + + if (extent_arena_get(extent) == locked_arena) { + large_dalloc_finish(tsd_tsdn(tsd), extent); + } else { /* * This object was allocated via a different * arena than the one that is currently locked. * Stash the object, so that it can be handled * in a future pass. */ - tbin->avail[ndeferred] = ptr; + *(tbin->avail - 1 - ndeferred) = ptr; + item_extent[ndeferred] = extent; ndeferred++; } } - malloc_mutex_unlock(&arena->lock); - if (config_prof && idump) - prof_idump(); + if (config_prof && idump) { + prof_idump(tsd_tsdn(tsd)); + } + arena_decay_ticks(tsd_tsdn(tsd), locked_arena, nflush - + ndeferred); + nflush = ndeferred; } - if (config_stats && merged_stats == false) { + if (config_stats && !merged_stats) { /* * The flush loop didn't happen to flush to this thread's * arena, so the stats didn't get merged. Manually do so now. */ - arena_t *arena = tcache->arena; - malloc_mutex_lock(&arena->lock); - arena->stats.nrequests_large += tbin->tstats.nrequests; - arena->stats.lstats[binind - NBINS].nrequests += - tbin->tstats.nrequests; + arena_stats_large_nrequests_add(tsd_tsdn(tsd), &arena->stats, + binind, tbin->tstats.nrequests); tbin->tstats.nrequests = 0; - malloc_mutex_unlock(&arena->lock); } - memmove(tbin->avail, &tbin->avail[tbin->ncached - rem], - rem * sizeof(void *)); + memmove(tbin->avail - rem, tbin->avail - tbin->ncached, rem * + sizeof(void *)); tbin->ncached = rem; - if ((int)tbin->ncached < tbin->low_water) + if ((low_water_t)tbin->ncached < tbin->low_water) { tbin->low_water = tbin->ncached; + } } void -tcache_arena_associate(tcache_t *tcache, arena_t *arena) -{ +tcache_arena_associate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena) { + assert(tcache->arena == NULL); + tcache->arena = arena; if (config_stats) { /* Link into list of extant tcaches. */ - malloc_mutex_lock(&arena->lock); + malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); ql_elm_new(tcache, link); ql_tail_insert(&arena->tcache_ql, tcache, link); - malloc_mutex_unlock(&arena->lock); + malloc_mutex_unlock(tsdn, &arena->tcache_ql_mtx); } - tcache->arena = arena; } -void -tcache_arena_dissociate(tcache_t *tcache) -{ - +static void +tcache_arena_dissociate(tsdn_t *tsdn, tcache_t *tcache) { + arena_t *arena = tcache->arena; + assert(arena != NULL); if (config_stats) { /* Unlink from list of extant tcaches. */ - malloc_mutex_lock(&tcache->arena->lock); - ql_remove(&tcache->arena->tcache_ql, tcache, link); - tcache_stats_merge(tcache, tcache->arena); - malloc_mutex_unlock(&tcache->arena->lock); + malloc_mutex_lock(tsdn, &arena->tcache_ql_mtx); + if (config_debug) { + bool in_ql = false; + tcache_t *iter; + ql_foreach(iter, &arena->tcache_ql, link) { + if (iter == tcache) { + in_ql = true; + break; + } + } + assert(in_ql); + } + ql_remove(&arena->tcache_ql, tcache, link); + tcache_stats_merge(tsdn, tcache, arena); + malloc_mutex_unlock(tsdn, &arena->tcache_ql_mtx); } + tcache->arena = NULL; } +void +tcache_arena_reassociate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena) { + tcache_arena_dissociate(tsdn, tcache); + tcache_arena_associate(tsdn, tcache, arena); +} + +bool +tsd_tcache_enabled_data_init(tsd_t *tsd) { + /* Called upon tsd initialization. */ + tsd_tcache_enabled_set(tsd, opt_tcache); + tsd_slow_update(tsd); + + if (opt_tcache) { + /* Trigger tcache init. */ + tsd_tcache_data_init(tsd); + } + + return false; +} + +/* Initialize auto tcache (embedded in TSD). */ +static void +tcache_init(tsd_t *tsd, tcache_t *tcache, void *avail_stack) { + memset(&tcache->link, 0, sizeof(ql_elm(tcache_t))); + tcache->prof_accumbytes = 0; + tcache->next_gc_bin = 0; + tcache->arena = NULL; + + ticker_init(&tcache->gc_ticker, TCACHE_GC_INCR); + + size_t stack_offset = 0; + assert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0); + memset(tcache->tbins_small, 0, sizeof(tcache_bin_t) * NBINS); + memset(tcache->tbins_large, 0, sizeof(tcache_bin_t) * (nhbins - NBINS)); + unsigned i = 0; + for (; i < NBINS; i++) { + tcache->lg_fill_div[i] = 1; + stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *); + /* + * avail points past the available space. Allocations will + * access the slots toward higher addresses (for the benefit of + * prefetch). + */ + tcache_small_bin_get(tcache, i)->avail = + (void **)((uintptr_t)avail_stack + (uintptr_t)stack_offset); + } + for (; i < nhbins; i++) { + stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *); + tcache_large_bin_get(tcache, i)->avail = + (void **)((uintptr_t)avail_stack + (uintptr_t)stack_offset); + } + assert(stack_offset == stack_nelms * sizeof(void *)); +} + +/* Initialize auto tcache (embedded in TSD). */ +bool +tsd_tcache_data_init(tsd_t *tsd) { + tcache_t *tcache = tsd_tcachep_get_unsafe(tsd); + assert(tcache_small_bin_get(tcache, 0)->avail == NULL); + size_t size = stack_nelms * sizeof(void *); + /* Avoid false cacheline sharing. */ + size = sz_sa2u(size, CACHELINE); + + void *avail_array = ipallocztm(tsd_tsdn(tsd), size, CACHELINE, true, + NULL, true, arena_get(TSDN_NULL, 0, true)); + if (avail_array == NULL) { + return true; + } + + tcache_init(tsd, tcache, avail_array); + /* + * Initialization is a bit tricky here. After malloc init is done, all + * threads can rely on arena_choose and associate tcache accordingly. + * However, the thread that does actual malloc bootstrapping relies on + * functional tsd, and it can only rely on a0. In that case, we + * associate its tcache to a0 temporarily, and later on + * arena_choose_hard() will re-associate properly. + */ + tcache->arena = NULL; + arena_t *arena; + if (!malloc_initialized()) { + /* If in initialization, assign to a0. */ + arena = arena_get(tsd_tsdn(tsd), 0, false); + tcache_arena_associate(tsd_tsdn(tsd), tcache, arena); + } else { + arena = arena_choose(tsd, NULL); + /* This may happen if thread.tcache.enabled is used. */ + if (tcache->arena == NULL) { + tcache_arena_associate(tsd_tsdn(tsd), tcache, arena); + } + } + assert(arena == tcache->arena); + + return false; +} + +/* Created manual tcache for tcache.create mallctl. */ tcache_t * -tcache_create(arena_t *arena) -{ +tcache_create_explicit(tsd_t *tsd) { tcache_t *tcache; size_t size, stack_offset; - unsigned i; - size = offsetof(tcache_t, tbins) + (sizeof(tcache_bin_t) * nhbins); + size = sizeof(tcache_t); /* Naturally align the pointer stacks. */ size = PTR_CEILING(size); stack_offset = size; size += stack_nelms * sizeof(void *); - /* - * Round up to the nearest multiple of the cacheline size, in order to - * avoid the possibility of false cacheline sharing. - * - * That this works relies on the same logic as in ipalloc(), but we - * cannot directly call ipalloc() here due to tcache bootstrapping - * issues. - */ - size = (size + CACHELINE_MASK) & (-CACHELINE); - - if (size <= SMALL_MAXCLASS) - tcache = (tcache_t *)arena_malloc_small(arena, size, true); - else if (size <= tcache_maxclass) - tcache = (tcache_t *)arena_malloc_large(arena, size, true); - else - tcache = (tcache_t *)icalloct(size, false, arena); - - if (tcache == NULL) - return (NULL); - - tcache_arena_associate(tcache, arena); + /* Avoid false cacheline sharing. */ + size = sz_sa2u(size, CACHELINE); - assert((TCACHE_NSLOTS_SMALL_MAX & 1U) == 0); - for (i = 0; i < nhbins; i++) { - tcache->tbins[i].lg_fill_div = 1; - tcache->tbins[i].avail = (void **)((uintptr_t)tcache + - (uintptr_t)stack_offset); - stack_offset += tcache_bin_info[i].ncached_max * sizeof(void *); + tcache = ipallocztm(tsd_tsdn(tsd), size, CACHELINE, true, NULL, true, + arena_get(TSDN_NULL, 0, true)); + if (tcache == NULL) { + return NULL; } - tcache_tsd_set(&tcache); + tcache_init(tsd, tcache, + (void *)((uintptr_t)tcache + (uintptr_t)stack_offset)); + tcache_arena_associate(tsd_tsdn(tsd), tcache, arena_ichoose(tsd, NULL)); - return (tcache); + return tcache; } -void -tcache_destroy(tcache_t *tcache) -{ - unsigned i; - size_t tcache_size; +static void +tcache_flush_cache(tsd_t *tsd, tcache_t *tcache) { + assert(tcache->arena != NULL); - tcache_arena_dissociate(tcache); + for (unsigned i = 0; i < NBINS; i++) { + tcache_bin_t *tbin = tcache_small_bin_get(tcache, i); + tcache_bin_flush_small(tsd, tcache, tbin, i, 0); - for (i = 0; i < NBINS; i++) { - tcache_bin_t *tbin = &tcache->tbins[i]; - tcache_bin_flush_small(tbin, i, 0, tcache); - - if (config_stats && tbin->tstats.nrequests != 0) { - arena_t *arena = tcache->arena; - arena_bin_t *bin = &arena->bins[i]; - malloc_mutex_lock(&bin->lock); - bin->stats.nrequests += tbin->tstats.nrequests; - malloc_mutex_unlock(&bin->lock); + if (config_stats) { + assert(tbin->tstats.nrequests == 0); } } + for (unsigned i = NBINS; i < nhbins; i++) { + tcache_bin_t *tbin = tcache_large_bin_get(tcache, i); + tcache_bin_flush_large(tsd, tbin, i, 0, tcache); - for (; i < nhbins; i++) { - tcache_bin_t *tbin = &tcache->tbins[i]; - tcache_bin_flush_large(tbin, i, 0, tcache); - - if (config_stats && tbin->tstats.nrequests != 0) { - arena_t *arena = tcache->arena; - malloc_mutex_lock(&arena->lock); - arena->stats.nrequests_large += tbin->tstats.nrequests; - arena->stats.lstats[i - NBINS].nrequests += - tbin->tstats.nrequests; - malloc_mutex_unlock(&arena->lock); + if (config_stats) { + assert(tbin->tstats.nrequests == 0); } } if (config_prof && tcache->prof_accumbytes > 0 && - arena_prof_accum(tcache->arena, tcache->prof_accumbytes)) - prof_idump(); - - tcache_size = arena_salloc(tcache, false); - if (tcache_size <= SMALL_MAXCLASS) { - arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache); - arena_t *arena = chunk->arena; - size_t pageind = ((uintptr_t)tcache - (uintptr_t)chunk) >> - LG_PAGE; - arena_chunk_map_t *mapelm = arena_mapp_get(chunk, pageind); - - arena_dalloc_bin(arena, chunk, tcache, pageind, mapelm); - } else if (tcache_size <= tcache_maxclass) { - arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache); - arena_t *arena = chunk->arena; - - arena_dalloc_large(arena, chunk, tcache); - } else - idalloct(tcache, false); + arena_prof_accum(tsd_tsdn(tsd), tcache->arena, + tcache->prof_accumbytes)) { + prof_idump(tsd_tsdn(tsd)); + } } void -tcache_thread_cleanup(void *arg) -{ - tcache_t *tcache = *(tcache_t **)arg; +tcache_flush(tsd_t *tsd) { + assert(tcache_available(tsd)); + tcache_flush_cache(tsd, tsd_tcachep_get(tsd)); +} - if (tcache == TCACHE_STATE_DISABLED) { - /* Do nothing. */ - } else if (tcache == TCACHE_STATE_REINCARNATED) { - /* - * Another destructor called an allocator function after this - * destructor was called. Reset tcache to - * TCACHE_STATE_PURGATORY in order to receive another callback. - */ - tcache = TCACHE_STATE_PURGATORY; - tcache_tsd_set(&tcache); - } else if (tcache == TCACHE_STATE_PURGATORY) { - /* - * The previous time this destructor was called, we set the key - * to TCACHE_STATE_PURGATORY so that other destructors wouldn't - * cause re-creation of the tcache. This time, do nothing, so - * that the destructor will not be called again. - */ - } else if (tcache != NULL) { - assert(tcache != TCACHE_STATE_PURGATORY); - tcache_destroy(tcache); - tcache = TCACHE_STATE_PURGATORY; - tcache_tsd_set(&tcache); +static void +tcache_destroy(tsd_t *tsd, tcache_t *tcache, bool tsd_tcache) { + tcache_flush_cache(tsd, tcache); + tcache_arena_dissociate(tsd_tsdn(tsd), tcache); + + if (tsd_tcache) { + /* Release the avail array for the TSD embedded auto tcache. */ + void *avail_array = + (void *)((uintptr_t)tcache_small_bin_get(tcache, 0)->avail - + (uintptr_t)tcache_bin_info[0].ncached_max * sizeof(void *)); + idalloctm(tsd_tsdn(tsd), avail_array, NULL, NULL, true, true); + } else { + /* Release both the tcache struct and avail array. */ + idalloctm(tsd_tsdn(tsd), tcache, NULL, NULL, true, true); } } -/* Caller must own arena->lock. */ +/* For auto tcache (embedded in TSD) only. */ void -tcache_stats_merge(tcache_t *tcache, arena_t *arena) -{ +tcache_cleanup(tsd_t *tsd) { + tcache_t *tcache = tsd_tcachep_get(tsd); + if (!tcache_available(tsd)) { + assert(tsd_tcache_enabled_get(tsd) == false); + if (config_debug) { + assert(tcache_small_bin_get(tcache, 0)->avail == NULL); + } + return; + } + assert(tsd_tcache_enabled_get(tsd)); + assert(tcache_small_bin_get(tcache, 0)->avail != NULL); + + tcache_destroy(tsd, tcache, true); + if (config_debug) { + tcache_small_bin_get(tcache, 0)->avail = NULL; + } +} + +void +tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena) { unsigned i; cassert(config_stats); @@ -410,48 +525,151 @@ tcache_stats_merge(tcache_t *tcache, arena_t *arena) /* Merge and reset tcache stats. */ for (i = 0; i < NBINS; i++) { arena_bin_t *bin = &arena->bins[i]; - tcache_bin_t *tbin = &tcache->tbins[i]; - malloc_mutex_lock(&bin->lock); + tcache_bin_t *tbin = tcache_small_bin_get(tcache, i); + malloc_mutex_lock(tsdn, &bin->lock); bin->stats.nrequests += tbin->tstats.nrequests; - malloc_mutex_unlock(&bin->lock); + malloc_mutex_unlock(tsdn, &bin->lock); tbin->tstats.nrequests = 0; } for (; i < nhbins; i++) { - malloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS]; - tcache_bin_t *tbin = &tcache->tbins[i]; - arena->stats.nrequests_large += tbin->tstats.nrequests; - lstats->nrequests += tbin->tstats.nrequests; + tcache_bin_t *tbin = tcache_large_bin_get(tcache, i); + arena_stats_large_nrequests_add(tsdn, &arena->stats, i, + tbin->tstats.nrequests); tbin->tstats.nrequests = 0; } } +static bool +tcaches_create_prep(tsd_t *tsd) { + bool err; + + malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); + + if (tcaches == NULL) { + tcaches = base_alloc(tsd_tsdn(tsd), b0get(), sizeof(tcache_t *) + * (MALLOCX_TCACHE_MAX+1), CACHELINE); + if (tcaches == NULL) { + err = true; + goto label_return; + } + } + + if (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX) { + err = true; + goto label_return; + } + + err = false; +label_return: + malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); + return err; +} + bool -tcache_boot0(void) -{ - unsigned i; +tcaches_create(tsd_t *tsd, unsigned *r_ind) { + witness_assert_depth(tsdn_witness_tsdp_get(tsd_tsdn(tsd)), 0); - /* - * If necessary, clamp opt_lg_tcache_max, now that arena_maxclass is - * known. - */ - if (opt_lg_tcache_max < 0 || (1U << opt_lg_tcache_max) < SMALL_MAXCLASS) + bool err; + + if (tcaches_create_prep(tsd)) { + err = true; + goto label_return; + } + + tcache_t *tcache = tcache_create_explicit(tsd); + if (tcache == NULL) { + err = true; + goto label_return; + } + + tcaches_t *elm; + malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); + if (tcaches_avail != NULL) { + elm = tcaches_avail; + tcaches_avail = tcaches_avail->next; + elm->tcache = tcache; + *r_ind = (unsigned)(elm - tcaches); + } else { + elm = &tcaches[tcaches_past]; + elm->tcache = tcache; + *r_ind = tcaches_past; + tcaches_past++; + } + malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); + + err = false; +label_return: + witness_assert_depth(tsdn_witness_tsdp_get(tsd_tsdn(tsd)), 0); + return err; +} + +static tcache_t * +tcaches_elm_remove(tsd_t *tsd, tcaches_t *elm) { + malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx); + + if (elm->tcache == NULL) { + return NULL; + } + tcache_t *tcache = elm->tcache; + elm->tcache = NULL; + return tcache; +} + +void +tcaches_flush(tsd_t *tsd, unsigned ind) { + malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); + tcache_t *tcache = tcaches_elm_remove(tsd, &tcaches[ind]); + malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); + if (tcache != NULL) { + tcache_destroy(tsd, tcache, false); + } +} + +void +tcaches_destroy(tsd_t *tsd, unsigned ind) { + malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx); + tcaches_t *elm = &tcaches[ind]; + tcache_t *tcache = tcaches_elm_remove(tsd, elm); + elm->next = tcaches_avail; + tcaches_avail = elm; + malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx); + if (tcache != NULL) { + tcache_destroy(tsd, tcache, false); + } +} + +bool +tcache_boot(tsdn_t *tsdn) { + /* If necessary, clamp opt_lg_tcache_max. */ + if (opt_lg_tcache_max < 0 || (ZU(1) << opt_lg_tcache_max) < + SMALL_MAXCLASS) { tcache_maxclass = SMALL_MAXCLASS; - else if ((1U << opt_lg_tcache_max) > arena_maxclass) - tcache_maxclass = arena_maxclass; - else - tcache_maxclass = (1U << opt_lg_tcache_max); + } else { + tcache_maxclass = (ZU(1) << opt_lg_tcache_max); + } - nhbins = NBINS + (tcache_maxclass >> LG_PAGE); + if (malloc_mutex_init(&tcaches_mtx, "tcaches", WITNESS_RANK_TCACHES, + malloc_mutex_rank_exclusive)) { + return true; + } + + nhbins = sz_size2index(tcache_maxclass) + 1; /* Initialize tcache_bin_info. */ - tcache_bin_info = (tcache_bin_info_t *)base_alloc(nhbins * - sizeof(tcache_bin_info_t)); - if (tcache_bin_info == NULL) - return (true); + tcache_bin_info = (tcache_bin_info_t *)base_alloc(tsdn, b0get(), nhbins + * sizeof(tcache_bin_info_t), CACHELINE); + if (tcache_bin_info == NULL) { + return true; + } stack_nelms = 0; + unsigned i; for (i = 0; i < NBINS; i++) { - if ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MAX) { + if ((arena_bin_info[i].nregs << 1) <= TCACHE_NSLOTS_SMALL_MIN) { + tcache_bin_info[i].ncached_max = + TCACHE_NSLOTS_SMALL_MIN; + } else if ((arena_bin_info[i].nregs << 1) <= + TCACHE_NSLOTS_SMALL_MAX) { tcache_bin_info[i].ncached_max = (arena_bin_info[i].nregs << 1); } else { @@ -465,15 +683,26 @@ tcache_boot0(void) stack_nelms += tcache_bin_info[i].ncached_max; } - return (false); + return false; } -bool -tcache_boot1(void) -{ +void +tcache_prefork(tsdn_t *tsdn) { + if (!config_prof && opt_tcache) { + malloc_mutex_prefork(tsdn, &tcaches_mtx); + } +} - if (tcache_tsd_boot() || tcache_enabled_tsd_boot()) - return (true); +void +tcache_postfork_parent(tsdn_t *tsdn) { + if (!config_prof && opt_tcache) { + malloc_mutex_postfork_parent(tsdn, &tcaches_mtx); + } +} - return (false); +void +tcache_postfork_child(tsdn_t *tsdn) { + if (!config_prof && opt_tcache) { + malloc_mutex_postfork_child(tsdn, &tcaches_mtx); + } } diff --git a/deps/jemalloc/src/tsd.c b/deps/jemalloc/src/tsd.c index 700caabfe4..f968992f2b 100644 --- a/deps/jemalloc/src/tsd.c +++ b/deps/jemalloc/src/tsd.c @@ -1,5 +1,10 @@ -#define JEMALLOC_TSD_C_ -#include "jemalloc/internal/jemalloc_internal.h" +#define JEMALLOC_TSD_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/rtree.h" /******************************************************************************/ /* Data. */ @@ -7,28 +12,148 @@ static unsigned ncleanups; static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX]; +#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP +__thread tsd_t JEMALLOC_TLS_MODEL tsd_tls = TSD_INITIALIZER; +__thread bool JEMALLOC_TLS_MODEL tsd_initialized = false; +bool tsd_booted = false; +#elif (defined(JEMALLOC_TLS)) +__thread tsd_t JEMALLOC_TLS_MODEL tsd_tls = TSD_INITIALIZER; +pthread_key_t tsd_tsd; +bool tsd_booted = false; +#elif (defined(_WIN32)) +DWORD tsd_tsd; +tsd_wrapper_t tsd_boot_wrapper = {false, TSD_INITIALIZER}; +bool tsd_booted = false; +#else + +/* + * This contains a mutex, but it's pretty convenient to allow the mutex code to + * have a dependency on tsd. So we define the struct here, and only refer to it + * by pointer in the header. + */ +struct tsd_init_head_s { + ql_head(tsd_init_block_t) blocks; + malloc_mutex_t lock; +}; + +pthread_key_t tsd_tsd; +tsd_init_head_t tsd_init_head = { + ql_head_initializer(blocks), + MALLOC_MUTEX_INITIALIZER +}; +tsd_wrapper_t tsd_boot_wrapper = { + false, + TSD_INITIALIZER +}; +bool tsd_booted = false; +#endif + + /******************************************************************************/ -void * -malloc_tsd_malloc(size_t size) -{ +void +tsd_slow_update(tsd_t *tsd) { + if (tsd_nominal(tsd)) { + if (malloc_slow || !tsd_tcache_enabled_get(tsd) || + tsd_reentrancy_level_get(tsd) > 0) { + tsd->state = tsd_state_nominal_slow; + } else { + tsd->state = tsd_state_nominal; + } + } +} + +static bool +tsd_data_init(tsd_t *tsd) { + /* + * We initialize the rtree context first (before the tcache), since the + * tcache initialization depends on it. + */ + rtree_ctx_data_init(tsd_rtree_ctxp_get_unsafe(tsd)); - /* Avoid choose_arena() in order to dodge bootstrapping issues. */ - return (arena_malloc(arenas[0], size, false, false)); + return tsd_tcache_enabled_data_init(tsd); } -void -malloc_tsd_dalloc(void *wrapper) -{ +static void +assert_tsd_data_cleanup_done(tsd_t *tsd) { + assert(!tsd_nominal(tsd)); + assert(*tsd_arenap_get_unsafe(tsd) == NULL); + assert(*tsd_iarenap_get_unsafe(tsd) == NULL); + assert(*tsd_arenas_tdata_bypassp_get_unsafe(tsd) == true); + assert(*tsd_arenas_tdatap_get_unsafe(tsd) == NULL); + assert(*tsd_tcache_enabledp_get_unsafe(tsd) == false); + assert(*tsd_prof_tdatap_get_unsafe(tsd) == NULL); +} + +static bool +tsd_data_init_nocleanup(tsd_t *tsd) { + assert(tsd->state == tsd_state_reincarnated || + tsd->state == tsd_state_minimal_initialized); + /* + * During reincarnation, there is no guarantee that the cleanup function + * will be called (deallocation may happen after all tsd destructors). + * We set up tsd in a way that no cleanup is needed. + */ + rtree_ctx_data_init(tsd_rtree_ctxp_get_unsafe(tsd)); + *tsd_arenas_tdata_bypassp_get(tsd) = true; + *tsd_tcache_enabledp_get_unsafe(tsd) = false; + *tsd_reentrancy_levelp_get(tsd) = 1; + assert_tsd_data_cleanup_done(tsd); - idalloct(wrapper, false); + return false; } -void -malloc_tsd_no_cleanup(void *arg) -{ +tsd_t * +tsd_fetch_slow(tsd_t *tsd, bool minimal) { + assert(!tsd_fast(tsd)); + + if (tsd->state == tsd_state_nominal_slow) { + /* On slow path but no work needed. */ + assert(malloc_slow || !tsd_tcache_enabled_get(tsd) || + tsd_reentrancy_level_get(tsd) > 0 || + *tsd_arenas_tdata_bypassp_get(tsd)); + } else if (tsd->state == tsd_state_uninitialized) { + if (!minimal) { + tsd->state = tsd_state_nominal; + tsd_slow_update(tsd); + /* Trigger cleanup handler registration. */ + tsd_set(tsd); + tsd_data_init(tsd); + } else { + tsd->state = tsd_state_minimal_initialized; + tsd_set(tsd); + tsd_data_init_nocleanup(tsd); + } + } else if (tsd->state == tsd_state_minimal_initialized) { + if (!minimal) { + /* Switch to fully initialized. */ + tsd->state = tsd_state_nominal; + assert(*tsd_reentrancy_levelp_get(tsd) >= 1); + (*tsd_reentrancy_levelp_get(tsd))--; + tsd_slow_update(tsd); + tsd_data_init(tsd); + } else { + assert_tsd_data_cleanup_done(tsd); + } + } else if (tsd->state == tsd_state_purgatory) { + tsd->state = tsd_state_reincarnated; + tsd_set(tsd); + tsd_data_init_nocleanup(tsd); + } else { + assert(tsd->state == tsd_state_reincarnated); + } + + return tsd; +} + +void * +malloc_tsd_malloc(size_t size) { + return a0malloc(CACHELINE_CEILING(size)); +} - not_reached(); +void +malloc_tsd_dalloc(void *wrapper) { + a0dalloc(wrapper); } #if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32) @@ -36,21 +161,22 @@ malloc_tsd_no_cleanup(void *arg) JEMALLOC_EXPORT #endif void -_malloc_thread_cleanup(void) -{ +_malloc_thread_cleanup(void) { bool pending[MALLOC_TSD_CLEANUPS_MAX], again; unsigned i; - for (i = 0; i < ncleanups; i++) + for (i = 0; i < ncleanups; i++) { pending[i] = true; + } do { again = false; for (i = 0; i < ncleanups; i++) { if (pending[i]) { pending[i] = cleanups[i](); - if (pending[i]) + if (pending[i]) { again = true; + } } } } while (again); @@ -58,26 +184,92 @@ _malloc_thread_cleanup(void) #endif void -malloc_tsd_cleanup_register(bool (*f)(void)) -{ - +malloc_tsd_cleanup_register(bool (*f)(void)) { assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX); cleanups[ncleanups] = f; ncleanups++; } +static void +tsd_do_data_cleanup(tsd_t *tsd) { + prof_tdata_cleanup(tsd); + iarena_cleanup(tsd); + arena_cleanup(tsd); + arenas_tdata_cleanup(tsd); + tcache_cleanup(tsd); + witnesses_cleanup(tsd_witness_tsdp_get_unsafe(tsd)); +} + void -malloc_tsd_boot(void) -{ +tsd_cleanup(void *arg) { + tsd_t *tsd = (tsd_t *)arg; + + switch (tsd->state) { + case tsd_state_uninitialized: + /* Do nothing. */ + break; + case tsd_state_minimal_initialized: + /* This implies the thread only did free() in its life time. */ + /* Fall through. */ + case tsd_state_reincarnated: + /* + * Reincarnated means another destructor deallocated memory + * after the destructor was called. Cleanup isn't required but + * is still called for testing and completeness. + */ + assert_tsd_data_cleanup_done(tsd); + /* Fall through. */ + case tsd_state_nominal: + case tsd_state_nominal_slow: + tsd_do_data_cleanup(tsd); + tsd->state = tsd_state_purgatory; + tsd_set(tsd); + break; + case tsd_state_purgatory: + /* + * The previous time this destructor was called, we set the + * state to tsd_state_purgatory so that other destructors + * wouldn't cause re-creation of the tsd. This time, do + * nothing, and do not request another callback. + */ + break; + default: + not_reached(); + } +#ifdef JEMALLOC_JET + test_callback_t test_callback = *tsd_test_callbackp_get_unsafe(tsd); + int *data = tsd_test_datap_get_unsafe(tsd); + if (test_callback != NULL) { + test_callback(data); + } +#endif +} + +tsd_t * +malloc_tsd_boot0(void) { + tsd_t *tsd; ncleanups = 0; + if (tsd_boot0()) { + return NULL; + } + tsd = tsd_fetch(); + *tsd_arenas_tdata_bypassp_get(tsd) = true; + return tsd; +} + +void +malloc_tsd_boot1(void) { + tsd_boot1(); + tsd_t *tsd = tsd_fetch(); + /* malloc_slow has been set properly. Update tsd_slow. */ + tsd_slow_update(tsd); + *tsd_arenas_tdata_bypassp_get(tsd) = false; } #ifdef _WIN32 static BOOL WINAPI -_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - +_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { #ifdef JEMALLOC_LAZY_LOCK case DLL_THREAD_ATTACH: @@ -90,52 +282,60 @@ _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) default: break; } - return (true); + return true; } +/* + * We need to be able to say "read" here (in the "pragma section"), but have + * hooked "read". We won't read for the rest of the file, so we can get away + * with unhooking. + */ +#ifdef read +# undef read +#endif + #ifdef _MSC_VER # ifdef _M_IX86 # pragma comment(linker, "/INCLUDE:__tls_used") +# pragma comment(linker, "/INCLUDE:_tls_callback") # else # pragma comment(linker, "/INCLUDE:_tls_used") +# pragma comment(linker, "/INCLUDE:tls_callback") # endif # pragma section(".CRT$XLY",long,read) #endif JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used) -static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL, +BOOL (WINAPI *const tls_callback)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) = _tls_callback; #endif #if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \ !defined(_WIN32)) void * -tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block) -{ +tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block) { pthread_t self = pthread_self(); tsd_init_block_t *iter; /* Check whether this thread has already inserted into the list. */ - malloc_mutex_lock(&head->lock); + malloc_mutex_lock(TSDN_NULL, &head->lock); ql_foreach(iter, &head->blocks, link) { if (iter->thread == self) { - malloc_mutex_unlock(&head->lock); - return (iter->data); + malloc_mutex_unlock(TSDN_NULL, &head->lock); + return iter->data; } } /* Insert block into list. */ ql_elm_new(block, link); block->thread = self; ql_tail_insert(&head->blocks, block, link); - malloc_mutex_unlock(&head->lock); - return (NULL); + malloc_mutex_unlock(TSDN_NULL, &head->lock); + return NULL; } void -tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block) -{ - - malloc_mutex_lock(&head->lock); +tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block) { + malloc_mutex_lock(TSDN_NULL, &head->lock); ql_remove(&head->blocks, block, link); - malloc_mutex_unlock(&head->lock); + malloc_mutex_unlock(TSDN_NULL, &head->lock); } #endif diff --git a/deps/jemalloc/src/zone.c b/deps/jemalloc/src/zone.c index e0302ef4ed..9d3b7b4952 100644 --- a/deps/jemalloc/src/zone.c +++ b/deps/jemalloc/src/zone.c @@ -1,10 +1,83 @@ -#include "jemalloc/internal/jemalloc_internal.h" +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" + #ifndef JEMALLOC_ZONE # error "This source file is for zones on Darwin (OS X)." #endif +/* Definitions of the following structs in malloc/malloc.h might be too old + * for the built binary to run on newer versions of OSX. So use the newest + * possible version of those structs. + */ +typedef struct _malloc_zone_t { + void *reserved1; + void *reserved2; + size_t (*size)(struct _malloc_zone_t *, const void *); + void *(*malloc)(struct _malloc_zone_t *, size_t); + void *(*calloc)(struct _malloc_zone_t *, size_t, size_t); + void *(*valloc)(struct _malloc_zone_t *, size_t); + void (*free)(struct _malloc_zone_t *, void *); + void *(*realloc)(struct _malloc_zone_t *, void *, size_t); + void (*destroy)(struct _malloc_zone_t *); + const char *zone_name; + unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned); + void (*batch_free)(struct _malloc_zone_t *, void **, unsigned); + struct malloc_introspection_t *introspect; + unsigned version; + void *(*memalign)(struct _malloc_zone_t *, size_t, size_t); + void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t); + size_t (*pressure_relief)(struct _malloc_zone_t *, size_t); +} malloc_zone_t; + +typedef struct { + vm_address_t address; + vm_size_t size; +} vm_range_t; + +typedef struct malloc_statistics_t { + unsigned blocks_in_use; + size_t size_in_use; + size_t max_size_in_use; + size_t size_allocated; +} malloc_statistics_t; + +typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **); + +typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned); + +typedef struct malloc_introspection_t { + kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t); + size_t (*good_size)(malloc_zone_t *, size_t); + boolean_t (*check)(malloc_zone_t *); + void (*print)(malloc_zone_t *, boolean_t); + void (*log)(malloc_zone_t *, void *); + void (*force_lock)(malloc_zone_t *); + void (*force_unlock)(malloc_zone_t *); + void (*statistics)(malloc_zone_t *, malloc_statistics_t *); + boolean_t (*zone_locked)(malloc_zone_t *); + boolean_t (*enable_discharge_checking)(malloc_zone_t *); + boolean_t (*disable_discharge_checking)(malloc_zone_t *); + void (*discharge)(malloc_zone_t *, void *); +#ifdef __BLOCKS__ + void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *)); +#else + void *enumerate_unavailable_without_blocks; +#endif + void (*reinit_lock)(malloc_zone_t *); +} malloc_introspection_t; + +extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *); + +extern malloc_zone_t *malloc_default_zone(void); + +extern void malloc_zone_register(malloc_zone_t *zone); + +extern void malloc_zone_unregister(malloc_zone_t *zone); + /* - * The malloc_default_purgeable_zone function is only available on >= 10.6. + * The malloc_default_purgeable_zone() function is only available on >= 10.6. * We need to check whether it is present at runtime, thus the weak_import. */ extern malloc_zone_t *malloc_default_purgeable_zone(void) @@ -13,30 +86,42 @@ JEMALLOC_ATTR(weak_import); /******************************************************************************/ /* Data. */ -static malloc_zone_t zone; -static struct malloc_introspection_t zone_introspect; +static malloc_zone_t *default_zone, *purgeable_zone; +static malloc_zone_t jemalloc_zone; +static struct malloc_introspection_t jemalloc_zone_introspect; /******************************************************************************/ /* Function prototypes for non-inline static functions. */ -static size_t zone_size(malloc_zone_t *zone, void *ptr); +static size_t zone_size(malloc_zone_t *zone, const void *ptr); static void *zone_malloc(malloc_zone_t *zone, size_t size); static void *zone_calloc(malloc_zone_t *zone, size_t num, size_t size); static void *zone_valloc(malloc_zone_t *zone, size_t size); static void zone_free(malloc_zone_t *zone, void *ptr); static void *zone_realloc(malloc_zone_t *zone, void *ptr, size_t size); -#if (JEMALLOC_ZONE_VERSION >= 5) static void *zone_memalign(malloc_zone_t *zone, size_t alignment, -#endif -#if (JEMALLOC_ZONE_VERSION >= 6) size_t size); static void zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size); -#endif -static void *zone_destroy(malloc_zone_t *zone); +static void zone_destroy(malloc_zone_t *zone); +static unsigned zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, + void **results, unsigned num_requested); +static void zone_batch_free(struct _malloc_zone_t *zone, + void **to_be_freed, unsigned num_to_be_freed); +static size_t zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal); static size_t zone_good_size(malloc_zone_t *zone, size_t size); +static kern_return_t zone_enumerator(task_t task, void *data, unsigned type_mask, + vm_address_t zone_address, memory_reader_t reader, + vm_range_recorder_t recorder); +static boolean_t zone_check(malloc_zone_t *zone); +static void zone_print(malloc_zone_t *zone, boolean_t verbose); +static void zone_log(malloc_zone_t *zone, void *address); static void zone_force_lock(malloc_zone_t *zone); static void zone_force_unlock(malloc_zone_t *zone); +static void zone_statistics(malloc_zone_t *zone, + malloc_statistics_t *stats); +static boolean_t zone_locked(malloc_zone_t *zone); +static void zone_reinit_lock(malloc_zone_t *zone); /******************************************************************************/ /* @@ -44,9 +129,7 @@ static void zone_force_unlock(malloc_zone_t *zone); */ static size_t -zone_size(malloc_zone_t *zone, void *ptr) -{ - +zone_size(malloc_zone_t *zone, const void *ptr) { /* * There appear to be places within Darwin (such as setenv(3)) that * cause calls to this function with pointers that *no* zone owns. If @@ -54,40 +137,33 @@ zone_size(malloc_zone_t *zone, void *ptr) * our zone into two parts, and use one as the default allocator and * the other as the default deallocator/reallocator. Since that will * not work in practice, we must check all pointers to assure that they - * reside within a mapped chunk before determining size. + * reside within a mapped extent before determining size. */ - return (ivsalloc(ptr, config_prof)); + return ivsalloc(tsdn_fetch(), ptr); } static void * -zone_malloc(malloc_zone_t *zone, size_t size) -{ - - return (je_malloc(size)); +zone_malloc(malloc_zone_t *zone, size_t size) { + return je_malloc(size); } static void * -zone_calloc(malloc_zone_t *zone, size_t num, size_t size) -{ - - return (je_calloc(num, size)); +zone_calloc(malloc_zone_t *zone, size_t num, size_t size) { + return je_calloc(num, size); } static void * -zone_valloc(malloc_zone_t *zone, size_t size) -{ +zone_valloc(malloc_zone_t *zone, size_t size) { void *ret = NULL; /* Assignment avoids useless compiler warning. */ je_posix_memalign(&ret, PAGE, size); - return (ret); + return ret; } static void -zone_free(malloc_zone_t *zone, void *ptr) -{ - - if (ivsalloc(ptr, config_prof) != 0) { +zone_free(malloc_zone_t *zone, void *ptr) { + if (ivsalloc(tsdn_fetch(), ptr) != 0) { je_free(ptr); return; } @@ -96,163 +172,280 @@ zone_free(malloc_zone_t *zone, void *ptr) } static void * -zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) -{ - - if (ivsalloc(ptr, config_prof) != 0) - return (je_realloc(ptr, size)); +zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) { + if (ivsalloc(tsdn_fetch(), ptr) != 0) { + return je_realloc(ptr, size); + } - return (realloc(ptr, size)); + return realloc(ptr, size); } -#if (JEMALLOC_ZONE_VERSION >= 5) static void * -zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) -{ +zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size) { void *ret = NULL; /* Assignment avoids useless compiler warning. */ je_posix_memalign(&ret, alignment, size); - return (ret); + return ret; } -#endif -#if (JEMALLOC_ZONE_VERSION >= 6) static void -zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) -{ +zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size) { + size_t alloc_size; - if (ivsalloc(ptr, config_prof) != 0) { - assert(ivsalloc(ptr, config_prof) == size); + alloc_size = ivsalloc(tsdn_fetch(), ptr); + if (alloc_size != 0) { + assert(alloc_size == size); je_free(ptr); return; } free(ptr); } -#endif - -static void * -zone_destroy(malloc_zone_t *zone) -{ +static void +zone_destroy(malloc_zone_t *zone) { /* This function should never be called. */ not_reached(); - return (NULL); +} + +static unsigned +zone_batch_malloc(struct _malloc_zone_t *zone, size_t size, void **results, + unsigned num_requested) { + unsigned i; + + for (i = 0; i < num_requested; i++) { + results[i] = je_malloc(size); + if (!results[i]) + break; + } + + return i; +} + +static void +zone_batch_free(struct _malloc_zone_t *zone, void **to_be_freed, + unsigned num_to_be_freed) { + unsigned i; + + for (i = 0; i < num_to_be_freed; i++) { + zone_free(zone, to_be_freed[i]); + to_be_freed[i] = NULL; + } } static size_t -zone_good_size(malloc_zone_t *zone, size_t size) -{ +zone_pressure_relief(struct _malloc_zone_t *zone, size_t goal) { + return 0; +} - if (size == 0) +static size_t +zone_good_size(malloc_zone_t *zone, size_t size) { + if (size == 0) { size = 1; - return (s2u(size)); + } + return sz_s2u(size); +} + +static kern_return_t +zone_enumerator(task_t task, void *data, unsigned type_mask, + vm_address_t zone_address, memory_reader_t reader, + vm_range_recorder_t recorder) { + return KERN_SUCCESS; +} + +static boolean_t +zone_check(malloc_zone_t *zone) { + return true; +} + +static void +zone_print(malloc_zone_t *zone, boolean_t verbose) { } static void -zone_force_lock(malloc_zone_t *zone) -{ +zone_log(malloc_zone_t *zone, void *address) { +} - if (isthreaded) +static void +zone_force_lock(malloc_zone_t *zone) { + if (isthreaded) { jemalloc_prefork(); + } +} + +static void +zone_force_unlock(malloc_zone_t *zone) { + /* + * Call jemalloc_postfork_child() rather than + * jemalloc_postfork_parent(), because this function is executed by both + * parent and child. The parent can tolerate having state + * reinitialized, but the child cannot unlock mutexes that were locked + * by the parent. + */ + if (isthreaded) { + jemalloc_postfork_child(); + } +} + +static void +zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { + /* We make no effort to actually fill the values */ + stats->blocks_in_use = 0; + stats->size_in_use = 0; + stats->max_size_in_use = 0; + stats->size_allocated = 0; +} + +static boolean_t +zone_locked(malloc_zone_t *zone) { + /* Pretend no lock is being held */ + return false; +} + +static void +zone_reinit_lock(malloc_zone_t *zone) { + /* As of OSX 10.12, this function is only used when force_unlock would + * be used if the zone version were < 9. So just use force_unlock. */ + zone_force_unlock(zone); +} + +static void +zone_init(void) { + jemalloc_zone.size = zone_size; + jemalloc_zone.malloc = zone_malloc; + jemalloc_zone.calloc = zone_calloc; + jemalloc_zone.valloc = zone_valloc; + jemalloc_zone.free = zone_free; + jemalloc_zone.realloc = zone_realloc; + jemalloc_zone.destroy = zone_destroy; + jemalloc_zone.zone_name = "jemalloc_zone"; + jemalloc_zone.batch_malloc = zone_batch_malloc; + jemalloc_zone.batch_free = zone_batch_free; + jemalloc_zone.introspect = &jemalloc_zone_introspect; + jemalloc_zone.version = 9; + jemalloc_zone.memalign = zone_memalign; + jemalloc_zone.free_definite_size = zone_free_definite_size; + jemalloc_zone.pressure_relief = zone_pressure_relief; + + jemalloc_zone_introspect.enumerator = zone_enumerator; + jemalloc_zone_introspect.good_size = zone_good_size; + jemalloc_zone_introspect.check = zone_check; + jemalloc_zone_introspect.print = zone_print; + jemalloc_zone_introspect.log = zone_log; + jemalloc_zone_introspect.force_lock = zone_force_lock; + jemalloc_zone_introspect.force_unlock = zone_force_unlock; + jemalloc_zone_introspect.statistics = zone_statistics; + jemalloc_zone_introspect.zone_locked = zone_locked; + jemalloc_zone_introspect.enable_discharge_checking = NULL; + jemalloc_zone_introspect.disable_discharge_checking = NULL; + jemalloc_zone_introspect.discharge = NULL; +#ifdef __BLOCKS__ + jemalloc_zone_introspect.enumerate_discharged_pointers = NULL; +#else + jemalloc_zone_introspect.enumerate_unavailable_without_blocks = NULL; +#endif + jemalloc_zone_introspect.reinit_lock = zone_reinit_lock; +} + +static malloc_zone_t * +zone_default_get(void) { + malloc_zone_t **zones = NULL; + unsigned int num_zones = 0; + + /* + * On OSX 10.12, malloc_default_zone returns a special zone that is not + * present in the list of registered zones. That zone uses a "lite zone" + * if one is present (apparently enabled when malloc stack logging is + * enabled), or the first registered zone otherwise. In practice this + * means unless malloc stack logging is enabled, the first registered + * zone is the default. So get the list of zones to get the first one, + * instead of relying on malloc_default_zone. + */ + if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, + (vm_address_t**)&zones, &num_zones)) { + /* + * Reset the value in case the failure happened after it was + * set. + */ + num_zones = 0; + } + + if (num_zones) { + return zones[0]; + } + + return malloc_default_zone(); } +/* As written, this function can only promote jemalloc_zone. */ static void -zone_force_unlock(malloc_zone_t *zone) -{ +zone_promote(void) { + malloc_zone_t *zone; + + do { + /* + * Unregister and reregister the default zone. On OSX >= 10.6, + * unregistering takes the last registered zone and places it + * at the location of the specified zone. Unregistering the + * default zone thus makes the last registered one the default. + * On OSX < 10.6, unregistering shifts all registered zones. + * The first registered zone then becomes the default. + */ + malloc_zone_unregister(default_zone); + malloc_zone_register(default_zone); - if (isthreaded) - jemalloc_postfork_parent(); + /* + * On OSX 10.6, having the default purgeable zone appear before + * the default zone makes some things crash because it thinks it + * owns the default zone allocated pointers. We thus + * unregister/re-register it in order to ensure it's always + * after the default zone. On OSX < 10.6, there is no purgeable + * zone, so this does nothing. On OSX >= 10.6, unregistering + * replaces the purgeable zone with the last registered zone + * above, i.e. the default zone. Registering it again then puts + * it at the end, obviously after the default zone. + */ + if (purgeable_zone != NULL) { + malloc_zone_unregister(purgeable_zone); + malloc_zone_register(purgeable_zone); + } + + zone = zone_default_get(); + } while (zone != &jemalloc_zone); } JEMALLOC_ATTR(constructor) void -register_zone(void) -{ - +zone_register(void) { /* * If something else replaced the system default zone allocator, don't * register jemalloc's. */ - malloc_zone_t *default_zone = malloc_default_zone(); - if (!default_zone->zone_name || - strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) { + default_zone = zone_default_get(); + if (!default_zone->zone_name || strcmp(default_zone->zone_name, + "DefaultMallocZone") != 0) { return; } - zone.size = (void *)zone_size; - zone.malloc = (void *)zone_malloc; - zone.calloc = (void *)zone_calloc; - zone.valloc = (void *)zone_valloc; - zone.free = (void *)zone_free; - zone.realloc = (void *)zone_realloc; - zone.destroy = (void *)zone_destroy; - zone.zone_name = "jemalloc_zone"; - zone.batch_malloc = NULL; - zone.batch_free = NULL; - zone.introspect = &zone_introspect; - zone.version = JEMALLOC_ZONE_VERSION; -#if (JEMALLOC_ZONE_VERSION >= 5) - zone.memalign = zone_memalign; -#endif -#if (JEMALLOC_ZONE_VERSION >= 6) - zone.free_definite_size = zone_free_definite_size; -#endif -#if (JEMALLOC_ZONE_VERSION >= 8) - zone.pressure_relief = NULL; -#endif - - zone_introspect.enumerator = NULL; - zone_introspect.good_size = (void *)zone_good_size; - zone_introspect.check = NULL; - zone_introspect.print = NULL; - zone_introspect.log = NULL; - zone_introspect.force_lock = (void *)zone_force_lock; - zone_introspect.force_unlock = (void *)zone_force_unlock; - zone_introspect.statistics = NULL; -#if (JEMALLOC_ZONE_VERSION >= 6) - zone_introspect.zone_locked = NULL; -#endif -#if (JEMALLOC_ZONE_VERSION >= 7) - zone_introspect.enable_discharge_checking = NULL; - zone_introspect.disable_discharge_checking = NULL; - zone_introspect.discharge = NULL; -#ifdef __BLOCKS__ - zone_introspect.enumerate_discharged_pointers = NULL; -#else - zone_introspect.enumerate_unavailable_without_blocks = NULL; -#endif -#endif - /* * The default purgeable zone is created lazily by OSX's libc. It uses * the default zone when it is created for "small" allocations * (< 15 KiB), but assumes the default zone is a scalable_zone. This * obviously fails when the default zone is the jemalloc zone, so - * malloc_default_purgeable_zone is called beforehand so that the + * malloc_default_purgeable_zone() is called beforehand so that the * default purgeable zone is created when the default zone is still * a scalable_zone. As purgeable zones only exist on >= 10.6, we need * to check for the existence of malloc_default_purgeable_zone() at * run time. */ - if (malloc_default_purgeable_zone != NULL) - malloc_default_purgeable_zone(); + purgeable_zone = (malloc_default_purgeable_zone == NULL) ? NULL : + malloc_default_purgeable_zone(); /* Register the custom zone. At this point it won't be the default. */ - malloc_zone_register(&zone); + zone_init(); + malloc_zone_register(&jemalloc_zone); - /* - * Unregister and reregister the default zone. On OSX >= 10.6, - * unregistering takes the last registered zone and places it at the - * location of the specified zone. Unregistering the default zone thus - * makes the last registered one the default. On OSX < 10.6, - * unregistering shifts all registered zones. The first registered zone - * then becomes the default. - */ - do { - default_zone = malloc_default_zone(); - malloc_zone_unregister(default_zone); - malloc_zone_register(default_zone); - } while (malloc_default_zone() != &zone); + /* Promote the custom zone to be default. */ + zone_promote(); } diff --git a/deps/recastnavigation/CMakeLists.txt b/deps/recastnavigation/CMakeLists.txt index 9a4e725c52..dd28884eb1 100644 --- a/deps/recastnavigation/CMakeLists.txt +++ b/deps/recastnavigation/CMakeLists.txt @@ -1,5 +1,5 @@ -# -# Copyright (C) +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# Copyright (C) 2005-2011 MaNGOS project <http://getmangos.com/> # # 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 diff --git a/deps/recastnavigation/Detour/CMakeLists.txt b/deps/recastnavigation/Detour/CMakeLists.txt index 233d123434..be271211b3 100644 --- a/deps/recastnavigation/Detour/CMakeLists.txt +++ b/deps/recastnavigation/Detour/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without @@ -9,12 +9,12 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. set(Detour_STAT_SRCS - DetourAlloc.cpp - DetourCommon.cpp - DetourNavMesh.cpp - DetourNavMeshBuilder.cpp - DetourNavMeshQuery.cpp - DetourNode.cpp + Source/DetourAlloc.cpp + Source/DetourCommon.cpp + Source/DetourNavMesh.cpp + Source/DetourNavMeshBuilder.cpp + Source/DetourNavMeshQuery.cpp + Source/DetourNode.cpp ) if(WIN32) @@ -25,4 +25,15 @@ endif() add_library(Detour STATIC ${Detour_STAT_SRCS}) -target_link_libraries(Detour ${ZLIB_LIBRARIES}) +target_include_directories(Detour + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/Include) + +target_link_libraries(Detour + PUBLIC + zlib) + +set_target_properties(Detour + PROPERTIES + FOLDER + "dep") diff --git a/deps/recastnavigation/Detour/DetourAlloc.h b/deps/recastnavigation/Detour/DetourAlloc.h deleted file mode 100644 index 8693475419..0000000000 --- a/deps/recastnavigation/Detour/DetourAlloc.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef DETOURALLOCATOR_H -#define DETOURALLOCATOR_H - -enum dtAllocHint -{ - DT_ALLOC_PERM, // Memory persist after a function call. - DT_ALLOC_TEMP // Memory used temporarily within a function. -}; - -typedef void* (dtAllocFunc)(int size, dtAllocHint hint); -typedef void (dtFreeFunc)(void* ptr); - -void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc); - -void* dtAlloc(int size, dtAllocHint hint); -void dtFree(void* ptr); - -#endif diff --git a/deps/recastnavigation/Detour/DetourCommon.h b/deps/recastnavigation/Detour/DetourCommon.h deleted file mode 100644 index 3cee3f6351..0000000000 --- a/deps/recastnavigation/Detour/DetourCommon.h +++ /dev/null @@ -1,248 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef DETOURCOMMON_H -#define DETOURCOMMON_H - -template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; } -template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; } -template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; } -template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; } -template<class T> inline T dtSqr(T a) { return a*a; } -template<class T> inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } - -float dtSqrt(float x); - -inline void dtVcross(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; - dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; - dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -inline float dtVdot(const float* v1, const float* v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -inline void dtVmad(float* dest, const float* v1, const float* v2, const float s) -{ - dest[0] = v1[0]+v2[0]*s; - dest[1] = v1[1]+v2[1]*s; - dest[2] = v1[2]+v2[2]*s; -} - -inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t) -{ - dest[0] = v1[0]+(v2[0]-v1[0])*t; - dest[1] = v1[1]+(v2[1]-v1[1])*t; - dest[2] = v1[2]+(v2[2]-v1[2])*t; -} - -inline void dtVadd(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]+v2[0]; - dest[1] = v1[1]+v2[1]; - dest[2] = v1[2]+v2[2]; -} - -inline void dtVsub(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]-v2[0]; - dest[1] = v1[1]-v2[1]; - dest[2] = v1[2]-v2[2]; -} - -inline void dtVscale(float* dest, const float* v, const float t) -{ - dest[0] = v[0]*t; - dest[1] = v[1]*t; - dest[2] = v[2]*t; -} - -inline void dtVmin(float* mn, const float* v) -{ - mn[0] = dtMin(mn[0], v[0]); - mn[1] = dtMin(mn[1], v[1]); - mn[2] = dtMin(mn[2], v[2]); -} - -inline void dtVmax(float* mx, const float* v) -{ - mx[0] = dtMax(mx[0], v[0]); - mx[1] = dtMax(mx[1], v[1]); - mx[2] = dtMax(mx[2], v[2]); -} - -inline void dtVset(float* dest, const float x, const float y, const float z) -{ - dest[0] = x; dest[1] = y; dest[2] = z; -} - -inline void dtVcopy(float* dest, const float* a) -{ - dest[0] = a[0]; - dest[1] = a[1]; - dest[2] = a[2]; -} - -inline float dtVlen(const float* v) -{ - return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); -} - -inline float dtVlenSqr(const float* v) -{ - return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; -} - -inline float dtVdist(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; - const float dz = v2[2] - v1[2]; - return dtSqrt(dx*dx + dy*dy + dz*dz); -} - -inline float dtVdistSqr(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; - const float dz = v2[2] - v1[2]; - return dx*dx + dy*dy + dz*dz; -} - -inline float dtVdist2D(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dz = v2[2] - v1[2]; - return dtSqrt(dx*dx + dz*dz); -} - -inline float dtVdist2DSqr(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dz = v2[2] - v1[2]; - return dx*dx + dz*dz; -} - -inline void dtVnormalize(float* v) -{ - float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2])); - v[0] *= d; - v[1] *= d; - v[2] *= d; -} - -inline bool dtVequal(const float* p0, const float* p1) -{ - static const float thr = dtSqr(1.0f/16384.0f); - const float d = dtVdistSqr(p0, p1); - return d < thr; -} - -inline unsigned int dtNextPow2(unsigned int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -inline unsigned int dtIlog2(unsigned int v) -{ - unsigned int r; - unsigned int shift; - r = (v > 0xffff) << 4; v >>= r; - shift = (v > 0xff) << 3; v >>= shift; r |= shift; - shift = (v > 0xf) << 2; v >>= shift; r |= shift; - shift = (v > 0x3) << 1; v >>= shift; r |= shift; - r |= (v >> 1); - return r; -} - -inline int dtAlign4(int x) { return (x+3) & ~3; } - -inline int dtOppositeTile(int side) { return (side+4) & 0x7; } - -inline float dtVdot2D(const float* u, const float* v) -{ - return u[0]*v[0] + u[2]*v[2]; -} - -inline float dtVperp2D(const float* u, const float* v) -{ - return u[2]*v[0] - u[0]*v[2]; -} - -inline float dtTriArea2D(const float* a, const float* b, const float* c) -{ - const float abx = b[0] - a[0]; - const float abz = b[2] - a[2]; - const float acx = c[0] - a[0]; - const float acz = c[2] - a[2]; - return acx*abz - abx*acz; -} - -inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3], - const unsigned short bmin[3], const unsigned short bmax[3]) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -inline bool dtOverlapBounds(const float* amin, const float* amax, - const float* bmin, const float* bmax) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -void dtClosestPtPointTriangle(float* closest, const float* p, - const float* a, const float* b, const float* c); - -bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h); - -bool dtIntersectSegmentPoly2D(const float* p0, const float* p1, - const float* verts, int nverts, - float& tmin, float& tmax, - int& segMin, int& segMax); - -bool dtPointInPolygon(const float* pt, const float* verts, const int nverts); - -bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts, - float* ed, float* et); - -float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t); - -void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts); - -bool dtOverlapPolyPoly2D(const float* polya, const int npolya, - const float* polyb, const int npolyb); - -#endif // DETOURCOMMON_H diff --git a/deps/recastnavigation/Detour/DetourNavMesh.h b/deps/recastnavigation/Detour/DetourNavMesh.h deleted file mode 100644 index 6f2db04004..0000000000 --- a/deps/recastnavigation/Detour/DetourNavMesh.h +++ /dev/null @@ -1,428 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef DETOURNAVMESH_H -#define DETOURNAVMESH_H - -#include "DetourAlloc.h" - -#ifdef WIN32 - typedef unsigned __int64 uint64; -#else -#include <stdint.h> -#ifndef uint64_t -#ifdef __linux__ -#include <linux/types.h> -#endif -#endif - typedef uint64_t uint64; -#endif - -// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. -// It is also recommended to change dtHashRef() to proper 64-bit hash too. - -// Reference to navigation polygon. -typedef uint64 dtPolyRef; - -// Reference to navigation mesh tile. -typedef uint64 dtTileRef; - -// Maximum number of vertices per navigation polygon. -static const int DT_VERTS_PER_POLYGON = 6; - -static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; //'DNAV'; -static const int DT_NAVMESH_VERSION = 6; - -static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; //'DNMS'; -static const int DT_NAVMESH_STATE_VERSION = 1; - -static const unsigned short DT_EXT_LINK = 0x8000; -static const unsigned int DT_NULL_LINK = 0xffffffff; -static const unsigned int DT_OFFMESH_CON_BIDIR = 1; - -static const int DT_MAX_AREAS = 64; - -static const int STATIC_SALT_BITS = 12; -static const int STATIC_TILE_BITS = 21; -static const int STATIC_POLY_BITS = 31; -// we cannot have over 31 bits for either tile nor poly -// without changing polyCount to use 64bits too. - -// Flags for addTile -enum dtTileFlags -{ - DT_TILE_FREE_DATA = 0x01, // Navmesh owns the tile memory and should free it. -}; - -// Flags returned by findStraightPath(). -enum dtStraightPathFlags -{ - DT_STRAIGHTPATH_START = 0x01, // The vertex is the start position. - DT_STRAIGHTPATH_END = 0x02, // The vertex is the end position. - DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, // The vertex is start of an off-mesh link. -}; - -// Flags describing polygon properties. -enum dtPolyTypes -{ - DT_POLYTYPE_GROUND = 0, // Regular ground polygons. - DT_POLYTYPE_OFFMESH_CONNECTION = 1, // Off-mesh connections. -}; - -enum dtStatus -{ - DT_FAILURE = 0, // Operation failed. - DT_FAILURE_DATA_MAGIC, - DT_FAILURE_DATA_VERSION, - DT_FAILURE_OUT_OF_MEMORY, - DT_SUCCESS, // Operation succeed. - DT_IN_PROGRESS, // Operation still in progress. -}; - - -// Structure describing the navigation polygon data. -struct dtPoly -{ - unsigned int firstLink; // Index to first link in linked list. - unsigned short verts[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly. - unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly. - unsigned short flags; // Flags (see dtPolyFlags). - unsigned char vertCount; // Number of vertices. - unsigned char areaAndtype; // Bit packed: Area ID of the polygon, and Polygon type, see dtPolyTypes.. - inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); } - inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); } - inline unsigned char getArea() const { return areaAndtype & 0x3f; } - inline unsigned char getType() const { return areaAndtype >> 6; } -}; - -// Stucture describing polygon detail triangles. -struct dtPolyDetail -{ - unsigned int vertBase; // Offset to detail vertex array. - unsigned int triBase; // Offset to detail triangle array. - unsigned char vertCount; // Number of vertices in the detail mesh. - unsigned char triCount; // Number of triangles. -}; - -// Stucture describing a link to another polygon. -struct dtLink -{ - dtPolyRef ref; // Neighbour reference. - unsigned int next; // Index to next link. - unsigned char edge; // Index to polygon edge which owns this link. - unsigned char side; // If boundary link, defines on which side the link is. - unsigned char bmin, bmax; // If boundary link, defines the sub edge area. -}; - -struct dtBVNode -{ - unsigned short bmin[3], bmax[3]; // BVnode bounds - int i; // Index to item or if negative, escape index. -}; - -struct dtOffMeshConnection -{ - float pos[6]; // Both end point locations. - float rad; // Link connection radius. - unsigned short poly; // Poly Id - unsigned char flags; // Link flags - unsigned char side; // End point side. - unsigned int userId; // User ID to identify this connection. -}; - -struct dtMeshHeader -{ - int magic; // Magic number, used to identify the data. - int version; // Data version number. - int x, y; // Location of the time on the grid. - unsigned int userId; // User ID of the tile. - int polyCount; // Number of polygons in the tile. - int vertCount; // Number of vertices in the tile. - int maxLinkCount; // Number of allocated links. - int detailMeshCount; // Number of detail meshes. - int detailVertCount; // Number of detail vertices. - int detailTriCount; // Number of detail triangles. - int bvNodeCount; // Number of BVtree nodes. - int offMeshConCount; // Number of Off-Mesh links. - int offMeshBase; // Index to first polygon which is Off-Mesh link. - float walkableHeight; // Height of the agent. - float walkableRadius; // Radius of the agent - float walkableClimb; // Max climb height of the agent. - float bmin[3], bmax[3]; // Bounding box of the tile. - float bvQuantFactor; // BVtree quantization factor (world to bvnode coords) -}; - -struct dtMeshTile -{ - unsigned int salt; // Counter describing modifications to the tile. - - unsigned int linksFreeList; // Index to next free link. - dtMeshHeader* header; // Pointer to tile header. - dtPoly* polys; // Pointer to the polygons (will be updated when tile is added). - float* verts; // Pointer to the vertices (will be updated when tile added). - dtLink* links; // Pointer to the links (will be updated when tile added). - dtPolyDetail* detailMeshes; // Pointer to detail meshes (will be updated when tile added). - float* detailVerts; // Pointer to detail vertices (will be updated when tile added). - unsigned char* detailTris; // Pointer to detail triangles (will be updated when tile added). - dtBVNode* bvTree; // Pointer to BVtree nodes (will be updated when tile added). - dtOffMeshConnection* offMeshCons; // Pointer to Off-Mesh links. (will be updated when tile added). - - unsigned char* data; // Pointer to tile data. - int dataSize; // Size of the tile data. - int flags; // Tile flags, see dtTileFlags. - dtMeshTile* next; // Next free tile or, next tile in spatial grid. -}; - -struct dtNavMeshParams -{ - float orig[3]; // Origin of the nav mesh tile space. - float tileWidth, tileHeight; // Width and height of each tile. - int maxTiles; // Maximum number of tiles the navmesh can contain. - int maxPolys; // Maximum number of polygons each tile can contain. -}; - - -class dtNavMesh -{ -public: - dtNavMesh(); - ~dtNavMesh(); - - // Initializes the nav mesh for tiled use. - // Params: - // params - (in) navmesh initialization params, see dtNavMeshParams. - // Returns: True if succeed, else false. - dtStatus init(const dtNavMeshParams* params); - - // Initializes the nav mesh for single tile use. - // Params: - // data - (in) Data of the new tile mesh. - // dataSize - (in) Data size of the new tile mesh. - // flags - (in) Tile flags, see dtTileFlags. - // Returns: True if succeed, else false. - dtStatus init(unsigned char* data, const int dataSize, const int flags); - - // Returns pointer to navmesh initialization params. - const dtNavMeshParams* getParams() const; - - // Adds new tile into the navmesh. - // The add will fail if the data is in wrong format, - // there is not enough tiles left, or if there is a tile already at the location. - // Params: - // data - (in) Data of the new tile mesh. - // dataSize - (in) Data size of the new tile mesh. - // flags - (in) Tile flags, see dtTileFlags. - // lastRef - (in,optional) Last tile ref, the tile will be restored so that - // the reference (as well as poly references) will be the same. Default: 0. - // result - (out,optional) tile ref if the tile was succesfully added. - dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result); - - // Removes specified tile. - // Params: - // ref - (in) Reference to the tile to remove. - // data - (out) Data associated with deleted tile. - // dataSize - (out) Size of the data associated with deleted tile. - dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize); - - // Calculates tile location based in input world position. - // Params: - // pos - (in) world position of the query. - // tx - (out) tile x location. - // ty - (out) tile y location. - void calcTileLoc(const float* pos, int* tx, int* ty) const; - - // Returns pointer to tile at specified location. - // Params: - // x,y - (in) Location of the tile to get. - // Returns: pointer to tile if tile exists or 0 tile does not exists. - const dtMeshTile* getTileAt(int x, int y) const; - - // Returns reference to tile at specified location. - // Params: - // x,y - (in) Location of the tile to get. - // Returns: reference to tile if tile exists or 0 tile does not exists. - dtTileRef getTileRefAt(int x, int y) const; - - // Returns tile references of a tile based on tile pointer. - dtTileRef getTileRef(const dtMeshTile* tile) const; - - // Returns tile based on references. - const dtMeshTile* getTileByRef(dtTileRef ref) const; - - // Returns max number of tiles. - int getMaxTiles() const; - - // Returns pointer to tile in the tile array. - // Params: - // i - (in) Index to the tile to retrieve, max index is getMaxTiles()-1. - // Returns: Pointer to specified tile. - const dtMeshTile* getTile(int i) const; - - // Returns pointer to tile and polygon pointed by the polygon reference. - // Params: - // ref - (in) reference to a polygon. - // tile - (out) pointer to the tile containing the polygon. - // poly - (out) pointer to the polygon. - dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; - - // Returns pointer to tile and polygon pointed by the polygon reference. - // Note: this function does not check if 'ref' s valid, and is thus faster. Use only with valid refs! - // Params: - // ref - (in) reference to a polygon. - // tile - (out) pointer to the tile containing the polygon. - // poly - (out) pointer to the polygon. - void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; - - // Returns true if polygon reference points to valid data. - bool isValidPolyRef(dtPolyRef ref) const; - - // Returns base poly id for specified tile, polygon refs can be deducted from this. - dtPolyRef getPolyRefBase(const dtMeshTile* tile) const; - - // Returns start and end location of an off-mesh link polygon. - // Params: - // prevRef - (in) ref to the polygon before the link (used to select direction). - // polyRef - (in) ref to the off-mesh link polygon. - // startPos[3] - (out) start point of the link. - // endPos[3] - (out) end point of the link. - // Returns: true if link is found. - dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const; - - // Returns pointer to off-mesh connection based on polyref, or null if ref not valid. - const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const; - - // Sets polygon flags. - dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags); - - // Return polygon flags. - dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const; - - // Set polygon type. - dtStatus setPolyArea(dtPolyRef ref, unsigned char area); - - // Return polygon area type. - dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const; - - - // Returns number of bytes required to store tile state. - int getTileStateSize(const dtMeshTile* tile) const; - - // Stores tile state to buffer. - dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const; - - // Restores tile state. - dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize); - - - // Encodes a tile id. - inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const - { - return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip; - } - - // Decodes a tile id. - inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const - { - const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; - const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; - const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; - salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); - it = (unsigned int)((ref >> m_polyBits) & tileMask); - ip = (unsigned int)(ref & polyMask); - } - - // Decodes a tile salt. - inline unsigned int decodePolyIdSalt(dtPolyRef ref) const - { - const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; - return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); - } - - // Decodes a tile id. - inline unsigned int decodePolyIdTile(dtPolyRef ref) const - { - const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; - return (unsigned int)((ref >> m_polyBits) & tileMask); - } - - // Decodes a poly id. - inline unsigned int decodePolyIdPoly(dtPolyRef ref) const - { - const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; - return (unsigned int)(ref & polyMask); - } - -private: - - // Returns pointer to tile in the tile array. - dtMeshTile* getTile(int i); - - // Returns neighbour tile based on side. - dtMeshTile* getNeighbourTileAt(int x, int y, int side) const; - // Returns all polygons in neighbour tile based on portal defined by the segment. - int findConnectingPolys(const float* va, const float* vb, - const dtMeshTile* tile, int side, - dtPolyRef* con, float* conarea, int maxcon) const; - - // Builds internal polygons links for a tile. - void connectIntLinks(dtMeshTile* tile); - // Builds internal polygons links for a tile. - void connectIntOffMeshLinks(dtMeshTile* tile); - - // Builds external polygon links for a tile. - void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side); - // Builds external polygon links for a tile. - void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side); - - // Removes external links at specified side. - void unconnectExtLinks(dtMeshTile* tile, int side); - - - // TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding. - - // Queries polygons within a tile. - int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, - dtPolyRef* polys, const int maxPolys) const; - // Find nearest polygon within a tile. - dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, - const float* extents, float* nearestPt) const; - // Returns closest point on polygon. - dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, - const float* pos, float* closest) const; - - dtNavMeshParams m_params; // Current initialization params. TODO: do not store this info twice. - float m_orig[3]; // Origin of the tile (0,0) - float m_tileWidth, m_tileHeight; // Dimensions of each tile. - int m_maxTiles; // Max number of tiles. - int m_tileLutSize; // Tile hash lookup size (must be pot). - int m_tileLutMask; // Tile hash lookup mask. - - dtMeshTile** m_posLookup; // Tile hash lookup. - dtMeshTile* m_nextFree; // Freelist of tiles. - dtMeshTile* m_tiles; // List of tiles. - - unsigned int m_saltBits; // Number of salt bits in the tile ID. - unsigned int m_tileBits; // Number of tile bits in the tile ID. - unsigned int m_polyBits; // Number of poly bits in the tile ID. -}; - -// Helper function to allocate navmesh class using Detour allocator. -dtNavMesh* dtAllocNavMesh(); -void dtFreeNavMesh(dtNavMesh* navmesh); - -#endif // DETOURNAVMESH_H diff --git a/deps/recastnavigation/Detour/DetourNavMeshBuilder.h b/deps/recastnavigation/Detour/DetourNavMeshBuilder.h deleted file mode 100644 index aa802d71cb..0000000000 --- a/deps/recastnavigation/Detour/DetourNavMeshBuilder.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef DETOURNAVMESHBUILDER_H -#define DETOURNAVMESHBUILDER_H - -#include "DetourAlloc.h" - - -// The units of the parameters are specified in parenthesis as follows: -// (vx) voxels, (wu) world units -struct dtNavMeshCreateParams -{ - // Navmesh vertices. - const unsigned short* verts; // Array of vertices, each vertex has 3 components. (vx). - int vertCount; // Vertex count - // Navmesh polygons - const unsigned short* polys; // Array of polygons, uses same format as rcPolyMesh. - const unsigned short* polyFlags; // Array of flags per polygon. - const unsigned char* polyAreas; // Array of area ids per polygon. - int polyCount; // Number of polygons - int nvp; // Number of verts per polygon. - // Navmesh Detail - const unsigned int* detailMeshes; // Detail meshes, uses same format as rcPolyMeshDetail. - const float* detailVerts; // Detail mesh vertices, uses same format as rcPolyMeshDetail (wu). - int detailVertsCount; // Total number of detail vertices - const unsigned char* detailTris; // Array of detail tris per detail mesh. - int detailTriCount; // Total number of detail triangles. - // Off-Mesh Connections. - const float* offMeshConVerts; // Off-mesh connection vertices (wu). - const float* offMeshConRad; // Off-mesh connection radii (wu). - const unsigned short* offMeshConFlags; // Off-mesh connection flags. - const unsigned char* offMeshConAreas; // Off-mesh connection area ids. - const unsigned char* offMeshConDir; // Off-mesh connection direction flags (1 = bidir, 0 = oneway). - const unsigned int* offMeshConUserID; // Off-mesh connection user id (optional). - int offMeshConCount; // Number of off-mesh connections - // Tile location - unsigned int userId; // User ID bound to the tile. - int tileX, tileY; // Tile location (tile coords). - float bmin[3], bmax[3]; // Tile bounds (wu). - // Settings - float walkableHeight; // Agent height (wu). - float walkableRadius; // Agent radius (wu). - float walkableClimb; // Agent max climb (wu). - float cs; // Cell size (xz) (wu). - float ch; // Cell height (y) (wu). - int tileSize; // Tile size (width & height) (vx). - int tileLayer; - bool buildBvTree; -}; - -// Build navmesh data from given input data. -bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize); - -// Swaps endianess of navmesh header. -bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize); - -// Swaps endianess of the navmesh data. This function assumes that the header is in correct -// endianess already. Call dtNavMeshHeaderSwapEndian() first on the data if the data is -// assumed to be in wrong endianess to start with. If converting from native endianess to foreign, -// call dtNavMeshHeaderSwapEndian() after the data has been swapped. -bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize); - -#endif // DETOURNAVMESHBUILDER_H diff --git a/deps/recastnavigation/Detour/DetourNavMeshQuery.h b/deps/recastnavigation/Detour/DetourNavMeshQuery.h deleted file mode 100644 index f5046d8329..0000000000 --- a/deps/recastnavigation/Detour/DetourNavMeshQuery.h +++ /dev/null @@ -1,407 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef DETOURNAVMESHQUERY_H -#define DETOURNAVMESHQUERY_H - -#include "DetourNavMesh.h" - - -// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter. -// On certain platforms indirect or virtual function call is expensive. The default -// setting is to use non-virtual functions, the actualy implementations of the functions -// are declared as inline for maximum speed. - -//#define DT_VIRTUAL_QUERYFILTER 1 - -// Class for polygon filtering and cost calculation during query operations. -// - It is possible to derive a custom query filter from dtQueryFilter by overriding -// the virtual functions passFilter() and getCost(). -// - Both functions should be as fast as possible. Use cached local copy of data -// instead of accessing your own objects where possible. -// - You do not need to adhere to the flags and cost logic provided by the default -// implementation. -// - In order for the A* to work properly, the cost should be proportional to -// the travel distance. Using cost modifier less than 1.0 is likely to lead -// to problems during pathfinding. -class dtQueryFilter -{ - float m_areaCost[DT_MAX_AREAS]; // Array storing cost per area type, used by default implementation. - unsigned short m_includeFlags; // Include poly flags, used by default implementation. - unsigned short m_excludeFlags; // Exclude poly flags, used by default implementation. - -public: - dtQueryFilter(); - - // Returns true if the polygon is can visited. - // Params: - // ref - (in) reference to the polygon test. - // tile - (in) pointer to the tile of the polygon test. - // poly - (in) pointer to the polygon test. -#ifdef DT_VIRTUAL_QUERYFILTER - virtual bool passFilter(const dtPolyRef ref, - const dtMeshTile* tile, - const dtPoly* poly) const; -#else - bool passFilter(const dtPolyRef ref, - const dtMeshTile* tile, - const dtPoly* poly) const; -#endif - - // Returns cost to travel from 'pa' to 'pb'.' - // The segment is fully contained inside 'cur'. - // 'pa' lies on the edge between 'prev' and 'cur', - // 'pb' lies on the edge between 'cur' and 'next'. - // Params: - // pa - (in) segment start position. - // pb - (in) segment end position. - // prevRef, prevTile, prevPoly - (in) data describing the previous polygon, can be null. - // curRef, curTile, curPoly - (in) data describing the current polygon. - // nextRef, nextTile, nextPoly - (in) data describing the next polygon, can be null. -#ifdef DT_VIRTUAL_QUERYFILTER - virtual float getCost(const float* pa, const float* pb, - const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, - const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, - const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; -#else - float getCost(const float* pa, const float* pb, - const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, - const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, - const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; -#endif - - // Getters and setters for the default implementation data. - inline float getAreaCost(const int i) const { return m_areaCost[i]; } - inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; } - - inline unsigned short getIncludeFlags() const { return m_includeFlags; } - inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; } - - inline unsigned short getExcludeFlags() const { return m_excludeFlags; } - inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; } -}; - -class dtNavMeshQuery -{ -public: - dtNavMeshQuery(); - ~dtNavMeshQuery(); - - // Initializes the nav mesh query. - // Params: - // nav - (in) pointer to navigation mesh data. - // maxNodes - (in) Maximum number of search nodes to use (max 65536). - // Returns: True if succeed, else false. - dtStatus init(const dtNavMesh* nav, const int maxNodes); - - // Finds the nearest navigation polygon around the center location. - // Params: - // center[3] - (in) The center of the search box. - // extents[3] - (in) The extents of the search box. - // filter - (in) path polygon filter. - // nearestRef - (out) Reference to the nearest polygon. - // nearestPt[3] - (out, opt) The nearest point on found polygon, null if not needed. - // Returns: Reference identifier for the polygon, or 0 if no polygons found. - dtStatus findNearestPoly(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* nearestRef, float* nearestPt) const; - - // Returns polygons which overlap the query box. - // Params: - // center[3] - (in) the center of the search box. - // extents[3] - (in) the extents of the search box. - // filter - (in) path polygon filter. - // polys - (out) array holding the search result. - // polyCount - (out) Number of polygons in search result array. - // maxPolys - (in) The max number of polygons the polys array can hold. - dtStatus queryPolygons(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* polys, int* polyCount, const int maxPolys) const; - - // Finds path from start polygon to end polygon. - // If target polygon canno be reached through the navigation graph, - // the last node on the array is nearest node to the end polygon. - // Start end end positions are needed to calculate more accurate - // traversal cost at start end end polygons. - // Params: - // startRef - (in) ref to path start polygon. - // endRef - (in) ref to path end polygon. - // startPos[3] - (in) Path start location. - // endPos[3] - (in) Path end location. - // filter - (in) path polygon filter. - // path - (out) array holding the search result. - // pathCount - (out) Number of polygons in search result array. - // maxPath - (in) The max number of polygons the path array can hold. Must be at least 1. - dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter, - dtPolyRef* path, int* pathCount, const int maxPath) const; - - // Intializes sliced path find query. - // Note 1: calling any other dtNavMeshQuery method before calling findPathEnd() - // may results in corrupted data! - // Note 2: The pointer to filter is store, and used in subsequent - // calls to updateSlicedFindPath(). - // Params: - // startRef - (in) ref to path start polygon. - // endRef - (in) ref to path end polygon. - // startPos[3] - (in) Path start location. - // endPos[3] - (in) Path end location. - // filter - (in) path polygon filter. - dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter); - - // Updates sliced path find query. - // Params: - // maxIter - (in) max number of iterations to update. - // Returns: Path query state. - dtStatus updateSlicedFindPath(const int maxIter); - - // Finalizes sliced path find query and returns found path. - // path - (out) array holding the search result. - // pathCount - (out) Number of polygons in search result array. - // maxPath - (in) The max number of polygons the path array can hold. - dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath); - - // Finalizes partial sliced path find query and returns path to the furthest - // polygon on the existing path that was visited during the search. - // existing - (out) Array of polygons in the existing path. - // existingSize - (out) Number of polygons in existing path array. - // path - (out) array holding the search result. - // pathCount - (out) Number of polygons in search result array. - // maxPath - (in) The max number of polygons the path array can hold. - dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, - dtPolyRef* path, int* pathCount, const int maxPath); - - // Finds a straight path from start to end locations within the corridor - // described by the path polygons. - // Start and end locations will be clamped on the corridor. - // The returned polygon references are point to polygon which was entered when - // a path point was added. For the end point, zero will be returned. This allows - // to match for example off-mesh link points to their representative polygons. - // Params: - // startPos[3] - (in) Path start location. - // endPo[3] - (in) Path end location. - // path - (in) Array of connected polygons describing the corridor. - // pathSize - (in) Number of polygons in path array. - // straightPath - (out) Points describing the straight path. - // straightPathFlags - (out, opt) Flags describing each point type, see dtStraightPathFlags. - // straightPathRefs - (out, opt) References to polygons at point locations. - // straightPathCount - (out) Number of points in the path. - // maxStraightPath - (in) The max number of points the straight path array can hold. Must be at least 1. - dtStatus findStraightPath(const float* startPos, const float* endPos, - const dtPolyRef* path, const int pathSize, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const; - - // Moves from startPos to endPos constrained to the navmesh. - // If the endPos is reachable, the resultPos will be endPos, - // or else the resultPos will be the nearest point in navmesh. - // Note: The resulting point is not projected to the ground, use getPolyHeight() to get height. - // Note: The algorithm is optimized for small delta movement and small number of polygons. - // Params: - // startRef - (in) ref to the polygon where startPos lies. - // startPos[3] - (in) start position of the mover. - // endPos[3] - (in) desired end position of the mover. - // filter - (in) path polygon filter. - // resultPos[3] - (out) new position of the mover. - // visited - (out) array of visited polygons. - // visitedCount - (out) Number of entries in the visited array. - // maxVisitedSize - (in) max number of polygons in the visited array. - dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const; - - // Casts 'walkability' ray along the navmesh surface from startPos towards the endPos. - // Params: - // startRef - (in) ref to the polygon where the start lies. - // startPos[3] - (in) start position of the query. - // endPos[3] - (in) end position of the query. - // t - (out) hit parameter along the segment, FLT_MAX if no hit. - // hitNormal[3] - (out) normal of the nearest hit. - // filter - (in) path polygon filter. - // path - (out,opt) visited path polygons. - // pathCount - (out,opt) Number of polygons visited. - // maxPath - (in) max number of polygons in the path array. - dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const; - - // Returns distance to nearest wall from the specified location. - // Params: - // startRef - (in) ref to the polygon where the center lies. - // centerPos[3] - (in) center if the query circle. - // maxRadius - (in) max search radius. - // filter - (in) path polygon filter. - // hitDist - (out) distance to nearest wall from the test location. - // hitPos[3] - (out) location of the nearest hit. - // hitNormal[3] - (out) normal of the nearest hit. - dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, - float* hitDist, float* hitPos, float* hitNormal) const; - - // Finds polygons found along the navigation graph which touch the specified circle. - // Params: - // startRef - (in) ref to the polygon where the search starts. - // centerPos[3] - (in) center if the query circle. - // radius - (in) radius of the query circle. - // filter - (in) path polygon filter. - // resultRef - (out, opt) refs to the polygons touched by the circle. - // resultParent - (out, opt) parent of each result polygon. - // resultCost - (out, opt) search cost at each result polygon. - // resultCount - (out, opt) Number of results. - // maxResult - (int) maximum capacity of search results. - dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const; - - // Finds polygons found along the navigation graph which touch the convex polygon shape. - // Params: - // startRef - (in) ref to the polygon where the search starts. - // verts[3*n] - (in) vertices describing convex polygon shape (CCW). - // nverts - (in) number of vertices in the polygon. - // filter - (in) path polygon filter. - // resultRef - (out, opt) refs to the polygons touched by the circle. - // resultParent - (out, opt) parent of each result polygon. - // resultCost - (out, opt) search cost at each result polygon. - // resultCount - (out) number of results. - // maxResult - (int) maximum capacity of search results. - dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const; - - // Finds non-overlapping local neighbourhood around center location. - // Note: The algorithm is optimized for small query radius and small number of polygons. - // Params: - // startRef - (in) ref to the polygon where the search starts. - // centerPos[3] - (in) center if the query circle. - // radius - (in) radius of the query circle. - // filter - (in) path polygon filter. - // resultRef - (out) refs to the polygons touched by the circle. - // resultParent - (out, opt) parent of each result polygon. - // resultCount - (out) number of results. - // maxResult - (int) maximum capacity of search results. - dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, - int* resultCount, const int maxResult) const; - - // Returns wall segments of specified polygon. - // Params: - // ref - (in) ref to the polygon. - // filter - (in) path polygon filter. - // segments[6*maxSegments] - (out) wall segments (2 endpoints per segment). - // segmentCount - (out) number of wall segments. - // maxSegments - (in) max number of segments that can be stored in 'segments'. - dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segments, int* segmentCount, const int maxSegments) const; - - // Returns closest point on navigation polygon. - // Uses detail polygons to find the closest point to the navigation polygon surface. - // Params: - // ref - (in) ref to the polygon. - // pos[3] - (in) the point to check. - // closest[3] - (out) closest point. - // Returns: true if closest point found. - dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const; - - // Returns closest point on navigation polygon boundary. - // Uses the navigation polygon boundary to snap the point to poly boundary - // if it is outside the polygon. Much faster than closestPointToPoly. Does not affect height. - // Params: - // ref - (in) ref to the polygon. - // pos[3] - (in) the point to check. - // closest[3] - (out) closest point. - // Returns: true if closest point found. - dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const; - - // Returns start and end location of an off-mesh link polygon. - // Params: - // prevRef - (in) ref to the polygon before the link (used to select direction). - // polyRef - (in) ref to the off-mesh link polygon. - // startPos[3] - (out) start point of the link. - // endPos[3] - (out) end point of the link. - // Returns: true if link is found. - dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const; - - // Returns height of the polygon at specified location. - // Params: - // ref - (in) ref to the polygon. - // pos[3] - (in) the point where to locate the height. - // height - (out) height at the location. - // Returns: true if over polygon. - dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const; - - // Returns true if poly reference ins in closed list. - bool isInClosedList(dtPolyRef ref) const; - - class dtNodePool* getNodePool() const { return m_nodePool; } - -private: - - // Returns neighbour tile based on side. - dtMeshTile* getNeighbourTileAt(int x, int y, int side) const; - - // Queries polygons within a tile. - int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter, - dtPolyRef* polys, const int maxPolys) const; - // Find nearest polygon within a tile. - dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents, - const dtQueryFilter* filter, float* nearestPt) const; - // Returns closest point on polygon. - dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const; - - // Returns portal points between two polygons. - dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, - unsigned char& fromType, unsigned char& toType) const; - dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* left, float* right) const; - - // Returns edge mid point between two polygons. - dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const; - dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* mid) const; - - const dtNavMesh* m_nav; // Pointer to navmesh data. - - struct dtQueryData - { - dtStatus status; - struct dtNode* lastBestNode; - float lastBestNodeCost; - dtPolyRef startRef, endRef; - float startPos[3], endPos[3]; - const dtQueryFilter* filter; - }; - dtQueryData m_query; // Sliced query state. - - class dtNodePool* m_tinyNodePool; // Pointer to small node pool. - class dtNodePool* m_nodePool; // Pointer to node pool. - class dtNodeQueue* m_openList; // Pointer to open list queue. -}; - -// Helper function to allocate navmesh query class using Detour allocator. -dtNavMeshQuery* dtAllocNavMeshQuery(); -void dtFreeNavMeshQuery(dtNavMeshQuery* query); - -#endif // DETOURNAVMESHQUERY_H diff --git a/deps/recastnavigation/Detour/DetourObstacleAvoidance.cpp b/deps/recastnavigation/Detour/DetourObstacleAvoidance.cpp deleted file mode 100644 index a255c9b3fd..0000000000 --- a/deps/recastnavigation/Detour/DetourObstacleAvoidance.cpp +++ /dev/null @@ -1,532 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#include "DetourObstacleAvoidance.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include <string.h> -#include <math.h> -#include <float.h> -#include <new> - - -static int sweepCircleCircle(const float* c0, const float r0, const float* v, - const float* c1, const float r1, - float& tmin, float& tmax) -{ - static const float EPS = 0.0001f; - float s[3]; - dtVsub(s,c1,c0); - float r = r0+r1; - float c = dtVdot2D(s,s) - r*r; - float a = dtVdot2D(v,v); - if (a < EPS) return 0; // not moving - - // Overlap, calc time to exit. - float b = dtVdot2D(v,s); - float d = b*b - a*c; - if (d < 0.0f) return 0; // no intersection. - a = 1.0f / a; - const float rd = dtSqrt(d); - tmin = (b - rd) * a; - tmax = (b + rd) * a; - return 1; -} - -static int isectRaySeg(const float* ap, const float* u, - const float* bp, const float* bq, - float& t) -{ - float v[3], w[3]; - dtVsub(v,bq,bp); - dtVsub(w,ap,bp); - float d = dtVperp2D(u,v); - if (fabsf(d) < 1e-6f) return 0; - d = 1.0f/d; - t = dtVperp2D(v,w) * d; - if (t < 0 || t > 1) return 0; - float s = dtVperp2D(u,w) * d; - if (s < 0 || s > 1) return 0; - return 1; -} - - - -dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData() -{ - void* mem = dtAlloc(sizeof(dtObstacleAvoidanceDebugData), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtObstacleAvoidanceDebugData; -} - -void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr) -{ - if (!ptr) return; - ptr->~dtObstacleAvoidanceDebugData(); - dtFree(ptr); -} - - -dtObstacleAvoidanceDebugData::dtObstacleAvoidanceDebugData() : - m_nsamples(0), - m_maxSamples(0), - m_vel(0), - m_ssize(0), - m_pen(0), - m_vpen(0), - m_vcpen(0), - m_spen(0), - m_tpen(0) -{ -} - -dtObstacleAvoidanceDebugData::~dtObstacleAvoidanceDebugData() -{ - dtFree(m_vel); - dtFree(m_ssize); - dtFree(m_pen); - dtFree(m_vpen); - dtFree(m_vcpen); - dtFree(m_spen); - dtFree(m_tpen); -} - -bool dtObstacleAvoidanceDebugData::init(const int maxSamples) -{ - dtAssert(maxSamples); - m_maxSamples = maxSamples; - - m_vel = (float*)dtAlloc(sizeof(float)*3*m_maxSamples, DT_ALLOC_PERM); - if (!m_vel) - return false; - m_pen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_pen) - return false; - m_ssize = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_ssize) - return false; - m_vpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_vpen) - return false; - m_vcpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_vcpen) - return false; - m_spen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_spen) - return false; - m_tpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_tpen) - return false; - - return true; -} - -void dtObstacleAvoidanceDebugData::reset() -{ - m_nsamples = 0; -} - -void dtObstacleAvoidanceDebugData::addSample(const float* vel, const float ssize, const float pen, - const float vpen, const float vcpen, const float spen, const float tpen) -{ - if (m_nsamples >= m_maxSamples) - return; - dtAssert(m_vel); - dtAssert(m_ssize); - dtAssert(m_pen); - dtAssert(m_vpen); - dtAssert(m_vcpen); - dtAssert(m_spen); - dtAssert(m_tpen); - dtVcopy(&m_vel[m_nsamples*3], vel); - m_ssize[m_nsamples] = ssize; - m_pen[m_nsamples] = pen; - m_vpen[m_nsamples] = vpen; - m_vcpen[m_nsamples] = vcpen; - m_spen[m_nsamples] = spen; - m_tpen[m_nsamples] = tpen; - m_nsamples++; -} - -static void normalizeArray(float* arr, const int n) -{ - // Normalize penaly range. - float minPen = FLT_MAX; - float maxPen = -FLT_MAX; - for (int i = 0; i < n; ++i) - { - minPen = dtMin(minPen, arr[i]); - maxPen = dtMax(maxPen, arr[i]); - } - const float penRange = maxPen-minPen; - const float s = penRange > 0.001f ? (1.0f / penRange) : 1; - for (int i = 0; i < n; ++i) - arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f); -} - -void dtObstacleAvoidanceDebugData::normalizeSamples() -{ - normalizeArray(m_pen, m_nsamples); - normalizeArray(m_vpen, m_nsamples); - normalizeArray(m_vcpen, m_nsamples); - normalizeArray(m_spen, m_nsamples); - normalizeArray(m_tpen, m_nsamples); -} - - -dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery() -{ - void* mem = dtAlloc(sizeof(dtObstacleAvoidanceQuery), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtObstacleAvoidanceQuery; -} - -void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr) -{ - if (!ptr) return; - ptr->~dtObstacleAvoidanceQuery(); - dtFree(ptr); -} - - -dtObstacleAvoidanceQuery::dtObstacleAvoidanceQuery() : - m_velBias(0.0f), - m_weightDesVel(0.0f), - m_weightCurVel(0.0f), - m_weightSide(0.0f), - m_weightToi(0.0f), - m_horizTime(0.0f), - m_maxCircles(0), - m_circles(0), - m_ncircles(0), - m_maxSegments(0), - m_segments(0), - m_nsegments(0) -{ -} - -dtObstacleAvoidanceQuery::~dtObstacleAvoidanceQuery() -{ - dtFree(m_circles); - dtFree(m_segments); -} - -bool dtObstacleAvoidanceQuery::init(const int maxCircles, const int maxSegments) -{ - m_maxCircles = maxCircles; - m_ncircles = 0; - m_circles = (dtObstacleCircle*)dtAlloc(sizeof(dtObstacleCircle)*m_maxCircles, DT_ALLOC_PERM); - if (!m_circles) - return false; - memset(m_circles, 0, sizeof(dtObstacleCircle)*m_maxCircles); - - m_maxSegments = maxSegments; - m_nsegments = 0; - m_segments = (dtObstacleSegment*)dtAlloc(sizeof(dtObstacleSegment)*m_maxSegments, DT_ALLOC_PERM); - if (!m_segments) - return false; - memset(m_segments, 0, sizeof(dtObstacleSegment)*m_maxSegments); - - return true; -} - -void dtObstacleAvoidanceQuery::reset() -{ - m_ncircles = 0; - m_nsegments = 0; -} - -void dtObstacleAvoidanceQuery::addCircle(const float* pos, const float rad, - const float* vel, const float* dvel) -{ - if (m_ncircles >= m_maxCircles) - return; - - dtObstacleCircle* cir = &m_circles[m_ncircles++]; - dtVcopy(cir->p, pos); - cir->rad = rad; - dtVcopy(cir->vel, vel); - dtVcopy(cir->dvel, dvel); -} - -void dtObstacleAvoidanceQuery::addSegment(const float* p, const float* q) -{ - if (m_nsegments > m_maxSegments) - return; - - dtObstacleSegment* seg = &m_segments[m_nsegments++]; - dtVcopy(seg->p, p); - dtVcopy(seg->q, q); -} - -void dtObstacleAvoidanceQuery::prepare(const float* pos, const float* dvel) -{ - // Prepare obstacles - for (int i = 0; i < m_ncircles; ++i) - { - dtObstacleCircle* cir = &m_circles[i]; - - // Side - const float* pa = pos; - const float* pb = cir->p; - - const float orig[3] = {0,0}; - float dv[3]; - dtVsub(cir->dp,pb,pa); - dtVnormalize(cir->dp); - dtVsub(dv, cir->dvel, dvel); - - const float a = dtTriArea2D(orig, cir->dp,dv); - if (a < 0.01f) - { - cir->np[0] = -cir->dp[2]; - cir->np[2] = cir->dp[0]; - } - else - { - cir->np[0] = cir->dp[2]; - cir->np[2] = -cir->dp[0]; - } - } - - for (int i = 0; i < m_nsegments; ++i) - { - dtObstacleSegment* seg = &m_segments[i]; - - // Precalc if the agent is really close to the segment. - const float r = 0.01f; - float t; - seg->touch = dtDistancePtSegSqr2D(pos, seg->p, seg->q, t) < dtSqr(r); - } -} - -float dtObstacleAvoidanceQuery::processSample(const float* vcand, const float cs, - const float* pos, const float rad, - const float vmax, const float* vel, const float* dvel, - dtObstacleAvoidanceDebugData* debug) -{ - // Find min time of impact and exit amongst all obstacles. - float tmin = m_horizTime; - float side = 0; - int nside = 0; - - for (int i = 0; i < m_ncircles; ++i) - { - const dtObstacleCircle* cir = &m_circles[i]; - - // RVO - float vab[3]; - dtVscale(vab, vcand, 2); - dtVsub(vab, vab, vel); - dtVsub(vab, vab, cir->vel); - - // Side - side += dtClamp(dtMin(dtVdot2D(cir->dp,vab)*0.5f+0.5f, dtVdot2D(cir->np,vab)*2), 0.0f, 1.0f); - nside++; - - float htmin = 0, htmax = 0; - if (!sweepCircleCircle(pos,rad, vab, cir->p,cir->rad, htmin, htmax)) - continue; - - // Handle overlapping obstacles. - if (htmin < 0.0f && htmax > 0.0f) - { - // Avoid more when overlapped. - htmin = -htmin * 0.5f; - } - - if (htmin >= 0.0f) - { - // The closest obstacle is somewhere ahead of us, keep track of nearest obstacle. - if (htmin < tmin) - tmin = htmin; - } - } - - for (int i = 0; i < m_nsegments; ++i) - { - const dtObstacleSegment* seg = &m_segments[i]; - float htmin = 0; - - if (seg->touch) - { - // Special case when the agent is very close to the segment. - float sdir[3], snorm[3]; - dtVsub(sdir, seg->q, seg->p); - snorm[0] = -sdir[2]; - snorm[2] = sdir[0]; - // If the velocity is pointing towards the segment, no collision. - if (dtVdot2D(snorm, vcand) < 0.0f) - continue; - // Else immediate collision. - htmin = 0.0f; - } - else - { - if (!isectRaySeg(pos, vcand, seg->p, seg->q, htmin)) - continue; - } - - // Avoid less when facing walls. - htmin *= 2.0f; - - // The closest obstacle is somewhere ahead of us, keep track of nearest obstacle. - if (htmin < tmin) - tmin = htmin; - } - - // Normalize side bias, to prevent it dominating too much. - if (nside) - side /= nside; - - const float ivmax = 1.0f / vmax; - const float vpen = m_weightDesVel * (dtVdist2D(vcand, dvel) * ivmax); - const float vcpen = m_weightCurVel * (dtVdist2D(vcand, vel) * ivmax); - const float spen = m_weightSide * side; - const float tpen = m_weightToi * (1.0f/(0.1f+tmin / m_horizTime)); - - const float penalty = vpen + vcpen + spen + tpen; - - // Store different penalties for debug viewing - if (debug) - debug->addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen); - - return penalty; -} - -void dtObstacleAvoidanceQuery::sampleVelocityGrid(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, - float* nvel, const int gsize, - dtObstacleAvoidanceDebugData* debug) -{ - prepare(pos, dvel); - - dtVset(nvel, 0,0,0); - - if (debug) - debug->reset(); - - const float cvx = dvel[0] * m_velBias; - const float cvz = dvel[2] * m_velBias; - const float cs = vmax * 2 * (1 - m_velBias) / (float)(gsize-1); - const float half = (gsize-1)*cs*0.5f; - - float minPenalty = FLT_MAX; - - for (int y = 0; y < gsize; ++y) - { - for (int x = 0; x < gsize; ++x) - { - float vcand[3]; - vcand[0] = cvx + x*cs - half; - vcand[1] = 0; - vcand[2] = cvz + y*cs - half; - - if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+cs/2)) continue; - - const float penalty = processSample(vcand, cs, pos,rad,vmax,vel,dvel, debug); - if (penalty < minPenalty) - { - minPenalty = penalty; - dtVcopy(nvel, vcand); - } - } - } -} - - -static const float DT_PI = 3.14159265f; - -void dtObstacleAvoidanceQuery::sampleVelocityAdaptive(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const int ndivs, const int nrings, const int depth, - dtObstacleAvoidanceDebugData* debug) -{ - prepare(pos, dvel); - - dtVset(nvel, 0,0,0); - - if (debug) - debug->reset(); - - // Build sampling pattern aligned to desired velocity. - static const int MAX_PATTERN_DIVS = 32; - static const int MAX_PATTERN_RINGS = 4; - float pat[(MAX_PATTERN_DIVS*MAX_PATTERN_RINGS+1)*2]; - int npat = 0; - - const int nd = dtClamp(ndivs, 1, MAX_PATTERN_DIVS); - const int nr = dtClamp(nrings, 1, MAX_PATTERN_RINGS); - const float da = (1.0f/nd) * DT_PI*2; - const float dang = atan2f(dvel[2], dvel[0]); - - // Always add sample at zero - pat[npat*2+0] = 0; - pat[npat*2+1] = 0; - npat++; - - for (int j = 0; j < nr; ++j) - { - const float rad = (float)(nr-j)/(float)nr; - float a = dang + (j&1)*0.5f*da; - for (int i = 0; i < nd; ++i) - { - pat[npat*2+0] = cosf(a)*rad; - pat[npat*2+1] = sinf(a)*rad; - npat++; - a += da; - } - } - - // Start sampling. - float cr = vmax * (1.0f-m_velBias); - float res[3]; - dtVset(res, dvel[0] * m_velBias, 0, dvel[2] * m_velBias); - - for (int k = 0; k < depth; ++k) - { - float minPenalty = FLT_MAX; - float bvel[3]; - dtVset(bvel, 0,0,0); - - for (int i = 0; i < npat; ++i) - { - float vcand[3]; - vcand[0] = res[0] + pat[i*2+0]*cr; - vcand[1] = 0; - vcand[2] = res[2] + pat[i*2+1]*cr; - - if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+0.001f)) continue; - - const float penalty = processSample(vcand,cr/10, pos,rad,vmax,vel,dvel, debug); - if (penalty < minPenalty) - { - minPenalty = penalty; - dtVcopy(bvel, vcand); - } - } - - dtVcopy(res, bvel); - - cr *= 0.5f; - } - - dtVcopy(nvel, res); -} - diff --git a/deps/recastnavigation/Detour/DetourObstacleAvoidance.h b/deps/recastnavigation/Detour/DetourObstacleAvoidance.h deleted file mode 100644 index 4a7187a799..0000000000 --- a/deps/recastnavigation/Detour/DetourObstacleAvoidance.h +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef DETOUROBSTACLEAVOIDANCE_H -#define DETOUROBSTACLEAVOIDANCE_H - -struct dtObstacleCircle -{ - float p[3]; // Position of the obstacle - float vel[3]; // Velocity of the obstacle - float dvel[3]; // Velocity of the obstacle - float rad; // Radius of the obstacle - float dp[3], np[3]; // Use for side selection during sampling. -}; - -struct dtObstacleSegment -{ - float p[3], q[3]; // End points of the obstacle segment - bool touch; -}; - -static const int RVO_SAMPLE_RAD = 15; -static const int MAX_RVO_SAMPLES = (RVO_SAMPLE_RAD*2+1)*(RVO_SAMPLE_RAD*2+1) + 100; - -class dtObstacleAvoidanceDebugData -{ -public: - dtObstacleAvoidanceDebugData(); - ~dtObstacleAvoidanceDebugData(); - - bool init(const int maxSamples); - void reset(); - void addSample(const float* vel, const float ssize, const float pen, - const float vpen, const float vcpen, const float spen, const float tpen); - - void normalizeSamples(); - - inline int getSampleCount() const { return m_nsamples; } - inline const float* getSampleVelocity(const int i) const { return &m_vel[i*3]; } - inline float getSampleSize(const int i) const { return m_ssize[i]; } - inline float getSamplePenalty(const int i) const { return m_pen[i]; } - inline float getSampleDesiredVelocityPenalty(const int i) const { return m_vpen[i]; } - inline float getSampleCurrentVelocityPenalty(const int i) const { return m_vcpen[i]; } - inline float getSamplePreferredSidePenalty(const int i) const { return m_spen[i]; } - inline float getSampleCollisionTimePenalty(const int i) const { return m_tpen[i]; } - -private: - int m_nsamples; - int m_maxSamples; - float* m_vel; - float* m_ssize; - float* m_pen; - float* m_vpen; - float* m_vcpen; - float* m_spen; - float* m_tpen; -}; - -dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData(); -void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr); - - -class dtObstacleAvoidanceQuery -{ -public: - dtObstacleAvoidanceQuery(); - ~dtObstacleAvoidanceQuery(); - - bool init(const int maxCircles, const int maxSegments); - - void reset(); - - void addCircle(const float* pos, const float rad, - const float* vel, const float* dvel); - - void addSegment(const float* p, const float* q); - - inline void setVelocitySelectionBias(float v) { m_velBias = v; } - inline void setDesiredVelocityWeight(float w) { m_weightDesVel = w; } - inline void setCurrentVelocityWeight(float w) { m_weightCurVel = w; } - inline void setPreferredSideWeight(float w) { m_weightSide = w; } - inline void setCollisionTimeWeight(float w) { m_weightToi = w; } - inline void setTimeHorizon(float t) { m_horizTime = t; } - - void sampleVelocityGrid(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const int gsize, - dtObstacleAvoidanceDebugData* debug = 0); - - void sampleVelocityAdaptive(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const int ndivs, const int nrings, const int depth, - dtObstacleAvoidanceDebugData* debug = 0); - - inline int getObstacleCircleCount() const { return m_ncircles; } - const dtObstacleCircle* getObstacleCircle(const int i) { return &m_circles[i]; } - - inline int getObstacleSegmentCount() const { return m_nsegments; } - const dtObstacleSegment* getObstacleSegment(const int i) { return &m_segments[i]; } - -private: - - void prepare(const float* pos, const float* dvel); - - float processSample(const float* vcand, const float cs, - const float* pos, const float rad, - const float vmax, const float* vel, const float* dvel, - dtObstacleAvoidanceDebugData* debug); - - dtObstacleCircle* insertCircle(const float dist); - dtObstacleSegment* insertSegment(const float dist); - - float m_velBias; - float m_weightDesVel; - float m_weightCurVel; - float m_weightSide; - float m_weightToi; - float m_horizTime; - - int m_maxCircles; - dtObstacleCircle* m_circles; - int m_ncircles; - - int m_maxSegments; - dtObstacleSegment* m_segments; - int m_nsegments; -}; - -dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery(); -void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr); - - -#endif // DETOUROBSTACLEAVOIDANCE_H
\ No newline at end of file diff --git a/deps/recastnavigation/Readme.txt b/deps/recastnavigation/Readme.txt deleted file mode 100644 index 0c2f7b1675..0000000000 --- a/deps/recastnavigation/Readme.txt +++ /dev/null @@ -1,120 +0,0 @@ - -Recast & Detour Version 1.4 - - -Recast - -Recast is state of the art navigation mesh construction toolset for games. - - * It is automatic, which means that you can throw any level geometry - at it and you will get robust mesh out - * It is fast which means swift turnaround times for level designers - * It is open source so it comes with full source and you can - customize it to your hearts content. - -The Recast process starts with constructing a voxel mold from a level geometry -and then casting a navigation mesh over it. The process consists of three steps, -building the voxel mold, partitioning the mold into simple regions, peeling off -the regions as simple polygons. - - 1. The voxel mold is build from the input triangle mesh by rasterizing - the triangles into a multi-layer heightfield. Some simple filters are - then applied to the mold to prune out locations where the character - would not be able to move. - 2. The walkable areas described by the mold are divided into simple - overlayed 2D regions. The resulting regions have only one non-overlapping - contour, which simplifies the final step of the process tremendously. - 3. The navigation polygons are peeled off from the regions by first tracing - the boundaries and then simplifying them. The resulting polygons are - finally converted to convex polygons which makes them perfect for - pathfinding and spatial reasoning about the level. - -The toolset code is located in the Recast folder and demo application using the Recast -toolset is located in the RecastDemo folder. - -The project files with this distribution can be compiled with Microsoft Visual C++ 2008 -(you can download it for free) and XCode 3.1. - - -Detour - -Recast is accompanied with Detour, path-finding and spatial reasoning toolkit. You can use any navigation mesh with Detour, but of course the data generated with Recast fits perfectly. - -Detour offers simple static navigation mesh which is suitable for many simple cases, as well as tiled navigation mesh which allows you to plug in and out pieces of the mesh. The tiled mesh allows to create systems where you stream new navigation data in and out as the player progresses the level, or you may regenerate tiles as the world changes. - - -Latest code available at http://code.google.com/p/recastnavigation/ - - --- - -Release Notes - ----------------- -* Recast 1.4 - Released August 24th, 2009 - -- Added detail height mesh generation (RecastDetailMesh.cpp) for single, - tiled statmeshes as well as tilemesh. -- Added feature to contour tracing which detects extra vertices along - tile edges which should be removed later. -- Changed the tiled stat mesh preprocess, so that it first generated - polymeshes per tile and finally combines them. -- Fixed bug in the GUI code where invisible buttons could be pressed. - ----------------- -* Recast 1.31 - Released July 24th, 2009 - -- Better cost and heuristic functions. -- Fixed tile navmesh raycast on tile borders. - ----------------- -* Recast 1.3 - Released July 14th, 2009 - -- Added dtTileNavMesh which allows to dynamically add and remove navmesh pieces at runtime. -- Renamed stat navmesh types to dtStat* (i.e. dtPoly is now dtStatPoly). -- Moved common code used by tile and stat navmesh to DetourNode.h/cpp and DetourCommon.h/cpp. -- Refactores the demo code. - ----------------- -* Recast 1.2 - Released June 17th, 2009 - -- Added tiled mesh generation. The tiled generation allows to generate navigation for - much larger worlds, it removes some of the artifacts that comes from distance fields - in open areas, and allows later streaming and dynamic runtime generation -- Improved and added some debug draw modes -- API change: The helper function rcBuildNavMesh does not exists anymore, - had to change few internal things to cope with the tiled processing, - similar API functionality will be added later once the tiled process matures -- The demo is getting way too complicated, need to split demos -- Fixed several filtering functions so that the mesh is tighter to the geometry, - sometimes there could be up error up to tow voxel units close to walls, - now it should be just one. - ----------------- -* Recast 1.1 - Released April 11th, 2009 - -This is the first release of Detour. - ----------------- -* Recast 1.0 - Released March 29th, 2009 - -This is the first release of Recast. - -The process is not always as robust as I would wish. The watershed phase sometimes swallows tiny islands -which are close to edges. These droppings are handled in rcBuildContours, but the code is not -particularly robust either. - -Another non-robust case is when portal contours (contours shared between two regions) are always -assumed to be straight. That can lead to overlapping contours specially when the level has -large open areas. - - - -Mikko Mononen -memon@inside.org diff --git a/deps/recastnavigation/Recast/CMakeLists.txt b/deps/recastnavigation/Recast/CMakeLists.txt index 975b4a9c14..30265cb7e4 100644 --- a/deps/recastnavigation/Recast/CMakeLists.txt +++ b/deps/recastnavigation/Recast/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without @@ -9,15 +9,16 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. set(Recast_STAT_SRCS - Recast.cpp - RecastAlloc.cpp - RecastArea.cpp - RecastContour.cpp - RecastFilter.cpp - RecastMesh.cpp - RecastMeshDetail.cpp - RecastRasterization.cpp - RecastRegion.cpp + Source/Recast.cpp + Source/RecastAlloc.cpp + Source/RecastArea.cpp + Source/RecastContour.cpp + Source/RecastFilter.cpp + Source/RecastLayers.cpp + Source/RecastMesh.cpp + Source/RecastMeshDetail.cpp + Source/RecastRasterization.cpp + Source/RecastRegion.cpp ) if(WIN32) @@ -28,4 +29,15 @@ endif() add_library(Recast STATIC ${Recast_STAT_SRCS}) -target_link_libraries(Recast ${ZLIB_LIBRARIES}) +target_include_directories(Recast + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/Include) + +target_link_libraries(Recast + PUBLIC + zlib) + +set_target_properties(Recast + PROPERTIES + FOLDER + "dep") diff --git a/deps/recastnavigation/Recast/Recast.h b/deps/recastnavigation/Recast/Recast.h deleted file mode 100644 index 0e5f074248..0000000000 --- a/deps/recastnavigation/Recast/Recast.h +++ /dev/null @@ -1,688 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef RECAST_H -#define RECAST_H - -// Some math headers don't have PI defined. -static const float RC_PI = 3.14159265f; - -enum rcLogCategory -{ - RC_LOG_PROGRESS = 1, - RC_LOG_WARNING, - RC_LOG_ERROR, -}; - -enum rcTimerLabel -{ - RC_TIMER_TOTAL, - RC_TIMER_TEMP, - RC_TIMER_RASTERIZE_TRIANGLES, - RC_TIMER_BUILD_COMPACTHEIGHTFIELD, - RC_TIMER_BUILD_CONTOURS, - RC_TIMER_BUILD_CONTOURS_TRACE, - RC_TIMER_BUILD_CONTOURS_SIMPLIFY, - RC_TIMER_FILTER_BORDER, - RC_TIMER_FILTER_WALKABLE, - RC_TIMER_MEDIAN_AREA, - RC_TIMER_FILTER_LOW_OBSTACLES, - RC_TIMER_BUILD_POLYMESH, - RC_TIMER_MERGE_POLYMESH, - RC_TIMER_ERODE_AREA, - RC_TIMER_MARK_BOX_AREA, - RC_TIMER_MARK_CONVEXPOLY_AREA, - RC_TIMER_BUILD_DISTANCEFIELD, - RC_TIMER_BUILD_DISTANCEFIELD_DIST, - RC_TIMER_BUILD_DISTANCEFIELD_BLUR, - RC_TIMER_BUILD_REGIONS, - RC_TIMER_BUILD_REGIONS_WATERSHED, - RC_TIMER_BUILD_REGIONS_EXPAND, - RC_TIMER_BUILD_REGIONS_FLOOD, - RC_TIMER_BUILD_REGIONS_FILTER, - RC_TIMER_BUILD_POLYMESHDETAIL, - RC_TIMER_MERGE_POLYMESHDETAIL, - RC_MAX_TIMERS -}; - -// Build context provides several optional utilities needed for the build process, -// such as timing, logging, and build time collecting. -class rcContext -{ -public: - inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {} - virtual ~rcContext() {} - - // Enables or disables logging. - inline void enableLog(bool state) { m_logEnabled = state; } - // Resets log. - inline void resetLog() { if (m_logEnabled) doResetLog(); } - // Logs a message. - void log(const rcLogCategory category, const char* format, ...); - - // Enables or disables timer. - inline void enableTimer(bool state) { m_timerEnabled = state; } - // Resets all timers. - inline void resetTimers() { if (m_timerEnabled) doResetTimers(); } - // Starts timer, used for performance timing. - inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); } - // Stops timer, used for performance timing. - inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); } - // Returns time accumulated between timer start/stop. - inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; } - -protected: - // Virtual functions to override for custom implementations. - virtual void doResetLog() {} - virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {} - virtual void doResetTimers() {} - virtual void doStartTimer(const rcTimerLabel /*label*/) {} - virtual void doStopTimer(const rcTimerLabel /*label*/) {} - virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; } - - bool m_logEnabled; - bool m_timerEnabled; -}; - - -// The units of the parameters are specified in parenthesis as follows: -// (vx) voxels, (wu) world units -struct rcConfig -{ - int width, height; // Dimensions of the rasterized heightfield (vx) - int tileSize; // Width and Height of a tile (vx) - int borderSize; // Non-navigable Border around the heightfield (vx) - float cs, ch; // Grid cell size and height (wu) - float bmin[3], bmax[3]; // Grid bounds (wu) - float walkableSlopeAngle; // Maximum walkable slope angle in degrees. - int walkableHeight; // Minimum height where the agent can still walk (vx) - int walkableClimb; // Maximum height between grid cells the agent can climb (vx) - int walkableRadius; // Radius of the agent in cells (vx) - int maxEdgeLen; // Maximum contour edge length (vx) - float maxSimplificationError; // Maximum distance error from contour to cells (vx) - int minRegionArea; // Regions whose area is smaller than this threshold will be removed. (vx) - int mergeRegionArea; // Regions whose area is smaller than this threshold will be merged (vx) - int maxVertsPerPoly; // Max number of vertices per polygon - float detailSampleDist; // Detail mesh sample spacing. - float detailSampleMaxError; // Detail mesh simplification max sample error. -}; - -// Define number of bits in the above structure for smin/smax. -// The max height is used for clamping rasterized values. -static const int RC_SPAN_HEIGHT_BITS = 16; -static const int RC_SPAN_MAX_HEIGHT = (1<<RC_SPAN_HEIGHT_BITS)-1; - -// Heightfield span. -struct rcSpan -{ - unsigned int smin : 16; // Span min height. - unsigned int smax : 16; // Span max height. - unsigned char area; // Span area type. - rcSpan* next; // Next span in column. -}; - -// Number of spans allocated per pool. -static const int RC_SPANS_PER_POOL = 2048; - -// Memory pool used for quick span allocation. -struct rcSpanPool -{ - rcSpanPool* next; // Pointer to next pool. - rcSpan items[RC_SPANS_PER_POOL]; // Array of spans. -}; - -// Dynamic span-heightfield. -struct rcHeightfield -{ - int width, height; // Dimension of the heightfield. - float bmin[3], bmax[3]; // Bounding box of the heightfield - float cs, ch; // Cell size and height. - rcSpan** spans; // Heightfield of spans (width*height). - rcSpanPool* pools; // Linked list of span pools. - rcSpan* freelist; // Pointer to next free span. -}; - -rcHeightfield* rcAllocHeightfield(); -void rcFreeHeightField(rcHeightfield* hf); - - -struct rcCompactCell -{ - unsigned int index : 24; // Index to first span in column. - unsigned int count : 8; // Number of spans in this column. -}; - -struct rcCompactSpan -{ - unsigned short y; // Bottom coordinate of the span. - unsigned short reg; - unsigned int con : 24; // Connections to neighbour cells. - unsigned int h : 8; // Height of the span. -}; - -// Compact static heightfield. -struct rcCompactHeightfield -{ - int width, height; // Width and height of the heightfield. - int spanCount; // Number of spans in the heightfield. - int walkableHeight, walkableClimb; // Agent properties. - unsigned short maxDistance; // Maximum distance value stored in heightfield. - unsigned short maxRegions; // Maximum Region Id stored in heightfield. - float bmin[3], bmax[3]; // Bounding box of the heightfield. - float cs, ch; // Cell size and height. - rcCompactCell* cells; // Pointer to width*height cells. - rcCompactSpan* spans; // Pointer to spans. - unsigned short* dist; // Pointer to per span distance to border. - unsigned char* areas; // Pointer to per span area ID. -}; - -rcCompactHeightfield* rcAllocCompactHeightfield(); -void rcFreeCompactHeightfield(rcCompactHeightfield* chf); - - -struct rcContour -{ - int* verts; // Vertex coordinates, each vertex contains 4 components. - int nverts; // Number of vertices. - int* rverts; // Raw vertex coordinates, each vertex contains 4 components. - int nrverts; // Number of raw vertices. - unsigned short reg; // Region ID of the contour. - unsigned char area; // Area ID of the contour. -}; - -struct rcContourSet -{ - rcContour* conts; // Pointer to all contours. - int nconts; // Number of contours. - float bmin[3], bmax[3]; // Bounding box of the heightfield. - float cs, ch; // Cell size and height. -}; - -rcContourSet* rcAllocContourSet(); -void rcFreeContourSet(rcContourSet* cset); - - -// Polymesh store a connected mesh of polygons. -// The polygons are store in an array where each polygons takes -// 'nvp*2' elements. The first 'nvp' elements are indices to vertices -// and the second 'nvp' elements are indices to neighbour polygons. -// If a polygon has less than 'bvp' vertices, the remaining indices -// are set to RC_MESH_NULL_IDX. If an polygon edge does not have a neighbour -// the neighbour index is set to RC_MESH_NULL_IDX. -// Vertices can be transformed into world space as follows: -// x = bmin[0] + verts[i*3+0]*cs; -// y = bmin[1] + verts[i*3+1]*ch; -// z = bmin[2] + verts[i*3+2]*cs; -struct rcPolyMesh -{ - unsigned short* verts; // Vertices of the mesh, 3 elements per vertex. - unsigned short* polys; // Polygons of the mesh, nvp*2 elements per polygon. - unsigned short* regs; // Region ID of the polygons. - unsigned short* flags; // Per polygon flags. - unsigned char* areas; // Area ID of polygons. - int nverts; // Number of vertices. - int npolys; // Number of polygons. - int maxpolys; // Number of allocated polygons. - int nvp; // Max number of vertices per polygon. - float bmin[3], bmax[3]; // Bounding box of the mesh. - float cs, ch; // Cell size and height. -}; - -rcPolyMesh* rcAllocPolyMesh(); -void rcFreePolyMesh(rcPolyMesh* pmesh); - - -// Detail mesh generated from a rcPolyMesh. -// Each submesh represents a polygon in the polymesh and they are stored in -// exactly same order. Each submesh is described as 4 values: -// base vertex, vertex count, base triangle, triangle count. That is, -// const unsigned char* t = &dmesh.tris[(tbase+i)*3]; and -// const float* v = &dmesh.verts[(vbase+t[j])*3]; -// If the input polygon has 'n' vertices, those vertices are first in the -// submesh vertex list. This allows to compres the mesh by not storing the -// first vertices and using the polymesh vertices instead. -// Max number of vertices per submesh is 127 and -// max number of triangles per submesh is 255. - -struct rcPolyMeshDetail -{ - unsigned int* meshes; // Pointer to all mesh data. - float* verts; // Pointer to all vertex data. - unsigned char* tris; // Pointer to all triangle data. - int nmeshes; // Number of meshes. - int nverts; // Number of total vertices. - int ntris; // Number of triangles. -}; - -rcPolyMeshDetail* rcAllocPolyMeshDetail(); -void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh); - - -// If heightfield region ID has the following bit set, the region is on border area -// and excluded from many calculations. -static const unsigned short RC_BORDER_REG = 0x8000; - -// If contour region ID has the following bit set, the vertex will be later -// removed in order to match the segments and vertices at tile boundaries. -static const int RC_BORDER_VERTEX = 0x10000; - -static const int RC_AREA_BORDER = 0x20000; - -enum rcBuildContoursFlags -{ - RC_CONTOUR_TESS_WALL_EDGES = 0x01, // Tessellate wall edges - RC_CONTOUR_TESS_AREA_EDGES = 0x02, // Tessellate edges between areas. -}; - -// Mask used with contours to extract region id. -static const int RC_CONTOUR_REG_MASK = 0xffff; - -// Null index which is used with meshes to mark unset or invalid indices. -static const unsigned short RC_MESH_NULL_IDX = 0xffff; - -// Area ID that is considered empty. -static const unsigned char RC_NULL_AREA = 0; - -// Area ID that is considered generally walkable. -static const unsigned char RC_WALKABLE_AREA = 63; - -// Value returned by rcGetCon() if the direction is not connected. -static const int RC_NOT_CONNECTED = 0x3f; - -// Compact span neighbour helpers. -inline void rcSetCon(rcCompactSpan& s, int dir, int i) -{ - const unsigned int shift = (unsigned int)dir*6; - unsigned int con = s.con; - s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift); -} - -inline int rcGetCon(const rcCompactSpan& s, int dir) -{ - const unsigned int shift = (unsigned int)dir*6; - return (s.con >> shift) & 0x3f; -} - -inline int rcGetDirOffsetX(int dir) -{ - const int offset[4] = { -1, 0, 1, 0, }; - return offset[dir&0x03]; -} - -inline int rcGetDirOffsetY(int dir) -{ - const int offset[4] = { 0, 1, 0, -1 }; - return offset[dir&0x03]; -} - -// Common helper functions -template<class T> inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; } -template<class T> inline T rcMin(T a, T b) { return a < b ? a : b; } -template<class T> inline T rcMax(T a, T b) { return a > b ? a : b; } -template<class T> inline T rcAbs(T a) { return a < 0 ? -a : a; } -template<class T> inline T rcSqr(T a) { return a*a; } -template<class T> inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } -float rcSqrt(float x); - -// Common vector helper functions. -inline void rcVcross(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; - dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; - dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -inline float rcVdot(const float* v1, const float* v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -inline void rcVmad(float* dest, const float* v1, const float* v2, const float s) -{ - dest[0] = v1[0]+v2[0]*s; - dest[1] = v1[1]+v2[1]*s; - dest[2] = v1[2]+v2[2]*s; -} - -inline void rcVadd(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]+v2[0]; - dest[1] = v1[1]+v2[1]; - dest[2] = v1[2]+v2[2]; -} - -inline void rcVsub(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]-v2[0]; - dest[1] = v1[1]-v2[1]; - dest[2] = v1[2]-v2[2]; -} - -inline void rcVmin(float* mn, const float* v) -{ - mn[0] = rcMin(mn[0], v[0]); - mn[1] = rcMin(mn[1], v[1]); - mn[2] = rcMin(mn[2], v[2]); -} - -inline void rcVmax(float* mx, const float* v) -{ - mx[0] = rcMax(mx[0], v[0]); - mx[1] = rcMax(mx[1], v[1]); - mx[2] = rcMax(mx[2], v[2]); -} - -inline void rcVcopy(float* dest, const float* v) -{ - dest[0] = v[0]; - dest[1] = v[1]; - dest[2] = v[2]; -} - -inline float rcVdist(const float* v1, const float* v2) -{ - float dx = v2[0] - v1[0]; - float dy = v2[1] - v1[1]; - float dz = v2[2] - v1[2]; - return rcSqrt(dx*dx + dy*dy + dz*dz); -} - -inline float rcVdistSqr(const float* v1, const float* v2) -{ - float dx = v2[0] - v1[0]; - float dy = v2[1] - v1[1]; - float dz = v2[2] - v1[2]; - return dx*dx + dy*dy + dz*dz; -} - -inline void rcVnormalize(float* v) -{ - float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2])); - v[0] *= d; - v[1] *= d; - v[2] *= d; -} - -inline bool rcVequal(const float* p0, const float* p1) -{ - static const float thr = rcSqr(1.0f/16384.0f); - const float d = rcVdistSqr(p0, p1); - return d < thr; -} - -// Calculated bounding box of array of vertices. -// Params: -// verts - (in) array of vertices -// nv - (in) vertex count -// bmin, bmax - (out) bounding box -void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax); - -// Calculates grid size based on bounding box and grid cell size. -// Params: -// bmin, bmax - (in) bounding box -// cs - (in) grid cell size -// w - (out) grid width -// h - (out) grid height -void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h); - -// Creates and initializes new heightfield. -// Params: -// hf - (in/out) heightfield to initialize. -// width - (in) width of the heightfield. -// height - (in) height of the heightfield. -// bmin, bmax - (in) bounding box of the heightfield -// cs - (in) grid cell size -// ch - (in) grid cell height -bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, - const float* bmin, const float* bmax, - float cs, float ch); - -// Sets the RC_WALKABLE_AREA for every triangle whose slope is below -// the maximum walkable slope angle. -// Params: -// walkableSlopeAngle - (in) maximum slope angle in degrees. -// verts - (in) array of vertices -// nv - (in) vertex count -// tris - (in) array of triangle vertex indices -// nt - (in) triangle count -// areas - (out) array of triangle area types -void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, - const int* tris, int nt, unsigned char* areas); - -// Sets the RC_NULL_AREA for every triangle whose slope is steeper than -// the maximum walkable slope angle. -// Params: -// walkableSlopeAngle - (in) maximum slope angle in degrees. -// verts - (in) array of vertices -// nv - (in) vertex count -// tris - (in) array of triangle vertex indices -// nt - (in) triangle count -// areas - (out) array of triangle are types -void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, - const int* tris, int nt, unsigned char* areas); - -// Adds span to heightfield. -// The span addition can set to favor flags. If the span is merged to -// another span and the new smax is within 'flagMergeThr' units away -// from the existing span the span flags are merged and stored. -// Params: -// solid - (in) heightfield where the spans is added to -// x,y - (in) location on the heightfield where the span is added -// smin,smax - (in) spans min/max height -// flags - (in) span flags (zero or WALKABLE) -// flagMergeThr - (in) merge threshold. -void rcAddSpan(rcContext* ctx, rcHeightfield& solid, const int x, const int y, - const unsigned short smin, const unsigned short smax, - const unsigned short area, const int flagMergeThr); - -// Rasterizes a triangle into heightfield spans. -// Params: -// v0,v1,v2 - (in) the vertices of the triangle. -// area - (in) area type of the triangle. -// solid - (in) heightfield where the triangle is rasterized -// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable. -void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, - const unsigned char area, rcHeightfield& solid, - const int flagMergeThr = 1); - -// Rasterizes indexed triangle mesh into heightfield spans. -// Params: -// verts - (in) array of vertices -// nv - (in) vertex count -// tris - (in) array of triangle vertex indices -// area - (in) array of triangle area types. -// nt - (in) triangle count -// solid - (in) heightfield where the triangles are rasterized -// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable. -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, - const int* tris, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr = 1); - -// Rasterizes indexed triangle mesh into heightfield spans. -// Params: -// verts - (in) array of vertices -// nv - (in) vertex count -// tris - (in) array of triangle vertex indices -// area - (in) array of triangle area types. -// nt - (in) triangle count -// solid - (in) heightfield where the triangles are rasterized -// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable. -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, - const unsigned short* tris, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr = 1); - -// Rasterizes the triangles into heightfield spans. -// Params: -// verts - (in) array of vertices -// area - (in) array of triangle area types. -// nt - (in) triangle count -// solid - (in) heightfield where the triangles are rasterized -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr = 1); - -// Marks non-walkable low obstacles as walkable if they are closer than walkableClimb -// from a walkable surface. Applying this filter allows to step over low hanging -// low obstacles. -// Params: -// walkableHeight - (in) minimum height where the agent can still walk -// solid - (in/out) heightfield describing the solid space -// TODO: Missuses ledge flag, must be called before rcFilterLedgeSpans! -void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid); - -// Removes WALKABLE flag from all spans that are at ledges. This filtering -// removes possible overestimation of the conservative voxelization so that -// the resulting mesh will not have regions hanging in air over ledges. -// Params: -// walkableHeight - (in) minimum height where the agent can still walk -// walkableClimb - (in) maximum height between grid cells the agent can climb -// solid - (in/out) heightfield describing the solid space -void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, - const int walkableClimb, rcHeightfield& solid); - -// Removes WALKABLE flag from all spans which have smaller than -// 'walkableHeight' clearance above them. -// Params: -// walkableHeight - (in) minimum height where the agent can still walk -// solid - (in/out) heightfield describing the solid space -void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid); - -// Returns number of spans contained in a heightfield. -// Params: -// hf - (in) heightfield to be compacted -// Returns number of spans. -int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); - -// Builds compact representation of the heightfield. -// Params: -// walkableHeight - (in) minimum height where the agent can still walk -// walkableClimb - (in) maximum height between grid cells the agent can climb -// flags - (in) require flags for a cell to be included in the compact heightfield. -// hf - (in) heightfield to be compacted -// chf - (out) compact heightfield representing the open space. -// Returns false if operation ran out of memory. -bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, - rcHeightfield& hf, rcCompactHeightfield& chf); - -// Erodes walkable area. -// Params: -// radius - (in) radius of erosion (max 255). -// chf - (in/out) compact heightfield to erode. -// Returns false if operation ran out of memory. -bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf); - -// Applies median filter to walkable area types, removing noise. -// Params: -// chf - (in/out) compact heightfield to erode. -// Returns false if operation ran out of memory. -bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); - -// Marks the area of the convex polygon into the area type of the compact heightfield. -// Params: -// bmin/bmax - (in) bounds of the axis aligned box. -// areaId - (in) area ID to mark. -// chf - (in/out) compact heightfield to mark. -void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, - rcCompactHeightfield& chf); - -// Marks the area of the convex polygon into the area type of the compact heightfield. -// Params: -// verts - (in) vertices of the convex polygon. -// nverts - (in) number of vertices in the polygon. -// hmin/hmax - (in) min and max height of the polygon. -// areaId - (in) area ID to mark. -// chf - (in/out) compact heightfield to mark. -void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, - const float hmin, const float hmax, unsigned char areaId, - rcCompactHeightfield& chf); - -// Builds distance field and stores it into the combat heightfield. -// Params: -// chf - (in/out) compact heightfield representing the open space. -// Returns false if operation ran out of memory. -bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf); - -// Divides the walkable heighfied into simple regions using watershed partitioning. -// Each region has only one contour and no overlaps. -// The regions are stored in the compact heightfield 'reg' field. -// The process sometimes creates small regions. If the area of a regions is -// smaller than 'mergeRegionArea' then the region will be merged with a neighbour -// region if possible. If multiple regions form an area which is smaller than -// 'minRegionArea' all the regions belonging to that area will be removed. -// Here area means the count of spans in an area. -// Params: -// chf - (in/out) compact heightfield representing the open space. -// minRegionArea - (in) the smallest allowed region area. -// maxMergeRegionArea - (in) the largest allowed region area which can be merged. -// Returns false if operation ran out of memory. -bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int minRegionArea, const int mergeRegionArea); - -// Divides the walkable heighfied into simple regions using simple monotone partitioning. -// Each region has only one contour and no overlaps. -// The regions are stored in the compact heightfield 'reg' field. -// The process sometimes creates small regions. If the area of a regions is -// smaller than 'mergeRegionArea' then the region will be merged with a neighbour -// region if possible. If multiple regions form an area which is smaller than -// 'minRegionArea' all the regions belonging to that area will be removed. -// Here area means the count of spans in an area. -// Params: -// chf - (in/out) compact heightfield representing the open space. -// minRegionArea - (in) the smallest allowed regions size. -// maxMergeRegionArea - (in) the largest allowed regions size which can be merged. -// Returns false if operation ran out of memory. -bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int minRegionArea, const int mergeRegionArea); - -// Builds simplified contours from the regions outlines. -// Params: -// chf - (in) compact heightfield which has regions set. -// maxError - (in) maximum allowed distance between simplified contour and cells. -// maxEdgeLen - (in) maximum allowed contour edge length in cells. -// cset - (out) Resulting contour set. -// flags - (in) build flags, see rcBuildContoursFlags. -// Returns false if operation ran out of memory. -bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, - const float maxError, const int maxEdgeLen, - rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES); - -// Builds connected convex polygon mesh from contour polygons. -// Params: -// cset - (in) contour set. -// nvp - (in) maximum number of vertices per polygon. -// mesh - (out) poly mesh. -// Returns false if operation ran out of memory. -bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh); - -bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); - -// Builds detail triangle mesh for each polygon in the poly mesh. -// Params: -// mesh - (in) poly mesh to detail. -// chf - (in) compact height field, used to query height for new vertices. -// sampleDist - (in) spacing between height samples used to generate more detail into mesh. -// sampleMaxError - (in) maximum allowed distance between simplified detail mesh and height sample. -// pmdtl - (out) detail mesh. -// Returns false if operation ran out of memory. -bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, - const float sampleDist, const float sampleMaxError, - rcPolyMeshDetail& dmesh); - -bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); - - -#endif // RECAST_H diff --git a/deps/recastnavigation/Recast/RecastAlloc.h b/deps/recastnavigation/Recast/RecastAlloc.h deleted file mode 100644 index 9a316374a7..0000000000 --- a/deps/recastnavigation/Recast/RecastAlloc.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// - -#ifndef RECASTALLOC_H -#define RECASTALLOC_H - -enum rcAllocHint -{ - RC_ALLOC_PERM, // Memory persist after a function call. - RC_ALLOC_TEMP // Memory used temporarily within a function. -}; - -typedef void* (rcAllocFunc)(int size, rcAllocHint hint); -typedef void (rcFreeFunc)(void* ptr); - -void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc); - -void* rcAlloc(int size, rcAllocHint hint); -void rcFree(void* ptr); - - - -// Simple dynamic array ints. -class rcIntArray -{ - int* m_data; - int m_size, m_cap; - inline rcIntArray(const rcIntArray&); - inline rcIntArray& operator=(const rcIntArray&); -public: - inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {} - inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); } - inline ~rcIntArray() { rcFree(m_data); } - void resize(int n); - inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; } - inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; } - inline const int& operator[](int i) const { return m_data[i]; } - inline int& operator[](int i) { return m_data[i]; } - inline int size() const { return m_size; } -}; - -// Simple internal helper class to delete array in scope -template<class T> class rcScopedDelete -{ - T* ptr; - inline T* operator=(T* p); -public: - inline rcScopedDelete() : ptr(0) {} - inline rcScopedDelete(T* p) : ptr(p) {} - inline ~rcScopedDelete() { rcFree(ptr); } - inline operator T*() { return ptr; } -}; - -#endif diff --git a/deps/recastnavigation/TODO.txt b/deps/recastnavigation/TODO.txt deleted file mode 100644 index b911c0e472..0000000000 --- a/deps/recastnavigation/TODO.txt +++ /dev/null @@ -1,20 +0,0 @@ -TODO/Roadmap - -Summer/Autumn 2009 - -- Off mesh links (jump links) -- Area annotations -- Embed extra data per polygon -- Height conforming navmesh - - -Autumn/Winter 2009/2010 - -- Detour path following -- More dynamic example with tile navmesh -- Faster small tile process - - -More info at http://digestingduck.blogspot.com/2009/07/recast-and-detour-roadmap.html - -- diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_externs.h new file mode 100644 index 0000000000..af16d15885 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_externs.h @@ -0,0 +1,97 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_EXTERNS_H +#define JEMALLOC_INTERNAL_ARENA_EXTERNS_H + +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/pages.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/stats.h" + +extern ssize_t opt_dirty_decay_ms; +extern ssize_t opt_muzzy_decay_ms; + +extern const arena_bin_info_t arena_bin_info[NBINS]; + +extern percpu_arena_mode_t opt_percpu_arena; +extern const char *percpu_arena_mode_names[]; + +extern const uint64_t h_steps[SMOOTHSTEP_NSTEPS]; +extern malloc_mutex_t arenas_lock; + +void arena_stats_large_nrequests_add(tsdn_t *tsdn, arena_stats_t *arena_stats, + szind_t szind, uint64_t nrequests); +void arena_stats_mapped_add(tsdn_t *tsdn, arena_stats_t *arena_stats, + size_t size); +void arena_basic_stats_merge(tsdn_t *tsdn, arena_t *arena, + unsigned *nthreads, const char **dss, ssize_t *dirty_decay_ms, + ssize_t *muzzy_decay_ms, size_t *nactive, size_t *ndirty, size_t *nmuzzy); +void arena_stats_merge(tsdn_t *tsdn, arena_t *arena, unsigned *nthreads, + const char **dss, ssize_t *dirty_decay_ms, ssize_t *muzzy_decay_ms, + size_t *nactive, size_t *ndirty, size_t *nmuzzy, arena_stats_t *astats, + malloc_bin_stats_t *bstats, malloc_large_stats_t *lstats); +void arena_extents_dirty_dalloc(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent); +#ifdef JEMALLOC_JET +size_t arena_slab_regind(extent_t *slab, szind_t binind, const void *ptr); +#endif +extent_t *arena_extent_alloc_large(tsdn_t *tsdn, arena_t *arena, + size_t usize, size_t alignment, bool *zero); +void arena_extent_dalloc_large_prep(tsdn_t *tsdn, arena_t *arena, + extent_t *extent); +void arena_extent_ralloc_large_shrink(tsdn_t *tsdn, arena_t *arena, + extent_t *extent, size_t oldsize); +void arena_extent_ralloc_large_expand(tsdn_t *tsdn, arena_t *arena, + extent_t *extent, size_t oldsize); +ssize_t arena_dirty_decay_ms_get(arena_t *arena); +bool arena_dirty_decay_ms_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_ms); +ssize_t arena_muzzy_decay_ms_get(arena_t *arena); +bool arena_muzzy_decay_ms_set(tsdn_t *tsdn, arena_t *arena, ssize_t decay_ms); +void arena_decay(tsdn_t *tsdn, arena_t *arena, bool is_background_thread, + bool all); +void arena_reset(tsd_t *tsd, arena_t *arena); +void arena_destroy(tsd_t *tsd, arena_t *arena); +void arena_tcache_fill_small(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, + tcache_bin_t *tbin, szind_t binind, uint64_t prof_accumbytes); +void arena_alloc_junk_small(void *ptr, const arena_bin_info_t *bin_info, + bool zero); + +typedef void (arena_dalloc_junk_small_t)(void *, const arena_bin_info_t *); +extern arena_dalloc_junk_small_t *JET_MUTABLE arena_dalloc_junk_small; + +void *arena_malloc_hard(tsdn_t *tsdn, arena_t *arena, size_t size, + szind_t ind, bool zero); +void *arena_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, + size_t alignment, bool zero, tcache_t *tcache); +void arena_prof_promote(tsdn_t *tsdn, const void *ptr, size_t usize); +void arena_dalloc_promoted(tsdn_t *tsdn, void *ptr, tcache_t *tcache, + bool slow_path); +void arena_dalloc_bin_junked_locked(tsdn_t *tsdn, arena_t *arena, + extent_t *extent, void *ptr); +void arena_dalloc_small(tsdn_t *tsdn, void *ptr); +bool arena_ralloc_no_move(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, + size_t extra, bool zero); +void *arena_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t oldsize, + size_t size, size_t alignment, bool zero, tcache_t *tcache); +dss_prec_t arena_dss_prec_get(arena_t *arena); +bool arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec); +ssize_t arena_dirty_decay_ms_default_get(void); +bool arena_dirty_decay_ms_default_set(ssize_t decay_ms); +ssize_t arena_muzzy_decay_ms_default_get(void); +bool arena_muzzy_decay_ms_default_set(ssize_t decay_ms); +unsigned arena_nthreads_get(arena_t *arena, bool internal); +void arena_nthreads_inc(arena_t *arena, bool internal); +void arena_nthreads_dec(arena_t *arena, bool internal); +size_t arena_extent_sn_next(arena_t *arena); +arena_t *arena_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks); +void arena_boot(void); +void arena_prefork0(tsdn_t *tsdn, arena_t *arena); +void arena_prefork1(tsdn_t *tsdn, arena_t *arena); +void arena_prefork2(tsdn_t *tsdn, arena_t *arena); +void arena_prefork3(tsdn_t *tsdn, arena_t *arena); +void arena_prefork4(tsdn_t *tsdn, arena_t *arena); +void arena_prefork5(tsdn_t *tsdn, arena_t *arena); +void arena_prefork6(tsdn_t *tsdn, arena_t *arena); +void arena_prefork7(tsdn_t *tsdn, arena_t *arena); +void arena_postfork_parent(tsdn_t *tsdn, arena_t *arena); +void arena_postfork_child(tsdn_t *tsdn, arena_t *arena); + +#endif /* JEMALLOC_INTERNAL_ARENA_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_inlines_a.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_inlines_a.h new file mode 100644 index 0000000000..da5877060a --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_inlines_a.h @@ -0,0 +1,57 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_INLINES_A_H +#define JEMALLOC_INTERNAL_ARENA_INLINES_A_H + +static inline unsigned +arena_ind_get(const arena_t *arena) { + return base_ind_get(arena->base); +} + +static inline void +arena_internal_add(arena_t *arena, size_t size) { + atomic_fetch_add_zu(&arena->stats.internal, size, ATOMIC_RELAXED); +} + +static inline void +arena_internal_sub(arena_t *arena, size_t size) { + atomic_fetch_sub_zu(&arena->stats.internal, size, ATOMIC_RELAXED); +} + +static inline size_t +arena_internal_get(arena_t *arena) { + return atomic_load_zu(&arena->stats.internal, ATOMIC_RELAXED); +} + +static inline bool +arena_prof_accum(tsdn_t *tsdn, arena_t *arena, uint64_t accumbytes) { + cassert(config_prof); + + if (likely(prof_interval == 0)) { + return false; + } + + return prof_accum_add(tsdn, &arena->prof_accum, accumbytes); +} + +static inline void +percpu_arena_update(tsd_t *tsd, unsigned cpu) { + assert(have_percpu_arena); + arena_t *oldarena = tsd_arena_get(tsd); + assert(oldarena != NULL); + unsigned oldind = arena_ind_get(oldarena); + + if (oldind != cpu) { + unsigned newind = cpu; + arena_t *newarena = arena_get(tsd_tsdn(tsd), newind, true); + assert(newarena != NULL); + + /* Set new arena/tcache associations. */ + arena_migrate(tsd, oldind, newind); + tcache_t *tcache = tcache_get(tsd); + if (tcache != NULL) { + tcache_arena_reassociate(tsd_tsdn(tsd), tcache, + newarena); + } + } +} + +#endif /* JEMALLOC_INTERNAL_ARENA_INLINES_A_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_inlines_b.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_inlines_b.h new file mode 100644 index 0000000000..003abe116f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_inlines_b.h @@ -0,0 +1,361 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_INLINES_B_H +#define JEMALLOC_INTERNAL_ARENA_INLINES_B_H + +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/rtree.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sz.h" +#include "jemalloc/internal/ticker.h" + +static inline szind_t +arena_bin_index(arena_t *arena, arena_bin_t *bin) { + szind_t binind = (szind_t)(bin - arena->bins); + assert(binind < NBINS); + return binind; +} + +JEMALLOC_ALWAYS_INLINE prof_tctx_t * +arena_prof_tctx_get(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx) { + cassert(config_prof); + assert(ptr != NULL); + + /* Static check. */ + if (alloc_ctx == NULL) { + const extent_t *extent = iealloc(tsdn, ptr); + if (unlikely(!extent_slab_get(extent))) { + return large_prof_tctx_get(tsdn, extent); + } + } else { + if (unlikely(!alloc_ctx->slab)) { + return large_prof_tctx_get(tsdn, iealloc(tsdn, ptr)); + } + } + return (prof_tctx_t *)(uintptr_t)1U; +} + +JEMALLOC_ALWAYS_INLINE void +arena_prof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize, + alloc_ctx_t *alloc_ctx, prof_tctx_t *tctx) { + cassert(config_prof); + assert(ptr != NULL); + + /* Static check. */ + if (alloc_ctx == NULL) { + extent_t *extent = iealloc(tsdn, ptr); + if (unlikely(!extent_slab_get(extent))) { + large_prof_tctx_set(tsdn, extent, tctx); + } + } else { + if (unlikely(!alloc_ctx->slab)) { + large_prof_tctx_set(tsdn, iealloc(tsdn, ptr), tctx); + } + } +} + +static inline void +arena_prof_tctx_reset(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx) { + cassert(config_prof); + assert(ptr != NULL); + + extent_t *extent = iealloc(tsdn, ptr); + assert(!extent_slab_get(extent)); + + large_prof_tctx_reset(tsdn, extent); +} + +JEMALLOC_ALWAYS_INLINE void +arena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks) { + tsd_t *tsd; + ticker_t *decay_ticker; + + if (unlikely(tsdn_null(tsdn))) { + return; + } + tsd = tsdn_tsd(tsdn); + decay_ticker = decay_ticker_get(tsd, arena_ind_get(arena)); + if (unlikely(decay_ticker == NULL)) { + return; + } + if (unlikely(ticker_ticks(decay_ticker, nticks))) { + arena_decay(tsdn, arena, false, false); + } +} + +JEMALLOC_ALWAYS_INLINE void +arena_decay_tick(tsdn_t *tsdn, arena_t *arena) { + malloc_mutex_assert_not_owner(tsdn, &arena->decay_dirty.mtx); + malloc_mutex_assert_not_owner(tsdn, &arena->decay_muzzy.mtx); + + arena_decay_ticks(tsdn, arena, 1); +} + +JEMALLOC_ALWAYS_INLINE void * +arena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, bool zero, + tcache_t *tcache, bool slow_path) { + assert(!tsdn_null(tsdn) || tcache == NULL); + assert(size != 0); + + if (likely(tcache != NULL)) { + if (likely(size <= SMALL_MAXCLASS)) { + return tcache_alloc_small(tsdn_tsd(tsdn), arena, + tcache, size, ind, zero, slow_path); + } + if (likely(size <= tcache_maxclass)) { + return tcache_alloc_large(tsdn_tsd(tsdn), arena, + tcache, size, ind, zero, slow_path); + } + /* (size > tcache_maxclass) case falls through. */ + assert(size > tcache_maxclass); + } + + return arena_malloc_hard(tsdn, arena, size, ind, zero); +} + +JEMALLOC_ALWAYS_INLINE arena_t * +arena_aalloc(tsdn_t *tsdn, const void *ptr) { + return extent_arena_get(iealloc(tsdn, ptr)); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_salloc(tsdn_t *tsdn, const void *ptr) { + assert(ptr != NULL); + + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + szind_t szind = rtree_szind_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true); + assert(szind != NSIZES); + + return sz_index2size(szind); +} + +JEMALLOC_ALWAYS_INLINE size_t +arena_vsalloc(tsdn_t *tsdn, const void *ptr) { + /* + * Return 0 if ptr is not within an extent managed by jemalloc. This + * function has two extra costs relative to isalloc(): + * - The rtree calls cannot claim to be dependent lookups, which induces + * rtree lookup load dependencies. + * - The lookup may fail, so there is an extra branch to check for + * failure. + */ + + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + extent_t *extent; + szind_t szind; + if (rtree_extent_szind_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, false, &extent, &szind)) { + return 0; + } + + if (extent == NULL) { + return 0; + } + assert(extent_state_get(extent) == extent_state_active); + /* Only slab members should be looked up via interior pointers. */ + assert(extent_addr_get(extent) == ptr || extent_slab_get(extent)); + + assert(szind != NSIZES); + + return sz_index2size(szind); +} + +static inline void +arena_dalloc_no_tcache(tsdn_t *tsdn, void *ptr) { + assert(ptr != NULL); + + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + szind_t szind; + bool slab; + rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr, + true, &szind, &slab); + + if (config_debug) { + extent_t *extent = rtree_extent_read(tsdn, &extents_rtree, + rtree_ctx, (uintptr_t)ptr, true); + assert(szind == extent_szind_get(extent)); + assert(szind < NSIZES); + assert(slab == extent_slab_get(extent)); + } + + if (likely(slab)) { + /* Small allocation. */ + arena_dalloc_small(tsdn, ptr); + } else { + extent_t *extent = iealloc(tsdn, ptr); + large_dalloc(tsdn, extent); + } +} + +JEMALLOC_ALWAYS_INLINE void +arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache, + alloc_ctx_t *alloc_ctx, bool slow_path) { + assert(!tsdn_null(tsdn) || tcache == NULL); + assert(ptr != NULL); + + if (unlikely(tcache == NULL)) { + arena_dalloc_no_tcache(tsdn, ptr); + return; + } + + szind_t szind; + bool slab; + rtree_ctx_t *rtree_ctx; + if (alloc_ctx != NULL) { + szind = alloc_ctx->szind; + slab = alloc_ctx->slab; + assert(szind != NSIZES); + } else { + rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn)); + rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &szind, &slab); + } + + if (config_debug) { + rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn)); + extent_t *extent = rtree_extent_read(tsdn, &extents_rtree, + rtree_ctx, (uintptr_t)ptr, true); + assert(szind == extent_szind_get(extent)); + assert(szind < NSIZES); + assert(slab == extent_slab_get(extent)); + } + + if (likely(slab)) { + /* Small allocation. */ + tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, szind, + slow_path); + } else { + if (szind < nhbins) { + if (config_prof && unlikely(szind < NBINS)) { + arena_dalloc_promoted(tsdn, ptr, tcache, + slow_path); + } else { + tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, + szind, slow_path); + } + } else { + extent_t *extent = iealloc(tsdn, ptr); + large_dalloc(tsdn, extent); + } + } +} + +static inline void +arena_sdalloc_no_tcache(tsdn_t *tsdn, void *ptr, size_t size) { + assert(ptr != NULL); + assert(size <= LARGE_MAXCLASS); + + szind_t szind; + bool slab; + if (!config_prof || !opt_prof) { + /* + * There is no risk of being confused by a promoted sampled + * object, so base szind and slab on the given size. + */ + szind = sz_size2index(size); + slab = (szind < NBINS); + } + + if ((config_prof && opt_prof) || config_debug) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, + &rtree_ctx_fallback); + + rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &szind, &slab); + + assert(szind == sz_size2index(size)); + assert((config_prof && opt_prof) || slab == (szind < NBINS)); + + if (config_debug) { + extent_t *extent = rtree_extent_read(tsdn, + &extents_rtree, rtree_ctx, (uintptr_t)ptr, true); + assert(szind == extent_szind_get(extent)); + assert(slab == extent_slab_get(extent)); + } + } + + if (likely(slab)) { + /* Small allocation. */ + arena_dalloc_small(tsdn, ptr); + } else { + extent_t *extent = iealloc(tsdn, ptr); + large_dalloc(tsdn, extent); + } +} + +JEMALLOC_ALWAYS_INLINE void +arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, + alloc_ctx_t *alloc_ctx, bool slow_path) { + assert(!tsdn_null(tsdn) || tcache == NULL); + assert(ptr != NULL); + assert(size <= LARGE_MAXCLASS); + + if (unlikely(tcache == NULL)) { + arena_sdalloc_no_tcache(tsdn, ptr, size); + return; + } + + szind_t szind; + bool slab; + UNUSED alloc_ctx_t local_ctx; + if (config_prof && opt_prof) { + if (alloc_ctx == NULL) { + /* Uncommon case and should be a static check. */ + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, + &rtree_ctx_fallback); + rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &local_ctx.szind, + &local_ctx.slab); + assert(local_ctx.szind == sz_size2index(size)); + alloc_ctx = &local_ctx; + } + slab = alloc_ctx->slab; + szind = alloc_ctx->szind; + } else { + /* + * There is no risk of being confused by a promoted sampled + * object, so base szind and slab on the given size. + */ + szind = sz_size2index(size); + slab = (szind < NBINS); + } + + if (config_debug) { + rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn)); + rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true, &szind, &slab); + extent_t *extent = rtree_extent_read(tsdn, + &extents_rtree, rtree_ctx, (uintptr_t)ptr, true); + assert(szind == extent_szind_get(extent)); + assert(slab == extent_slab_get(extent)); + } + + if (likely(slab)) { + /* Small allocation. */ + tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, szind, + slow_path); + } else { + if (szind < nhbins) { + if (config_prof && unlikely(szind < NBINS)) { + arena_dalloc_promoted(tsdn, ptr, tcache, + slow_path); + } else { + tcache_dalloc_large(tsdn_tsd(tsdn), + tcache, ptr, szind, slow_path); + } + } else { + extent_t *extent = iealloc(tsdn, ptr); + large_dalloc(tsdn, extent); + } + } +} + +#endif /* JEMALLOC_INTERNAL_ARENA_INLINES_B_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_structs_a.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_structs_a.h new file mode 100644 index 0000000000..46aa77c884 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_structs_a.h @@ -0,0 +1,11 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_STRUCTS_A_H +#define JEMALLOC_INTERNAL_ARENA_STRUCTS_A_H + +#include "jemalloc/internal/bitmap.h" + +struct arena_slab_data_s { + /* Per region allocated/deallocated bitmap. */ + bitmap_t bitmap[BITMAP_GROUPS_MAX]; +}; + +#endif /* JEMALLOC_INTERNAL_ARENA_STRUCTS_A_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_structs_b.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_structs_b.h new file mode 100644 index 0000000000..d1fffec193 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_structs_b.h @@ -0,0 +1,284 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H +#define JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/bitmap.h" +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/nstime.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/smoothstep.h" +#include "jemalloc/internal/stats.h" +#include "jemalloc/internal/ticker.h" + +/* + * Read-only information associated with each element of arena_t's bins array + * is stored separately, partly to reduce memory usage (only one copy, rather + * than one per arena), but mainly to avoid false cacheline sharing. + * + * Each slab has the following layout: + * + * /--------------------\ + * | region 0 | + * |--------------------| + * | region 1 | + * |--------------------| + * | ... | + * | ... | + * | ... | + * |--------------------| + * | region nregs-1 | + * \--------------------/ + */ +struct arena_bin_info_s { + /* Size of regions in a slab for this bin's size class. */ + size_t reg_size; + + /* Total size of a slab for this bin's size class. */ + size_t slab_size; + + /* Total number of regions in a slab for this bin's size class. */ + uint32_t nregs; + + /* + * Metadata used to manipulate bitmaps for slabs associated with this + * bin. + */ + bitmap_info_t bitmap_info; +}; + +struct arena_decay_s { + /* Synchronizes all non-atomic fields. */ + malloc_mutex_t mtx; + /* + * True if a thread is currently purging the extents associated with + * this decay structure. + */ + bool purging; + /* + * Approximate time in milliseconds from the creation of a set of unused + * dirty pages until an equivalent set of unused dirty pages is purged + * and/or reused. + */ + atomic_zd_t time_ms; + /* time / SMOOTHSTEP_NSTEPS. */ + nstime_t interval; + /* + * Time at which the current decay interval logically started. We do + * not actually advance to a new epoch until sometime after it starts + * because of scheduling and computation delays, and it is even possible + * to completely skip epochs. In all cases, during epoch advancement we + * merge all relevant activity into the most recently recorded epoch. + */ + nstime_t epoch; + /* Deadline randomness generator. */ + uint64_t jitter_state; + /* + * Deadline for current epoch. This is the sum of interval and per + * epoch jitter which is a uniform random variable in [0..interval). + * Epochs always advance by precise multiples of interval, but we + * randomize the deadline to reduce the likelihood of arenas purging in + * lockstep. + */ + nstime_t deadline; + /* + * Number of unpurged pages at beginning of current epoch. During epoch + * advancement we use the delta between arena->decay_*.nunpurged and + * extents_npages_get(&arena->extents_*) to determine how many dirty + * pages, if any, were generated. + */ + size_t nunpurged; + /* + * Trailing log of how many unused dirty pages were generated during + * each of the past SMOOTHSTEP_NSTEPS decay epochs, where the last + * element is the most recent epoch. Corresponding epoch times are + * relative to epoch. + */ + size_t backlog[SMOOTHSTEP_NSTEPS]; + + /* + * Pointer to associated stats. These stats are embedded directly in + * the arena's stats due to how stats structures are shared between the + * arena and ctl code. + * + * Synchronization: Same as associated arena's stats field. */ + decay_stats_t *stats; + /* Peak number of pages in associated extents. Used for debug only. */ + uint64_t ceil_npages; +}; + +struct arena_bin_s { + /* All operations on arena_bin_t fields require lock ownership. */ + malloc_mutex_t lock; + + /* + * Current slab being used to service allocations of this bin's size + * class. slabcur is independent of slabs_{nonfull,full}; whenever + * slabcur is reassigned, the previous slab must be deallocated or + * inserted into slabs_{nonfull,full}. + */ + extent_t *slabcur; + + /* + * Heap of non-full slabs. This heap is used to assure that new + * allocations come from the non-full slab that is oldest/lowest in + * memory. + */ + extent_heap_t slabs_nonfull; + + /* List used to track full slabs. */ + extent_list_t slabs_full; + + /* Bin statistics. */ + malloc_bin_stats_t stats; +}; + +struct arena_s { + /* + * Number of threads currently assigned to this arena. Each thread has + * two distinct assignments, one for application-serving allocation, and + * the other for internal metadata allocation. Internal metadata must + * not be allocated from arenas explicitly created via the arenas.create + * mallctl, because the arena.<i>.reset mallctl indiscriminately + * discards all allocations for the affected arena. + * + * 0: Application allocation. + * 1: Internal metadata allocation. + * + * Synchronization: atomic. + */ + atomic_u_t nthreads[2]; + + /* + * When percpu_arena is enabled, to amortize the cost of reading / + * updating the current CPU id, track the most recent thread accessing + * this arena, and only read CPU if there is a mismatch. + */ + tsdn_t *last_thd; + + /* Synchronization: internal. */ + arena_stats_t stats; + + /* + * List of tcaches for extant threads associated with this arena. + * Stats from these are merged incrementally, and at exit if + * opt_stats_print is enabled. + * + * Synchronization: tcache_ql_mtx. + */ + ql_head(tcache_t) tcache_ql; + malloc_mutex_t tcache_ql_mtx; + + /* Synchronization: internal. */ + prof_accum_t prof_accum; + uint64_t prof_accumbytes; + + /* + * PRNG state for cache index randomization of large allocation base + * pointers. + * + * Synchronization: atomic. + */ + atomic_zu_t offset_state; + + /* + * Extent serial number generator state. + * + * Synchronization: atomic. + */ + atomic_zu_t extent_sn_next; + + /* + * Represents a dss_prec_t, but atomically. + * + * Synchronization: atomic. + */ + atomic_u_t dss_prec; + + /* + * Number of pages in active extents. + * + * Synchronization: atomic. + */ + atomic_zu_t nactive; + + /* + * Extant large allocations. + * + * Synchronization: large_mtx. + */ + extent_list_t large; + /* Synchronizes all large allocation/update/deallocation. */ + malloc_mutex_t large_mtx; + + /* + * Collections of extents that were previously allocated. These are + * used when allocating extents, in an attempt to re-use address space. + * + * Synchronization: internal. + */ + extents_t extents_dirty; + extents_t extents_muzzy; + extents_t extents_retained; + + /* + * Decay-based purging state, responsible for scheduling extent state + * transitions. + * + * Synchronization: internal. + */ + arena_decay_t decay_dirty; /* dirty --> muzzy */ + arena_decay_t decay_muzzy; /* muzzy --> retained */ + + /* + * Next extent size class in a growing series to use when satisfying a + * request via the extent hooks (only if opt_retain). This limits the + * number of disjoint virtual memory ranges so that extent merging can + * be effective even if multiple arenas' extent allocation requests are + * highly interleaved. + * + * Synchronization: extent_grow_mtx + */ + pszind_t extent_grow_next; + malloc_mutex_t extent_grow_mtx; + + /* + * Available extent structures that were allocated via + * base_alloc_extent(). + * + * Synchronization: extent_avail_mtx. + */ + extent_tree_t extent_avail; + malloc_mutex_t extent_avail_mtx; + + /* + * bins is used to store heaps of free regions. + * + * Synchronization: internal. + */ + arena_bin_t bins[NBINS]; + + /* + * Base allocator, from which arena metadata are allocated. + * + * Synchronization: internal. + */ + base_t *base; + /* Used to determine uptime. Read-only after initialization. */ + nstime_t create_time; +}; + +/* Used in conjunction with tsd for fast arena-related context lookup. */ +struct arena_tdata_s { + ticker_t decay_ticker; +}; + +/* Used to pass rtree lookup context down the path. */ +struct alloc_ctx_s { + szind_t szind; + bool slab; +}; + +#endif /* JEMALLOC_INTERNAL_ARENA_STRUCTS_B_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_types.h new file mode 100644 index 0000000000..a691bd811e --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/arena_types.h @@ -0,0 +1,45 @@ +#ifndef JEMALLOC_INTERNAL_ARENA_TYPES_H +#define JEMALLOC_INTERNAL_ARENA_TYPES_H + +/* Maximum number of regions in one slab. */ +#define LG_SLAB_MAXREGS (LG_PAGE - LG_TINY_MIN) +#define SLAB_MAXREGS (1U << LG_SLAB_MAXREGS) + +/* Default decay times in milliseconds. */ +#define DIRTY_DECAY_MS_DEFAULT ZD(10 * 1000) +#define MUZZY_DECAY_MS_DEFAULT ZD(10 * 1000) +/* Number of event ticks between time checks. */ +#define DECAY_NTICKS_PER_UPDATE 1000 + +typedef struct arena_slab_data_s arena_slab_data_t; +typedef struct arena_bin_info_s arena_bin_info_t; +typedef struct arena_decay_s arena_decay_t; +typedef struct arena_bin_s arena_bin_t; +typedef struct arena_s arena_t; +typedef struct arena_tdata_s arena_tdata_t; +typedef struct alloc_ctx_s alloc_ctx_t; + +typedef enum { + percpu_arena_mode_names_base = 0, /* Used for options processing. */ + + /* + * *_uninit are used only during bootstrapping, and must correspond + * to initialized variant plus percpu_arena_mode_enabled_base. + */ + percpu_arena_uninit = 0, + per_phycpu_arena_uninit = 1, + + /* All non-disabled modes must come after percpu_arena_disabled. */ + percpu_arena_disabled = 2, + + percpu_arena_mode_names_limit = 3, /* Used for options processing. */ + percpu_arena_mode_enabled_base = 3, + + percpu_arena = 3, + per_phycpu_arena = 4 /* Hyper threads share arena. */ +} percpu_arena_mode_t; + +#define PERCPU_ARENA_ENABLED(m) ((m) >= percpu_arena_mode_enabled_base) +#define PERCPU_ARENA_DEFAULT percpu_arena_disabled + +#endif /* JEMALLOC_INTERNAL_ARENA_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/assert.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/assert.h new file mode 100644 index 0000000000..be4d45b321 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/assert.h @@ -0,0 +1,56 @@ +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/util.h" + +/* + * Define a custom assert() in order to reduce the chances of deadlock during + * assertion failure. + */ +#ifndef assert +#define assert(e) do { \ + if (unlikely(config_debug && !(e))) { \ + malloc_printf( \ + "<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \ + __FILE__, __LINE__, #e); \ + abort(); \ + } \ +} while (0) +#endif + +#ifndef not_reached +#define not_reached() do { \ + if (config_debug) { \ + malloc_printf( \ + "<jemalloc>: %s:%d: Unreachable code reached\n", \ + __FILE__, __LINE__); \ + abort(); \ + } \ + unreachable(); \ +} while (0) +#endif + +#ifndef not_implemented +#define not_implemented() do { \ + if (config_debug) { \ + malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \ + __FILE__, __LINE__); \ + abort(); \ + } \ +} while (0) +#endif + +#ifndef assert_not_implemented +#define assert_not_implemented(e) do { \ + if (unlikely(config_debug && !(e))) { \ + not_implemented(); \ + } \ +} while (0) +#endif + +/* Use to assert a particular configuration, e.g., cassert(config_debug). */ +#ifndef cassert +#define cassert(c) do { \ + if (unlikely(!(c))) { \ + not_reached(); \ + } \ +} while (0) +#endif diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_c11.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_c11.h new file mode 100644 index 0000000000..a5f9313a61 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_c11.h @@ -0,0 +1,97 @@ +#ifndef JEMALLOC_INTERNAL_ATOMIC_C11_H +#define JEMALLOC_INTERNAL_ATOMIC_C11_H + +#include <stdatomic.h> + +#define ATOMIC_INIT(...) ATOMIC_VAR_INIT(__VA_ARGS__) + +#define atomic_memory_order_t memory_order +#define atomic_memory_order_relaxed memory_order_relaxed +#define atomic_memory_order_acquire memory_order_acquire +#define atomic_memory_order_release memory_order_release +#define atomic_memory_order_acq_rel memory_order_acq_rel +#define atomic_memory_order_seq_cst memory_order_seq_cst + +#define atomic_fence atomic_thread_fence + +#define JEMALLOC_GENERATE_ATOMICS(type, short_type, \ + /* unused */ lg_size) \ +typedef _Atomic(type) atomic_##short_type##_t; \ + \ +ATOMIC_INLINE type \ +atomic_load_##short_type(const atomic_##short_type##_t *a, \ + atomic_memory_order_t mo) { \ + /* \ + * A strict interpretation of the C standard prevents \ + * atomic_load from taking a const argument, but it's \ + * convenient for our purposes. This cast is a workaround. \ + */ \ + atomic_##short_type##_t* a_nonconst = \ + (atomic_##short_type##_t*)a; \ + return atomic_load_explicit(a_nonconst, mo); \ +} \ + \ +ATOMIC_INLINE void \ +atomic_store_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + atomic_store_explicit(a, val, mo); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return atomic_exchange_explicit(a, val, mo); \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + return atomic_compare_exchange_weak_explicit(a, expected, \ + desired, success_mo, failure_mo); \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + return atomic_compare_exchange_strong_explicit(a, expected, \ + desired, success_mo, failure_mo); \ +} + +/* + * Integral types have some special operations available that non-integral ones + * lack. + */ +#define JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, \ + /* unused */ lg_size) \ +JEMALLOC_GENERATE_ATOMICS(type, short_type, /* unused */ lg_size) \ + \ +ATOMIC_INLINE type \ +atomic_fetch_add_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return atomic_fetch_add_explicit(a, val, mo); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_sub_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return atomic_fetch_sub_explicit(a, val, mo); \ +} \ +ATOMIC_INLINE type \ +atomic_fetch_and_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return atomic_fetch_and_explicit(a, val, mo); \ +} \ +ATOMIC_INLINE type \ +atomic_fetch_or_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return atomic_fetch_or_explicit(a, val, mo); \ +} \ +ATOMIC_INLINE type \ +atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return atomic_fetch_xor_explicit(a, val, mo); \ +} + +#endif /* JEMALLOC_INTERNAL_ATOMIC_C11_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h new file mode 100644 index 0000000000..6b73a14f81 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_gcc_atomic.h @@ -0,0 +1,127 @@ +#ifndef JEMALLOC_INTERNAL_ATOMIC_GCC_ATOMIC_H +#define JEMALLOC_INTERNAL_ATOMIC_GCC_ATOMIC_H + +#include "jemalloc/internal/assert.h" + +#define ATOMIC_INIT(...) {__VA_ARGS__} + +typedef enum { + atomic_memory_order_relaxed, + atomic_memory_order_acquire, + atomic_memory_order_release, + atomic_memory_order_acq_rel, + atomic_memory_order_seq_cst +} atomic_memory_order_t; + +ATOMIC_INLINE int +atomic_enum_to_builtin(atomic_memory_order_t mo) { + switch (mo) { + case atomic_memory_order_relaxed: + return __ATOMIC_RELAXED; + case atomic_memory_order_acquire: + return __ATOMIC_ACQUIRE; + case atomic_memory_order_release: + return __ATOMIC_RELEASE; + case atomic_memory_order_acq_rel: + return __ATOMIC_ACQ_REL; + case atomic_memory_order_seq_cst: + return __ATOMIC_SEQ_CST; + } + /* Can't happen; the switch is exhaustive. */ + not_reached(); +} + +ATOMIC_INLINE void +atomic_fence(atomic_memory_order_t mo) { + __atomic_thread_fence(atomic_enum_to_builtin(mo)); +} + +#define JEMALLOC_GENERATE_ATOMICS(type, short_type, \ + /* unused */ lg_size) \ +typedef struct { \ + type repr; \ +} atomic_##short_type##_t; \ + \ +ATOMIC_INLINE type \ +atomic_load_##short_type(const atomic_##short_type##_t *a, \ + atomic_memory_order_t mo) { \ + type result; \ + __atomic_load(&a->repr, &result, atomic_enum_to_builtin(mo)); \ + return result; \ +} \ + \ +ATOMIC_INLINE void \ +atomic_store_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + __atomic_store(&a->repr, &val, atomic_enum_to_builtin(mo)); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + type result; \ + __atomic_exchange(&a->repr, &val, &result, \ + atomic_enum_to_builtin(mo)); \ + return result; \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + return __atomic_compare_exchange(&a->repr, expected, &desired, \ + true, atomic_enum_to_builtin(success_mo), \ + atomic_enum_to_builtin(failure_mo)); \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + return __atomic_compare_exchange(&a->repr, expected, &desired, \ + false, \ + atomic_enum_to_builtin(success_mo), \ + atomic_enum_to_builtin(failure_mo)); \ +} + + +#define JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, \ + /* unused */ lg_size) \ +JEMALLOC_GENERATE_ATOMICS(type, short_type, /* unused */ lg_size) \ + \ +ATOMIC_INLINE type \ +atomic_fetch_add_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __atomic_fetch_add(&a->repr, val, \ + atomic_enum_to_builtin(mo)); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_sub_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __atomic_fetch_sub(&a->repr, val, \ + atomic_enum_to_builtin(mo)); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_and_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __atomic_fetch_and(&a->repr, val, \ + atomic_enum_to_builtin(mo)); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_or_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __atomic_fetch_or(&a->repr, val, \ + atomic_enum_to_builtin(mo)); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __atomic_fetch_xor(&a->repr, val, \ + atomic_enum_to_builtin(mo)); \ +} + +#endif /* JEMALLOC_INTERNAL_ATOMIC_GCC_ATOMIC_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h new file mode 100644 index 0000000000..30846e4d27 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_gcc_sync.h @@ -0,0 +1,191 @@ +#ifndef JEMALLOC_INTERNAL_ATOMIC_GCC_SYNC_H +#define JEMALLOC_INTERNAL_ATOMIC_GCC_SYNC_H + +#define ATOMIC_INIT(...) {__VA_ARGS__} + +typedef enum { + atomic_memory_order_relaxed, + atomic_memory_order_acquire, + atomic_memory_order_release, + atomic_memory_order_acq_rel, + atomic_memory_order_seq_cst +} atomic_memory_order_t; + +ATOMIC_INLINE void +atomic_fence(atomic_memory_order_t mo) { + /* Easy cases first: no barrier, and full barrier. */ + if (mo == atomic_memory_order_relaxed) { + asm volatile("" ::: "memory"); + return; + } + if (mo == atomic_memory_order_seq_cst) { + asm volatile("" ::: "memory"); + __sync_synchronize(); + asm volatile("" ::: "memory"); + return; + } + asm volatile("" ::: "memory"); +# if defined(__i386__) || defined(__x86_64__) + /* This is implicit on x86. */ +# elif defined(__ppc__) + asm volatile("lwsync"); +# elif defined(__sparc__) && defined(__arch64__) + if (mo == atomic_memory_order_acquire) { + asm volatile("membar #LoadLoad | #LoadStore"); + } else if (mo == atomic_memory_order_release) { + asm volatile("membar #LoadStore | #StoreStore"); + } else { + asm volatile("membar #LoadLoad | #LoadStore | #StoreStore"); + } +# else + __sync_synchronize(); +# endif + asm volatile("" ::: "memory"); +} + +/* + * A correct implementation of seq_cst loads and stores on weakly ordered + * architectures could do either of the following: + * 1. store() is weak-fence -> store -> strong fence, load() is load -> + * strong-fence. + * 2. store() is strong-fence -> store, load() is strong-fence -> load -> + * weak-fence. + * The tricky thing is, load() and store() above can be the load or store + * portions of a gcc __sync builtin, so we have to follow GCC's lead, which + * means going with strategy 2. + * On strongly ordered architectures, the natural strategy is to stick a strong + * fence after seq_cst stores, and have naked loads. So we want the strong + * fences in different places on different architectures. + * atomic_pre_sc_load_fence and atomic_post_sc_store_fence allow us to + * accomplish this. + */ + +ATOMIC_INLINE void +atomic_pre_sc_load_fence() { +# if defined(__i386__) || defined(__x86_64__) || \ + (defined(__sparc__) && defined(__arch64__)) + atomic_fence(atomic_memory_order_relaxed); +# else + atomic_fence(atomic_memory_order_seq_cst); +# endif +} + +ATOMIC_INLINE void +atomic_post_sc_store_fence() { +# if defined(__i386__) || defined(__x86_64__) || \ + (defined(__sparc__) && defined(__arch64__)) + atomic_fence(atomic_memory_order_seq_cst); +# else + atomic_fence(atomic_memory_order_relaxed); +# endif + +} + +#define JEMALLOC_GENERATE_ATOMICS(type, short_type, \ + /* unused */ lg_size) \ +typedef struct { \ + type volatile repr; \ +} atomic_##short_type##_t; \ + \ +ATOMIC_INLINE type \ +atomic_load_##short_type(const atomic_##short_type##_t *a, \ + atomic_memory_order_t mo) { \ + if (mo == atomic_memory_order_seq_cst) { \ + atomic_pre_sc_load_fence(); \ + } \ + type result = a->repr; \ + if (mo != atomic_memory_order_relaxed) { \ + atomic_fence(atomic_memory_order_acquire); \ + } \ + return result; \ +} \ + \ +ATOMIC_INLINE void \ +atomic_store_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + if (mo != atomic_memory_order_relaxed) { \ + atomic_fence(atomic_memory_order_release); \ + } \ + a->repr = val; \ + if (mo == atomic_memory_order_seq_cst) { \ + atomic_post_sc_store_fence(); \ + } \ +} \ + \ +ATOMIC_INLINE type \ +atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + /* \ + * Because of FreeBSD, we care about gcc 4.2, which doesn't have\ + * an atomic exchange builtin. We fake it with a CAS loop. \ + */ \ + while (true) { \ + type old = a->repr; \ + if (__sync_bool_compare_and_swap(&a->repr, old, val)) { \ + return old; \ + } \ + } \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + type prev = __sync_val_compare_and_swap(&a->repr, *expected, \ + desired); \ + if (prev == *expected) { \ + return true; \ + } else { \ + *expected = prev; \ + return false; \ + } \ +} \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + type prev = __sync_val_compare_and_swap(&a->repr, *expected, \ + desired); \ + if (prev == *expected) { \ + return true; \ + } else { \ + *expected = prev; \ + return false; \ + } \ +} + +#define JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, \ + /* unused */ lg_size) \ +JEMALLOC_GENERATE_ATOMICS(type, short_type, /* unused */ lg_size) \ + \ +ATOMIC_INLINE type \ +atomic_fetch_add_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __sync_fetch_and_add(&a->repr, val); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_sub_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __sync_fetch_and_sub(&a->repr, val); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_and_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __sync_fetch_and_and(&a->repr, val); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_or_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __sync_fetch_and_or(&a->repr, val); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return __sync_fetch_and_xor(&a->repr, val); \ +} + +#endif /* JEMALLOC_INTERNAL_ATOMIC_GCC_SYNC_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_msvc.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_msvc.h new file mode 100644 index 0000000000..67057ce508 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/atomic_msvc.h @@ -0,0 +1,158 @@ +#ifndef JEMALLOC_INTERNAL_ATOMIC_MSVC_H +#define JEMALLOC_INTERNAL_ATOMIC_MSVC_H + +#define ATOMIC_INIT(...) {__VA_ARGS__} + +typedef enum { + atomic_memory_order_relaxed, + atomic_memory_order_acquire, + atomic_memory_order_release, + atomic_memory_order_acq_rel, + atomic_memory_order_seq_cst +} atomic_memory_order_t; + +typedef char atomic_repr_0_t; +typedef short atomic_repr_1_t; +typedef long atomic_repr_2_t; +typedef __int64 atomic_repr_3_t; + +ATOMIC_INLINE void +atomic_fence(atomic_memory_order_t mo) { + _ReadWriteBarrier(); +# if defined(_M_ARM) || defined(_M_ARM64) + /* ARM needs a barrier for everything but relaxed. */ + if (mo != atomic_memory_order_relaxed) { + MemoryBarrier(); + } +# elif defined(_M_IX86) || defined (_M_X64) + /* x86 needs a barrier only for seq_cst. */ + if (mo == atomic_memory_order_seq_cst) { + MemoryBarrier(); + } +# else +# error "Don't know how to create atomics for this platform for MSVC." +# endif + _ReadWriteBarrier(); +} + +#define ATOMIC_INTERLOCKED_REPR(lg_size) atomic_repr_ ## lg_size ## _t + +#define ATOMIC_CONCAT(a, b) ATOMIC_RAW_CONCAT(a, b) +#define ATOMIC_RAW_CONCAT(a, b) a ## b + +#define ATOMIC_INTERLOCKED_NAME(base_name, lg_size) ATOMIC_CONCAT( \ + base_name, ATOMIC_INTERLOCKED_SUFFIX(lg_size)) + +#define ATOMIC_INTERLOCKED_SUFFIX(lg_size) \ + ATOMIC_CONCAT(ATOMIC_INTERLOCKED_SUFFIX_, lg_size) + +#define ATOMIC_INTERLOCKED_SUFFIX_0 8 +#define ATOMIC_INTERLOCKED_SUFFIX_1 16 +#define ATOMIC_INTERLOCKED_SUFFIX_2 +#define ATOMIC_INTERLOCKED_SUFFIX_3 64 + +#define JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_size) \ +typedef struct { \ + ATOMIC_INTERLOCKED_REPR(lg_size) repr; \ +} atomic_##short_type##_t; \ + \ +ATOMIC_INLINE type \ +atomic_load_##short_type(const atomic_##short_type##_t *a, \ + atomic_memory_order_t mo) { \ + ATOMIC_INTERLOCKED_REPR(lg_size) ret = a->repr; \ + if (mo != atomic_memory_order_relaxed) { \ + atomic_fence(atomic_memory_order_acquire); \ + } \ + return (type) ret; \ +} \ + \ +ATOMIC_INLINE void \ +atomic_store_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + if (mo != atomic_memory_order_relaxed) { \ + atomic_fence(atomic_memory_order_release); \ + } \ + a->repr = (ATOMIC_INTERLOCKED_REPR(lg_size)) val; \ + if (mo == atomic_memory_order_seq_cst) { \ + atomic_fence(atomic_memory_order_seq_cst); \ + } \ +} \ + \ +ATOMIC_INLINE type \ +atomic_exchange_##short_type(atomic_##short_type##_t *a, type val, \ + atomic_memory_order_t mo) { \ + return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedExchange, \ + lg_size)(&a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val); \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_weak_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + ATOMIC_INTERLOCKED_REPR(lg_size) e = \ + (ATOMIC_INTERLOCKED_REPR(lg_size))*expected; \ + ATOMIC_INTERLOCKED_REPR(lg_size) d = \ + (ATOMIC_INTERLOCKED_REPR(lg_size))desired; \ + ATOMIC_INTERLOCKED_REPR(lg_size) old = \ + ATOMIC_INTERLOCKED_NAME(_InterlockedCompareExchange, \ + lg_size)(&a->repr, d, e); \ + if (old == e) { \ + return true; \ + } else { \ + *expected = (type)old; \ + return false; \ + } \ +} \ + \ +ATOMIC_INLINE bool \ +atomic_compare_exchange_strong_##short_type(atomic_##short_type##_t *a, \ + type *expected, type desired, atomic_memory_order_t success_mo, \ + atomic_memory_order_t failure_mo) { \ + /* We implement the weak version with strong semantics. */ \ + return atomic_compare_exchange_weak_##short_type(a, expected, \ + desired, success_mo, failure_mo); \ +} + + +#define JEMALLOC_GENERATE_INT_ATOMICS(type, short_type, lg_size) \ +JEMALLOC_GENERATE_ATOMICS(type, short_type, lg_size) \ + \ +ATOMIC_INLINE type \ +atomic_fetch_add_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedExchangeAdd, \ + lg_size)(&a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val); \ +} \ + \ +ATOMIC_INLINE type \ +atomic_fetch_sub_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + /* \ + * MSVC warns on negation of unsigned operands, but for us it \ + * gives exactly the right semantics (MAX_TYPE + 1 - operand). \ + */ \ + __pragma(warning(push)) \ + __pragma(warning(disable: 4146)) \ + return atomic_fetch_add_##short_type(a, -val, mo); \ + __pragma(warning(pop)) \ +} \ +ATOMIC_INLINE type \ +atomic_fetch_and_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedAnd, lg_size)( \ + &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val); \ +} \ +ATOMIC_INLINE type \ +atomic_fetch_or_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedOr, lg_size)( \ + &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val); \ +} \ +ATOMIC_INLINE type \ +atomic_fetch_xor_##short_type(atomic_##short_type##_t *a, \ + type val, atomic_memory_order_t mo) { \ + return (type)ATOMIC_INTERLOCKED_NAME(_InterlockedXor, lg_size)( \ + &a->repr, (ATOMIC_INTERLOCKED_REPR(lg_size))val); \ +} + +#endif /* JEMALLOC_INTERNAL_ATOMIC_MSVC_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_externs.h new file mode 100644 index 0000000000..8b4b8471a9 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_externs.h @@ -0,0 +1,31 @@ +#ifndef JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H +#define JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H + +extern bool opt_background_thread; +extern malloc_mutex_t background_thread_lock; +extern atomic_b_t background_thread_enabled_state; +extern size_t n_background_threads; +extern background_thread_info_t *background_thread_info; +extern bool can_enable_background_thread; + +bool background_thread_create(tsd_t *tsd, unsigned arena_ind); +bool background_threads_enable(tsd_t *tsd); +bool background_threads_disable(tsd_t *tsd); +void background_thread_interval_check(tsdn_t *tsdn, arena_t *arena, + arena_decay_t *decay, size_t npages_new); +void background_thread_prefork0(tsdn_t *tsdn); +void background_thread_prefork1(tsdn_t *tsdn); +void background_thread_postfork_parent(tsdn_t *tsdn); +void background_thread_postfork_child(tsdn_t *tsdn); +bool background_thread_stats_read(tsdn_t *tsdn, + background_thread_stats_t *stats); +void background_thread_ctl_init(tsdn_t *tsdn); + +#ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER +extern int pthread_create_wrapper(pthread_t *__restrict, const pthread_attr_t *, + void *(*)(void *), void *__restrict); +#endif +bool background_thread_boot0(void); +bool background_thread_boot1(tsdn_t *tsdn); + +#endif /* JEMALLOC_INTERNAL_BACKGROUND_THREAD_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_inlines.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_inlines.h new file mode 100644 index 0000000000..ef50231e8d --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_inlines.h @@ -0,0 +1,57 @@ +#ifndef JEMALLOC_INTERNAL_BACKGROUND_THREAD_INLINES_H +#define JEMALLOC_INTERNAL_BACKGROUND_THREAD_INLINES_H + +JEMALLOC_ALWAYS_INLINE bool +background_thread_enabled(void) { + return atomic_load_b(&background_thread_enabled_state, ATOMIC_RELAXED); +} + +JEMALLOC_ALWAYS_INLINE void +background_thread_enabled_set(tsdn_t *tsdn, bool state) { + malloc_mutex_assert_owner(tsdn, &background_thread_lock); + atomic_store_b(&background_thread_enabled_state, state, ATOMIC_RELAXED); +} + +JEMALLOC_ALWAYS_INLINE background_thread_info_t * +arena_background_thread_info_get(arena_t *arena) { + unsigned arena_ind = arena_ind_get(arena); + return &background_thread_info[arena_ind % ncpus]; +} + +JEMALLOC_ALWAYS_INLINE uint64_t +background_thread_wakeup_time_get(background_thread_info_t *info) { + uint64_t next_wakeup = nstime_ns(&info->next_wakeup); + assert(atomic_load_b(&info->indefinite_sleep, ATOMIC_ACQUIRE) == + (next_wakeup == BACKGROUND_THREAD_INDEFINITE_SLEEP)); + return next_wakeup; +} + +JEMALLOC_ALWAYS_INLINE void +background_thread_wakeup_time_set(tsdn_t *tsdn, background_thread_info_t *info, + uint64_t wakeup_time) { + malloc_mutex_assert_owner(tsdn, &info->mtx); + atomic_store_b(&info->indefinite_sleep, + wakeup_time == BACKGROUND_THREAD_INDEFINITE_SLEEP, ATOMIC_RELEASE); + nstime_init(&info->next_wakeup, wakeup_time); +} + +JEMALLOC_ALWAYS_INLINE bool +background_thread_indefinite_sleep(background_thread_info_t *info) { + return atomic_load_b(&info->indefinite_sleep, ATOMIC_ACQUIRE); +} + +JEMALLOC_ALWAYS_INLINE void +arena_background_thread_inactivity_check(tsdn_t *tsdn, arena_t *arena, + bool is_background_thread) { + if (!background_thread_enabled() || is_background_thread) { + return; + } + background_thread_info_t *info = + arena_background_thread_info_get(arena); + if (background_thread_indefinite_sleep(info)) { + background_thread_interval_check(tsdn, arena, + &arena->decay_dirty, 0); + } +} + +#endif /* JEMALLOC_INTERNAL_BACKGROUND_THREAD_INLINES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_structs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_structs.h new file mode 100644 index 0000000000..e69a7d022b --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/background_thread_structs.h @@ -0,0 +1,52 @@ +#ifndef JEMALLOC_INTERNAL_BACKGROUND_THREAD_STRUCTS_H +#define JEMALLOC_INTERNAL_BACKGROUND_THREAD_STRUCTS_H + +/* This file really combines "structs" and "types", but only transitionally. */ + +#if defined(JEMALLOC_BACKGROUND_THREAD) || defined(JEMALLOC_LAZY_LOCK) +# define JEMALLOC_PTHREAD_CREATE_WRAPPER +#endif + +#define BACKGROUND_THREAD_INDEFINITE_SLEEP UINT64_MAX + +typedef enum { + background_thread_stopped, + background_thread_started, + /* Thread waits on the global lock when paused (for arena_reset). */ + background_thread_paused, +} background_thread_state_t; + +struct background_thread_info_s { +#ifdef JEMALLOC_BACKGROUND_THREAD + /* Background thread is pthread specific. */ + pthread_t thread; + pthread_cond_t cond; +#endif + malloc_mutex_t mtx; + background_thread_state_t state; + /* When true, it means no wakeup scheduled. */ + atomic_b_t indefinite_sleep; + /* Next scheduled wakeup time (absolute time in ns). */ + nstime_t next_wakeup; + /* + * Since the last background thread run, newly added number of pages + * that need to be purged by the next wakeup. This is adjusted on + * epoch advance, and is used to determine whether we should signal the + * background thread to wake up earlier. + */ + size_t npages_to_purge_new; + /* Stats: total number of runs since started. */ + uint64_t tot_n_runs; + /* Stats: total sleep time since started. */ + nstime_t tot_sleep_time; +}; +typedef struct background_thread_info_s background_thread_info_t; + +struct background_thread_stats_s { + size_t num_threads; + uint64_t num_runs; + nstime_t run_interval; +}; +typedef struct background_thread_stats_s background_thread_stats_t; + +#endif /* JEMALLOC_INTERNAL_BACKGROUND_THREAD_STRUCTS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_externs.h new file mode 100644 index 0000000000..a4fd5ac7d9 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_externs.h @@ -0,0 +1,19 @@ +#ifndef JEMALLOC_INTERNAL_BASE_EXTERNS_H +#define JEMALLOC_INTERNAL_BASE_EXTERNS_H + +base_t *b0get(void); +base_t *base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks); +void base_delete(tsdn_t *tsdn, base_t *base); +extent_hooks_t *base_extent_hooks_get(base_t *base); +extent_hooks_t *base_extent_hooks_set(base_t *base, + extent_hooks_t *extent_hooks); +void *base_alloc(tsdn_t *tsdn, base_t *base, size_t size, size_t alignment); +extent_t *base_alloc_extent(tsdn_t *tsdn, base_t *base); +void base_stats_get(tsdn_t *tsdn, base_t *base, size_t *allocated, + size_t *resident, size_t *mapped); +void base_prefork(tsdn_t *tsdn, base_t *base); +void base_postfork_parent(tsdn_t *tsdn, base_t *base); +void base_postfork_child(tsdn_t *tsdn, base_t *base); +bool base_boot(tsdn_t *tsdn); + +#endif /* JEMALLOC_INTERNAL_BASE_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_inlines.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_inlines.h new file mode 100644 index 0000000000..931560bfae --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_inlines.h @@ -0,0 +1,9 @@ +#ifndef JEMALLOC_INTERNAL_BASE_INLINES_H +#define JEMALLOC_INTERNAL_BASE_INLINES_H + +static inline unsigned +base_ind_get(const base_t *base) { + return base->ind; +} + +#endif /* JEMALLOC_INTERNAL_BASE_INLINES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_structs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_structs.h new file mode 100644 index 0000000000..18e227bd5a --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_structs.h @@ -0,0 +1,55 @@ +#ifndef JEMALLOC_INTERNAL_BASE_STRUCTS_H +#define JEMALLOC_INTERNAL_BASE_STRUCTS_H + +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/size_classes.h" + +/* Embedded at the beginning of every block of base-managed virtual memory. */ +struct base_block_s { + /* Total size of block's virtual memory mapping. */ + size_t size; + + /* Next block in list of base's blocks. */ + base_block_t *next; + + /* Tracks unused trailing space. */ + extent_t extent; +}; + +struct base_s { + /* Associated arena's index within the arenas array. */ + unsigned ind; + + /* + * User-configurable extent hook functions. Points to an + * extent_hooks_t. + */ + atomic_p_t extent_hooks; + + /* Protects base_alloc() and base_stats_get() operations. */ + malloc_mutex_t mtx; + + /* + * Most recent size class in the series of increasingly large base + * extents. Logarithmic spacing between subsequent allocations ensures + * that the total number of distinct mappings remains small. + */ + pszind_t pind_last; + + /* Serial number generation state. */ + size_t extent_sn_next; + + /* Chain of all blocks associated with base. */ + base_block_t *blocks; + + /* Heap of extents that track unused trailing space within blocks. */ + extent_heap_t avail[NSIZES]; + + /* Stats, only maintained if config_stats. */ + size_t allocated; + size_t resident; + size_t mapped; +}; + +#endif /* JEMALLOC_INTERNAL_BASE_STRUCTS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_types.h new file mode 100644 index 0000000000..be7ee82589 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/base_types.h @@ -0,0 +1,7 @@ +#ifndef JEMALLOC_INTERNAL_BASE_TYPES_H +#define JEMALLOC_INTERNAL_BASE_TYPES_H + +typedef struct base_block_s base_block_t; +typedef struct base_s base_t; + +#endif /* JEMALLOC_INTERNAL_BASE_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/bit_util.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/bit_util.h new file mode 100644 index 0000000000..8d078a8a35 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/bit_util.h @@ -0,0 +1,165 @@ +#ifndef JEMALLOC_INTERNAL_BIT_UTIL_H +#define JEMALLOC_INTERNAL_BIT_UTIL_H + +#include "jemalloc/internal/assert.h" + +#define BIT_UTIL_INLINE static inline + +/* Sanity check. */ +#if !defined(JEMALLOC_INTERNAL_FFSLL) || !defined(JEMALLOC_INTERNAL_FFSL) \ + || !defined(JEMALLOC_INTERNAL_FFS) +# error JEMALLOC_INTERNAL_FFS{,L,LL} should have been defined by configure +#endif + + +BIT_UTIL_INLINE unsigned +ffs_llu(unsigned long long bitmap) { + return JEMALLOC_INTERNAL_FFSLL(bitmap); +} + +BIT_UTIL_INLINE unsigned +ffs_lu(unsigned long bitmap) { + return JEMALLOC_INTERNAL_FFSL(bitmap); +} + +BIT_UTIL_INLINE unsigned +ffs_u(unsigned bitmap) { + return JEMALLOC_INTERNAL_FFS(bitmap); +} + +BIT_UTIL_INLINE unsigned +ffs_zu(size_t bitmap) { +#if LG_SIZEOF_PTR == LG_SIZEOF_INT + return ffs_u(bitmap); +#elif LG_SIZEOF_PTR == LG_SIZEOF_LONG + return ffs_lu(bitmap); +#elif LG_SIZEOF_PTR == LG_SIZEOF_LONG_LONG + return ffs_llu(bitmap); +#else +#error No implementation for size_t ffs() +#endif +} + +BIT_UTIL_INLINE unsigned +ffs_u64(uint64_t bitmap) { +#if LG_SIZEOF_LONG == 3 + return ffs_lu(bitmap); +#elif LG_SIZEOF_LONG_LONG == 3 + return ffs_llu(bitmap); +#else +#error No implementation for 64-bit ffs() +#endif +} + +BIT_UTIL_INLINE unsigned +ffs_u32(uint32_t bitmap) { +#if LG_SIZEOF_INT == 2 + return ffs_u(bitmap); +#else +#error No implementation for 32-bit ffs() +#endif + return ffs_u(bitmap); +} + +BIT_UTIL_INLINE uint64_t +pow2_ceil_u64(uint64_t x) { + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + x++; + return x; +} + +BIT_UTIL_INLINE uint32_t +pow2_ceil_u32(uint32_t x) { + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return x; +} + +/* Compute the smallest power of 2 that is >= x. */ +BIT_UTIL_INLINE size_t +pow2_ceil_zu(size_t x) { +#if (LG_SIZEOF_PTR == 3) + return pow2_ceil_u64(x); +#else + return pow2_ceil_u32(x); +#endif +} + +#if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) +BIT_UTIL_INLINE unsigned +lg_floor(size_t x) { + size_t ret; + assert(x != 0); + + asm ("bsr %1, %0" + : "=r"(ret) // Outputs. + : "r"(x) // Inputs. + ); + assert(ret < UINT_MAX); + return (unsigned)ret; +} +#elif (defined(_MSC_VER)) +BIT_UTIL_INLINE unsigned +lg_floor(size_t x) { + unsigned long ret; + + assert(x != 0); + +#if (LG_SIZEOF_PTR == 3) + _BitScanReverse64(&ret, x); +#elif (LG_SIZEOF_PTR == 2) + _BitScanReverse(&ret, x); +#else +# error "Unsupported type size for lg_floor()" +#endif + assert(ret < UINT_MAX); + return (unsigned)ret; +} +#elif (defined(JEMALLOC_HAVE_BUILTIN_CLZ)) +BIT_UTIL_INLINE unsigned +lg_floor(size_t x) { + assert(x != 0); + +#if (LG_SIZEOF_PTR == LG_SIZEOF_INT) + return ((8 << LG_SIZEOF_PTR) - 1) - __builtin_clz(x); +#elif (LG_SIZEOF_PTR == LG_SIZEOF_LONG) + return ((8 << LG_SIZEOF_PTR) - 1) - __builtin_clzl(x); +#else +# error "Unsupported type size for lg_floor()" +#endif +} +#else +BIT_UTIL_INLINE unsigned +lg_floor(size_t x) { + assert(x != 0); + + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); +#if (LG_SIZEOF_PTR == 3) + x |= (x >> 32); +#endif + if (x == SIZE_T_MAX) { + return (8 << LG_SIZEOF_PTR) - 1; + } + x++; + return ffs_zu(x) - 2; +} +#endif + +#undef BIT_UTIL_INLINE + +#endif /* JEMALLOC_INTERNAL_BIT_UTIL_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_dss.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_dss.h new file mode 100644 index 0000000000..e8f02ce2ad --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_dss.h @@ -0,0 +1,26 @@ +#ifndef JEMALLOC_INTERNAL_EXTENT_DSS_H +#define JEMALLOC_INTERNAL_EXTENT_DSS_H + +typedef enum { + dss_prec_disabled = 0, + dss_prec_primary = 1, + dss_prec_secondary = 2, + + dss_prec_limit = 3 +} dss_prec_t; +#define DSS_PREC_DEFAULT dss_prec_secondary +#define DSS_DEFAULT "secondary" + +extern const char *dss_prec_names[]; + +extern const char *opt_dss; + +dss_prec_t extent_dss_prec_get(void); +bool extent_dss_prec_set(dss_prec_t dss_prec); +void *extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, + size_t size, size_t alignment, bool *zero, bool *commit); +bool extent_in_dss(void *addr); +bool extent_dss_mergeable(void *addr_a, void *addr_b); +void extent_dss_boot(void); + +#endif /* JEMALLOC_INTERNAL_EXTENT_DSS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_externs.h new file mode 100644 index 0000000000..489a813c80 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_externs.h @@ -0,0 +1,72 @@ +#ifndef JEMALLOC_INTERNAL_EXTENT_EXTERNS_H +#define JEMALLOC_INTERNAL_EXTENT_EXTERNS_H + +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/mutex_pool.h" +#include "jemalloc/internal/ph.h" +#include "jemalloc/internal/rb.h" +#include "jemalloc/internal/rtree.h" + +extern rtree_t extents_rtree; +extern const extent_hooks_t extent_hooks_default; +extern mutex_pool_t extent_mutex_pool; + +extent_t *extent_alloc(tsdn_t *tsdn, arena_t *arena); +void extent_dalloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent); + +extent_hooks_t *extent_hooks_get(arena_t *arena); +extent_hooks_t *extent_hooks_set(tsd_t *tsd, arena_t *arena, + extent_hooks_t *extent_hooks); + +#ifdef JEMALLOC_JET +size_t extent_size_quantize_floor(size_t size); +size_t extent_size_quantize_ceil(size_t size); +#endif + +rb_proto(, extent_avail_, extent_tree_t, extent_t) +ph_proto(, extent_heap_, extent_heap_t, extent_t) + +bool extents_init(tsdn_t *tsdn, extents_t *extents, extent_state_t state, + bool delay_coalesce); +extent_state_t extents_state_get(const extents_t *extents); +size_t extents_npages_get(extents_t *extents); +extent_t *extents_alloc(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extents_t *extents, void *new_addr, + size_t size, size_t pad, size_t alignment, bool slab, szind_t szind, + bool *zero, bool *commit); +void extents_dalloc(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extents_t *extents, extent_t *extent); +extent_t *extents_evict(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extents_t *extents, size_t npages_min); +void extents_prefork(tsdn_t *tsdn, extents_t *extents); +void extents_postfork_parent(tsdn_t *tsdn, extents_t *extents); +void extents_postfork_child(tsdn_t *tsdn, extents_t *extents); +extent_t *extent_alloc_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, void *new_addr, size_t size, size_t pad, + size_t alignment, bool slab, szind_t szind, bool *zero, bool *commit); +void extent_dalloc_gap(tsdn_t *tsdn, arena_t *arena, extent_t *extent); +void extent_dalloc_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent); +void extent_destroy_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent); +bool extent_commit_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length); +bool extent_decommit_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length); +bool extent_purge_lazy_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length); +bool extent_purge_forced_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t offset, + size_t length); +extent_t *extent_split_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *extent, size_t size_a, + szind_t szind_a, bool slab_a, size_t size_b, szind_t szind_b, bool slab_b); +bool extent_merge_wrapper(tsdn_t *tsdn, arena_t *arena, + extent_hooks_t **r_extent_hooks, extent_t *a, extent_t *b); + +bool extent_boot(void); + +#endif /* JEMALLOC_INTERNAL_EXTENT_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_inlines.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_inlines.h new file mode 100644 index 0000000000..bb2bd699ed --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_inlines.h @@ -0,0 +1,407 @@ +#ifndef JEMALLOC_INTERNAL_EXTENT_INLINES_H +#define JEMALLOC_INTERNAL_EXTENT_INLINES_H + +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/mutex_pool.h" +#include "jemalloc/internal/pages.h" +#include "jemalloc/internal/prng.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/sz.h" + +static inline void +extent_lock(tsdn_t *tsdn, extent_t *extent) { + assert(extent != NULL); + mutex_pool_lock(tsdn, &extent_mutex_pool, (uintptr_t)extent); +} + +static inline void +extent_unlock(tsdn_t *tsdn, extent_t *extent) { + assert(extent != NULL); + mutex_pool_unlock(tsdn, &extent_mutex_pool, (uintptr_t)extent); +} + +static inline void +extent_lock2(tsdn_t *tsdn, extent_t *extent1, extent_t *extent2) { + assert(extent1 != NULL && extent2 != NULL); + mutex_pool_lock2(tsdn, &extent_mutex_pool, (uintptr_t)extent1, + (uintptr_t)extent2); +} + +static inline void +extent_unlock2(tsdn_t *tsdn, extent_t *extent1, extent_t *extent2) { + assert(extent1 != NULL && extent2 != NULL); + mutex_pool_unlock2(tsdn, &extent_mutex_pool, (uintptr_t)extent1, + (uintptr_t)extent2); +} + +static inline arena_t * +extent_arena_get(const extent_t *extent) { + unsigned arena_ind = (unsigned)((extent->e_bits & + EXTENT_BITS_ARENA_MASK) >> EXTENT_BITS_ARENA_SHIFT); + /* + * The following check is omitted because we should never actually read + * a NULL arena pointer. + */ + if (false && arena_ind >= MALLOCX_ARENA_LIMIT) { + return NULL; + } + assert(arena_ind < MALLOCX_ARENA_LIMIT); + return (arena_t *)atomic_load_p(&arenas[arena_ind], ATOMIC_ACQUIRE); +} + +static inline szind_t +extent_szind_get_maybe_invalid(const extent_t *extent) { + szind_t szind = (szind_t)((extent->e_bits & EXTENT_BITS_SZIND_MASK) >> + EXTENT_BITS_SZIND_SHIFT); + assert(szind <= NSIZES); + return szind; +} + +static inline szind_t +extent_szind_get(const extent_t *extent) { + szind_t szind = extent_szind_get_maybe_invalid(extent); + assert(szind < NSIZES); /* Never call when "invalid". */ + return szind; +} + +static inline size_t +extent_usize_get(const extent_t *extent) { + return sz_index2size(extent_szind_get(extent)); +} + +static inline size_t +extent_sn_get(const extent_t *extent) { + return (size_t)((extent->e_bits & EXTENT_BITS_SN_MASK) >> + EXTENT_BITS_SN_SHIFT); +} + +static inline extent_state_t +extent_state_get(const extent_t *extent) { + return (extent_state_t)((extent->e_bits & EXTENT_BITS_STATE_MASK) >> + EXTENT_BITS_STATE_SHIFT); +} + +static inline bool +extent_zeroed_get(const extent_t *extent) { + return (bool)((extent->e_bits & EXTENT_BITS_ZEROED_MASK) >> + EXTENT_BITS_ZEROED_SHIFT); +} + +static inline bool +extent_committed_get(const extent_t *extent) { + return (bool)((extent->e_bits & EXTENT_BITS_COMMITTED_MASK) >> + EXTENT_BITS_COMMITTED_SHIFT); +} + +static inline bool +extent_slab_get(const extent_t *extent) { + return (bool)((extent->e_bits & EXTENT_BITS_SLAB_MASK) >> + EXTENT_BITS_SLAB_SHIFT); +} + +static inline unsigned +extent_nfree_get(const extent_t *extent) { + assert(extent_slab_get(extent)); + return (unsigned)((extent->e_bits & EXTENT_BITS_NFREE_MASK) >> + EXTENT_BITS_NFREE_SHIFT); +} + +static inline void * +extent_base_get(const extent_t *extent) { + assert(extent->e_addr == PAGE_ADDR2BASE(extent->e_addr) || + !extent_slab_get(extent)); + return PAGE_ADDR2BASE(extent->e_addr); +} + +static inline void * +extent_addr_get(const extent_t *extent) { + assert(extent->e_addr == PAGE_ADDR2BASE(extent->e_addr) || + !extent_slab_get(extent)); + return extent->e_addr; +} + +static inline size_t +extent_size_get(const extent_t *extent) { + return (extent->e_size_esn & EXTENT_SIZE_MASK); +} + +static inline size_t +extent_esn_get(const extent_t *extent) { + return (extent->e_size_esn & EXTENT_ESN_MASK); +} + +static inline size_t +extent_bsize_get(const extent_t *extent) { + return extent->e_bsize; +} + +static inline void * +extent_before_get(const extent_t *extent) { + return (void *)((uintptr_t)extent_base_get(extent) - PAGE); +} + +static inline void * +extent_last_get(const extent_t *extent) { + return (void *)((uintptr_t)extent_base_get(extent) + + extent_size_get(extent) - PAGE); +} + +static inline void * +extent_past_get(const extent_t *extent) { + return (void *)((uintptr_t)extent_base_get(extent) + + extent_size_get(extent)); +} + +static inline arena_slab_data_t * +extent_slab_data_get(extent_t *extent) { + assert(extent_slab_get(extent)); + return &extent->e_slab_data; +} + +static inline const arena_slab_data_t * +extent_slab_data_get_const(const extent_t *extent) { + assert(extent_slab_get(extent)); + return &extent->e_slab_data; +} + +static inline prof_tctx_t * +extent_prof_tctx_get(const extent_t *extent) { + return (prof_tctx_t *)atomic_load_p(&extent->e_prof_tctx, + ATOMIC_ACQUIRE); +} + +static inline void +extent_arena_set(extent_t *extent, arena_t *arena) { + unsigned arena_ind = (arena != NULL) ? arena_ind_get(arena) : ((1U << + MALLOCX_ARENA_BITS) - 1); + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_ARENA_MASK) | + ((uint64_t)arena_ind << EXTENT_BITS_ARENA_SHIFT); +} + +static inline void +extent_addr_set(extent_t *extent, void *addr) { + extent->e_addr = addr; +} + +static inline void +extent_addr_randomize(tsdn_t *tsdn, extent_t *extent, size_t alignment) { + assert(extent_base_get(extent) == extent_addr_get(extent)); + + if (alignment < PAGE) { + unsigned lg_range = LG_PAGE - + lg_floor(CACHELINE_CEILING(alignment)); + size_t r = + prng_lg_range_zu(&extent_arena_get(extent)->offset_state, + lg_range, true); + uintptr_t random_offset = ((uintptr_t)r) << (LG_PAGE - + lg_range); + extent->e_addr = (void *)((uintptr_t)extent->e_addr + + random_offset); + assert(ALIGNMENT_ADDR2BASE(extent->e_addr, alignment) == + extent->e_addr); + } +} + +static inline void +extent_size_set(extent_t *extent, size_t size) { + assert((size & ~EXTENT_SIZE_MASK) == 0); + extent->e_size_esn = size | (extent->e_size_esn & ~EXTENT_SIZE_MASK); +} + +static inline void +extent_esn_set(extent_t *extent, size_t esn) { + extent->e_size_esn = (extent->e_size_esn & ~EXTENT_ESN_MASK) | (esn & + EXTENT_ESN_MASK); +} + +static inline void +extent_bsize_set(extent_t *extent, size_t bsize) { + extent->e_bsize = bsize; +} + +static inline void +extent_szind_set(extent_t *extent, szind_t szind) { + assert(szind <= NSIZES); /* NSIZES means "invalid". */ + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SZIND_MASK) | + ((uint64_t)szind << EXTENT_BITS_SZIND_SHIFT); +} + +static inline void +extent_nfree_set(extent_t *extent, unsigned nfree) { + assert(extent_slab_get(extent)); + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_NFREE_MASK) | + ((uint64_t)nfree << EXTENT_BITS_NFREE_SHIFT); +} + +static inline void +extent_nfree_inc(extent_t *extent) { + assert(extent_slab_get(extent)); + extent->e_bits += ((uint64_t)1U << EXTENT_BITS_NFREE_SHIFT); +} + +static inline void +extent_nfree_dec(extent_t *extent) { + assert(extent_slab_get(extent)); + extent->e_bits -= ((uint64_t)1U << EXTENT_BITS_NFREE_SHIFT); +} + +static inline void +extent_sn_set(extent_t *extent, size_t sn) { + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SN_MASK) | + ((uint64_t)sn << EXTENT_BITS_SN_SHIFT); +} + +static inline void +extent_state_set(extent_t *extent, extent_state_t state) { + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_STATE_MASK) | + ((uint64_t)state << EXTENT_BITS_STATE_SHIFT); +} + +static inline void +extent_zeroed_set(extent_t *extent, bool zeroed) { + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_ZEROED_MASK) | + ((uint64_t)zeroed << EXTENT_BITS_ZEROED_SHIFT); +} + +static inline void +extent_committed_set(extent_t *extent, bool committed) { + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_COMMITTED_MASK) | + ((uint64_t)committed << EXTENT_BITS_COMMITTED_SHIFT); +} + +static inline void +extent_slab_set(extent_t *extent, bool slab) { + extent->e_bits = (extent->e_bits & ~EXTENT_BITS_SLAB_MASK) | + ((uint64_t)slab << EXTENT_BITS_SLAB_SHIFT); +} + +static inline void +extent_prof_tctx_set(extent_t *extent, prof_tctx_t *tctx) { + atomic_store_p(&extent->e_prof_tctx, tctx, ATOMIC_RELEASE); +} + +static inline void +extent_init(extent_t *extent, arena_t *arena, void *addr, size_t size, + bool slab, szind_t szind, size_t sn, extent_state_t state, bool zeroed, + bool committed) { + assert(addr == PAGE_ADDR2BASE(addr) || !slab); + + extent_arena_set(extent, arena); + extent_addr_set(extent, addr); + extent_size_set(extent, size); + extent_slab_set(extent, slab); + extent_szind_set(extent, szind); + extent_sn_set(extent, sn); + extent_state_set(extent, state); + extent_zeroed_set(extent, zeroed); + extent_committed_set(extent, committed); + ql_elm_new(extent, ql_link); + if (config_prof) { + extent_prof_tctx_set(extent, NULL); + } +} + +static inline void +extent_binit(extent_t *extent, void *addr, size_t bsize, size_t sn) { + extent_arena_set(extent, NULL); + extent_addr_set(extent, addr); + extent_bsize_set(extent, bsize); + extent_slab_set(extent, false); + extent_szind_set(extent, NSIZES); + extent_sn_set(extent, sn); + extent_state_set(extent, extent_state_active); + extent_zeroed_set(extent, true); + extent_committed_set(extent, true); +} + +static inline void +extent_list_init(extent_list_t *list) { + ql_new(list); +} + +static inline extent_t * +extent_list_first(const extent_list_t *list) { + return ql_first(list); +} + +static inline extent_t * +extent_list_last(const extent_list_t *list) { + return ql_last(list, ql_link); +} + +static inline void +extent_list_append(extent_list_t *list, extent_t *extent) { + ql_tail_insert(list, extent, ql_link); +} + +static inline void +extent_list_replace(extent_list_t *list, extent_t *to_remove, + extent_t *to_insert) { + ql_after_insert(to_remove, to_insert, ql_link); + ql_remove(list, to_remove, ql_link); +} + +static inline void +extent_list_remove(extent_list_t *list, extent_t *extent) { + ql_remove(list, extent, ql_link); +} + +static inline int +extent_sn_comp(const extent_t *a, const extent_t *b) { + size_t a_sn = extent_sn_get(a); + size_t b_sn = extent_sn_get(b); + + return (a_sn > b_sn) - (a_sn < b_sn); +} + +static inline int +extent_esn_comp(const extent_t *a, const extent_t *b) { + size_t a_esn = extent_esn_get(a); + size_t b_esn = extent_esn_get(b); + + return (a_esn > b_esn) - (a_esn < b_esn); +} + +static inline int +extent_ad_comp(const extent_t *a, const extent_t *b) { + uintptr_t a_addr = (uintptr_t)extent_addr_get(a); + uintptr_t b_addr = (uintptr_t)extent_addr_get(b); + + return (a_addr > b_addr) - (a_addr < b_addr); +} + +static inline int +extent_ead_comp(const extent_t *a, const extent_t *b) { + uintptr_t a_eaddr = (uintptr_t)a; + uintptr_t b_eaddr = (uintptr_t)b; + + return (a_eaddr > b_eaddr) - (a_eaddr < b_eaddr); +} + +static inline int +extent_snad_comp(const extent_t *a, const extent_t *b) { + int ret; + + ret = extent_sn_comp(a, b); + if (ret != 0) { + return ret; + } + + ret = extent_ad_comp(a, b); + return ret; +} + +static inline int +extent_esnead_comp(const extent_t *a, const extent_t *b) { + int ret; + + ret = extent_esn_comp(a, b); + if (ret != 0) { + return ret; + } + + ret = extent_ead_comp(a, b); + return ret; +} + +#endif /* JEMALLOC_INTERNAL_EXTENT_INLINES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_mmap.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_mmap.h new file mode 100644 index 0000000000..55f17ee487 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_mmap.h @@ -0,0 +1,10 @@ +#ifndef JEMALLOC_INTERNAL_EXTENT_MMAP_EXTERNS_H +#define JEMALLOC_INTERNAL_EXTENT_MMAP_EXTERNS_H + +extern bool opt_retain; + +void *extent_alloc_mmap(void *new_addr, size_t size, size_t alignment, + bool *zero, bool *commit); +bool extent_dalloc_mmap(void *addr, size_t size); + +#endif /* JEMALLOC_INTERNAL_EXTENT_MMAP_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_structs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_structs.h new file mode 100644 index 0000000000..d297950345 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_structs.h @@ -0,0 +1,199 @@ +#ifndef JEMALLOC_INTERNAL_EXTENT_STRUCTS_H +#define JEMALLOC_INTERNAL_EXTENT_STRUCTS_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/bitmap.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/rb.h" +#include "jemalloc/internal/ph.h" +#include "jemalloc/internal/size_classes.h" + +typedef enum { + extent_state_active = 0, + extent_state_dirty = 1, + extent_state_muzzy = 2, + extent_state_retained = 3 +} extent_state_t; + +/* Extent (span of pages). Use accessor functions for e_* fields. */ +struct extent_s { + /* + * Bitfield containing several fields: + * + * a: arena_ind + * b: slab + * c: committed + * z: zeroed + * t: state + * i: szind + * f: nfree + * n: sn + * + * nnnnnnnn ... nnnnnfff fffffffi iiiiiiit tzcbaaaa aaaaaaaa + * + * arena_ind: Arena from which this extent came, or all 1 bits if + * unassociated. + * + * slab: The slab flag indicates whether the extent is used for a slab + * of small regions. This helps differentiate small size classes, + * and it indicates whether interior pointers can be looked up via + * iealloc(). + * + * committed: The committed flag indicates whether physical memory is + * committed to the extent, whether explicitly or implicitly + * as on a system that overcommits and satisfies physical + * memory needs on demand via soft page faults. + * + * zeroed: The zeroed flag is used by extent recycling code to track + * whether memory is zero-filled. + * + * state: The state flag is an extent_state_t. + * + * szind: The szind flag indicates usable size class index for + * allocations residing in this extent, regardless of whether the + * extent is a slab. Extent size and usable size often differ + * even for non-slabs, either due to sz_large_pad or promotion of + * sampled small regions. + * + * nfree: Number of free regions in slab. + * + * sn: Serial number (potentially non-unique). + * + * Serial numbers may wrap around if !opt_retain, but as long as + * comparison functions fall back on address comparison for equal + * serial numbers, stable (if imperfect) ordering is maintained. + * + * Serial numbers may not be unique even in the absence of + * wrap-around, e.g. when splitting an extent and assigning the same + * serial number to both resulting adjacent extents. + */ + uint64_t e_bits; +#define EXTENT_BITS_ARENA_SHIFT 0 +#define EXTENT_BITS_ARENA_MASK \ + (((uint64_t)(1U << MALLOCX_ARENA_BITS) - 1) << EXTENT_BITS_ARENA_SHIFT) + +#define EXTENT_BITS_SLAB_SHIFT MALLOCX_ARENA_BITS +#define EXTENT_BITS_SLAB_MASK \ + ((uint64_t)0x1U << EXTENT_BITS_SLAB_SHIFT) + +#define EXTENT_BITS_COMMITTED_SHIFT (MALLOCX_ARENA_BITS + 1) +#define EXTENT_BITS_COMMITTED_MASK \ + ((uint64_t)0x1U << EXTENT_BITS_COMMITTED_SHIFT) + +#define EXTENT_BITS_ZEROED_SHIFT (MALLOCX_ARENA_BITS + 2) +#define EXTENT_BITS_ZEROED_MASK \ + ((uint64_t)0x1U << EXTENT_BITS_ZEROED_SHIFT) + +#define EXTENT_BITS_STATE_SHIFT (MALLOCX_ARENA_BITS + 3) +#define EXTENT_BITS_STATE_MASK \ + ((uint64_t)0x3U << EXTENT_BITS_STATE_SHIFT) + +#define EXTENT_BITS_SZIND_SHIFT (MALLOCX_ARENA_BITS + 5) +#define EXTENT_BITS_SZIND_MASK \ + (((uint64_t)(1U << LG_CEIL_NSIZES) - 1) << EXTENT_BITS_SZIND_SHIFT) + +#define EXTENT_BITS_NFREE_SHIFT \ + (MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES) +#define EXTENT_BITS_NFREE_MASK \ + ((uint64_t)((1U << (LG_SLAB_MAXREGS + 1)) - 1) << EXTENT_BITS_NFREE_SHIFT) + +#define EXTENT_BITS_SN_SHIFT \ + (MALLOCX_ARENA_BITS + 5 + LG_CEIL_NSIZES + (LG_SLAB_MAXREGS + 1)) +#define EXTENT_BITS_SN_MASK (UINT64_MAX << EXTENT_BITS_SN_SHIFT) + + /* Pointer to the extent that this structure is responsible for. */ + void *e_addr; + + union { + /* + * Extent size and serial number associated with the extent + * structure (different than the serial number for the extent at + * e_addr). + * + * ssssssss [...] ssssssss ssssnnnn nnnnnnnn + */ + size_t e_size_esn; + #define EXTENT_SIZE_MASK ((size_t)~(PAGE-1)) + #define EXTENT_ESN_MASK ((size_t)PAGE-1) + /* Base extent size, which may not be a multiple of PAGE. */ + size_t e_bsize; + }; + + union { + /* + * List linkage, used by a variety of lists: + * - arena_bin_t's slabs_full + * - extents_t's LRU + * - stashed dirty extents + * - arena's large allocations + */ + ql_elm(extent_t) ql_link; + /* Red-black tree linkage, used by arena's extent_avail. */ + rb_node(extent_t) rb_link; + }; + + /* Linkage for per size class sn/address-ordered heaps. */ + phn(extent_t) ph_link; + + union { + /* Small region slab metadata. */ + arena_slab_data_t e_slab_data; + + /* + * Profile counters, used for large objects. Points to a + * prof_tctx_t. + */ + atomic_p_t e_prof_tctx; + }; +}; +typedef ql_head(extent_t) extent_list_t; +typedef rb_tree(extent_t) extent_tree_t; +typedef ph(extent_t) extent_heap_t; + +/* Quantized collection of extents, with built-in LRU queue. */ +struct extents_s { + malloc_mutex_t mtx; + + /* + * Quantized per size class heaps of extents. + * + * Synchronization: mtx. + */ + extent_heap_t heaps[NPSIZES+1]; + + /* + * Bitmap for which set bits correspond to non-empty heaps. + * + * Synchronization: mtx. + */ + bitmap_t bitmap[BITMAP_GROUPS(NPSIZES+1)]; + + /* + * LRU of all extents in heaps. + * + * Synchronization: mtx. + */ + extent_list_t lru; + + /* + * Page sum for all extents in heaps. + * + * The synchronization here is a little tricky. Modifications to npages + * must hold mtx, but reads need not (though, a reader who sees npages + * without holding the mutex can't assume anything about the rest of the + * state of the extents_t). + */ + atomic_zu_t npages; + + /* All stored extents must be in the same state. */ + extent_state_t state; + + /* + * If true, delay coalescing until eviction; otherwise coalesce during + * deallocation. + */ + bool delay_coalesce; +}; + +#endif /* JEMALLOC_INTERNAL_EXTENT_STRUCTS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_types.h new file mode 100644 index 0000000000..b6905ce105 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/extent_types.h @@ -0,0 +1,9 @@ +#ifndef JEMALLOC_INTERNAL_EXTENT_TYPES_H +#define JEMALLOC_INTERNAL_EXTENT_TYPES_H + +typedef struct extent_s extent_t; +typedef struct extents_s extents_t; + +#define EXTENT_HOOKS_INITIALIZER NULL + +#endif /* JEMALLOC_INTERNAL_EXTENT_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/hooks.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/hooks.h new file mode 100644 index 0000000000..cd49afcb09 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/hooks.h @@ -0,0 +1,19 @@ +#ifndef JEMALLOC_INTERNAL_HOOKS_H +#define JEMALLOC_INTERNAL_HOOKS_H + +extern JEMALLOC_EXPORT void (*hooks_arena_new_hook)(); +extern JEMALLOC_EXPORT void (*hooks_libc_hook)(); + +#define JEMALLOC_HOOK(fn, hook) ((void)(hook != NULL && (hook(), 0)), fn) + +#define open JEMALLOC_HOOK(open, hooks_libc_hook) +#define read JEMALLOC_HOOK(read, hooks_libc_hook) +#define write JEMALLOC_HOOK(write, hooks_libc_hook) +#define readlink JEMALLOC_HOOK(readlink, hooks_libc_hook) +#define close JEMALLOC_HOOK(close, hooks_libc_hook) +#define creat JEMALLOC_HOOK(creat, hooks_libc_hook) +#define secure_getenv JEMALLOC_HOOK(secure_getenv, hooks_libc_hook) +/* Note that this is undef'd and re-define'd in src/prof.c. */ +#define _Unwind_Backtrace JEMALLOC_HOOK(_Unwind_Backtrace, hooks_libc_hook) + +#endif /* JEMALLOC_INTERNAL_HOOKS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h new file mode 100644 index 0000000000..8ae5ef48cd --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_decls.h @@ -0,0 +1,82 @@ +#ifndef JEMALLOC_INTERNAL_DECLS_H +#define JEMALLOC_INTERNAL_DECLS_H + +#include <math.h> +#ifdef _WIN32 +# include <windows.h> +# include "msvc_compat/windows_extra.h" + +#else +# include <sys/param.h> +# include <sys/mman.h> +# if !defined(__pnacl__) && !defined(__native_client__) +# include <sys/syscall.h> +# if !defined(SYS_write) && defined(__NR_write) +# define SYS_write __NR_write +# endif +# if defined(SYS_open) && defined(__aarch64__) + /* Android headers may define SYS_open to __NR_open even though + * __NR_open may not exist on AArch64 (superseded by __NR_openat). */ +# undef SYS_open +# endif +# include <sys/uio.h> +# endif +# include <pthread.h> +# include <signal.h> +# ifdef JEMALLOC_OS_UNFAIR_LOCK +# include <os/lock.h> +# endif +# ifdef JEMALLOC_GLIBC_MALLOC_HOOK +# include <sched.h> +# endif +# include <errno.h> +# include <sys/time.h> +# include <time.h> +# ifdef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME +# include <mach/mach_time.h> +# endif +#endif +#include <sys/types.h> + +#include <limits.h> +#ifndef SIZE_T_MAX +# define SIZE_T_MAX SIZE_MAX +#endif +#ifndef SSIZE_MAX +# define SSIZE_MAX ((ssize_t)(SIZE_T_MAX >> 1)) +#endif +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#ifndef offsetof +# define offsetof(type, member) ((size_t)&(((type *)NULL)->member)) +#endif +#include <string.h> +#include <strings.h> +#include <ctype.h> +#ifdef _MSC_VER +# include <io.h> +typedef intptr_t ssize_t; +# define PATH_MAX 1024 +# define STDERR_FILENO 2 +# define __func__ __FUNCTION__ +# ifdef JEMALLOC_HAS_RESTRICT +# define restrict __restrict +# endif +/* Disable warnings about deprecated system functions. */ +# pragma warning(disable: 4996) +#if _MSC_VER < 1800 +static int +isblank(int c) { + return (c == '\t' || c == ' '); +} +#endif +#else +# include <unistd.h> +#endif +#include <fcntl.h> + +#endif /* JEMALLOC_INTERNAL_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h new file mode 100644 index 0000000000..e10fb275d4 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_externs.h @@ -0,0 +1,53 @@ +#ifndef JEMALLOC_INTERNAL_EXTERNS_H +#define JEMALLOC_INTERNAL_EXTERNS_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/tsd_types.h" + +/* TSD checks this to set thread local slow state accordingly. */ +extern bool malloc_slow; + +/* Run-time options. */ +extern bool opt_abort; +extern bool opt_abort_conf; +extern const char *opt_junk; +extern bool opt_junk_alloc; +extern bool opt_junk_free; +extern bool opt_utrace; +extern bool opt_xmalloc; +extern bool opt_zero; +extern unsigned opt_narenas; + +/* Number of CPUs. */ +extern unsigned ncpus; + +/* Number of arenas used for automatic multiplexing of threads and arenas. */ +extern unsigned narenas_auto; + +/* + * Arenas that are used to service external requests. Not all elements of the + * arenas array are necessarily used; arenas are created lazily as needed. + */ +extern atomic_p_t arenas[]; + +void *a0malloc(size_t size); +void a0dalloc(void *ptr); +void *bootstrap_malloc(size_t size); +void *bootstrap_calloc(size_t num, size_t size); +void bootstrap_free(void *ptr); +void arena_set(unsigned ind, arena_t *arena); +unsigned narenas_total_get(void); +arena_t *arena_init(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks); +arena_tdata_t *arena_tdata_get_hard(tsd_t *tsd, unsigned ind); +arena_t *arena_choose_hard(tsd_t *tsd, bool internal); +void arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind); +void iarena_cleanup(tsd_t *tsd); +void arena_cleanup(tsd_t *tsd); +void arenas_tdata_cleanup(tsd_t *tsd); +void jemalloc_prefork(void); +void jemalloc_postfork_parent(void); +void jemalloc_postfork_child(void); +bool malloc_initialized(void); + +#endif /* JEMALLOC_INTERNAL_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h new file mode 100644 index 0000000000..437eaa4079 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_includes.h @@ -0,0 +1,94 @@ +#ifndef JEMALLOC_INTERNAL_INCLUDES_H +#define JEMALLOC_INTERNAL_INCLUDES_H + +/* + * jemalloc can conceptually be broken into components (arena, tcache, etc.), + * but there are circular dependencies that cannot be broken without + * substantial performance degradation. + * + * Historically, we dealt with this by each header into four sections (types, + * structs, externs, and inlines), and included each header file multiple times + * in this file, picking out the portion we want on each pass using the + * following #defines: + * JEMALLOC_H_TYPES : Preprocessor-defined constants and psuedo-opaque data + * types. + * JEMALLOC_H_STRUCTS : Data structures. + * JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes. + * JEMALLOC_H_INLINES : Inline functions. + * + * We're moving toward a world in which the dependencies are explicit; each file + * will #include the headers it depends on (rather than relying on them being + * implicitly available via this file including every header file in the + * project). + * + * We're now in an intermediate state: we've broken up the header files to avoid + * having to include each one multiple times, but have not yet moved the + * dependency information into the header files (i.e. we still rely on the + * ordering in this file to ensure all a header's dependencies are available in + * its translation unit). Each component is now broken up into multiple header + * files, corresponding to the sections above (e.g. instead of "foo.h", we now + * have "foo_types.h", "foo_structs.h", "foo_externs.h", "foo_inlines.h"). + * + * Those files which have been converted to explicitly include their + * inter-component dependencies are now in the initial HERMETIC HEADERS + * section. All headers may still rely on jemalloc_preamble.h (which, by fiat, + * must be included first in every translation unit) for system headers and + * global jemalloc definitions, however. + */ + +/******************************************************************************/ +/* TYPES */ +/******************************************************************************/ + +#include "jemalloc/internal/extent_types.h" +#include "jemalloc/internal/base_types.h" +#include "jemalloc/internal/arena_types.h" +#include "jemalloc/internal/tcache_types.h" +#include "jemalloc/internal/prof_types.h" + +/******************************************************************************/ +/* STRUCTS */ +/******************************************************************************/ + +#include "jemalloc/internal/arena_structs_a.h" +#include "jemalloc/internal/extent_structs.h" +#include "jemalloc/internal/base_structs.h" +#include "jemalloc/internal/prof_structs.h" +#include "jemalloc/internal/arena_structs_b.h" +#include "jemalloc/internal/tcache_structs.h" +#include "jemalloc/internal/background_thread_structs.h" + +/******************************************************************************/ +/* EXTERNS */ +/******************************************************************************/ + +#include "jemalloc/internal/jemalloc_internal_externs.h" +#include "jemalloc/internal/extent_externs.h" +#include "jemalloc/internal/base_externs.h" +#include "jemalloc/internal/arena_externs.h" +#include "jemalloc/internal/large_externs.h" +#include "jemalloc/internal/tcache_externs.h" +#include "jemalloc/internal/prof_externs.h" +#include "jemalloc/internal/background_thread_externs.h" + +/******************************************************************************/ +/* INLINES */ +/******************************************************************************/ + +#include "jemalloc/internal/jemalloc_internal_inlines_a.h" +#include "jemalloc/internal/base_inlines.h" +/* + * Include portions of arena code interleaved with tcache code in order to + * resolve circular dependencies. + */ +#include "jemalloc/internal/prof_inlines_a.h" +#include "jemalloc/internal/arena_inlines_a.h" +#include "jemalloc/internal/extent_inlines.h" +#include "jemalloc/internal/jemalloc_internal_inlines_b.h" +#include "jemalloc/internal/tcache_inlines.h" +#include "jemalloc/internal/arena_inlines_b.h" +#include "jemalloc/internal/jemalloc_internal_inlines_c.h" +#include "jemalloc/internal/prof_inlines_b.h" +#include "jemalloc/internal/background_thread_inlines.h" + +#endif /* JEMALLOC_INTERNAL_INCLUDES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h new file mode 100644 index 0000000000..24ea416297 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_a.h @@ -0,0 +1,171 @@ +#ifndef JEMALLOC_INTERNAL_INLINES_A_H +#define JEMALLOC_INTERNAL_INLINES_A_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/bit_util.h" +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/ticker.h" + +JEMALLOC_ALWAYS_INLINE malloc_cpuid_t +malloc_getcpu(void) { + assert(have_percpu_arena); +#if defined(JEMALLOC_HAVE_SCHED_GETCPU) + return (malloc_cpuid_t)sched_getcpu(); +#else + not_reached(); + return -1; +#endif +} + +/* Return the chosen arena index based on current cpu. */ +JEMALLOC_ALWAYS_INLINE unsigned +percpu_arena_choose(void) { + assert(have_percpu_arena && PERCPU_ARENA_ENABLED(opt_percpu_arena)); + + malloc_cpuid_t cpuid = malloc_getcpu(); + assert(cpuid >= 0); + + unsigned arena_ind; + if ((opt_percpu_arena == percpu_arena) || ((unsigned)cpuid < ncpus / + 2)) { + arena_ind = cpuid; + } else { + assert(opt_percpu_arena == per_phycpu_arena); + /* Hyper threads on the same physical CPU share arena. */ + arena_ind = cpuid - ncpus / 2; + } + + return arena_ind; +} + +/* Return the limit of percpu auto arena range, i.e. arenas[0...ind_limit). */ +JEMALLOC_ALWAYS_INLINE unsigned +percpu_arena_ind_limit(percpu_arena_mode_t mode) { + assert(have_percpu_arena && PERCPU_ARENA_ENABLED(mode)); + if (mode == per_phycpu_arena && ncpus > 1) { + if (ncpus % 2) { + /* This likely means a misconfig. */ + return ncpus / 2 + 1; + } + return ncpus / 2; + } else { + return ncpus; + } +} + +static inline arena_tdata_t * +arena_tdata_get(tsd_t *tsd, unsigned ind, bool refresh_if_missing) { + arena_tdata_t *tdata; + arena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd); + + if (unlikely(arenas_tdata == NULL)) { + /* arenas_tdata hasn't been initialized yet. */ + return arena_tdata_get_hard(tsd, ind); + } + if (unlikely(ind >= tsd_narenas_tdata_get(tsd))) { + /* + * ind is invalid, cache is old (too small), or tdata to be + * initialized. + */ + return (refresh_if_missing ? arena_tdata_get_hard(tsd, ind) : + NULL); + } + + tdata = &arenas_tdata[ind]; + if (likely(tdata != NULL) || !refresh_if_missing) { + return tdata; + } + return arena_tdata_get_hard(tsd, ind); +} + +static inline arena_t * +arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing) { + arena_t *ret; + + assert(ind < MALLOCX_ARENA_LIMIT); + + ret = (arena_t *)atomic_load_p(&arenas[ind], ATOMIC_ACQUIRE); + if (unlikely(ret == NULL)) { + if (init_if_missing) { + ret = arena_init(tsdn, ind, + (extent_hooks_t *)&extent_hooks_default); + } + } + return ret; +} + +static inline ticker_t * +decay_ticker_get(tsd_t *tsd, unsigned ind) { + arena_tdata_t *tdata; + + tdata = arena_tdata_get(tsd, ind, true); + if (unlikely(tdata == NULL)) { + return NULL; + } + return &tdata->decay_ticker; +} + +JEMALLOC_ALWAYS_INLINE tcache_bin_t * +tcache_small_bin_get(tcache_t *tcache, szind_t binind) { + assert(binind < NBINS); + return &tcache->tbins_small[binind]; +} + +JEMALLOC_ALWAYS_INLINE tcache_bin_t * +tcache_large_bin_get(tcache_t *tcache, szind_t binind) { + assert(binind >= NBINS &&binind < nhbins); + return &tcache->tbins_large[binind - NBINS]; +} + +JEMALLOC_ALWAYS_INLINE bool +tcache_available(tsd_t *tsd) { + /* + * Thread specific auto tcache might be unavailable if: 1) during tcache + * initialization, or 2) disabled through thread.tcache.enabled mallctl + * or config options. This check covers all cases. + */ + if (likely(tsd_tcache_enabled_get(tsd))) { + /* Associated arena == NULL implies tcache init in progress. */ + assert(tsd_tcachep_get(tsd)->arena == NULL || + tcache_small_bin_get(tsd_tcachep_get(tsd), 0)->avail != + NULL); + return true; + } + + return false; +} + +JEMALLOC_ALWAYS_INLINE tcache_t * +tcache_get(tsd_t *tsd) { + if (!tcache_available(tsd)) { + return NULL; + } + + return tsd_tcachep_get(tsd); +} + +static inline void +pre_reentrancy(tsd_t *tsd, arena_t *arena) { + /* arena is the current context. Reentry from a0 is not allowed. */ + assert(arena != arena_get(tsd_tsdn(tsd), 0, false)); + + bool fast = tsd_fast(tsd); + ++*tsd_reentrancy_levelp_get(tsd); + if (fast) { + /* Prepare slow path for reentrancy. */ + tsd_slow_update(tsd); + assert(tsd->state == tsd_state_nominal_slow); + } +} + +static inline void +post_reentrancy(tsd_t *tsd) { + int8_t *reentrancy_level = tsd_reentrancy_levelp_get(tsd); + assert(*reentrancy_level > 0); + if (--*reentrancy_level == 0) { + tsd_slow_update(tsd); + } +} + +#endif /* JEMALLOC_INTERNAL_INLINES_A_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h new file mode 100644 index 0000000000..2e76e5d8f7 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_b.h @@ -0,0 +1,86 @@ +#ifndef JEMALLOC_INTERNAL_INLINES_B_H +#define JEMALLOC_INTERNAL_INLINES_B_H + +#include "jemalloc/internal/rtree.h" + +/* Choose an arena based on a per-thread value. */ +static inline arena_t * +arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal) { + arena_t *ret; + + if (arena != NULL) { + return arena; + } + + /* During reentrancy, arena 0 is the safest bet. */ + if (unlikely(tsd_reentrancy_level_get(tsd) > 0)) { + return arena_get(tsd_tsdn(tsd), 0, true); + } + + ret = internal ? tsd_iarena_get(tsd) : tsd_arena_get(tsd); + if (unlikely(ret == NULL)) { + ret = arena_choose_hard(tsd, internal); + assert(ret); + if (tcache_available(tsd)) { + tcache_t *tcache = tcache_get(tsd); + if (tcache->arena != NULL) { + /* See comments in tcache_data_init().*/ + assert(tcache->arena == + arena_get(tsd_tsdn(tsd), 0, false)); + if (tcache->arena != ret) { + tcache_arena_reassociate(tsd_tsdn(tsd), + tcache, ret); + } + } else { + tcache_arena_associate(tsd_tsdn(tsd), tcache, + ret); + } + } + } + + /* + * Note that for percpu arena, if the current arena is outside of the + * auto percpu arena range, (i.e. thread is assigned to a manually + * managed arena), then percpu arena is skipped. + */ + if (have_percpu_arena && PERCPU_ARENA_ENABLED(opt_percpu_arena) && + !internal && (arena_ind_get(ret) < + percpu_arena_ind_limit(opt_percpu_arena)) && (ret->last_thd != + tsd_tsdn(tsd))) { + unsigned ind = percpu_arena_choose(); + if (arena_ind_get(ret) != ind) { + percpu_arena_update(tsd, ind); + ret = tsd_arena_get(tsd); + } + ret->last_thd = tsd_tsdn(tsd); + } + + return ret; +} + +static inline arena_t * +arena_choose(tsd_t *tsd, arena_t *arena) { + return arena_choose_impl(tsd, arena, false); +} + +static inline arena_t * +arena_ichoose(tsd_t *tsd, arena_t *arena) { + return arena_choose_impl(tsd, arena, true); +} + +static inline bool +arena_is_auto(arena_t *arena) { + assert(narenas_auto > 0); + return (arena_ind_get(arena) < narenas_auto); +} + +JEMALLOC_ALWAYS_INLINE extent_t * +iealloc(tsdn_t *tsdn, const void *ptr) { + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + + return rtree_extent_read(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)ptr, true); +} + +#endif /* JEMALLOC_INTERNAL_INLINES_B_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h new file mode 100644 index 0000000000..7ffce6fb03 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_inlines_c.h @@ -0,0 +1,197 @@ +#ifndef JEMALLOC_INTERNAL_INLINES_C_H +#define JEMALLOC_INTERNAL_INLINES_C_H + +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/sz.h" +#include "jemalloc/internal/witness.h" + +JEMALLOC_ALWAYS_INLINE arena_t * +iaalloc(tsdn_t *tsdn, const void *ptr) { + assert(ptr != NULL); + + return arena_aalloc(tsdn, ptr); +} + +JEMALLOC_ALWAYS_INLINE size_t +isalloc(tsdn_t *tsdn, const void *ptr) { + assert(ptr != NULL); + + return arena_salloc(tsdn, ptr); +} + +JEMALLOC_ALWAYS_INLINE void * +iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache, + bool is_internal, arena_t *arena, bool slow_path) { + void *ret; + + assert(size != 0); + assert(!is_internal || tcache == NULL); + assert(!is_internal || arena == NULL || arena_is_auto(arena)); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + ret = arena_malloc(tsdn, arena, size, ind, zero, tcache, slow_path); + if (config_stats && is_internal && likely(ret != NULL)) { + arena_internal_add(iaalloc(tsdn, ret), isalloc(tsdn, ret)); + } + return ret; +} + +JEMALLOC_ALWAYS_INLINE void * +ialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero, bool slow_path) { + return iallocztm(tsd_tsdn(tsd), size, ind, zero, tcache_get(tsd), false, + NULL, slow_path); +} + +JEMALLOC_ALWAYS_INLINE void * +ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, + tcache_t *tcache, bool is_internal, arena_t *arena) { + void *ret; + + assert(usize != 0); + assert(usize == sz_sa2u(usize, alignment)); + assert(!is_internal || tcache == NULL); + assert(!is_internal || arena == NULL || arena_is_auto(arena)); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + ret = arena_palloc(tsdn, arena, usize, alignment, zero, tcache); + assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret); + if (config_stats && is_internal && likely(ret != NULL)) { + arena_internal_add(iaalloc(tsdn, ret), isalloc(tsdn, ret)); + } + return ret; +} + +JEMALLOC_ALWAYS_INLINE void * +ipalloct(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero, + tcache_t *tcache, arena_t *arena) { + return ipallocztm(tsdn, usize, alignment, zero, tcache, false, arena); +} + +JEMALLOC_ALWAYS_INLINE void * +ipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero) { + return ipallocztm(tsd_tsdn(tsd), usize, alignment, zero, + tcache_get(tsd), false, NULL); +} + +JEMALLOC_ALWAYS_INLINE size_t +ivsalloc(tsdn_t *tsdn, const void *ptr) { + return arena_vsalloc(tsdn, ptr); +} + +JEMALLOC_ALWAYS_INLINE void +idalloctm(tsdn_t *tsdn, void *ptr, tcache_t *tcache, alloc_ctx_t *alloc_ctx, + bool is_internal, bool slow_path) { + assert(ptr != NULL); + assert(!is_internal || tcache == NULL); + assert(!is_internal || arena_is_auto(iaalloc(tsdn, ptr))); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + if (config_stats && is_internal) { + arena_internal_sub(iaalloc(tsdn, ptr), isalloc(tsdn, ptr)); + } + if (!is_internal && tsd_reentrancy_level_get(tsdn_tsd(tsdn)) != 0) { + assert(tcache == NULL); + } + arena_dalloc(tsdn, ptr, tcache, alloc_ctx, slow_path); +} + +JEMALLOC_ALWAYS_INLINE void +idalloc(tsd_t *tsd, void *ptr) { + idalloctm(tsd_tsdn(tsd), ptr, tcache_get(tsd), NULL, false, true); +} + +JEMALLOC_ALWAYS_INLINE void +isdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache, + alloc_ctx_t *alloc_ctx, bool slow_path) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + arena_sdalloc(tsdn, ptr, size, tcache, alloc_ctx, slow_path); +} + +JEMALLOC_ALWAYS_INLINE void * +iralloct_realign(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, + size_t extra, size_t alignment, bool zero, tcache_t *tcache, + arena_t *arena) { + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + void *p; + size_t usize, copysize; + + usize = sz_sa2u(size + extra, alignment); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + return NULL; + } + p = ipalloct(tsdn, usize, alignment, zero, tcache, arena); + if (p == NULL) { + if (extra == 0) { + return NULL; + } + /* Try again, without extra this time. */ + usize = sz_sa2u(size, alignment); + if (unlikely(usize == 0 || usize > LARGE_MAXCLASS)) { + return NULL; + } + p = ipalloct(tsdn, usize, alignment, zero, tcache, arena); + if (p == NULL) { + return NULL; + } + } + /* + * Copy at most size bytes (not size+extra), since the caller has no + * expectation that the extra bytes will be reliably preserved. + */ + copysize = (size < oldsize) ? size : oldsize; + memcpy(p, ptr, copysize); + isdalloct(tsdn, ptr, oldsize, tcache, NULL, true); + return p; +} + +JEMALLOC_ALWAYS_INLINE void * +iralloct(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t alignment, + bool zero, tcache_t *tcache, arena_t *arena) { + assert(ptr != NULL); + assert(size != 0); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1)) + != 0) { + /* + * Existing object alignment is inadequate; allocate new space + * and copy. + */ + return iralloct_realign(tsdn, ptr, oldsize, size, 0, alignment, + zero, tcache, arena); + } + + return arena_ralloc(tsdn, arena, ptr, oldsize, size, alignment, zero, + tcache); +} + +JEMALLOC_ALWAYS_INLINE void * +iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment, + bool zero) { + return iralloct(tsd_tsdn(tsd), ptr, oldsize, size, alignment, zero, + tcache_get(tsd), NULL); +} + +JEMALLOC_ALWAYS_INLINE bool +ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra, + size_t alignment, bool zero) { + assert(ptr != NULL); + assert(size != 0); + witness_assert_depth_to_rank(tsdn_witness_tsdp_get(tsdn), + WITNESS_RANK_CORE, 0); + + if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1)) + != 0) { + /* Existing object alignment is inadequate. */ + return true; + } + + return arena_ralloc_no_move(tsdn, ptr, oldsize, size, extra, zero); +} + +#endif /* JEMALLOC_INTERNAL_INLINES_C_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h new file mode 100644 index 0000000000..4571895ec3 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_macros.h @@ -0,0 +1,40 @@ +#ifndef JEMALLOC_INTERNAL_MACROS_H +#define JEMALLOC_INTERNAL_MACROS_H + +#ifdef JEMALLOC_DEBUG +# define JEMALLOC_ALWAYS_INLINE static inline +#else +# define JEMALLOC_ALWAYS_INLINE JEMALLOC_ATTR(always_inline) static inline +#endif +#ifdef _MSC_VER +# define inline _inline +#endif + +#define UNUSED JEMALLOC_ATTR(unused) + +#define ZU(z) ((size_t)z) +#define ZD(z) ((ssize_t)z) +#define QU(q) ((uint64_t)q) +#define QD(q) ((int64_t)q) + +#define KZU(z) ZU(z##ULL) +#define KZD(z) ZD(z##LL) +#define KQU(q) QU(q##ULL) +#define KQD(q) QI(q##LL) + +#ifndef __DECONST +# define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) +#endif + +#if !defined(JEMALLOC_HAS_RESTRICT) || defined(__cplusplus) +# define restrict +#endif + +/* Various function pointers are statick and immutable except during testing. */ +#ifdef JEMALLOC_JET +# define JET_MUTABLE +#else +# define JET_MUTABLE const +#endif + +#endif /* JEMALLOC_INTERNAL_MACROS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h new file mode 100644 index 0000000000..50f9d001d5 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_internal_types.h @@ -0,0 +1,178 @@ +#ifndef JEMALLOC_INTERNAL_TYPES_H +#define JEMALLOC_INTERNAL_TYPES_H + +/* Page size index type. */ +typedef unsigned pszind_t; + +/* Size class index type. */ +typedef unsigned szind_t; + +/* Processor / core id type. */ +typedef int malloc_cpuid_t; + +/* + * Flags bits: + * + * a: arena + * t: tcache + * 0: unused + * z: zero + * n: alignment + * + * aaaaaaaa aaaatttt tttttttt 0znnnnnn + */ +#define MALLOCX_ARENA_BITS 12 +#define MALLOCX_TCACHE_BITS 12 +#define MALLOCX_LG_ALIGN_BITS 6 +#define MALLOCX_ARENA_SHIFT 20 +#define MALLOCX_TCACHE_SHIFT 8 +#define MALLOCX_ARENA_MASK \ + (((1 << MALLOCX_ARENA_BITS) - 1) << MALLOCX_ARENA_SHIFT) +/* NB: Arena index bias decreases the maximum number of arenas by 1. */ +#define MALLOCX_ARENA_LIMIT ((1 << MALLOCX_ARENA_BITS) - 1) +#define MALLOCX_TCACHE_MASK \ + (((1 << MALLOCX_TCACHE_BITS) - 1) << MALLOCX_TCACHE_SHIFT) +#define MALLOCX_TCACHE_MAX ((1 << MALLOCX_TCACHE_BITS) - 3) +#define MALLOCX_LG_ALIGN_MASK ((1 << MALLOCX_LG_ALIGN_BITS) - 1) +/* Use MALLOCX_ALIGN_GET() if alignment may not be specified in flags. */ +#define MALLOCX_ALIGN_GET_SPECIFIED(flags) \ + (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK)) +#define MALLOCX_ALIGN_GET(flags) \ + (MALLOCX_ALIGN_GET_SPECIFIED(flags) & (SIZE_T_MAX-1)) +#define MALLOCX_ZERO_GET(flags) \ + ((bool)(flags & MALLOCX_ZERO)) + +#define MALLOCX_TCACHE_GET(flags) \ + (((unsigned)((flags & MALLOCX_TCACHE_MASK) >> MALLOCX_TCACHE_SHIFT)) - 2) +#define MALLOCX_ARENA_GET(flags) \ + (((unsigned)(((unsigned)flags) >> MALLOCX_ARENA_SHIFT)) - 1) + +/* Smallest size class to support. */ +#define TINY_MIN (1U << LG_TINY_MIN) + +/* + * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size + * classes). + */ +#ifndef LG_QUANTUM +# if (defined(__i386__) || defined(_M_IX86)) +# define LG_QUANTUM 4 +# endif +# ifdef __ia64__ +# define LG_QUANTUM 4 +# endif +# ifdef __alpha__ +# define LG_QUANTUM 4 +# endif +# if (defined(__sparc64__) || defined(__sparcv9) || defined(__sparc_v9__)) +# define LG_QUANTUM 4 +# endif +# if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)) +# define LG_QUANTUM 4 +# endif +# ifdef __arm__ +# define LG_QUANTUM 3 +# endif +# ifdef __aarch64__ +# define LG_QUANTUM 4 +# endif +# ifdef __hppa__ +# define LG_QUANTUM 4 +# endif +# ifdef __mips__ +# define LG_QUANTUM 3 +# endif +# ifdef __or1k__ +# define LG_QUANTUM 3 +# endif +# ifdef __powerpc__ +# define LG_QUANTUM 4 +# endif +# ifdef __riscv__ +# define LG_QUANTUM 4 +# endif +# ifdef __s390__ +# define LG_QUANTUM 4 +# endif +# ifdef __SH4__ +# define LG_QUANTUM 4 +# endif +# ifdef __tile__ +# define LG_QUANTUM 4 +# endif +# ifdef __le32__ +# define LG_QUANTUM 4 +# endif +# ifndef LG_QUANTUM +# error "Unknown minimum alignment for architecture; specify via " + "--with-lg-quantum" +# endif +#endif + +#define QUANTUM ((size_t)(1U << LG_QUANTUM)) +#define QUANTUM_MASK (QUANTUM - 1) + +/* Return the smallest quantum multiple that is >= a. */ +#define QUANTUM_CEILING(a) \ + (((a) + QUANTUM_MASK) & ~QUANTUM_MASK) + +#define LONG ((size_t)(1U << LG_SIZEOF_LONG)) +#define LONG_MASK (LONG - 1) + +/* Return the smallest long multiple that is >= a. */ +#define LONG_CEILING(a) \ + (((a) + LONG_MASK) & ~LONG_MASK) + +#define SIZEOF_PTR (1U << LG_SIZEOF_PTR) +#define PTR_MASK (SIZEOF_PTR - 1) + +/* Return the smallest (void *) multiple that is >= a. */ +#define PTR_CEILING(a) \ + (((a) + PTR_MASK) & ~PTR_MASK) + +/* + * Maximum size of L1 cache line. This is used to avoid cache line aliasing. + * In addition, this controls the spacing of cacheline-spaced size classes. + * + * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can + * only handle raw constants. + */ +#define LG_CACHELINE 6 +#define CACHELINE 64 +#define CACHELINE_MASK (CACHELINE - 1) + +/* Return the smallest cacheline multiple that is >= s. */ +#define CACHELINE_CEILING(s) \ + (((s) + CACHELINE_MASK) & ~CACHELINE_MASK) + +/* Return the nearest aligned address at or below a. */ +#define ALIGNMENT_ADDR2BASE(a, alignment) \ + ((void *)((uintptr_t)(a) & ((~(alignment)) + 1))) + +/* Return the offset between a and the nearest aligned address at or below a. */ +#define ALIGNMENT_ADDR2OFFSET(a, alignment) \ + ((size_t)((uintptr_t)(a) & (alignment - 1))) + +/* Return the smallest alignment multiple that is >= s. */ +#define ALIGNMENT_CEILING(s, alignment) \ + (((s) + (alignment - 1)) & ((~(alignment)) + 1)) + +/* Declare a variable-length array. */ +#if __STDC_VERSION__ < 199901L +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# ifdef JEMALLOC_HAS_ALLOCA_H +# include <alloca.h> +# else +# include <stdlib.h> +# endif +# endif +# define VARIABLE_ARRAY(type, name, count) \ + type *name = alloca(sizeof(type) * (count)) +#else +# define VARIABLE_ARRAY(type, name, count) type name[(count)] +#endif + +#endif /* JEMALLOC_INTERNAL_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_preamble.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_preamble.h new file mode 100644 index 0000000000..39045c857f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_preamble.h @@ -0,0 +1,179 @@ +#ifndef JEMALLOC_PREAMBLE_H +#define JEMALLOC_PREAMBLE_H + +#include "jemalloc_internal_defs.h" +#include "jemalloc/internal/jemalloc_internal_decls.h" + +#ifdef JEMALLOC_UTRACE +#include <sys/ktrace.h> +#endif + +#define JEMALLOC_NO_DEMANGLE +#ifdef JEMALLOC_JET +# undef JEMALLOC_IS_MALLOC +# define JEMALLOC_N(n) jet_##n +# include "jemalloc/internal/public_namespace.h" +# define JEMALLOC_NO_RENAME +# include "../jemalloc.h" +# undef JEMALLOC_NO_RENAME +#else +# define JEMALLOC_N(n) je_##n +# include "../jemalloc.h" +#endif + +#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN)) +#include <libkern/OSAtomic.h> +#endif + +#ifdef JEMALLOC_ZONE +#include <mach/mach_error.h> +#include <mach/mach_init.h> +#include <mach/vm_map.h> +#endif + +#include "jemalloc/internal/jemalloc_internal_macros.h" + +/* + * Note that the ordering matters here; the hook itself is name-mangled. We + * want the inclusion of hooks to happen early, so that we hook as much as + * possible. + */ +#ifndef JEMALLOC_NO_PRIVATE_NAMESPACE +# ifndef JEMALLOC_JET +# include "jemalloc/internal/private_namespace.h" +# else +# include "jemalloc/internal/private_namespace_jet.h" +# endif +#endif +#include "jemalloc/internal/hooks.h" + +static const bool config_debug = +#ifdef JEMALLOC_DEBUG + true +#else + false +#endif + ; +static const bool have_dss = +#ifdef JEMALLOC_DSS + true +#else + false +#endif + ; +static const bool config_fill = +#ifdef JEMALLOC_FILL + true +#else + false +#endif + ; +static const bool config_lazy_lock = +#ifdef JEMALLOC_LAZY_LOCK + true +#else + false +#endif + ; +static const char * const config_malloc_conf = JEMALLOC_CONFIG_MALLOC_CONF; +static const bool config_prof = +#ifdef JEMALLOC_PROF + true +#else + false +#endif + ; +static const bool config_prof_libgcc = +#ifdef JEMALLOC_PROF_LIBGCC + true +#else + false +#endif + ; +static const bool config_prof_libunwind = +#ifdef JEMALLOC_PROF_LIBUNWIND + true +#else + false +#endif + ; +static const bool maps_coalesce = +#ifdef JEMALLOC_MAPS_COALESCE + true +#else + false +#endif + ; +static const bool config_stats = +#ifdef JEMALLOC_STATS + true +#else + false +#endif + ; +static const bool config_thp = +#ifdef JEMALLOC_THP + true +#else + false +#endif + ; +static const bool config_tls = +#ifdef JEMALLOC_TLS + true +#else + false +#endif + ; +static const bool config_utrace = +#ifdef JEMALLOC_UTRACE + true +#else + false +#endif + ; +static const bool config_xmalloc = +#ifdef JEMALLOC_XMALLOC + true +#else + false +#endif + ; +static const bool config_cache_oblivious = +#ifdef JEMALLOC_CACHE_OBLIVIOUS + true +#else + false +#endif + ; +#ifdef JEMALLOC_HAVE_SCHED_GETCPU +/* Currently percpu_arena depends on sched_getcpu. */ +#define JEMALLOC_PERCPU_ARENA +#endif +static const bool have_percpu_arena = +#ifdef JEMALLOC_PERCPU_ARENA + true +#else + false +#endif + ; +/* + * Undocumented, and not recommended; the application should take full + * responsibility for tracking provenance. + */ +static const bool force_ivsalloc = +#ifdef JEMALLOC_FORCE_IVSALLOC + true +#else + false +#endif + ; +static const bool have_background_thread = +#ifdef JEMALLOC_BACKGROUND_THREAD + true +#else + false +#endif + ; + +#endif /* JEMALLOC_PREAMBLE_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in new file mode 100644 index 0000000000..18539a0988 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/jemalloc_preamble.h.in @@ -0,0 +1,179 @@ +#ifndef JEMALLOC_PREAMBLE_H +#define JEMALLOC_PREAMBLE_H + +#include "jemalloc_internal_defs.h" +#include "jemalloc/internal/jemalloc_internal_decls.h" + +#ifdef JEMALLOC_UTRACE +#include <sys/ktrace.h> +#endif + +#define JEMALLOC_NO_DEMANGLE +#ifdef JEMALLOC_JET +# undef JEMALLOC_IS_MALLOC +# define JEMALLOC_N(n) jet_##n +# include "jemalloc/internal/public_namespace.h" +# define JEMALLOC_NO_RENAME +# include "../jemalloc@install_suffix@.h" +# undef JEMALLOC_NO_RENAME +#else +# define JEMALLOC_N(n) @private_namespace@##n +# include "../jemalloc@install_suffix@.h" +#endif + +#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN)) +#include <libkern/OSAtomic.h> +#endif + +#ifdef JEMALLOC_ZONE +#include <mach/mach_error.h> +#include <mach/mach_init.h> +#include <mach/vm_map.h> +#endif + +#include "jemalloc/internal/jemalloc_internal_macros.h" + +/* + * Note that the ordering matters here; the hook itself is name-mangled. We + * want the inclusion of hooks to happen early, so that we hook as much as + * possible. + */ +#ifndef JEMALLOC_NO_PRIVATE_NAMESPACE +# ifndef JEMALLOC_JET +# include "jemalloc/internal/private_namespace.h" +# else +# include "jemalloc/internal/private_namespace_jet.h" +# endif +#endif +#include "jemalloc/internal/hooks.h" + +static const bool config_debug = +#ifdef JEMALLOC_DEBUG + true +#else + false +#endif + ; +static const bool have_dss = +#ifdef JEMALLOC_DSS + true +#else + false +#endif + ; +static const bool config_fill = +#ifdef JEMALLOC_FILL + true +#else + false +#endif + ; +static const bool config_lazy_lock = +#ifdef JEMALLOC_LAZY_LOCK + true +#else + false +#endif + ; +static const char * const config_malloc_conf = JEMALLOC_CONFIG_MALLOC_CONF; +static const bool config_prof = +#ifdef JEMALLOC_PROF + true +#else + false +#endif + ; +static const bool config_prof_libgcc = +#ifdef JEMALLOC_PROF_LIBGCC + true +#else + false +#endif + ; +static const bool config_prof_libunwind = +#ifdef JEMALLOC_PROF_LIBUNWIND + true +#else + false +#endif + ; +static const bool maps_coalesce = +#ifdef JEMALLOC_MAPS_COALESCE + true +#else + false +#endif + ; +static const bool config_stats = +#ifdef JEMALLOC_STATS + true +#else + false +#endif + ; +static const bool config_thp = +#ifdef JEMALLOC_THP + true +#else + false +#endif + ; +static const bool config_tls = +#ifdef JEMALLOC_TLS + true +#else + false +#endif + ; +static const bool config_utrace = +#ifdef JEMALLOC_UTRACE + true +#else + false +#endif + ; +static const bool config_xmalloc = +#ifdef JEMALLOC_XMALLOC + true +#else + false +#endif + ; +static const bool config_cache_oblivious = +#ifdef JEMALLOC_CACHE_OBLIVIOUS + true +#else + false +#endif + ; +#ifdef JEMALLOC_HAVE_SCHED_GETCPU +/* Currently percpu_arena depends on sched_getcpu. */ +#define JEMALLOC_PERCPU_ARENA +#endif +static const bool have_percpu_arena = +#ifdef JEMALLOC_PERCPU_ARENA + true +#else + false +#endif + ; +/* + * Undocumented, and not recommended; the application should take full + * responsibility for tracking provenance. + */ +static const bool force_ivsalloc = +#ifdef JEMALLOC_FORCE_IVSALLOC + true +#else + false +#endif + ; +static const bool have_background_thread = +#ifdef JEMALLOC_BACKGROUND_THREAD + true +#else + false +#endif + ; + +#endif /* JEMALLOC_PREAMBLE_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/large_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/large_externs.h new file mode 100644 index 0000000000..3f36282cd4 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/large_externs.h @@ -0,0 +1,26 @@ +#ifndef JEMALLOC_INTERNAL_LARGE_EXTERNS_H +#define JEMALLOC_INTERNAL_LARGE_EXTERNS_H + +void *large_malloc(tsdn_t *tsdn, arena_t *arena, size_t usize, bool zero); +void *large_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, + bool zero); +bool large_ralloc_no_move(tsdn_t *tsdn, extent_t *extent, size_t usize_min, + size_t usize_max, bool zero); +void *large_ralloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent, size_t usize, + size_t alignment, bool zero, tcache_t *tcache); + +typedef void (large_dalloc_junk_t)(void *, size_t); +extern large_dalloc_junk_t *JET_MUTABLE large_dalloc_junk; + +typedef void (large_dalloc_maybe_junk_t)(void *, size_t); +extern large_dalloc_maybe_junk_t *JET_MUTABLE large_dalloc_maybe_junk; + +void large_dalloc_prep_junked_locked(tsdn_t *tsdn, extent_t *extent); +void large_dalloc_finish(tsdn_t *tsdn, extent_t *extent); +void large_dalloc(tsdn_t *tsdn, extent_t *extent); +size_t large_salloc(tsdn_t *tsdn, const extent_t *extent); +prof_tctx_t *large_prof_tctx_get(tsdn_t *tsdn, const extent_t *extent); +void large_prof_tctx_set(tsdn_t *tsdn, extent_t *extent, prof_tctx_t *tctx); +void large_prof_tctx_reset(tsdn_t *tsdn, extent_t *extent); + +#endif /* JEMALLOC_INTERNAL_LARGE_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/malloc_io.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/malloc_io.h new file mode 100644 index 0000000000..47ae58ec35 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/malloc_io.h @@ -0,0 +1,62 @@ +#ifndef JEMALLOC_INTERNAL_MALLOC_IO_H +#define JEMALLOC_INTERNAL_MALLOC_IO_H + +#ifdef _WIN32 +# ifdef _WIN64 +# define FMT64_PREFIX "ll" +# define FMTPTR_PREFIX "ll" +# else +# define FMT64_PREFIX "ll" +# define FMTPTR_PREFIX "" +# endif +# define FMTd32 "d" +# define FMTu32 "u" +# define FMTx32 "x" +# define FMTd64 FMT64_PREFIX "d" +# define FMTu64 FMT64_PREFIX "u" +# define FMTx64 FMT64_PREFIX "x" +# define FMTdPTR FMTPTR_PREFIX "d" +# define FMTuPTR FMTPTR_PREFIX "u" +# define FMTxPTR FMTPTR_PREFIX "x" +#else +# include <inttypes.h> +# define FMTd32 PRId32 +# define FMTu32 PRIu32 +# define FMTx32 PRIx32 +# define FMTd64 PRId64 +# define FMTu64 PRIu64 +# define FMTx64 PRIx64 +# define FMTdPTR PRIdPTR +# define FMTuPTR PRIuPTR +# define FMTxPTR PRIxPTR +#endif + +/* Size of stack-allocated buffer passed to buferror(). */ +#define BUFERROR_BUF 64 + +/* + * Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be + * large enough for all possible uses within jemalloc. + */ +#define MALLOC_PRINTF_BUFSIZE 4096 + +int buferror(int err, char *buf, size_t buflen); +uintmax_t malloc_strtoumax(const char *restrict nptr, char **restrict endptr, + int base); +void malloc_write(const char *s); + +/* + * malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating + * point math. + */ +size_t malloc_vsnprintf(char *str, size_t size, const char *format, + va_list ap); +size_t malloc_snprintf(char *str, size_t size, const char *format, ...) + JEMALLOC_FORMAT_PRINTF(3, 4); +void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, va_list ap); +void malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4); +void malloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2); + +#endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/mutex_pool.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/mutex_pool.h new file mode 100644 index 0000000000..726cece90b --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/mutex_pool.h @@ -0,0 +1,94 @@ +#ifndef JEMALLOC_INTERNAL_MUTEX_POOL_H +#define JEMALLOC_INTERNAL_MUTEX_POOL_H + +#include "jemalloc/internal/hash.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/witness.h" + +/* We do mod reductions by this value, so it should be kept a power of 2. */ +#define MUTEX_POOL_SIZE 256 + +typedef struct mutex_pool_s mutex_pool_t; +struct mutex_pool_s { + malloc_mutex_t mutexes[MUTEX_POOL_SIZE]; +}; + +bool mutex_pool_init(mutex_pool_t *pool, const char *name, witness_rank_t rank); + +/* Internal helper - not meant to be called outside this module. */ +static inline malloc_mutex_t * +mutex_pool_mutex(mutex_pool_t *pool, uintptr_t key) { + size_t hash_result[2]; + hash(&key, sizeof(key), 0xd50dcc1b, hash_result); + return &pool->mutexes[hash_result[0] % MUTEX_POOL_SIZE]; +} + +static inline void +mutex_pool_assert_not_held(tsdn_t *tsdn, mutex_pool_t *pool) { + for (int i = 0; i < MUTEX_POOL_SIZE; i++) { + malloc_mutex_assert_not_owner(tsdn, &pool->mutexes[i]); + } +} + +/* + * Note that a mutex pool doesn't work exactly the way an embdedded mutex would. + * You're not allowed to acquire mutexes in the pool one at a time. You have to + * acquire all the mutexes you'll need in a single function call, and then + * release them all in a single function call. + */ + +static inline void +mutex_pool_lock(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) { + mutex_pool_assert_not_held(tsdn, pool); + + malloc_mutex_t *mutex = mutex_pool_mutex(pool, key); + malloc_mutex_lock(tsdn, mutex); +} + +static inline void +mutex_pool_unlock(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) { + malloc_mutex_t *mutex = mutex_pool_mutex(pool, key); + malloc_mutex_unlock(tsdn, mutex); + + mutex_pool_assert_not_held(tsdn, pool); +} + +static inline void +mutex_pool_lock2(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key1, + uintptr_t key2) { + mutex_pool_assert_not_held(tsdn, pool); + + malloc_mutex_t *mutex1 = mutex_pool_mutex(pool, key1); + malloc_mutex_t *mutex2 = mutex_pool_mutex(pool, key2); + if ((uintptr_t)mutex1 < (uintptr_t)mutex2) { + malloc_mutex_lock(tsdn, mutex1); + malloc_mutex_lock(tsdn, mutex2); + } else if ((uintptr_t)mutex1 == (uintptr_t)mutex2) { + malloc_mutex_lock(tsdn, mutex1); + } else { + malloc_mutex_lock(tsdn, mutex2); + malloc_mutex_lock(tsdn, mutex1); + } +} + +static inline void +mutex_pool_unlock2(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key1, + uintptr_t key2) { + malloc_mutex_t *mutex1 = mutex_pool_mutex(pool, key1); + malloc_mutex_t *mutex2 = mutex_pool_mutex(pool, key2); + if (mutex1 == mutex2) { + malloc_mutex_unlock(tsdn, mutex1); + } else { + malloc_mutex_unlock(tsdn, mutex1); + malloc_mutex_unlock(tsdn, mutex2); + } + + mutex_pool_assert_not_held(tsdn, pool); +} + +static inline void +mutex_pool_assert_owner(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) { + malloc_mutex_assert_owner(tsdn, mutex_pool_mutex(pool, key)); +} + +#endif /* JEMALLOC_INTERNAL_MUTEX_POOL_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/mutex_prof.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/mutex_prof.h new file mode 100644 index 0000000000..3358bcf535 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/mutex_prof.h @@ -0,0 +1,86 @@ +#ifndef JEMALLOC_INTERNAL_MUTEX_PROF_H +#define JEMALLOC_INTERNAL_MUTEX_PROF_H + +#include "jemalloc/internal/atomic.h" +#include "jemalloc/internal/nstime.h" +#include "jemalloc/internal/tsd_types.h" + +#define MUTEX_PROF_GLOBAL_MUTEXES \ + OP(background_thread) \ + OP(ctl) \ + OP(prof) + +typedef enum { +#define OP(mtx) global_prof_mutex_##mtx, + MUTEX_PROF_GLOBAL_MUTEXES +#undef OP + mutex_prof_num_global_mutexes +} mutex_prof_global_ind_t; + +#define MUTEX_PROF_ARENA_MUTEXES \ + OP(large) \ + OP(extent_avail) \ + OP(extents_dirty) \ + OP(extents_muzzy) \ + OP(extents_retained) \ + OP(decay_dirty) \ + OP(decay_muzzy) \ + OP(base) \ + OP(tcache_list) + +typedef enum { +#define OP(mtx) arena_prof_mutex_##mtx, + MUTEX_PROF_ARENA_MUTEXES +#undef OP + mutex_prof_num_arena_mutexes +} mutex_prof_arena_ind_t; + +#define MUTEX_PROF_COUNTERS \ + OP(num_ops, uint64_t) \ + OP(num_wait, uint64_t) \ + OP(num_spin_acq, uint64_t) \ + OP(num_owner_switch, uint64_t) \ + OP(total_wait_time, uint64_t) \ + OP(max_wait_time, uint64_t) \ + OP(max_num_thds, uint32_t) + +typedef enum { +#define OP(counter, type) mutex_counter_##counter, + MUTEX_PROF_COUNTERS +#undef OP + mutex_prof_num_counters +} mutex_prof_counter_ind_t; + +typedef struct { + /* + * Counters touched on the slow path, i.e. when there is lock + * contention. We update them once we have the lock. + */ + /* Total time (in nano seconds) spent waiting on this mutex. */ + nstime_t tot_wait_time; + /* Max time (in nano seconds) spent on a single lock operation. */ + nstime_t max_wait_time; + /* # of times have to wait for this mutex (after spinning). */ + uint64_t n_wait_times; + /* # of times acquired the mutex through local spinning. */ + uint64_t n_spin_acquired; + /* Max # of threads waiting for the mutex at the same time. */ + uint32_t max_n_thds; + /* Current # of threads waiting on the lock. Atomic synced. */ + atomic_u32_t n_waiting_thds; + + /* + * Data touched on the fast path. These are modified right after we + * grab the lock, so it's placed closest to the end (i.e. right before + * the lock) so that we have a higher chance of them being on the same + * cacheline. + */ + /* # of times the mutex holder is different than the previous one. */ + uint64_t n_owner_switches; + /* Previous mutex holder, to facilitate n_owner_switches. */ + tsdn_t *prev_owner; + /* # of lock() operations in total. */ + uint64_t n_lock_ops; +} mutex_prof_data_t; + +#endif /* JEMALLOC_INTERNAL_MUTEX_PROF_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/nstime.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/nstime.h new file mode 100644 index 0000000000..17c177c7f4 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/nstime.h @@ -0,0 +1,34 @@ +#ifndef JEMALLOC_INTERNAL_NSTIME_H +#define JEMALLOC_INTERNAL_NSTIME_H + +/* Maximum supported number of seconds (~584 years). */ +#define NSTIME_SEC_MAX KQU(18446744072) +#define NSTIME_ZERO_INITIALIZER {0} + +typedef struct { + uint64_t ns; +} nstime_t; + +void nstime_init(nstime_t *time, uint64_t ns); +void nstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec); +uint64_t nstime_ns(const nstime_t *time); +uint64_t nstime_sec(const nstime_t *time); +uint64_t nstime_msec(const nstime_t *time); +uint64_t nstime_nsec(const nstime_t *time); +void nstime_copy(nstime_t *time, const nstime_t *source); +int nstime_compare(const nstime_t *a, const nstime_t *b); +void nstime_add(nstime_t *time, const nstime_t *addend); +void nstime_iadd(nstime_t *time, uint64_t addend); +void nstime_subtract(nstime_t *time, const nstime_t *subtrahend); +void nstime_isubtract(nstime_t *time, uint64_t subtrahend); +void nstime_imultiply(nstime_t *time, uint64_t multiplier); +void nstime_idivide(nstime_t *time, uint64_t divisor); +uint64_t nstime_divide(const nstime_t *time, const nstime_t *divisor); + +typedef bool (nstime_monotonic_t)(void); +extern nstime_monotonic_t *JET_MUTABLE nstime_monotonic; + +typedef bool (nstime_update_t)(nstime_t *); +extern nstime_update_t *JET_MUTABLE nstime_update; + +#endif /* JEMALLOC_INTERNAL_NSTIME_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/pages.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/pages.h new file mode 100644 index 0000000000..28383b7f97 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/pages.h @@ -0,0 +1,71 @@ +#ifndef JEMALLOC_INTERNAL_PAGES_EXTERNS_H +#define JEMALLOC_INTERNAL_PAGES_EXTERNS_H + +/* Page size. LG_PAGE is determined by the configure script. */ +#ifdef PAGE_MASK +# undef PAGE_MASK +#endif +#define PAGE ((size_t)(1U << LG_PAGE)) +#define PAGE_MASK ((size_t)(PAGE - 1)) +/* Return the page base address for the page containing address a. */ +#define PAGE_ADDR2BASE(a) \ + ((void *)((uintptr_t)(a) & ~PAGE_MASK)) +/* Return the smallest pagesize multiple that is >= s. */ +#define PAGE_CEILING(s) \ + (((s) + PAGE_MASK) & ~PAGE_MASK) + +/* Huge page size. LG_HUGEPAGE is determined by the configure script. */ +#define HUGEPAGE ((size_t)(1U << LG_HUGEPAGE)) +#define HUGEPAGE_MASK ((size_t)(HUGEPAGE - 1)) +/* Return the huge page base address for the huge page containing address a. */ +#define HUGEPAGE_ADDR2BASE(a) \ + ((void *)((uintptr_t)(a) & ~HUGEPAGE_MASK)) +/* Return the smallest pagesize multiple that is >= s. */ +#define HUGEPAGE_CEILING(s) \ + (((s) + HUGEPAGE_MASK) & ~HUGEPAGE_MASK) + +/* PAGES_CAN_PURGE_LAZY is defined if lazy purging is supported. */ +#if defined(_WIN32) || defined(JEMALLOC_PURGE_MADVISE_FREE) +# define PAGES_CAN_PURGE_LAZY +#endif +/* + * PAGES_CAN_PURGE_FORCED is defined if forced purging is supported. + * + * The only supported way to hard-purge on Windows is to decommit and then + * re-commit, but doing so is racy, and if re-commit fails it's a pain to + * propagate the "poisoned" memory state. Since we typically decommit as the + * next step after purging on Windows anyway, there's no point in adding such + * complexity. + */ +#if !defined(_WIN32) && ((defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ + defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS)) || \ + defined(JEMALLOC_MAPS_COALESCE)) +# define PAGES_CAN_PURGE_FORCED +#endif + +static const bool pages_can_purge_lazy = +#ifdef PAGES_CAN_PURGE_LAZY + true +#else + false +#endif + ; +static const bool pages_can_purge_forced = +#ifdef PAGES_CAN_PURGE_FORCED + true +#else + false +#endif + ; + +void *pages_map(void *addr, size_t size, size_t alignment, bool *commit); +void pages_unmap(void *addr, size_t size); +bool pages_commit(void *addr, size_t size); +bool pages_decommit(void *addr, size_t size); +bool pages_purge_lazy(void *addr, size_t size); +bool pages_purge_forced(void *addr, size_t size); +bool pages_huge(void *addr, size_t size); +bool pages_nohuge(void *addr, size_t size); +bool pages_boot(void); + +#endif /* JEMALLOC_INTERNAL_PAGES_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/ph.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/ph.h new file mode 100644 index 0000000000..84d6778a90 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/ph.h @@ -0,0 +1,391 @@ +/* + * A Pairing Heap implementation. + * + * "The Pairing Heap: A New Form of Self-Adjusting Heap" + * https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf + * + * With auxiliary twopass list, described in a follow on paper. + * + * "Pairing Heaps: Experiments and Analysis" + * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.2988&rep=rep1&type=pdf + * + ******************************************************************************* + */ + +#ifndef PH_H_ +#define PH_H_ + +/* Node structure. */ +#define phn(a_type) \ +struct { \ + a_type *phn_prev; \ + a_type *phn_next; \ + a_type *phn_lchild; \ +} + +/* Root structure. */ +#define ph(a_type) \ +struct { \ + a_type *ph_root; \ +} + +/* Internal utility macros. */ +#define phn_lchild_get(a_type, a_field, a_phn) \ + (a_phn->a_field.phn_lchild) +#define phn_lchild_set(a_type, a_field, a_phn, a_lchild) do { \ + a_phn->a_field.phn_lchild = a_lchild; \ +} while (0) + +#define phn_next_get(a_type, a_field, a_phn) \ + (a_phn->a_field.phn_next) +#define phn_prev_set(a_type, a_field, a_phn, a_prev) do { \ + a_phn->a_field.phn_prev = a_prev; \ +} while (0) + +#define phn_prev_get(a_type, a_field, a_phn) \ + (a_phn->a_field.phn_prev) +#define phn_next_set(a_type, a_field, a_phn, a_next) do { \ + a_phn->a_field.phn_next = a_next; \ +} while (0) + +#define phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, a_cmp) do { \ + a_type *phn0child; \ + \ + assert(a_phn0 != NULL); \ + assert(a_phn1 != NULL); \ + assert(a_cmp(a_phn0, a_phn1) <= 0); \ + \ + phn_prev_set(a_type, a_field, a_phn1, a_phn0); \ + phn0child = phn_lchild_get(a_type, a_field, a_phn0); \ + phn_next_set(a_type, a_field, a_phn1, phn0child); \ + if (phn0child != NULL) { \ + phn_prev_set(a_type, a_field, phn0child, a_phn1); \ + } \ + phn_lchild_set(a_type, a_field, a_phn0, a_phn1); \ +} while (0) + +#define phn_merge(a_type, a_field, a_phn0, a_phn1, a_cmp, r_phn) do { \ + if (a_phn0 == NULL) { \ + r_phn = a_phn1; \ + } else if (a_phn1 == NULL) { \ + r_phn = a_phn0; \ + } else if (a_cmp(a_phn0, a_phn1) < 0) { \ + phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, \ + a_cmp); \ + r_phn = a_phn0; \ + } else { \ + phn_merge_ordered(a_type, a_field, a_phn1, a_phn0, \ + a_cmp); \ + r_phn = a_phn1; \ + } \ +} while (0) + +#define ph_merge_siblings(a_type, a_field, a_phn, a_cmp, r_phn) do { \ + a_type *head = NULL; \ + a_type *tail = NULL; \ + a_type *phn0 = a_phn; \ + a_type *phn1 = phn_next_get(a_type, a_field, phn0); \ + \ + /* \ + * Multipass merge, wherein the first two elements of a FIFO \ + * are repeatedly merged, and each result is appended to the \ + * singly linked FIFO, until the FIFO contains only a single \ + * element. We start with a sibling list but no reference to \ + * its tail, so we do a single pass over the sibling list to \ + * populate the FIFO. \ + */ \ + if (phn1 != NULL) { \ + a_type *phnrest = phn_next_get(a_type, a_field, phn1); \ + if (phnrest != NULL) { \ + phn_prev_set(a_type, a_field, phnrest, NULL); \ + } \ + phn_prev_set(a_type, a_field, phn0, NULL); \ + phn_next_set(a_type, a_field, phn0, NULL); \ + phn_prev_set(a_type, a_field, phn1, NULL); \ + phn_next_set(a_type, a_field, phn1, NULL); \ + phn_merge(a_type, a_field, phn0, phn1, a_cmp, phn0); \ + head = tail = phn0; \ + phn0 = phnrest; \ + while (phn0 != NULL) { \ + phn1 = phn_next_get(a_type, a_field, phn0); \ + if (phn1 != NULL) { \ + phnrest = phn_next_get(a_type, a_field, \ + phn1); \ + if (phnrest != NULL) { \ + phn_prev_set(a_type, a_field, \ + phnrest, NULL); \ + } \ + phn_prev_set(a_type, a_field, phn0, \ + NULL); \ + phn_next_set(a_type, a_field, phn0, \ + NULL); \ + phn_prev_set(a_type, a_field, phn1, \ + NULL); \ + phn_next_set(a_type, a_field, phn1, \ + NULL); \ + phn_merge(a_type, a_field, phn0, phn1, \ + a_cmp, phn0); \ + phn_next_set(a_type, a_field, tail, \ + phn0); \ + tail = phn0; \ + phn0 = phnrest; \ + } else { \ + phn_next_set(a_type, a_field, tail, \ + phn0); \ + tail = phn0; \ + phn0 = NULL; \ + } \ + } \ + phn0 = head; \ + phn1 = phn_next_get(a_type, a_field, phn0); \ + if (phn1 != NULL) { \ + while (true) { \ + head = phn_next_get(a_type, a_field, \ + phn1); \ + assert(phn_prev_get(a_type, a_field, \ + phn0) == NULL); \ + phn_next_set(a_type, a_field, phn0, \ + NULL); \ + assert(phn_prev_get(a_type, a_field, \ + phn1) == NULL); \ + phn_next_set(a_type, a_field, phn1, \ + NULL); \ + phn_merge(a_type, a_field, phn0, phn1, \ + a_cmp, phn0); \ + if (head == NULL) { \ + break; \ + } \ + phn_next_set(a_type, a_field, tail, \ + phn0); \ + tail = phn0; \ + phn0 = head; \ + phn1 = phn_next_get(a_type, a_field, \ + phn0); \ + } \ + } \ + } \ + r_phn = phn0; \ +} while (0) + +#define ph_merge_aux(a_type, a_field, a_ph, a_cmp) do { \ + a_type *phn = phn_next_get(a_type, a_field, a_ph->ph_root); \ + if (phn != NULL) { \ + phn_prev_set(a_type, a_field, a_ph->ph_root, NULL); \ + phn_next_set(a_type, a_field, a_ph->ph_root, NULL); \ + phn_prev_set(a_type, a_field, phn, NULL); \ + ph_merge_siblings(a_type, a_field, phn, a_cmp, phn); \ + assert(phn_next_get(a_type, a_field, phn) == NULL); \ + phn_merge(a_type, a_field, a_ph->ph_root, phn, a_cmp, \ + a_ph->ph_root); \ + } \ +} while (0) + +#define ph_merge_children(a_type, a_field, a_phn, a_cmp, r_phn) do { \ + a_type *lchild = phn_lchild_get(a_type, a_field, a_phn); \ + if (lchild == NULL) { \ + r_phn = NULL; \ + } else { \ + ph_merge_siblings(a_type, a_field, lchild, a_cmp, \ + r_phn); \ + } \ +} while (0) + +/* + * The ph_proto() macro generates function prototypes that correspond to the + * functions generated by an equivalently parameterized call to ph_gen(). + */ +#define ph_proto(a_attr, a_prefix, a_ph_type, a_type) \ +a_attr void a_prefix##new(a_ph_type *ph); \ +a_attr bool a_prefix##empty(a_ph_type *ph); \ +a_attr a_type *a_prefix##first(a_ph_type *ph); \ +a_attr a_type *a_prefix##any(a_ph_type *ph); \ +a_attr void a_prefix##insert(a_ph_type *ph, a_type *phn); \ +a_attr a_type *a_prefix##remove_first(a_ph_type *ph); \ +a_attr a_type *a_prefix##remove_any(a_ph_type *ph); \ +a_attr void a_prefix##remove(a_ph_type *ph, a_type *phn); + +/* + * The ph_gen() macro generates a type-specific pairing heap implementation, + * based on the above cpp macros. + */ +#define ph_gen(a_attr, a_prefix, a_ph_type, a_type, a_field, a_cmp) \ +a_attr void \ +a_prefix##new(a_ph_type *ph) { \ + memset(ph, 0, sizeof(ph(a_type))); \ +} \ +a_attr bool \ +a_prefix##empty(a_ph_type *ph) { \ + return (ph->ph_root == NULL); \ +} \ +a_attr a_type * \ +a_prefix##first(a_ph_type *ph) { \ + if (ph->ph_root == NULL) { \ + return NULL; \ + } \ + ph_merge_aux(a_type, a_field, ph, a_cmp); \ + return ph->ph_root; \ +} \ +a_attr a_type * \ +a_prefix##any(a_ph_type *ph) { \ + if (ph->ph_root == NULL) { \ + return NULL; \ + } \ + a_type *aux = phn_next_get(a_type, a_field, ph->ph_root); \ + if (aux != NULL) { \ + return aux; \ + } \ + return ph->ph_root; \ +} \ +a_attr void \ +a_prefix##insert(a_ph_type *ph, a_type *phn) { \ + memset(&phn->a_field, 0, sizeof(phn(a_type))); \ + \ + /* \ + * Treat the root as an aux list during insertion, and lazily \ + * merge during a_prefix##remove_first(). For elements that \ + * are inserted, then removed via a_prefix##remove() before the \ + * aux list is ever processed, this makes insert/remove \ + * constant-time, whereas eager merging would make insert \ + * O(log n). \ + */ \ + if (ph->ph_root == NULL) { \ + ph->ph_root = phn; \ + } else { \ + phn_next_set(a_type, a_field, phn, phn_next_get(a_type, \ + a_field, ph->ph_root)); \ + if (phn_next_get(a_type, a_field, ph->ph_root) != \ + NULL) { \ + phn_prev_set(a_type, a_field, \ + phn_next_get(a_type, a_field, ph->ph_root), \ + phn); \ + } \ + phn_prev_set(a_type, a_field, phn, ph->ph_root); \ + phn_next_set(a_type, a_field, ph->ph_root, phn); \ + } \ +} \ +a_attr a_type * \ +a_prefix##remove_first(a_ph_type *ph) { \ + a_type *ret; \ + \ + if (ph->ph_root == NULL) { \ + return NULL; \ + } \ + ph_merge_aux(a_type, a_field, ph, a_cmp); \ + \ + ret = ph->ph_root; \ + \ + ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \ + ph->ph_root); \ + \ + return ret; \ +} \ +a_attr a_type * \ +a_prefix##remove_any(a_ph_type *ph) { \ + /* \ + * Remove the most recently inserted aux list element, or the \ + * root if the aux list is empty. This has the effect of \ + * behaving as a LIFO (and insertion/removal is therefore \ + * constant-time) if a_prefix##[remove_]first() are never \ + * called. \ + */ \ + if (ph->ph_root == NULL) { \ + return NULL; \ + } \ + a_type *ret = phn_next_get(a_type, a_field, ph->ph_root); \ + if (ret != NULL) { \ + a_type *aux = phn_next_get(a_type, a_field, ret); \ + phn_next_set(a_type, a_field, ph->ph_root, aux); \ + if (aux != NULL) { \ + phn_prev_set(a_type, a_field, aux, \ + ph->ph_root); \ + } \ + return ret; \ + } \ + ret = ph->ph_root; \ + ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \ + ph->ph_root); \ + return ret; \ +} \ +a_attr void \ +a_prefix##remove(a_ph_type *ph, a_type *phn) { \ + a_type *replace, *parent; \ + \ + if (ph->ph_root == phn) { \ + /* \ + * We can delete from aux list without merging it, but \ + * we need to merge if we are dealing with the root \ + * node and it has children. \ + */ \ + if (phn_lchild_get(a_type, a_field, phn) == NULL) { \ + ph->ph_root = phn_next_get(a_type, a_field, \ + phn); \ + if (ph->ph_root != NULL) { \ + phn_prev_set(a_type, a_field, \ + ph->ph_root, NULL); \ + } \ + return; \ + } \ + ph_merge_aux(a_type, a_field, ph, a_cmp); \ + if (ph->ph_root == phn) { \ + ph_merge_children(a_type, a_field, ph->ph_root, \ + a_cmp, ph->ph_root); \ + return; \ + } \ + } \ + \ + /* Get parent (if phn is leftmost child) before mutating. */ \ + if ((parent = phn_prev_get(a_type, a_field, phn)) != NULL) { \ + if (phn_lchild_get(a_type, a_field, parent) != phn) { \ + parent = NULL; \ + } \ + } \ + /* Find a possible replacement node, and link to parent. */ \ + ph_merge_children(a_type, a_field, phn, a_cmp, replace); \ + /* Set next/prev for sibling linked list. */ \ + if (replace != NULL) { \ + if (parent != NULL) { \ + phn_prev_set(a_type, a_field, replace, parent); \ + phn_lchild_set(a_type, a_field, parent, \ + replace); \ + } else { \ + phn_prev_set(a_type, a_field, replace, \ + phn_prev_get(a_type, a_field, phn)); \ + if (phn_prev_get(a_type, a_field, phn) != \ + NULL) { \ + phn_next_set(a_type, a_field, \ + phn_prev_get(a_type, a_field, phn), \ + replace); \ + } \ + } \ + phn_next_set(a_type, a_field, replace, \ + phn_next_get(a_type, a_field, phn)); \ + if (phn_next_get(a_type, a_field, phn) != NULL) { \ + phn_prev_set(a_type, a_field, \ + phn_next_get(a_type, a_field, phn), \ + replace); \ + } \ + } else { \ + if (parent != NULL) { \ + a_type *next = phn_next_get(a_type, a_field, \ + phn); \ + phn_lchild_set(a_type, a_field, parent, next); \ + if (next != NULL) { \ + phn_prev_set(a_type, a_field, next, \ + parent); \ + } \ + } else { \ + assert(phn_prev_get(a_type, a_field, phn) != \ + NULL); \ + phn_next_set(a_type, a_field, \ + phn_prev_get(a_type, a_field, phn), \ + phn_next_get(a_type, a_field, phn)); \ + } \ + if (phn_next_get(a_type, a_field, phn) != NULL) { \ + phn_prev_set(a_type, a_field, \ + phn_next_get(a_type, a_field, phn), \ + phn_prev_get(a_type, a_field, phn)); \ + } \ + } \ +} + +#endif /* PH_H_ */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_externs.h new file mode 100644 index 0000000000..04348696f5 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_externs.h @@ -0,0 +1,92 @@ +#ifndef JEMALLOC_INTERNAL_PROF_EXTERNS_H +#define JEMALLOC_INTERNAL_PROF_EXTERNS_H + +#include "jemalloc/internal/mutex.h" + +extern malloc_mutex_t bt2gctx_mtx; + +extern bool opt_prof; +extern bool opt_prof_active; +extern bool opt_prof_thread_active_init; +extern size_t opt_lg_prof_sample; /* Mean bytes between samples. */ +extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */ +extern bool opt_prof_gdump; /* High-water memory dumping. */ +extern bool opt_prof_final; /* Final profile dumping. */ +extern bool opt_prof_leak; /* Dump leak summary at exit. */ +extern bool opt_prof_accum; /* Report cumulative bytes. */ +extern char opt_prof_prefix[ + /* Minimize memory bloat for non-prof builds. */ +#ifdef JEMALLOC_PROF + PATH_MAX + +#endif + 1]; + +/* Accessed via prof_active_[gs]et{_unlocked,}(). */ +extern bool prof_active; + +/* Accessed via prof_gdump_[gs]et{_unlocked,}(). */ +extern bool prof_gdump_val; + +/* + * Profile dump interval, measured in bytes allocated. Each arena triggers a + * profile dump when it reaches this threshold. The effect is that the + * interval between profile dumps averages prof_interval, though the actual + * interval between dumps will tend to be sporadic, and the interval will be a + * maximum of approximately (prof_interval * narenas). + */ +extern uint64_t prof_interval; + +/* + * Initialized as opt_lg_prof_sample, and potentially modified during profiling + * resets. + */ +extern size_t lg_prof_sample; + +void prof_alloc_rollback(tsd_t *tsd, prof_tctx_t *tctx, bool updated); +void prof_malloc_sample_object(tsdn_t *tsdn, const void *ptr, size_t usize, + prof_tctx_t *tctx); +void prof_free_sampled_object(tsd_t *tsd, size_t usize, prof_tctx_t *tctx); +void bt_init(prof_bt_t *bt, void **vec); +void prof_backtrace(prof_bt_t *bt); +prof_tctx_t *prof_lookup(tsd_t *tsd, prof_bt_t *bt); +#ifdef JEMALLOC_JET +size_t prof_tdata_count(void); +size_t prof_bt_count(void); +#endif +typedef int (prof_dump_open_t)(bool, const char *); +extern prof_dump_open_t *JET_MUTABLE prof_dump_open; + +typedef bool (prof_dump_header_t)(tsdn_t *, bool, const prof_cnt_t *); +extern prof_dump_header_t *JET_MUTABLE prof_dump_header; +#ifdef JEMALLOC_JET +void prof_cnt_all(uint64_t *curobjs, uint64_t *curbytes, uint64_t *accumobjs, + uint64_t *accumbytes); +#endif +bool prof_accum_init(tsdn_t *tsdn, prof_accum_t *prof_accum); +void prof_idump(tsdn_t *tsdn); +bool prof_mdump(tsd_t *tsd, const char *filename); +void prof_gdump(tsdn_t *tsdn); +prof_tdata_t *prof_tdata_init(tsd_t *tsd); +prof_tdata_t *prof_tdata_reinit(tsd_t *tsd, prof_tdata_t *tdata); +void prof_reset(tsd_t *tsd, size_t lg_sample); +void prof_tdata_cleanup(tsd_t *tsd); +bool prof_active_get(tsdn_t *tsdn); +bool prof_active_set(tsdn_t *tsdn, bool active); +const char *prof_thread_name_get(tsd_t *tsd); +int prof_thread_name_set(tsd_t *tsd, const char *thread_name); +bool prof_thread_active_get(tsd_t *tsd); +bool prof_thread_active_set(tsd_t *tsd, bool active); +bool prof_thread_active_init_get(tsdn_t *tsdn); +bool prof_thread_active_init_set(tsdn_t *tsdn, bool active_init); +bool prof_gdump_get(tsdn_t *tsdn); +bool prof_gdump_set(tsdn_t *tsdn, bool active); +void prof_boot0(void); +void prof_boot1(void); +bool prof_boot2(tsd_t *tsd); +void prof_prefork0(tsdn_t *tsdn); +void prof_prefork1(tsdn_t *tsdn); +void prof_postfork_parent(tsdn_t *tsdn); +void prof_postfork_child(tsdn_t *tsdn); +void prof_sample_threshold_update(prof_tdata_t *tdata); + +#endif /* JEMALLOC_INTERNAL_PROF_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_inlines_a.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_inlines_a.h new file mode 100644 index 0000000000..eda6839ade --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_inlines_a.h @@ -0,0 +1,72 @@ +#ifndef JEMALLOC_INTERNAL_PROF_INLINES_A_H +#define JEMALLOC_INTERNAL_PROF_INLINES_A_H + +#include "jemalloc/internal/mutex.h" + +static inline bool +prof_accum_add(tsdn_t *tsdn, prof_accum_t *prof_accum, uint64_t accumbytes) { + cassert(config_prof); + + bool overflow; + uint64_t a0, a1; + + /* + * If the application allocates fast enough (and/or if idump is slow + * enough), extreme overflow here (a1 >= prof_interval * 2) can cause + * idump trigger coalescing. This is an intentional mechanism that + * avoids rate-limiting allocation. + */ +#ifdef JEMALLOC_ATOMIC_U64 + a0 = atomic_load_u64(&prof_accum->accumbytes, ATOMIC_RELAXED); + do { + a1 = a0 + accumbytes; + assert(a1 >= a0); + overflow = (a1 >= prof_interval); + if (overflow) { + a1 %= prof_interval; + } + } while (!atomic_compare_exchange_weak_u64(&prof_accum->accumbytes, &a0, + a1, ATOMIC_RELAXED, ATOMIC_RELAXED)); +#else + malloc_mutex_lock(tsdn, &prof_accum->mtx); + a0 = prof_accum->accumbytes; + a1 = a0 + accumbytes; + overflow = (a1 >= prof_interval); + if (overflow) { + a1 %= prof_interval; + } + prof_accum->accumbytes = a1; + malloc_mutex_unlock(tsdn, &prof_accum->mtx); +#endif + return overflow; +} + +static inline void +prof_accum_cancel(tsdn_t *tsdn, prof_accum_t *prof_accum, size_t usize) { + cassert(config_prof); + + /* + * Cancel out as much of the excessive prof_accumbytes increase as + * possible without underflowing. Interval-triggered dumps occur + * slightly more often than intended as a result of incomplete + * canceling. + */ + uint64_t a0, a1; +#ifdef JEMALLOC_ATOMIC_U64 + a0 = atomic_load_u64(&prof_accum->accumbytes, ATOMIC_RELAXED); + do { + a1 = (a0 >= LARGE_MINCLASS - usize) ? a0 - (LARGE_MINCLASS - + usize) : 0; + } while (!atomic_compare_exchange_weak_u64(&prof_accum->accumbytes, &a0, + a1, ATOMIC_RELAXED, ATOMIC_RELAXED)); +#else + malloc_mutex_lock(tsdn, &prof_accum->mtx); + a0 = prof_accum->accumbytes; + a1 = (a0 >= LARGE_MINCLASS - usize) ? a0 - (LARGE_MINCLASS - usize) : + 0; + prof_accum->accumbytes = a1; + malloc_mutex_unlock(tsdn, &prof_accum->mtx); +#endif +} + +#endif /* JEMALLOC_INTERNAL_PROF_INLINES_A_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_inlines_b.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_inlines_b.h new file mode 100644 index 0000000000..d670cb7b8f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_inlines_b.h @@ -0,0 +1,217 @@ +#ifndef JEMALLOC_INTERNAL_PROF_INLINES_B_H +#define JEMALLOC_INTERNAL_PROF_INLINES_B_H + +#include "jemalloc/internal/sz.h" + +JEMALLOC_ALWAYS_INLINE bool +prof_active_get_unlocked(void) { + /* + * Even if opt_prof is true, sampling can be temporarily disabled by + * setting prof_active to false. No locking is used when reading + * prof_active in the fast path, so there are no guarantees regarding + * how long it will take for all threads to notice state changes. + */ + return prof_active; +} + +JEMALLOC_ALWAYS_INLINE bool +prof_gdump_get_unlocked(void) { + /* + * No locking is used when reading prof_gdump_val in the fast path, so + * there are no guarantees regarding how long it will take for all + * threads to notice state changes. + */ + return prof_gdump_val; +} + +JEMALLOC_ALWAYS_INLINE prof_tdata_t * +prof_tdata_get(tsd_t *tsd, bool create) { + prof_tdata_t *tdata; + + cassert(config_prof); + + tdata = tsd_prof_tdata_get(tsd); + if (create) { + if (unlikely(tdata == NULL)) { + if (tsd_nominal(tsd)) { + tdata = prof_tdata_init(tsd); + tsd_prof_tdata_set(tsd, tdata); + } + } else if (unlikely(tdata->expired)) { + tdata = prof_tdata_reinit(tsd, tdata); + tsd_prof_tdata_set(tsd, tdata); + } + assert(tdata == NULL || tdata->attached); + } + + return tdata; +} + +JEMALLOC_ALWAYS_INLINE prof_tctx_t * +prof_tctx_get(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx) { + cassert(config_prof); + assert(ptr != NULL); + + return arena_prof_tctx_get(tsdn, ptr, alloc_ctx); +} + +JEMALLOC_ALWAYS_INLINE void +prof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize, + alloc_ctx_t *alloc_ctx, prof_tctx_t *tctx) { + cassert(config_prof); + assert(ptr != NULL); + + arena_prof_tctx_set(tsdn, ptr, usize, alloc_ctx, tctx); +} + +JEMALLOC_ALWAYS_INLINE void +prof_tctx_reset(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx) { + cassert(config_prof); + assert(ptr != NULL); + + arena_prof_tctx_reset(tsdn, ptr, tctx); +} + +JEMALLOC_ALWAYS_INLINE bool +prof_sample_accum_update(tsd_t *tsd, size_t usize, bool update, + prof_tdata_t **tdata_out) { + prof_tdata_t *tdata; + + cassert(config_prof); + + tdata = prof_tdata_get(tsd, true); + if (unlikely((uintptr_t)tdata <= (uintptr_t)PROF_TDATA_STATE_MAX)) { + tdata = NULL; + } + + if (tdata_out != NULL) { + *tdata_out = tdata; + } + + if (unlikely(tdata == NULL)) { + return true; + } + + if (likely(tdata->bytes_until_sample >= usize)) { + if (update) { + tdata->bytes_until_sample -= usize; + } + return true; + } else { + if (tsd_reentrancy_level_get(tsd) > 0) { + return true; + } + /* Compute new sample threshold. */ + if (update) { + prof_sample_threshold_update(tdata); + } + return !tdata->active; + } +} + +JEMALLOC_ALWAYS_INLINE prof_tctx_t * +prof_alloc_prep(tsd_t *tsd, size_t usize, bool prof_active, bool update) { + prof_tctx_t *ret; + prof_tdata_t *tdata; + prof_bt_t bt; + + assert(usize == sz_s2u(usize)); + + if (!prof_active || likely(prof_sample_accum_update(tsd, usize, update, + &tdata))) { + ret = (prof_tctx_t *)(uintptr_t)1U; + } else { + bt_init(&bt, tdata->vec); + prof_backtrace(&bt); + ret = prof_lookup(tsd, &bt); + } + + return ret; +} + +JEMALLOC_ALWAYS_INLINE void +prof_malloc(tsdn_t *tsdn, const void *ptr, size_t usize, alloc_ctx_t *alloc_ctx, + prof_tctx_t *tctx) { + cassert(config_prof); + assert(ptr != NULL); + assert(usize == isalloc(tsdn, ptr)); + + if (unlikely((uintptr_t)tctx > (uintptr_t)1U)) { + prof_malloc_sample_object(tsdn, ptr, usize, tctx); + } else { + prof_tctx_set(tsdn, ptr, usize, alloc_ctx, + (prof_tctx_t *)(uintptr_t)1U); + } +} + +JEMALLOC_ALWAYS_INLINE void +prof_realloc(tsd_t *tsd, const void *ptr, size_t usize, prof_tctx_t *tctx, + bool prof_active, bool updated, const void *old_ptr, size_t old_usize, + prof_tctx_t *old_tctx) { + bool sampled, old_sampled, moved; + + cassert(config_prof); + assert(ptr != NULL || (uintptr_t)tctx <= (uintptr_t)1U); + + if (prof_active && !updated && ptr != NULL) { + assert(usize == isalloc(tsd_tsdn(tsd), ptr)); + if (prof_sample_accum_update(tsd, usize, true, NULL)) { + /* + * Don't sample. The usize passed to prof_alloc_prep() + * was larger than what actually got allocated, so a + * backtrace was captured for this allocation, even + * though its actual usize was insufficient to cross the + * sample threshold. + */ + prof_alloc_rollback(tsd, tctx, true); + tctx = (prof_tctx_t *)(uintptr_t)1U; + } + } + + sampled = ((uintptr_t)tctx > (uintptr_t)1U); + old_sampled = ((uintptr_t)old_tctx > (uintptr_t)1U); + moved = (ptr != old_ptr); + + if (unlikely(sampled)) { + prof_malloc_sample_object(tsd_tsdn(tsd), ptr, usize, tctx); + } else if (moved) { + prof_tctx_set(tsd_tsdn(tsd), ptr, usize, NULL, + (prof_tctx_t *)(uintptr_t)1U); + } else if (unlikely(old_sampled)) { + /* + * prof_tctx_set() would work for the !moved case as well, but + * prof_tctx_reset() is slightly cheaper, and the proper thing + * to do here in the presence of explicit knowledge re: moved + * state. + */ + prof_tctx_reset(tsd_tsdn(tsd), ptr, tctx); + } else { + assert((uintptr_t)prof_tctx_get(tsd_tsdn(tsd), ptr, NULL) == + (uintptr_t)1U); + } + + /* + * The prof_free_sampled_object() call must come after the + * prof_malloc_sample_object() call, because tctx and old_tctx may be + * the same, in which case reversing the call order could cause the tctx + * to be prematurely destroyed as a side effect of momentarily zeroed + * counters. + */ + if (unlikely(old_sampled)) { + prof_free_sampled_object(tsd, old_usize, old_tctx); + } +} + +JEMALLOC_ALWAYS_INLINE void +prof_free(tsd_t *tsd, const void *ptr, size_t usize, alloc_ctx_t *alloc_ctx) { + prof_tctx_t *tctx = prof_tctx_get(tsd_tsdn(tsd), ptr, alloc_ctx); + + cassert(config_prof); + assert(usize == isalloc(tsd_tsdn(tsd), ptr)); + + if (unlikely((uintptr_t)tctx > (uintptr_t)1U)) { + prof_free_sampled_object(tsd, usize, tctx); + } +} + +#endif /* JEMALLOC_INTERNAL_PROF_INLINES_B_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_structs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_structs.h new file mode 100644 index 0000000000..0d58ae1005 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_structs.h @@ -0,0 +1,201 @@ +#ifndef JEMALLOC_INTERNAL_PROF_STRUCTS_H +#define JEMALLOC_INTERNAL_PROF_STRUCTS_H + +#include "jemalloc/internal/ckh.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/prng.h" +#include "jemalloc/internal/rb.h" + +struct prof_bt_s { + /* Backtrace, stored as len program counters. */ + void **vec; + unsigned len; +}; + +#ifdef JEMALLOC_PROF_LIBGCC +/* Data structure passed to libgcc _Unwind_Backtrace() callback functions. */ +typedef struct { + prof_bt_t *bt; + unsigned max; +} prof_unwind_data_t; +#endif + +struct prof_accum_s { +#ifndef JEMALLOC_ATOMIC_U64 + malloc_mutex_t mtx; + uint64_t accumbytes; +#else + atomic_u64_t accumbytes; +#endif +}; + +struct prof_cnt_s { + /* Profiling counters. */ + uint64_t curobjs; + uint64_t curbytes; + uint64_t accumobjs; + uint64_t accumbytes; +}; + +typedef enum { + prof_tctx_state_initializing, + prof_tctx_state_nominal, + prof_tctx_state_dumping, + prof_tctx_state_purgatory /* Dumper must finish destroying. */ +} prof_tctx_state_t; + +struct prof_tctx_s { + /* Thread data for thread that performed the allocation. */ + prof_tdata_t *tdata; + + /* + * Copy of tdata->thr_{uid,discrim}, necessary because tdata may be + * defunct during teardown. + */ + uint64_t thr_uid; + uint64_t thr_discrim; + + /* Profiling counters, protected by tdata->lock. */ + prof_cnt_t cnts; + + /* Associated global context. */ + prof_gctx_t *gctx; + + /* + * UID that distinguishes multiple tctx's created by the same thread, + * but coexisting in gctx->tctxs. There are two ways that such + * coexistence can occur: + * - A dumper thread can cause a tctx to be retained in the purgatory + * state. + * - Although a single "producer" thread must create all tctx's which + * share the same thr_uid, multiple "consumers" can each concurrently + * execute portions of prof_tctx_destroy(). prof_tctx_destroy() only + * gets called once each time cnts.cur{objs,bytes} drop to 0, but this + * threshold can be hit again before the first consumer finishes + * executing prof_tctx_destroy(). + */ + uint64_t tctx_uid; + + /* Linkage into gctx's tctxs. */ + rb_node(prof_tctx_t) tctx_link; + + /* + * True during prof_alloc_prep()..prof_malloc_sample_object(), prevents + * sample vs destroy race. + */ + bool prepared; + + /* Current dump-related state, protected by gctx->lock. */ + prof_tctx_state_t state; + + /* + * Copy of cnts snapshotted during early dump phase, protected by + * dump_mtx. + */ + prof_cnt_t dump_cnts; +}; +typedef rb_tree(prof_tctx_t) prof_tctx_tree_t; + +struct prof_gctx_s { + /* Protects nlimbo, cnt_summed, and tctxs. */ + malloc_mutex_t *lock; + + /* + * Number of threads that currently cause this gctx to be in a state of + * limbo due to one of: + * - Initializing this gctx. + * - Initializing per thread counters associated with this gctx. + * - Preparing to destroy this gctx. + * - Dumping a heap profile that includes this gctx. + * nlimbo must be 1 (single destroyer) in order to safely destroy the + * gctx. + */ + unsigned nlimbo; + + /* + * Tree of profile counters, one for each thread that has allocated in + * this context. + */ + prof_tctx_tree_t tctxs; + + /* Linkage for tree of contexts to be dumped. */ + rb_node(prof_gctx_t) dump_link; + + /* Temporary storage for summation during dump. */ + prof_cnt_t cnt_summed; + + /* Associated backtrace. */ + prof_bt_t bt; + + /* Backtrace vector, variable size, referred to by bt. */ + void *vec[1]; +}; +typedef rb_tree(prof_gctx_t) prof_gctx_tree_t; + +struct prof_tdata_s { + malloc_mutex_t *lock; + + /* Monotonically increasing unique thread identifier. */ + uint64_t thr_uid; + + /* + * Monotonically increasing discriminator among tdata structures + * associated with the same thr_uid. + */ + uint64_t thr_discrim; + + /* Included in heap profile dumps if non-NULL. */ + char *thread_name; + + bool attached; + bool expired; + + rb_node(prof_tdata_t) tdata_link; + + /* + * Counter used to initialize prof_tctx_t's tctx_uid. No locking is + * necessary when incrementing this field, because only one thread ever + * does so. + */ + uint64_t tctx_uid_next; + + /* + * Hash of (prof_bt_t *)-->(prof_tctx_t *). Each thread tracks + * backtraces for which it has non-zero allocation/deallocation counters + * associated with thread-specific prof_tctx_t objects. Other threads + * may write to prof_tctx_t contents when freeing associated objects. + */ + ckh_t bt2tctx; + + /* Sampling state. */ + uint64_t prng_state; + uint64_t bytes_until_sample; + + /* State used to avoid dumping while operating on prof internals. */ + bool enq; + bool enq_idump; + bool enq_gdump; + + /* + * Set to true during an early dump phase for tdata's which are + * currently being dumped. New threads' tdata's have this initialized + * to false so that they aren't accidentally included in later dump + * phases. + */ + bool dumping; + + /* + * True if profiling is active for this tdata's thread + * (thread.prof.active mallctl). + */ + bool active; + + /* Temporary storage for summation during dump. */ + prof_cnt_t cnt_summed; + + /* Backtrace vector, used for calls to prof_backtrace(). */ + void *vec[PROF_BT_MAX]; +}; +typedef rb_tree(prof_tdata_t) prof_tdata_tree_t; + +#endif /* JEMALLOC_INTERNAL_PROF_STRUCTS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_types.h new file mode 100644 index 0000000000..1eff995ecf --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/prof_types.h @@ -0,0 +1,56 @@ +#ifndef JEMALLOC_INTERNAL_PROF_TYPES_H +#define JEMALLOC_INTERNAL_PROF_TYPES_H + +typedef struct prof_bt_s prof_bt_t; +typedef struct prof_accum_s prof_accum_t; +typedef struct prof_cnt_s prof_cnt_t; +typedef struct prof_tctx_s prof_tctx_t; +typedef struct prof_gctx_s prof_gctx_t; +typedef struct prof_tdata_s prof_tdata_t; + +/* Option defaults. */ +#ifdef JEMALLOC_PROF +# define PROF_PREFIX_DEFAULT "jeprof" +#else +# define PROF_PREFIX_DEFAULT "" +#endif +#define LG_PROF_SAMPLE_DEFAULT 19 +#define LG_PROF_INTERVAL_DEFAULT -1 + +/* + * Hard limit on stack backtrace depth. The version of prof_backtrace() that + * is based on __builtin_return_address() necessarily has a hard-coded number + * of backtrace frame handlers, and should be kept in sync with this setting. + */ +#define PROF_BT_MAX 128 + +/* Initial hash table size. */ +#define PROF_CKH_MINITEMS 64 + +/* Size of memory buffer to use when writing dump files. */ +#define PROF_DUMP_BUFSIZE 65536 + +/* Size of stack-allocated buffer used by prof_printf(). */ +#define PROF_PRINTF_BUFSIZE 128 + +/* + * Number of mutexes shared among all gctx's. No space is allocated for these + * unless profiling is enabled, so it's okay to over-provision. + */ +#define PROF_NCTX_LOCKS 1024 + +/* + * Number of mutexes shared among all tdata's. No space is allocated for these + * unless profiling is enabled, so it's okay to over-provision. + */ +#define PROF_NTDATA_LOCKS 256 + +/* + * prof_tdata pointers close to NULL are used to encode state information that + * is used for cleaning up during thread shutdown. + */ +#define PROF_TDATA_STATE_REINCARNATED ((prof_tdata_t *)(uintptr_t)1) +#define PROF_TDATA_STATE_PURGATORY ((prof_tdata_t *)(uintptr_t)2) +#define PROF_TDATA_STATE_MAX PROF_TDATA_STATE_PURGATORY + +#endif /* JEMALLOC_INTERNAL_PROF_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/rtree_tsd.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/rtree_tsd.h new file mode 100644 index 0000000000..3cdc862548 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/rtree_tsd.h @@ -0,0 +1,50 @@ +#ifndef JEMALLOC_INTERNAL_RTREE_CTX_H +#define JEMALLOC_INTERNAL_RTREE_CTX_H + +/* + * Number of leafkey/leaf pairs to cache in L1 and L2 level respectively. Each + * entry supports an entire leaf, so the cache hit rate is typically high even + * with a small number of entries. In rare cases extent activity will straddle + * the boundary between two leaf nodes. Furthermore, an arena may use a + * combination of dss and mmap. Note that as memory usage grows past the amount + * that this cache can directly cover, the cache will become less effective if + * locality of reference is low, but the consequence is merely cache misses + * while traversing the tree nodes. + * + * The L1 direct mapped cache offers consistent and low cost on cache hit. + * However collision could affect hit rate negatively. This is resolved by + * combining with a L2 LRU cache, which requires linear search and re-ordering + * on access but suffers no collision. Note that, the cache will itself suffer + * cache misses if made overly large, plus the cost of linear search in the LRU + * cache. + */ +#define RTREE_CTX_LG_NCACHE 4 +#define RTREE_CTX_NCACHE (1 << RTREE_CTX_LG_NCACHE) +#define RTREE_CTX_NCACHE_L2 8 + +/* + * Zero initializer required for tsd initialization only. Proper initialization + * done via rtree_ctx_data_init(). + */ +#define RTREE_CTX_ZERO_INITIALIZER {{{0}}} + + +typedef struct rtree_leaf_elm_s rtree_leaf_elm_t; + +typedef struct rtree_ctx_cache_elm_s rtree_ctx_cache_elm_t; +struct rtree_ctx_cache_elm_s { + uintptr_t leafkey; + rtree_leaf_elm_t *leaf; +}; + +typedef struct rtree_ctx_s rtree_ctx_t; +struct rtree_ctx_s { + /* Direct mapped cache. */ + rtree_ctx_cache_elm_t cache[RTREE_CTX_NCACHE]; + /* L2 LRU cache. */ + rtree_ctx_cache_elm_t l2_cache[RTREE_CTX_NCACHE_L2]; +}; + +void rtree_ctx_data_init(rtree_ctx_t *ctx); + +#endif /* JEMALLOC_INTERNAL_RTREE_CTX_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/smoothstep.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/smoothstep.h new file mode 100644 index 0000000000..2e14430f5f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/smoothstep.h @@ -0,0 +1,232 @@ +#ifndef JEMALLOC_INTERNAL_SMOOTHSTEP_H +#define JEMALLOC_INTERNAL_SMOOTHSTEP_H + +/* + * This file was generated by the following command: + * sh smoothstep.sh smoother 200 24 3 15 + */ +/******************************************************************************/ + +/* + * This header defines a precomputed table based on the smoothstep family of + * sigmoidal curves (https://en.wikipedia.org/wiki/Smoothstep) that grow from 0 + * to 1 in 0 <= x <= 1. The table is stored as integer fixed point values so + * that floating point math can be avoided. + * + * 3 2 + * smoothstep(x) = -2x + 3x + * + * 5 4 3 + * smootherstep(x) = 6x - 15x + 10x + * + * 7 6 5 4 + * smootheststep(x) = -20x + 70x - 84x + 35x + */ + +#define SMOOTHSTEP_VARIANT "smoother" +#define SMOOTHSTEP_NSTEPS 200 +#define SMOOTHSTEP_BFP 24 +#define SMOOTHSTEP \ + /* STEP(step, h, x, y) */ \ + STEP( 1, UINT64_C(0x0000000000000014), 0.005, 0.000001240643750) \ + STEP( 2, UINT64_C(0x00000000000000a5), 0.010, 0.000009850600000) \ + STEP( 3, UINT64_C(0x0000000000000229), 0.015, 0.000032995181250) \ + STEP( 4, UINT64_C(0x0000000000000516), 0.020, 0.000077619200000) \ + STEP( 5, UINT64_C(0x00000000000009dc), 0.025, 0.000150449218750) \ + STEP( 6, UINT64_C(0x00000000000010e8), 0.030, 0.000257995800000) \ + STEP( 7, UINT64_C(0x0000000000001aa4), 0.035, 0.000406555756250) \ + STEP( 8, UINT64_C(0x0000000000002777), 0.040, 0.000602214400000) \ + STEP( 9, UINT64_C(0x00000000000037c2), 0.045, 0.000850847793750) \ + STEP( 10, UINT64_C(0x0000000000004be6), 0.050, 0.001158125000000) \ + STEP( 11, UINT64_C(0x000000000000643c), 0.055, 0.001529510331250) \ + STEP( 12, UINT64_C(0x000000000000811f), 0.060, 0.001970265600000) \ + STEP( 13, UINT64_C(0x000000000000a2e2), 0.065, 0.002485452368750) \ + STEP( 14, UINT64_C(0x000000000000c9d8), 0.070, 0.003079934200000) \ + STEP( 15, UINT64_C(0x000000000000f64f), 0.075, 0.003758378906250) \ + STEP( 16, UINT64_C(0x0000000000012891), 0.080, 0.004525260800000) \ + STEP( 17, UINT64_C(0x00000000000160e7), 0.085, 0.005384862943750) \ + STEP( 18, UINT64_C(0x0000000000019f95), 0.090, 0.006341279400000) \ + STEP( 19, UINT64_C(0x000000000001e4dc), 0.095, 0.007398417481250) \ + STEP( 20, UINT64_C(0x00000000000230fc), 0.100, 0.008560000000000) \ + STEP( 21, UINT64_C(0x0000000000028430), 0.105, 0.009829567518750) \ + STEP( 22, UINT64_C(0x000000000002deb0), 0.110, 0.011210480600000) \ + STEP( 23, UINT64_C(0x00000000000340b1), 0.115, 0.012705922056250) \ + STEP( 24, UINT64_C(0x000000000003aa67), 0.120, 0.014318899200000) \ + STEP( 25, UINT64_C(0x0000000000041c00), 0.125, 0.016052246093750) \ + STEP( 26, UINT64_C(0x00000000000495a8), 0.130, 0.017908625800000) \ + STEP( 27, UINT64_C(0x000000000005178b), 0.135, 0.019890532631250) \ + STEP( 28, UINT64_C(0x000000000005a1cf), 0.140, 0.022000294400000) \ + STEP( 29, UINT64_C(0x0000000000063498), 0.145, 0.024240074668750) \ + STEP( 30, UINT64_C(0x000000000006d009), 0.150, 0.026611875000000) \ + STEP( 31, UINT64_C(0x000000000007743f), 0.155, 0.029117537206250) \ + STEP( 32, UINT64_C(0x0000000000082157), 0.160, 0.031758745600000) \ + STEP( 33, UINT64_C(0x000000000008d76b), 0.165, 0.034537029243750) \ + STEP( 34, UINT64_C(0x0000000000099691), 0.170, 0.037453764200000) \ + STEP( 35, UINT64_C(0x00000000000a5edf), 0.175, 0.040510175781250) \ + STEP( 36, UINT64_C(0x00000000000b3067), 0.180, 0.043707340800000) \ + STEP( 37, UINT64_C(0x00000000000c0b38), 0.185, 0.047046189818750) \ + STEP( 38, UINT64_C(0x00000000000cef5e), 0.190, 0.050527509400000) \ + STEP( 39, UINT64_C(0x00000000000ddce6), 0.195, 0.054151944356250) \ + STEP( 40, UINT64_C(0x00000000000ed3d8), 0.200, 0.057920000000000) \ + STEP( 41, UINT64_C(0x00000000000fd439), 0.205, 0.061832044393750) \ + STEP( 42, UINT64_C(0x000000000010de0e), 0.210, 0.065888310600000) \ + STEP( 43, UINT64_C(0x000000000011f158), 0.215, 0.070088898931250) \ + STEP( 44, UINT64_C(0x0000000000130e17), 0.220, 0.074433779200000) \ + STEP( 45, UINT64_C(0x0000000000143448), 0.225, 0.078922792968750) \ + STEP( 46, UINT64_C(0x00000000001563e7), 0.230, 0.083555655800000) \ + STEP( 47, UINT64_C(0x0000000000169cec), 0.235, 0.088331959506250) \ + STEP( 48, UINT64_C(0x000000000017df4f), 0.240, 0.093251174400000) \ + STEP( 49, UINT64_C(0x0000000000192b04), 0.245, 0.098312651543750) \ + STEP( 50, UINT64_C(0x00000000001a8000), 0.250, 0.103515625000000) \ + STEP( 51, UINT64_C(0x00000000001bde32), 0.255, 0.108859214081250) \ + STEP( 52, UINT64_C(0x00000000001d458b), 0.260, 0.114342425600000) \ + STEP( 53, UINT64_C(0x00000000001eb5f8), 0.265, 0.119964156118750) \ + STEP( 54, UINT64_C(0x0000000000202f65), 0.270, 0.125723194200000) \ + STEP( 55, UINT64_C(0x000000000021b1bb), 0.275, 0.131618222656250) \ + STEP( 56, UINT64_C(0x0000000000233ce3), 0.280, 0.137647820800000) \ + STEP( 57, UINT64_C(0x000000000024d0c3), 0.285, 0.143810466693750) \ + STEP( 58, UINT64_C(0x0000000000266d40), 0.290, 0.150104539400000) \ + STEP( 59, UINT64_C(0x000000000028123d), 0.295, 0.156528321231250) \ + STEP( 60, UINT64_C(0x000000000029bf9c), 0.300, 0.163080000000000) \ + STEP( 61, UINT64_C(0x00000000002b753d), 0.305, 0.169757671268750) \ + STEP( 62, UINT64_C(0x00000000002d32fe), 0.310, 0.176559340600000) \ + STEP( 63, UINT64_C(0x00000000002ef8bc), 0.315, 0.183482925806250) \ + STEP( 64, UINT64_C(0x000000000030c654), 0.320, 0.190526259200000) \ + STEP( 65, UINT64_C(0x0000000000329b9f), 0.325, 0.197687089843750) \ + STEP( 66, UINT64_C(0x0000000000347875), 0.330, 0.204963085800000) \ + STEP( 67, UINT64_C(0x0000000000365cb0), 0.335, 0.212351836381250) \ + STEP( 68, UINT64_C(0x0000000000384825), 0.340, 0.219850854400000) \ + STEP( 69, UINT64_C(0x00000000003a3aa8), 0.345, 0.227457578418750) \ + STEP( 70, UINT64_C(0x00000000003c340f), 0.350, 0.235169375000000) \ + STEP( 71, UINT64_C(0x00000000003e342b), 0.355, 0.242983540956250) \ + STEP( 72, UINT64_C(0x0000000000403ace), 0.360, 0.250897305600000) \ + STEP( 73, UINT64_C(0x00000000004247c8), 0.365, 0.258907832993750) \ + STEP( 74, UINT64_C(0x0000000000445ae9), 0.370, 0.267012224200000) \ + STEP( 75, UINT64_C(0x0000000000467400), 0.375, 0.275207519531250) \ + STEP( 76, UINT64_C(0x00000000004892d8), 0.380, 0.283490700800000) \ + STEP( 77, UINT64_C(0x00000000004ab740), 0.385, 0.291858693568750) \ + STEP( 78, UINT64_C(0x00000000004ce102), 0.390, 0.300308369400000) \ + STEP( 79, UINT64_C(0x00000000004f0fe9), 0.395, 0.308836548106250) \ + STEP( 80, UINT64_C(0x00000000005143bf), 0.400, 0.317440000000000) \ + STEP( 81, UINT64_C(0x0000000000537c4d), 0.405, 0.326115448143750) \ + STEP( 82, UINT64_C(0x000000000055b95b), 0.410, 0.334859570600000) \ + STEP( 83, UINT64_C(0x000000000057fab1), 0.415, 0.343669002681250) \ + STEP( 84, UINT64_C(0x00000000005a4015), 0.420, 0.352540339200000) \ + STEP( 85, UINT64_C(0x00000000005c894e), 0.425, 0.361470136718750) \ + STEP( 86, UINT64_C(0x00000000005ed622), 0.430, 0.370454915800000) \ + STEP( 87, UINT64_C(0x0000000000612655), 0.435, 0.379491163256250) \ + STEP( 88, UINT64_C(0x00000000006379ac), 0.440, 0.388575334400000) \ + STEP( 89, UINT64_C(0x000000000065cfeb), 0.445, 0.397703855293750) \ + STEP( 90, UINT64_C(0x00000000006828d6), 0.450, 0.406873125000000) \ + STEP( 91, UINT64_C(0x00000000006a842f), 0.455, 0.416079517831250) \ + STEP( 92, UINT64_C(0x00000000006ce1bb), 0.460, 0.425319385600000) \ + STEP( 93, UINT64_C(0x00000000006f413a), 0.465, 0.434589059868750) \ + STEP( 94, UINT64_C(0x000000000071a270), 0.470, 0.443884854200000) \ + STEP( 95, UINT64_C(0x000000000074051d), 0.475, 0.453203066406250) \ + STEP( 96, UINT64_C(0x0000000000766905), 0.480, 0.462539980800000) \ + STEP( 97, UINT64_C(0x000000000078cde7), 0.485, 0.471891870443750) \ + STEP( 98, UINT64_C(0x00000000007b3387), 0.490, 0.481254999400000) \ + STEP( 99, UINT64_C(0x00000000007d99a4), 0.495, 0.490625624981250) \ + STEP( 100, UINT64_C(0x0000000000800000), 0.500, 0.500000000000000) \ + STEP( 101, UINT64_C(0x000000000082665b), 0.505, 0.509374375018750) \ + STEP( 102, UINT64_C(0x000000000084cc78), 0.510, 0.518745000600000) \ + STEP( 103, UINT64_C(0x0000000000873218), 0.515, 0.528108129556250) \ + STEP( 104, UINT64_C(0x00000000008996fa), 0.520, 0.537460019200000) \ + STEP( 105, UINT64_C(0x00000000008bfae2), 0.525, 0.546796933593750) \ + STEP( 106, UINT64_C(0x00000000008e5d8f), 0.530, 0.556115145800000) \ + STEP( 107, UINT64_C(0x000000000090bec5), 0.535, 0.565410940131250) \ + STEP( 108, UINT64_C(0x0000000000931e44), 0.540, 0.574680614400000) \ + STEP( 109, UINT64_C(0x0000000000957bd0), 0.545, 0.583920482168750) \ + STEP( 110, UINT64_C(0x000000000097d729), 0.550, 0.593126875000000) \ + STEP( 111, UINT64_C(0x00000000009a3014), 0.555, 0.602296144706250) \ + STEP( 112, UINT64_C(0x00000000009c8653), 0.560, 0.611424665600000) \ + STEP( 113, UINT64_C(0x00000000009ed9aa), 0.565, 0.620508836743750) \ + STEP( 114, UINT64_C(0x0000000000a129dd), 0.570, 0.629545084200000) \ + STEP( 115, UINT64_C(0x0000000000a376b1), 0.575, 0.638529863281250) \ + STEP( 116, UINT64_C(0x0000000000a5bfea), 0.580, 0.647459660800000) \ + STEP( 117, UINT64_C(0x0000000000a8054e), 0.585, 0.656330997318750) \ + STEP( 118, UINT64_C(0x0000000000aa46a4), 0.590, 0.665140429400000) \ + STEP( 119, UINT64_C(0x0000000000ac83b2), 0.595, 0.673884551856250) \ + STEP( 120, UINT64_C(0x0000000000aebc40), 0.600, 0.682560000000000) \ + STEP( 121, UINT64_C(0x0000000000b0f016), 0.605, 0.691163451893750) \ + STEP( 122, UINT64_C(0x0000000000b31efd), 0.610, 0.699691630600000) \ + STEP( 123, UINT64_C(0x0000000000b548bf), 0.615, 0.708141306431250) \ + STEP( 124, UINT64_C(0x0000000000b76d27), 0.620, 0.716509299200000) \ + STEP( 125, UINT64_C(0x0000000000b98c00), 0.625, 0.724792480468750) \ + STEP( 126, UINT64_C(0x0000000000bba516), 0.630, 0.732987775800000) \ + STEP( 127, UINT64_C(0x0000000000bdb837), 0.635, 0.741092167006250) \ + STEP( 128, UINT64_C(0x0000000000bfc531), 0.640, 0.749102694400000) \ + STEP( 129, UINT64_C(0x0000000000c1cbd4), 0.645, 0.757016459043750) \ + STEP( 130, UINT64_C(0x0000000000c3cbf0), 0.650, 0.764830625000000) \ + STEP( 131, UINT64_C(0x0000000000c5c557), 0.655, 0.772542421581250) \ + STEP( 132, UINT64_C(0x0000000000c7b7da), 0.660, 0.780149145600000) \ + STEP( 133, UINT64_C(0x0000000000c9a34f), 0.665, 0.787648163618750) \ + STEP( 134, UINT64_C(0x0000000000cb878a), 0.670, 0.795036914200000) \ + STEP( 135, UINT64_C(0x0000000000cd6460), 0.675, 0.802312910156250) \ + STEP( 136, UINT64_C(0x0000000000cf39ab), 0.680, 0.809473740800000) \ + STEP( 137, UINT64_C(0x0000000000d10743), 0.685, 0.816517074193750) \ + STEP( 138, UINT64_C(0x0000000000d2cd01), 0.690, 0.823440659400000) \ + STEP( 139, UINT64_C(0x0000000000d48ac2), 0.695, 0.830242328731250) \ + STEP( 140, UINT64_C(0x0000000000d64063), 0.700, 0.836920000000000) \ + STEP( 141, UINT64_C(0x0000000000d7edc2), 0.705, 0.843471678768750) \ + STEP( 142, UINT64_C(0x0000000000d992bf), 0.710, 0.849895460600000) \ + STEP( 143, UINT64_C(0x0000000000db2f3c), 0.715, 0.856189533306250) \ + STEP( 144, UINT64_C(0x0000000000dcc31c), 0.720, 0.862352179200000) \ + STEP( 145, UINT64_C(0x0000000000de4e44), 0.725, 0.868381777343750) \ + STEP( 146, UINT64_C(0x0000000000dfd09a), 0.730, 0.874276805800000) \ + STEP( 147, UINT64_C(0x0000000000e14a07), 0.735, 0.880035843881250) \ + STEP( 148, UINT64_C(0x0000000000e2ba74), 0.740, 0.885657574400000) \ + STEP( 149, UINT64_C(0x0000000000e421cd), 0.745, 0.891140785918750) \ + STEP( 150, UINT64_C(0x0000000000e58000), 0.750, 0.896484375000000) \ + STEP( 151, UINT64_C(0x0000000000e6d4fb), 0.755, 0.901687348456250) \ + STEP( 152, UINT64_C(0x0000000000e820b0), 0.760, 0.906748825600000) \ + STEP( 153, UINT64_C(0x0000000000e96313), 0.765, 0.911668040493750) \ + STEP( 154, UINT64_C(0x0000000000ea9c18), 0.770, 0.916444344200000) \ + STEP( 155, UINT64_C(0x0000000000ebcbb7), 0.775, 0.921077207031250) \ + STEP( 156, UINT64_C(0x0000000000ecf1e8), 0.780, 0.925566220800000) \ + STEP( 157, UINT64_C(0x0000000000ee0ea7), 0.785, 0.929911101068750) \ + STEP( 158, UINT64_C(0x0000000000ef21f1), 0.790, 0.934111689400000) \ + STEP( 159, UINT64_C(0x0000000000f02bc6), 0.795, 0.938167955606250) \ + STEP( 160, UINT64_C(0x0000000000f12c27), 0.800, 0.942080000000000) \ + STEP( 161, UINT64_C(0x0000000000f22319), 0.805, 0.945848055643750) \ + STEP( 162, UINT64_C(0x0000000000f310a1), 0.810, 0.949472490600000) \ + STEP( 163, UINT64_C(0x0000000000f3f4c7), 0.815, 0.952953810181250) \ + STEP( 164, UINT64_C(0x0000000000f4cf98), 0.820, 0.956292659200000) \ + STEP( 165, UINT64_C(0x0000000000f5a120), 0.825, 0.959489824218750) \ + STEP( 166, UINT64_C(0x0000000000f6696e), 0.830, 0.962546235800000) \ + STEP( 167, UINT64_C(0x0000000000f72894), 0.835, 0.965462970756250) \ + STEP( 168, UINT64_C(0x0000000000f7dea8), 0.840, 0.968241254400000) \ + STEP( 169, UINT64_C(0x0000000000f88bc0), 0.845, 0.970882462793750) \ + STEP( 170, UINT64_C(0x0000000000f92ff6), 0.850, 0.973388125000000) \ + STEP( 171, UINT64_C(0x0000000000f9cb67), 0.855, 0.975759925331250) \ + STEP( 172, UINT64_C(0x0000000000fa5e30), 0.860, 0.977999705600000) \ + STEP( 173, UINT64_C(0x0000000000fae874), 0.865, 0.980109467368750) \ + STEP( 174, UINT64_C(0x0000000000fb6a57), 0.870, 0.982091374200000) \ + STEP( 175, UINT64_C(0x0000000000fbe400), 0.875, 0.983947753906250) \ + STEP( 176, UINT64_C(0x0000000000fc5598), 0.880, 0.985681100800000) \ + STEP( 177, UINT64_C(0x0000000000fcbf4e), 0.885, 0.987294077943750) \ + STEP( 178, UINT64_C(0x0000000000fd214f), 0.890, 0.988789519400000) \ + STEP( 179, UINT64_C(0x0000000000fd7bcf), 0.895, 0.990170432481250) \ + STEP( 180, UINT64_C(0x0000000000fdcf03), 0.900, 0.991440000000000) \ + STEP( 181, UINT64_C(0x0000000000fe1b23), 0.905, 0.992601582518750) \ + STEP( 182, UINT64_C(0x0000000000fe606a), 0.910, 0.993658720600000) \ + STEP( 183, UINT64_C(0x0000000000fe9f18), 0.915, 0.994615137056250) \ + STEP( 184, UINT64_C(0x0000000000fed76e), 0.920, 0.995474739200000) \ + STEP( 185, UINT64_C(0x0000000000ff09b0), 0.925, 0.996241621093750) \ + STEP( 186, UINT64_C(0x0000000000ff3627), 0.930, 0.996920065800000) \ + STEP( 187, UINT64_C(0x0000000000ff5d1d), 0.935, 0.997514547631250) \ + STEP( 188, UINT64_C(0x0000000000ff7ee0), 0.940, 0.998029734400000) \ + STEP( 189, UINT64_C(0x0000000000ff9bc3), 0.945, 0.998470489668750) \ + STEP( 190, UINT64_C(0x0000000000ffb419), 0.950, 0.998841875000000) \ + STEP( 191, UINT64_C(0x0000000000ffc83d), 0.955, 0.999149152206250) \ + STEP( 192, UINT64_C(0x0000000000ffd888), 0.960, 0.999397785600000) \ + STEP( 193, UINT64_C(0x0000000000ffe55b), 0.965, 0.999593444243750) \ + STEP( 194, UINT64_C(0x0000000000ffef17), 0.970, 0.999742004200000) \ + STEP( 195, UINT64_C(0x0000000000fff623), 0.975, 0.999849550781250) \ + STEP( 196, UINT64_C(0x0000000000fffae9), 0.980, 0.999922380800000) \ + STEP( 197, UINT64_C(0x0000000000fffdd6), 0.985, 0.999967004818750) \ + STEP( 198, UINT64_C(0x0000000000ffff5a), 0.990, 0.999990149400000) \ + STEP( 199, UINT64_C(0x0000000000ffffeb), 0.995, 0.999998759356250) \ + STEP( 200, UINT64_C(0x0000000001000000), 1.000, 1.000000000000000) \ + +#endif /* JEMALLOC_INTERNAL_SMOOTHSTEP_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/spin.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/spin.h new file mode 100644 index 0000000000..e2afc98cfd --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/spin.h @@ -0,0 +1,36 @@ +#ifndef JEMALLOC_INTERNAL_SPIN_H +#define JEMALLOC_INTERNAL_SPIN_H + +#ifdef JEMALLOC_SPIN_C_ +# define SPIN_INLINE extern inline +#else +# define SPIN_INLINE inline +#endif + +#define SPIN_INITIALIZER {0U} + +typedef struct { + unsigned iteration; +} spin_t; + +SPIN_INLINE void +spin_adaptive(spin_t *spin) { + volatile uint32_t i; + + if (spin->iteration < 5) { + for (i = 0; i < (1U << spin->iteration); i++) { + CPU_SPINWAIT; + } + spin->iteration++; + } else { +#ifdef _WIN32 + SwitchToThread(); +#else + sched_yield(); +#endif + } +} + +#undef SPIN_INLINE + +#endif /* JEMALLOC_INTERNAL_SPIN_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/stats_tsd.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/stats_tsd.h new file mode 100644 index 0000000000..d0c3bbe494 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/stats_tsd.h @@ -0,0 +1,12 @@ +#ifndef JEMALLOC_INTERNAL_STATS_TSD_H +#define JEMALLOC_INTERNAL_STATS_TSD_H + +typedef struct tcache_bin_stats_s { + /* + * Number of allocation requests that corresponded to the size of this + * bin. + */ + uint64_t nrequests; +} tcache_bin_stats_t; + +#endif /* JEMALLOC_INTERNAL_STATS_TSD_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/sz.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/sz.h new file mode 100644 index 0000000000..7f640d55ad --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/sz.h @@ -0,0 +1,317 @@ +#ifndef JEMALLOC_INTERNAL_SIZE_H +#define JEMALLOC_INTERNAL_SIZE_H + +#include "jemalloc/internal/bit_util.h" +#include "jemalloc/internal/pages.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/util.h" + +/* + * sz module: Size computations. + * + * Some abbreviations used here: + * p: Page + * ind: Index + * s, sz: Size + * u: Usable size + * a: Aligned + * + * These are not always used completely consistently, but should be enough to + * interpret function names. E.g. sz_psz2ind converts page size to page size + * index; sz_sa2u converts a (size, alignment) allocation request to the usable + * size that would result from such an allocation. + */ + +/* + * sz_pind2sz_tab encodes the same information as could be computed by + * sz_pind2sz_compute(). + */ +extern size_t const sz_pind2sz_tab[NPSIZES+1]; +/* + * sz_index2size_tab encodes the same information as could be computed (at + * unacceptable cost in some code paths) by sz_index2size_compute(). + */ +extern size_t const sz_index2size_tab[NSIZES]; +/* + * sz_size2index_tab is a compact lookup table that rounds request sizes up to + * size classes. In order to reduce cache footprint, the table is compressed, + * and all accesses are via sz_size2index(). + */ +extern uint8_t const sz_size2index_tab[]; + +static const size_t sz_large_pad = +#ifdef JEMALLOC_CACHE_OBLIVIOUS + PAGE +#else + 0 +#endif + ; + +JEMALLOC_ALWAYS_INLINE pszind_t +sz_psz2ind(size_t psz) { + if (unlikely(psz > LARGE_MAXCLASS)) { + return NPSIZES; + } + { + pszind_t x = lg_floor((psz<<1)-1); + pszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_PAGE) ? 0 : x - + (LG_SIZE_CLASS_GROUP + LG_PAGE); + pszind_t grp = shift << LG_SIZE_CLASS_GROUP; + + pszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ? + LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1; + + size_t delta_inverse_mask = ZD(-1) << lg_delta; + pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) & + ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + + pszind_t ind = grp + mod; + return ind; + } +} + +static inline size_t +sz_pind2sz_compute(pszind_t pind) { + if (unlikely(pind == NPSIZES)) { + return LARGE_MAXCLASS + PAGE; + } + { + size_t grp = pind >> LG_SIZE_CLASS_GROUP; + size_t mod = pind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + + size_t grp_size_mask = ~((!!grp)-1); + size_t grp_size = ((ZU(1) << (LG_PAGE + + (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask; + + size_t shift = (grp == 0) ? 1 : grp; + size_t lg_delta = shift + (LG_PAGE-1); + size_t mod_size = (mod+1) << lg_delta; + + size_t sz = grp_size + mod_size; + return sz; + } +} + +static inline size_t +sz_pind2sz_lookup(pszind_t pind) { + size_t ret = (size_t)sz_pind2sz_tab[pind]; + assert(ret == sz_pind2sz_compute(pind)); + return ret; +} + +static inline size_t +sz_pind2sz(pszind_t pind) { + assert(pind < NPSIZES+1); + return sz_pind2sz_lookup(pind); +} + +static inline size_t +sz_psz2u(size_t psz) { + if (unlikely(psz > LARGE_MAXCLASS)) { + return LARGE_MAXCLASS + PAGE; + } + { + size_t x = lg_floor((psz<<1)-1); + size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ? + LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1; + size_t delta = ZU(1) << lg_delta; + size_t delta_mask = delta - 1; + size_t usize = (psz + delta_mask) & ~delta_mask; + return usize; + } +} + +static inline szind_t +sz_size2index_compute(size_t size) { + if (unlikely(size > LARGE_MAXCLASS)) { + return NSIZES; + } +#if (NTBINS != 0) + if (size <= (ZU(1) << LG_TINY_MAXCLASS)) { + szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1; + szind_t lg_ceil = lg_floor(pow2_ceil_zu(size)); + return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin); + } +#endif + { + szind_t x = lg_floor((size<<1)-1); + szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 : + x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM); + szind_t grp = shift << LG_SIZE_CLASS_GROUP; + + szind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1) + ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1; + + size_t delta_inverse_mask = ZD(-1) << lg_delta; + szind_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) & + ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1); + + szind_t index = NTBINS + grp + mod; + return index; + } +} + +JEMALLOC_ALWAYS_INLINE szind_t +sz_size2index_lookup(size_t size) { + assert(size <= LOOKUP_MAXCLASS); + { + szind_t ret = (sz_size2index_tab[(size-1) >> LG_TINY_MIN]); + assert(ret == sz_size2index_compute(size)); + return ret; + } +} + +JEMALLOC_ALWAYS_INLINE szind_t +sz_size2index(size_t size) { + assert(size > 0); + if (likely(size <= LOOKUP_MAXCLASS)) { + return sz_size2index_lookup(size); + } + return sz_size2index_compute(size); +} + +static inline size_t +sz_index2size_compute(szind_t index) { +#if (NTBINS > 0) + if (index < NTBINS) { + return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index)); + } +#endif + { + size_t reduced_index = index - NTBINS; + size_t grp = reduced_index >> LG_SIZE_CLASS_GROUP; + size_t mod = reduced_index & ((ZU(1) << LG_SIZE_CLASS_GROUP) - + 1); + + size_t grp_size_mask = ~((!!grp)-1); + size_t grp_size = ((ZU(1) << (LG_QUANTUM + + (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask; + + size_t shift = (grp == 0) ? 1 : grp; + size_t lg_delta = shift + (LG_QUANTUM-1); + size_t mod_size = (mod+1) << lg_delta; + + size_t usize = grp_size + mod_size; + return usize; + } +} + +JEMALLOC_ALWAYS_INLINE size_t +sz_index2size_lookup(szind_t index) { + size_t ret = (size_t)sz_index2size_tab[index]; + assert(ret == sz_index2size_compute(index)); + return ret; +} + +JEMALLOC_ALWAYS_INLINE size_t +sz_index2size(szind_t index) { + assert(index < NSIZES); + return sz_index2size_lookup(index); +} + +JEMALLOC_ALWAYS_INLINE size_t +sz_s2u_compute(size_t size) { + if (unlikely(size > LARGE_MAXCLASS)) { + return 0; + } +#if (NTBINS > 0) + if (size <= (ZU(1) << LG_TINY_MAXCLASS)) { + size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1; + size_t lg_ceil = lg_floor(pow2_ceil_zu(size)); + return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) : + (ZU(1) << lg_ceil)); + } +#endif + { + size_t x = lg_floor((size<<1)-1); + size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1) + ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1; + size_t delta = ZU(1) << lg_delta; + size_t delta_mask = delta - 1; + size_t usize = (size + delta_mask) & ~delta_mask; + return usize; + } +} + +JEMALLOC_ALWAYS_INLINE size_t +sz_s2u_lookup(size_t size) { + size_t ret = sz_index2size_lookup(sz_size2index_lookup(size)); + + assert(ret == sz_s2u_compute(size)); + return ret; +} + +/* + * Compute usable size that would result from allocating an object with the + * specified size. + */ +JEMALLOC_ALWAYS_INLINE size_t +sz_s2u(size_t size) { + assert(size > 0); + if (likely(size <= LOOKUP_MAXCLASS)) { + return sz_s2u_lookup(size); + } + return sz_s2u_compute(size); +} + +/* + * Compute usable size that would result from allocating an object with the + * specified size and alignment. + */ +JEMALLOC_ALWAYS_INLINE size_t +sz_sa2u(size_t size, size_t alignment) { + size_t usize; + + assert(alignment != 0 && ((alignment - 1) & alignment) == 0); + + /* Try for a small size class. */ + if (size <= SMALL_MAXCLASS && alignment < PAGE) { + /* + * Round size up to the nearest multiple of alignment. + * + * This done, we can take advantage of the fact that for each + * small size class, every object is aligned at the smallest + * power of two that is non-zero in the base two representation + * of the size. For example: + * + * Size | Base 2 | Minimum alignment + * -----+----------+------------------ + * 96 | 1100000 | 32 + * 144 | 10100000 | 32 + * 192 | 11000000 | 64 + */ + usize = sz_s2u(ALIGNMENT_CEILING(size, alignment)); + if (usize < LARGE_MINCLASS) { + return usize; + } + } + + /* Large size class. Beware of overflow. */ + + if (unlikely(alignment > LARGE_MAXCLASS)) { + return 0; + } + + /* Make sure result is a large size class. */ + if (size <= LARGE_MINCLASS) { + usize = LARGE_MINCLASS; + } else { + usize = sz_s2u(size); + if (usize < size) { + /* size_t overflow. */ + return 0; + } + } + + /* + * Calculate the multi-page mapping that large_palloc() would need in + * order to guarantee the alignment. + */ + if (usize + sz_large_pad + PAGE_CEILING(alignment) - PAGE < usize) { + /* size_t overflow. */ + return 0; + } + return usize; +} + +#endif /* JEMALLOC_INTERNAL_SIZE_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_externs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_externs.h new file mode 100644 index 0000000000..db3e9c7d5d --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_externs.h @@ -0,0 +1,55 @@ +#ifndef JEMALLOC_INTERNAL_TCACHE_EXTERNS_H +#define JEMALLOC_INTERNAL_TCACHE_EXTERNS_H + +#include "jemalloc/internal/size_classes.h" + +extern bool opt_tcache; +extern ssize_t opt_lg_tcache_max; + +extern tcache_bin_info_t *tcache_bin_info; + +/* + * Number of tcache bins. There are NBINS small-object bins, plus 0 or more + * large-object bins. + */ +extern unsigned nhbins; + +/* Maximum cached size class. */ +extern size_t tcache_maxclass; + +/* + * Explicit tcaches, managed via the tcache.{create,flush,destroy} mallctls and + * usable via the MALLOCX_TCACHE() flag. The automatic per thread tcaches are + * completely disjoint from this data structure. tcaches starts off as a sparse + * array, so it has no physical memory footprint until individual pages are + * touched. This allows the entire array to be allocated the first time an + * explicit tcache is created without a disproportionate impact on memory usage. + */ +extern tcaches_t *tcaches; + +size_t tcache_salloc(tsdn_t *tsdn, const void *ptr); +void tcache_event_hard(tsd_t *tsd, tcache_t *tcache); +void *tcache_alloc_small_hard(tsdn_t *tsdn, arena_t *arena, tcache_t *tcache, + tcache_bin_t *tbin, szind_t binind, bool *tcache_success); +void tcache_bin_flush_small(tsd_t *tsd, tcache_t *tcache, tcache_bin_t *tbin, + szind_t binind, unsigned rem); +void tcache_bin_flush_large(tsd_t *tsd, tcache_bin_t *tbin, szind_t binind, + unsigned rem, tcache_t *tcache); +void tcache_arena_reassociate(tsdn_t *tsdn, tcache_t *tcache, + arena_t *arena); +tcache_t *tcache_create_explicit(tsd_t *tsd); +void tcache_cleanup(tsd_t *tsd); +void tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena); +bool tcaches_create(tsd_t *tsd, unsigned *r_ind); +void tcaches_flush(tsd_t *tsd, unsigned ind); +void tcaches_destroy(tsd_t *tsd, unsigned ind); +bool tcache_boot(tsdn_t *tsdn); +void tcache_arena_associate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena); +void tcache_prefork(tsdn_t *tsdn); +void tcache_postfork_parent(tsdn_t *tsdn); +void tcache_postfork_child(tsdn_t *tsdn); +void tcache_flush(tsd_t *tsd); +bool tsd_tcache_data_init(tsd_t *tsd); +bool tsd_tcache_enabled_data_init(tsd_t *tsd); + +#endif /* JEMALLOC_INTERNAL_TCACHE_EXTERNS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_inlines.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_inlines.h new file mode 100644 index 0000000000..c55bcd2723 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_inlines.h @@ -0,0 +1,250 @@ +#ifndef JEMALLOC_INTERNAL_TCACHE_INLINES_H +#define JEMALLOC_INTERNAL_TCACHE_INLINES_H + +#include "jemalloc/internal/jemalloc_internal_types.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/sz.h" +#include "jemalloc/internal/ticker.h" +#include "jemalloc/internal/util.h" + +static inline bool +tcache_enabled_get(tsd_t *tsd) { + return tsd_tcache_enabled_get(tsd); +} + +static inline void +tcache_enabled_set(tsd_t *tsd, bool enabled) { + bool was_enabled = tsd_tcache_enabled_get(tsd); + + if (!was_enabled && enabled) { + tsd_tcache_data_init(tsd); + } else if (was_enabled && !enabled) { + tcache_cleanup(tsd); + } + /* Commit the state last. Above calls check current state. */ + tsd_tcache_enabled_set(tsd, enabled); + tsd_slow_update(tsd); +} + +JEMALLOC_ALWAYS_INLINE void +tcache_event(tsd_t *tsd, tcache_t *tcache) { + if (TCACHE_GC_INCR == 0) { + return; + } + + if (unlikely(ticker_tick(&tcache->gc_ticker))) { + tcache_event_hard(tsd, tcache); + } +} + +JEMALLOC_ALWAYS_INLINE void * +tcache_alloc_easy(tcache_bin_t *tbin, bool *tcache_success) { + void *ret; + + if (unlikely(tbin->ncached == 0)) { + tbin->low_water = -1; + *tcache_success = false; + return NULL; + } + /* + * tcache_success (instead of ret) should be checked upon the return of + * this function. We avoid checking (ret == NULL) because there is + * never a null stored on the avail stack (which is unknown to the + * compiler), and eagerly checking ret would cause pipeline stall + * (waiting for the cacheline). + */ + *tcache_success = true; + ret = *(tbin->avail - tbin->ncached); + tbin->ncached--; + + if (unlikely((low_water_t)tbin->ncached < tbin->low_water)) { + tbin->low_water = tbin->ncached; + } + + return ret; +} + +JEMALLOC_ALWAYS_INLINE void * +tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, + szind_t binind, bool zero, bool slow_path) { + void *ret; + tcache_bin_t *tbin; + bool tcache_success; + size_t usize JEMALLOC_CC_SILENCE_INIT(0); + + assert(binind < NBINS); + tbin = tcache_small_bin_get(tcache, binind); + ret = tcache_alloc_easy(tbin, &tcache_success); + assert(tcache_success == (ret != NULL)); + if (unlikely(!tcache_success)) { + bool tcache_hard_success; + arena = arena_choose(tsd, arena); + if (unlikely(arena == NULL)) { + return NULL; + } + + ret = tcache_alloc_small_hard(tsd_tsdn(tsd), arena, tcache, + tbin, binind, &tcache_hard_success); + if (tcache_hard_success == false) { + return NULL; + } + } + + assert(ret); + /* + * Only compute usize if required. The checks in the following if + * statement are all static. + */ + if (config_prof || (slow_path && config_fill) || unlikely(zero)) { + usize = sz_index2size(binind); + assert(tcache_salloc(tsd_tsdn(tsd), ret) == usize); + } + + if (likely(!zero)) { + if (slow_path && config_fill) { + if (unlikely(opt_junk_alloc)) { + arena_alloc_junk_small(ret, + &arena_bin_info[binind], false); + } else if (unlikely(opt_zero)) { + memset(ret, 0, usize); + } + } + } else { + if (slow_path && config_fill && unlikely(opt_junk_alloc)) { + arena_alloc_junk_small(ret, &arena_bin_info[binind], + true); + } + memset(ret, 0, usize); + } + + if (config_stats) { + tbin->tstats.nrequests++; + } + if (config_prof) { + tcache->prof_accumbytes += usize; + } + tcache_event(tsd, tcache); + return ret; +} + +JEMALLOC_ALWAYS_INLINE void * +tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size, + szind_t binind, bool zero, bool slow_path) { + void *ret; + tcache_bin_t *tbin; + bool tcache_success; + + assert(binind >= NBINS &&binind < nhbins); + tbin = tcache_large_bin_get(tcache, binind); + ret = tcache_alloc_easy(tbin, &tcache_success); + assert(tcache_success == (ret != NULL)); + if (unlikely(!tcache_success)) { + /* + * Only allocate one large object at a time, because it's quite + * expensive to create one and not use it. + */ + arena = arena_choose(tsd, arena); + if (unlikely(arena == NULL)) { + return NULL; + } + + ret = large_malloc(tsd_tsdn(tsd), arena, sz_s2u(size), zero); + if (ret == NULL) { + return NULL; + } + } else { + size_t usize JEMALLOC_CC_SILENCE_INIT(0); + + /* Only compute usize on demand */ + if (config_prof || (slow_path && config_fill) || + unlikely(zero)) { + usize = sz_index2size(binind); + assert(usize <= tcache_maxclass); + } + + if (likely(!zero)) { + if (slow_path && config_fill) { + if (unlikely(opt_junk_alloc)) { + memset(ret, JEMALLOC_ALLOC_JUNK, + usize); + } else if (unlikely(opt_zero)) { + memset(ret, 0, usize); + } + } + } else { + memset(ret, 0, usize); + } + + if (config_stats) { + tbin->tstats.nrequests++; + } + if (config_prof) { + tcache->prof_accumbytes += usize; + } + } + + tcache_event(tsd, tcache); + return ret; +} + +JEMALLOC_ALWAYS_INLINE void +tcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, + bool slow_path) { + tcache_bin_t *tbin; + tcache_bin_info_t *tbin_info; + + assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= SMALL_MAXCLASS); + + if (slow_path && config_fill && unlikely(opt_junk_free)) { + arena_dalloc_junk_small(ptr, &arena_bin_info[binind]); + } + + tbin = tcache_small_bin_get(tcache, binind); + tbin_info = &tcache_bin_info[binind]; + if (unlikely(tbin->ncached == tbin_info->ncached_max)) { + tcache_bin_flush_small(tsd, tcache, tbin, binind, + (tbin_info->ncached_max >> 1)); + } + assert(tbin->ncached < tbin_info->ncached_max); + tbin->ncached++; + *(tbin->avail - tbin->ncached) = ptr; + + tcache_event(tsd, tcache); +} + +JEMALLOC_ALWAYS_INLINE void +tcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind, + bool slow_path) { + tcache_bin_t *tbin; + tcache_bin_info_t *tbin_info; + + assert(tcache_salloc(tsd_tsdn(tsd), ptr) > SMALL_MAXCLASS); + assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= tcache_maxclass); + + if (slow_path && config_fill && unlikely(opt_junk_free)) { + large_dalloc_junk(ptr, sz_index2size(binind)); + } + + tbin = tcache_large_bin_get(tcache, binind); + tbin_info = &tcache_bin_info[binind]; + if (unlikely(tbin->ncached == tbin_info->ncached_max)) { + tcache_bin_flush_large(tsd, tbin, binind, + (tbin_info->ncached_max >> 1), tcache); + } + assert(tbin->ncached < tbin_info->ncached_max); + tbin->ncached++; + *(tbin->avail - tbin->ncached) = ptr; + + tcache_event(tsd, tcache); +} + +JEMALLOC_ALWAYS_INLINE tcache_t * +tcaches_get(tsd_t *tsd, unsigned ind) { + tcaches_t *elm = &tcaches[ind]; + if (unlikely(elm->tcache == NULL)) { + elm->tcache = tcache_create_explicit(tsd); + } + return elm->tcache; +} + +#endif /* JEMALLOC_INTERNAL_TCACHE_INLINES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_structs.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_structs.h new file mode 100644 index 0000000000..7eb516fb6b --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_structs.h @@ -0,0 +1,64 @@ +#ifndef JEMALLOC_INTERNAL_TCACHE_STRUCTS_H +#define JEMALLOC_INTERNAL_TCACHE_STRUCTS_H + +#include "jemalloc/internal/ql.h" +#include "jemalloc/internal/size_classes.h" +#include "jemalloc/internal/stats_tsd.h" +#include "jemalloc/internal/ticker.h" + +/* + * Read-only information associated with each element of tcache_t's tbins array + * is stored separately, mainly to reduce memory usage. + */ +struct tcache_bin_info_s { + unsigned ncached_max; /* Upper limit on ncached. */ +}; + +struct tcache_bin_s { + low_water_t low_water; /* Min # cached since last GC. */ + uint32_t ncached; /* # of cached objects. */ + /* + * ncached and stats are both modified frequently. Let's keep them + * close so that they have a higher chance of being on the same + * cacheline, thus less write-backs. + */ + tcache_bin_stats_t tstats; + /* + * To make use of adjacent cacheline prefetch, the items in the avail + * stack goes to higher address for newer allocations. avail points + * just above the available space, which means that + * avail[-ncached, ... -1] are available items and the lowest item will + * be allocated first. + */ + void **avail; /* Stack of available objects. */ +}; + +struct tcache_s { + /* Data accessed frequently first: prof, ticker and small bins. */ + uint64_t prof_accumbytes;/* Cleared after arena_prof_accum(). */ + ticker_t gc_ticker; /* Drives incremental GC. */ + /* + * The pointer stacks associated with tbins follow as a contiguous + * array. During tcache initialization, the avail pointer in each + * element of tbins is initialized to point to the proper offset within + * this array. + */ + tcache_bin_t tbins_small[NBINS]; + /* Data accessed less often below. */ + ql_elm(tcache_t) link; /* Used for aggregating stats. */ + arena_t *arena; /* Associated arena. */ + szind_t next_gc_bin; /* Next bin to GC. */ + /* For small bins, fill (ncached_max >> lg_fill_div). */ + uint8_t lg_fill_div[NBINS]; + tcache_bin_t tbins_large[NSIZES-NBINS]; +}; + +/* Linkage for list of available (previously used) explicit tcache IDs. */ +struct tcaches_s { + union { + tcache_t *tcache; + tcaches_t *next; + }; +}; + +#endif /* JEMALLOC_INTERNAL_TCACHE_STRUCTS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_types.h new file mode 100644 index 0000000000..1155d62cb4 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tcache_types.h @@ -0,0 +1,61 @@ +#ifndef JEMALLOC_INTERNAL_TCACHE_TYPES_H +#define JEMALLOC_INTERNAL_TCACHE_TYPES_H + +#include "jemalloc/internal/size_classes.h" + +typedef struct tcache_bin_info_s tcache_bin_info_t; +typedef struct tcache_bin_s tcache_bin_t; +typedef struct tcache_s tcache_t; +typedef struct tcaches_s tcaches_t; + +/* ncached is cast to this type for comparison. */ +typedef int32_t low_water_t; + +/* + * tcache pointers close to NULL are used to encode state information that is + * used for two purposes: preventing thread caching on a per thread basis and + * cleaning up during thread shutdown. + */ +#define TCACHE_STATE_DISABLED ((tcache_t *)(uintptr_t)1) +#define TCACHE_STATE_REINCARNATED ((tcache_t *)(uintptr_t)2) +#define TCACHE_STATE_PURGATORY ((tcache_t *)(uintptr_t)3) +#define TCACHE_STATE_MAX TCACHE_STATE_PURGATORY + +/* + * Absolute minimum number of cache slots for each small bin. + */ +#define TCACHE_NSLOTS_SMALL_MIN 20 + +/* + * Absolute maximum number of cache slots for each small bin in the thread + * cache. This is an additional constraint beyond that imposed as: twice the + * number of regions per slab for this size class. + * + * This constant must be an even number. + */ +#define TCACHE_NSLOTS_SMALL_MAX 200 + +/* Number of cache slots for large size classes. */ +#define TCACHE_NSLOTS_LARGE 20 + +/* (1U << opt_lg_tcache_max) is used to compute tcache_maxclass. */ +#define LG_TCACHE_MAXCLASS_DEFAULT 15 + +/* + * TCACHE_GC_SWEEP is the approximate number of allocation events between + * full GC sweeps. Integer rounding may cause the actual number to be + * slightly higher, since GC is performed incrementally. + */ +#define TCACHE_GC_SWEEP 8192 + +/* Number of tcache allocation/deallocation events between incremental GCs. */ +#define TCACHE_GC_INCR \ + ((TCACHE_GC_SWEEP / NBINS) + ((TCACHE_GC_SWEEP / NBINS == 0) ? 0 : 1)) + +/* Used in TSD static initializer only. Real init in tcache_data_init(). */ +#define TCACHE_ZERO_INITIALIZER {0} + +/* Used in TSD static initializer only. Will be initialized to opt_tcache. */ +#define TCACHE_ENABLED_ZERO_INITIALIZER false + +#endif /* JEMALLOC_INTERNAL_TCACHE_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/ticker.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/ticker.h new file mode 100644 index 0000000000..572b96459c --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/ticker.h @@ -0,0 +1,50 @@ +#ifndef JEMALLOC_INTERNAL_TICKER_H +#define JEMALLOC_INTERNAL_TICKER_H + +#include "jemalloc/internal/util.h" + +/** + * A ticker makes it easy to count-down events until some limit. You + * ticker_init the ticker to trigger every nticks events. You then notify it + * that an event has occurred with calls to ticker_tick (or that nticks events + * have occurred with a call to ticker_ticks), which will return true (and reset + * the counter) if the countdown hit zero. + */ + +typedef struct { + int32_t tick; + int32_t nticks; +} ticker_t; + +static inline void +ticker_init(ticker_t *ticker, int32_t nticks) { + ticker->tick = nticks; + ticker->nticks = nticks; +} + +static inline void +ticker_copy(ticker_t *ticker, const ticker_t *other) { + *ticker = *other; +} + +static inline int32_t +ticker_read(const ticker_t *ticker) { + return ticker->tick; +} + +static inline bool +ticker_ticks(ticker_t *ticker, int32_t nticks) { + if (unlikely(ticker->tick < nticks)) { + ticker->tick = ticker->nticks; + return true; + } + ticker->tick -= nticks; + return(false); +} + +static inline bool +ticker_tick(ticker_t *ticker) { + return ticker_ticks(ticker, 1); +} + +#endif /* JEMALLOC_INTERNAL_TICKER_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_generic.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_generic.h new file mode 100644 index 0000000000..1e52ef767f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_generic.h @@ -0,0 +1,157 @@ +#ifdef JEMALLOC_INTERNAL_TSD_GENERIC_H +#error This file should be included only once, by tsd.h. +#endif +#define JEMALLOC_INTERNAL_TSD_GENERIC_H + +typedef struct tsd_init_block_s tsd_init_block_t; +struct tsd_init_block_s { + ql_elm(tsd_init_block_t) link; + pthread_t thread; + void *data; +}; + +/* Defined in tsd.c, to allow the mutex headers to have tsd dependencies. */ +typedef struct tsd_init_head_s tsd_init_head_t; + +typedef struct { + bool initialized; + tsd_t val; +} tsd_wrapper_t; + +void *tsd_init_check_recursion(tsd_init_head_t *head, + tsd_init_block_t *block); +void tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block); + +extern pthread_key_t tsd_tsd; +extern tsd_init_head_t tsd_init_head; +extern tsd_wrapper_t tsd_boot_wrapper; +extern bool tsd_booted; + +/* Initialization/cleanup. */ +JEMALLOC_ALWAYS_INLINE void +tsd_cleanup_wrapper(void *arg) { + tsd_wrapper_t *wrapper = (tsd_wrapper_t *)arg; + + if (wrapper->initialized) { + wrapper->initialized = false; + tsd_cleanup(&wrapper->val); + if (wrapper->initialized) { + /* Trigger another cleanup round. */ + if (pthread_setspecific(tsd_tsd, (void *)wrapper) != 0) + { + malloc_write("<jemalloc>: Error setting TSD\n"); + if (opt_abort) { + abort(); + } + } + return; + } + } + malloc_tsd_dalloc(wrapper); +} + +JEMALLOC_ALWAYS_INLINE void +tsd_wrapper_set(tsd_wrapper_t *wrapper) { + if (pthread_setspecific(tsd_tsd, (void *)wrapper) != 0) { + malloc_write("<jemalloc>: Error setting TSD\n"); + abort(); + } +} + +JEMALLOC_ALWAYS_INLINE tsd_wrapper_t * +tsd_wrapper_get(bool init) { + tsd_wrapper_t *wrapper = (tsd_wrapper_t *)pthread_getspecific(tsd_tsd); + + if (init && unlikely(wrapper == NULL)) { + tsd_init_block_t block; + wrapper = (tsd_wrapper_t *) + tsd_init_check_recursion(&tsd_init_head, &block); + if (wrapper) { + return wrapper; + } + wrapper = (tsd_wrapper_t *) + malloc_tsd_malloc(sizeof(tsd_wrapper_t)); + block.data = (void *)wrapper; + if (wrapper == NULL) { + malloc_write("<jemalloc>: Error allocating TSD\n"); + abort(); + } else { + wrapper->initialized = false; + tsd_t initializer = TSD_INITIALIZER; + wrapper->val = initializer; + } + tsd_wrapper_set(wrapper); + tsd_init_finish(&tsd_init_head, &block); + } + return wrapper; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_boot0(void) { + if (pthread_key_create(&tsd_tsd, tsd_cleanup_wrapper) != 0) { + return true; + } + tsd_wrapper_set(&tsd_boot_wrapper); + tsd_booted = true; + return false; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_boot1(void) { + tsd_wrapper_t *wrapper; + wrapper = (tsd_wrapper_t *)malloc_tsd_malloc(sizeof(tsd_wrapper_t)); + if (wrapper == NULL) { + malloc_write("<jemalloc>: Error allocating TSD\n"); + abort(); + } + tsd_boot_wrapper.initialized = false; + tsd_cleanup(&tsd_boot_wrapper.val); + wrapper->initialized = false; + tsd_t initializer = TSD_INITIALIZER; + wrapper->val = initializer; + tsd_wrapper_set(wrapper); +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_boot(void) { + if (tsd_boot0()) { + return true; + } + tsd_boot1(); + return false; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_booted_get(void) { + return tsd_booted; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_get_allocates(void) { + return true; +} + +/* Get/set. */ +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_get(bool init) { + tsd_wrapper_t *wrapper; + + assert(tsd_booted); + wrapper = tsd_wrapper_get(init); + if (tsd_get_allocates() && !init && wrapper == NULL) { + return NULL; + } + return &wrapper->val; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_set(tsd_t *val) { + tsd_wrapper_t *wrapper; + + assert(tsd_booted); + wrapper = tsd_wrapper_get(true); + if (likely(&wrapper->val != val)) { + wrapper->val = *(val); + } + wrapper->initialized = true; +} diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h new file mode 100644 index 0000000000..beb467a67e --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_malloc_thread_cleanup.h @@ -0,0 +1,60 @@ +#ifdef JEMALLOC_INTERNAL_TSD_MALLOC_THREAD_CLEANUP_H +#error This file should be included only once, by tsd.h. +#endif +#define JEMALLOC_INTERNAL_TSD_MALLOC_THREAD_CLEANUP_H + +extern __thread tsd_t tsd_tls; +extern __thread bool tsd_initialized; +extern bool tsd_booted; + +/* Initialization/cleanup. */ +JEMALLOC_ALWAYS_INLINE bool +tsd_cleanup_wrapper(void) { + if (tsd_initialized) { + tsd_initialized = false; + tsd_cleanup(&tsd_tls); + } + return tsd_initialized; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_boot0(void) { + malloc_tsd_cleanup_register(&tsd_cleanup_wrapper); + tsd_booted = true; + return false; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_boot1(void) { + /* Do nothing. */ +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_boot(void) { + return tsd_boot0(); +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_booted_get(void) { + return tsd_booted; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_get_allocates(void) { + return false; +} + +/* Get/set. */ +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_get(bool init) { + assert(tsd_booted); + return &tsd_tls; +} +JEMALLOC_ALWAYS_INLINE void +tsd_set(tsd_t *val) { + assert(tsd_booted); + if (likely(&tsd_tls != val)) { + tsd_tls = (*val); + } + tsd_initialized = true; +} diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_tls.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_tls.h new file mode 100644 index 0000000000..757aaa0eef --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_tls.h @@ -0,0 +1,59 @@ +#ifdef JEMALLOC_INTERNAL_TSD_TLS_H +#error This file should be included only once, by tsd.h. +#endif +#define JEMALLOC_INTERNAL_TSD_TLS_H + +extern __thread tsd_t tsd_tls; +extern pthread_key_t tsd_tsd; +extern bool tsd_booted; + +/* Initialization/cleanup. */ +JEMALLOC_ALWAYS_INLINE bool +tsd_boot0(void) { + if (pthread_key_create(&tsd_tsd, &tsd_cleanup) != 0) { + return true; + } + tsd_booted = true; + return false; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_boot1(void) { + /* Do nothing. */ +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_boot(void) { + return tsd_boot0(); +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_booted_get(void) { + return tsd_booted; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_get_allocates(void) { + return false; +} + +/* Get/set. */ +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_get(bool init) { + assert(tsd_booted); + return &tsd_tls; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_set(tsd_t *val) { + assert(tsd_booted); + if (likely(&tsd_tls != val)) { + tsd_tls = (*val); + } + if (pthread_setspecific(tsd_tsd, (void *)(&tsd_tls)) != 0) { + malloc_write("<jemalloc>: Error setting tsd.\n"); + if (opt_abort) { + abort(); + } + } +} diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_types.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_types.h new file mode 100644 index 0000000000..6200af61f3 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_types.h @@ -0,0 +1,10 @@ +#ifndef JEMALLOC_INTERNAL_TSD_TYPES_H +#define JEMALLOC_INTERNAL_TSD_TYPES_H + +#define MALLOC_TSD_CLEANUPS_MAX 2 + +typedef struct tsd_s tsd_t; +typedef struct tsdn_s tsdn_t; +typedef bool (*malloc_tsd_cleanup_t)(void); + +#endif /* JEMALLOC_INTERNAL_TSD_TYPES_H */ diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_win.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_win.h new file mode 100644 index 0000000000..cf30d18e3c --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/tsd_win.h @@ -0,0 +1,139 @@ +#ifdef JEMALLOC_INTERNAL_TSD_WIN_H +#error This file should be included only once, by tsd.h. +#endif +#define JEMALLOC_INTERNAL_TSD_WIN_H + +typedef struct { + bool initialized; + tsd_t val; +} tsd_wrapper_t; + +extern DWORD tsd_tsd; +extern tsd_wrapper_t tsd_boot_wrapper; +extern bool tsd_booted; + +/* Initialization/cleanup. */ +JEMALLOC_ALWAYS_INLINE bool +tsd_cleanup_wrapper(void) { + DWORD error = GetLastError(); + tsd_wrapper_t *wrapper = (tsd_wrapper_t *)TlsGetValue(tsd_tsd); + SetLastError(error); + + if (wrapper == NULL) { + return false; + } + + if (wrapper->initialized) { + wrapper->initialized = false; + tsd_cleanup(&wrapper->val); + if (wrapper->initialized) { + /* Trigger another cleanup round. */ + return true; + } + } + malloc_tsd_dalloc(wrapper); + return false; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_wrapper_set(tsd_wrapper_t *wrapper) { + if (!TlsSetValue(tsd_tsd, (void *)wrapper)) { + malloc_write("<jemalloc>: Error setting TSD\n"); + abort(); + } +} + +JEMALLOC_ALWAYS_INLINE tsd_wrapper_t * +tsd_wrapper_get(bool init) { + DWORD error = GetLastError(); + tsd_wrapper_t *wrapper = (tsd_wrapper_t *) TlsGetValue(tsd_tsd); + SetLastError(error); + + if (init && unlikely(wrapper == NULL)) { + wrapper = (tsd_wrapper_t *) + malloc_tsd_malloc(sizeof(tsd_wrapper_t)); + if (wrapper == NULL) { + malloc_write("<jemalloc>: Error allocating TSD\n"); + abort(); + } else { + wrapper->initialized = false; + /* MSVC is finicky about aggregate initialization. */ + tsd_t tsd_initializer = TSD_INITIALIZER; + wrapper->val = tsd_initializer; + } + tsd_wrapper_set(wrapper); + } + return wrapper; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_boot0(void) { + tsd_tsd = TlsAlloc(); + if (tsd_tsd == TLS_OUT_OF_INDEXES) { + return true; + } + malloc_tsd_cleanup_register(&tsd_cleanup_wrapper); + tsd_wrapper_set(&tsd_boot_wrapper); + tsd_booted = true; + return false; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_boot1(void) { + tsd_wrapper_t *wrapper; + wrapper = (tsd_wrapper_t *) + malloc_tsd_malloc(sizeof(tsd_wrapper_t)); + if (wrapper == NULL) { + malloc_write("<jemalloc>: Error allocating TSD\n"); + abort(); + } + tsd_boot_wrapper.initialized = false; + tsd_cleanup(&tsd_boot_wrapper.val); + wrapper->initialized = false; + tsd_t initializer = TSD_INITIALIZER; + wrapper->val = initializer; + tsd_wrapper_set(wrapper); +} +JEMALLOC_ALWAYS_INLINE bool +tsd_boot(void) { + if (tsd_boot0()) { + return true; + } + tsd_boot1(); + return false; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_booted_get(void) { + return tsd_booted; +} + +JEMALLOC_ALWAYS_INLINE bool +tsd_get_allocates(void) { + return true; +} + +/* Get/set. */ +JEMALLOC_ALWAYS_INLINE tsd_t * +tsd_get(bool init) { + tsd_wrapper_t *wrapper; + + assert(tsd_booted); + wrapper = tsd_wrapper_get(init); + if (tsd_get_allocates() && !init && wrapper == NULL) { + return NULL; + } + return &wrapper->val; +} + +JEMALLOC_ALWAYS_INLINE void +tsd_set(tsd_t *val) { + tsd_wrapper_t *wrapper; + + assert(tsd_booted); + wrapper = tsd_wrapper_get(true); + if (likely(&wrapper->val != val)) { + wrapper->val = *(val); + } + wrapper->initialized = true; +} diff --git a/modules/worldengine/deps/jemalloc/include/jemalloc/internal/witness.h b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/witness.h new file mode 100644 index 0000000000..33be666107 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/jemalloc/internal/witness.h @@ -0,0 +1,346 @@ +#ifndef JEMALLOC_INTERNAL_WITNESS_H +#define JEMALLOC_INTERNAL_WITNESS_H + +#include "jemalloc/internal/ql.h" + +/******************************************************************************/ +/* LOCK RANKS */ +/******************************************************************************/ + +/* + * Witnesses with rank WITNESS_RANK_OMIT are completely ignored by the witness + * machinery. + */ + +#define WITNESS_RANK_OMIT 0U + +#define WITNESS_RANK_MIN 1U + +#define WITNESS_RANK_INIT 1U +#define WITNESS_RANK_CTL 1U +#define WITNESS_RANK_TCACHES 2U +#define WITNESS_RANK_ARENAS 3U + +#define WITNESS_RANK_BACKGROUND_THREAD_GLOBAL 4U + +#define WITNESS_RANK_PROF_DUMP 5U +#define WITNESS_RANK_PROF_BT2GCTX 6U +#define WITNESS_RANK_PROF_TDATAS 7U +#define WITNESS_RANK_PROF_TDATA 8U +#define WITNESS_RANK_PROF_GCTX 9U + +#define WITNESS_RANK_BACKGROUND_THREAD 10U + +/* + * Used as an argument to witness_assert_depth_to_rank() in order to validate + * depth excluding non-core locks with lower ranks. Since the rank argument to + * witness_assert_depth_to_rank() is inclusive rather than exclusive, this + * definition can have the same value as the minimally ranked core lock. + */ +#define WITNESS_RANK_CORE 11U + +#define WITNESS_RANK_DECAY 11U +#define WITNESS_RANK_TCACHE_QL 12U +#define WITNESS_RANK_EXTENT_GROW 13U +#define WITNESS_RANK_EXTENTS 14U +#define WITNESS_RANK_EXTENT_AVAIL 15U + +#define WITNESS_RANK_EXTENT_POOL 16U +#define WITNESS_RANK_RTREE 17U +#define WITNESS_RANK_BASE 18U +#define WITNESS_RANK_ARENA_LARGE 19U + +#define WITNESS_RANK_LEAF 0xffffffffU +#define WITNESS_RANK_ARENA_BIN WITNESS_RANK_LEAF +#define WITNESS_RANK_ARENA_STATS WITNESS_RANK_LEAF +#define WITNESS_RANK_DSS WITNESS_RANK_LEAF +#define WITNESS_RANK_PROF_ACTIVE WITNESS_RANK_LEAF +#define WITNESS_RANK_PROF_ACCUM WITNESS_RANK_LEAF +#define WITNESS_RANK_PROF_DUMP_SEQ WITNESS_RANK_LEAF +#define WITNESS_RANK_PROF_GDUMP WITNESS_RANK_LEAF +#define WITNESS_RANK_PROF_NEXT_THR_UID WITNESS_RANK_LEAF +#define WITNESS_RANK_PROF_THREAD_ACTIVE_INIT WITNESS_RANK_LEAF + +/******************************************************************************/ +/* PER-WITNESS DATA */ +/******************************************************************************/ +#if defined(JEMALLOC_DEBUG) +# define WITNESS_INITIALIZER(name, rank) {name, rank, NULL, NULL, {NULL, NULL}} +#else +# define WITNESS_INITIALIZER(name, rank) +#endif + +typedef struct witness_s witness_t; +typedef unsigned witness_rank_t; +typedef ql_head(witness_t) witness_list_t; +typedef int witness_comp_t (const witness_t *, void *, const witness_t *, + void *); + +struct witness_s { + /* Name, used for printing lock order reversal messages. */ + const char *name; + + /* + * Witness rank, where 0 is lowest and UINT_MAX is highest. Witnesses + * must be acquired in order of increasing rank. + */ + witness_rank_t rank; + + /* + * If two witnesses are of equal rank and they have the samp comp + * function pointer, it is called as a last attempt to differentiate + * between witnesses of equal rank. + */ + witness_comp_t *comp; + + /* Opaque data, passed to comp(). */ + void *opaque; + + /* Linkage for thread's currently owned locks. */ + ql_elm(witness_t) link; +}; + +/******************************************************************************/ +/* PER-THREAD DATA */ +/******************************************************************************/ +typedef struct witness_tsd_s witness_tsd_t; +struct witness_tsd_s { + witness_list_t witnesses; + bool forking; +}; + +#define WITNESS_TSD_INITIALIZER { ql_head_initializer(witnesses), false } +#define WITNESS_TSDN_NULL ((witness_tsdn_t *)0) + +/******************************************************************************/ +/* (PER-THREAD) NULLABILITY HELPERS */ +/******************************************************************************/ +typedef struct witness_tsdn_s witness_tsdn_t; +struct witness_tsdn_s { + witness_tsd_t witness_tsd; +}; + +JEMALLOC_ALWAYS_INLINE witness_tsdn_t * +witness_tsd_tsdn(witness_tsd_t *witness_tsd) { + return (witness_tsdn_t *)witness_tsd; +} + +JEMALLOC_ALWAYS_INLINE bool +witness_tsdn_null(witness_tsdn_t *witness_tsdn) { + return witness_tsdn == NULL; +} + +JEMALLOC_ALWAYS_INLINE witness_tsd_t * +witness_tsdn_tsd(witness_tsdn_t *witness_tsdn) { + assert(!witness_tsdn_null(witness_tsdn)); + return &witness_tsdn->witness_tsd; +} + +/******************************************************************************/ +/* API */ +/******************************************************************************/ +void witness_init(witness_t *witness, const char *name, witness_rank_t rank, + witness_comp_t *comp, void *opaque); + +typedef void (witness_lock_error_t)(const witness_list_t *, const witness_t *); +extern witness_lock_error_t *JET_MUTABLE witness_lock_error; + +typedef void (witness_owner_error_t)(const witness_t *); +extern witness_owner_error_t *JET_MUTABLE witness_owner_error; + +typedef void (witness_not_owner_error_t)(const witness_t *); +extern witness_not_owner_error_t *JET_MUTABLE witness_not_owner_error; + +typedef void (witness_depth_error_t)(const witness_list_t *, + witness_rank_t rank_inclusive, unsigned depth); +extern witness_depth_error_t *JET_MUTABLE witness_depth_error; + +void witnesses_cleanup(witness_tsd_t *witness_tsd); +void witness_prefork(witness_tsd_t *witness_tsd); +void witness_postfork_parent(witness_tsd_t *witness_tsd); +void witness_postfork_child(witness_tsd_t *witness_tsd); + +/* Helper, not intended for direct use. */ +static inline bool +witness_owner(witness_tsd_t *witness_tsd, const witness_t *witness) { + witness_list_t *witnesses; + witness_t *w; + + cassert(config_debug); + + witnesses = &witness_tsd->witnesses; + ql_foreach(w, witnesses, link) { + if (w == witness) { + return true; + } + } + + return false; +} + +static inline void +witness_assert_owner(witness_tsdn_t *witness_tsdn, const witness_t *witness) { + witness_tsd_t *witness_tsd; + + if (!config_debug) { + return; + } + + if (witness_tsdn_null(witness_tsdn)) { + return; + } + witness_tsd = witness_tsdn_tsd(witness_tsdn); + if (witness->rank == WITNESS_RANK_OMIT) { + return; + } + + if (witness_owner(witness_tsd, witness)) { + return; + } + witness_owner_error(witness); +} + +static inline void +witness_assert_not_owner(witness_tsdn_t *witness_tsdn, + const witness_t *witness) { + witness_tsd_t *witness_tsd; + witness_list_t *witnesses; + witness_t *w; + + if (!config_debug) { + return; + } + + if (witness_tsdn_null(witness_tsdn)) { + return; + } + witness_tsd = witness_tsdn_tsd(witness_tsdn); + if (witness->rank == WITNESS_RANK_OMIT) { + return; + } + + witnesses = &witness_tsd->witnesses; + ql_foreach(w, witnesses, link) { + if (w == witness) { + witness_not_owner_error(witness); + } + } +} + +static inline void +witness_assert_depth_to_rank(witness_tsdn_t *witness_tsdn, + witness_rank_t rank_inclusive, unsigned depth) { + witness_tsd_t *witness_tsd; + unsigned d; + witness_list_t *witnesses; + witness_t *w; + + if (!config_debug) { + return; + } + + if (witness_tsdn_null(witness_tsdn)) { + return; + } + witness_tsd = witness_tsdn_tsd(witness_tsdn); + + d = 0; + witnesses = &witness_tsd->witnesses; + w = ql_last(witnesses, link); + if (w != NULL) { + ql_reverse_foreach(w, witnesses, link) { + if (w->rank < rank_inclusive) { + break; + } + d++; + } + } + if (d != depth) { + witness_depth_error(witnesses, rank_inclusive, depth); + } +} + +static inline void +witness_assert_depth(witness_tsdn_t *witness_tsdn, unsigned depth) { + witness_assert_depth_to_rank(witness_tsdn, WITNESS_RANK_MIN, depth); +} + +static inline void +witness_assert_lockless(witness_tsdn_t *witness_tsdn) { + witness_assert_depth(witness_tsdn, 0); +} + +static inline void +witness_lock(witness_tsdn_t *witness_tsdn, witness_t *witness) { + witness_tsd_t *witness_tsd; + witness_list_t *witnesses; + witness_t *w; + + if (!config_debug) { + return; + } + + if (witness_tsdn_null(witness_tsdn)) { + return; + } + witness_tsd = witness_tsdn_tsd(witness_tsdn); + if (witness->rank == WITNESS_RANK_OMIT) { + return; + } + + witness_assert_not_owner(witness_tsdn, witness); + + witnesses = &witness_tsd->witnesses; + w = ql_last(witnesses, link); + if (w == NULL) { + /* No other locks; do nothing. */ + } else if (witness_tsd->forking && w->rank <= witness->rank) { + /* Forking, and relaxed ranking satisfied. */ + } else if (w->rank > witness->rank) { + /* Not forking, rank order reversal. */ + witness_lock_error(witnesses, witness); + } else if (w->rank == witness->rank && (w->comp == NULL || w->comp != + witness->comp || w->comp(w, w->opaque, witness, witness->opaque) > + 0)) { + /* + * Missing/incompatible comparison function, or comparison + * function indicates rank order reversal. + */ + witness_lock_error(witnesses, witness); + } + + ql_elm_new(witness, link); + ql_tail_insert(witnesses, witness, link); +} + +static inline void +witness_unlock(witness_tsdn_t *witness_tsdn, witness_t *witness) { + witness_tsd_t *witness_tsd; + witness_list_t *witnesses; + + if (!config_debug) { + return; + } + + if (witness_tsdn_null(witness_tsdn)) { + return; + } + witness_tsd = witness_tsdn_tsd(witness_tsdn); + if (witness->rank == WITNESS_RANK_OMIT) { + return; + } + + /* + * Check whether owner before removal, rather than relying on + * witness_assert_owner() to abort, so that unit tests can test this + * function's failure mode without causing undefined behavior. + */ + if (witness_owner(witness_tsd, witness)) { + witnesses = &witness_tsd->witnesses; + ql_remove(witnesses, witness, link); + } else { + witness_assert_owner(witness_tsdn, witness); + } +} + +#endif /* JEMALLOC_INTERNAL_WITNESS_H */ diff --git a/modules/worldengine/deps/jemalloc/include/msvc_compat/C99/stdbool.h b/modules/worldengine/deps/jemalloc/include/msvc_compat/C99/stdbool.h new file mode 100644 index 0000000000..d92160ebc7 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/msvc_compat/C99/stdbool.h @@ -0,0 +1,20 @@ +#ifndef stdbool_h +#define stdbool_h + +#include <wtypes.h> + +/* MSVC doesn't define _Bool or bool in C, but does have BOOL */ +/* Note this doesn't pass autoconf's test because (bool) 0.5 != true */ +/* Clang-cl uses MSVC headers, so needs msvc_compat, but has _Bool as + * a built-in type. */ +#ifndef __clang__ +typedef BOOL _Bool; +#endif + +#define bool _Bool +#define true 1 +#define false 0 + +#define __bool_true_false_are_defined 1 + +#endif /* stdbool_h */ diff --git a/modules/worldengine/deps/jemalloc/include/msvc_compat/C99/stdint.h b/modules/worldengine/deps/jemalloc/include/msvc_compat/C99/stdint.h new file mode 100644 index 0000000000..d02608a597 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/msvc_compat/C99/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include <wchar.h> +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/modules/worldengine/deps/jemalloc/include/msvc_compat/windows_extra.h b/modules/worldengine/deps/jemalloc/include/msvc_compat/windows_extra.h new file mode 100644 index 0000000000..a6ebb9306f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/include/msvc_compat/windows_extra.h @@ -0,0 +1,6 @@ +#ifndef MSVC_COMPAT_WINDOWS_EXTRA_H +#define MSVC_COMPAT_WINDOWS_EXTRA_H + +#include <errno.h> + +#endif /* MSVC_COMPAT_WINDOWS_EXTRA_H */ diff --git a/modules/worldengine/deps/jemalloc/src/background_thread.c b/modules/worldengine/deps/jemalloc/src/background_thread.c new file mode 100644 index 0000000000..eb30eb5b42 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/background_thread.c @@ -0,0 +1,880 @@ +#define JEMALLOC_BACKGROUND_THREAD_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" + +/******************************************************************************/ +/* Data. */ + +/* This option should be opt-in only. */ +#define BACKGROUND_THREAD_DEFAULT false +/* Read-only after initialization. */ +bool opt_background_thread = BACKGROUND_THREAD_DEFAULT; + +/* Used for thread creation, termination and stats. */ +malloc_mutex_t background_thread_lock; +/* Indicates global state. Atomic because decay reads this w/o locking. */ +atomic_b_t background_thread_enabled_state; +size_t n_background_threads; +/* Thread info per-index. */ +background_thread_info_t *background_thread_info; + +/* False if no necessary runtime support. */ +bool can_enable_background_thread; + +/******************************************************************************/ + +#ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER +#include <dlfcn.h> + +static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, + void *(*)(void *), void *__restrict); +static pthread_once_t once_control = PTHREAD_ONCE_INIT; + +static void +pthread_create_wrapper_once(void) { +#ifdef JEMALLOC_LAZY_LOCK + isthreaded = true; +#endif +} + +int +pthread_create_wrapper(pthread_t *__restrict thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *__restrict arg) { + pthread_once(&once_control, pthread_create_wrapper_once); + + return pthread_create_fptr(thread, attr, start_routine, arg); +} +#endif /* JEMALLOC_PTHREAD_CREATE_WRAPPER */ + +#ifndef JEMALLOC_BACKGROUND_THREAD +#define NOT_REACHED { not_reached(); } +bool background_thread_create(tsd_t *tsd, unsigned arena_ind) NOT_REACHED +bool background_threads_enable(tsd_t *tsd) NOT_REACHED +bool background_threads_disable(tsd_t *tsd) NOT_REACHED +void background_thread_interval_check(tsdn_t *tsdn, arena_t *arena, + arena_decay_t *decay, size_t npages_new) NOT_REACHED +void background_thread_prefork0(tsdn_t *tsdn) NOT_REACHED +void background_thread_prefork1(tsdn_t *tsdn) NOT_REACHED +void background_thread_postfork_parent(tsdn_t *tsdn) NOT_REACHED +void background_thread_postfork_child(tsdn_t *tsdn) NOT_REACHED +bool background_thread_stats_read(tsdn_t *tsdn, + background_thread_stats_t *stats) NOT_REACHED +void background_thread_ctl_init(tsdn_t *tsdn) NOT_REACHED +#undef NOT_REACHED +#else + +static bool background_thread_enabled_at_fork; + +static void +background_thread_info_init(tsdn_t *tsdn, background_thread_info_t *info) { + background_thread_wakeup_time_set(tsdn, info, 0); + info->npages_to_purge_new = 0; + if (config_stats) { + info->tot_n_runs = 0; + nstime_init(&info->tot_sleep_time, 0); + } +} + +static inline bool +set_current_thread_affinity(UNUSED int cpu) { +#if defined(JEMALLOC_HAVE_SCHED_SETAFFINITY) + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + int ret = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); + + return (ret != 0); +#else + return false; +#endif +} + +/* Threshold for determining when to wake up the background thread. */ +#define BACKGROUND_THREAD_NPAGES_THRESHOLD UINT64_C(1024) +#define BILLION UINT64_C(1000000000) +/* Minimal sleep interval 100 ms. */ +#define BACKGROUND_THREAD_MIN_INTERVAL_NS (BILLION / 10) + +static inline size_t +decay_npurge_after_interval(arena_decay_t *decay, size_t interval) { + size_t i; + uint64_t sum = 0; + for (i = 0; i < interval; i++) { + sum += decay->backlog[i] * h_steps[i]; + } + for (; i < SMOOTHSTEP_NSTEPS; i++) { + sum += decay->backlog[i] * (h_steps[i] - h_steps[i - interval]); + } + + return (size_t)(sum >> SMOOTHSTEP_BFP); +} + +static uint64_t +arena_decay_compute_purge_interval_impl(tsdn_t *tsdn, arena_decay_t *decay, + extents_t *extents) { + if (malloc_mutex_trylock(tsdn, &decay->mtx)) { + /* Use minimal interval if decay is contended. */ + return BACKGROUND_THREAD_MIN_INTERVAL_NS; + } + + uint64_t interval; + ssize_t decay_time = atomic_load_zd(&decay->time_ms, ATOMIC_RELAXED); + if (decay_time <= 0) { + /* Purging is eagerly done or disabled currently. */ + interval = BACKGROUND_THREAD_INDEFINITE_SLEEP; + goto label_done; + } + + uint64_t decay_interval_ns = nstime_ns(&decay->interval); + assert(decay_interval_ns > 0); + size_t npages = extents_npages_get(extents); + if (npages == 0) { + unsigned i; + for (i = 0; i < SMOOTHSTEP_NSTEPS; i++) { + if (decay->backlog[i] > 0) { + break; + } + } + if (i == SMOOTHSTEP_NSTEPS) { + /* No dirty pages recorded. Sleep indefinitely. */ + interval = BACKGROUND_THREAD_INDEFINITE_SLEEP; + goto label_done; + } + } + if (npages <= BACKGROUND_THREAD_NPAGES_THRESHOLD) { + /* Use max interval. */ + interval = decay_interval_ns * SMOOTHSTEP_NSTEPS; + goto label_done; + } + + size_t lb = BACKGROUND_THREAD_MIN_INTERVAL_NS / decay_interval_ns; + size_t ub = SMOOTHSTEP_NSTEPS; + /* Minimal 2 intervals to ensure reaching next epoch deadline. */ + lb = (lb < 2) ? 2 : lb; + if ((decay_interval_ns * ub <= BACKGROUND_THREAD_MIN_INTERVAL_NS) || + (lb + 2 > ub)) { + interval = BACKGROUND_THREAD_MIN_INTERVAL_NS; + goto label_done; + } + + assert(lb + 2 <= ub); + size_t npurge_lb, npurge_ub; + npurge_lb = decay_npurge_after_interval(decay, lb); + if (npurge_lb > BACKGROUND_THREAD_NPAGES_THRESHOLD) { + interval = decay_interval_ns * lb; + goto label_done; + } + npurge_ub = decay_npurge_after_interval(decay, ub); + if (npurge_ub < BACKGROUND_THREAD_NPAGES_THRESHOLD) { + interval = decay_interval_ns * ub; + goto label_done; + } + + unsigned n_search = 0; + size_t target, npurge; + while ((npurge_lb + BACKGROUND_THREAD_NPAGES_THRESHOLD < npurge_ub) + && (lb + 2 < ub)) { + target = (lb + ub) / 2; + npurge = decay_npurge_after_interval(decay, target); + if (npurge > BACKGROUND_THREAD_NPAGES_THRESHOLD) { + ub = target; + npurge_ub = npurge; + } else { + lb = target; + npurge_lb = npurge; + } + assert(n_search++ < lg_floor(SMOOTHSTEP_NSTEPS) + 1); + } + interval = decay_interval_ns * (ub + lb) / 2; +label_done: + interval = (interval < BACKGROUND_THREAD_MIN_INTERVAL_NS) ? + BACKGROUND_THREAD_MIN_INTERVAL_NS : interval; + malloc_mutex_unlock(tsdn, &decay->mtx); + + return interval; +} + +/* Compute purge interval for background threads. */ +static uint64_t +arena_decay_compute_purge_interval(tsdn_t *tsdn, arena_t *arena) { + uint64_t i1, i2; + i1 = arena_decay_compute_purge_interval_impl(tsdn, &arena->decay_dirty, + &arena->extents_dirty); + if (i1 == BACKGROUND_THREAD_MIN_INTERVAL_NS) { + return i1; + } + i2 = arena_decay_compute_purge_interval_impl(tsdn, &arena->decay_muzzy, + &arena->extents_muzzy); + + return i1 < i2 ? i1 : i2; +} + +static void +background_thread_sleep(tsdn_t *tsdn, background_thread_info_t *info, + uint64_t interval) { + if (config_stats) { + info->tot_n_runs++; + } + info->npages_to_purge_new = 0; + + struct timeval tv; + /* Specific clock required by timedwait. */ + gettimeofday(&tv, NULL); + nstime_t before_sleep; + nstime_init2(&before_sleep, tv.tv_sec, tv.tv_usec * 1000); + + int ret; + if (interval == BACKGROUND_THREAD_INDEFINITE_SLEEP) { + assert(background_thread_indefinite_sleep(info)); + ret = pthread_cond_wait(&info->cond, &info->mtx.lock); + assert(ret == 0); + } else { + assert(interval >= BACKGROUND_THREAD_MIN_INTERVAL_NS && + interval <= BACKGROUND_THREAD_INDEFINITE_SLEEP); + /* We need malloc clock (can be different from tv). */ + nstime_t next_wakeup; + nstime_init(&next_wakeup, 0); + nstime_update(&next_wakeup); + nstime_iadd(&next_wakeup, interval); + assert(nstime_ns(&next_wakeup) < + BACKGROUND_THREAD_INDEFINITE_SLEEP); + background_thread_wakeup_time_set(tsdn, info, + nstime_ns(&next_wakeup)); + + nstime_t ts_wakeup; + nstime_copy(&ts_wakeup, &before_sleep); + nstime_iadd(&ts_wakeup, interval); + struct timespec ts; + ts.tv_sec = (size_t)nstime_sec(&ts_wakeup); + ts.tv_nsec = (size_t)nstime_nsec(&ts_wakeup); + + assert(!background_thread_indefinite_sleep(info)); + ret = pthread_cond_timedwait(&info->cond, &info->mtx.lock, &ts); + assert(ret == ETIMEDOUT || ret == 0); + background_thread_wakeup_time_set(tsdn, info, + BACKGROUND_THREAD_INDEFINITE_SLEEP); + } + if (config_stats) { + gettimeofday(&tv, NULL); + nstime_t after_sleep; + nstime_init2(&after_sleep, tv.tv_sec, tv.tv_usec * 1000); + if (nstime_compare(&after_sleep, &before_sleep) > 0) { + nstime_subtract(&after_sleep, &before_sleep); + nstime_add(&info->tot_sleep_time, &after_sleep); + } + } +} + +static bool +background_thread_pause_check(tsdn_t *tsdn, background_thread_info_t *info) { + if (unlikely(info->state == background_thread_paused)) { + malloc_mutex_unlock(tsdn, &info->mtx); + /* Wait on global lock to update status. */ + malloc_mutex_lock(tsdn, &background_thread_lock); + malloc_mutex_unlock(tsdn, &background_thread_lock); + malloc_mutex_lock(tsdn, &info->mtx); + return true; + } + + return false; +} + +static inline void +background_work_sleep_once(tsdn_t *tsdn, background_thread_info_t *info, unsigned ind) { + uint64_t min_interval = BACKGROUND_THREAD_INDEFINITE_SLEEP; + unsigned narenas = narenas_total_get(); + + for (unsigned i = ind; i < narenas; i += ncpus) { + arena_t *arena = arena_get(tsdn, i, false); + if (!arena) { + continue; + } + arena_decay(tsdn, arena, true, false); + if (min_interval == BACKGROUND_THREAD_MIN_INTERVAL_NS) { + /* Min interval will be used. */ + continue; + } + uint64_t interval = arena_decay_compute_purge_interval(tsdn, + arena); + assert(interval >= BACKGROUND_THREAD_MIN_INTERVAL_NS); + if (min_interval > interval) { + min_interval = interval; + } + } + background_thread_sleep(tsdn, info, min_interval); +} + +static bool +background_threads_disable_single(tsd_t *tsd, background_thread_info_t *info) { + if (info == &background_thread_info[0]) { + malloc_mutex_assert_owner(tsd_tsdn(tsd), + &background_thread_lock); + } else { + malloc_mutex_assert_not_owner(tsd_tsdn(tsd), + &background_thread_lock); + } + + pre_reentrancy(tsd, NULL); + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + bool has_thread; + assert(info->state != background_thread_paused); + if (info->state == background_thread_started) { + has_thread = true; + info->state = background_thread_stopped; + pthread_cond_signal(&info->cond); + } else { + has_thread = false; + } + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + + if (!has_thread) { + post_reentrancy(tsd); + return false; + } + void *ret; + if (pthread_join(info->thread, &ret)) { + post_reentrancy(tsd); + return true; + } + assert(ret == NULL); + n_background_threads--; + post_reentrancy(tsd); + + return false; +} + +static void *background_thread_entry(void *ind_arg); + +static int +background_thread_create_signals_masked(pthread_t *thread, + const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { + /* + * Mask signals during thread creation so that the thread inherits + * an empty signal set. + */ + sigset_t set; + sigfillset(&set); + sigset_t oldset; + int mask_err = pthread_sigmask(SIG_SETMASK, &set, &oldset); + if (mask_err != 0) { + return mask_err; + } + int create_err = pthread_create_wrapper(thread, attr, start_routine, + arg); + /* + * Restore the signal mask. Failure to restore the signal mask here + * changes program behavior. + */ + int restore_err = pthread_sigmask(SIG_SETMASK, &oldset, NULL); + if (restore_err != 0) { + malloc_printf("<jemalloc>: background thread creation " + "failed (%d), and signal mask restoration failed " + "(%d)\n", create_err, restore_err); + if (opt_abort) { + abort(); + } + } + return create_err; +} + +static void +check_background_thread_creation(tsd_t *tsd, unsigned *n_created, + bool *created_threads) { + if (likely(*n_created == n_background_threads)) { + return; + } + + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_info[0].mtx); +label_restart: + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock); + for (unsigned i = 1; i < ncpus; i++) { + if (created_threads[i]) { + continue; + } + background_thread_info_t *info = &background_thread_info[i]; + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + assert(info->state != background_thread_paused); + bool create = (info->state == background_thread_started); + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + if (!create) { + continue; + } + + /* + * To avoid deadlock with prefork handlers (which waits for the + * mutex held here), unlock before calling pthread_create(). + */ + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); + + pre_reentrancy(tsd, NULL); + int err = background_thread_create_signals_masked(&info->thread, + NULL, background_thread_entry, (void *)(uintptr_t)i); + post_reentrancy(tsd); + + if (err == 0) { + (*n_created)++; + created_threads[i] = true; + } else { + malloc_printf("<jemalloc>: background thread " + "creation failed (%d)\n", err); + if (opt_abort) { + abort(); + } + } + /* Restart since we unlocked. */ + goto label_restart; + } + malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_info[0].mtx); + malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock); +} + +static void +background_thread0_work(tsd_t *tsd) { + /* Thread0 is also responsible for launching / terminating threads. */ + VARIABLE_ARRAY(bool, created_threads, ncpus); + unsigned i; + for (i = 1; i < ncpus; i++) { + created_threads[i] = false; + } + /* Start working, and create more threads when asked. */ + unsigned n_created = 1; + while (background_thread_info[0].state != background_thread_stopped) { + if (background_thread_pause_check(tsd_tsdn(tsd), + &background_thread_info[0])) { + continue; + } + check_background_thread_creation(tsd, &n_created, + (bool *)&created_threads); + background_work_sleep_once(tsd_tsdn(tsd), + &background_thread_info[0], 0); + } + + /* + * Shut down other threads at exit. Note that the ctl thread is holding + * the global background_thread mutex (and is waiting) for us. + */ + assert(!background_thread_enabled()); + for (i = 1; i < ncpus; i++) { + background_thread_info_t *info = &background_thread_info[i]; + assert(info->state != background_thread_paused); + if (created_threads[i]) { + background_threads_disable_single(tsd, info); + } else { + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + /* Clear in case the thread wasn't created. */ + info->state = background_thread_stopped; + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + } + } + background_thread_info[0].state = background_thread_stopped; + assert(n_background_threads == 1); +} + +static void +background_work(tsd_t *tsd, unsigned ind) { + background_thread_info_t *info = &background_thread_info[ind]; + + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + background_thread_wakeup_time_set(tsd_tsdn(tsd), info, + BACKGROUND_THREAD_INDEFINITE_SLEEP); + if (ind == 0) { + background_thread0_work(tsd); + } else { + while (info->state != background_thread_stopped) { + if (background_thread_pause_check(tsd_tsdn(tsd), + info)) { + continue; + } + background_work_sleep_once(tsd_tsdn(tsd), info, ind); + } + } + assert(info->state == background_thread_stopped); + background_thread_wakeup_time_set(tsd_tsdn(tsd), info, 0); + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); +} + +static void * +background_thread_entry(void *ind_arg) { + unsigned thread_ind = (unsigned)(uintptr_t)ind_arg; + assert(thread_ind < ncpus); +#ifdef JEMALLOC_HAVE_PTHREAD_SETNAME_NP + pthread_setname_np(pthread_self(), "jemalloc_bg_thd"); +#endif + if (opt_percpu_arena != percpu_arena_disabled) { + set_current_thread_affinity((int)thread_ind); + } + /* + * Start periodic background work. We use internal tsd which avoids + * side effects, for example triggering new arena creation (which in + * turn triggers another background thread creation). + */ + background_work(tsd_internal_fetch(), thread_ind); + assert(pthread_equal(pthread_self(), + background_thread_info[thread_ind].thread)); + + return NULL; +} + +static void +background_thread_init(tsd_t *tsd, background_thread_info_t *info) { + malloc_mutex_assert_owner(tsd_tsdn(tsd), &background_thread_lock); + info->state = background_thread_started; + background_thread_info_init(tsd_tsdn(tsd), info); + n_background_threads++; +} + +/* Create a new background thread if needed. */ +bool +background_thread_create(tsd_t *tsd, unsigned arena_ind) { + assert(have_background_thread); + malloc_mutex_assert_owner(tsd_tsdn(tsd), &background_thread_lock); + + /* We create at most NCPUs threads. */ + size_t thread_ind = arena_ind % ncpus; + background_thread_info_t *info = &background_thread_info[thread_ind]; + + bool need_new_thread; + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + need_new_thread = background_thread_enabled() && + (info->state == background_thread_stopped); + if (need_new_thread) { + background_thread_init(tsd, info); + } + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + if (!need_new_thread) { + return false; + } + if (arena_ind != 0) { + /* Threads are created asynchronously by Thread 0. */ + background_thread_info_t *t0 = &background_thread_info[0]; + malloc_mutex_lock(tsd_tsdn(tsd), &t0->mtx); + assert(t0->state == background_thread_started); + pthread_cond_signal(&t0->cond); + malloc_mutex_unlock(tsd_tsdn(tsd), &t0->mtx); + + return false; + } + + pre_reentrancy(tsd, NULL); + /* + * To avoid complications (besides reentrancy), create internal + * background threads with the underlying pthread_create. + */ + int err = background_thread_create_signals_masked(&info->thread, NULL, + background_thread_entry, (void *)thread_ind); + post_reentrancy(tsd); + + if (err != 0) { + malloc_printf("<jemalloc>: arena 0 background thread creation " + "failed (%d)\n", err); + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + info->state = background_thread_stopped; + n_background_threads--; + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + + return true; + } + + return false; +} + +bool +background_threads_enable(tsd_t *tsd) { + assert(n_background_threads == 0); + assert(background_thread_enabled()); + malloc_mutex_assert_owner(tsd_tsdn(tsd), &background_thread_lock); + + VARIABLE_ARRAY(bool, marked, ncpus); + unsigned i, nmarked; + for (i = 0; i < ncpus; i++) { + marked[i] = false; + } + nmarked = 0; + /* Mark the threads we need to create for thread 0. */ + unsigned n = narenas_total_get(); + for (i = 1; i < n; i++) { + if (marked[i % ncpus] || + arena_get(tsd_tsdn(tsd), i, false) == NULL) { + continue; + } + background_thread_info_t *info = &background_thread_info[i]; + malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx); + assert(info->state == background_thread_stopped); + background_thread_init(tsd, info); + malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx); + marked[i % ncpus] = true; + if (++nmarked == ncpus) { + break; + } + } + + return background_thread_create(tsd, 0); +} + +bool +background_threads_disable(tsd_t *tsd) { + assert(!background_thread_enabled()); + malloc_mutex_assert_owner(tsd_tsdn(tsd), &background_thread_lock); + + /* Thread 0 will be responsible for terminating other threads. */ + if (background_threads_disable_single(tsd, + &background_thread_info[0])) { + return true; + } + assert(n_background_threads == 0); + + return false; +} + +/* Check if we need to signal the background thread early. */ +void +background_thread_interval_check(tsdn_t *tsdn, arena_t *arena, + arena_decay_t *decay, size_t npages_new) { + background_thread_info_t *info = arena_background_thread_info_get( + arena); + if (malloc_mutex_trylock(tsdn, &info->mtx)) { + /* + * Background thread may hold the mutex for a long period of + * time. We'd like to avoid the variance on application + * threads. So keep this non-blocking, and leave the work to a + * future epoch. + */ + return; + } + + if (info->state != background_thread_started) { + goto label_done; + } + if (malloc_mutex_trylock(tsdn, &decay->mtx)) { + goto label_done; + } + + ssize_t decay_time = atomic_load_zd(&decay->time_ms, ATOMIC_RELAXED); + if (decay_time <= 0) { + /* Purging is eagerly done or disabled currently. */ + goto label_done_unlock2; + } + uint64_t decay_interval_ns = nstime_ns(&decay->interval); + assert(decay_interval_ns > 0); + + nstime_t diff; + nstime_init(&diff, background_thread_wakeup_time_get(info)); + if (nstime_compare(&diff, &decay->epoch) <= 0) { + goto label_done_unlock2; + } + nstime_subtract(&diff, &decay->epoch); + if (nstime_ns(&diff) < BACKGROUND_THREAD_MIN_INTERVAL_NS) { + goto label_done_unlock2; + } + + if (npages_new > 0) { + size_t n_epoch = (size_t)(nstime_ns(&diff) / decay_interval_ns); + /* + * Compute how many new pages we would need to purge by the next + * wakeup, which is used to determine if we should signal the + * background thread. + */ + uint64_t npurge_new; + if (n_epoch >= SMOOTHSTEP_NSTEPS) { + npurge_new = npages_new; + } else { + uint64_t h_steps_max = h_steps[SMOOTHSTEP_NSTEPS - 1]; + assert(h_steps_max >= + h_steps[SMOOTHSTEP_NSTEPS - 1 - n_epoch]); + npurge_new = npages_new * (h_steps_max - + h_steps[SMOOTHSTEP_NSTEPS - 1 - n_epoch]); + npurge_new >>= SMOOTHSTEP_BFP; + } + info->npages_to_purge_new += npurge_new; + } + + bool should_signal; + if (info->npages_to_purge_new > BACKGROUND_THREAD_NPAGES_THRESHOLD) { + should_signal = true; + } else if (unlikely(background_thread_indefinite_sleep(info)) && + (extents_npages_get(&arena->extents_dirty) > 0 || + extents_npages_get(&arena->extents_muzzy) > 0 || + info->npages_to_purge_new > 0)) { + should_signal = true; + } else { + should_signal = false; + } + + if (should_signal) { + info->npages_to_purge_new = 0; + pthread_cond_signal(&info->cond); + } +label_done_unlock2: + malloc_mutex_unlock(tsdn, &decay->mtx); +label_done: + malloc_mutex_unlock(tsdn, &info->mtx); +} + +void +background_thread_prefork0(tsdn_t *tsdn) { + malloc_mutex_prefork(tsdn, &background_thread_lock); + background_thread_enabled_at_fork = background_thread_enabled(); +} + +void +background_thread_prefork1(tsdn_t *tsdn) { + for (unsigned i = 0; i < ncpus; i++) { + malloc_mutex_prefork(tsdn, &background_thread_info[i].mtx); + } +} + +void +background_thread_postfork_parent(tsdn_t *tsdn) { + for (unsigned i = 0; i < ncpus; i++) { + malloc_mutex_postfork_parent(tsdn, + &background_thread_info[i].mtx); + } + malloc_mutex_postfork_parent(tsdn, &background_thread_lock); +} + +void +background_thread_postfork_child(tsdn_t *tsdn) { + for (unsigned i = 0; i < ncpus; i++) { + malloc_mutex_postfork_child(tsdn, + &background_thread_info[i].mtx); + } + malloc_mutex_postfork_child(tsdn, &background_thread_lock); + if (!background_thread_enabled_at_fork) { + return; + } + + /* Clear background_thread state (reset to disabled for child). */ + malloc_mutex_lock(tsdn, &background_thread_lock); + n_background_threads = 0; + background_thread_enabled_set(tsdn, false); + for (unsigned i = 0; i < ncpus; i++) { + background_thread_info_t *info = &background_thread_info[i]; + malloc_mutex_lock(tsdn, &info->mtx); + info->state = background_thread_stopped; + int ret = pthread_cond_init(&info->cond, NULL); + assert(ret == 0); + background_thread_info_init(tsdn, info); + malloc_mutex_unlock(tsdn, &info->mtx); + } + malloc_mutex_unlock(tsdn, &background_thread_lock); +} + +bool +background_thread_stats_read(tsdn_t *tsdn, background_thread_stats_t *stats) { + assert(config_stats); + malloc_mutex_lock(tsdn, &background_thread_lock); + if (!background_thread_enabled()) { + malloc_mutex_unlock(tsdn, &background_thread_lock); + return true; + } + + stats->num_threads = n_background_threads; + uint64_t num_runs = 0; + nstime_init(&stats->run_interval, 0); + for (unsigned i = 0; i < ncpus; i++) { + background_thread_info_t *info = &background_thread_info[i]; + malloc_mutex_lock(tsdn, &info->mtx); + if (info->state != background_thread_stopped) { + num_runs += info->tot_n_runs; + nstime_add(&stats->run_interval, &info->tot_sleep_time); + } + malloc_mutex_unlock(tsdn, &info->mtx); + } + stats->num_runs = num_runs; + if (num_runs > 0) { + nstime_idivide(&stats->run_interval, num_runs); + } + malloc_mutex_unlock(tsdn, &background_thread_lock); + + return false; +} + +#undef BACKGROUND_THREAD_NPAGES_THRESHOLD +#undef BILLION +#undef BACKGROUND_THREAD_MIN_INTERVAL_NS + +/* + * When lazy lock is enabled, we need to make sure setting isthreaded before + * taking any background_thread locks. This is called early in ctl (instead of + * wait for the pthread_create calls to trigger) because the mutex is required + * before creating background threads. + */ +void +background_thread_ctl_init(tsdn_t *tsdn) { + malloc_mutex_assert_not_owner(tsdn, &background_thread_lock); +#ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER + pthread_once(&once_control, pthread_create_wrapper_once); +#endif +} + +#endif /* defined(JEMALLOC_BACKGROUND_THREAD) */ + +bool +background_thread_boot0(void) { + if (!have_background_thread && opt_background_thread) { + malloc_printf("<jemalloc>: option background_thread currently " + "supports pthread only\n"); + return true; + } + +#ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER + pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); + if (pthread_create_fptr == NULL) { + can_enable_background_thread = false; + if (config_lazy_lock || opt_background_thread) { + malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, " + "\"pthread_create\")\n"); + abort(); + } + } else { + can_enable_background_thread = true; + } +#endif + return false; +} + +bool +background_thread_boot1(tsdn_t *tsdn) { +#ifdef JEMALLOC_BACKGROUND_THREAD + assert(have_background_thread); + assert(narenas_total_get() > 0); + + background_thread_enabled_set(tsdn, opt_background_thread); + if (malloc_mutex_init(&background_thread_lock, + "background_thread_global", + WITNESS_RANK_BACKGROUND_THREAD_GLOBAL, + malloc_mutex_rank_exclusive)) { + return true; + } + if (opt_background_thread) { + background_thread_ctl_init(tsdn); + } + + background_thread_info = (background_thread_info_t *)base_alloc(tsdn, + b0get(), ncpus * sizeof(background_thread_info_t), CACHELINE); + if (background_thread_info == NULL) { + return true; + } + + for (unsigned i = 0; i < ncpus; i++) { + background_thread_info_t *info = &background_thread_info[i]; + /* Thread mutex is rank_inclusive because of thread0. */ + if (malloc_mutex_init(&info->mtx, "background_thread", + WITNESS_RANK_BACKGROUND_THREAD, + malloc_mutex_address_ordered)) { + return true; + } + if (pthread_cond_init(&info->cond, NULL)) { + return true; + } + malloc_mutex_lock(tsdn, &info->mtx); + info->state = background_thread_stopped; + background_thread_info_init(tsdn, info); + malloc_mutex_unlock(tsdn, &info->mtx); + } +#endif + + return false; +} diff --git a/modules/worldengine/deps/jemalloc/src/extent_dss.c b/modules/worldengine/deps/jemalloc/src/extent_dss.c new file mode 100644 index 0000000000..e72da95870 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/extent_dss.c @@ -0,0 +1,269 @@ +#define JEMALLOC_EXTENT_DSS_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/extent_dss.h" +#include "jemalloc/internal/spin.h" + +/******************************************************************************/ +/* Data. */ + +const char *opt_dss = DSS_DEFAULT; + +const char *dss_prec_names[] = { + "disabled", + "primary", + "secondary", + "N/A" +}; + +/* + * Current dss precedence default, used when creating new arenas. NB: This is + * stored as unsigned rather than dss_prec_t because in principle there's no + * guarantee that sizeof(dss_prec_t) is the same as sizeof(unsigned), and we use + * atomic operations to synchronize the setting. + */ +static atomic_u_t dss_prec_default = ATOMIC_INIT( + (unsigned)DSS_PREC_DEFAULT); + +/* Base address of the DSS. */ +static void *dss_base; +/* Atomic boolean indicating whether a thread is currently extending DSS. */ +static atomic_b_t dss_extending; +/* Atomic boolean indicating whether the DSS is exhausted. */ +static atomic_b_t dss_exhausted; +/* Atomic current upper limit on DSS addresses. */ +static atomic_p_t dss_max; + +/******************************************************************************/ + +static void * +extent_dss_sbrk(intptr_t increment) { +#ifdef JEMALLOC_DSS + return sbrk(increment); +#else + not_implemented(); + return NULL; +#endif +} + +dss_prec_t +extent_dss_prec_get(void) { + dss_prec_t ret; + + if (!have_dss) { + return dss_prec_disabled; + } + ret = (dss_prec_t)atomic_load_u(&dss_prec_default, ATOMIC_ACQUIRE); + return ret; +} + +bool +extent_dss_prec_set(dss_prec_t dss_prec) { + if (!have_dss) { + return (dss_prec != dss_prec_disabled); + } + atomic_store_u(&dss_prec_default, (unsigned)dss_prec, ATOMIC_RELEASE); + return false; +} + +static void +extent_dss_extending_start(void) { + spin_t spinner = SPIN_INITIALIZER; + while (true) { + bool expected = false; + if (atomic_compare_exchange_weak_b(&dss_extending, &expected, + true, ATOMIC_ACQ_REL, ATOMIC_RELAXED)) { + break; + } + spin_adaptive(&spinner); + } +} + +static void +extent_dss_extending_finish(void) { + assert(atomic_load_b(&dss_extending, ATOMIC_RELAXED)); + + atomic_store_b(&dss_extending, false, ATOMIC_RELEASE); +} + +static void * +extent_dss_max_update(void *new_addr) { + /* + * Get the current end of the DSS as max_cur and assure that dss_max is + * up to date. + */ + void *max_cur = extent_dss_sbrk(0); + if (max_cur == (void *)-1) { + return NULL; + } + atomic_store_p(&dss_max, max_cur, ATOMIC_RELEASE); + /* Fixed new_addr can only be supported if it is at the edge of DSS. */ + if (new_addr != NULL && max_cur != new_addr) { + return NULL; + } + return max_cur; +} + +void * +extent_alloc_dss(tsdn_t *tsdn, arena_t *arena, void *new_addr, size_t size, + size_t alignment, bool *zero, bool *commit) { + extent_t *gap; + + cassert(have_dss); + assert(size > 0); + assert(alignment > 0); + + /* + * sbrk() uses a signed increment argument, so take care not to + * interpret a large allocation request as a negative increment. + */ + if ((intptr_t)size < 0) { + return NULL; + } + + gap = extent_alloc(tsdn, arena); + if (gap == NULL) { + return NULL; + } + + extent_dss_extending_start(); + if (!atomic_load_b(&dss_exhausted, ATOMIC_ACQUIRE)) { + /* + * The loop is necessary to recover from races with other + * threads that are using the DSS for something other than + * malloc. + */ + while (true) { + void *max_cur = extent_dss_max_update(new_addr); + if (max_cur == NULL) { + goto label_oom; + } + + /* + * Compute how much page-aligned gap space (if any) is + * necessary to satisfy alignment. This space can be + * recycled for later use. + */ + void *gap_addr_page = (void *)(PAGE_CEILING( + (uintptr_t)max_cur)); + void *ret = (void *)ALIGNMENT_CEILING( + (uintptr_t)gap_addr_page, alignment); + size_t gap_size_page = (uintptr_t)ret - + (uintptr_t)gap_addr_page; + if (gap_size_page != 0) { + extent_init(gap, arena, gap_addr_page, + gap_size_page, false, NSIZES, + arena_extent_sn_next(arena), + extent_state_active, false, true); + } + /* + * Compute the address just past the end of the desired + * allocation space. + */ + void *dss_next = (void *)((uintptr_t)ret + size); + if ((uintptr_t)ret < (uintptr_t)max_cur || + (uintptr_t)dss_next < (uintptr_t)max_cur) { + goto label_oom; /* Wrap-around. */ + } + /* Compute the increment, including subpage bytes. */ + void *gap_addr_subpage = max_cur; + size_t gap_size_subpage = (uintptr_t)ret - + (uintptr_t)gap_addr_subpage; + intptr_t incr = gap_size_subpage + size; + + assert((uintptr_t)max_cur + incr == (uintptr_t)ret + + size); + + /* Try to allocate. */ + void *dss_prev = extent_dss_sbrk(incr); + if (dss_prev == max_cur) { + /* Success. */ + atomic_store_p(&dss_max, dss_next, + ATOMIC_RELEASE); + extent_dss_extending_finish(); + + if (gap_size_page != 0) { + extent_dalloc_gap(tsdn, arena, gap); + } else { + extent_dalloc(tsdn, arena, gap); + } + if (!*commit) { + *commit = pages_decommit(ret, size); + } + if (*zero && *commit) { + extent_hooks_t *extent_hooks = + EXTENT_HOOKS_INITIALIZER; + extent_t extent; + + extent_init(&extent, arena, ret, size, + size, false, NSIZES, + extent_state_active, false, true); + if (extent_purge_forced_wrapper(tsdn, + arena, &extent_hooks, &extent, 0, + size)) { + memset(ret, 0, size); + } + } + return ret; + } + /* + * Failure, whether due to OOM or a race with a raw + * sbrk() call from outside the allocator. + */ + if (dss_prev == (void *)-1) { + /* OOM. */ + atomic_store_b(&dss_exhausted, true, + ATOMIC_RELEASE); + goto label_oom; + } + } + } +label_oom: + extent_dss_extending_finish(); + extent_dalloc(tsdn, arena, gap); + return NULL; +} + +static bool +extent_in_dss_helper(void *addr, void *max) { + return ((uintptr_t)addr >= (uintptr_t)dss_base && (uintptr_t)addr < + (uintptr_t)max); +} + +bool +extent_in_dss(void *addr) { + cassert(have_dss); + + return extent_in_dss_helper(addr, atomic_load_p(&dss_max, + ATOMIC_ACQUIRE)); +} + +bool +extent_dss_mergeable(void *addr_a, void *addr_b) { + void *max; + + cassert(have_dss); + + if ((uintptr_t)addr_a < (uintptr_t)dss_base && (uintptr_t)addr_b < + (uintptr_t)dss_base) { + return true; + } + + max = atomic_load_p(&dss_max, ATOMIC_ACQUIRE); + return (extent_in_dss_helper(addr_a, max) == + extent_in_dss_helper(addr_b, max)); +} + +void +extent_dss_boot(void) { + cassert(have_dss); + + dss_base = extent_dss_sbrk(0); + atomic_store_b(&dss_extending, false, ATOMIC_RELAXED); + atomic_store_b(&dss_exhausted, dss_base == (void *)-1, ATOMIC_RELAXED); + atomic_store_p(&dss_max, dss_base, ATOMIC_RELAXED); +} + +/******************************************************************************/ diff --git a/modules/worldengine/deps/jemalloc/src/extent_mmap.c b/modules/worldengine/deps/jemalloc/src/extent_mmap.c new file mode 100644 index 0000000000..8d607dc803 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/extent_mmap.c @@ -0,0 +1,42 @@ +#define JEMALLOC_EXTENT_MMAP_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/extent_mmap.h" + +/******************************************************************************/ +/* Data. */ + +bool opt_retain = +#ifdef JEMALLOC_RETAIN + true +#else + false +#endif + ; + +/******************************************************************************/ + +void * +extent_alloc_mmap(void *new_addr, size_t size, size_t alignment, bool *zero, + bool *commit) { + void *ret = pages_map(new_addr, size, ALIGNMENT_CEILING(alignment, + PAGE), commit); + if (ret == NULL) { + return NULL; + } + assert(ret != NULL); + if (*commit) { + *zero = true; + } + return ret; +} + +bool +extent_dalloc_mmap(void *addr, size_t size) { + if (!opt_retain) { + pages_unmap(addr, size); + } + return opt_retain; +} diff --git a/modules/worldengine/deps/jemalloc/src/hooks.c b/modules/worldengine/deps/jemalloc/src/hooks.c new file mode 100644 index 0000000000..6266ecd47f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/hooks.c @@ -0,0 +1,12 @@ +#include "jemalloc/internal/jemalloc_preamble.h" + +/* + * The hooks are a little bit screwy -- they're not genuinely exported in the + * sense that we want them available to end-users, but we do want them visible + * from outside the generated library, so that we can use them in test code. + */ +JEMALLOC_EXPORT +void (*hooks_arena_new_hook)() = NULL; + +JEMALLOC_EXPORT +void (*hooks_libc_hook)() = NULL; diff --git a/modules/worldengine/deps/jemalloc/src/jemalloc_cpp.cpp b/modules/worldengine/deps/jemalloc/src/jemalloc_cpp.cpp new file mode 100644 index 0000000000..844ab398a7 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/jemalloc_cpp.cpp @@ -0,0 +1,132 @@ +#include <mutex> +#include <new> + +#define JEMALLOC_CPP_CPP_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#ifdef __cplusplus +} +#endif + +// All operators in this file are exported. + +// Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt +// thunk? +// +// extern __typeof (sdallocx) sdallocx_int +// __attribute ((alias ("sdallocx"), +// visibility ("hidden"))); +// +// ... but it needs to work with jemalloc namespaces. + +void *operator new(std::size_t size); +void *operator new[](std::size_t size); +void *operator new(std::size_t size, const std::nothrow_t &) noexcept; +void *operator new[](std::size_t size, const std::nothrow_t &) noexcept; +void operator delete(void *ptr) noexcept; +void operator delete[](void *ptr) noexcept; +void operator delete(void *ptr, const std::nothrow_t &) noexcept; +void operator delete[](void *ptr, const std::nothrow_t &) noexcept; + +#if __cpp_sized_deallocation >= 201309 +/* C++14's sized-delete operators. */ +void operator delete(void *ptr, std::size_t size) noexcept; +void operator delete[](void *ptr, std::size_t size) noexcept; +#endif + +template <bool IsNoExcept> +void * +newImpl(std::size_t size) noexcept(IsNoExcept) { + void *ptr = je_malloc(size); + if (likely(ptr != nullptr)) + return ptr; + + while (ptr == nullptr) { + std::new_handler handler; + // GCC-4.8 and clang 4.0 do not have std::get_new_handler. + { + static std::mutex mtx; + std::lock_guard<std::mutex> lock(mtx); + + handler = std::set_new_handler(nullptr); + std::set_new_handler(handler); + } + if (handler == nullptr) + break; + + try { + handler(); + } catch (const std::bad_alloc &) { + break; + } + + ptr = je_malloc(size); + } + + if (ptr == nullptr && !IsNoExcept) + std::__throw_bad_alloc(); + return ptr; +} + +void * +operator new(std::size_t size) { + return newImpl<false>(size); +} + +void * +operator new[](std::size_t size) { + return newImpl<false>(size); +} + +void * +operator new(std::size_t size, const std::nothrow_t &) noexcept { + return newImpl<true>(size); +} + +void * +operator new[](std::size_t size, const std::nothrow_t &) noexcept { + return newImpl<true>(size); +} + +void +operator delete(void *ptr) noexcept { + je_free(ptr); +} + +void +operator delete[](void *ptr) noexcept { + je_free(ptr); +} + +void +operator delete(void *ptr, const std::nothrow_t &) noexcept { + je_free(ptr); +} + +void operator delete[](void *ptr, const std::nothrow_t &) noexcept { + je_free(ptr); +} + +#if __cpp_sized_deallocation >= 201309 + +void +operator delete(void *ptr, std::size_t size) noexcept { + if (unlikely(ptr == nullptr)) { + return; + } + je_sdallocx(ptr, size, /*flags=*/0); +} + +void operator delete[](void *ptr, std::size_t size) noexcept { + if (unlikely(ptr == nullptr)) { + return; + } + je_sdallocx(ptr, size, /*flags=*/0); +} + +#endif // __cpp_sized_deallocation diff --git a/modules/worldengine/deps/jemalloc/src/large.c b/modules/worldengine/deps/jemalloc/src/large.c new file mode 100644 index 0000000000..27a2c67987 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/large.c @@ -0,0 +1,371 @@ +#define JEMALLOC_LARGE_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/extent_mmap.h" +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/rtree.h" +#include "jemalloc/internal/util.h" + +/******************************************************************************/ + +void * +large_malloc(tsdn_t *tsdn, arena_t *arena, size_t usize, bool zero) { + assert(usize == sz_s2u(usize)); + + return large_palloc(tsdn, arena, usize, CACHELINE, zero); +} + +void * +large_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment, + bool zero) { + size_t ausize; + extent_t *extent; + bool is_zeroed; + UNUSED bool idump JEMALLOC_CC_SILENCE_INIT(false); + + assert(!tsdn_null(tsdn) || arena != NULL); + + ausize = sz_sa2u(usize, alignment); + if (unlikely(ausize == 0 || ausize > LARGE_MAXCLASS)) { + return NULL; + } + + if (config_fill && unlikely(opt_zero)) { + zero = true; + } + /* + * Copy zero into is_zeroed and pass the copy when allocating the + * extent, so that it is possible to make correct junk/zero fill + * decisions below, even if is_zeroed ends up true when zero is false. + */ + is_zeroed = zero; + if (likely(!tsdn_null(tsdn))) { + arena = arena_choose(tsdn_tsd(tsdn), arena); + } + if (unlikely(arena == NULL) || (extent = arena_extent_alloc_large(tsdn, + arena, usize, alignment, &is_zeroed)) == NULL) { + return NULL; + } + + /* See comments in arena_bin_slabs_full_insert(). */ + if (!arena_is_auto(arena)) { + /* Insert extent into large. */ + malloc_mutex_lock(tsdn, &arena->large_mtx); + extent_list_append(&arena->large, extent); + malloc_mutex_unlock(tsdn, &arena->large_mtx); + } + if (config_prof && arena_prof_accum(tsdn, arena, usize)) { + prof_idump(tsdn); + } + + if (zero) { + assert(is_zeroed); + } else if (config_fill && unlikely(opt_junk_alloc)) { + memset(extent_addr_get(extent), JEMALLOC_ALLOC_JUNK, + extent_usize_get(extent)); + } + + arena_decay_tick(tsdn, arena); + return extent_addr_get(extent); +} + +static void +large_dalloc_junk_impl(void *ptr, size_t size) { + memset(ptr, JEMALLOC_FREE_JUNK, size); +} +large_dalloc_junk_t *JET_MUTABLE large_dalloc_junk = large_dalloc_junk_impl; + +static void +large_dalloc_maybe_junk_impl(void *ptr, size_t size) { + if (config_fill && have_dss && unlikely(opt_junk_free)) { + /* + * Only bother junk filling if the extent isn't about to be + * unmapped. + */ + if (opt_retain || (have_dss && extent_in_dss(ptr))) { + large_dalloc_junk(ptr, size); + } + } +} +large_dalloc_maybe_junk_t *JET_MUTABLE large_dalloc_maybe_junk = + large_dalloc_maybe_junk_impl; + +static bool +large_ralloc_no_move_shrink(tsdn_t *tsdn, extent_t *extent, size_t usize) { + arena_t *arena = extent_arena_get(extent); + size_t oldusize = extent_usize_get(extent); + extent_hooks_t *extent_hooks = extent_hooks_get(arena); + size_t diff = extent_size_get(extent) - (usize + sz_large_pad); + + assert(oldusize > usize); + + if (extent_hooks->split == NULL) { + return true; + } + + /* Split excess pages. */ + if (diff != 0) { + extent_t *trail = extent_split_wrapper(tsdn, arena, + &extent_hooks, extent, usize + sz_large_pad, + sz_size2index(usize), false, diff, NSIZES, false); + if (trail == NULL) { + return true; + } + + if (config_fill && unlikely(opt_junk_free)) { + large_dalloc_maybe_junk(extent_addr_get(trail), + extent_size_get(trail)); + } + + arena_extents_dirty_dalloc(tsdn, arena, &extent_hooks, trail); + } + + arena_extent_ralloc_large_shrink(tsdn, arena, extent, oldusize); + + return false; +} + +static bool +large_ralloc_no_move_expand(tsdn_t *tsdn, extent_t *extent, size_t usize, + bool zero) { + arena_t *arena = extent_arena_get(extent); + size_t oldusize = extent_usize_get(extent); + extent_hooks_t *extent_hooks = extent_hooks_get(arena); + size_t trailsize = usize - oldusize; + + if (extent_hooks->merge == NULL) { + return true; + } + + if (config_fill && unlikely(opt_zero)) { + zero = true; + } + /* + * Copy zero into is_zeroed_trail and pass the copy when allocating the + * extent, so that it is possible to make correct junk/zero fill + * decisions below, even if is_zeroed_trail ends up true when zero is + * false. + */ + bool is_zeroed_trail = zero; + bool commit = true; + extent_t *trail; + bool new_mapping; + if ((trail = extents_alloc(tsdn, arena, &extent_hooks, + &arena->extents_dirty, extent_past_get(extent), trailsize, 0, + CACHELINE, false, NSIZES, &is_zeroed_trail, &commit)) != NULL + || (trail = extents_alloc(tsdn, arena, &extent_hooks, + &arena->extents_muzzy, extent_past_get(extent), trailsize, 0, + CACHELINE, false, NSIZES, &is_zeroed_trail, &commit)) != NULL) { + if (config_stats) { + new_mapping = false; + } + } else { + if ((trail = extent_alloc_wrapper(tsdn, arena, &extent_hooks, + extent_past_get(extent), trailsize, 0, CACHELINE, false, + NSIZES, &is_zeroed_trail, &commit)) == NULL) { + return true; + } + if (config_stats) { + new_mapping = true; + } + } + + if (extent_merge_wrapper(tsdn, arena, &extent_hooks, extent, trail)) { + extent_dalloc_wrapper(tsdn, arena, &extent_hooks, trail); + return true; + } + rtree_ctx_t rtree_ctx_fallback; + rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback); + szind_t szind = sz_size2index(usize); + extent_szind_set(extent, szind); + rtree_szind_slab_update(tsdn, &extents_rtree, rtree_ctx, + (uintptr_t)extent_addr_get(extent), szind, false); + + if (config_stats && new_mapping) { + arena_stats_mapped_add(tsdn, &arena->stats, trailsize); + } + + if (zero) { + if (config_cache_oblivious) { + /* + * Zero the trailing bytes of the original allocation's + * last page, since they are in an indeterminate state. + * There will always be trailing bytes, because ptr's + * offset from the beginning of the extent is a multiple + * of CACHELINE in [0 .. PAGE). + */ + void *zbase = (void *) + ((uintptr_t)extent_addr_get(extent) + oldusize); + void *zpast = PAGE_ADDR2BASE((void *)((uintptr_t)zbase + + PAGE)); + size_t nzero = (uintptr_t)zpast - (uintptr_t)zbase; + assert(nzero > 0); + memset(zbase, 0, nzero); + } + assert(is_zeroed_trail); + } else if (config_fill && unlikely(opt_junk_alloc)) { + memset((void *)((uintptr_t)extent_addr_get(extent) + oldusize), + JEMALLOC_ALLOC_JUNK, usize - oldusize); + } + + arena_extent_ralloc_large_expand(tsdn, arena, extent, oldusize); + + return false; +} + +bool +large_ralloc_no_move(tsdn_t *tsdn, extent_t *extent, size_t usize_min, + size_t usize_max, bool zero) { + size_t oldusize = extent_usize_get(extent); + + /* The following should have been caught by callers. */ + assert(usize_min > 0 && usize_max <= LARGE_MAXCLASS); + /* Both allocation sizes must be large to avoid a move. */ + assert(oldusize >= LARGE_MINCLASS && usize_max >= LARGE_MINCLASS); + + if (usize_max > oldusize) { + /* Attempt to expand the allocation in-place. */ + if (!large_ralloc_no_move_expand(tsdn, extent, usize_max, + zero)) { + arena_decay_tick(tsdn, extent_arena_get(extent)); + return false; + } + /* Try again, this time with usize_min. */ + if (usize_min < usize_max && usize_min > oldusize && + large_ralloc_no_move_expand(tsdn, extent, usize_min, + zero)) { + arena_decay_tick(tsdn, extent_arena_get(extent)); + return false; + } + } + + /* + * Avoid moving the allocation if the existing extent size accommodates + * the new size. + */ + if (oldusize >= usize_min && oldusize <= usize_max) { + arena_decay_tick(tsdn, extent_arena_get(extent)); + return false; + } + + /* Attempt to shrink the allocation in-place. */ + if (oldusize > usize_max) { + if (!large_ralloc_no_move_shrink(tsdn, extent, usize_max)) { + arena_decay_tick(tsdn, extent_arena_get(extent)); + return false; + } + } + return true; +} + +static void * +large_ralloc_move_helper(tsdn_t *tsdn, arena_t *arena, size_t usize, + size_t alignment, bool zero) { + if (alignment <= CACHELINE) { + return large_malloc(tsdn, arena, usize, zero); + } + return large_palloc(tsdn, arena, usize, alignment, zero); +} + +void * +large_ralloc(tsdn_t *tsdn, arena_t *arena, extent_t *extent, size_t usize, + size_t alignment, bool zero, tcache_t *tcache) { + size_t oldusize = extent_usize_get(extent); + + /* The following should have been caught by callers. */ + assert(usize > 0 && usize <= LARGE_MAXCLASS); + /* Both allocation sizes must be large to avoid a move. */ + assert(oldusize >= LARGE_MINCLASS && usize >= LARGE_MINCLASS); + + /* Try to avoid moving the allocation. */ + if (!large_ralloc_no_move(tsdn, extent, usize, usize, zero)) { + return extent_addr_get(extent); + } + + /* + * usize and old size are different enough that we need to use a + * different size class. In that case, fall back to allocating new + * space and copying. + */ + void *ret = large_ralloc_move_helper(tsdn, arena, usize, alignment, + zero); + if (ret == NULL) { + return NULL; + } + + size_t copysize = (usize < oldusize) ? usize : oldusize; + memcpy(ret, extent_addr_get(extent), copysize); + isdalloct(tsdn, extent_addr_get(extent), oldusize, tcache, NULL, true); + return ret; +} + +/* + * junked_locked indicates whether the extent's data have been junk-filled, and + * whether the arena's large_mtx is currently held. + */ +static void +large_dalloc_prep_impl(tsdn_t *tsdn, arena_t *arena, extent_t *extent, + bool junked_locked) { + if (!junked_locked) { + /* See comments in arena_bin_slabs_full_insert(). */ + if (!arena_is_auto(arena)) { + malloc_mutex_lock(tsdn, &arena->large_mtx); + extent_list_remove(&arena->large, extent); + malloc_mutex_unlock(tsdn, &arena->large_mtx); + } + large_dalloc_maybe_junk(extent_addr_get(extent), + extent_usize_get(extent)); + } else { + malloc_mutex_assert_owner(tsdn, &arena->large_mtx); + if (!arena_is_auto(arena)) { + extent_list_remove(&arena->large, extent); + } + } + arena_extent_dalloc_large_prep(tsdn, arena, extent); +} + +static void +large_dalloc_finish_impl(tsdn_t *tsdn, arena_t *arena, extent_t *extent) { + extent_hooks_t *extent_hooks = EXTENT_HOOKS_INITIALIZER; + arena_extents_dirty_dalloc(tsdn, arena, &extent_hooks, extent); +} + +void +large_dalloc_prep_junked_locked(tsdn_t *tsdn, extent_t *extent) { + large_dalloc_prep_impl(tsdn, extent_arena_get(extent), extent, true); +} + +void +large_dalloc_finish(tsdn_t *tsdn, extent_t *extent) { + large_dalloc_finish_impl(tsdn, extent_arena_get(extent), extent); +} + +void +large_dalloc(tsdn_t *tsdn, extent_t *extent) { + arena_t *arena = extent_arena_get(extent); + large_dalloc_prep_impl(tsdn, arena, extent, false); + large_dalloc_finish_impl(tsdn, arena, extent); + arena_decay_tick(tsdn, arena); +} + +size_t +large_salloc(tsdn_t *tsdn, const extent_t *extent) { + return extent_usize_get(extent); +} + +prof_tctx_t * +large_prof_tctx_get(tsdn_t *tsdn, const extent_t *extent) { + return extent_prof_tctx_get(extent); +} + +void +large_prof_tctx_set(tsdn_t *tsdn, extent_t *extent, prof_tctx_t *tctx) { + extent_prof_tctx_set(extent, tctx); +} + +void +large_prof_tctx_reset(tsdn_t *tsdn, extent_t *extent) { + large_prof_tctx_set(tsdn, extent, (prof_tctx_t *)(uintptr_t)1U); +} diff --git a/modules/worldengine/deps/jemalloc/src/malloc_io.c b/modules/worldengine/deps/jemalloc/src/malloc_io.c new file mode 100644 index 0000000000..6b99afcd3f --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/malloc_io.c @@ -0,0 +1,689 @@ +#define JEMALLOC_MALLOC_IO_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/malloc_io.h" +#include "jemalloc/internal/util.h" + +#ifdef assert +# undef assert +#endif +#ifdef not_reached +# undef not_reached +#endif +#ifdef not_implemented +# undef not_implemented +#endif +#ifdef assert_not_implemented +# undef assert_not_implemented +#endif + +/* + * Define simple versions of assertion macros that won't recurse in case + * of assertion failures in malloc_*printf(). + */ +#define assert(e) do { \ + if (config_debug && !(e)) { \ + malloc_write("<jemalloc>: Failed assertion\n"); \ + abort(); \ + } \ +} while (0) + +#define not_reached() do { \ + if (config_debug) { \ + malloc_write("<jemalloc>: Unreachable code reached\n"); \ + abort(); \ + } \ + unreachable(); \ +} while (0) + +#define not_implemented() do { \ + if (config_debug) { \ + malloc_write("<jemalloc>: Not implemented\n"); \ + abort(); \ + } \ +} while (0) + +#define assert_not_implemented(e) do { \ + if (unlikely(config_debug && !(e))) { \ + not_implemented(); \ + } \ +} while (0) + +/******************************************************************************/ +/* Function prototypes for non-inline static functions. */ + +static void wrtmessage(void *cbopaque, const char *s); +#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1) +static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s, + size_t *slen_p); +#define D2S_BUFSIZE (1 + U2S_BUFSIZE) +static char *d2s(intmax_t x, char sign, char *s, size_t *slen_p); +#define O2S_BUFSIZE (1 + U2S_BUFSIZE) +static char *o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p); +#define X2S_BUFSIZE (2 + U2S_BUFSIZE) +static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, + size_t *slen_p); + +/******************************************************************************/ + +/* malloc_message() setup. */ +static void +wrtmessage(void *cbopaque, const char *s) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) + /* + * Use syscall(2) rather than write(2) when possible in order to avoid + * the possibility of memory allocation within libc. This is necessary + * on FreeBSD; most operating systems do not have this problem though. + * + * syscall() returns long or int, depending on platform, so capture the + * unused result in the widest plausible type to avoid compiler + * warnings. + */ + UNUSED long result = syscall(SYS_write, STDERR_FILENO, s, strlen(s)); +#else + UNUSED ssize_t result = write(STDERR_FILENO, s, strlen(s)); +#endif +} + +JEMALLOC_EXPORT void (*je_malloc_message)(void *, const char *s); + +/* + * Wrapper around malloc_message() that avoids the need for + * je_malloc_message(...) throughout the code. + */ +void +malloc_write(const char *s) { + if (je_malloc_message != NULL) { + je_malloc_message(NULL, s); + } else { + wrtmessage(NULL, s); + } +} + +/* + * glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so + * provide a wrapper. + */ +int +buferror(int err, char *buf, size_t buflen) { +#ifdef _WIN32 + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, + (LPSTR)buf, (DWORD)buflen, NULL); + return 0; +#elif defined(__GLIBC__) && defined(_GNU_SOURCE) + char *b = strerror_r(err, buf, buflen); + if (b != buf) { + strncpy(buf, b, buflen); + buf[buflen-1] = '\0'; + } + return 0; +#else + return strerror_r(err, buf, buflen); +#endif +} + +uintmax_t +malloc_strtoumax(const char *restrict nptr, char **restrict endptr, int base) { + uintmax_t ret, digit; + unsigned b; + bool neg; + const char *p, *ns; + + p = nptr; + if (base < 0 || base == 1 || base > 36) { + ns = p; + set_errno(EINVAL); + ret = UINTMAX_MAX; + goto label_return; + } + b = base; + + /* Swallow leading whitespace and get sign, if any. */ + neg = false; + while (true) { + switch (*p) { + case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': + p++; + break; + case '-': + neg = true; + /* Fall through. */ + case '+': + p++; + /* Fall through. */ + default: + goto label_prefix; + } + } + + /* Get prefix, if any. */ + label_prefix: + /* + * Note where the first non-whitespace/sign character is so that it is + * possible to tell whether any digits are consumed (e.g., " 0" vs. + * " -x"). + */ + ns = p; + if (*p == '0') { + switch (p[1]) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': + if (b == 0) { + b = 8; + } + if (b == 8) { + p++; + } + break; + case 'X': case 'x': + switch (p[2]) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': + if (b == 0) { + b = 16; + } + if (b == 16) { + p += 2; + } + break; + default: + break; + } + break; + default: + p++; + ret = 0; + goto label_return; + } + } + if (b == 0) { + b = 10; + } + + /* Convert. */ + ret = 0; + while ((*p >= '0' && *p <= '9' && (digit = *p - '0') < b) + || (*p >= 'A' && *p <= 'Z' && (digit = 10 + *p - 'A') < b) + || (*p >= 'a' && *p <= 'z' && (digit = 10 + *p - 'a') < b)) { + uintmax_t pret = ret; + ret *= b; + ret += digit; + if (ret < pret) { + /* Overflow. */ + set_errno(ERANGE); + ret = UINTMAX_MAX; + goto label_return; + } + p++; + } + if (neg) { + ret = (uintmax_t)(-((intmax_t)ret)); + } + + if (p == ns) { + /* No conversion performed. */ + set_errno(EINVAL); + ret = UINTMAX_MAX; + goto label_return; + } + +label_return: + if (endptr != NULL) { + if (p == ns) { + /* No characters were converted. */ + *endptr = (char *)nptr; + } else { + *endptr = (char *)p; + } + } + return ret; +} + +static char * +u2s(uintmax_t x, unsigned base, bool uppercase, char *s, size_t *slen_p) { + unsigned i; + + i = U2S_BUFSIZE - 1; + s[i] = '\0'; + switch (base) { + case 10: + do { + i--; + s[i] = "0123456789"[x % (uint64_t)10]; + x /= (uint64_t)10; + } while (x > 0); + break; + case 16: { + const char *digits = (uppercase) + ? "0123456789ABCDEF" + : "0123456789abcdef"; + + do { + i--; + s[i] = digits[x & 0xf]; + x >>= 4; + } while (x > 0); + break; + } default: { + const char *digits = (uppercase) + ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + : "0123456789abcdefghijklmnopqrstuvwxyz"; + + assert(base >= 2 && base <= 36); + do { + i--; + s[i] = digits[x % (uint64_t)base]; + x /= (uint64_t)base; + } while (x > 0); + }} + + *slen_p = U2S_BUFSIZE - 1 - i; + return &s[i]; +} + +static char * +d2s(intmax_t x, char sign, char *s, size_t *slen_p) { + bool neg; + + if ((neg = (x < 0))) { + x = -x; + } + s = u2s(x, 10, false, s, slen_p); + if (neg) { + sign = '-'; + } + switch (sign) { + case '-': + if (!neg) { + break; + } + /* Fall through. */ + case ' ': + case '+': + s--; + (*slen_p)++; + *s = sign; + break; + default: not_reached(); + } + return s; +} + +static char * +o2s(uintmax_t x, bool alt_form, char *s, size_t *slen_p) { + s = u2s(x, 8, false, s, slen_p); + if (alt_form && *s != '0') { + s--; + (*slen_p)++; + *s = '0'; + } + return s; +} + +static char * +x2s(uintmax_t x, bool alt_form, bool uppercase, char *s, size_t *slen_p) { + s = u2s(x, 16, uppercase, s, slen_p); + if (alt_form) { + s -= 2; + (*slen_p) += 2; + memcpy(s, uppercase ? "0X" : "0x", 2); + } + return s; +} + +size_t +malloc_vsnprintf(char *str, size_t size, const char *format, va_list ap) { + size_t i; + const char *f; + +#define APPEND_C(c) do { \ + if (i < size) { \ + str[i] = (c); \ + } \ + i++; \ +} while (0) +#define APPEND_S(s, slen) do { \ + if (i < size) { \ + size_t cpylen = (slen <= size - i) ? slen : size - i; \ + memcpy(&str[i], s, cpylen); \ + } \ + i += slen; \ +} while (0) +#define APPEND_PADDED_S(s, slen, width, left_justify) do { \ + /* Left padding. */ \ + size_t pad_len = (width == -1) ? 0 : ((slen < (size_t)width) ? \ + (size_t)width - slen : 0); \ + if (!left_justify && pad_len != 0) { \ + size_t j; \ + for (j = 0; j < pad_len; j++) { \ + APPEND_C(' '); \ + } \ + } \ + /* Value. */ \ + APPEND_S(s, slen); \ + /* Right padding. */ \ + if (left_justify && pad_len != 0) { \ + size_t j; \ + for (j = 0; j < pad_len; j++) { \ + APPEND_C(' '); \ + } \ + } \ +} while (0) +#define GET_ARG_NUMERIC(val, len) do { \ + switch (len) { \ + case '?': \ + val = va_arg(ap, int); \ + break; \ + case '?' | 0x80: \ + val = va_arg(ap, unsigned int); \ + break; \ + case 'l': \ + val = va_arg(ap, long); \ + break; \ + case 'l' | 0x80: \ + val = va_arg(ap, unsigned long); \ + break; \ + case 'q': \ + val = va_arg(ap, long long); \ + break; \ + case 'q' | 0x80: \ + val = va_arg(ap, unsigned long long); \ + break; \ + case 'j': \ + val = va_arg(ap, intmax_t); \ + break; \ + case 'j' | 0x80: \ + val = va_arg(ap, uintmax_t); \ + break; \ + case 't': \ + val = va_arg(ap, ptrdiff_t); \ + break; \ + case 'z': \ + val = va_arg(ap, ssize_t); \ + break; \ + case 'z' | 0x80: \ + val = va_arg(ap, size_t); \ + break; \ + case 'p': /* Synthetic; used for %p. */ \ + val = va_arg(ap, uintptr_t); \ + break; \ + default: \ + not_reached(); \ + val = 0; \ + } \ +} while (0) + + i = 0; + f = format; + while (true) { + switch (*f) { + case '\0': goto label_out; + case '%': { + bool alt_form = false; + bool left_justify = false; + bool plus_space = false; + bool plus_plus = false; + int prec = -1; + int width = -1; + unsigned char len = '?'; + char *s; + size_t slen; + + f++; + /* Flags. */ + while (true) { + switch (*f) { + case '#': + assert(!alt_form); + alt_form = true; + break; + case '-': + assert(!left_justify); + left_justify = true; + break; + case ' ': + assert(!plus_space); + plus_space = true; + break; + case '+': + assert(!plus_plus); + plus_plus = true; + break; + default: goto label_width; + } + f++; + } + /* Width. */ + label_width: + switch (*f) { + case '*': + width = va_arg(ap, int); + f++; + if (width < 0) { + left_justify = true; + width = -width; + } + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + uintmax_t uwidth; + set_errno(0); + uwidth = malloc_strtoumax(f, (char **)&f, 10); + assert(uwidth != UINTMAX_MAX || get_errno() != + ERANGE); + width = (int)uwidth; + break; + } default: + break; + } + /* Width/precision separator. */ + if (*f == '.') { + f++; + } else { + goto label_length; + } + /* Precision. */ + switch (*f) { + case '*': + prec = va_arg(ap, int); + f++; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + uintmax_t uprec; + set_errno(0); + uprec = malloc_strtoumax(f, (char **)&f, 10); + assert(uprec != UINTMAX_MAX || get_errno() != + ERANGE); + prec = (int)uprec; + break; + } + default: break; + } + /* Length. */ + label_length: + switch (*f) { + case 'l': + f++; + if (*f == 'l') { + len = 'q'; + f++; + } else { + len = 'l'; + } + break; + case 'q': case 'j': case 't': case 'z': + len = *f; + f++; + break; + default: break; + } + /* Conversion specifier. */ + switch (*f) { + case '%': + /* %% */ + APPEND_C(*f); + f++; + break; + case 'd': case 'i': { + intmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[D2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len); + s = d2s(val, (plus_plus ? '+' : (plus_space ? + ' ' : '-')), buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'o': { + uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[O2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len | 0x80); + s = o2s(val, alt_form, buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'u': { + uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[U2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len | 0x80); + s = u2s(val, 10, false, buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'x': case 'X': { + uintmax_t val JEMALLOC_CC_SILENCE_INIT(0); + char buf[X2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, len | 0x80); + s = x2s(val, alt_form, *f == 'X', buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } case 'c': { + unsigned char val; + char buf[2]; + + assert(len == '?' || len == 'l'); + assert_not_implemented(len != 'l'); + val = va_arg(ap, int); + buf[0] = val; + buf[1] = '\0'; + APPEND_PADDED_S(buf, 1, width, left_justify); + f++; + break; + } case 's': + assert(len == '?' || len == 'l'); + assert_not_implemented(len != 'l'); + s = va_arg(ap, char *); + slen = (prec < 0) ? strlen(s) : (size_t)prec; + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + case 'p': { + uintmax_t val; + char buf[X2S_BUFSIZE]; + + GET_ARG_NUMERIC(val, 'p'); + s = x2s(val, true, false, buf, &slen); + APPEND_PADDED_S(s, slen, width, left_justify); + f++; + break; + } default: not_reached(); + } + break; + } default: { + APPEND_C(*f); + f++; + break; + }} + } + label_out: + if (i < size) { + str[i] = '\0'; + } else { + str[size - 1] = '\0'; + } + +#undef APPEND_C +#undef APPEND_S +#undef APPEND_PADDED_S +#undef GET_ARG_NUMERIC + return i; +} + +JEMALLOC_FORMAT_PRINTF(3, 4) +size_t +malloc_snprintf(char *str, size_t size, const char *format, ...) { + size_t ret; + va_list ap; + + va_start(ap, format); + ret = malloc_vsnprintf(str, size, format, ap); + va_end(ap); + + return ret; +} + +void +malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, va_list ap) { + char buf[MALLOC_PRINTF_BUFSIZE]; + + if (write_cb == NULL) { + /* + * The caller did not provide an alternate write_cb callback + * function, so use the default one. malloc_write() is an + * inline function, so use malloc_message() directly here. + */ + write_cb = (je_malloc_message != NULL) ? je_malloc_message : + wrtmessage; + cbopaque = NULL; + } + + malloc_vsnprintf(buf, sizeof(buf), format, ap); + write_cb(cbopaque, buf); +} + +/* + * Print to a callback function in such a way as to (hopefully) avoid memory + * allocation. + */ +JEMALLOC_FORMAT_PRINTF(3, 4) +void +malloc_cprintf(void (*write_cb)(void *, const char *), void *cbopaque, + const char *format, ...) { + va_list ap; + + va_start(ap, format); + malloc_vcprintf(write_cb, cbopaque, format, ap); + va_end(ap); +} + +/* Print to stderr in such a way as to avoid memory allocation. */ +JEMALLOC_FORMAT_PRINTF(1, 2) +void +malloc_printf(const char *format, ...) { + va_list ap; + + va_start(ap, format); + malloc_vcprintf(NULL, NULL, format, ap); + va_end(ap); +} + +/* + * Restore normal assertion macros, in order to make it possible to compile all + * C files as a single concatenation. + */ +#undef assert +#undef not_reached +#undef not_implemented +#undef assert_not_implemented +#include "jemalloc/internal/assert.h" diff --git a/modules/worldengine/deps/jemalloc/src/mutex_pool.c b/modules/worldengine/deps/jemalloc/src/mutex_pool.c new file mode 100644 index 0000000000..f24d10e44a --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/mutex_pool.c @@ -0,0 +1,18 @@ +#define JEMALLOC_MUTEX_POOL_C_ + +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/mutex.h" +#include "jemalloc/internal/mutex_pool.h" + +bool +mutex_pool_init(mutex_pool_t *pool, const char *name, witness_rank_t rank) { + for (int i = 0; i < MUTEX_POOL_SIZE; ++i) { + if (malloc_mutex_init(&pool->mutexes[i], name, rank, + malloc_mutex_address_ordered)) { + return true; + } + } + return false; +} diff --git a/modules/worldengine/deps/jemalloc/src/nstime.c b/modules/worldengine/deps/jemalloc/src/nstime.c new file mode 100644 index 0000000000..71db353965 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/nstime.c @@ -0,0 +1,170 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/nstime.h" + +#include "jemalloc/internal/assert.h" + +#define BILLION UINT64_C(1000000000) +#define MILLION UINT64_C(1000000) + +void +nstime_init(nstime_t *time, uint64_t ns) { + time->ns = ns; +} + +void +nstime_init2(nstime_t *time, uint64_t sec, uint64_t nsec) { + time->ns = sec * BILLION + nsec; +} + +uint64_t +nstime_ns(const nstime_t *time) { + return time->ns; +} + +uint64_t +nstime_msec(const nstime_t *time) { + return time->ns / MILLION; +} + +uint64_t +nstime_sec(const nstime_t *time) { + return time->ns / BILLION; +} + +uint64_t +nstime_nsec(const nstime_t *time) { + return time->ns % BILLION; +} + +void +nstime_copy(nstime_t *time, const nstime_t *source) { + *time = *source; +} + +int +nstime_compare(const nstime_t *a, const nstime_t *b) { + return (a->ns > b->ns) - (a->ns < b->ns); +} + +void +nstime_add(nstime_t *time, const nstime_t *addend) { + assert(UINT64_MAX - time->ns >= addend->ns); + + time->ns += addend->ns; +} + +void +nstime_iadd(nstime_t *time, uint64_t addend) { + assert(UINT64_MAX - time->ns >= addend); + + time->ns += addend; +} + +void +nstime_subtract(nstime_t *time, const nstime_t *subtrahend) { + assert(nstime_compare(time, subtrahend) >= 0); + + time->ns -= subtrahend->ns; +} + +void +nstime_isubtract(nstime_t *time, uint64_t subtrahend) { + assert(time->ns >= subtrahend); + + time->ns -= subtrahend; +} + +void +nstime_imultiply(nstime_t *time, uint64_t multiplier) { + assert((((time->ns | multiplier) & (UINT64_MAX << (sizeof(uint64_t) << + 2))) == 0) || ((time->ns * multiplier) / multiplier == time->ns)); + + time->ns *= multiplier; +} + +void +nstime_idivide(nstime_t *time, uint64_t divisor) { + assert(divisor != 0); + + time->ns /= divisor; +} + +uint64_t +nstime_divide(const nstime_t *time, const nstime_t *divisor) { + assert(divisor->ns != 0); + + return time->ns / divisor->ns; +} + +#ifdef _WIN32 +# define NSTIME_MONOTONIC true +static void +nstime_get(nstime_t *time) { + FILETIME ft; + uint64_t ticks_100ns; + + GetSystemTimeAsFileTime(&ft); + ticks_100ns = (((uint64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + + nstime_init(time, ticks_100ns * 100); +} +#elif defined(JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE) +# define NSTIME_MONOTONIC true +static void +nstime_get(nstime_t *time) { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC_COARSE, &ts); + nstime_init2(time, ts.tv_sec, ts.tv_nsec); +} +#elif defined(JEMALLOC_HAVE_CLOCK_MONOTONIC) +# define NSTIME_MONOTONIC true +static void +nstime_get(nstime_t *time) { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + nstime_init2(time, ts.tv_sec, ts.tv_nsec); +} +#elif defined(JEMALLOC_HAVE_MACH_ABSOLUTE_TIME) +# define NSTIME_MONOTONIC true +static void +nstime_get(nstime_t *time) { + nstime_init(time, mach_absolute_time()); +} +#else +# define NSTIME_MONOTONIC false +static void +nstime_get(nstime_t *time) { + struct timeval tv; + + gettimeofday(&tv, NULL); + nstime_init2(time, tv.tv_sec, tv.tv_usec * 1000); +} +#endif + +static bool +nstime_monotonic_impl(void) { + return NSTIME_MONOTONIC; +#undef NSTIME_MONOTONIC +} +nstime_monotonic_t *JET_MUTABLE nstime_monotonic = nstime_monotonic_impl; + +static bool +nstime_update_impl(nstime_t *time) { + nstime_t old_time; + + nstime_copy(&old_time, time); + nstime_get(time); + + /* Handle non-monotonic clocks. */ + if (unlikely(nstime_compare(&old_time, time) > 0)) { + nstime_copy(time, &old_time); + return true; + } + + return false; +} +nstime_update_t *JET_MUTABLE nstime_update = nstime_update_impl; diff --git a/modules/worldengine/deps/jemalloc/src/pages.c b/modules/worldengine/deps/jemalloc/src/pages.c new file mode 100644 index 0000000000..6f2ba5669b --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/pages.c @@ -0,0 +1,423 @@ +#define JEMALLOC_PAGES_C_ +#include "jemalloc/internal/jemalloc_preamble.h" + +#include "jemalloc/internal/pages.h" + +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/malloc_io.h" + +#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT +#include <sys/sysctl.h> +#endif + +/******************************************************************************/ +/* Data. */ + +/* Actual operating system page size, detected during bootstrap, <= PAGE. */ +static size_t os_page; + +#ifndef _WIN32 +# define PAGES_PROT_COMMIT (PROT_READ | PROT_WRITE) +# define PAGES_PROT_DECOMMIT (PROT_NONE) +static int mmap_flags; +#endif +static bool os_overcommits; + +/******************************************************************************/ +/* + * Function prototypes for static functions that are referenced prior to + * definition. + */ + +static void os_pages_unmap(void *addr, size_t size); + +/******************************************************************************/ + +static void * +os_pages_map(void *addr, size_t size, size_t alignment, bool *commit) { + assert(ALIGNMENT_ADDR2BASE(addr, os_page) == addr); + assert(ALIGNMENT_CEILING(size, os_page) == size); + assert(size != 0); + + if (os_overcommits) { + *commit = true; + } + + void *ret; +#ifdef _WIN32 + /* + * If VirtualAlloc can't allocate at the given address when one is + * given, it fails and returns NULL. + */ + ret = VirtualAlloc(addr, size, MEM_RESERVE | (*commit ? MEM_COMMIT : 0), + PAGE_READWRITE); +#else + /* + * We don't use MAP_FIXED here, because it can cause the *replacement* + * of existing mappings, and we only want to create new mappings. + */ + { + int prot = *commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT; + + ret = mmap(addr, size, prot, mmap_flags, -1, 0); + } + assert(ret != NULL); + + if (ret == MAP_FAILED) { + ret = NULL; + } else if (addr != NULL && ret != addr) { + /* + * We succeeded in mapping memory, but not in the right place. + */ + os_pages_unmap(ret, size); + ret = NULL; + } +#endif + assert(ret == NULL || (addr == NULL && ret != addr) || (addr != NULL && + ret == addr)); + return ret; +} + +static void * +os_pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size, + bool *commit) { + void *ret = (void *)((uintptr_t)addr + leadsize); + + assert(alloc_size >= leadsize + size); +#ifdef _WIN32 + os_pages_unmap(addr, alloc_size); + void *new_addr = os_pages_map(ret, size, PAGE, commit); + if (new_addr == ret) { + return ret; + } + if (new_addr != NULL) { + os_pages_unmap(new_addr, size); + } + return NULL; +#else + size_t trailsize = alloc_size - leadsize - size; + + if (leadsize != 0) { + os_pages_unmap(addr, leadsize); + } + if (trailsize != 0) { + os_pages_unmap((void *)((uintptr_t)ret + size), trailsize); + } + return ret; +#endif +} + +static void +os_pages_unmap(void *addr, size_t size) { + assert(ALIGNMENT_ADDR2BASE(addr, os_page) == addr); + assert(ALIGNMENT_CEILING(size, os_page) == size); + +#ifdef _WIN32 + if (VirtualFree(addr, 0, MEM_RELEASE) == 0) +#else + if (munmap(addr, size) == -1) +#endif + { + char buf[BUFERROR_BUF]; + + buferror(get_errno(), buf, sizeof(buf)); + malloc_printf("<jemalloc>: Error in " +#ifdef _WIN32 + "VirtualFree" +#else + "munmap" +#endif + "(): %s\n", buf); + if (opt_abort) { + abort(); + } + } +} + +static void * +pages_map_slow(size_t size, size_t alignment, bool *commit) { + size_t alloc_size = size + alignment - os_page; + /* Beware size_t wrap-around. */ + if (alloc_size < size) { + return NULL; + } + + void *ret; + do { + void *pages = os_pages_map(NULL, alloc_size, alignment, commit); + if (pages == NULL) { + return NULL; + } + size_t leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) + - (uintptr_t)pages; + ret = os_pages_trim(pages, alloc_size, leadsize, size, commit); + } while (ret == NULL); + + assert(ret != NULL); + assert(PAGE_ADDR2BASE(ret) == ret); + return ret; +} + +void * +pages_map(void *addr, size_t size, size_t alignment, bool *commit) { + assert(alignment >= PAGE); + assert(ALIGNMENT_ADDR2BASE(addr, alignment) == addr); + + /* + * Ideally, there would be a way to specify alignment to mmap() (like + * NetBSD has), but in the absence of such a feature, we have to work + * hard to efficiently create aligned mappings. The reliable, but + * slow method is to create a mapping that is over-sized, then trim the + * excess. However, that always results in one or two calls to + * os_pages_unmap(), and it can leave holes in the process's virtual + * memory map if memory grows downward. + * + * Optimistically try mapping precisely the right amount before falling + * back to the slow method, with the expectation that the optimistic + * approach works most of the time. + */ + + void *ret = os_pages_map(addr, size, os_page, commit); + if (ret == NULL || ret == addr) { + return ret; + } + assert(addr == NULL); + if (ALIGNMENT_ADDR2OFFSET(ret, alignment) != 0) { + os_pages_unmap(ret, size); + return pages_map_slow(size, alignment, commit); + } + + assert(PAGE_ADDR2BASE(ret) == ret); + return ret; +} + +void +pages_unmap(void *addr, size_t size) { + assert(PAGE_ADDR2BASE(addr) == addr); + assert(PAGE_CEILING(size) == size); + + os_pages_unmap(addr, size); +} + +static bool +pages_commit_impl(void *addr, size_t size, bool commit) { + assert(PAGE_ADDR2BASE(addr) == addr); + assert(PAGE_CEILING(size) == size); + + if (os_overcommits) { + return true; + } + +#ifdef _WIN32 + return (commit ? (addr != VirtualAlloc(addr, size, MEM_COMMIT, + PAGE_READWRITE)) : (!VirtualFree(addr, size, MEM_DECOMMIT))); +#else + { + int prot = commit ? PAGES_PROT_COMMIT : PAGES_PROT_DECOMMIT; + void *result = mmap(addr, size, prot, mmap_flags | MAP_FIXED, + -1, 0); + if (result == MAP_FAILED) { + return true; + } + if (result != addr) { + /* + * We succeeded in mapping memory, but not in the right + * place. + */ + os_pages_unmap(result, size); + return true; + } + return false; + } +#endif +} + +bool +pages_commit(void *addr, size_t size) { + return pages_commit_impl(addr, size, true); +} + +bool +pages_decommit(void *addr, size_t size) { + return pages_commit_impl(addr, size, false); +} + +bool +pages_purge_lazy(void *addr, size_t size) { + assert(PAGE_ADDR2BASE(addr) == addr); + assert(PAGE_CEILING(size) == size); + + if (!pages_can_purge_lazy) { + return true; + } + +#ifdef _WIN32 + VirtualAlloc(addr, size, MEM_RESET, PAGE_READWRITE); + return false; +#elif defined(JEMALLOC_PURGE_MADVISE_FREE) && \ + !defined(PAGES_CAN_PURGE_LAZY) + return (madvise(addr, size, MADV_FREE) != 0); +#elif defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ + !defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS) + return (madvise(addr, size, MADV_DONTNEED) != 0); +#else + not_reached(); +#endif +} + +bool +pages_purge_forced(void *addr, size_t size) { + assert(PAGE_ADDR2BASE(addr) == addr); + assert(PAGE_CEILING(size) == size); + + if (!pages_can_purge_forced) { + return true; + } + +#if defined(JEMALLOC_PURGE_MADVISE_DONTNEED) && \ + defined(JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS) + return (madvise(addr, size, MADV_DONTNEED) != 0); +#elif defined(JEMALLOC_MAPS_COALESCE) + /* Try to overlay a new demand-zeroed mapping. */ + return pages_commit(addr, size); +#else + not_reached(); +#endif +} + +bool +pages_huge(void *addr, size_t size) { + assert(HUGEPAGE_ADDR2BASE(addr) == addr); + assert(HUGEPAGE_CEILING(size) == size); + +#ifdef JEMALLOC_THP + return (madvise(addr, size, MADV_HUGEPAGE) != 0); +#else + return true; +#endif +} + +bool +pages_nohuge(void *addr, size_t size) { + assert(HUGEPAGE_ADDR2BASE(addr) == addr); + assert(HUGEPAGE_CEILING(size) == size); + +#ifdef JEMALLOC_THP + return (madvise(addr, size, MADV_NOHUGEPAGE) != 0); +#else + return false; +#endif +} + +static size_t +os_page_detect(void) { +#ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; +#else + long result = sysconf(_SC_PAGESIZE); + if (result == -1) { + return LG_PAGE; + } + return (size_t)result; +#endif +} + +#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT +static bool +os_overcommits_sysctl(void) { + int vm_overcommit; + size_t sz; + + sz = sizeof(vm_overcommit); + if (sysctlbyname("vm.overcommit", &vm_overcommit, &sz, NULL, 0) != 0) { + return false; /* Error. */ + } + + return ((vm_overcommit & 0x3) == 0); +} +#endif + +#ifdef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY +/* + * Use syscall(2) rather than {open,read,close}(2) when possible to avoid + * reentry during bootstrapping if another library has interposed system call + * wrappers. + */ +static bool +os_overcommits_proc(void) { + int fd; + char buf[1]; + ssize_t nread; + +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open) + fd = (int)syscall(SYS_open, "/proc/sys/vm/overcommit_memory", O_RDONLY | + O_CLOEXEC); +#elif defined(JEMALLOC_USE_SYSCALL) && defined(SYS_openat) + fd = (int)syscall(SYS_openat, + AT_FDCWD, "/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC); +#else + fd = open("/proc/sys/vm/overcommit_memory", O_RDONLY | O_CLOEXEC); +#endif + if (fd == -1) { + return false; /* Error. */ + } + +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) + nread = (ssize_t)syscall(SYS_read, fd, &buf, sizeof(buf)); +#else + nread = read(fd, &buf, sizeof(buf)); +#endif + +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close) + syscall(SYS_close, fd); +#else + close(fd); +#endif + + if (nread < 1) { + return false; /* Error. */ + } + /* + * /proc/sys/vm/overcommit_memory meanings: + * 0: Heuristic overcommit. + * 1: Always overcommit. + * 2: Never overcommit. + */ + return (buf[0] == '0' || buf[0] == '1'); +} +#endif + +bool +pages_boot(void) { + os_page = os_page_detect(); + if (os_page > PAGE) { + malloc_write("<jemalloc>: Unsupported system page size\n"); + if (opt_abort) { + abort(); + } + return true; + } + +#ifndef _WIN32 + mmap_flags = MAP_PRIVATE | MAP_ANON; +#endif + +#ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT + os_overcommits = os_overcommits_sysctl(); +#elif defined(JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY) + os_overcommits = os_overcommits_proc(); +# ifdef MAP_NORESERVE + if (os_overcommits) { + mmap_flags |= MAP_NORESERVE; + } +# endif +#else + os_overcommits = false; +#endif + + return false; +} diff --git a/modules/worldengine/deps/jemalloc/src/prng.c b/modules/worldengine/deps/jemalloc/src/prng.c new file mode 100644 index 0000000000..83c04bf9b5 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/prng.c @@ -0,0 +1,3 @@ +#define JEMALLOC_PRNG_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" diff --git a/modules/worldengine/deps/jemalloc/src/spin.c b/modules/worldengine/deps/jemalloc/src/spin.c new file mode 100644 index 0000000000..24372c26c9 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/spin.c @@ -0,0 +1,4 @@ +#define JEMALLOC_SPIN_C_ +#include "jemalloc/internal/jemalloc_preamble.h" + +#include "jemalloc/internal/spin.h" diff --git a/modules/worldengine/deps/jemalloc/src/sz.c b/modules/worldengine/deps/jemalloc/src/sz.c new file mode 100644 index 0000000000..0986615f71 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/sz.c @@ -0,0 +1,106 @@ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/sz.h" + +JEMALLOC_ALIGNED(CACHELINE) +const size_t sz_pind2sz_tab[NPSIZES+1] = { +#define PSZ_yes(lg_grp, ndelta, lg_delta) \ + (((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))), +#define PSZ_no(lg_grp, ndelta, lg_delta) +#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup) \ + PSZ_##psz(lg_grp, ndelta, lg_delta) + SIZE_CLASSES +#undef PSZ_yes +#undef PSZ_no +#undef SC + (LARGE_MAXCLASS + PAGE) +}; + +JEMALLOC_ALIGNED(CACHELINE) +const size_t sz_index2size_tab[NSIZES] = { +#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup) \ + ((ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta)), + SIZE_CLASSES +#undef SC +}; + +JEMALLOC_ALIGNED(CACHELINE) +const uint8_t sz_size2index_tab[] = { +#if LG_TINY_MIN == 0 +#warning "Dangerous LG_TINY_MIN" +#define S2B_0(i) i, +#elif LG_TINY_MIN == 1 +#warning "Dangerous LG_TINY_MIN" +#define S2B_1(i) i, +#elif LG_TINY_MIN == 2 +#warning "Dangerous LG_TINY_MIN" +#define S2B_2(i) i, +#elif LG_TINY_MIN == 3 +#define S2B_3(i) i, +#elif LG_TINY_MIN == 4 +#define S2B_4(i) i, +#elif LG_TINY_MIN == 5 +#define S2B_5(i) i, +#elif LG_TINY_MIN == 6 +#define S2B_6(i) i, +#elif LG_TINY_MIN == 7 +#define S2B_7(i) i, +#elif LG_TINY_MIN == 8 +#define S2B_8(i) i, +#elif LG_TINY_MIN == 9 +#define S2B_9(i) i, +#elif LG_TINY_MIN == 10 +#define S2B_10(i) i, +#elif LG_TINY_MIN == 11 +#define S2B_11(i) i, +#else +#error "Unsupported LG_TINY_MIN" +#endif +#if LG_TINY_MIN < 1 +#define S2B_1(i) S2B_0(i) S2B_0(i) +#endif +#if LG_TINY_MIN < 2 +#define S2B_2(i) S2B_1(i) S2B_1(i) +#endif +#if LG_TINY_MIN < 3 +#define S2B_3(i) S2B_2(i) S2B_2(i) +#endif +#if LG_TINY_MIN < 4 +#define S2B_4(i) S2B_3(i) S2B_3(i) +#endif +#if LG_TINY_MIN < 5 +#define S2B_5(i) S2B_4(i) S2B_4(i) +#endif +#if LG_TINY_MIN < 6 +#define S2B_6(i) S2B_5(i) S2B_5(i) +#endif +#if LG_TINY_MIN < 7 +#define S2B_7(i) S2B_6(i) S2B_6(i) +#endif +#if LG_TINY_MIN < 8 +#define S2B_8(i) S2B_7(i) S2B_7(i) +#endif +#if LG_TINY_MIN < 9 +#define S2B_9(i) S2B_8(i) S2B_8(i) +#endif +#if LG_TINY_MIN < 10 +#define S2B_10(i) S2B_9(i) S2B_9(i) +#endif +#if LG_TINY_MIN < 11 +#define S2B_11(i) S2B_10(i) S2B_10(i) +#endif +#define S2B_no(i) +#define SC(index, lg_grp, lg_delta, ndelta, psz, bin, pgs, lg_delta_lookup) \ + S2B_##lg_delta_lookup(index) + SIZE_CLASSES +#undef S2B_3 +#undef S2B_4 +#undef S2B_5 +#undef S2B_6 +#undef S2B_7 +#undef S2B_8 +#undef S2B_9 +#undef S2B_10 +#undef S2B_11 +#undef S2B_no +#undef SC +}; diff --git a/modules/worldengine/deps/jemalloc/src/ticker.c b/modules/worldengine/deps/jemalloc/src/ticker.c new file mode 100644 index 0000000000..d7b8cd26c0 --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/ticker.c @@ -0,0 +1,3 @@ +#define JEMALLOC_TICKER_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" diff --git a/modules/worldengine/deps/jemalloc/src/witness.c b/modules/worldengine/deps/jemalloc/src/witness.c new file mode 100644 index 0000000000..f42b72ad1a --- /dev/null +++ b/modules/worldengine/deps/jemalloc/src/witness.c @@ -0,0 +1,100 @@ +#define JEMALLOC_WITNESS_C_ +#include "jemalloc/internal/jemalloc_preamble.h" +#include "jemalloc/internal/jemalloc_internal_includes.h" + +#include "jemalloc/internal/assert.h" +#include "jemalloc/internal/malloc_io.h" + +void +witness_init(witness_t *witness, const char *name, witness_rank_t rank, + witness_comp_t *comp, void *opaque) { + witness->name = name; + witness->rank = rank; + witness->comp = comp; + witness->opaque = opaque; +} + +static void +witness_lock_error_impl(const witness_list_t *witnesses, + const witness_t *witness) { + witness_t *w; + + malloc_printf("<jemalloc>: Lock rank order reversal:"); + ql_foreach(w, witnesses, link) { + malloc_printf(" %s(%u)", w->name, w->rank); + } + malloc_printf(" %s(%u)\n", witness->name, witness->rank); + abort(); +} +witness_lock_error_t *JET_MUTABLE witness_lock_error = witness_lock_error_impl; + +static void +witness_owner_error_impl(const witness_t *witness) { + malloc_printf("<jemalloc>: Should own %s(%u)\n", witness->name, + witness->rank); + abort(); +} +witness_owner_error_t *JET_MUTABLE witness_owner_error = + witness_owner_error_impl; + +static void +witness_not_owner_error_impl(const witness_t *witness) { + malloc_printf("<jemalloc>: Should not own %s(%u)\n", witness->name, + witness->rank); + abort(); +} +witness_not_owner_error_t *JET_MUTABLE witness_not_owner_error = + witness_not_owner_error_impl; + +static void +witness_depth_error_impl(const witness_list_t *witnesses, + witness_rank_t rank_inclusive, unsigned depth) { + witness_t *w; + + malloc_printf("<jemalloc>: Should own %u lock%s of rank >= %u:", depth, + (depth != 1) ? "s" : "", rank_inclusive); + ql_foreach(w, witnesses, link) { + malloc_printf(" %s(%u)", w->name, w->rank); + } + malloc_printf("\n"); + abort(); +} +witness_depth_error_t *JET_MUTABLE witness_depth_error = + witness_depth_error_impl; + +void +witnesses_cleanup(witness_tsd_t *witness_tsd) { + witness_assert_lockless(witness_tsd_tsdn(witness_tsd)); + + /* Do nothing. */ +} + +void +witness_prefork(witness_tsd_t *witness_tsd) { + if (!config_debug) { + return; + } + witness_tsd->forking = true; +} + +void +witness_postfork_parent(witness_tsd_t *witness_tsd) { + if (!config_debug) { + return; + } + witness_tsd->forking = false; +} + +void +witness_postfork_child(witness_tsd_t *witness_tsd) { + if (!config_debug) { + return; + } +#ifndef JEMALLOC_MUTEX_INIT_CB + witness_list_t *witnesses; + + witnesses = &witness_tsd->witnesses; + ql_new(witnesses); +#endif + witness_tsd->forking = false; +} diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourAlloc.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourAlloc.h new file mode 100644 index 0000000000..f87b454acb --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourAlloc.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef DETOURALLOCATOR_H +#define DETOURALLOCATOR_H + +#include <stddef.h> + +/// Provides hint values to the memory allocator on how long the +/// memory is expected to be used. +enum dtAllocHint +{ + DT_ALLOC_PERM, ///< Memory persist after a function call. + DT_ALLOC_TEMP ///< Memory used temporarily within a function. +}; + +/// A memory allocation function. +// @param[in] size The size, in bytes of memory, to allocate. +// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use. +// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. +/// @see dtAllocSetCustom +typedef void* (dtAllocFunc)(size_t size, dtAllocHint hint); + +/// A memory deallocation function. +/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc. +/// @see dtAllocSetCustom +typedef void (dtFreeFunc)(void* ptr); + +/// Sets the base custom allocation functions to be used by Detour. +/// @param[in] allocFunc The memory allocation function to be used by #dtAlloc +/// @param[in] freeFunc The memory de-allocation function to be used by #dtFree +void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc); + +/// Allocates a memory block. +/// @param[in] size The size, in bytes of memory, to allocate. +/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use. +/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. +/// @see dtFree +void* dtAlloc(size_t size, dtAllocHint hint); + +/// Deallocates a memory block. +/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc. +/// @see dtAlloc +void dtFree(void* ptr); + +#endif diff --git a/deps/recastnavigation/Detour/DetourAssert.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourAssert.h index 3cf652288f..3cf652288f 100644 --- a/deps/recastnavigation/Detour/DetourAssert.h +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourAssert.h diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourCommon.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourCommon.h new file mode 100644 index 0000000000..739858cd9a --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourCommon.h @@ -0,0 +1,550 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef DETOURCOMMON_H +#define DETOURCOMMON_H + +#include "DetourMath.h" +#include <stddef.h> + +/** +@defgroup detour Detour + +Members in this module are used to create, manipulate, and query navigation +meshes. + +@note This is a summary list of members. Use the index or search +feature to find minor members. +*/ + +/// @name General helper functions +/// @{ + +/// Used to ignore a function parameter. VS complains about unused parameters +/// and this silences the warning. +/// @param [in] _ Unused parameter +template<class T> void dtIgnoreUnused(const T&) { } + +/// Swaps the values of the two parameters. +/// @param[in,out] a Value A +/// @param[in,out] b Value B +template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; } + +/// Returns the minimum of two values. +/// @param[in] a Value A +/// @param[in] b Value B +/// @return The minimum of the two values. +template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; } + +/// Returns the maximum of two values. +/// @param[in] a Value A +/// @param[in] b Value B +/// @return The maximum of the two values. +template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; } + +/// Returns the absolute value. +/// @param[in] a The value. +/// @return The absolute value of the specified value. +template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; } + +/// Returns the square of the value. +/// @param[in] a The value. +/// @return The square of the value. +template<class T> inline T dtSqr(T a) { return a*a; } + +/// Clamps the value to the specified range. +/// @param[in] v The value to clamp. +/// @param[in] mn The minimum permitted return value. +/// @param[in] mx The maximum permitted return value. +/// @return The value, clamped to the specified range. +template<class T> inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } + +/// @} +/// @name Vector helper functions. +/// @{ + +/// Derives the cross product of two vectors. (@p v1 x @p v2) +/// @param[out] dest The cross product. [(x, y, z)] +/// @param[in] v1 A Vector [(x, y, z)] +/// @param[in] v2 A vector [(x, y, z)] +inline void dtVcross(float* dest, const float* v1, const float* v2) +{ + dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; + dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; + dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +/// Derives the dot product of two vectors. (@p v1 . @p v2) +/// @param[in] v1 A Vector [(x, y, z)] +/// @param[in] v2 A vector [(x, y, z)] +/// @return The dot product. +inline float dtVdot(const float* v1, const float* v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s)) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v1 The base vector. [(x, y, z)] +/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)] +/// @param[in] s The amount to scale @p v2 by before adding to @p v1. +inline void dtVmad(float* dest, const float* v1, const float* v2, const float s) +{ + dest[0] = v1[0]+v2[0]*s; + dest[1] = v1[1]+v2[1]*s; + dest[2] = v1[2]+v2[2]*s; +} + +/// Performs a linear interpolation between two vectors. (@p v1 toward @p v2) +/// @param[out] dest The result vector. [(x, y, x)] +/// @param[in] v1 The starting vector. +/// @param[in] v2 The destination vector. +/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0] +inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t) +{ + dest[0] = v1[0]+(v2[0]-v1[0])*t; + dest[1] = v1[1]+(v2[1]-v1[1])*t; + dest[2] = v1[2]+(v2[2]-v1[2])*t; +} + +/// Performs a vector addition. (@p v1 + @p v2) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v1 The base vector. [(x, y, z)] +/// @param[in] v2 The vector to add to @p v1. [(x, y, z)] +inline void dtVadd(float* dest, const float* v1, const float* v2) +{ + dest[0] = v1[0]+v2[0]; + dest[1] = v1[1]+v2[1]; + dest[2] = v1[2]+v2[2]; +} + +/// Performs a vector subtraction. (@p v1 - @p v2) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v1 The base vector. [(x, y, z)] +/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)] +inline void dtVsub(float* dest, const float* v1, const float* v2) +{ + dest[0] = v1[0]-v2[0]; + dest[1] = v1[1]-v2[1]; + dest[2] = v1[2]-v2[2]; +} + +/// Scales the vector by the specified value. (@p v * @p t) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v The vector to scale. [(x, y, z)] +/// @param[in] t The scaling factor. +inline void dtVscale(float* dest, const float* v, const float t) +{ + dest[0] = v[0]*t; + dest[1] = v[1]*t; + dest[2] = v[2]*t; +} + +/// Selects the minimum value of each element from the specified vectors. +/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)] +/// @param[in] v A vector. [(x, y, z)] +inline void dtVmin(float* mn, const float* v) +{ + mn[0] = dtMin(mn[0], v[0]); + mn[1] = dtMin(mn[1], v[1]); + mn[2] = dtMin(mn[2], v[2]); +} + +/// Selects the maximum value of each element from the specified vectors. +/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)] +/// @param[in] v A vector. [(x, y, z)] +inline void dtVmax(float* mx, const float* v) +{ + mx[0] = dtMax(mx[0], v[0]); + mx[1] = dtMax(mx[1], v[1]); + mx[2] = dtMax(mx[2], v[2]); +} + +/// Sets the vector elements to the specified values. +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] x The x-value of the vector. +/// @param[in] y The y-value of the vector. +/// @param[in] z The z-value of the vector. +inline void dtVset(float* dest, const float x, const float y, const float z) +{ + dest[0] = x; dest[1] = y; dest[2] = z; +} + +/// Performs a vector copy. +/// @param[out] dest The result. [(x, y, z)] +/// @param[in] a The vector to copy. [(x, y, z)] +inline void dtVcopy(float* dest, const float* a) +{ + dest[0] = a[0]; + dest[1] = a[1]; + dest[2] = a[2]; +} + +/// Derives the scalar length of the vector. +/// @param[in] v The vector. [(x, y, z)] +/// @return The scalar length of the vector. +inline float dtVlen(const float* v) +{ + return dtMathSqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +/// Derives the square of the scalar length of the vector. (len * len) +/// @param[in] v The vector. [(x, y, z)] +/// @return The square of the scalar length of the vector. +inline float dtVlenSqr(const float* v) +{ + return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; +} + +/// Returns the distance between two points. +/// @param[in] v1 A point. [(x, y, z)] +/// @param[in] v2 A point. [(x, y, z)] +/// @return The distance between the two points. +inline float dtVdist(const float* v1, const float* v2) +{ + const float dx = v2[0] - v1[0]; + const float dy = v2[1] - v1[1]; + const float dz = v2[2] - v1[2]; + return dtMathSqrtf(dx*dx + dy*dy + dz*dz); +} + +/// Returns the square of the distance between two points. +/// @param[in] v1 A point. [(x, y, z)] +/// @param[in] v2 A point. [(x, y, z)] +/// @return The square of the distance between the two points. +inline float dtVdistSqr(const float* v1, const float* v2) +{ + const float dx = v2[0] - v1[0]; + const float dy = v2[1] - v1[1]; + const float dz = v2[2] - v1[2]; + return dx*dx + dy*dy + dz*dz; +} + +/// Derives the distance between the specified points on the xz-plane. +/// @param[in] v1 A point. [(x, y, z)] +/// @param[in] v2 A point. [(x, y, z)] +/// @return The distance between the point on the xz-plane. +/// +/// The vectors are projected onto the xz-plane, so the y-values are ignored. +inline float dtVdist2D(const float* v1, const float* v2) +{ + const float dx = v2[0] - v1[0]; + const float dz = v2[2] - v1[2]; + return dtMathSqrtf(dx*dx + dz*dz); +} + +/// Derives the square of the distance between the specified points on the xz-plane. +/// @param[in] v1 A point. [(x, y, z)] +/// @param[in] v2 A point. [(x, y, z)] +/// @return The square of the distance between the point on the xz-plane. +inline float dtVdist2DSqr(const float* v1, const float* v2) +{ + const float dx = v2[0] - v1[0]; + const float dz = v2[2] - v1[2]; + return dx*dx + dz*dz; +} + +/// Normalizes the vector. +/// @param[in,out] v The vector to normalize. [(x, y, z)] +inline void dtVnormalize(float* v) +{ + float d = 1.0f / dtMathSqrtf(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2])); + v[0] *= d; + v[1] *= d; + v[2] *= d; +} + +/// Performs a 'sloppy' colocation check of the specified points. +/// @param[in] p0 A point. [(x, y, z)] +/// @param[in] p1 A point. [(x, y, z)] +/// @return True if the points are considered to be at the same location. +/// +/// Basically, this function will return true if the specified points are +/// close enough to eachother to be considered colocated. +inline bool dtVequal(const float* p0, const float* p1) +{ + static const float thr = dtSqr(1.0f/16384.0f); + const float d = dtVdistSqr(p0, p1); + return d < thr; +} + +/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v) +/// @param[in] u A vector [(x, y, z)] +/// @param[in] v A vector [(x, y, z)] +/// @return The dot product on the xz-plane. +/// +/// The vectors are projected onto the xz-plane, so the y-values are ignored. +inline float dtVdot2D(const float* u, const float* v) +{ + return u[0]*v[0] + u[2]*v[2]; +} + +/// Derives the xz-plane 2D perp product of the two vectors. (uz*vx - ux*vz) +/// @param[in] u The LHV vector [(x, y, z)] +/// @param[in] v The RHV vector [(x, y, z)] +/// @return The dot product on the xz-plane. +/// +/// The vectors are projected onto the xz-plane, so the y-values are ignored. +inline float dtVperp2D(const float* u, const float* v) +{ + return u[2]*v[0] - u[0]*v[2]; +} + +/// @} +/// @name Computational geometry helper functions. +/// @{ + +/// Derives the signed xz-plane area of the triangle ABC, or the relationship of line AB to point C. +/// @param[in] a Vertex A. [(x, y, z)] +/// @param[in] b Vertex B. [(x, y, z)] +/// @param[in] c Vertex C. [(x, y, z)] +/// @return The signed xz-plane area of the triangle. +inline float dtTriArea2D(const float* a, const float* b, const float* c) +{ + const float abx = b[0] - a[0]; + const float abz = b[2] - a[2]; + const float acx = c[0] - a[0]; + const float acz = c[2] - a[2]; + return acx*abz - abx*acz; +} + +/// Determines if two axis-aligned bounding boxes overlap. +/// @param[in] amin Minimum bounds of box A. [(x, y, z)] +/// @param[in] amax Maximum bounds of box A. [(x, y, z)] +/// @param[in] bmin Minimum bounds of box B. [(x, y, z)] +/// @param[in] bmax Maximum bounds of box B. [(x, y, z)] +/// @return True if the two AABB's overlap. +/// @see dtOverlapBounds +inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3], + const unsigned short bmin[3], const unsigned short bmax[3]) +{ + bool overlap = true; + overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; + overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; + overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; + return overlap; +} + +/// Determines if two axis-aligned bounding boxes overlap. +/// @param[in] amin Minimum bounds of box A. [(x, y, z)] +/// @param[in] amax Maximum bounds of box A. [(x, y, z)] +/// @param[in] bmin Minimum bounds of box B. [(x, y, z)] +/// @param[in] bmax Maximum bounds of box B. [(x, y, z)] +/// @return True if the two AABB's overlap. +/// @see dtOverlapQuantBounds +inline bool dtOverlapBounds(const float* amin, const float* amax, + const float* bmin, const float* bmax) +{ + bool overlap = true; + overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; + overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; + overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; + return overlap; +} + +/// Derives the closest point on a triangle from the specified reference point. +/// @param[out] closest The closest point on the triangle. +/// @param[in] p The reference point from which to test. [(x, y, z)] +/// @param[in] a Vertex A of triangle ABC. [(x, y, z)] +/// @param[in] b Vertex B of triangle ABC. [(x, y, z)] +/// @param[in] c Vertex C of triangle ABC. [(x, y, z)] +void dtClosestPtPointTriangle(float* closest, const float* p, + const float* a, const float* b, const float* c); + +/// Derives the y-axis height of the closest point on the triangle from the specified reference point. +/// @param[in] p The reference point from which to test. [(x, y, z)] +/// @param[in] a Vertex A of triangle ABC. [(x, y, z)] +/// @param[in] b Vertex B of triangle ABC. [(x, y, z)] +/// @param[in] c Vertex C of triangle ABC. [(x, y, z)] +/// @param[out] h The resulting height. +bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h); + +bool dtIntersectSegmentPoly2D(const float* p0, const float* p1, + const float* verts, int nverts, + float& tmin, float& tmax, + int& segMin, int& segMax); + +bool dtIntersectSegSeg2D(const float* ap, const float* aq, + const float* bp, const float* bq, + float& s, float& t); + +/// Determines if the specified point is inside the convex polygon on the xz-plane. +/// @param[in] pt The point to check. [(x, y, z)] +/// @param[in] verts The polygon vertices. [(x, y, z) * @p nverts] +/// @param[in] nverts The number of vertices. [Limit: >= 3] +/// @return True if the point is inside the polygon. +bool dtPointInPolygon(const float* pt, const float* verts, const int nverts); + +bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts, + float* ed, float* et); + +float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t); + +/// Derives the centroid of a convex polygon. +/// @param[out] tc The centroid of the polgyon. [(x, y, z)] +/// @param[in] idx The polygon indices. [(vertIndex) * @p nidx] +/// @param[in] nidx The number of indices in the polygon. [Limit: >= 3] +/// @param[in] verts The polygon vertices. [(x, y, z) * vertCount] +void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts); + +/// Determines if the two convex polygons overlap on the xz-plane. +/// @param[in] polya Polygon A vertices. [(x, y, z) * @p npolya] +/// @param[in] npolya The number of vertices in polygon A. +/// @param[in] polyb Polygon B vertices. [(x, y, z) * @p npolyb] +/// @param[in] npolyb The number of vertices in polygon B. +/// @return True if the two polygons overlap. +bool dtOverlapPolyPoly2D(const float* polya, const int npolya, + const float* polyb, const int npolyb); + +/// @} +/// @name Miscellanious functions. +/// @{ + +inline unsigned int dtNextPow2(unsigned int v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} + +inline unsigned int dtIlog2(unsigned int v) +{ + unsigned int r; + unsigned int shift; + r = (v > 0xffff) << 4; v >>= r; + shift = (v > 0xff) << 3; v >>= shift; r |= shift; + shift = (v > 0xf) << 2; v >>= shift; r |= shift; + shift = (v > 0x3) << 1; v >>= shift; r |= shift; + r |= (v >> 1); + return r; +} + +inline int dtAlign4(int x) { return (x+3) & ~3; } + +inline int dtOppositeTile(int side) { return (side+4) & 0x7; } + +inline void dtSwapByte(unsigned char* a, unsigned char* b) +{ + unsigned char tmp = *a; + *a = *b; + *b = tmp; +} + +inline void dtSwapEndian(unsigned short* v) +{ + unsigned char* x = (unsigned char*)v; + dtSwapByte(x+0, x+1); +} + +inline void dtSwapEndian(short* v) +{ + unsigned char* x = (unsigned char*)v; + dtSwapByte(x+0, x+1); +} + +inline void dtSwapEndian(unsigned int* v) +{ + unsigned char* x = (unsigned char*)v; + dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); +} + +inline void dtSwapEndian(int* v) +{ + unsigned char* x = (unsigned char*)v; + dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); +} + +inline void dtSwapEndian(float* v) +{ + unsigned char* x = (unsigned char*)v; + dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); +} + +void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas, + const float s, const float t, float* out); + +template<typename TypeToRetrieveAs> +TypeToRetrieveAs* dtGetThenAdvanceBufferPointer(const unsigned char*& buffer, const size_t distanceToAdvance) +{ + TypeToRetrieveAs* returnPointer = reinterpret_cast<TypeToRetrieveAs*>(buffer); + buffer += distanceToAdvance; + return returnPointer; +} + +template<typename TypeToRetrieveAs> +TypeToRetrieveAs* dtGetThenAdvanceBufferPointer(unsigned char*& buffer, const size_t distanceToAdvance) +{ + TypeToRetrieveAs* returnPointer = reinterpret_cast<TypeToRetrieveAs*>(buffer); + buffer += distanceToAdvance; + return returnPointer; +} + + +/// @} + +#endif // DETOURCOMMON_H + +/////////////////////////////////////////////////////////////////////////// + +// This section contains detailed documentation for members that don't have +// a source file. It reduces clutter in the main section of the header. + +/** + +@fn float dtTriArea2D(const float* a, const float* b, const float* c) +@par + +The vertices are projected onto the xz-plane, so the y-values are ignored. + +This is a low cost function than can be used for various purposes. Its main purpose +is for point/line relationship testing. + +In all cases: A value of zero indicates that all vertices are collinear or represent the same point. +(On the xz-plane.) + +When used for point/line relationship tests, AB usually represents a line against which +the C point is to be tested. In this case: + +A positive value indicates that point C is to the left of line AB, looking from A toward B.<br/> +A negative value indicates that point C is to the right of lineAB, looking from A toward B. + +When used for evaluating a triangle: + +The absolute value of the return value is two times the area of the triangle when it is +projected onto the xz-plane. + +A positive return value indicates: + +<ul> +<li>The vertices are wrapped in the normal Detour wrap direction.</li> +<li>The triangle's 3D face normal is in the general up direction.</li> +</ul> + +A negative return value indicates: + +<ul> +<li>The vertices are reverse wrapped. (Wrapped opposite the normal Detour wrap direction.)</li> +<li>The triangle's 3D face normal is in the general down direction.</li> +</ul> + +*/ diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourMath.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourMath.h new file mode 100644 index 0000000000..95e14f8843 --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourMath.h @@ -0,0 +1,20 @@ +/** +@defgroup detour Detour + +Members in this module are wrappers around the standard math library +*/ + +#ifndef DETOURMATH_H +#define DETOURMATH_H + +#include <math.h> + +inline float dtMathFabsf(float x) { return fabsf(x); } +inline float dtMathSqrtf(float x) { return sqrtf(x); } +inline float dtMathFloorf(float x) { return floorf(x); } +inline float dtMathCeilf(float x) { return ceilf(x); } +inline float dtMathCosf(float x) { return cosf(x); } +inline float dtMathSinf(float x) { return sinf(x); } +inline float dtMathAtan2f(float y, float x) { return atan2f(y, x); } + +#endif diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMesh.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMesh.h new file mode 100644 index 0000000000..f50f705a2c --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMesh.h @@ -0,0 +1,777 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef DETOURNAVMESH_H +#define DETOURNAVMESH_H + +#include "DetourAlloc.h" +#include "DetourStatus.h" + +// Undefine (or define in a build cofnig) the following line to use 64bit polyref. +// Generally not needed, useful for very large worlds. +// Note: tiles build using 32bit refs are not compatible with 64bit refs! +#define DT_POLYREF64 1 + +#ifdef DT_POLYREF64 +// TODO: figure out a multiplatform version of uint64_t +// - maybe: https://code.google.com/p/msinttypes/ +// - or: http://www.azillionmonkeys.com/qed/pstdint.h +#if defined(WIN32) && !defined(__MINGW32__) +/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition +typedef unsigned __int64 uint64_d; +#else +#include <stdint.h> +#ifndef uint64_t +#ifdef __linux__ +#include <linux/types.h> +#endif +#endif +/// Do not rename back to uint64. Otherwise mac complains about typedef redefinition +typedef uint64_t uint64_d; +#endif +#endif + +// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. +// It is also recommended that you change dtHashRef() to a proper 64-bit hash. + +/// A handle to a polygon within a navigation mesh tile. +/// @ingroup detour +#ifdef DT_POLYREF64 +static const unsigned int DT_SALT_BITS = 12; +static const unsigned int DT_TILE_BITS = 21; +static const unsigned int DT_POLY_BITS = 31; +typedef uint64_d dtPolyRef; +#else +typedef unsigned int dtPolyRef; +#endif + +/// A handle to a tile within a navigation mesh. +/// @ingroup detour +#ifdef DT_POLYREF64 +typedef uint64_d dtTileRef; +#else +typedef unsigned int dtTileRef; +#endif + +/// The maximum number of vertices per navigation polygon. +/// @ingroup detour +static const int DT_VERTS_PER_POLYGON = 6; + +/// @{ +/// @name Tile Serialization Constants +/// These constants are used to detect whether a navigation tile's data +/// and state format is compatible with the current build. +/// + +/// A magic number used to detect compatibility of navigation tile data. +static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; + +/// A version number used to detect compatibility of navigation tile data. +static const int DT_NAVMESH_VERSION = 7; + +/// A magic number used to detect the compatibility of navigation tile states. +static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; + +/// A version number used to detect compatibility of navigation tile states. +static const int DT_NAVMESH_STATE_VERSION = 1; + +/// @} + +/// A flag that indicates that an entity links to an external entity. +/// (E.g. A polygon edge is a portal that links to another polygon.) +static const unsigned short DT_EXT_LINK = 0x8000; + +/// A value that indicates the entity does not link to anything. +static const unsigned int DT_NULL_LINK = 0xffffffff; + +/// A flag that indicates that an off-mesh connection can be traversed in both directions. (Is bidirectional.) +static const unsigned int DT_OFFMESH_CON_BIDIR = 1; + +/// The maximum number of user defined area ids. +/// @ingroup detour +static const int DT_MAX_AREAS = 64; + +/// Tile flags used for various functions and fields. +/// For an example, see dtNavMesh::addTile(). +enum dtTileFlags +{ + /// The navigation mesh owns the tile memory and is responsible for freeing it. + DT_TILE_FREE_DATA = 0x01, +}; + +/// Vertex flags returned by dtNavMeshQuery::findStraightPath. +enum dtStraightPathFlags +{ + DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path. + DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path. + DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection. +}; + +/// Options for dtNavMeshQuery::findStraightPath. +enum dtStraightPathOptions +{ + DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01, ///< Add a vertex at every polygon edge crossing where area changes. + DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02, ///< Add a vertex at every polygon edge crossing. +}; + + +/// Options for dtNavMeshQuery::initSlicedFindPath and updateSlicedFindPath +enum dtFindPathOptions +{ + DT_FINDPATH_ANY_ANGLE = 0x02, ///< use raycasts during pathfind to "shortcut" (raycast still consider costs) +}; + +/// Options for dtNavMeshQuery::raycast +enum dtRaycastOptions +{ + DT_RAYCAST_USE_COSTS = 0x01, ///< Raycast should calculate movement cost along the ray and fill RaycastHit::cost +}; + + +/// Limit raycasting during any angle pahfinding +/// The limit is given as a multiple of the character radius +static const float DT_RAY_CAST_LIMIT_PROPORTIONS = 50.0f; + +/// Flags representing the type of a navigation mesh polygon. +enum dtPolyTypes +{ + /// The polygon is a standard convex polygon that is part of the surface of the mesh. + DT_POLYTYPE_GROUND = 0, + /// The polygon is an off-mesh connection consisting of two vertices. + DT_POLYTYPE_OFFMESH_CONNECTION = 1, +}; + + +/// Defines a polygon within a dtMeshTile object. +/// @ingroup detour +struct dtPoly +{ + /// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.) + unsigned int firstLink; + + /// The indices of the polygon's vertices. + /// The actual vertices are located in dtMeshTile::verts. + unsigned short verts[DT_VERTS_PER_POLYGON]; + + /// Packed data representing neighbor polygons references and flags for each edge. + unsigned short neis[DT_VERTS_PER_POLYGON]; + + /// The user defined polygon flags. + unsigned short flags; + + /// The number of vertices in the polygon. + unsigned char vertCount; + + /// The bit packed area id and polygon type. + /// @note Use the structure's set and get methods to acess this value. + unsigned char areaAndtype; + + /// Sets the user defined area id. [Limit: < #DT_MAX_AREAS] + inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); } + + /// Sets the polygon type. (See: #dtPolyTypes.) + inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); } + + /// Gets the user defined area id. + inline unsigned char getArea() const { return areaAndtype & 0x3f; } + + /// Gets the polygon type. (See: #dtPolyTypes) + inline unsigned char getType() const { return areaAndtype >> 6; } +}; + +/// Defines the location of detail sub-mesh data within a dtMeshTile. +struct dtPolyDetail +{ + unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array. + unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array. + unsigned char vertCount; ///< The number of vertices in the sub-mesh. + unsigned char triCount; ///< The number of triangles in the sub-mesh. +}; + +/// Defines a link between polygons. +/// @note This structure is rarely if ever used by the end user. +/// @see dtMeshTile +struct dtLink +{ + dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.) + unsigned int next; ///< Index of the next link. + unsigned char edge; ///< Index of the polygon edge that owns this link. + unsigned char side; ///< If a boundary link, defines on which side the link is. + unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area. + unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area. +}; + +/// Bounding volume node. +/// @note This structure is rarely if ever used by the end user. +/// @see dtMeshTile +struct dtBVNode +{ + unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)] + unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)] + int i; ///< The node's index. (Negative for escape sequence.) +}; + +/// Defines an navigation mesh off-mesh connection within a dtMeshTile object. +/// An off-mesh connection is a user defined traversable connection made up to two vertices. +struct dtOffMeshConnection +{ + /// The endpoints of the connection. [(ax, ay, az, bx, by, bz)] + float pos[6]; + + /// The radius of the endpoints. [Limit: >= 0] + float rad; + + /// The polygon reference of the connection within the tile. + unsigned short poly; + + /// Link flags. + /// @note These are not the connection's user defined flags. Those are assigned via the + /// connection's dtPoly definition. These are link flags used for internal purposes. + unsigned char flags; + + /// End point side. + unsigned char side; + + /// The id of the offmesh connection. (User assigned when the navigation mesh is built.) + unsigned int userId; +}; + +/// Provides high level information related to a dtMeshTile object. +/// @ingroup detour +struct dtMeshHeader +{ + int magic; ///< Tile magic number. (Used to identify the data format.) + int version; ///< Tile data format version number. + int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer) + int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer) + int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer) + unsigned int userId; ///< The user defined id of the tile. + int polyCount; ///< The number of polygons in the tile. + int vertCount; ///< The number of vertices in the tile. + int maxLinkCount; ///< The number of allocated links. + int detailMeshCount; ///< The number of sub-meshes in the detail mesh. + + /// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.) + int detailVertCount; + + int detailTriCount; ///< The number of triangles in the detail mesh. + int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.) + int offMeshConCount; ///< The number of off-mesh connections. + int offMeshBase; ///< The index of the first polygon which is an off-mesh connection. + float walkableHeight; ///< The height of the agents using the tile. + float walkableRadius; ///< The radius of the agents using the tile. + float walkableClimb; ///< The maximum climb height of the agents using the tile. + float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)] + float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)] + + /// The bounding volume quantization factor. + float bvQuantFactor; +}; + +/// Defines a navigation mesh tile. +/// @ingroup detour +struct dtMeshTile +{ + unsigned int salt; ///< Counter describing modifications to the tile. + + unsigned int linksFreeList; ///< Index to the next free link. + dtMeshHeader* header; ///< The tile header. + dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount] + float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount] + dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount] + dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount] + + /// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount] + float* detailVerts; + + /// The detail mesh's triangles. [(vertA, vertB, vertC) * dtMeshHeader::detailTriCount] + unsigned char* detailTris; + + /// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount] + /// (Will be null if bounding volumes are disabled.) + dtBVNode* bvTree; + + dtOffMeshConnection* offMeshCons; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount] + + unsigned char* data; ///< The tile data. (Not directly accessed under normal situations.) + int dataSize; ///< Size of the tile data. + int flags; ///< Tile flags. (See: #dtTileFlags) + dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid. +private: + dtMeshTile(const dtMeshTile&); + dtMeshTile& operator=(const dtMeshTile&); +}; + +/// Configuration parameters used to define multi-tile navigation meshes. +/// The values are used to allocate space during the initialization of a navigation mesh. +/// @see dtNavMesh::init() +/// @ingroup detour +struct dtNavMeshParams +{ + float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)] + float tileWidth; ///< The width of each tile. (Along the x-axis.) + float tileHeight; ///< The height of each tile. (Along the z-axis.) + int maxTiles; ///< The maximum number of tiles the navigation mesh can contain. + int maxPolys; ///< The maximum number of polygons each tile can contain. +}; + +/// A navigation mesh based on tiles of convex polygons. +/// @ingroup detour +class dtNavMesh +{ +public: + dtNavMesh(); + ~dtNavMesh(); + + /// @{ + /// @name Initialization and Tile Management + + /// Initializes the navigation mesh for tiled use. + /// @param[in] params Initialization parameters. + /// @return The status flags for the operation. + dtStatus init(const dtNavMeshParams* params); + + /// Initializes the navigation mesh for single tile use. + /// @param[in] data Data of the new tile. (See: #dtCreateNavMeshData) + /// @param[in] dataSize The data size of the new tile. + /// @param[in] flags The tile flags. (See: #dtTileFlags) + /// @return The status flags for the operation. + /// @see dtCreateNavMeshData + dtStatus init(unsigned char* data, const int dataSize, const int flags); + + /// The navigation mesh initialization params. + const dtNavMeshParams* getParams() const; + + /// Adds a tile to the navigation mesh. + /// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData) + /// @param[in] dataSize Data size of the new tile mesh. + /// @param[in] flags Tile flags. (See: #dtTileFlags) + /// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0] + /// @param[out] result The tile reference. (If the tile was succesfully added.) [opt] + /// @return The status flags for the operation. + dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result); + + /// Removes the specified tile from the navigation mesh. + /// @param[in] ref The reference of the tile to remove. + /// @param[out] data Data associated with deleted tile. + /// @param[out] dataSize Size of the data associated with deleted tile. + /// @return The status flags for the operation. + dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize); + + /// @} + + /// @{ + /// @name Query Functions + + /// Calculates the tile grid location for the specified world position. + /// @param[in] pos The world position for the query. [(x, y, z)] + /// @param[out] tx The tile's x-location. (x, y) + /// @param[out] ty The tile's y-location. (x, y) + void calcTileLoc(const float* pos, int* tx, int* ty) const; + + /// Gets the tile at the specified grid location. + /// @param[in] x The tile's x-location. (x, y, layer) + /// @param[in] y The tile's y-location. (x, y, layer) + /// @param[in] layer The tile's layer. (x, y, layer) + /// @return The tile, or null if the tile does not exist. + const dtMeshTile* getTileAt(const int x, const int y, const int layer) const; + + /// Gets all tiles at the specified grid location. (All layers.) + /// @param[in] x The tile's x-location. (x, y) + /// @param[in] y The tile's y-location. (x, y) + /// @param[out] tiles A pointer to an array of tiles that will hold the result. + /// @param[in] maxTiles The maximum tiles the tiles parameter can hold. + /// @return The number of tiles returned in the tiles array. + int getTilesAt(const int x, const int y, + dtMeshTile const** tiles, const int maxTiles) const; + + /// Gets the tile reference for the tile at specified grid location. + /// @param[in] x The tile's x-location. (x, y, layer) + /// @param[in] y The tile's y-location. (x, y, layer) + /// @param[in] layer The tile's layer. (x, y, layer) + /// @return The tile reference of the tile, or 0 if there is none. + dtTileRef getTileRefAt(int x, int y, int layer) const; + + /// Gets the tile reference for the specified tile. + /// @param[in] tile The tile. + /// @return The tile reference of the tile. + dtTileRef getTileRef(const dtMeshTile* tile) const; + + /// Gets the tile for the specified tile reference. + /// @param[in] ref The tile reference of the tile to retrieve. + /// @return The tile for the specified reference, or null if the + /// reference is invalid. + const dtMeshTile* getTileByRef(dtTileRef ref) const; + + /// The maximum number of tiles supported by the navigation mesh. + /// @return The maximum number of tiles supported by the navigation mesh. + int getMaxTiles() const; + + /// Gets the tile at the specified index. + /// @param[in] i The tile index. [Limit: 0 >= index < #getMaxTiles()] + /// @return The tile at the specified index. + const dtMeshTile* getTile(int i) const; + + /// Gets the tile and polygon for the specified polygon reference. + /// @param[in] ref The reference for the a polygon. + /// @param[out] tile The tile containing the polygon. + /// @param[out] poly The polygon. + /// @return The status flags for the operation. + dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; + + /// Returns the tile and polygon for the specified polygon reference. + /// @param[in] ref A known valid reference for a polygon. + /// @param[out] tile The tile containing the polygon. + /// @param[out] poly The polygon. + void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; + + /// Checks the validity of a polygon reference. + /// @param[in] ref The polygon reference to check. + /// @return True if polygon reference is valid for the navigation mesh. + bool isValidPolyRef(dtPolyRef ref) const; + + /// Gets the polygon reference for the tile's base polygon. + /// @param[in] tile The tile. + /// @return The polygon reference for the base polygon in the specified tile. + dtPolyRef getPolyRefBase(const dtMeshTile* tile) const; + + /// Gets the endpoints for an off-mesh connection, ordered by "direction of travel". + /// @param[in] prevRef The reference of the polygon before the connection. + /// @param[in] polyRef The reference of the off-mesh connection polygon. + /// @param[out] startPos The start position of the off-mesh connection. [(x, y, z)] + /// @param[out] endPos The end position of the off-mesh connection. [(x, y, z)] + /// @return The status flags for the operation. + dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const; + + /// Gets the specified off-mesh connection. + /// @param[in] ref The polygon reference of the off-mesh connection. + /// @return The specified off-mesh connection, or null if the polygon reference is not valid. + const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const; + + /// @} + + /// @{ + /// @name State Management + /// These functions do not effect #dtTileRef or #dtPolyRef's. + + /// Sets the user defined flags for the specified polygon. + /// @param[in] ref The polygon reference. + /// @param[in] flags The new flags for the polygon. + /// @return The status flags for the operation. + dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags); + + /// Gets the user defined flags for the specified polygon. + /// @param[in] ref The polygon reference. + /// @param[out] resultFlags The polygon flags. + /// @return The status flags for the operation. + dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const; + + /// Sets the user defined area for the specified polygon. + /// @param[in] ref The polygon reference. + /// @param[in] area The new area id for the polygon. [Limit: < #DT_MAX_AREAS] + /// @return The status flags for the operation. + dtStatus setPolyArea(dtPolyRef ref, unsigned char area); + + /// Gets the user defined area for the specified polygon. + /// @param[in] ref The polygon reference. + /// @param[out] resultArea The area id for the polygon. + /// @return The status flags for the operation. + dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const; + + /// Gets the size of the buffer required by #storeTileState to store the specified tile's state. + /// @param[in] tile The tile. + /// @return The size of the buffer required to store the state. + int getTileStateSize(const dtMeshTile* tile) const; + + /// Stores the non-structural state of the tile in the specified buffer. (Flags, area ids, etc.) + /// @param[in] tile The tile. + /// @param[out] data The buffer to store the tile's state in. + /// @param[in] maxDataSize The size of the data buffer. [Limit: >= #getTileStateSize] + /// @return The status flags for the operation. + dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const; + + /// Restores the state of the tile. + /// @param[in] tile The tile. + /// @param[in] data The new state. (Obtained from #storeTileState.) + /// @param[in] maxDataSize The size of the state within the data buffer. + /// @return The status flags for the operation. + dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize); + + /// @} + + /// @{ + /// @name Encoding and Decoding + /// These functions are generally meant for internal use only. + + /// Derives a standard polygon reference. + /// @note This function is generally meant for internal use only. + /// @param[in] salt The tile's salt value. + /// @param[in] it The index of the tile. + /// @param[in] ip The index of the polygon within the tile. + inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const + { +#ifdef DT_POLYREF64 + return ((dtPolyRef)salt << (DT_POLY_BITS+DT_TILE_BITS)) | ((dtPolyRef)it << DT_POLY_BITS) | (dtPolyRef)ip; +#else + return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip; +#endif + } + + /// Decodes a standard polygon reference. + /// @note This function is generally meant for internal use only. + /// @param[in] ref The polygon reference to decode. + /// @param[out] salt The tile's salt value. + /// @param[out] it The index of the tile. + /// @param[out] ip The index of the polygon within the tile. + /// @see #encodePolyId + inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const + { +#ifdef DT_POLYREF64 + const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1; + const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1; + const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1; + salt = (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask); + it = (unsigned int)((ref >> DT_POLY_BITS) & tileMask); + ip = (unsigned int)(ref & polyMask); +#else + const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; + const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; + const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; + salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); + it = (unsigned int)((ref >> m_polyBits) & tileMask); + ip = (unsigned int)(ref & polyMask); +#endif + } + + /// Extracts a tile's salt value from the specified polygon reference. + /// @note This function is generally meant for internal use only. + /// @param[in] ref The polygon reference. + /// @see #encodePolyId + inline unsigned int decodePolyIdSalt(dtPolyRef ref) const + { +#ifdef DT_POLYREF64 + const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1; + return (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask); +#else + const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; + return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); +#endif + } + + /// Extracts the tile's index from the specified polygon reference. + /// @note This function is generally meant for internal use only. + /// @param[in] ref The polygon reference. + /// @see #encodePolyId + inline unsigned int decodePolyIdTile(dtPolyRef ref) const + { +#ifdef DT_POLYREF64 + const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1; + return (unsigned int)((ref >> DT_POLY_BITS) & tileMask); +#else + const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; + return (unsigned int)((ref >> m_polyBits) & tileMask); +#endif + } + + /// Extracts the polygon's index (within its tile) from the specified polygon reference. + /// @note This function is generally meant for internal use only. + /// @param[in] ref The polygon reference. + /// @see #encodePolyId + inline unsigned int decodePolyIdPoly(dtPolyRef ref) const + { +#ifdef DT_POLYREF64 + const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1; + return (unsigned int)(ref & polyMask); +#else + const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; + return (unsigned int)(ref & polyMask); +#endif + } + + /// @} + +private: + // Explicitly disabled copy constructor and copy assignment operator. + dtNavMesh(const dtNavMesh&); + dtNavMesh& operator=(const dtNavMesh&); + + /// Returns pointer to tile in the tile array. + dtMeshTile* getTile(int i); + + /// Returns neighbour tile based on side. + int getTilesAt(const int x, const int y, + dtMeshTile** tiles, const int maxTiles) const; + + /// Returns neighbour tile based on side. + int getNeighbourTilesAt(const int x, const int y, const int side, + dtMeshTile** tiles, const int maxTiles) const; + + /// Returns all polygons in neighbour tile based on portal defined by the segment. + int findConnectingPolys(const float* va, const float* vb, + const dtMeshTile* tile, int side, + dtPolyRef* con, float* conarea, int maxcon) const; + + /// Builds internal polygons links for a tile. + void connectIntLinks(dtMeshTile* tile); + /// Builds internal polygons links for a tile. + void baseOffMeshLinks(dtMeshTile* tile); + + /// Builds external polygon links for a tile. + void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side); + /// Builds external polygon links for a tile. + void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side); + + /// Removes external links at specified side. + void unconnectLinks(dtMeshTile* tile, dtMeshTile* target); + + + // TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding. + + /// Queries polygons within a tile. + int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, + dtPolyRef* polys, const int maxPolys) const; + /// Find nearest polygon within a tile. + dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, + const float* extents, float* nearestPt) const; + /// Returns closest point on polygon. + void closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const; + + dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice. + float m_orig[3]; ///< Origin of the tile (0,0) + float m_tileWidth, m_tileHeight; ///< Dimensions of each tile. + int m_maxTiles; ///< Max number of tiles. + int m_tileLutSize; ///< Tile hash lookup size (must be pot). + int m_tileLutMask; ///< Tile hash lookup mask. + + dtMeshTile** m_posLookup; ///< Tile hash lookup. + dtMeshTile* m_nextFree; ///< Freelist of tiles. + dtMeshTile* m_tiles; ///< List of tiles. + +#ifndef DT_POLYREF64 + unsigned int m_saltBits; ///< Number of salt bits in the tile ID. + unsigned int m_tileBits; ///< Number of tile bits in the tile ID. + unsigned int m_polyBits; ///< Number of poly bits in the tile ID. +#endif +}; + +/// Allocates a navigation mesh object using the Detour allocator. +/// @return A navigation mesh that is ready for initialization, or null on failure. +/// @ingroup detour +dtNavMesh* dtAllocNavMesh(); + +/// Frees the specified navigation mesh object using the Detour allocator. +/// @param[in] navmesh A navigation mesh allocated using #dtAllocNavMesh +/// @ingroup detour +void dtFreeNavMesh(dtNavMesh* navmesh); + +#endif // DETOURNAVMESH_H + +/////////////////////////////////////////////////////////////////////////// + +// This section contains detailed documentation for members that don't have +// a source file. It reduces clutter in the main section of the header. + +/** + +@typedef dtPolyRef +@par + +Polygon references are subject to the same invalidate/preserve/restore +rules that apply to #dtTileRef's. If the #dtTileRef for the polygon's +tile changes, the polygon reference becomes invalid. + +Changing a polygon's flags, area id, etc. does not impact its polygon +reference. + +@typedef dtTileRef +@par + +The following changes will invalidate a tile reference: + +- The referenced tile has been removed from the navigation mesh. +- The navigation mesh has been initialized using a different set + of #dtNavMeshParams. + +A tile reference is preserved/restored if the tile is added to a navigation +mesh initialized with the original #dtNavMeshParams and is added at the +original reference location. (E.g. The lastRef parameter is used with +dtNavMesh::addTile.) + +Basically, if the storage structure of a tile changes, its associated +tile reference changes. + + +@var unsigned short dtPoly::neis[DT_VERTS_PER_POLYGON] +@par + +Each entry represents data for the edge starting at the vertex of the same index. +E.g. The entry at index n represents the edge data for vertex[n] to vertex[n+1]. + +A value of zero indicates the edge has no polygon connection. (It makes up the +border of the navigation mesh.) + +The information can be extracted as follows: +@code +neighborRef = neis[n] & 0xff; // Get the neighbor polygon reference. + +if (neis[n] & #DT_EX_LINK) +{ + // The edge is an external (portal) edge. +} +@endcode + +@var float dtMeshHeader::bvQuantFactor +@par + +This value is used for converting between world and bounding volume coordinates. +For example: +@code +const float cs = 1.0f / tile->header->bvQuantFactor; +const dtBVNode* n = &tile->bvTree[i]; +if (n->i >= 0) +{ + // This is a leaf node. + float worldMinX = tile->header->bmin[0] + n->bmin[0]*cs; + float worldMinY = tile->header->bmin[0] + n->bmin[1]*cs; + // Etc... +} +@endcode + +@struct dtMeshTile +@par + +Tiles generally only exist within the context of a dtNavMesh object. + +Some tile content is optional. For example, a tile may not contain any +off-mesh connections. In this case the associated pointer will be null. + +If a detail mesh exists it will share vertices with the base polygon mesh. +Only the vertices unique to the detail mesh will be stored in #detailVerts. + +@warning Tiles returned by a dtNavMesh object are not guarenteed to be populated. +For example: The tile at a location might not have been loaded yet, or may have been removed. +In this case, pointers will be null. So if in doubt, check the polygon count in the +tile's header to determine if a tile has polygons defined. + +@var float dtOffMeshConnection::pos[6] +@par + +For a properly built navigation mesh, vertex A will always be within the bounds of the mesh. +Vertex B is not required to be within the bounds of the mesh. + +*/ diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMeshBuilder.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMeshBuilder.h new file mode 100644 index 0000000000..9425a7a789 --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMeshBuilder.h @@ -0,0 +1,149 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef DETOURNAVMESHBUILDER_H +#define DETOURNAVMESHBUILDER_H + +#include "DetourAlloc.h" + +/// Represents the source data used to build an navigation mesh tile. +/// @ingroup detour +struct dtNavMeshCreateParams +{ + + /// @name Polygon Mesh Attributes + /// Used to create the base navigation graph. + /// See #rcPolyMesh for details related to these attributes. + /// @{ + + const unsigned short* verts; ///< The polygon mesh vertices. [(x, y, z) * #vertCount] [Unit: vx] + int vertCount; ///< The number vertices in the polygon mesh. [Limit: >= 3] + const unsigned short* polys; ///< The polygon data. [Size: #polyCount * 2 * #nvp] + const unsigned short* polyFlags; ///< The user defined flags assigned to each polygon. [Size: #polyCount] + const unsigned char* polyAreas; ///< The user defined area ids assigned to each polygon. [Size: #polyCount] + int polyCount; ///< Number of polygons in the mesh. [Limit: >= 1] + int nvp; ///< Number maximum number of vertices per polygon. [Limit: >= 3] + + /// @} + /// @name Height Detail Attributes (Optional) + /// See #rcPolyMeshDetail for details related to these attributes. + /// @{ + + const unsigned int* detailMeshes; ///< The height detail sub-mesh data. [Size: 4 * #polyCount] + const float* detailVerts; ///< The detail mesh vertices. [Size: 3 * #detailVertsCount] [Unit: wu] + int detailVertsCount; ///< The number of vertices in the detail mesh. + const unsigned char* detailTris; ///< The detail mesh triangles. [Size: 4 * #detailTriCount] + int detailTriCount; ///< The number of triangles in the detail mesh. + + /// @} + /// @name Off-Mesh Connections Attributes (Optional) + /// Used to define a custom point-to-point edge within the navigation graph, an + /// off-mesh connection is a user defined traversable connection made up to two vertices, + /// at least one of which resides within a navigation mesh polygon. + /// @{ + + /// Off-mesh connection vertices. [(ax, ay, az, bx, by, bz) * #offMeshConCount] [Unit: wu] + const float* offMeshConVerts; + /// Off-mesh connection radii. [Size: #offMeshConCount] [Unit: wu] + const float* offMeshConRad; + /// User defined flags assigned to the off-mesh connections. [Size: #offMeshConCount] + const unsigned short* offMeshConFlags; + /// User defined area ids assigned to the off-mesh connections. [Size: #offMeshConCount] + const unsigned char* offMeshConAreas; + /// The permitted travel direction of the off-mesh connections. [Size: #offMeshConCount] + /// + /// 0 = Travel only from endpoint A to endpoint B.<br/> + /// #DT_OFFMESH_CON_BIDIR = Bidirectional travel. + const unsigned char* offMeshConDir; + /// The user defined ids of the off-mesh connection. [Size: #offMeshConCount] + const unsigned int* offMeshConUserID; + /// The number of off-mesh connections. [Limit: >= 0] + int offMeshConCount; + + /// @} + /// @name Tile Attributes + /// @note The tile grid/layer data can be left at zero if the destination is a single tile mesh. + /// @{ + + unsigned int userId; ///< The user defined id of the tile. + int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.) + int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.) + int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.) + float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu] + float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu] + + /// @} + /// @name General Configuration Attributes + /// @{ + + float walkableHeight; ///< The agent height. [Unit: wu] + float walkableRadius; ///< The agent radius. [Unit: wu] + float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu] + float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu] + float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu] + + /// True if a bounding volume tree should be built for the tile. + /// @note The BVTree is not normally needed for layered navigation meshes. + bool buildBvTree; + + /// @} +}; + +/// Builds navigation mesh tile data from the provided tile creation data. +/// @ingroup detour +/// @param[in] params Tile creation data. +/// @param[out] outData The resulting tile data. +/// @param[out] outDataSize The size of the tile data array. +/// @return True if the tile data was successfully created. +bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize); + +/// Swaps the endianess of the tile data's header (#dtMeshHeader). +/// @param[in,out] data The tile data array. +/// @param[in] dataSize The size of the data array. +bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize); + +/// Swaps endianess of the tile data. +/// @param[in,out] data The tile data array. +/// @param[in] dataSize The size of the data array. +bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize); + +#endif // DETOURNAVMESHBUILDER_H + +// This section contains detailed documentation for members that don't have +// a source file. It reduces clutter in the main section of the header. + +/** + +@struct dtNavMeshCreateParams +@par + +This structure is used to marshal data between the Recast mesh generation pipeline and Detour navigation components. + +See the rcPolyMesh and rcPolyMeshDetail documentation for detailed information related to mesh structure. + +Units are usually in voxels (vx) or world units (wu). The units for voxels, grid size, and cell size +are all based on the values of #cs and #ch. + +The standard navigation mesh build process is to create tile data using dtCreateNavMeshData, then add the tile +to a navigation mesh using either the dtNavMesh single tile <tt>init()</tt> function or the dtNavMesh::addTile() +function. + +@see dtCreateNavMeshData + +*/ + diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMeshQuery.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMeshQuery.h new file mode 100644 index 0000000000..61541e83df --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNavMeshQuery.h @@ -0,0 +1,575 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef DETOURNAVMESHQUERY_H +#define DETOURNAVMESHQUERY_H + +#include "DetourNavMesh.h" +#include "DetourStatus.h" + + +// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter. +// On certain platforms indirect or virtual function call is expensive. The default +// setting is to use non-virtual functions, the actual implementations of the functions +// are declared as inline for maximum speed. + +//#define DT_VIRTUAL_QUERYFILTER 1 + +/// Defines polygon filtering and traversal costs for navigation mesh query operations. +/// @ingroup detour +class dtQueryFilter +{ + float m_areaCost[DT_MAX_AREAS]; ///< Cost per area type. (Used by default implementation.) + unsigned short m_includeFlags; ///< Flags for polygons that can be visited. (Used by default implementation.) + unsigned short m_excludeFlags; ///< Flags for polygons that should not be visted. (Used by default implementation.) + +public: + dtQueryFilter(); + +#ifdef DT_VIRTUAL_QUERYFILTER + virtual ~dtQueryFilter() { } +#endif + + /// Returns true if the polygon can be visited. (I.e. Is traversable.) + /// @param[in] ref The reference id of the polygon test. + /// @param[in] tile The tile containing the polygon. + /// @param[in] poly The polygon to test. +#ifdef DT_VIRTUAL_QUERYFILTER + virtual bool passFilter(const dtPolyRef ref, + const dtMeshTile* tile, + const dtPoly* poly) const; +#else + bool passFilter(const dtPolyRef ref, + const dtMeshTile* tile, + const dtPoly* poly) const; +#endif + + /// Returns cost to move from the beginning to the end of a line segment + /// that is fully contained within a polygon. + /// @param[in] pa The start position on the edge of the previous and current polygon. [(x, y, z)] + /// @param[in] pb The end position on the edge of the current and next polygon. [(x, y, z)] + /// @param[in] prevRef The reference id of the previous polygon. [opt] + /// @param[in] prevTile The tile containing the previous polygon. [opt] + /// @param[in] prevPoly The previous polygon. [opt] + /// @param[in] curRef The reference id of the current polygon. + /// @param[in] curTile The tile containing the current polygon. + /// @param[in] curPoly The current polygon. + /// @param[in] nextRef The refernece id of the next polygon. [opt] + /// @param[in] nextTile The tile containing the next polygon. [opt] + /// @param[in] nextPoly The next polygon. [opt] +#ifdef DT_VIRTUAL_QUERYFILTER + virtual float getCost(const float* pa, const float* pb, + const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, + const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, + const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; +#else + float getCost(const float* pa, const float* pb, + const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, + const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, + const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; +#endif + + /// @name Getters and setters for the default implementation data. + ///@{ + + /// Returns the traversal cost of the area. + /// @param[in] i The id of the area. + /// @returns The traversal cost of the area. + inline float getAreaCost(const int i) const { return m_areaCost[i]; } + + /// Sets the traversal cost of the area. + /// @param[in] i The id of the area. + /// @param[in] cost The new cost of traversing the area. + inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; } + + /// Returns the include flags for the filter. + /// Any polygons that include one or more of these flags will be + /// included in the operation. + inline unsigned short getIncludeFlags() const { return m_includeFlags; } + + /// Sets the include flags for the filter. + /// @param[in] flags The new flags. + inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; } + + /// Returns the exclude flags for the filter. + /// Any polygons that include one ore more of these flags will be + /// excluded from the operation. + inline unsigned short getExcludeFlags() const { return m_excludeFlags; } + + /// Sets the exclude flags for the filter. + /// @param[in] flags The new flags. + inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; } + + ///@} + +}; + + + +/// Provides information about raycast hit +/// filled by dtNavMeshQuery::raycast +/// @ingroup detour +struct dtRaycastHit +{ + /// The hit parameter. (FLT_MAX if no wall hit.) + float t; + + /// hitNormal The normal of the nearest wall hit. [(x, y, z)] + float hitNormal[3]; + + /// The index of the edge on the final polygon where the wall was hit. + int hitEdgeIndex; + + /// Pointer to an array of reference ids of the visited polygons. [opt] + dtPolyRef* path; + + /// The number of visited polygons. [opt] + int pathCount; + + /// The maximum number of polygons the @p path array can hold. + int maxPath; + + /// The cost of the path until hit. + float pathCost; +}; + +/// Provides custom polygon query behavior. +/// Used by dtNavMeshQuery::queryPolygons. +/// @ingroup detour +class dtPolyQuery +{ +public: + virtual ~dtPolyQuery() { } + + /// Called for each batch of unique polygons touched by the search area in dtNavMeshQuery::queryPolygons. + /// This can be called multiple times for a single query. + virtual void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) = 0; +}; + +/// Provides the ability to perform pathfinding related queries against +/// a navigation mesh. +/// @ingroup detour +class dtNavMeshQuery +{ +public: + dtNavMeshQuery(); + ~dtNavMeshQuery(); + + /// Initializes the query object. + /// @param[in] nav Pointer to the dtNavMesh object to use for all queries. + /// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65535] + /// @returns The status flags for the query. + dtStatus init(const dtNavMesh* nav, const int maxNodes); + + /// @name Standard Pathfinding Functions + // /@{ + + /// Finds a path from the start polygon to the end polygon. + /// @param[in] startRef The refrence id of the start polygon. + /// @param[in] endRef The reference id of the end polygon. + /// @param[in] startPos A position within the start polygon. [(x, y, z)] + /// @param[in] endPos A position within the end polygon. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) + /// [(polyRef) * @p pathCount] + /// @param[out] pathCount The number of polygons returned in the @p path array. + /// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 1] + dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef, + const float* startPos, const float* endPos, + const dtQueryFilter* filter, + dtPolyRef* path, int* pathCount, const int maxPath) const; + + /// Finds the straight path from the start to the end position within the polygon corridor. + /// @param[in] startPos Path start position. [(x, y, z)] + /// @param[in] endPos Path end position. [(x, y, z)] + /// @param[in] path An array of polygon references that represent the path corridor. + /// @param[in] pathSize The number of polygons in the @p path array. + /// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount]. + /// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt] + /// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt] + /// @param[out] straightPathCount The number of points in the straight path. + /// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0] + /// @param[in] options Query options. (see: #dtStraightPathOptions) + /// @returns The status flags for the query. + dtStatus findStraightPath(const float* startPos, const float* endPos, + const dtPolyRef* path, const int pathSize, + float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, + int* straightPathCount, const int maxStraightPath, const int options = 0) const; + + ///@} + /// @name Sliced Pathfinding Functions + /// Common use case: + /// -# Call initSlicedFindPath() to initialize the sliced path query. + /// -# Call updateSlicedFindPath() until it returns complete. + /// -# Call finalizeSlicedFindPath() to get the path. + ///@{ + + /// Intializes a sliced path query. + /// @param[in] startRef The refrence id of the start polygon. + /// @param[in] endRef The reference id of the end polygon. + /// @param[in] startPos A position within the start polygon. [(x, y, z)] + /// @param[in] endPos A position within the end polygon. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[in] options query options (see: #dtFindPathOptions) + /// @returns The status flags for the query. + dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, + const float* startPos, const float* endPos, + const dtQueryFilter* filter, const unsigned int options = 0); + + /// Updates an in-progress sliced path query. + /// @param[in] maxIter The maximum number of iterations to perform. + /// @param[out] doneIters The actual number of iterations completed. [opt] + /// @returns The status flags for the query. + dtStatus updateSlicedFindPath(const int maxIter, int* doneIters); + + /// Finalizes and returns the results of a sliced path query. + /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) + /// [(polyRef) * @p pathCount] + /// @param[out] pathCount The number of polygons returned in the @p path array. + /// @param[in] maxPath The max number of polygons the path array can hold. [Limit: >= 1] + /// @returns The status flags for the query. + dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath); + + /// Finalizes and returns the results of an incomplete sliced path query, returning the path to the furthest + /// polygon on the existing path that was visited during the search. + /// @param[in] existing An array of polygon references for the existing path. + /// @param[in] existingSize The number of polygon in the @p existing array. + /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) + /// [(polyRef) * @p pathCount] + /// @param[out] pathCount The number of polygons returned in the @p path array. + /// @param[in] maxPath The max number of polygons the @p path array can hold. [Limit: >= 1] + /// @returns The status flags for the query. + dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, + dtPolyRef* path, int* pathCount, const int maxPath); + + ///@} + /// @name Dijkstra Search Functions + /// @{ + + /// Finds the polygons along the navigation graph that touch the specified circle. + /// @param[in] startRef The reference id of the polygon where the search starts. + /// @param[in] centerPos The center of the search circle. [(x, y, z)] + /// @param[in] radius The radius of the search circle. + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] resultRef The reference ids of the polygons touched by the circle. [opt] + /// @param[out] resultParent The reference ids of the parent polygons for each result. + /// Zero if a result polygon has no parent. [opt] + /// @param[out] resultCost The search cost from @p centerPos to the polygon. [opt] + /// @param[out] resultCount The number of polygons found. [opt] + /// @param[in] maxResult The maximum number of polygons the result arrays can hold. + /// @returns The status flags for the query. + dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, + const dtQueryFilter* filter, + dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, + int* resultCount, const int maxResult) const; + + /// Finds the polygons along the naviation graph that touch the specified convex polygon. + /// @param[in] startRef The reference id of the polygon where the search starts. + /// @param[in] verts The vertices describing the convex polygon. (CCW) + /// [(x, y, z) * @p nverts] + /// @param[in] nverts The number of vertices in the polygon. + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] resultRef The reference ids of the polygons touched by the search polygon. [opt] + /// @param[out] resultParent The reference ids of the parent polygons for each result. Zero if a + /// result polygon has no parent. [opt] + /// @param[out] resultCost The search cost from the centroid point to the polygon. [opt] + /// @param[out] resultCount The number of polygons found. + /// @param[in] maxResult The maximum number of polygons the result arrays can hold. + /// @returns The status flags for the query. + dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, + const dtQueryFilter* filter, + dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, + int* resultCount, const int maxResult) const; + + /// Gets a path from the explored nodes in the previous search. + /// @param[in] endRef The reference id of the end polygon. + /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) + /// [(polyRef) * @p pathCount] + /// @param[out] pathCount The number of polygons returned in the @p path array. + /// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 0] + /// @returns The status flags. Returns DT_FAILURE | DT_INVALID_PARAM if any parameter is wrong, or if + /// @p endRef was not explored in the previous search. Returns DT_SUCCESS | DT_BUFFER_TOO_SMALL + /// if @p path cannot contain the entire path. In this case it is filled to capacity with a partial path. + /// Otherwise returns DT_SUCCESS. + /// @remarks The result of this function depends on the state of the query object. For that reason it should only + /// be used immediately after one of the two Dijkstra searches, findPolysAroundCircle or findPolysAroundShape. + dtStatus getPathFromDijkstraSearch(dtPolyRef endRef, dtPolyRef* path, int* pathCount, int maxPath) const; + + /// @} + /// @name Local Query Functions + ///@{ + + /// Finds the polygon nearest to the specified center point. + /// @param[in] center The center of the search box. [(x, y, z)] + /// @param[in] extents The search distance along each axis. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] nearestRef The reference id of the nearest polygon. + /// @param[out] nearestPt The nearest point on the polygon. [opt] [(x, y, z)] + /// @returns The status flags for the query. + dtStatus findNearestPoly(const float* center, const float* extents, + const dtQueryFilter* filter, + dtPolyRef* nearestRef, float* nearestPt) const; + + /// Finds polygons that overlap the search box. + /// @param[in] center The center of the search box. [(x, y, z)] + /// @param[in] extents The search distance along each axis. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] polys The reference ids of the polygons that overlap the query box. + /// @param[out] polyCount The number of polygons in the search result. + /// @param[in] maxPolys The maximum number of polygons the search result can hold. + /// @returns The status flags for the query. + dtStatus queryPolygons(const float* center, const float* extents, + const dtQueryFilter* filter, + dtPolyRef* polys, int* polyCount, const int maxPolys) const; + + /// Finds polygons that overlap the search box. + /// @param[in] center The center of the search box. [(x, y, z)] + /// @param[in] extents The search distance along each axis. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[in] query The query. Polygons found will be batched together and passed to this query. + dtStatus queryPolygons(const float* center, const float* extents, + const dtQueryFilter* filter, dtPolyQuery* query) const; + + /// Finds the non-overlapping navigation polygons in the local neighbourhood around the center position. + /// @param[in] startRef The reference id of the polygon where the search starts. + /// @param[in] centerPos The center of the query circle. [(x, y, z)] + /// @param[in] radius The radius of the query circle. + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] resultRef The reference ids of the polygons touched by the circle. + /// @param[out] resultParent The reference ids of the parent polygons for each result. + /// Zero if a result polygon has no parent. [opt] + /// @param[out] resultCount The number of polygons found. + /// @param[in] maxResult The maximum number of polygons the result arrays can hold. + /// @returns The status flags for the query. + dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, + const dtQueryFilter* filter, + dtPolyRef* resultRef, dtPolyRef* resultParent, + int* resultCount, const int maxResult) const; + + /// Moves from the start to the end position constrained to the navigation mesh. + /// @param[in] startRef The reference id of the start polygon. + /// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)] + /// @param[in] endPos The desired end position of the mover. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] resultPos The result position of the mover. [(x, y, z)] + /// @param[out] visited The reference ids of the polygons visited during the move. + /// @param[out] visitedCount The number of polygons visited during the move. + /// @param[in] maxVisitedSize The maximum number of polygons the @p visited array can hold. + /// @returns The status flags for the query. + dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, + const dtQueryFilter* filter, + float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const; + + /// Casts a 'walkability' ray along the surface of the navigation mesh from + /// the start position toward the end position. + /// @note A wrapper around raycast(..., RaycastHit*). Retained for backward compatibility. + /// @param[in] startRef The reference id of the start polygon. + /// @param[in] startPos A position within the start polygon representing + /// the start of the ray. [(x, y, z)] + /// @param[in] endPos The position to cast the ray toward. [(x, y, z)] + /// @param[out] t The hit parameter. (FLT_MAX if no wall hit.) + /// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] path The reference ids of the visited polygons. [opt] + /// @param[out] pathCount The number of visited polygons. [opt] + /// @param[in] maxPath The maximum number of polygons the @p path array can hold. + /// @returns The status flags for the query. + dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos, + const dtQueryFilter* filter, + float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const; + + /// Casts a 'walkability' ray along the surface of the navigation mesh from + /// the start position toward the end position. + /// @param[in] startRef The reference id of the start polygon. + /// @param[in] startPos A position within the start polygon representing + /// the start of the ray. [(x, y, z)] + /// @param[in] endPos The position to cast the ray toward. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[in] flags govern how the raycast behaves. See dtRaycastOptions + /// @param[out] hit Pointer to a raycast hit structure which will be filled by the results. + /// @param[in] prevRef parent of start ref. Used during for cost calculation [opt] + /// @returns The status flags for the query. + dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos, + const dtQueryFilter* filter, const unsigned int options, + dtRaycastHit* hit, dtPolyRef prevRef = 0) const; + + + /// Finds the distance from the specified position to the nearest polygon wall. + /// @param[in] startRef The reference id of the polygon containing @p centerPos. + /// @param[in] centerPos The center of the search circle. [(x, y, z)] + /// @param[in] maxRadius The radius of the search circle. + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] hitDist The distance to the nearest wall from @p centerPos. + /// @param[out] hitPos The nearest position on the wall that was hit. [(x, y, z)] + /// @param[out] hitNormal The normalized ray formed from the wall point to the + /// source point. [(x, y, z)] + /// @returns The status flags for the query. + dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, + const dtQueryFilter* filter, + float* hitDist, float* hitPos, float* hitNormal) const; + + /// Returns the segments for the specified polygon, optionally including portals. + /// @param[in] ref The reference id of the polygon. + /// @param[in] filter The polygon filter to apply to the query. + /// @param[out] segmentVerts The segments. [(ax, ay, az, bx, by, bz) * segmentCount] + /// @param[out] segmentRefs The reference ids of each segment's neighbor polygon. + /// Or zero if the segment is a wall. [opt] [(parentRef) * @p segmentCount] + /// @param[out] segmentCount The number of segments returned. + /// @param[in] maxSegments The maximum number of segments the result arrays can hold. + /// @returns The status flags for the query. + dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, + float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, + const int maxSegments) const; + + /// Returns random location on navmesh. + /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon. + /// @param[in] filter The polygon filter to apply to the query. + /// @param[in] frand Function returning a random number [0..1). + /// @param[out] randomRef The reference id of the random location. + /// @param[out] randomPt The random location. + /// @returns The status flags for the query. + dtStatus findRandomPoint(const dtQueryFilter* filter, float (*frand)(), + dtPolyRef* randomRef, float* randomPt) const; + + /// Returns random location on navmesh within the reach of specified location. + /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon. + /// The location is not exactly constrained by the circle, but it limits the visited polygons. + /// @param[in] startRef The reference id of the polygon where the search starts. + /// @param[in] centerPos The center of the search circle. [(x, y, z)] + /// @param[in] filter The polygon filter to apply to the query. + /// @param[in] frand Function returning a random number [0..1). + /// @param[out] randomRef The reference id of the random location. + /// @param[out] randomPt The random location. [(x, y, z)] + /// @returns The status flags for the query. + dtStatus findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius, + const dtQueryFilter* filter, float (*frand)(), + dtPolyRef* randomRef, float* randomPt) const; + + /// Finds the closest point on the specified polygon. + /// @param[in] ref The reference id of the polygon. + /// @param[in] pos The position to check. [(x, y, z)] + /// @param[out] closest The closest point on the polygon. [(x, y, z)] + /// @param[out] posOverPoly True of the position is over the polygon. + /// @returns The status flags for the query. + dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const; + + /// Returns a point on the boundary closest to the source point if the source point is outside the + /// polygon's xz-bounds. + /// @param[in] ref The reference id to the polygon. + /// @param[in] pos The position to check. [(x, y, z)] + /// @param[out] closest The closest point. [(x, y, z)] + /// @returns The status flags for the query. + dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const; + + /// Gets the height of the polygon at the provided position using the height detail. (Most accurate.) + /// @param[in] ref The reference id of the polygon. + /// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)] + /// @param[out] height The height at the surface of the polygon. + /// @returns The status flags for the query. + dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const; + + /// @} + /// @name Miscellaneous Functions + /// @{ + + /// Returns true if the polygon reference is valid and passes the filter restrictions. + /// @param[in] ref The polygon reference to check. + /// @param[in] filter The filter to apply. + bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const; + + /// Returns true if the polygon reference is in the closed list. + /// @param[in] ref The reference id of the polygon to check. + /// @returns True if the polygon is in closed list. + bool isInClosedList(dtPolyRef ref) const; + + /// Gets the node pool. + /// @returns The node pool. + class dtNodePool* getNodePool() const { return m_nodePool; } + + /// Gets the navigation mesh the query object is using. + /// @return The navigation mesh the query object is using. + const dtNavMesh* getAttachedNavMesh() const { return m_nav; } + + /// @} + +private: + // Explicitly disabled copy constructor and copy assignment operator + dtNavMeshQuery(const dtNavMeshQuery&); + dtNavMeshQuery& operator=(const dtNavMeshQuery&); + + /// Queries polygons within a tile. + void queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, + const dtQueryFilter* filter, dtPolyQuery* query) const; + + /// Returns portal points between two polygons. + dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, + unsigned char& fromType, unsigned char& toType) const; + dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, + dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, + float* left, float* right) const; + + /// Returns edge mid point between two polygons. + dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const; + dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, + dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, + float* mid) const; + + // Appends vertex to a straight path + dtStatus appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref, + float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, + int* straightPathCount, const int maxStraightPath) const; + + // Appends intermediate portal points to a straight path. + dtStatus appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path, + float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, + int* straightPathCount, const int maxStraightPath, const int options) const; + + // Gets the path leading to the specified end node. + dtStatus getPathToNode(struct dtNode* endNode, dtPolyRef* path, int* pathCount, int maxPath) const; + + const dtNavMesh* m_nav; ///< Pointer to navmesh data. + + struct dtQueryData + { + dtStatus status; + struct dtNode* lastBestNode; + float lastBestNodeCost; + dtPolyRef startRef, endRef; + float startPos[3], endPos[3]; + const dtQueryFilter* filter; + unsigned int options; + float raycastLimitSqr; + }; + dtQueryData m_query; ///< Sliced query state. + + class dtNodePool* m_tinyNodePool; ///< Pointer to small node pool. + class dtNodePool* m_nodePool; ///< Pointer to node pool. + class dtNodeQueue* m_openList; ///< Pointer to open list queue. +}; + +/// Allocates a query object using the Detour allocator. +/// @return An allocated query object, or null on failure. +/// @ingroup detour +dtNavMeshQuery* dtAllocNavMeshQuery(); + +/// Frees the specified query object using the Detour allocator. +/// @param[in] query A query object allocated using #dtAllocNavMeshQuery +/// @ingroup detour +void dtFreeNavMeshQuery(dtNavMeshQuery* query); + +#endif // DETOURNAVMESHQUERY_H diff --git a/deps/recastnavigation/Detour/DetourNode.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNode.h index e46254fb50..db09747080 100644 --- a/deps/recastnavigation/Detour/DetourNode.h +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourNode.h @@ -25,48 +25,56 @@ enum dtNodeFlags { DT_NODE_OPEN = 0x01, DT_NODE_CLOSED = 0x02, + DT_NODE_PARENT_DETACHED = 0x04, // parent of the node is not adjacent. Found using raycast. }; typedef unsigned short dtNodeIndex; -static const dtNodeIndex DT_NULL_IDX = ~0; +static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0; +static const int DT_NODE_PARENT_BITS = 24; +static const int DT_NODE_STATE_BITS = 2; struct dtNode { - float pos[3]; // Position of the node. - float cost; // Cost from previous node to current node. - float total; // Cost up to the node. - unsigned int pidx : 30; // Index to parent node. - unsigned int flags : 2; // Node flags 0/open/closed. - dtPolyRef id; // Polygon ref the node corresponds to. + float pos[3]; ///< Position of the node. + float cost; ///< Cost from previous node to current node. + float total; ///< Cost up to the node. + unsigned int pidx : DT_NODE_PARENT_BITS; ///< Index to parent node. + unsigned int state : DT_NODE_STATE_BITS; ///< extra state information. A polyRef can have multiple nodes with different extra info. see DT_MAX_STATES_PER_NODE + unsigned int flags : 3; ///< Node flags. A combination of dtNodeFlags. + dtPolyRef id; ///< Polygon ref the node corresponds to. }; +static const int DT_MAX_STATES_PER_NODE = 1 << DT_NODE_STATE_BITS; // number of extra states per node. See dtNode::state class dtNodePool { public: dtNodePool(int maxNodes, int hashSize); ~dtNodePool(); - inline void operator=(const dtNodePool&) {} void clear(); - dtNode* getNode(dtPolyRef id); - dtNode* findNode(dtPolyRef id); + + // Get a dtNode by ref and extra state information. If there is none then - allocate + // There can be more than one node for the same polyRef but with different extra state information + dtNode* getNode(dtPolyRef id, unsigned char state=0); + dtNode* findNode(dtPolyRef id, unsigned char state); + unsigned int findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes); inline unsigned int getNodeIdx(const dtNode* node) const { if (!node) return 0; - return (unsigned int)(node - m_nodes)+1; + return (unsigned int)(node - m_nodes) + 1; } inline dtNode* getNodeAtIdx(unsigned int idx) { if (!idx) return 0; - return &m_nodes[idx-1]; + return &m_nodes[idx - 1]; } inline const dtNode* getNodeAtIdx(unsigned int idx) const { if (!idx) return 0; - return &m_nodes[idx-1]; + return &m_nodes[idx - 1]; } inline int getMemUsed() const @@ -82,8 +90,12 @@ public: inline int getHashSize() const { return m_hashSize; } inline dtNodeIndex getFirst(int bucket) const { return m_first[bucket]; } inline dtNodeIndex getNext(int i) const { return m_next[i]; } + inline int getNodeCount() const { return m_nodeCount; } private: + // Explicitly disabled copy constructor and copy assignment operator. + dtNodePool(const dtNodePool&); + dtNodePool& operator=(const dtNodePool&); dtNode* m_nodes; dtNodeIndex* m_first; @@ -98,17 +110,10 @@ class dtNodeQueue public: dtNodeQueue(int n); ~dtNodeQueue(); - inline void operator=(dtNodeQueue&) {} - inline void clear() - { - m_size = 0; - } + inline void clear() { m_size = 0; } - inline dtNode* top() - { - return m_heap[0]; - } + inline dtNode* top() { return m_heap[0]; } inline dtNode* pop() { @@ -141,12 +146,16 @@ public: inline int getMemUsed() const { return sizeof(*this) + - sizeof(dtNode*)*(m_capacity+1); + sizeof(dtNode*) * (m_capacity + 1); } inline int getCapacity() const { return m_capacity; } private: + // Explicitly disabled copy constructor and copy assignment operator. + dtNodeQueue(const dtNodeQueue&); + dtNodeQueue& operator=(const dtNodeQueue&); + void bubbleUp(int i, dtNode* node); void trickleDown(int i, dtNode* node); @@ -156,4 +165,4 @@ private: }; -#endif // DETOURNODE_H
\ No newline at end of file +#endif // DETOURNODE_H diff --git a/modules/worldengine/deps/recastnavigation/Detour/Include/DetourStatus.h b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourStatus.h new file mode 100644 index 0000000000..af822c4a92 --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Detour/Include/DetourStatus.h @@ -0,0 +1,64 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef DETOURSTATUS_H +#define DETOURSTATUS_H + +typedef unsigned int dtStatus; + +// High level status. +static const unsigned int DT_FAILURE = 1u << 31; // Operation failed. +static const unsigned int DT_SUCCESS = 1u << 30; // Operation succeed. +static const unsigned int DT_IN_PROGRESS = 1u << 29; // Operation still in progress. + +// Detail information for status. +static const unsigned int DT_STATUS_DETAIL_MASK = 0x0ffffff; +static const unsigned int DT_WRONG_MAGIC = 1 << 0; // Input data is not recognized. +static const unsigned int DT_WRONG_VERSION = 1 << 1; // Input data is in wrong version. +static const unsigned int DT_OUT_OF_MEMORY = 1 << 2; // Operation ran out of memory. +static const unsigned int DT_INVALID_PARAM = 1 << 3; // An input parameter was invalid. +static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the query was too small to store all results. +static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search. +static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess. + + +// Returns true of status is success. +inline bool dtStatusSucceed(dtStatus status) +{ + return (status & DT_SUCCESS) != 0; +} + +// Returns true of status is failure. +inline bool dtStatusFailed(dtStatus status) +{ + return (status & DT_FAILURE) != 0; +} + +// Returns true of status is in progress. +inline bool dtStatusInProgress(dtStatus status) +{ + return (status & DT_IN_PROGRESS) != 0; +} + +// Returns true if specific detail is set. +inline bool dtStatusDetail(dtStatus status, unsigned int detail) +{ + return (status & detail) != 0; +} + +#endif // DETOURSTATUS_H diff --git a/deps/recastnavigation/Detour/DetourAlloc.cpp b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourAlloc.cpp index 5f671df5bd..d9ad1fc013 100644 --- a/deps/recastnavigation/Detour/DetourAlloc.cpp +++ b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourAlloc.cpp @@ -19,7 +19,7 @@ #include <stdlib.h> #include "DetourAlloc.h" -static void *dtAllocDefault(int size, dtAllocHint) +static void *dtAllocDefault(size_t size, dtAllocHint) { return malloc(size); } @@ -38,7 +38,7 @@ void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc) sFreeFunc = freeFunc ? freeFunc : dtFreeDefault; } -void* dtAlloc(int size, dtAllocHint hint) +void* dtAlloc(size_t size, dtAllocHint hint) { return sAllocFunc(size, hint); } diff --git a/deps/recastnavigation/Detour/DetourCommon.cpp b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourCommon.cpp index c0b973e4a7..26fe65c178 100644 --- a/deps/recastnavigation/Detour/DetourCommon.cpp +++ b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourCommon.cpp @@ -16,16 +16,11 @@ // 3. This notice may not be removed or altered from any source distribution. // -#include <math.h> #include "DetourCommon.h" +#include "DetourMath.h" ////////////////////////////////////////////////////////////////////////////////////////// -float dtSqrt(float x) -{ - return sqrtf(x); -} - void dtClosestPtPointTriangle(float* closest, const float* p, const float* a, const float* b, const float* c) { @@ -238,6 +233,9 @@ bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b return false; } +/// @par +/// +/// All points are projected onto the xz-plane, so the y-values are ignored. bool dtPointInPolygon(const float* pt, const float* verts, const int nverts) { // TODO: Replace pnpoly with triArea2D tests? @@ -291,6 +289,9 @@ inline bool overlapRange(const float amin, const float amax, return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true; } +/// @par +/// +/// All vertices are projected onto the xz-plane, so the y-values are ignored. bool dtOverlapPolyPoly2D(const float* polya, const int npolya, const float* polyb, const int npolyb) { @@ -327,3 +328,61 @@ bool dtOverlapPolyPoly2D(const float* polya, const int npolya, return true; } +// Returns a random point in a convex polygon. +// Adapted from Graphics Gems article. +void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas, + const float s, const float t, float* out) +{ + // Calc triangle araes + float areasum = 0.0f; + for (int i = 2; i < npts; i++) { + areas[i] = dtTriArea2D(&pts[0], &pts[(i-1)*3], &pts[i*3]); + areasum += dtMax(0.001f, areas[i]); + } + // Find sub triangle weighted by area. + const float thr = s*areasum; + float acc = 0.0f; + float u = 0.0f; + int tri = 0; + for (int i = 2; i < npts; i++) { + const float dacc = areas[i]; + if (thr >= acc && thr < (acc+dacc)) + { + u = (thr - acc) / dacc; + tri = i; + break; + } + acc += dacc; + } + + float v = dtMathSqrtf(t); + + const float a = 1 - v; + const float b = (1 - u) * v; + const float c = u * v; + const float* pa = &pts[0]; + const float* pb = &pts[(tri-1)*3]; + const float* pc = &pts[tri*3]; + + out[0] = a*pa[0] + b*pb[0] + c*pc[0]; + out[1] = a*pa[1] + b*pb[1] + c*pc[1]; + out[2] = a*pa[2] + b*pb[2] + c*pc[2]; +} + +inline float vperpXZ(const float* a, const float* b) { return a[0]*b[2] - a[2]*b[0]; } + +bool dtIntersectSegSeg2D(const float* ap, const float* aq, + const float* bp, const float* bq, + float& s, float& t) +{ + float u[3], v[3], w[3]; + dtVsub(u,aq,ap); + dtVsub(v,bq,bp); + dtVsub(w,ap,bp); + float d = vperpXZ(u,v); + if (fabsf(d) < 1e-6f) return false; + s = vperpXZ(v,w) / d; + t = vperpXZ(u,w) / d; + return true; +} + diff --git a/deps/recastnavigation/Detour/DetourNavMesh.cpp b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNavMesh.cpp index 95af28797d..f70fa04729 100644 --- a/deps/recastnavigation/Detour/DetourNavMesh.cpp +++ b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNavMesh.cpp @@ -16,13 +16,13 @@ // 3. This notice may not be removed or altered from any source distribution. // -#include <math.h> #include <float.h> #include <string.h> #include <stdio.h> #include "DetourNavMesh.h" #include "DetourNode.h" #include "DetourCommon.h" +#include "DetourMath.h" #include "DetourAlloc.h" #include "DetourAssert.h" #include <new> @@ -64,6 +64,15 @@ inline bool overlapSlabs(const float* amin, const float* amax, return false; } +static float getSlabCoord(const float* va, const int side) +{ + if (side == 0 || side == 4) + return va[0]; + else if (side == 2 || side == 6) + return va[2]; + return 0; +} + static void calcSlabEndPoints(const float* va, const float* vb, float* bmin, float* bmax, const int side) { if (side == 0 || side == 4) @@ -133,6 +142,10 @@ dtNavMesh* dtAllocNavMesh() return new(mem) dtNavMesh; } +/// @par +/// +/// This function will only free the memory for tiles with the #DT_TILE_FREE_DATA +/// flag set. void dtFreeNavMesh(dtNavMesh* navmesh) { if (!navmesh) return; @@ -141,6 +154,37 @@ void dtFreeNavMesh(dtNavMesh* navmesh) } ////////////////////////////////////////////////////////////////////////////////////////// + +/** +@class dtNavMesh + +The navigation mesh consists of one or more tiles defining three primary types of structural data: + +A polygon mesh which defines most of the navigation graph. (See rcPolyMesh for its structure.) +A detail mesh used for determining surface height on the polygon mesh. (See rcPolyMeshDetail for its structure.) +Off-mesh connections, which define custom point-to-point edges within the navigation graph. + +The general build process is as follows: + +-# Create rcPolyMesh and rcPolyMeshDetail data using the Recast build pipeline. +-# Optionally, create off-mesh connection data. +-# Combine the source data into a dtNavMeshCreateParams structure. +-# Create a tile data array using dtCreateNavMeshData(). +-# Allocate at dtNavMesh object and initialize it. (For single tile navigation meshes, + the tile data is loaded during this step.) +-# For multi-tile navigation meshes, load the tile data using dtNavMesh::addTile(). + +Notes: + +- This class is usually used in conjunction with the dtNavMeshQuery class for pathfinding. +- Technically, all navigation meshes are tiled. A 'solo' mesh is simply a navigation mesh initialized + to have only a single tile. +- This class does not implement any asynchronous methods. So the ::dtStatus result of all methods will + always contain either a success or failure flag. + +@see dtNavMeshQuery, dtCreateNavMeshData, dtNavMeshCreateParams, #dtAllocNavMesh, #dtFreeNavMesh +*/ + dtNavMesh::dtNavMesh() : m_tileWidth(0), m_tileHeight(0), @@ -149,11 +193,13 @@ dtNavMesh::dtNavMesh() : m_tileLutMask(0), m_posLookup(0), m_nextFree(0), - m_tiles(0), - m_saltBits(0), - m_tileBits(0), - m_polyBits(0) + m_tiles(0) { +#ifndef DT_POLYREF64 + m_saltBits = 0; + m_tileBits = 0; + m_polyBits = 0; +#endif memset(&m_params, 0, sizeof(dtNavMeshParams)); m_orig[0] = 0; m_orig[1] = 0; @@ -190,10 +236,10 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params) m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); if (!m_tiles) - return DT_FAILURE; + return DT_FAILURE | DT_OUT_OF_MEMORY; m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); if (!m_posLookup) - return DT_FAILURE; + return DT_FAILURE | DT_OUT_OF_MEMORY; memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); m_nextFree = 0; @@ -205,11 +251,15 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params) } // Init ID generator values. - m_tileBits = STATIC_TILE_BITS; //dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); - m_polyBits = STATIC_POLY_BITS; //dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); - m_saltBits = STATIC_SALT_BITS; //sizeof(dtPolyRef)*8 - m_tileBits - m_polyBits; - //if (m_saltBits < SALT_MIN_BITS) - //return DT_FAILURE; +#ifndef DT_POLYREF64 + m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); + m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); + // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. + m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits); + + if (m_saltBits < 10) + return DT_FAILURE | DT_INVALID_PARAM; +#endif return DT_SUCCESS; } @@ -219,9 +269,9 @@ dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flag // Make sure the data is in right format. dtMeshHeader* header = (dtMeshHeader*)data; if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE; + return DT_FAILURE | DT_WRONG_MAGIC; if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE; + return DT_FAILURE | DT_WRONG_VERSION; dtNavMeshParams params; dtVcopy(params.orig, header->bmin); @@ -230,13 +280,17 @@ dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flag params.maxTiles = 1; params.maxPolys = header->polyCount; - dtStatus res = init(¶ms); - if (res != DT_SUCCESS) - return res; + dtStatus status = init(¶ms); + if (dtStatusFailed(status)) + return status; return addTile(data, dataSize, flags, 0, 0); } +/// @par +/// +/// @note The parameters are created automatically when the single tile +/// initialization is performed. const dtNavMeshParams* dtNavMesh::getParams() const { return &m_params; @@ -250,7 +304,8 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb, if (!tile) return 0; float amin[2], amax[2]; - calcSlabEndPoints(va,vb, amin,amax, side); + calcSlabEndPoints(va, vb, amin, amax, side); + const float apos = getSlabCoord(va, side); // Remove links pointing to 'side' and compact the links array. float bmin[2], bmax[2]; @@ -267,11 +322,18 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb, { // Skip edges which do not point to the right side. if (poly->neis[j] != m) continue; - // Check if the segments touch. + const float* vc = &tile->verts[poly->verts[j]*3]; const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3]; + const float bpos = getSlabCoord(vc, side); + + // Segments are not close enough. + if (dtAbs(apos-bpos) > 0.01f) + continue; + + // Check if the segments touch. calcSlabEndPoints(vc,vd, bmin,bmax, side); - + if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue; // Add return value. @@ -288,9 +350,11 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb, return n; } -void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, int side) +void dtNavMesh::unconnectLinks(dtMeshTile* tile, dtMeshTile* target) { - if (!tile) return; + if (!tile || !target) return; + + const unsigned int targetNum = decodePolyIdTile(getTileRef(target)); for (int i = 0; i < tile->header->polyCount; ++i) { @@ -299,9 +363,9 @@ void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, int side) unsigned int pj = DT_NULL_LINK; while (j != DT_NULL_LINK) { - if (tile->links[j].side == side) + if (decodePolyIdTile(tile->links[j].ref) == targetNum) { - // Revove link. + // Remove link. unsigned int nj = tile->links[j].next; if (pj == DT_NULL_LINK) poly->firstLink = nj; @@ -330,19 +394,25 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side) dtPoly* poly = &tile->polys[i]; // Create new links. - unsigned short m = DT_EXT_LINK | (unsigned short)side; +// unsigned short m = DT_EXT_LINK | (unsigned short)side; + const int nv = poly->vertCount; for (int j = 0; j < nv; ++j) { - // Skip edges which do not point to the right side. - if (poly->neis[j] != m) continue; + // Skip non-portal edges. + if ((poly->neis[j] & DT_EXT_LINK) == 0) + continue; + + const int dir = (int)(poly->neis[j] & 0xff); + if (side != -1 && dir != side) + continue; // Create new links const float* va = &tile->verts[poly->verts[j]*3]; const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3]; dtPolyRef nei[4]; float neia[4*2]; - int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(side), nei,neia,4); + int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(dir), nei,neia,4); for (int k = 0; k < nnei; ++k) { unsigned int idx = allocLink(tile); @@ -351,13 +421,13 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side) dtLink* link = &tile->links[idx]; link->ref = nei[k]; link->edge = (unsigned char)j; - link->side = (unsigned char)side; + link->side = (unsigned char)dir; link->next = poly->firstLink; poly->firstLink = idx; // Compress portal limits to a byte value. - if (side == 0 || side == 4) + if (dir == 0 || dir == 4) { float tmin = (neia[k*2+0]-va[2]) / (vb[2]-va[2]); float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]); @@ -366,7 +436,7 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side) link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); } - else if (side == 2 || side == 6) + else if (dir == 2 || dir == 6) { float tmin = (neia[k*2+0]-va[0]) / (vb[0]-va[0]); float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]); @@ -387,15 +457,18 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int // Connect off-mesh links. // We are interested on links which land from target tile to this tile. - const unsigned char oppositeSide = (unsigned char)dtOppositeTile(side); + const unsigned char oppositeSide = (side == -1) ? 0xff : (unsigned char)dtOppositeTile(side); for (int i = 0; i < target->header->offMeshConCount; ++i) { dtOffMeshConnection* targetCon = &target->offMeshCons[i]; if (targetCon->side != oppositeSide) continue; - + dtPoly* targetPoly = &target->polys[targetCon->poly]; + // Skip off-mesh connections which start location could not be connected at all. + if (targetPoly->firstLink == DT_NULL_LINK) + continue; const float ext[3] = { targetCon->rad, target->header->walkableClimb, targetCon->rad }; @@ -403,7 +476,8 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int const float* p = &targetCon->pos[3]; float nearestPt[3]; dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); - if (!ref) continue; + if (!ref) + continue; // findNearestPoly may return too optimistic results, further check to make sure. if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(targetCon->rad)) continue; @@ -428,19 +502,19 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int // Link target poly to off-mesh connection. if (targetCon->flags & DT_OFFMESH_CON_BIDIR) { - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) + unsigned int tidx = allocLink(tile); + if (tidx != DT_NULL_LINK) { const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); dtPoly* landPoly = &tile->polys[landPolyIdx]; - dtLink* link = &tile->links[idx]; + dtLink* link = &tile->links[tidx]; link->ref = getPolyRefBase(target) | (dtPolyRef)(targetCon->poly); link->edge = 0xff; - link->side = (unsigned char)side; + link->side = (unsigned char)(side == -1 ? 0xff : side); link->bmin = link->bmax = 0; // Add to linked list. link->next = landPoly->firstLink; - landPoly->firstLink = idx; + landPoly->firstLink = tidx; } } } @@ -484,13 +558,13 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile) } } -void dtNavMesh::connectIntOffMeshLinks(dtMeshTile* tile) +void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile) { if (!tile) return; dtPolyRef base = getPolyRefBase(tile); - // Find Off-mesh connection end points. + // Base off-mesh connection start points. for (int i = 0; i < tile->header->offMeshConCount; ++i) { dtOffMeshConnection* con = &tile->offMeshCons[i]; @@ -498,72 +572,109 @@ void dtNavMesh::connectIntOffMeshLinks(dtMeshTile* tile) const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad }; - for (int j = 0; j < 2; ++j) - { - unsigned char side = j == 0 ? 0xff : con->side; + // Find polygon to connect to. + const float* p = &con->pos[0]; // First vertex + float nearestPt[3]; + dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); + if (!ref) continue; + // findNearestPoly may return too optimistic results, further check to make sure. + if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad)) + continue; + // Make sure the location is on current mesh. + float* v = &tile->verts[poly->verts[0]*3]; + dtVcopy(v, nearestPt); - if (side == 0xff) - { - // Find polygon to connect to. - const float* p = &con->pos[j*3]; - float nearestPt[3]; - dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); - if (!ref) continue; - // findNearestPoly may return too optimistic results, further check to make sure. - if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad)) - continue; - // Make sure the location is on current mesh. - float* v = &tile->verts[poly->verts[j]*3]; - dtVcopy(v, nearestPt); - - // Link off-mesh connection to target poly. - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = ref; - link->edge = (unsigned char)j; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = poly->firstLink; - poly->firstLink = idx; - } + // Link off-mesh connection to target poly. + unsigned int idx = allocLink(tile); + if (idx != DT_NULL_LINK) + { + dtLink* link = &tile->links[idx]; + link->ref = ref; + link->edge = (unsigned char)0; + link->side = 0xff; + link->bmin = link->bmax = 0; + // Add to linked list. + link->next = poly->firstLink; + poly->firstLink = idx; + } - // Start end-point is always connect back to off-mesh connection, - // Destination end-point only if it is bidirectional link. - if (j == 0 || (j == 1 && (con->flags & DT_OFFMESH_CON_BIDIR))) - { - // Link target poly to off-mesh connection. - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); - dtPoly* landPoly = &tile->polys[landPolyIdx]; - dtLink* link = &tile->links[idx]; - link->ref = base | (dtPolyRef)(con->poly); - link->edge = 0xff; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = landPoly->firstLink; - landPoly->firstLink = idx; - } - } - - } + // Start end-point is always connect back to off-mesh connection. + unsigned int tidx = allocLink(tile); + if (tidx != DT_NULL_LINK) + { + const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); + dtPoly* landPoly = &tile->polys[landPolyIdx]; + dtLink* link = &tile->links[tidx]; + link->ref = base | (dtPolyRef)(con->poly); + link->edge = 0xff; + link->side = 0xff; + link->bmin = link->bmax = 0; + // Add to linked list. + link->next = landPoly->firstLink; + landPoly->firstLink = tidx; } } } -dtStatus dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, - const float* pos, float* closest) const +void dtNavMesh::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const { - const dtPoly* poly = &tile->polys[ip]; + const dtMeshTile* tile = 0; + const dtPoly* poly = 0; + getTileAndPolyByRefUnsafe(ref, &tile, &poly); + + // Off-mesh connections don't have detail polygons. + if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) + { + const float* v0 = &tile->verts[poly->verts[0]*3]; + const float* v1 = &tile->verts[poly->verts[1]*3]; + const float d0 = dtVdist(pos, v0); + const float d1 = dtVdist(pos, v1); + const float u = d0 / (d0+d1); + dtVlerp(closest, v0, v1, u); + if (posOverPoly) + *posOverPoly = false; + return; + } - float closestDistSqr = FLT_MAX; + const unsigned int ip = (unsigned int)(poly - tile->polys); const dtPolyDetail* pd = &tile->detailMeshes[ip]; + // Clamp point to be inside the polygon. + float verts[DT_VERTS_PER_POLYGON*3]; + float edged[DT_VERTS_PER_POLYGON]; + float edget[DT_VERTS_PER_POLYGON]; + const int nv = poly->vertCount; + for (int i = 0; i < nv; ++i) + dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); + + dtVcopy(closest, pos); + if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) + { + // Point is outside the polygon, dtClamp to nearest edge. + float dmin = edged[0]; + int imin = 0; + for (int i = 1; i < nv; ++i) + { + if (edged[i] < dmin) + { + dmin = edged[i]; + imin = i; + } + } + const float* va = &verts[imin*3]; + const float* vb = &verts[((imin+1)%nv)*3]; + dtVlerp(closest, va, vb, edget[imin]); + + if (posOverPoly) + *posOverPoly = false; + } + else + { + if (posOverPoly) + *posOverPoly = true; + } + + // Find height at the location. for (int j = 0; j < pd->triCount; ++j) { const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; @@ -575,17 +686,13 @@ dtStatus dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned in else v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; } - float pt[3]; - dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); - float d = dtVdistSqr(pos, pt); - if (d < closestDistSqr) + float h; + if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) { - dtVcopy(closest, pt); - closestDistSqr = d; + closest[1] = h; + break; } } - - return DT_SUCCESS; } dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile, @@ -607,13 +714,27 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile, { dtPolyRef ref = polys[i]; float closestPtPoly[3]; - if (closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly) != DT_SUCCESS) - continue; - float d = dtVdistSqr(center, closestPtPoly); + float diff[3]; + bool posOverPoly = false; + float d; + closestPointOnPoly(ref, center, closestPtPoly, &posOverPoly); + + // If a point is directly over a polygon and closer than + // climb height, favor that instead of straight line nearest point. + dtVsub(diff, center, closestPtPoly); + if (posOverPoly) + { + d = dtAbs(diff[1]) - tile->header->walkableClimb; + d = d > 0 ? d*d : 0; + } + else + { + d = dtVlenSqr(diff); + } + if (d < nearestDistanceSqr) { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); + dtVcopy(nearestPt, closestPtPoly); nearestDistanceSqr = d; nearest = ref; } @@ -706,18 +827,34 @@ int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, co } } +/// @par +/// +/// The add operation will fail if the data is in the wrong format, the allocated tile +/// space is full, or there is a tile already at the specified reference. +/// +/// The lastRef parameter is used to restore a tile with the same tile +/// reference it had previously used. In this case the #dtPolyRef's for the +/// tile will be restored to the same values they were before the tile was +/// removed. +/// +/// The nav mesh assumes exclusive access to the data passed and will make +/// changes to the dynamic portion of the data. For that reason the data +/// should not be reused in other nav meshes until the tile has been successfully +/// removed from this nav mesh. +/// +/// @see dtCreateNavMeshData, #removeTile dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result) { // Make sure the data is in right format. dtMeshHeader* header = (dtMeshHeader*)data; if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE_DATA_MAGIC; + return DT_FAILURE | DT_WRONG_MAGIC; if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE_DATA_VERSION; + return DT_FAILURE | DT_WRONG_VERSION; // Make sure the location is free. - if (getTileAt(header->x, header->y)) + if (getTileAt(header->x, header->y, header->layer)) return DT_FAILURE; // Allocate a tile. @@ -736,7 +873,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, // Try to relocate the tile to specific index with same salt. int tileIndex = (int)decodePolyIdTile((dtPolyRef)lastRef); if (tileIndex >= m_maxTiles) - return DT_FAILURE_OUT_OF_MEMORY; + return DT_FAILURE | DT_OUT_OF_MEMORY; // Try to find the specific tile id from the free list. dtMeshTile* target = &m_tiles[tileIndex]; dtMeshTile* prev = 0; @@ -748,7 +885,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, } // Could not find the correct location. if (tile != target) - return DT_FAILURE_OUT_OF_MEMORY; + return DT_FAILURE | DT_OUT_OF_MEMORY; // Remove from freelist if (!prev) m_nextFree = tile->next; @@ -761,7 +898,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, // Make sure we could allocate a tile. if (!tile) - return DT_FAILURE_OUT_OF_MEMORY; + return DT_FAILURE | DT_OUT_OF_MEMORY; // Insert tile into the position lut. int h = computeTileHash(header->x, header->y, m_tileLutMask); @@ -780,14 +917,18 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); unsigned char* d = data + headerSize; - tile->verts = (float*)d; d += vertsSize; - tile->polys = (dtPoly*)d; d += polysSize; - tile->links = (dtLink*)d; d += linksSize; - tile->detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - tile->detailVerts = (float*)d; d += detailVertsSize; - tile->detailTris = (unsigned char*)d; d += detailTrisSize; - tile->bvTree = (dtBVNode*)d; d += bvtreeSize; - tile->offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; + tile->verts = dtGetThenAdvanceBufferPointer<float>(d, vertsSize); + tile->polys = dtGetThenAdvanceBufferPointer<dtPoly>(d, polysSize); + tile->links = dtGetThenAdvanceBufferPointer<dtLink>(d, linksSize); + tile->detailMeshes = dtGetThenAdvanceBufferPointer<dtPolyDetail>(d, detailMeshesSize); + tile->detailVerts = dtGetThenAdvanceBufferPointer<float>(d, detailVertsSize); + tile->detailTris = dtGetThenAdvanceBufferPointer<unsigned char>(d, detailTrisSize); + tile->bvTree = dtGetThenAdvanceBufferPointer<dtBVNode>(d, bvtreeSize); + tile->offMeshCons = dtGetThenAdvanceBufferPointer<dtOffMeshConnection>(d, offMeshLinksSize); + + // If there are no items in the bvtree, reset the tree pointer. + if (!bvtreeSize) + tile->bvTree = 0; // Build links freelist tile->linksFreeList = 0; @@ -802,18 +943,39 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, tile->flags = flags; connectIntLinks(tile); - connectIntOffMeshLinks(tile); - // Create connections connections. + // Base off-mesh connections to their starting polygons and connect connections inside the tile. + baseOffMeshLinks(tile); + connectExtOffMeshLinks(tile, tile, -1); + + // Create connections with neighbour tiles. + static const int MAX_NEIS = 32; + dtMeshTile* neis[MAX_NEIS]; + int nneis; + + // Connect with layers in current tile. + nneis = getTilesAt(header->x, header->y, neis, MAX_NEIS); + for (int j = 0; j < nneis; ++j) + { + if (neis[j] == tile) + continue; + + connectExtLinks(tile, neis[j], -1); + connectExtLinks(neis[j], tile, -1); + connectExtOffMeshLinks(tile, neis[j], -1); + connectExtOffMeshLinks(neis[j], tile, -1); + } + + // Connect with neighbour tiles. for (int i = 0; i < 8; ++i) { - dtMeshTile* nei = getNeighbourTileAt(header->x, header->y, i); - if (nei) + nneis = getNeighbourTilesAt(header->x, header->y, i, neis, MAX_NEIS); + for (int j = 0; j < nneis; ++j) { - connectExtLinks(tile, nei, i); - connectExtLinks(nei, tile, dtOppositeTile(i)); - connectExtOffMeshLinks(tile, nei, i); - connectExtOffMeshLinks(nei, tile, dtOppositeTile(i)); + connectExtLinks(tile, neis[j], i); + connectExtLinks(neis[j], tile, dtOppositeTile(i)); + connectExtOffMeshLinks(tile, neis[j], i); + connectExtOffMeshLinks(neis[j], tile, dtOppositeTile(i)); } } @@ -823,55 +985,106 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, return DT_SUCCESS; } -const dtMeshTile* dtNavMesh::getTileAt(int x, int y) const +const dtMeshTile* dtNavMesh::getTileAt(const int x, const int y, const int layer) const { // Find tile based on hash. int h = computeTileHash(x,y,m_tileLutMask); dtMeshTile* tile = m_posLookup[h]; while (tile) { - if (tile->header && tile->header->x == x && tile->header->y == y) + if (tile->header && + tile->header->x == x && + tile->header->y == y && + tile->header->layer == layer) + { return tile; + } tile = tile->next; } return 0; } -dtMeshTile* dtNavMesh::getNeighbourTileAt(int x, int y, int side) const +int dtNavMesh::getNeighbourTilesAt(const int x, const int y, const int side, dtMeshTile** tiles, const int maxTiles) const { + int nx = x, ny = y; switch (side) { - case 0: x++; break; - case 1: x++; y++; break; - case 2: y++; break; - case 3: x--; y++; break; - case 4: x--; break; - case 5: x--; y--; break; - case 6: y--; break; - case 7: x++; y--; break; + case 0: nx++; break; + case 1: nx++; ny++; break; + case 2: ny++; break; + case 3: nx--; ny++; break; + case 4: nx--; break; + case 5: nx--; ny--; break; + case 6: ny--; break; + case 7: nx++; ny--; break; }; + return getTilesAt(nx, ny, tiles, maxTiles); +} + +int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile** tiles, const int maxTiles) const +{ + int n = 0; + // Find tile based on hash. int h = computeTileHash(x,y,m_tileLutMask); dtMeshTile* tile = m_posLookup[h]; while (tile) { - if (tile->header && tile->header->x == x && tile->header->y == y) - return tile; + if (tile->header && + tile->header->x == x && + tile->header->y == y) + { + if (n < maxTiles) + tiles[n++] = tile; + } tile = tile->next; } - return 0; + + return n; +} + +/// @par +/// +/// This function will not fail if the tiles array is too small to hold the +/// entire result set. It will simply fill the array to capacity. +int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile const** tiles, const int maxTiles) const +{ + int n = 0; + + // Find tile based on hash. + int h = computeTileHash(x,y,m_tileLutMask); + dtMeshTile* tile = m_posLookup[h]; + while (tile) + { + if (tile->header && + tile->header->x == x && + tile->header->y == y) + { + if (n < maxTiles) + tiles[n++] = tile; + } + tile = tile->next; + } + + return n; } -dtTileRef dtNavMesh::getTileRefAt(int x, int y) const + +dtTileRef dtNavMesh::getTileRefAt(const int x, const int y, const int layer) const { // Find tile based on hash. int h = computeTileHash(x,y,m_tileLutMask); dtMeshTile* tile = m_posLookup[h]; while (tile) { - if (tile->header && tile->header->x == x && tile->header->y == y) + if (tile->header && + tile->header->x == x && + tile->header->y == y && + tile->header->layer == layer) + { return getTileRef(tile); + } tile = tile->next; } return 0; @@ -914,16 +1127,22 @@ void dtNavMesh::calcTileLoc(const float* pos, int* tx, int* ty) const dtStatus dtNavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const { + if (!ref) return DT_FAILURE; unsigned int salt, it, ip; decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE; - if (ip >= (unsigned int)m_tiles[it].header->polyCount) return DT_FAILURE; + if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; + if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; + if (ip >= (unsigned int)m_tiles[it].header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; *tile = &m_tiles[it]; *poly = &m_tiles[it].polys[ip]; return DT_SUCCESS; } +/// @par +/// +/// @warning Only use this function if it is known that the provided polygon +/// reference is valid. This function is faster than #getTileAndPolyByRef, but +/// it does not validate the reference. void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const { unsigned int salt, it, ip; @@ -934,6 +1153,7 @@ void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile* bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const { + if (!ref) return false; unsigned int salt, it, ip; decodePolyId(ref, salt, it, ip); if (it >= (unsigned int)m_maxTiles) return false; @@ -942,17 +1162,23 @@ bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const return true; } +/// @par +/// +/// This function returns the data for the tile so that, if desired, +/// it can be added back to the navigation mesh at a later point. +/// +/// @see #addTile dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSize) { if (!ref) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; unsigned int tileIndex = decodePolyIdTile((dtPolyRef)ref); unsigned int tileSalt = decodePolyIdSalt((dtPolyRef)ref); if ((int)tileIndex >= m_maxTiles) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; dtMeshTile* tile = &m_tiles[tileIndex]; if (tile->salt != tileSalt) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; // Remove tile from hash lookup. int h = computeTileHash(tile->header->x,tile->header->y,m_tileLutMask); @@ -973,14 +1199,26 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz } // Remove connections to neighbour tiles. - for (int i = 0; i < 8; ++i) + static const int MAX_NEIS = 32; + dtMeshTile* neis[MAX_NEIS]; + int nneis; + + // Disconnect from other layers in current tile. + nneis = getTilesAt(tile->header->x, tile->header->y, neis, MAX_NEIS); + for (int j = 0; j < nneis; ++j) { - dtMeshTile* nei = getNeighbourTileAt(tile->header->x,tile->header->y,i); - if (!nei) continue; - unconnectExtLinks(nei, dtOppositeTile(i)); + if (neis[j] == tile) continue; + unconnectLinks(neis[j], tile); } - + // Disconnect from neighbour tiles. + for (int i = 0; i < 8; ++i) + { + nneis = getNeighbourTilesAt(tile->header->x, tile->header->y, i, neis, MAX_NEIS); + for (int j = 0; j < nneis; ++j) + unconnectLinks(neis[j], tile); + } + // Reset tile. if (tile->flags & DT_TILE_FREE_DATA) { @@ -1010,7 +1248,11 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz tile->offMeshCons = 0; // Update salt, salt should never be zero. +#ifdef DT_POLYREF64 + tile->salt = (tile->salt+1) & ((1<<DT_SALT_BITS)-1); +#else tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1); +#endif if (tile->salt == 0) tile->salt++; @@ -1028,6 +1270,20 @@ dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const return (dtTileRef)encodePolyId(tile->salt, it, 0); } +/// @par +/// +/// Example use case: +/// @code +/// +/// const dtPolyRef base = navmesh->getPolyRefBase(tile); +/// for (int i = 0; i < tile->header->polyCount; ++i) +/// { +/// const dtPoly* p = &tile->polys[i]; +/// const dtPolyRef ref = base | (dtPolyRef)i; +/// +/// // Use the reference to access the polygon data. +/// } +/// @endcode dtPolyRef dtNavMesh::getPolyRefBase(const dtMeshTile* tile) const { if (!tile) return 0; @@ -1048,6 +1304,7 @@ struct dtPolyState unsigned char area; // Area ID of the polygon. }; +/// @see #storeTileState int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const { if (!tile) return 0; @@ -1056,15 +1313,20 @@ int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const return headerSize + polyStateSize; } +/// @par +/// +/// Tile state includes non-structural data such as polygon flags, area ids, etc. +/// @note The state data is only valid until the tile reference changes. +/// @see #getTileStateSize, #restoreTileState dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const { // Make sure there is enough space to store the state. const int sizeReq = getTileStateSize(tile); if (maxDataSize < sizeReq) - return DT_FAILURE; + return DT_FAILURE | DT_BUFFER_TOO_SMALL; - dtTileState* tileState = (dtTileState*)data; data += dtAlign4(sizeof(dtTileState)); - dtPolyState* polyStates = (dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); + dtTileState* tileState = dtGetThenAdvanceBufferPointer<dtTileState>(data, dtAlign4(sizeof(dtTileState))); + dtPolyState* polyStates = dtGetThenAdvanceBufferPointer<dtPolyState>(data, dtAlign4(sizeof(dtPolyState) * tile->header->polyCount)); // Store tile state. tileState->magic = DT_NAVMESH_STATE_MAGIC; @@ -1083,23 +1345,28 @@ dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data, return DT_SUCCESS; } +/// @par +/// +/// Tile state includes non-structural data such as polygon flags, area ids, etc. +/// @note This function does not impact the tile's #dtTileRef and #dtPolyRef's. +/// @see #storeTileState dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize) { // Make sure there is enough space to store the state. const int sizeReq = getTileStateSize(tile); if (maxDataSize < sizeReq) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; - const dtTileState* tileState = (const dtTileState*)data; data += dtAlign4(sizeof(dtTileState)); - const dtPolyState* polyStates = (const dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); + const dtTileState* tileState = dtGetThenAdvanceBufferPointer<const dtTileState>(data, dtAlign4(sizeof(dtTileState))); + const dtPolyState* polyStates = dtGetThenAdvanceBufferPointer<const dtPolyState>(data, dtAlign4(sizeof(dtPolyState) * tile->header->polyCount)); // Check that the restore is possible. if (tileState->magic != DT_NAVMESH_STATE_MAGIC) - return DT_FAILURE_DATA_MAGIC; + return DT_FAILURE | DT_WRONG_MAGIC; if (tileState->version != DT_NAVMESH_STATE_VERSION) - return DT_FAILURE_DATA_VERSION; + return DT_FAILURE | DT_WRONG_VERSION; if (tileState->ref != getTileRef(tile)) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; // Restore per poly state. for (int i = 0; i < tile->header->polyCount; ++i) @@ -1113,17 +1380,26 @@ dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data return DT_SUCCESS; } -// Returns start and end location of an off-mesh link polygon. +/// @par +/// +/// Off-mesh connections are stored in the navigation mesh as special 2-vertex +/// polygons with a single edge. At least one of the vertices is expected to be +/// inside a normal polygon. So an off-mesh connection is "entered" from a +/// normal polygon at one of its endpoints. This is the polygon identified by +/// the prevRef parameter. dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const { unsigned int salt, it, ip; + if (!polyRef) + return DT_FAILURE; + // Get current polygon decodePolyId(polyRef, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE; + if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; + if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE; + if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; const dtPoly* poly = &tile->polys[ip]; // Make sure that the current poly is indeed off-mesh link. @@ -1158,6 +1434,9 @@ const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) c { unsigned int salt, it, ip; + if (!ref) + return 0; + // Get current polygon decodePolyId(ref, salt, it, ip); if (it >= (unsigned int)m_maxTiles) return 0; @@ -1178,12 +1457,13 @@ const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) c dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags) { + if (!ref) return DT_FAILURE; unsigned int salt, it, ip; decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE; + if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; + if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE; + if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; dtPoly* poly = &tile->polys[ip]; // Change flags. @@ -1194,12 +1474,13 @@ dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags) dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const { + if (!ref) return DT_FAILURE; unsigned int salt, it, ip; decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE; + if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; + if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE; + if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; const dtPoly* poly = &tile->polys[ip]; *resultFlags = poly->flags; @@ -1209,12 +1490,13 @@ dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) con dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area) { + if (!ref) return DT_FAILURE; unsigned int salt, it, ip; decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE; + if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; + if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE; + if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; dtPoly* poly = &tile->polys[ip]; poly->setArea(area); @@ -1224,12 +1506,13 @@ dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area) dtStatus dtNavMesh::getPolyArea(dtPolyRef ref, unsigned char* resultArea) const { + if (!ref) return DT_FAILURE; unsigned int salt, it, ip; decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE; + if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; + if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE; + if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; const dtPoly* poly = &tile->polys[ip]; *resultArea = poly->getArea(); diff --git a/deps/recastnavigation/Detour/DetourNavMeshBuilder.cpp b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNavMeshBuilder.cpp index 68f3d730da..965e6cdc5c 100644 --- a/deps/recastnavigation/Detour/DetourNavMeshBuilder.cpp +++ b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNavMeshBuilder.cpp @@ -16,12 +16,13 @@ // 3. This notice may not be removed or altered from any source distribution. // -#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <float.h> #include "DetourNavMesh.h" #include "DetourCommon.h" +#include "DetourMath.h" #include "DetourNavMeshBuilder.h" #include "DetourAlloc.h" #include "DetourAssert.h" @@ -105,7 +106,6 @@ inline int longestAxis(unsigned short x, unsigned short y, unsigned short z) if (z > maxVal) { axis = 2; - maxVal = z; } return axis; } @@ -201,8 +201,8 @@ static int createBVTree(const unsigned short* verts, const int /*nverts*/, if (z > it.bmax[2]) it.bmax[2] = z; } // Remap y - it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs); - it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs); + it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs); + it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs); } int curNode = 0; @@ -237,11 +237,19 @@ static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, co case ZM: return 6; case XP|ZM: return 7; }; + return 0xff; } // TODO: Better error handling. +/// @par +/// +/// The output data array is allocated using the detour allocator (dtAlloc()). The method +/// used to free the memory will be determined by how the tile is added to the navigation +/// mesh. +/// +/// @see dtNavMesh, dtNavMesh::addTile() bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize) { if (params->nvp > DT_VERTS_PER_POLYGON) @@ -252,8 +260,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, return false; if (!params->polyCount || !params->polys) return false; - //if (!params->detailMeshes || !params->detailVerts || !params->detailTris) - // return false; const int nvp = params->nvp; @@ -269,10 +275,50 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, if (!offMeshConClass) return false; + // Find tight heigh bounds, used for culling out off-mesh start locations. + float hmin = FLT_MAX; + float hmax = -FLT_MAX; + + if (params->detailVerts && params->detailVertsCount) + { + for (int i = 0; i < params->detailVertsCount; ++i) + { + const float h = params->detailVerts[i*3+1]; + hmin = dtMin(hmin,h); + hmax = dtMax(hmax,h); + } + } + else + { + for (int i = 0; i < params->vertCount; ++i) + { + const unsigned short* iv = ¶ms->verts[i*3]; + const float h = params->bmin[1] + iv[1] * params->ch; + hmin = dtMin(hmin,h); + hmax = dtMax(hmax,h); + } + } + hmin -= params->walkableClimb; + hmax += params->walkableClimb; + float bmin[3], bmax[3]; + dtVcopy(bmin, params->bmin); + dtVcopy(bmax, params->bmax); + bmin[1] = hmin; + bmax[1] = hmax; + for (int i = 0; i < params->offMeshConCount; ++i) { - offMeshConClass[i*2+0] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax); - offMeshConClass[i*2+1] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax); + const float* p0 = ¶ms->offMeshConVerts[(i*2+0)*3]; + const float* p1 = ¶ms->offMeshConVerts[(i*2+1)*3]; + offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax); + offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax); + + // Zero out off-mesh start positions which are not even potentially touching the mesh. + if (offMeshConClass[i*2+0] == 0xff) + { + if (p0[1] < bmin[1] || p0[1] > bmax[1]) + offMeshConClass[i*2+0] = 0; + } // Cound how many links should be allocated for off-mesh connections. if (offMeshConClass[i*2+0] == 0xff) @@ -298,23 +344,13 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, for (int j = 0; j < nvp; ++j) { if (p[j] == MESH_NULL_IDX) break; - int nj = j+1; - if (nj >= nvp || p[nj] == MESH_NULL_IDX) nj = 0; - const unsigned short* va = ¶ms->verts[p[j]*3]; - const unsigned short* vb = ¶ms->verts[p[nj]*3]; - edgeCount++; - if (params->tileSize > 0) + if (p[nvp+j] & 0x8000) { - if (va[0] == params->tileSize && vb[0] == params->tileSize) - portalCount++; // x+ - else if (va[2] == params->tileSize && vb[2] == params->tileSize) - portalCount++; // z+ - else if (va[0] == 0 && vb[0] == 0) - portalCount++; // x- - else if (va[2] == 0 && vb[2] == 0) - portalCount++; // z- + unsigned short dir = p[nvp+j] & 0xf; + if (dir != 0xf) + portalCount++; } } } @@ -368,7 +404,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount); const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount); const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount); - const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2); + const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0; const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount); const int dataSize = headerSize + vertsSize + polysSize + linksSize + @@ -384,15 +420,16 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, memset(data, 0, dataSize); unsigned char* d = data; - dtMeshHeader* header = (dtMeshHeader*)d; d += headerSize; - float* navVerts = (float*)d; d += vertsSize; - dtPoly* navPolys = (dtPoly*)d; d += polysSize; - d += linksSize; - dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - float* navDVerts = (float*)d; d += detailVertsSize; - unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize; - dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize; - dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize; + + dtMeshHeader* header = dtGetThenAdvanceBufferPointer<dtMeshHeader>(d, headerSize); + float* navVerts = dtGetThenAdvanceBufferPointer<float>(d, vertsSize); + dtPoly* navPolys = dtGetThenAdvanceBufferPointer<dtPoly>(d, polysSize); + d += linksSize; // Ignore links; just leave enough space for them. They'll be created on load. + dtPolyDetail* navDMeshes = dtGetThenAdvanceBufferPointer<dtPolyDetail>(d, detailMeshesSize); + float* navDVerts = dtGetThenAdvanceBufferPointer<float>(d, detailVertsSize); + unsigned char* navDTris = dtGetThenAdvanceBufferPointer<unsigned char>(d, detailTrisSize); + dtBVNode* navBvtree = dtGetThenAdvanceBufferPointer<dtBVNode>(d, bvTreeSize); + dtOffMeshConnection* offMeshCons = dtGetThenAdvanceBufferPointer<dtOffMeshConnection>(d, offMeshConsSize); // Store header @@ -400,6 +437,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, header->version = DT_NAVMESH_VERSION; header->x = params->tileX; header->y = params->tileY; + header->layer = params->tileLayer; header->userId = params->userId; header->polyCount = totPolyCount; header->vertCount = totVertCount; @@ -415,7 +453,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, header->walkableRadius = params->walkableRadius; header->walkableClimb = params->walkableClimb; header->offMeshConCount = storedOffMeshConCount; - header->bvNodeCount = params->polyCount*2; + header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0; const int offMeshVertsBase = params->vertCount; const int offMeshPolyBase = params->polyCount; @@ -459,7 +497,27 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, { if (src[j] == MESH_NULL_IDX) break; p->verts[j] = src[j]; - p->neis[j] = (src[nvp+j]+1) & 0xffff; + if (src[nvp+j] & 0x8000) + { + // Border or portal edge. + unsigned short dir = src[nvp+j] & 0xf; + if (dir == 0xf) // Border + p->neis[j] = 0; + else if (dir == 0) // Portal x- + p->neis[j] = DT_EXT_LINK | 4; + else if (dir == 1) // Portal z+ + p->neis[j] = DT_EXT_LINK | 2; + else if (dir == 2) // Portal x+ + p->neis[j] = DT_EXT_LINK | 0; + else if (dir == 3) // Portal z- + p->neis[j] = DT_EXT_LINK | 6; + } + else + { + // Normal connection + p->neis[j] = src[nvp+j]+1; + } + p->vertCount++; } src += nvp*2; @@ -481,32 +539,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, n++; } } - - // Store portal edges. - if (params->tileSize > 0) - { - for (int i = 0; i < params->polyCount; ++i) - { - dtPoly* poly = &navPolys[i]; - for (int j = 0; j < poly->vertCount; ++j) - { - int nj = j+1; - if (nj >= poly->vertCount) nj = 0; - - const unsigned short* va = ¶ms->verts[poly->verts[j]*3]; - const unsigned short* vb = ¶ms->verts[poly->verts[nj]*3]; - - if (va[0] == params->tileSize && vb[0] == params->tileSize) // x+ - poly->neis[j] = DT_EXT_LINK | 0; - else if (va[2] == params->tileSize && vb[2] == params->tileSize) // z+ - poly->neis[j] = DT_EXT_LINK | 2; - else if (va[0] == 0 && vb[0] == 0) // x- - poly->neis[j] = DT_EXT_LINK | 4; - else if (va[2] == 0 && vb[2] == 0) // z- - poly->neis[j] = DT_EXT_LINK | 6; - } - } - } // Store detail meshes and vertices. // The nav polygon vertices are stored as the first vertices on each mesh. @@ -564,8 +596,11 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, // Store and create BVtree. // TODO: take detail mesh into account! use byte per bbox extent? - createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, - nvp, params->cs, params->ch, params->polyCount*2, navBvtree); + if (params->buildBvTree) + { + createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, + nvp, params->cs, params->ch, params->polyCount*2, navBvtree); + } // Store Off-Mesh connections. n = 0; @@ -597,51 +632,14 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, return true; } -inline void swapByte(unsigned char* a, unsigned char* b) -{ - unsigned char tmp = *a; - *a = *b; - *b = tmp; -} - -inline void swapEndian(unsigned short* v) -{ - unsigned char* x = (unsigned char*)v; - swapByte(x+0, x+1); -} - -inline void swapEndian(short* v) -{ - unsigned char* x = (unsigned char*)v; - swapByte(x+0, x+1); -} - -inline void swapEndian(unsigned int* v) -{ - unsigned char* x = (unsigned char*)v; - swapByte(x+0, x+3); swapByte(x+1, x+2); -} - -inline void swapEndian(int* v) -{ - unsigned char* x = (unsigned char*)v; - swapByte(x+0, x+3); swapByte(x+1, x+2); -} - -inline void swapEndian(float* v) -{ - unsigned char* x = (unsigned char*)v; - swapByte(x+0, x+3); swapByte(x+1, x+2); -} - bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) { dtMeshHeader* header = (dtMeshHeader*)data; int swappedMagic = DT_NAVMESH_MAGIC; int swappedVersion = DT_NAVMESH_VERSION; - swapEndian(&swappedMagic); - swapEndian(&swappedVersion); + dtSwapEndian(&swappedMagic); + dtSwapEndian(&swappedVersion); if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) && (header->magic != swappedMagic || header->version != swappedVersion)) @@ -649,36 +647,43 @@ bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) return false; } - swapEndian(&header->magic); - swapEndian(&header->version); - swapEndian(&header->x); - swapEndian(&header->y); - swapEndian(&header->userId); - swapEndian(&header->polyCount); - swapEndian(&header->vertCount); - swapEndian(&header->maxLinkCount); - swapEndian(&header->detailMeshCount); - swapEndian(&header->detailVertCount); - swapEndian(&header->detailTriCount); - swapEndian(&header->bvNodeCount); - swapEndian(&header->offMeshConCount); - swapEndian(&header->offMeshBase); - swapEndian(&header->walkableHeight); - swapEndian(&header->walkableRadius); - swapEndian(&header->walkableClimb); - swapEndian(&header->bmin[0]); - swapEndian(&header->bmin[1]); - swapEndian(&header->bmin[2]); - swapEndian(&header->bmax[0]); - swapEndian(&header->bmax[1]); - swapEndian(&header->bmax[2]); - swapEndian(&header->bvQuantFactor); + dtSwapEndian(&header->magic); + dtSwapEndian(&header->version); + dtSwapEndian(&header->x); + dtSwapEndian(&header->y); + dtSwapEndian(&header->layer); + dtSwapEndian(&header->userId); + dtSwapEndian(&header->polyCount); + dtSwapEndian(&header->vertCount); + dtSwapEndian(&header->maxLinkCount); + dtSwapEndian(&header->detailMeshCount); + dtSwapEndian(&header->detailVertCount); + dtSwapEndian(&header->detailTriCount); + dtSwapEndian(&header->bvNodeCount); + dtSwapEndian(&header->offMeshConCount); + dtSwapEndian(&header->offMeshBase); + dtSwapEndian(&header->walkableHeight); + dtSwapEndian(&header->walkableRadius); + dtSwapEndian(&header->walkableClimb); + dtSwapEndian(&header->bmin[0]); + dtSwapEndian(&header->bmin[1]); + dtSwapEndian(&header->bmin[2]); + dtSwapEndian(&header->bmax[0]); + dtSwapEndian(&header->bmax[1]); + dtSwapEndian(&header->bmax[2]); + dtSwapEndian(&header->bvQuantFactor); // Freelist index and pointers are updated when tile is added, no need to swap. return true; } +/// @par +/// +/// @warning This function assumes that the header is in the correct endianess already. +/// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess +/// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from +/// native to foreign endianess. bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) { // Make sure the data is in right format. @@ -700,19 +705,21 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); unsigned char* d = data + headerSize; - float* verts = (float*)d; d += vertsSize; - dtPoly* polys = (dtPoly*)d; d += polysSize; - /*dtLink* links = (dtLink*)d;*/ d += linksSize; - dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - float* detailVerts = (float*)d; d += detailVertsSize; - /*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize; - dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize; - dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; + float* verts = dtGetThenAdvanceBufferPointer<float>(d, vertsSize); + dtPoly* polys = dtGetThenAdvanceBufferPointer<dtPoly>(d, polysSize); + d += linksSize; // Ignore links; they technically should be endian-swapped but all their data is overwritten on load anyway. + //dtLink* links = dtGetThenAdvanceBufferPointer<dtLink>(d, linksSize); + dtPolyDetail* detailMeshes = dtGetThenAdvanceBufferPointer<dtPolyDetail>(d, detailMeshesSize); + float* detailVerts = dtGetThenAdvanceBufferPointer<float>(d, detailVertsSize); + d += detailTrisSize; // Ignore detail tris; single bytes can't be endian-swapped. + //unsigned char* detailTris = dtGetThenAdvanceBufferPointer<unsigned char>(d, detailTrisSize); + dtBVNode* bvTree = dtGetThenAdvanceBufferPointer<dtBVNode>(d, bvtreeSize); + dtOffMeshConnection* offMeshCons = dtGetThenAdvanceBufferPointer<dtOffMeshConnection>(d, offMeshLinksSize); // Vertices for (int i = 0; i < header->vertCount*3; ++i) { - swapEndian(&verts[i]); + dtSwapEndian(&verts[i]); } // Polys @@ -722,10 +729,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) // poly->firstLink is update when tile is added, no need to swap. for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j) { - swapEndian(&p->verts[j]); - swapEndian(&p->neis[j]); + dtSwapEndian(&p->verts[j]); + dtSwapEndian(&p->neis[j]); } - swapEndian(&p->flags); + dtSwapEndian(&p->flags); } // Links are rebuild when tile is added, no need to swap. @@ -734,14 +741,14 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) for (int i = 0; i < header->detailMeshCount; ++i) { dtPolyDetail* pd = &detailMeshes[i]; - swapEndian(&pd->vertBase); - swapEndian(&pd->triBase); + dtSwapEndian(&pd->vertBase); + dtSwapEndian(&pd->triBase); } // Detail verts for (int i = 0; i < header->detailVertCount*3; ++i) { - swapEndian(&detailVerts[i]); + dtSwapEndian(&detailVerts[i]); } // BV-tree @@ -750,10 +757,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) dtBVNode* node = &bvTree[i]; for (int j = 0; j < 3; ++j) { - swapEndian(&node->bmin[j]); - swapEndian(&node->bmax[j]); + dtSwapEndian(&node->bmin[j]); + dtSwapEndian(&node->bmax[j]); } - swapEndian(&node->i); + dtSwapEndian(&node->i); } // Off-mesh Connections. @@ -761,9 +768,9 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) { dtOffMeshConnection* con = &offMeshCons[i]; for (int j = 0; j < 6; ++j) - swapEndian(&con->pos[j]); - swapEndian(&con->rad); - swapEndian(&con->poly); + dtSwapEndian(&con->pos[j]); + dtSwapEndian(&con->rad); + dtSwapEndian(&con->poly); } return true; diff --git a/deps/recastnavigation/Detour/DetourNavMeshQuery.cpp b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp index 33ee87fb95..a263106dc1 100644 --- a/deps/recastnavigation/Detour/DetourNavMeshQuery.cpp +++ b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNavMeshQuery.cpp @@ -16,17 +16,49 @@ // 3. This notice may not be removed or altered from any source distribution. // -#include <math.h> #include <float.h> #include <string.h> #include "DetourNavMeshQuery.h" #include "DetourNavMesh.h" #include "DetourNode.h" #include "DetourCommon.h" +#include "DetourMath.h" #include "DetourAlloc.h" #include "DetourAssert.h" #include <new> +/// @class dtQueryFilter +/// +/// <b>The Default Implementation</b> +/// +/// At construction: All area costs default to 1.0. All flags are included +/// and none are excluded. +/// +/// If a polygon has both an include and an exclude flag, it will be excluded. +/// +/// The way filtering works, a navigation mesh polygon must have at least one flag +/// set to ever be considered by a query. So a polygon with no flags will never +/// be considered. +/// +/// Setting the include flags to 0 will result in all polygons being excluded. +/// +/// <b>Custom Implementations</b> +/// +/// DT_VIRTUAL_QUERYFILTER must be defined in order to extend this class. +/// +/// Implement a custom query filter by overriding the virtual passFilter() +/// and getCost() functions. If this is done, both functions should be as +/// fast as possible. Use cached local copies of data rather than accessing +/// your own objects where possible. +/// +/// Custom implementations do not need to adhere to the flags or cost logic +/// used by the default implementation. +/// +/// In order for A* searches to work properly, the cost should be proportional to +/// the travel distance. Implementing a cost modifier less than 1.0 is likely +/// to lead to problems during pathfinding. +/// +/// @see dtNavMeshQuery dtQueryFilter::dtQueryFilter() : m_includeFlags(0xffff), @@ -86,6 +118,23 @@ void dtFreeNavMeshQuery(dtNavMeshQuery* navmesh) } ////////////////////////////////////////////////////////////////////////////////////////// + +/// @class dtNavMeshQuery +/// +/// For methods that support undersized buffers, if the buffer is too small +/// to hold the entire result set the return status of the method will include +/// the #DT_BUFFER_TOO_SMALL flag. +/// +/// Constant member functions can be used by multiple clients without side +/// effects. (E.g. No change to the closed list. No impact on an in-progress +/// sliced path query. Etc.) +/// +/// Walls and portals: A @e wall is a polygon segment that is +/// considered impassable. A @e portal is a passable segment between polygons. +/// A portal may be treated as a wall based on the dtQueryFilter used for a query. +/// +/// @see dtNavMesh, dtQueryFilter, #dtAllocNavMeshQuery(), #dtAllocNavMeshQuery() + dtNavMeshQuery::dtNavMeshQuery() : m_nav(0), m_tinyNodePool(0), @@ -108,8 +157,17 @@ dtNavMeshQuery::~dtNavMeshQuery() dtFree(m_openList); } +/// @par +/// +/// Must be the first function called after construction, before other +/// functions are used. +/// +/// This function can be used multiple times. dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) { + if (maxNodes > DT_NULL_IDX || maxNodes > (1 << DT_NODE_PARENT_BITS) - 1) + return DT_FAILURE | DT_INVALID_PARAM; + m_nav = nav; if (!m_nodePool || m_nodePool->getMaxNodes() < maxNodes) @@ -122,7 +180,7 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) } m_nodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(maxNodes, dtNextPow2(maxNodes/4)); if (!m_nodePool) - return DT_FAILURE_OUT_OF_MEMORY; + return DT_FAILURE | DT_OUT_OF_MEMORY; } else { @@ -133,14 +191,13 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) { m_tinyNodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(64, 32); if (!m_tinyNodePool) - return DT_FAILURE_OUT_OF_MEMORY; + return DT_FAILURE | DT_OUT_OF_MEMORY; } else { m_tinyNodePool->clear(); } - // TODO: check the open list size too. if (!m_openList || m_openList->getCapacity() < maxNodes) { if (m_openList) @@ -151,7 +208,7 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) } m_openList = new (dtAlloc(sizeof(dtNodeQueue), DT_ALLOC_PERM)) dtNodeQueue(maxNodes); if (!m_openList) - return DT_FAILURE_OUT_OF_MEMORY; + return DT_FAILURE | DT_OUT_OF_MEMORY; } else { @@ -161,33 +218,318 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) return DT_SUCCESS; } -////////////////////////////////////////////////////////////////////////////////////////// -dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const +dtStatus dtNavMeshQuery::findRandomPoint(const dtQueryFilter* filter, float (*frand)(), + dtPolyRef* randomRef, float* randomPt) const { dtAssert(m_nav); + + // Randomly pick one tile. Assume that all tiles cover roughly the same area. const dtMeshTile* tile = 0; + float tsum = 0.0f; + for (int i = 0; i < m_nav->getMaxTiles(); i++) + { + const dtMeshTile* t = m_nav->getTile(i); + if (!t || !t->header) continue; + + // Choose random tile using reservoi sampling. + const float area = 1.0f; // Could be tile area too. + tsum += area; + const float u = frand(); + if (u*tsum <= area) + tile = t; + } + if (!tile) + return DT_FAILURE; + + // Randomly pick one polygon weighted by polygon area. const dtPoly* poly = 0; - if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS) + dtPolyRef polyRef = 0; + const dtPolyRef base = m_nav->getPolyRefBase(tile); + + float areaSum = 0.0f; + for (int i = 0; i < tile->header->polyCount; ++i) + { + const dtPoly* p = &tile->polys[i]; + // Do not return off-mesh connection polygons. + if (p->getType() != DT_POLYTYPE_GROUND) + continue; + // Must pass filter + const dtPolyRef ref = base | (dtPolyRef)i; + if (!filter->passFilter(ref, tile, p)) + continue; + + // Calc area of the polygon. + float polyArea = 0.0f; + for (int j = 2; j < p->vertCount; ++j) + { + const float* va = &tile->verts[p->verts[0]*3]; + const float* vb = &tile->verts[p->verts[j-1]*3]; + const float* vc = &tile->verts[p->verts[j]*3]; + polyArea += dtTriArea2D(va,vb,vc); + } + + // Choose random polygon weighted by area, using reservoi sampling. + areaSum += polyArea; + const float u = frand(); + if (u*areaSum <= polyArea) + { + poly = p; + polyRef = ref; + } + } + + if (!poly) return DT_FAILURE; - if (!tile) return DT_FAILURE; - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - return DT_FAILURE; + // Randomly pick point on polygon. + const float* v = &tile->verts[poly->verts[0]*3]; + float verts[3*DT_VERTS_PER_POLYGON]; + float areas[DT_VERTS_PER_POLYGON]; + dtVcopy(&verts[0*3],v); + for (int j = 1; j < poly->vertCount; ++j) + { + v = &tile->verts[poly->verts[j]*3]; + dtVcopy(&verts[j*3],v); + } + + const float s = frand(); + const float t = frand(); + + float pt[3]; + dtRandomPointInConvexPoly(verts, poly->vertCount, areas, s, t, pt); + + float h = 0.0f; + dtStatus status = getPolyHeight(polyRef, pt, &h); + if (dtStatusFailed(status)) + return status; + pt[1] = h; + + dtVcopy(randomPt, pt); + *randomRef = polyRef; - if (closestPointOnPolyInTile(tile, poly, pos, closest) != DT_SUCCESS) + return DT_SUCCESS; +} + +dtStatus dtNavMeshQuery::findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius, + const dtQueryFilter* filter, float (*frand)(), + dtPolyRef* randomRef, float* randomPt) const +{ + dtAssert(m_nav); + dtAssert(m_nodePool); + dtAssert(m_openList); + + // Validate input + if (!startRef || !m_nav->isValidPolyRef(startRef)) + return DT_FAILURE | DT_INVALID_PARAM; + + const dtMeshTile* startTile = 0; + const dtPoly* startPoly = 0; + m_nav->getTileAndPolyByRefUnsafe(startRef, &startTile, &startPoly); + if (!filter->passFilter(startRef, startTile, startPoly)) + return DT_FAILURE | DT_INVALID_PARAM; + + m_nodePool->clear(); + m_openList->clear(); + + dtNode* startNode = m_nodePool->getNode(startRef); + dtVcopy(startNode->pos, centerPos); + startNode->pidx = 0; + startNode->cost = 0; + startNode->total = 0; + startNode->id = startRef; + startNode->flags = DT_NODE_OPEN; + m_openList->push(startNode); + + dtStatus status = DT_SUCCESS; + + const float radiusSqr = dtSqr(maxRadius); + float areaSum = 0.0f; + + const dtMeshTile* randomTile = 0; + const dtPoly* randomPoly = 0; + dtPolyRef randomPolyRef = 0; + + while (!m_openList->empty()) + { + dtNode* bestNode = m_openList->pop(); + bestNode->flags &= ~DT_NODE_OPEN; + bestNode->flags |= DT_NODE_CLOSED; + + // Get poly and tile. + // The API input has been cheked already, skip checking internal data. + const dtPolyRef bestRef = bestNode->id; + const dtMeshTile* bestTile = 0; + const dtPoly* bestPoly = 0; + m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); + + // Place random locations on on ground. + if (bestPoly->getType() == DT_POLYTYPE_GROUND) + { + // Calc area of the polygon. + float polyArea = 0.0f; + for (int j = 2; j < bestPoly->vertCount; ++j) + { + const float* va = &bestTile->verts[bestPoly->verts[0]*3]; + const float* vb = &bestTile->verts[bestPoly->verts[j-1]*3]; + const float* vc = &bestTile->verts[bestPoly->verts[j]*3]; + polyArea += dtTriArea2D(va,vb,vc); + } + // Choose random polygon weighted by area, using reservoi sampling. + areaSum += polyArea; + const float u = frand(); + if (u*areaSum <= polyArea) + { + randomTile = bestTile; + randomPoly = bestPoly; + randomPolyRef = bestRef; + } + } + + + // Get parent poly and tile. + dtPolyRef parentRef = 0; + const dtMeshTile* parentTile = 0; + const dtPoly* parentPoly = 0; + if (bestNode->pidx) + parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; + if (parentRef) + m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); + + for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) + { + const dtLink* link = &bestTile->links[i]; + dtPolyRef neighbourRef = link->ref; + // Skip invalid neighbours and do not follow back to parent. + if (!neighbourRef || neighbourRef == parentRef) + continue; + + // Expand to neighbour + const dtMeshTile* neighbourTile = 0; + const dtPoly* neighbourPoly = 0; + m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); + + // Do not advance if the polygon is excluded by the filter. + if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) + continue; + + // Find edge and calc distance to the edge. + float va[3], vb[3]; + if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) + continue; + + // If the circle is not touching the next polygon, skip it. + float tseg; + float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); + if (distSqr > radiusSqr) + continue; + + dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); + if (!neighbourNode) + { + status |= DT_OUT_OF_NODES; + continue; + } + + if (neighbourNode->flags & DT_NODE_CLOSED) + continue; + + // Cost + if (neighbourNode->flags == 0) + dtVlerp(neighbourNode->pos, va, vb, 0.5f); + + const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); + + // The node is already in open list and the new result is worse, skip. + if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) + continue; + + neighbourNode->id = neighbourRef; + neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); + neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); + neighbourNode->total = total; + + if (neighbourNode->flags & DT_NODE_OPEN) + { + m_openList->modify(neighbourNode); + } + else + { + neighbourNode->flags = DT_NODE_OPEN; + m_openList->push(neighbourNode); + } + } + } + + if (!randomPoly) return DT_FAILURE; + + // Randomly pick point on polygon. + const float* v = &randomTile->verts[randomPoly->verts[0]*3]; + float verts[3*DT_VERTS_PER_POLYGON]; + float areas[DT_VERTS_PER_POLYGON]; + dtVcopy(&verts[0*3],v); + for (int j = 1; j < randomPoly->vertCount; ++j) + { + v = &randomTile->verts[randomPoly->verts[j]*3]; + dtVcopy(&verts[j*3],v); + } + + const float s = frand(); + const float t = frand(); + + float pt[3]; + dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt); + + float h = 0.0f; + dtStatus stat = getPolyHeight(randomPolyRef, pt, &h); + if (dtStatusFailed(status)) + return stat; + pt[1] = h; + + dtVcopy(randomPt, pt); + *randomRef = randomPolyRef; + return DT_SUCCESS; } -dtStatus dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, - const float* pos, float* closest) const + +////////////////////////////////////////////////////////////////////////////////////////// + +/// @par +/// +/// Uses the detail polygons to find the surface height. (Most accurate.) +/// +/// @p pos does not have to be within the bounds of the polygon or navigation mesh. +/// +/// See closestPointOnPolyBoundary() for a limited but faster option. +/// +dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const { + dtAssert(m_nav); + const dtMeshTile* tile = 0; + const dtPoly* poly = 0; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) + return DT_FAILURE | DT_INVALID_PARAM; + if (!tile) + return DT_FAILURE | DT_INVALID_PARAM; + + // Off-mesh connections don't have detail polygons. + if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) + { + const float* v0 = &tile->verts[poly->verts[0]*3]; + const float* v1 = &tile->verts[poly->verts[1]*3]; + const float d0 = dtVdist(pos, v0); + const float d1 = dtVdist(pos, v1); + const float u = d0 / (d0+d1); + dtVlerp(closest, v0, v1, u); + if (posOverPoly) + *posOverPoly = false; + return DT_SUCCESS; + } + const unsigned int ip = (unsigned int)(poly - tile->polys); const dtPolyDetail* pd = &tile->detailMeshes[ip]; - // TODO: The commented out version finds 'cylinder distance' instead of 'sphere distance' to the navmesh. - // Test and enable. -/* // Clamp point to be inside the polygon. float verts[DT_VERTS_PER_POLYGON*3]; float edged[DT_VERTS_PER_POLYGON]; @@ -200,9 +542,9 @@ dtStatus dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) { // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) + float dmin = edged[0]; + int imin = 0; + for (int i = 1; i < nv; ++i) { if (edged[i] < dmin) { @@ -213,6 +555,14 @@ dtStatus dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const const float* va = &verts[imin*3]; const float* vb = &verts[((imin+1)%nv)*3]; dtVlerp(closest, va, vb, edget[imin]); + + if (posOverPoly) + *posOverPoly = false; + } + else + { + if (posOverPoly) + *posOverPoly = true; } // Find height at the location. @@ -234,42 +584,29 @@ dtStatus dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const break; } } -*/ - float closestDistSqr = FLT_MAX; - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - - float pt[3]; - dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); - float d = dtVdistSqr(pos, pt); - - if (d < closestDistSqr) - { - dtVcopy(closest, pt); - closestDistSqr = d; - } - } return DT_SUCCESS; } +/// @par +/// +/// Much faster than closestPointOnPoly(). +/// +/// If the provided position lies within the polygon's xz-bounds (above or below), +/// then @p pos and @p closest will be equal. +/// +/// The height of @p closest will be the polygon boundary. The height detail is not used. +/// +/// @p pos does not have to be within the bounds of the polybon or the navigation mesh. +/// dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const { dtAssert(m_nav); const dtMeshTile* tile = 0; const dtPoly* poly = 0; - if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) + return DT_FAILURE | DT_INVALID_PARAM; // Collect vertices. float verts[DT_VERTS_PER_POLYGON*3]; @@ -291,9 +628,9 @@ dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* else { // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) + float dmin = edged[0]; + int imin = 0; + for (int i = 1; i < nv; ++i) { if (edged[i] < dmin) { @@ -309,22 +646,26 @@ dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* return DT_SUCCESS; } - +/// @par +/// +/// Will return #DT_FAILURE if the provided position is outside the xz-bounds +/// of the polygon. +/// dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* height) const { dtAssert(m_nav); const dtMeshTile* tile = 0; const dtPoly* poly = 0; - if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) + return DT_FAILURE | DT_INVALID_PARAM; if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) { const float* v0 = &tile->verts[poly->verts[0]*3]; const float* v1 = &tile->verts[poly->verts[1]*3]; - const float d0 = dtVdist(pos, v0); - const float d1 = dtVdist(pos, v1); + const float d0 = dtVdist2D(pos, v0); + const float d1 = dtVdist2D(pos, v1); const float u = d0 / (d0+d1); if (height) *height = v0[1] + (v1[1] - v0[1]) * u; @@ -355,90 +696,101 @@ dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* h } } - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; } -dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* nearestRef, float* nearestPt) const +class dtFindNearestPolyQuery : public dtPolyQuery { - dtAssert(m_nav); + const dtNavMeshQuery* m_query; + const float* m_center; + float m_nearestDistanceSqr; + dtPolyRef m_nearestRef; + float m_nearestPoint[3]; + +public: + dtFindNearestPolyQuery(const dtNavMeshQuery* query, const float* center) + : m_query(query), m_center(center), m_nearestDistanceSqr(FLT_MAX), m_nearestRef(0), m_nearestPoint() + { + } - *nearestRef = 0; - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = 0; - if (queryPolygons(center, extents, filter, polys, &polyCount, 128) != DT_SUCCESS) - return DT_FAILURE; - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) + dtPolyRef nearestRef() const { return m_nearestRef; } + const float* nearestPoint() const { return m_nearestPoint; } + + void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) { - dtPolyRef ref = polys[i]; - float closestPtPoly[3]; - if (closestPointOnPoly(ref, center, closestPtPoly) != DT_SUCCESS) - continue; - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) + dtIgnoreUnused(polys); + + for (int i = 0; i < count; ++i) { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; + dtPolyRef ref = refs[i]; + float closestPtPoly[3]; + float diff[3]; + bool posOverPoly = false; + float d; + m_query->closestPointOnPoly(ref, m_center, closestPtPoly, &posOverPoly); + + // If a point is directly over a polygon and closer than + // climb height, favor that instead of straight line nearest point. + dtVsub(diff, m_center, closestPtPoly); + if (posOverPoly) + { + d = dtAbs(diff[1]) - tile->header->walkableClimb; + d = d > 0 ? d*d : 0; + } + else + { + d = dtVlenSqr(diff); + } + + if (d < m_nearestDistanceSqr) + { + dtVcopy(m_nearestPoint, closestPtPoly); + + m_nearestDistanceSqr = d; + m_nearestRef = ref; + } } } - - if (nearestRef) - *nearestRef = nearest; - - return DT_SUCCESS; -} +}; -dtPolyRef dtNavMeshQuery::findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents, - const dtQueryFilter* filter, float* nearestPt) const +/// @par +/// +/// @note If the search box does not intersect any polygons the search will +/// return #DT_SUCCESS, but @p nearestRef will be zero. So if in doubt, check +/// @p nearestRef before using @p nearestPt. +/// +dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* extents, + const dtQueryFilter* filter, + dtPolyRef* nearestRef, float* nearestPt) const { dtAssert(m_nav); + + if (!nearestRef) + return DT_FAILURE | DT_INVALID_PARAM; - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = queryPolygonsInTile(tile, bmin, bmax, filter, polys, 128); - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - const dtPoly* poly = &tile->polys[m_nav->decodePolyIdPoly(ref)]; - float closestPtPoly[3]; - if (closestPointOnPolyInTile(tile, poly, center, closestPtPoly) != DT_SUCCESS) - continue; - - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } + dtFindNearestPolyQuery query(this, center); + + dtStatus status = queryPolygons(center, extents, filter, &query); + if (dtStatusFailed(status)) + return status; + + *nearestRef = query.nearestRef(); + // Only override nearestPt if we actually found a poly so the nearest point + // is valid. + if (nearestPt && *nearestRef) + dtVcopy(nearestPt, query.nearestPoint()); - return nearest; + return DT_SUCCESS; } -int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, - const dtQueryFilter* filter, - dtPolyRef* polys, const int maxPolys) const +void dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, + const dtQueryFilter* filter, dtPolyQuery* query) const { dtAssert(m_nav); + static const int batchSize = 32; + dtPolyRef polyRefs[batchSize]; + dtPoly* polys[batchSize]; + int n = 0; if (tile->bvTree) { @@ -447,7 +799,7 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi const float* tbmin = tile->header->bmin; const float* tbmax = tile->header->bmax; const float qfac = tile->header->bvQuantFactor; - + // Calculate quantized box unsigned short bmin[3], bmax[3]; // dtClamp query box to world box. @@ -464,25 +816,34 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi bmax[0] = (unsigned short)(qfac * maxx + 1) | 1; bmax[1] = (unsigned short)(qfac * maxy + 1) | 1; bmax[2] = (unsigned short)(qfac * maxz + 1) | 1; - + // Traverse tree const dtPolyRef base = m_nav->getPolyRefBase(tile); - int n = 0; while (node < end) { const bool overlap = dtOverlapQuantBounds(bmin, bmax, node->bmin, node->bmax); const bool isLeafNode = node->i >= 0; - + if (isLeafNode && overlap) { dtPolyRef ref = base | (dtPolyRef)node->i; if (filter->passFilter(ref, tile, &tile->polys[node->i])) { - if (n < maxPolys) - polys[n++] = ref; + polyRefs[n] = ref; + polys[n] = &tile->polys[node->i]; + + if (n == batchSize - 1) + { + query->process(tile, polys, polyRefs, batchSize); + n = 0; + } + else + { + n++; + } } } - + if (overlap || isLeafNode) node++; else @@ -491,22 +852,22 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi node += escapeIndex; } } - - return n; } else { float bmin[3], bmax[3]; - int n = 0; const dtPolyRef base = m_nav->getPolyRefBase(tile); for (int i = 0; i < tile->header->polyCount; ++i) { - // Calc polygon bounds. dtPoly* p = &tile->polys[i]; // Do not return off-mesh connection polygons. if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) continue; - + // Must pass filter + const dtPolyRef ref = base | (dtPolyRef)i; + if (!filter->passFilter(ref, tile, p)) + continue; + // Calc polygon bounds. const float* v = &tile->verts[p->verts[0]*3]; dtVcopy(bmin, v); dtVcopy(bmax, v); @@ -516,26 +877,104 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi dtVmin(bmin, v); dtVmax(bmax, v); } - if (dtOverlapBounds(qmin,qmax, bmin,bmax)) + if (dtOverlapBounds(qmin, qmax, bmin, bmax)) { - const dtPolyRef ref = base | (dtPolyRef)i; - if (filter->passFilter(ref, tile, p)) + polyRefs[n] = ref; + polys[n] = p; + + if (n == batchSize - 1) { - if (n < maxPolys) - polys[n++] = ref; + query->process(tile, polys, polyRefs, batchSize); + n = 0; + } + else + { + n++; } } } - return n; } + + // Process the last polygons that didn't make a full batch. + if (n > 0) + query->process(tile, polys, polyRefs, n); } +class dtCollectPolysQuery : public dtPolyQuery +{ + dtPolyRef* m_polys; + const int m_maxPolys; + int m_numCollected; + bool m_overflow; + +public: + dtCollectPolysQuery(dtPolyRef* polys, const int maxPolys) + : m_polys(polys), m_maxPolys(maxPolys), m_numCollected(0), m_overflow(false) + { + } + + int numCollected() const { return m_numCollected; } + bool overflowed() const { return m_overflow; } + + void process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count) + { + dtIgnoreUnused(tile); + dtIgnoreUnused(polys); + + int numLeft = m_maxPolys - m_numCollected; + int toCopy = count; + if (toCopy > numLeft) + { + m_overflow = true; + toCopy = numLeft; + } + + memcpy(m_polys + m_numCollected, refs, (size_t)toCopy * sizeof(dtPolyRef)); + m_numCollected += toCopy; + } +}; + +/// @par +/// +/// If no polygons are found, the function will return #DT_SUCCESS with a +/// @p polyCount of zero. +/// +/// If @p polys is too small to hold the entire result set, then the array will +/// be filled to capacity. The method of choosing which polygons from the +/// full set are included in the partial result set is undefined. +/// dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents, const dtQueryFilter* filter, dtPolyRef* polys, int* polyCount, const int maxPolys) const { + if (!polys || !polyCount || maxPolys < 0) + return DT_FAILURE | DT_INVALID_PARAM; + + dtCollectPolysQuery collector(polys, maxPolys); + + dtStatus status = queryPolygons(center, extents, filter, &collector); + if (dtStatusFailed(status)) + return status; + + *polyCount = collector.numCollected(); + return collector.overflowed() ? DT_SUCCESS | DT_BUFFER_TOO_SMALL : DT_SUCCESS; +} + +/// @par +/// +/// The query will be invoked with batches of polygons. Polygons passed +/// to the query have bounding boxes that overlap with the center and extents +/// passed to this function. The dtPolyQuery::process function is invoked multiple +/// times until all overlapping polygons have been processed. +/// +dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents, + const dtQueryFilter* filter, dtPolyQuery* query) const +{ dtAssert(m_nav); - + + if (!center || !extents || !filter || !query) + return DT_FAILURE | DT_INVALID_PARAM; + float bmin[3], bmax[3]; dtVsub(bmin, center, extents); dtVadd(bmax, center, extents); @@ -545,35 +984,35 @@ dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents m_nav->calcTileLoc(bmin, &minx, &miny); m_nav->calcTileLoc(bmax, &maxx, &maxy); - int n = 0; - - /// pussywizard: additional checks as in PathGenerator::HaveTile - if (minx < 0) minx = 0; if (miny < 0) miny = 0; // min can be negative because we subtract extents (few lines above) - if (maxx < 0 || maxy < 0 || maxx-minx >= 64 /*MAX_NUMBER_OF_GRIDS*/ || maxy-miny >= 64) // max should never be negative - { - *polyCount = n; - return DT_SUCCESS; - } - + static const int MAX_NEIS = 32; + const dtMeshTile* neis[MAX_NEIS]; + for (int y = miny; y <= maxy; ++y) { for (int x = minx; x <= maxx; ++x) { - const dtMeshTile* tile = m_nav->getTileAt(x,y); - if (!tile) continue; - n += queryPolygonsInTile(tile, bmin, bmax, filter, polys+n, maxPolys-n); - if (n >= maxPolys) + const int nneis = m_nav->getTilesAt(x,y,neis,MAX_NEIS); + for (int j = 0; j < nneis; ++j) { - *polyCount = n; - return DT_SUCCESS; + queryPolygonsInTile(neis[j], bmin, bmax, filter, query); } } } - *polyCount = n; return DT_SUCCESS; } +/// @par +/// +/// If the end polygon cannot be reached through the navigation graph, +/// the last polygon in the path will be the nearest the end polygon. +/// +/// If the path array is to small to hold the full result, it will be filled as +/// far as possible from the start polygon toward the end polygon. +/// +/// The start and end positions are used to calculate traversal costs. +/// (The y-values impact the result.) +/// dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, const float* startPos, const float* endPos, const dtQueryFilter* filter, @@ -583,18 +1022,14 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, dtAssert(m_nodePool); dtAssert(m_openList); - *pathCount = 0; - - if (!startRef || !endRef) - return DT_FAILURE; - - if (!maxPath) - return DT_FAILURE; + if (pathCount) + *pathCount = 0; // Validate input - if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef)) - return DT_FAILURE; - + if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef) || + !startPos || !endPos || !filter || maxPath <= 0 || !path || !pathCount) + return DT_FAILURE | DT_INVALID_PARAM; + if (startRef == endRef) { path[0] = startRef; @@ -617,6 +1052,8 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, dtNode* lastBestNode = startNode; float lastBestNodeCost = startNode->total; + bool outOfNodes = false; + while (!m_openList->empty()) { // Remove node from open list and put it in closed list. @@ -664,9 +1101,18 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) continue; - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); + // deal explicitly with crossing tile boundaries + unsigned char crossSide = 0; + if (bestTile->links[i].side != 0xff) + crossSide = bestTile->links[i].side >> 1; + + // get the node + dtNode* neighbourNode = m_nodePool->getNode(neighbourRef, crossSide); if (!neighbourNode) + { + outOfNodes = true; continue; + } // If the node is visited the first time, calculate node position. if (neighbourNode->flags == 0) @@ -719,7 +1165,7 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, // Add or update the node. neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->id = neighbourRef; - neighbourNode->flags &= ~DT_NODE_CLOSED; + neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); neighbourNode->cost = cost; neighbourNode->total = total; @@ -743,37 +1189,70 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, } } } + + dtStatus status = getPathToNode(lastBestNode, path, pathCount, maxPath); + + if (lastBestNode->id != endRef) + status |= DT_PARTIAL_RESULT; + + if (outOfNodes) + status |= DT_OUT_OF_NODES; - // Reverse the path. - dtNode* prev = 0; - dtNode* node = lastBestNode; + return status; +} + +dtStatus dtNavMeshQuery::getPathToNode(dtNode* endNode, dtPolyRef* path, int* pathCount, int maxPath) const +{ + // Find the length of the entire path. + dtNode* curNode = endNode; + int length = 0; do { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; + length++; + curNode = m_nodePool->getNodeAtIdx(curNode->pidx); + } while (curNode); + + // If the path cannot be fully stored then advance to the last node we will be able to store. + curNode = endNode; + int writeCount; + for (writeCount = length; writeCount > maxPath; writeCount--) + { + dtAssert(curNode); + + curNode = m_nodePool->getNodeAtIdx(curNode->pidx); } - while (node); - - // Store path - node = prev; - int n = 0; - do + + // Write path + for (int i = writeCount - 1; i >= 0; i--) { - path[n++] = node->id; - node = m_nodePool->getNodeAtIdx(node->pidx); + dtAssert(curNode); + + path[i] = curNode->id; + curNode = m_nodePool->getNodeAtIdx(curNode->pidx); } - while (node && n < maxPath); - - *pathCount = n; - + + dtAssert(!curNode); + + *pathCount = dtMin(length, maxPath); + + if (length > maxPath) + return DT_SUCCESS | DT_BUFFER_TOO_SMALL; + return DT_SUCCESS; } + +/// @par +/// +/// @warning Calling any non-slice methods before calling finalizeSlicedFindPath() +/// or finalizeSlicedFindPathPartial() may result in corrupted data! +/// +/// The @p filter pointer is stored and used for the duration of the sliced +/// path query. +/// dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter) + const dtQueryFilter* filter, const unsigned int options) { dtAssert(m_nav); dtAssert(m_nodePool); @@ -787,13 +1266,25 @@ dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef dtVcopy(m_query.startPos, startPos); dtVcopy(m_query.endPos, endPos); m_query.filter = filter; + m_query.options = options; + m_query.raycastLimitSqr = FLT_MAX; if (!startRef || !endRef) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; // Validate input if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef)) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; + + // trade quality with performance? + if (options & DT_FINDPATH_ANY_ANGLE) + { + // limiting to several times the character radius yields nice results. It is not sensitive + // so it is enough to compute it from the first tile. + const dtMeshTile* tile = m_nav->getTileByRef(startRef); + float agentRadius = tile->header->walkableRadius; + m_query.raycastLimitSqr = dtSqr(agentRadius * DT_RAY_CAST_LIMIT_PROPORTIONS); + } if (startRef == endRef) { @@ -820,9 +1311,9 @@ dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef return m_query.status; } -dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) +dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) { - if (m_query.status!= DT_IN_PROGRESS) + if (!dtStatusInProgress(m_query.status)) return m_query.status; // Make sure the request is still valid. @@ -831,6 +1322,9 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) m_query.status = DT_FAILURE; return DT_FAILURE; } + + dtRaycastHit rayHit; + rayHit.maxPath = 0; int iter = 0; while (iter < maxIter && !m_openList->empty()) @@ -846,7 +1340,10 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) if (bestNode->id == m_query.endRef) { m_query.lastBestNode = bestNode; - m_query.status = DT_SUCCESS; + const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; + m_query.status = DT_SUCCESS | details; + if (doneIters) + *doneIters = iter; return m_query.status; } @@ -855,28 +1352,47 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) const dtPolyRef bestRef = bestNode->id; const dtMeshTile* bestTile = 0; const dtPoly* bestPoly = 0; - if (m_nav->getTileAndPolyByRef(bestRef, &bestTile, &bestPoly) != DT_SUCCESS) + if (dtStatusFailed(m_nav->getTileAndPolyByRef(bestRef, &bestTile, &bestPoly))) { // The polygon has disappeared during the sliced query, fail. m_query.status = DT_FAILURE; + if (doneIters) + *doneIters = iter; return m_query.status; } - // Get parent poly and tile. - dtPolyRef parentRef = 0; + // Get parent and grand parent poly and tile. + dtPolyRef parentRef = 0, grandpaRef = 0; const dtMeshTile* parentTile = 0; const dtPoly* parentPoly = 0; + dtNode* parentNode = 0; if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; + { + parentNode = m_nodePool->getNodeAtIdx(bestNode->pidx); + parentRef = parentNode->id; + if (parentNode->pidx) + grandpaRef = m_nodePool->getNodeAtIdx(parentNode->pidx)->id; + } if (parentRef) { - if (m_nav->getTileAndPolyByRef(parentRef, &parentTile, &parentPoly) != DT_SUCCESS) + bool invalidParent = dtStatusFailed(m_nav->getTileAndPolyByRef(parentRef, &parentTile, &parentPoly)); + if (invalidParent || (grandpaRef && !m_nav->isValidPolyRef(grandpaRef)) ) { // The polygon has disappeared during the sliced query, fail. m_query.status = DT_FAILURE; + if (doneIters) + *doneIters = iter; return m_query.status; } } + + // decide whether to test raycast to previous nodes + bool tryLOS = false; + if (m_query.options & DT_FINDPATH_ANY_ANGLE) + { + if ((parentRef != 0) && (dtVdistSqr(parentNode->pos, bestNode->pos) < m_query.raycastLimitSqr)) + tryLOS = true; + } for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) { @@ -895,10 +1411,18 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) if (!m_query.filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) continue; - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); + // get the neighbor node + dtNode* neighbourNode = m_nodePool->getNode(neighbourRef, 0); if (!neighbourNode) + { + m_query.status |= DT_OUT_OF_NODES; continue; + } + // do not expand to nodes that were already visited from the same parent + if (neighbourNode->pidx != 0 && neighbourNode->pidx == bestNode->pidx) + continue; + // If the node is visited the first time, calculate node position. if (neighbourNode->flags == 0) { @@ -911,30 +1435,44 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) float cost = 0; float heuristic = 0; - // Special case for last node. - if (neighbourRef == m_query.endRef) + // raycast parent + bool foundShortCut = false; + rayHit.pathCost = rayHit.t = 0; + if (tryLOS) { - // Cost + raycast(parentRef, parentNode->pos, neighbourNode->pos, m_query.filter, DT_RAYCAST_USE_COSTS, &rayHit, grandpaRef); + foundShortCut = rayHit.t >= 1.0f; + } + + // update move cost + if (foundShortCut) + { + // shortcut found using raycast. Using shorter cost instead + cost = parentNode->cost + rayHit.pathCost; + } + else + { + // No shortcut found. const float curCost = m_query.filter->getCost(bestNode->pos, neighbourNode->pos, parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); + bestRef, bestTile, bestPoly, + neighbourRef, neighbourTile, neighbourPoly); + cost = bestNode->cost + curCost; + } + + // Special case for last node. + if (neighbourRef == m_query.endRef) + { const float endCost = m_query.filter->getCost(neighbourNode->pos, m_query.endPos, bestRef, bestTile, bestPoly, neighbourRef, neighbourTile, neighbourPoly, 0, 0, 0); - cost = bestNode->cost + curCost + endCost; + cost = cost + endCost; heuristic = 0; } else { - // Cost - const float curCost = m_query.filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - cost = bestNode->cost + curCost; heuristic = dtVdist(neighbourNode->pos, m_query.endPos)*H_SCALE; } @@ -948,11 +1486,13 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) continue; // Add or update the node. - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); + neighbourNode->pidx = foundShortCut ? bestNode->pidx : m_nodePool->getNodeIdx(bestNode); neighbourNode->id = neighbourRef; - neighbourNode->flags &= ~DT_NODE_CLOSED; + neighbourNode->flags = (neighbourNode->flags & ~(DT_NODE_CLOSED | DT_NODE_PARENT_DETACHED)); neighbourNode->cost = cost; neighbourNode->total = total; + if (foundShortCut) + neighbourNode->flags = (neighbourNode->flags | DT_NODE_PARENT_DETACHED); if (neighbourNode->flags & DT_NODE_OPEN) { @@ -977,7 +1517,13 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter) // Exhausted all nodes, but could not find path. if (m_openList->empty()) - m_query.status = DT_SUCCESS; + { + const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; + m_query.status = DT_SUCCESS | details; + } + + if (doneIters) + *doneIters = iter; return m_query.status; } @@ -986,7 +1532,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, { *pathCount = 0; - if (m_query.status != DT_SUCCESS) + if (dtStatusFailed(m_query.status)) { // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); @@ -1004,13 +1550,21 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, { // Reverse the path. dtAssert(m_query.lastBestNode); + + if (m_query.lastBestNode->id != m_query.endRef) + m_query.status |= DT_PARTIAL_RESULT; + dtNode* prev = 0; dtNode* node = m_query.lastBestNode; + int prevRay = 0; do { dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); node->pidx = m_nodePool->getNodeIdx(prev); prev = node; + int nextRay = node->flags & DT_NODE_PARENT_DETACHED; // keep track of whether parent is not adjacent (i.e. due to raycast shortcut) + node->flags = (node->flags & ~DT_NODE_PARENT_DETACHED) | prevRay; // and store it in the reversed path's node + prevRay = nextRay; node = next; } while (node); @@ -1019,18 +1573,43 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, node = prev; do { - path[n++] = node->id; - node = m_nodePool->getNodeAtIdx(node->pidx); + dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); + dtStatus status = 0; + if (node->flags & DT_NODE_PARENT_DETACHED) + { + float t, normal[3]; + int m; + status = raycast(node->id, node->pos, next->pos, m_query.filter, &t, normal, path+n, &m, maxPath-n); + n += m; + // raycast ends on poly boundary and the path might include the next poly boundary. + if (path[n-1] == next->id) + n--; // remove to avoid duplicates + } + else + { + path[n++] = node->id; + if (n >= maxPath) + status = DT_BUFFER_TOO_SMALL; + } + + if (status & DT_STATUS_DETAIL_MASK) + { + m_query.status |= status & DT_STATUS_DETAIL_MASK; + break; + } + node = next; } - while (node && n < maxPath); + while (node); } + const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; + // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); *pathCount = n; - return DT_SUCCESS; + return DT_SUCCESS | details; } dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, @@ -1043,7 +1622,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing return DT_FAILURE; } - if (m_query.status != DT_SUCCESS && m_query.status != DT_IN_PROGRESS) + if (dtStatusFailed(m_query.status)) { // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); @@ -1064,22 +1643,28 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing dtNode* node = 0; for (int i = existingSize-1; i >= 0; --i) { - node = m_nodePool->findNode(existing[i]); + m_nodePool->findNodes(existing[i], &node, 1); if (node) break; } if (!node) { - return DT_FAILURE; + m_query.status |= DT_PARTIAL_RESULT; + dtAssert(m_query.lastBestNode); + node = m_query.lastBestNode; } // Reverse the path. + int prevRay = 0; do { dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); node->pidx = m_nodePool->getNodeIdx(prev); prev = node; + int nextRay = node->flags & DT_NODE_PARENT_DETACHED; // keep track of whether parent is not adjacent (i.e. due to raycast shortcut) + node->flags = (node->flags & ~DT_NODE_PARENT_DETACHED) | prevRay; // and store it in the reversed path's node + prevRay = nextRay; node = next; } while (node); @@ -1088,59 +1673,182 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing node = prev; do { - path[n++] = node->id; - node = m_nodePool->getNodeAtIdx(node->pidx); + dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); + dtStatus status = 0; + if (node->flags & DT_NODE_PARENT_DETACHED) + { + float t, normal[3]; + int m; + status = raycast(node->id, node->pos, next->pos, m_query.filter, &t, normal, path+n, &m, maxPath-n); + n += m; + // raycast ends on poly boundary and the path might include the next poly boundary. + if (path[n-1] == next->id) + n--; // remove to avoid duplicates + } + else + { + path[n++] = node->id; + if (n >= maxPath) + status = DT_BUFFER_TOO_SMALL; + } + + if (status & DT_STATUS_DETAIL_MASK) + { + m_query.status |= status & DT_STATUS_DETAIL_MASK; + break; + } + node = next; } - while (node && n < maxPath); + while (node); } + const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; + // Reset query. memset(&m_query, 0, sizeof(dtQueryData)); *pathCount = n; - return DT_SUCCESS; + return DT_SUCCESS | details; } +dtStatus dtNavMeshQuery::appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref, + float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, + int* straightPathCount, const int maxStraightPath) const +{ + if ((*straightPathCount) > 0 && dtVequal(&straightPath[((*straightPathCount)-1)*3], pos)) + { + // The vertices are equal, update flags and poly. + if (straightPathFlags) + straightPathFlags[(*straightPathCount)-1] = flags; + if (straightPathRefs) + straightPathRefs[(*straightPathCount)-1] = ref; + } + else + { + // Append new vertex. + dtVcopy(&straightPath[(*straightPathCount)*3], pos); + if (straightPathFlags) + straightPathFlags[(*straightPathCount)] = flags; + if (straightPathRefs) + straightPathRefs[(*straightPathCount)] = ref; + (*straightPathCount)++; + + // If there is no space to append more vertices, return. + if ((*straightPathCount) >= maxStraightPath) + { + return DT_SUCCESS | DT_BUFFER_TOO_SMALL; + } + + // If reached end of path, return. + if (flags == DT_STRAIGHTPATH_END) + { + return DT_SUCCESS; + } + } + return DT_IN_PROGRESS; +} + +dtStatus dtNavMeshQuery::appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path, + float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, + int* straightPathCount, const int maxStraightPath, const int options) const +{ + const float* startPos = &straightPath[(*straightPathCount-1)*3]; + // Append or update last vertex + dtStatus stat = 0; + for (int i = startIdx; i < endIdx; i++) + { + // Calculate portal + const dtPolyRef from = path[i]; + const dtMeshTile* fromTile = 0; + const dtPoly* fromPoly = 0; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly))) + return DT_FAILURE | DT_INVALID_PARAM; + + const dtPolyRef to = path[i+1]; + const dtMeshTile* toTile = 0; + const dtPoly* toPoly = 0; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly))) + return DT_FAILURE | DT_INVALID_PARAM; + + float left[3], right[3]; + if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right))) + break; + + if (options & DT_STRAIGHTPATH_AREA_CROSSINGS) + { + // Skip intersection if only area crossings are requested. + if (fromPoly->getArea() == toPoly->getArea()) + continue; + } + + // Append intersection + float s,t; + if (dtIntersectSegSeg2D(startPos, endPos, left, right, s, t)) + { + float pt[3]; + dtVlerp(pt, left,right, t); + + stat = appendVertex(pt, 0, path[i+1], + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath); + if (stat != DT_IN_PROGRESS) + return stat; + } + } + return DT_IN_PROGRESS; +} + +/// @par +/// +/// This method peforms what is often called 'string pulling'. +/// +/// The start position is clamped to the first polygon in the path, and the +/// end position is clamped to the last. So the start and end positions should +/// normally be within or very near the first and last polygons respectively. +/// +/// The returned polygon references represent the reference id of the polygon +/// that is entered at the associated path position. The reference id associated +/// with the end point will always be zero. This allows, for example, matching +/// off-mesh link points to their representative polygons. +/// +/// If the provided result buffers are too small for the entire result set, +/// they will be filled as far as possible from the start toward the end +/// position. +/// dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos, const dtPolyRef* path, const int pathSize, float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const + int* straightPathCount, const int maxStraightPath, const int options) const { dtAssert(m_nav); *straightPathCount = 0; if (!maxStraightPath) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; if (!path[0]) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; - int n = 0; + dtStatus stat = 0; // TODO: Should this be callers responsibility? float closestStartPos[3]; - if (closestPointOnPolyBoundary(path[0], startPos, closestStartPos) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(closestPointOnPolyBoundary(path[0], startPos, closestStartPos))) + return DT_FAILURE | DT_INVALID_PARAM; + + float closestEndPos[3]; + if (dtStatusFailed(closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos))) + return DT_FAILURE | DT_INVALID_PARAM; // Add start point. - dtVcopy(&straightPath[n*3], closestStartPos); - if (straightPathFlags) - straightPathFlags[n] = DT_STRAIGHTPATH_START; - if (straightPathRefs) - straightPathRefs[n] = path[0]; - n++; - if (n >= maxStraightPath) - { - *straightPathCount = n; - return DT_SUCCESS; - } - - float closestEndPos[3]; - if (closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos) != DT_SUCCESS) - return DT_FAILURE; + stat = appendVertex(closestStartPos, DT_STRAIGHTPATH_START, path[0], + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath); + if (stat != DT_IN_PROGRESS) + return stat; if (pathSize > 1) { @@ -1161,24 +1869,39 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en for (int i = 0; i < pathSize; ++i) { float left[3], right[3]; - unsigned char fromType, toType; + unsigned char toType; if (i+1 < pathSize) { + unsigned char fromType; // fromType is ignored. + // Next portal. - if (getPortalPoints(path[i], path[i+1], left, right, fromType, toType) != DT_SUCCESS) + if (dtStatusFailed(getPortalPoints(path[i], path[i+1], left, right, fromType, toType))) { - if (closestPointOnPolyBoundary(path[i], endPos, closestEndPos) != DT_SUCCESS) - return DT_FAILURE; + // Failed to get portal points, in practice this means that path[i+1] is invalid polygon. + // Clamp the end point to path[i], and return the path so far. - dtVcopy(&straightPath[n*3], closestEndPos); - if (straightPathFlags) - straightPathFlags[n] = 0; - if (straightPathRefs) - straightPathRefs[n] = path[i]; - n++; + if (dtStatusFailed(closestPointOnPolyBoundary(path[i], endPos, closestEndPos))) + { + // This should only happen when the first polygon is invalid. + return DT_FAILURE | DT_INVALID_PARAM; + } + + // Apeend portals along the current straight path segment. + if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) + { + // Ignore status return value as we're just about to return anyway. + appendPortals(apexIndex, i, closestEndPos, path, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath, options); + } + + // Ignore status return value as we're just about to return anyway. + appendVertex(closestEndPos, 0, path[i], + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath); - return DT_SUCCESS; + return DT_SUCCESS | DT_PARTIAL_RESULT | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); } // If starting really close the portal, advance. @@ -1195,7 +1918,7 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en dtVcopy(left, closestEndPos); dtVcopy(right, closestEndPos); - fromType = toType = DT_POLYTYPE_GROUND; + toType = DT_POLYTYPE_GROUND; } // Right vertex. @@ -1210,6 +1933,16 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en } else { + // Append portals along the current straight path segment. + if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) + { + stat = appendPortals(apexIndex, leftIndex, portalLeft, path, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath, options); + if (stat != DT_IN_PROGRESS) + return stat; + } + dtVcopy(portalApex, portalLeft); apexIndex = leftIndex; @@ -1220,30 +1953,12 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; dtPolyRef ref = leftPolyRef; - if (!dtVequal(&straightPath[(n-1)*3], portalApex)) - { - // Append new vertex. - dtVcopy(&straightPath[n*3], portalApex); - if (straightPathFlags) - straightPathFlags[n] = flags; - if (straightPathRefs) - straightPathRefs[n] = ref; - n++; - // If reached end of path or there is no space to append more vertices, return. - if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath) - { - *straightPathCount = n; - return DT_SUCCESS; - } - } - else - { - // The vertices are equal, update flags and poly. - if (straightPathFlags) - straightPathFlags[n-1] = flags; - if (straightPathRefs) - straightPathRefs[n-1] = ref; - } + // Append or update vertex + stat = appendVertex(portalApex, flags, ref, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath); + if (stat != DT_IN_PROGRESS) + return stat; dtVcopy(portalLeft, portalApex); dtVcopy(portalRight, portalApex); @@ -1269,6 +1984,16 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en } else { + // Append portals along the current straight path segment. + if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) + { + stat = appendPortals(apexIndex, rightIndex, portalRight, path, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath, options); + if (stat != DT_IN_PROGRESS) + return stat; + } + dtVcopy(portalApex, portalRight); apexIndex = rightIndex; @@ -1278,31 +2003,13 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en else if (rightPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; dtPolyRef ref = rightPolyRef; - - if (!dtVequal(&straightPath[(n-1)*3], portalApex)) - { - // Append new vertex. - dtVcopy(&straightPath[n*3], portalApex); - if (straightPathFlags) - straightPathFlags[n] = flags; - if (straightPathRefs) - straightPathRefs[n] = ref; - n++; - // If reached end of path or there is no space to append more vertices, return. - if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath) - { - *straightPathCount = n; - return DT_SUCCESS; - } - } - else - { - // The vertices are equal, update flags and poly. - if (straightPathFlags) - straightPathFlags[n-1] = flags; - if (straightPathRefs) - straightPathRefs[n-1] = ref; - } + + // Append or update vertex + stat = appendVertex(portalApex, flags, ref, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath); + if (stat != DT_IN_PROGRESS) + return stat; dtVcopy(portalLeft, portalApex); dtVcopy(portalRight, portalApex); @@ -1316,27 +2023,46 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en } } } + + // Append portals along the current straight path segment. + if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) + { + stat = appendPortals(apexIndex, pathSize-1, closestEndPos, path, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath, options); + if (stat != DT_IN_PROGRESS) + return stat; + } } + + // Ignore status return value as we're just about to return anyway. + appendVertex(closestEndPos, DT_STRAIGHTPATH_END, 0, + straightPath, straightPathFlags, straightPathRefs, + straightPathCount, maxStraightPath); - // If the point already exists, remove it and add reappend the actual end location. - if (n > 0 && dtVequal(&straightPath[(n-1)*3], closestEndPos)) - n--; - - // Add end point. - if (n < maxStraightPath) - { - dtVcopy(&straightPath[n*3], closestEndPos); - if (straightPathFlags) - straightPathFlags[n] = DT_STRAIGHTPATH_END; - if (straightPathRefs) - straightPathRefs[n] = 0; - n++; - } - - *straightPathCount = n; - return DT_SUCCESS; + return DT_SUCCESS | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); } +/// @par +/// +/// This method is optimized for small delta movement and a small number of +/// polygons. If used for too great a distance, the result set will form an +/// incomplete path. +/// +/// @p resultPos will equal the @p endPos if the end is reached. +/// Otherwise the closest reachable position will be returned. +/// +/// @p resultPos is not projected onto the surface of the navigation +/// mesh. Use #getPolyHeight if this is needed. +/// +/// This method treats the end position in the same manner as +/// the #raycast method. (As a 2D point.) See that method's documentation +/// for details. +/// +/// If the @p visited array is too small to hold the entire result set, it will +/// be filled as far as possible from the start position toward the end +/// position. +/// dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, const dtQueryFilter* filter, float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const @@ -1347,8 +2073,12 @@ dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* start *visitedCount = 0; // Validate input - if (!startRef) return DT_FAILURE; - if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE; + if (!startRef) + return DT_FAILURE | DT_INVALID_PARAM; + if (!m_nav->isValidPolyRef(startRef)) + return DT_FAILURE | DT_INVALID_PARAM; + + dtStatus status = DT_SUCCESS; static const int MAX_STACK = 48; dtNode* stack[MAX_STACK]; @@ -1513,16 +2243,21 @@ dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* start do { visited[n++] = node->id; + if (n >= maxVisitedSize) + { + status |= DT_BUFFER_TOO_SMALL; + break; + } node = m_tinyNodePool->getNodeAtIdx(node->pidx); } - while (node && n < maxVisitedSize); + while (node); } dtVcopy(resultPos, bestPos); *visitedCount = n; - return DT_SUCCESS; + return status; } @@ -1533,14 +2268,14 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, dtPolyRef to, float* le const dtMeshTile* fromTile = 0; const dtPoly* fromPoly = 0; - if (m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly))) + return DT_FAILURE | DT_INVALID_PARAM; fromType = fromPoly->getType(); const dtMeshTile* toTile = 0; const dtPoly* toPoly = 0; - if (m_nav->getTileAndPolyByRef(to, &toTile, &toPoly) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly))) + return DT_FAILURE | DT_INVALID_PARAM; toType = toPoly->getType(); return getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right); @@ -1562,7 +2297,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, } } if (!link) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; // Handle off-mesh connections. if (fromPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) @@ -1578,7 +2313,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, return DT_SUCCESS; } } - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; } if (toPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) @@ -1593,7 +2328,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, return DT_SUCCESS; } } - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; } // Find portal vertices. @@ -1625,7 +2360,8 @@ dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mi { float left[3], right[3]; unsigned char fromType, toType; - if (!getPortalPoints(from, to, left,right, fromType, toType)) return DT_FAILURE; + if (dtStatusFailed(getPortalPoints(from, to, left,right, fromType, toType))) + return DT_FAILURE | DT_INVALID_PARAM; mid[0] = (left[0]+right[0])*0.5f; mid[1] = (left[1]+right[1])*0.5f; mid[2] = (left[2]+right[2])*0.5f; @@ -1637,79 +2373,197 @@ dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, float* mid) const { float left[3], right[3]; - if (getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right))) + return DT_FAILURE | DT_INVALID_PARAM; mid[0] = (left[0]+right[0])*0.5f; mid[1] = (left[1]+right[1])*0.5f; mid[2] = (left[2]+right[2])*0.5f; return DT_SUCCESS; } + + +/// @par +/// +/// This method is meant to be used for quick, short distance checks. +/// +/// If the path array is too small to hold the result, it will be filled as +/// far as possible from the start postion toward the end position. +/// +/// <b>Using the Hit Parameter (t)</b> +/// +/// If the hit parameter is a very high value (FLT_MAX), then the ray has hit +/// the end position. In this case the path represents a valid corridor to the +/// end position and the value of @p hitNormal is undefined. +/// +/// If the hit parameter is zero, then the start position is on the wall that +/// was hit and the value of @p hitNormal is undefined. +/// +/// If 0 < t < 1.0 then the following applies: +/// +/// @code +/// distanceToHitBorder = distanceToEndPosition * t +/// hitPoint = startPos + (endPos - startPos) * t +/// @endcode +/// +/// <b>Use Case Restriction</b> +/// +/// The raycast ignores the y-value of the end position. (2D check.) This +/// places significant limits on how it can be used. For example: +/// +/// Consider a scene where there is a main floor with a second floor balcony +/// that hangs over the main floor. So the first floor mesh extends below the +/// balcony mesh. The start position is somewhere on the first floor. The end +/// position is on the balcony. +/// +/// The raycast will search toward the end position along the first floor mesh. +/// If it reaches the end position's xz-coordinates it will indicate FLT_MAX +/// (no wall hit), meaning it reached the end position. This is one example of why +/// this method is meant for short distance checks. +/// dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, const float* endPos, const dtQueryFilter* filter, float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const { - dtAssert(m_nav); + dtRaycastHit hit; + hit.path = path; + hit.maxPath = maxPath; + + dtStatus status = raycast(startRef, startPos, endPos, filter, 0, &hit); - *t = 0; + *t = hit.t; + if (hitNormal) + dtVcopy(hitNormal, hit.hitNormal); if (pathCount) - *pathCount = 0; + *pathCount = hit.pathCount; + + return status; +} + + +/// @par +/// +/// This method is meant to be used for quick, short distance checks. +/// +/// If the path array is too small to hold the result, it will be filled as +/// far as possible from the start postion toward the end position. +/// +/// <b>Using the Hit Parameter t of RaycastHit</b> +/// +/// If the hit parameter is a very high value (FLT_MAX), then the ray has hit +/// the end position. In this case the path represents a valid corridor to the +/// end position and the value of @p hitNormal is undefined. +/// +/// If the hit parameter is zero, then the start position is on the wall that +/// was hit and the value of @p hitNormal is undefined. +/// +/// If 0 < t < 1.0 then the following applies: +/// +/// @code +/// distanceToHitBorder = distanceToEndPosition * t +/// hitPoint = startPos + (endPos - startPos) * t +/// @endcode +/// +/// <b>Use Case Restriction</b> +/// +/// The raycast ignores the y-value of the end position. (2D check.) This +/// places significant limits on how it can be used. For example: +/// +/// Consider a scene where there is a main floor with a second floor balcony +/// that hangs over the main floor. So the first floor mesh extends below the +/// balcony mesh. The start position is somewhere on the first floor. The end +/// position is on the balcony. +/// +/// The raycast will search toward the end position along the first floor mesh. +/// If it reaches the end position's xz-coordinates it will indicate FLT_MAX +/// (no wall hit), meaning it reached the end position. This is one example of why +/// this method is meant for short distance checks. +/// +dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, const float* endPos, + const dtQueryFilter* filter, const unsigned int options, + dtRaycastHit* hit, dtPolyRef prevRef) const +{ + dtAssert(m_nav); + hit->t = 0; + hit->pathCount = 0; + hit->pathCost = 0; + // Validate input if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE; + return DT_FAILURE | DT_INVALID_PARAM; + if (prevRef && !m_nav->isValidPolyRef(prevRef)) + return DT_FAILURE | DT_INVALID_PARAM; - dtPolyRef curRef = startRef; - float verts[DT_VERTS_PER_POLYGON*3]; + float dir[3], curPos[3], lastPos[3]; + float verts[DT_VERTS_PER_POLYGON*3+3]; int n = 0; - - hitNormal[0] = 0; - hitNormal[1] = 0; - hitNormal[2] = 0; - + + dtVcopy(curPos, startPos); + dtVsub(dir, endPos, startPos); + dtVset(hit->hitNormal, 0, 0, 0); + + dtStatus status = DT_SUCCESS; + + const dtMeshTile* prevTile, *tile, *nextTile; + const dtPoly* prevPoly, *poly, *nextPoly; + dtPolyRef curRef; + + // The API input has been checked already, skip checking internal data. + curRef = startRef; + tile = 0; + poly = 0; + m_nav->getTileAndPolyByRefUnsafe(curRef, &tile, &poly); + nextTile = prevTile = tile; + nextPoly = prevPoly = poly; + if (prevRef) + m_nav->getTileAndPolyByRefUnsafe(prevRef, &prevTile, &prevPoly); + while (curRef) { // Cast ray against current polygon. - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &tile, &poly); - // Collect vertices. int nv = 0; for (int i = 0; i < (int)poly->vertCount; ++i) { dtVcopy(&verts[nv*3], &tile->verts[poly->verts[i]*3]); nv++; - } + } float tmin, tmax; int segMin, segMax; if (!dtIntersectSegmentPoly2D(startPos, endPos, verts, nv, tmin, tmax, segMin, segMax)) { // Could not hit the polygon, keep the old t and report hit. - if (pathCount) - *pathCount = n; - return DT_SUCCESS; + hit->pathCount = n; + return status; } + + hit->hitEdgeIndex = segMax; + // Keep track of furthest t so far. - if (tmax > *t) - *t = tmax; + if (tmax > hit->t) + hit->t = tmax; // Store visited polygons. - if (n < maxPath) - path[n++] = curRef; - + if (n < hit->maxPath) + hit->path[n++] = curRef; + else + status |= DT_BUFFER_TOO_SMALL; + // Ray end is completely inside the polygon. if (segMax == -1) { - *t = FLT_MAX; - if (pathCount) - *pathCount = n; - return DT_SUCCESS; + hit->t = FLT_MAX; + hit->pathCount = n; + + // add the cost + if (options & DT_RAYCAST_USE_COSTS) + hit->pathCost += filter->getCost(curPos, endPos, prevRef, prevTile, prevPoly, curRef, tile, poly, curRef, tile, poly); + return status; } - + // Follow neighbours. dtPolyRef nextRef = 0; @@ -1722,8 +2576,8 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons continue; // Get pointer to the next polygon. - const dtMeshTile* nextTile = 0; - const dtPoly* nextPoly = 0; + nextTile = 0; + nextPoly = 0; m_nav->getTileAndPolyByRefUnsafe(link->ref, &nextTile, &nextPoly); // Skip off-mesh connections. @@ -1791,6 +2645,24 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons } } + // add the cost + if (options & DT_RAYCAST_USE_COSTS) + { + // compute the intersection point at the furthest end of the polygon + // and correct the height (since the raycast moves in 2d) + dtVcopy(lastPos, curPos); + dtVmad(curPos, startPos, dir, hit->t); + float* e1 = &verts[segMax*3]; + float* e2 = &verts[((segMax+1)%nv)*3]; + float eDir[3], diff[3]; + dtVsub(eDir, e2, e1); + dtVsub(diff, curPos, e1); + float s = dtSqr(eDir[0]) > dtSqr(eDir[2]) ? diff[0] / eDir[0] : diff[2] / eDir[2]; + curPos[1] = e1[1] + eDir[1] * s; + + hit->pathCost += filter->getCost(lastPos, curPos, prevRef, prevTile, prevPoly, curRef, tile, poly, nextRef, nextTile, nextPoly); + } + if (!nextRef) { // No neighbour, we hit a wall. @@ -1802,26 +2674,58 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons const float* vb = &verts[b*3]; const float dx = vb[0] - va[0]; const float dz = vb[2] - va[2]; - hitNormal[0] = dz; - hitNormal[1] = 0; - hitNormal[2] = -dx; - dtVnormalize(hitNormal); + hit->hitNormal[0] = dz; + hit->hitNormal[1] = 0; + hit->hitNormal[2] = -dx; + dtVnormalize(hit->hitNormal); - if (pathCount) - *pathCount = n; - return DT_SUCCESS; + hit->pathCount = n; + return status; } - + // No hit, advance to neighbour polygon. + prevRef = curRef; curRef = nextRef; + prevTile = tile; + tile = nextTile; + prevPoly = poly; + poly = nextPoly; } - if (pathCount) - *pathCount = n; + hit->pathCount = n; - return DT_SUCCESS; + return status; } +/// @par +/// +/// At least one result array must be provided. +/// +/// The order of the result set is from least to highest cost to reach the polygon. +/// +/// A common use case for this method is to perform Dijkstra searches. +/// Candidate polygons are found by searching the graph beginning at the start polygon. +/// +/// If a polygon is not found via the graph search, even if it intersects the +/// search circle, it will not be included in the result set. For example: +/// +/// polyA is the start polygon. +/// polyB shares an edge with polyA. (Is adjacent.) +/// polyC shares an edge with polyB, but not with polyA +/// Even if the search circle overlaps polyC, it will not be included in the +/// result set unless polyB is also in the set. +/// +/// The value of the center point is used as the start position for cost +/// calculations. It is not projected onto the surface of the mesh, so its +/// y-value will effect the costs. +/// +/// Intersection tests occur in 2D. All polygons and the search circle are +/// projected onto the xz-plane. So the y-value of the center point does not +/// effect intersection tests. +/// +/// If the result arrays are to small to hold the entire result set, they will be +/// filled to capacity. +/// dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, const dtQueryFilter* filter, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, @@ -1834,8 +2738,8 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* *resultCount = 0; // Validate input - if (!startRef) return DT_FAILURE; - if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE; + if (!startRef || !m_nav->isValidPolyRef(startRef)) + return DT_FAILURE | DT_INVALID_PARAM; m_nodePool->clear(); m_openList->clear(); @@ -1849,17 +2753,9 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* startNode->flags = DT_NODE_OPEN; m_openList->push(startNode); + dtStatus status = DT_SUCCESS; + int n = 0; - if (n < maxResult) - { - if (resultRef) - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - if (resultCost) - resultCost[n] = 0; - ++n; - } const float radiusSqr = dtSqr(radius); @@ -1884,6 +2780,21 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; if (parentRef) m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); + + if (n < maxResult) + { + if (resultRef) + resultRef[n] = bestRef; + if (resultParent) + resultParent[n] = parentRef; + if (resultCost) + resultCost[n] = bestNode->total; + ++n; + } + else + { + status |= DT_BUFFER_TOO_SMALL; + } for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) { @@ -1915,7 +2826,10 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) + { + status |= DT_OUT_OF_NODES; continue; + } if (neighbourNode->flags & DT_NODE_CLOSED) continue; @@ -1924,14 +2838,19 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* if (neighbourNode->flags == 0) dtVlerp(neighbourNode->pos, va, vb, 0.5f); - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); + float cost = filter->getCost( + bestNode->pos, neighbourNode->pos, + parentRef, parentTile, parentPoly, + bestRef, bestTile, bestPoly, + neighbourRef, neighbourTile, neighbourPoly); + + const float total = bestNode->total + cost; // The node is already in open list and the new result is worse, skip. if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) continue; neighbourNode->id = neighbourRef; - neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->total = total; @@ -1941,16 +2860,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* } else { - if (n < maxResult) - { - if (resultRef) - resultRef[n] = neighbourNode->id; - if (resultParent) - resultParent[n] = m_nodePool->getNodeAtIdx(neighbourNode->pidx)->id; - if (resultCost) - resultCost[n] = neighbourNode->total; - ++n; - } neighbourNode->flags = DT_NODE_OPEN; m_openList->push(neighbourNode); } @@ -1959,9 +2868,31 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* *resultCount = n; - return DT_SUCCESS; + return status; } +/// @par +/// +/// The order of the result set is from least to highest cost. +/// +/// At least one result array must be provided. +/// +/// A common use case for this method is to perform Dijkstra searches. +/// Candidate polygons are found by searching the graph beginning at the start +/// polygon. +/// +/// The same intersection test restrictions that apply to findPolysAroundCircle() +/// method apply to this method. +/// +/// The 3D centroid of the search polygon is used as the start position for cost +/// calculations. +/// +/// Intersection tests occur in 2D. All polygons are projected onto the +/// xz-plane. So the y-values of the vertices do not effect intersection tests. +/// +/// If the result arrays are is too small to hold the entire result set, they will +/// be filled to capacity. +/// dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, const dtQueryFilter* filter, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, @@ -1974,8 +2905,8 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v *resultCount = 0; // Validate input - if (!startRef) return DT_FAILURE; - if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE; + if (!startRef || !m_nav->isValidPolyRef(startRef)) + return DT_FAILURE | DT_INVALID_PARAM; m_nodePool->clear(); m_openList->clear(); @@ -1994,17 +2925,9 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v startNode->flags = DT_NODE_OPEN; m_openList->push(startNode); + dtStatus status = DT_SUCCESS; + int n = 0; - if (n < maxResult) - { - if (resultRef) - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - if (resultCost) - resultCost[n] = 0; - ++n; - } while (!m_openList->empty()) { @@ -2027,6 +2950,22 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; if (parentRef) m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); + + if (n < maxResult) + { + if (resultRef) + resultRef[n] = bestRef; + if (resultParent) + resultParent[n] = parentRef; + if (resultCost) + resultCost[n] = bestNode->total; + + ++n; + } + else + { + status |= DT_BUFFER_TOO_SMALL; + } for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) { @@ -2060,7 +2999,10 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) + { + status |= DT_OUT_OF_NODES; continue; + } if (neighbourNode->flags & DT_NODE_CLOSED) continue; @@ -2069,14 +3011,19 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v if (neighbourNode->flags == 0) dtVlerp(neighbourNode->pos, va, vb, 0.5f); - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); + float cost = filter->getCost( + bestNode->pos, neighbourNode->pos, + parentRef, parentTile, parentPoly, + bestRef, bestTile, bestPoly, + neighbourRef, neighbourTile, neighbourPoly); + + const float total = bestNode->total + cost; // The node is already in open list and the new result is worse, skip. if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) continue; neighbourNode->id = neighbourRef; - neighbourNode->flags &= ~DT_NODE_CLOSED; neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->total = total; @@ -2086,16 +3033,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v } else { - if (n < maxResult) - { - if (resultRef) - resultRef[n] = neighbourNode->id; - if (resultParent) - resultParent[n] = m_nodePool->getNodeAtIdx(neighbourNode->pidx)->id; - if (resultCost) - resultCost[n] = neighbourNode->total; - ++n; - } neighbourNode->flags = DT_NODE_OPEN; m_openList->push(neighbourNode); } @@ -2104,9 +3041,46 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v *resultCount = n; - return DT_SUCCESS; + return status; } +dtStatus dtNavMeshQuery::getPathFromDijkstraSearch(dtPolyRef endRef, dtPolyRef* path, int* pathCount, int maxPath) const +{ + if (!m_nav->isValidPolyRef(endRef) || !path || !pathCount || maxPath < 0) + return DT_FAILURE | DT_INVALID_PARAM; + + *pathCount = 0; + + dtNode* endNode; + if (m_nodePool->findNodes(endRef, &endNode, 1) != 1 || + (endNode->flags & DT_NODE_CLOSED) == 0) + return DT_FAILURE | DT_INVALID_PARAM; + + return getPathToNode(endNode, path, pathCount, maxPath); +} + +/// @par +/// +/// This method is optimized for a small search radius and small number of result +/// polygons. +/// +/// Candidate polygons are found by searching the navigation graph beginning at +/// the start polygon. +/// +/// The same intersection test restrictions that apply to the findPolysAroundCircle +/// mehtod applies to this method. +/// +/// The value of the center point is used as the start point for cost calculations. +/// It is not projected onto the surface of the mesh, so its y-value will effect +/// the costs. +/// +/// Intersection tests occur in 2D. All polygons and the search circle are +/// projected onto the xz-plane. So the y-value of the center point does not +/// effect intersection tests. +/// +/// If the result arrays are is too small to hold the entire result set, they will +/// be filled to capacity. +/// dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, const dtQueryFilter* filter, dtPolyRef* resultRef, dtPolyRef* resultParent, @@ -2118,8 +3092,8 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* *resultCount = 0; // Validate input - if (!startRef) return DT_FAILURE; - if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE; + if (!startRef || !m_nav->isValidPolyRef(startRef)) + return DT_FAILURE | DT_INVALID_PARAM; static const int MAX_STACK = 48; dtNode* stack[MAX_STACK]; @@ -2138,6 +3112,8 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* float pa[DT_VERTS_PER_POLYGON*3]; float pb[DT_VERTS_PER_POLYGON*3]; + dtStatus status = DT_SUCCESS; + int n = 0; if (n < maxResult) { @@ -2146,6 +3122,10 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* resultParent[n] = 0; ++n; } + else + { + status |= DT_BUFFER_TOO_SMALL; + } while (nstack) { @@ -2259,6 +3239,10 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* resultParent[n] = curRef; ++n; } + else + { + status |= DT_BUFFER_TOO_SMALL; + } if (nstack < MAX_STACK) { @@ -2269,17 +3253,18 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* *resultCount = n; - return DT_SUCCESS; + return status; } struct dtSegInterval { + dtPolyRef ref; short tmin, tmax; }; static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, - const short tmin, const short tmax) + const short tmin, const short tmax, const dtPolyRef ref) { if (nints+1 > maxInts) return; // Find insertion point. @@ -2294,13 +3279,26 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, if (nints-idx) memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx)); // Store + ints[idx].ref = ref; ints[idx].tmin = tmin; ints[idx].tmax = tmax; nints++; } +/// @par +/// +/// If the @p segmentRefs parameter is provided, then all polygon segments will be returned. +/// Otherwise only the wall segments are returned. +/// +/// A segment that is normally a portal will be included in the result set as a +/// wall if the @p filter results in the neighbor polygon becoomming impassable. +/// +/// The @p segmentVerts and @p segmentRefs buffers should normally be sized for the +/// maximum segments per polygon of the source navigation mesh. +/// dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segments, int* segmentCount, const int maxSegments) const + float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, + const int maxSegments) const { dtAssert(m_nav); @@ -2308,14 +3306,18 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* const dtMeshTile* tile = 0; const dtPoly* poly = 0; - if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS) - return DT_FAILURE; + if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) + return DT_FAILURE | DT_INVALID_PARAM; int n = 0; static const int MAX_INTERVAL = 16; dtSegInterval ints[MAX_INTERVAL]; int nints; + const bool storePortals = segmentRefs != 0; + + dtStatus status = DT_SUCCESS; + for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++) { // Skip non-solid edges. @@ -2335,54 +3337,95 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); if (filter->passFilter(link->ref, neiTile, neiPoly)) { - insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax); + insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax, link->ref); } } } } } - else if (poly->neis[j]) + else { // Internal edge - const unsigned int idx = (unsigned int)(poly->neis[j]-1); - const dtPolyRef ref = m_nav->getPolyRefBase(tile) | idx; - if (filter->passFilter(ref, tile, &tile->polys[idx])) + dtPolyRef neiRef = 0; + if (poly->neis[j]) + { + const unsigned int idx = (unsigned int)(poly->neis[j]-1); + neiRef = m_nav->getPolyRefBase(tile) | idx; + if (!filter->passFilter(neiRef, tile, &tile->polys[idx])) + neiRef = 0; + } + + // If the edge leads to another polygon and portals are not stored, skip. + if (neiRef != 0 && !storePortals) continue; + + if (n < maxSegments) + { + const float* vj = &tile->verts[poly->verts[j]*3]; + const float* vi = &tile->verts[poly->verts[i]*3]; + float* seg = &segmentVerts[n*6]; + dtVcopy(seg+0, vj); + dtVcopy(seg+3, vi); + if (segmentRefs) + segmentRefs[n] = neiRef; + n++; + } + else + { + status |= DT_BUFFER_TOO_SMALL; + } + + continue; } // Add sentinels - insertInterval(ints, nints, MAX_INTERVAL, -1, 0); - insertInterval(ints, nints, MAX_INTERVAL, 255, 256); + insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0); + insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0); - // Store segment. + // Store segments. const float* vj = &tile->verts[poly->verts[j]*3]; const float* vi = &tile->verts[poly->verts[i]*3]; for (int k = 1; k < nints; ++k) { - // Find the space inbetween the opening areas. - const int imin = ints[k-1].tmax; - const int imax = ints[k].tmin; - if (imin == imax) continue; - if (imin == 0 && imax == 255) + // Portal segment. + if (storePortals && ints[k].ref) { + const float tmin = ints[k].tmin/255.0f; + const float tmax = ints[k].tmax/255.0f; if (n < maxSegments) { - float* seg = &segments[n*6]; + float* seg = &segmentVerts[n*6]; + dtVlerp(seg+0, vj,vi, tmin); + dtVlerp(seg+3, vj,vi, tmax); + if (segmentRefs) + segmentRefs[n] = ints[k].ref; n++; - dtVcopy(seg+0, vj); - dtVcopy(seg+3, vi); + } + else + { + status |= DT_BUFFER_TOO_SMALL; } } - else + + // Wall segment. + const int imin = ints[k-1].tmax; + const int imax = ints[k].tmin; + if (imin != imax) { const float tmin = imin/255.0f; const float tmax = imax/255.0f; if (n < maxSegments) { - float* seg = &segments[n*6]; - n++; + float* seg = &segmentVerts[n*6]; dtVlerp(seg+0, vj,vi, tmin); dtVlerp(seg+3, vj,vi, tmax); + if (segmentRefs) + segmentRefs[n] = 0; + n++; + } + else + { + status |= DT_BUFFER_TOO_SMALL; } } } @@ -2390,9 +3433,19 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* *segmentCount = n; - return DT_SUCCESS; + return status; } +/// @par +/// +/// @p hitPos is not adjusted using the height detail data. +/// +/// @p hitDist will equal the search radius if there is no wall within the +/// radius. In this case the values of @p hitPos and @p hitNormal are +/// undefined. +/// +/// The normal will become unpredicable if @p hitDist is a very small number. +/// dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, const dtQueryFilter* filter, float* hitDist, float* hitPos, float* hitNormal) const @@ -2402,8 +3455,8 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen dtAssert(m_openList); // Validate input - if (!startRef) return DT_FAILURE; - if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE; + if (!startRef || !m_nav->isValidPolyRef(startRef)) + return DT_FAILURE | DT_INVALID_PARAM; m_nodePool->clear(); m_openList->clear(); @@ -2419,6 +3472,8 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen float radiusSqr = dtSqr(maxRadius); + dtStatus status = DT_SUCCESS; + while (!m_openList->empty()) { dtNode* bestNode = m_openList->pop(); @@ -2526,7 +3581,10 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); if (!neighbourNode) + { + status |= DT_OUT_OF_NODES; continue; + } if (neighbourNode->flags & DT_NODE_CLOSED) continue; @@ -2545,7 +3603,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen continue; neighbourNode->id = neighbourRef; - neighbourNode->flags &= ~DT_NODE_CLOSED; + neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); neighbourNode->total = total; @@ -2567,12 +3625,40 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen *hitDist = sqrtf(radiusSqr); - return DT_SUCCESS; + return status; } +bool dtNavMeshQuery::isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const +{ + const dtMeshTile* tile = 0; + const dtPoly* poly = 0; + dtStatus status = m_nav->getTileAndPolyByRef(ref, &tile, &poly); + // If cannot get polygon, assume it does not exists and boundary is invalid. + if (dtStatusFailed(status)) + return false; + // If cannot pass filter, assume flags has changed and boundary is invalid. + if (!filter->passFilter(ref, tile, poly)) + return false; + return true; +} + +/// @par +/// +/// The closed list is the list of polygons that were fully evaluated during +/// the last navigation graph search. (A* or Dijkstra) +/// bool dtNavMeshQuery::isInClosedList(dtPolyRef ref) const { if (!m_nodePool) return false; - const dtNode* node = m_nodePool->findNode(ref); - return node && node->flags & DT_NODE_CLOSED; + + dtNode* nodes[DT_MAX_STATES_PER_NODE]; + int n= m_nodePool->findNodes(ref, nodes, DT_MAX_STATES_PER_NODE); + + for (int i=0; i<n; i++) + { + if (nodes[i]->flags & DT_NODE_CLOSED) + return true; + } + + return false; } diff --git a/deps/recastnavigation/Detour/DetourNode.cpp b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNode.cpp index f7811e3450..48abbba6b5 100644 --- a/deps/recastnavigation/Detour/DetourNode.cpp +++ b/modules/worldengine/deps/recastnavigation/Detour/Source/DetourNode.cpp @@ -22,16 +22,30 @@ #include "DetourCommon.h" #include <string.h> +#ifdef DT_POLYREF64 +// From Thomas Wang, https://gist.github.com/badboy/6267743 inline unsigned int dtHashRef(dtPolyRef a) { - a = (~a) + (a << 18); - a = a ^ (a >> 31); - a = a * 21; - a = a ^ (a >> 11); - a = a + (a << 6); - a = a ^ (a >> 22); - return (unsigned int)a; + a = (~a) + (a << 18); // a = (a << 18) - a - 1; + a = a ^ (a >> 31); + a = a * 21; // a = (a + (a << 2)) + (a << 4); + a = a ^ (a >> 11); + a = a + (a << 6); + a = a ^ (a >> 22); + return (unsigned int)a; } +#else +inline unsigned int dtHashRef(dtPolyRef a) +{ + a += ~(a<<15); + a ^= (a>>10); + a += (a<<3); + a ^= (a>>6); + a += ~(a<<11); + a ^= (a>>16); + return (unsigned int)a; +} +#endif ////////////////////////////////////////////////////////////////////////////////////////// dtNodePool::dtNodePool(int maxNodes, int hashSize) : @@ -43,7 +57,9 @@ dtNodePool::dtNodePool(int maxNodes, int hashSize) : m_nodeCount(0) { dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize); - dtAssert(m_maxNodes > 0); + // pidx is special as 0 means "none" and 1 is the first node. For that reason + // we have 1 fewer nodes available than the number of values it can contain. + dtAssert(m_maxNodes > 0 && m_maxNodes <= DT_NULL_IDX && m_maxNodes <= (1 << DT_NODE_PARENT_BITS) - 1); m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM); m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM); @@ -70,27 +86,46 @@ void dtNodePool::clear() m_nodeCount = 0; } -dtNode* dtNodePool::findNode(dtPolyRef id) +unsigned int dtNodePool::findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes) { + int n = 0; unsigned int bucket = dtHashRef(id) & (m_hashSize-1); dtNodeIndex i = m_first[bucket]; while (i != DT_NULL_IDX) { if (m_nodes[i].id == id) + { + if (n >= maxNodes) + return n; + nodes[n++] = &m_nodes[i]; + } + i = m_next[i]; + } + + return n; +} + +dtNode* dtNodePool::findNode(dtPolyRef id, unsigned char state) +{ + unsigned int bucket = dtHashRef(id) & (m_hashSize-1); + dtNodeIndex i = m_first[bucket]; + while (i != DT_NULL_IDX) + { + if (m_nodes[i].id == id && m_nodes[i].state == state) return &m_nodes[i]; i = m_next[i]; } return 0; } -dtNode* dtNodePool::getNode(dtPolyRef id) +dtNode* dtNodePool::getNode(dtPolyRef id, unsigned char state) { unsigned int bucket = dtHashRef(id) & (m_hashSize-1); dtNodeIndex i = m_first[bucket]; dtNode* node = 0; while (i != DT_NULL_IDX) { - if (m_nodes[i].id == id) + if (m_nodes[i].id == id && m_nodes[i].state == state) return &m_nodes[i]; i = m_next[i]; } @@ -107,6 +142,7 @@ dtNode* dtNodePool::getNode(dtPolyRef id) node->cost = 0; node->total = 0; node->id = id; + node->state = state; node->flags = 0; m_next[i] = m_first[bucket]; diff --git a/modules/worldengine/deps/recastnavigation/README.md b/modules/worldengine/deps/recastnavigation/README.md new file mode 100644 index 0000000000..7db7996366 --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/README.md @@ -0,0 +1,89 @@ + +Recast & Detour +=============== + +[](https://travis-ci.org/recastnavigation/recastnavigation) +[](https://ci.appveyor.com/project/recastnavigation/recastnavigation/branch/master) + +[](http://www.issuestats.com/github/recastnavigation/recastnavigation) +[](http://www.issuestats.com/github/recastnavigation/recastnavigation) + + + +## Recast + +Recast is state of the art navigation mesh construction toolset for games. + +* It is automatic, which means that you can throw any level geometry at it and you will get robust mesh out +* It is fast which means swift turnaround times for level designers +* It is open source so it comes with full source and you can customize it to your heart's content. + +The Recast process starts with constructing a voxel mold from a level geometry +and then casting a navigation mesh over it. The process consists of three steps, +building the voxel mold, partitioning the mold into simple regions, peeling off +the regions as simple polygons. + +1. The voxel mold is build from the input triangle mesh by rasterizing the triangles into a multi-layer heightfield. Some simple filters are then applied to the mold to prune out locations where the character would not be able to move. +2. The walkable areas described by the mold are divided into simple overlayed 2D regions. The resulting regions have only one non-overlapping contour, which simplifies the final step of the process tremendously. +3. The navigation polygons are peeled off from the regions by first tracing the boundaries and then simplifying them. The resulting polygons are finally converted to convex polygons which makes them perfect for pathfinding and spatial reasoning about the level. + + +## Detour + +Recast is accompanied with Detour, path-finding and spatial reasoning toolkit. You can use any navigation mesh with Detour, but of course the data generated with Recast fits perfectly. + +Detour offers simple static navigation mesh which is suitable for many simple cases, as well as tiled navigation mesh which allows you to plug in and out pieces of the mesh. The tiled mesh allows you to create systems where you stream new navigation data in and out as the player progresses the level, or you may regenerate tiles as the world changes. + + +## Recast Demo + +You can find a comprehensive demo project in RecastDemo folder. It is a kitchen sink demo containing all the functionality of the library. If you are new to Recast & Detour, check out [Sample_SoloMesh.cpp](/RecastDemo/Source/Sample_SoloMesh.cpp) to get started with building navmeshes and [NavMeshTesterTool.cpp](/RecastDemo/Source/NavMeshTesterTool.cpp) to see how Detour can be used to find paths. + +### Building RecastDemo + +RecastDemo uses [premake5](http://premake.github.io/) to build platform specific projects. Download it and make sure it's available on your path, or specify the path to it. + +#### Linux + +- Install SDl2 and its dependencies according to your distro's guidelines. +- run `premake5 gmake` from the `RecastDemo` folder. +- `cd Build/gmake` then `make` +- Run `RecastDemo\Bin\RecastDemo` + +#### OSX + +- Grab the latest SDL2 development library dmg from [here](https://www.libsdl.org/download-2.0.php) and place `SDL2.framework` in `/Library/Frameworks/` +- Navigate to the `RecastDemo` folder and run `premake5 xcode4` +- Open `Build/xcode4/recastnavigation.xcworkspace` +- Select the "RecastDemo" project in the left pane, go to the "BuildPhases" tab and expand "Link Binary With Libraries" +- Remove the existing entry for SDL2 (it should have a white box icon) and re-add it by hitting the plus, selecting "Add Other", and selecting `/Library/Frameworks/SDL2.framework`. It should now have a suitcase icon. +- Set the RecastDemo project as the target and build. + +#### Windows + +- Grab the latest SDL2 development library release from [here](https://www.libsdl.org/download-2.0.php) and unzip it `RecastDemo\Contrib`. Rename the SDL folder such that the path `RecastDemo\Contrib\SDL\lib\x86` is valid. +- Run `"premake5" vs2015` from the `RecastDemo` folder +- Open the solution, build, and run. + +### Running Unit tests + +- Follow the instructions to build RecastDemo above. Premake should generate another build target called "Tests". +- Build the "Tests" project. This will generate an executable named "Tests" in `RecastDemo/Bin/` +- Run the "Tests" executable. It will execute all the unit tests, indicate those that failed, and display a count of those that succeeded. + +## Integrating with your own project + +It is recommended to add the source directories `DebugUtils`, `Detour`, `DetourCrowd`, `DetourTileCache`, and `Recast` into your own project depending on which parts of the project you need. For example your level building tool could include `DebugUtils`, `Recast`, and `Detour`, and your game runtime could just include `Detour`. + +## Contributing + +See the [Contributing document](CONTRIBUTING.md) for guidelines for making contributions. + +## Discuss + +- Discuss Recast & Detour: http://groups.google.com/group/recastnavigation +- Development blog: http://digestingduck.blogspot.com/ + +## License + +Recast & Detour is licensed under ZLib license, see License.txt for more information. diff --git a/modules/worldengine/deps/recastnavigation/Recast/Include/Recast.h b/modules/worldengine/deps/recastnavigation/Recast/Include/Recast.h new file mode 100644 index 0000000000..79d77e4a9a --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Recast/Include/Recast.h @@ -0,0 +1,1200 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef RECAST_H +#define RECAST_H + +/// The value of PI used by Recast. +static const float RC_PI = 3.14159265f; + +/// Recast log categories. +/// @see rcContext +enum rcLogCategory +{ + RC_LOG_PROGRESS = 1, ///< A progress log entry. + RC_LOG_WARNING, ///< A warning log entry. + RC_LOG_ERROR, ///< An error log entry. +}; + +/// Recast performance timer categories. +/// @see rcContext +enum rcTimerLabel +{ + /// The user defined total time of the build. + RC_TIMER_TOTAL, + /// A user defined build time. + RC_TIMER_TEMP, + /// The time to rasterize the triangles. (See: #rcRasterizeTriangle) + RC_TIMER_RASTERIZE_TRIANGLES, + /// The time to build the compact heightfield. (See: #rcBuildCompactHeightfield) + RC_TIMER_BUILD_COMPACTHEIGHTFIELD, + /// The total time to build the contours. (See: #rcBuildContours) + RC_TIMER_BUILD_CONTOURS, + /// The time to trace the boundaries of the contours. (See: #rcBuildContours) + RC_TIMER_BUILD_CONTOURS_TRACE, + /// The time to simplify the contours. (See: #rcBuildContours) + RC_TIMER_BUILD_CONTOURS_SIMPLIFY, + /// The time to filter ledge spans. (See: #rcFilterLedgeSpans) + RC_TIMER_FILTER_BORDER, + /// The time to filter low height spans. (See: #rcFilterWalkableLowHeightSpans) + RC_TIMER_FILTER_WALKABLE, + /// The time to apply the median filter. (See: #rcMedianFilterWalkableArea) + RC_TIMER_MEDIAN_AREA, + /// The time to filter low obstacles. (See: #rcFilterLowHangingWalkableObstacles) + RC_TIMER_FILTER_LOW_OBSTACLES, + /// The time to build the polygon mesh. (See: #rcBuildPolyMesh) + RC_TIMER_BUILD_POLYMESH, + /// The time to merge polygon meshes. (See: #rcMergePolyMeshes) + RC_TIMER_MERGE_POLYMESH, + /// The time to erode the walkable area. (See: #rcErodeWalkableArea) + RC_TIMER_ERODE_AREA, + /// The time to mark a box area. (See: #rcMarkBoxArea) + RC_TIMER_MARK_BOX_AREA, + /// The time to mark a cylinder area. (See: #rcMarkCylinderArea) + RC_TIMER_MARK_CYLINDER_AREA, + /// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea) + RC_TIMER_MARK_CONVEXPOLY_AREA, + /// The total time to build the distance field. (See: #rcBuildDistanceField) + RC_TIMER_BUILD_DISTANCEFIELD, + /// The time to build the distances of the distance field. (See: #rcBuildDistanceField) + RC_TIMER_BUILD_DISTANCEFIELD_DIST, + /// The time to blur the distance field. (See: #rcBuildDistanceField) + RC_TIMER_BUILD_DISTANCEFIELD_BLUR, + /// The total time to build the regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) + RC_TIMER_BUILD_REGIONS, + /// The total time to apply the watershed algorithm. (See: #rcBuildRegions) + RC_TIMER_BUILD_REGIONS_WATERSHED, + /// The time to expand regions while applying the watershed algorithm. (See: #rcBuildRegions) + RC_TIMER_BUILD_REGIONS_EXPAND, + /// The time to flood regions while applying the watershed algorithm. (See: #rcBuildRegions) + RC_TIMER_BUILD_REGIONS_FLOOD, + /// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) + RC_TIMER_BUILD_REGIONS_FILTER, + /// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers) + RC_TIMER_BUILD_LAYERS, + /// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail) + RC_TIMER_BUILD_POLYMESHDETAIL, + /// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails) + RC_TIMER_MERGE_POLYMESHDETAIL, + /// The maximum number of timers. (Used for iterating timers.) + RC_MAX_TIMERS +}; + +/// Provides an interface for optional logging and performance tracking of the Recast +/// build process. +/// @ingroup recast +class rcContext +{ +public: + + /// Contructor. + /// @param[in] state TRUE if the logging and performance timers should be enabled. [Default: true] + inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {} + virtual ~rcContext() {} + + /// Enables or disables logging. + /// @param[in] state TRUE if logging should be enabled. + inline void enableLog(bool state) { m_logEnabled = state; } + + /// Clears all log entries. + inline void resetLog() { if (m_logEnabled) doResetLog(); } + + /// Logs a message. + /// @param[in] category The category of the message. + /// @param[in] format The message. + void log(const rcLogCategory category, const char* format, ...); + + /// Enables or disables the performance timers. + /// @param[in] state TRUE if timers should be enabled. + inline void enableTimer(bool state) { m_timerEnabled = state; } + + /// Clears all peformance timers. (Resets all to unused.) + inline void resetTimers() { if (m_timerEnabled) doResetTimers(); } + + /// Starts the specified performance timer. + /// @param label The category of the timer. + inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); } + + /// Stops the specified performance timer. + /// @param label The category of the timer. + inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); } + + /// Returns the total accumulated time of the specified performance timer. + /// @param label The category of the timer. + /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. + inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; } + +protected: + + /// Clears all log entries. + virtual void doResetLog() {} + + /// Logs a message. + /// @param[in] category The category of the message. + /// @param[in] msg The formatted message. + /// @param[in] len The length of the formatted message. + virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {} + + /// Clears all timers. (Resets all to unused.) + virtual void doResetTimers() {} + + /// Starts the specified performance timer. + /// @param[in] label The category of timer. + virtual void doStartTimer(const rcTimerLabel /*label*/) {} + + /// Stops the specified performance timer. + /// @param[in] label The category of the timer. + virtual void doStopTimer(const rcTimerLabel /*label*/) {} + + /// Returns the total accumulated time of the specified performance timer. + /// @param[in] label The category of the timer. + /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. + virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; } + + /// True if logging is enabled. + bool m_logEnabled; + + /// True if the performance timers are enabled. + bool m_timerEnabled; +}; + +/// A helper to first start a timer and then stop it when this helper goes out of scope. +/// @see rcContext +class rcScopedTimer +{ +public: + /// Constructs an instance and starts the timer. + /// @param[in] ctx The context to use. + /// @param[in] label The category of the timer. + inline rcScopedTimer(rcContext* ctx, const rcTimerLabel label) : m_ctx(ctx), m_label(label) { m_ctx->startTimer(m_label); } + inline ~rcScopedTimer() { m_ctx->stopTimer(m_label); } + +private: + // Explicitly disabled copy constructor and copy assignment operator. + rcScopedTimer(const rcScopedTimer&); + rcScopedTimer& operator=(const rcScopedTimer&); + + rcContext* const m_ctx; + const rcTimerLabel m_label; +}; + +/// Specifies a configuration to use when performing Recast builds. +/// @ingroup recast +struct rcConfig +{ + /// The width of the field along the x-axis. [Limit: >= 0] [Units: vx] + int width; + + /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx] + int height; + + /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx] + int tileSize; + + /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx] + int borderSize; + + /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] + float cs; + + /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu] + float ch; + + /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] + float bmin[3]; + + /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] + float bmax[3]; + + /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] + float walkableSlopeAngle; + + /// Minimum floor to 'ceiling' height that will still allow the floor area to + /// be considered walkable. [Limit: >= 3] [Units: vx] + int walkableHeight; + + /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] + int walkableClimb; + + /// The distance to erode/shrink the walkable area of the heightfield away from + /// obstructions. [Limit: >=0] [Units: vx] + int walkableRadius; + + /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] + int maxEdgeLen; + + /// The maximum distance a simplfied contour's border edges should deviate + /// the original raw contour. [Limit: >=0] [Units: vx] + float maxSimplificationError; + + /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx] + int minRegionArea; + + /// Any regions with a span count smaller than this value will, if possible, + /// be merged with larger regions. [Limit: >=0] [Units: vx] + int mergeRegionArea; + + /// The maximum number of vertices allowed for polygons generated during the + /// contour to polygon conversion process. [Limit: >= 3] + int maxVertsPerPoly; + + /// Sets the sampling distance to use when generating the detail mesh. + /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] + float detailSampleDist; + + /// The maximum distance the detail mesh surface should deviate from heightfield + /// data. (For height detail only.) [Limit: >=0] [Units: wu] + float detailSampleMaxError; +}; + +/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax. +static const int RC_SPAN_HEIGHT_BITS = 16; +/// Defines the maximum value for rcSpan::smin and rcSpan::smax. +static const int RC_SPAN_MAX_HEIGHT = (1 << RC_SPAN_HEIGHT_BITS) - 1; + +/// The number of spans allocated per span spool. +/// @see rcSpanPool +static const int RC_SPANS_PER_POOL = 2048; + +/// Represents a span in a heightfield. +/// @see rcHeightfield +struct rcSpan +{ + unsigned int smin : RC_SPAN_HEIGHT_BITS; ///< The lower limit of the span. [Limit: < #smax] + unsigned int smax : RC_SPAN_HEIGHT_BITS; ///< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT] + unsigned char area; ///< The area id assigned to the span. + rcSpan* next; ///< The next span higher up in column. +}; + +/// A memory pool used for quick allocation of spans within a heightfield. +/// @see rcHeightfield +struct rcSpanPool +{ + rcSpanPool* next; ///< The next span pool. + rcSpan items[RC_SPANS_PER_POOL]; ///< Array of spans in the pool. +}; + +/// A dynamic heightfield representing obstructed space. +/// @ingroup recast +struct rcHeightfield +{ + rcHeightfield(); + ~rcHeightfield(); + + int width; ///< The width of the heightfield. (Along the x-axis in cell units.) + int height; ///< The height of the heightfield. (Along the z-axis in cell units.) + float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)] + float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] + float cs; ///< The size of each cell. (On the xz-plane.) + float ch; ///< The height of each cell. (The minimum increment along the y-axis.) + rcSpan** spans; ///< Heightfield of spans (width*height). + rcSpanPool* pools; ///< Linked list of span pools. + rcSpan* freelist; ///< The next free span. + +private: + // Explicitly-disabled copy constructor and copy assignment operator. + rcHeightfield(const rcHeightfield&); + rcHeightfield& operator=(const rcHeightfield&); +}; + +/// Provides information on the content of a cell column in a compact heightfield. +struct rcCompactCell +{ + unsigned int index : 24; ///< Index to the first span in the column. + unsigned int count : 8; ///< Number of spans in the column. +}; + +/// Represents a span of unobstructed space within a compact heightfield. +struct rcCompactSpan +{ + unsigned short y; ///< The lower extent of the span. (Measured from the heightfield's base.) + unsigned short reg; ///< The id of the region the span belongs to. (Or zero if not in a region.) + unsigned int con : 24; ///< Packed neighbor connection data. + unsigned int h : 8; ///< The height of the span. (Measured from #y.) +}; + +/// A compact, static heightfield representing unobstructed space. +/// @ingroup recast +struct rcCompactHeightfield +{ + int width; ///< The width of the heightfield. (Along the x-axis in cell units.) + int height; ///< The height of the heightfield. (Along the z-axis in cell units.) + int spanCount; ///< The number of spans in the heightfield. + int walkableHeight; ///< The walkable height used during the build of the field. (See: rcConfig::walkableHeight) + int walkableClimb; ///< The walkable climb used during the build of the field. (See: rcConfig::walkableClimb) + int borderSize; ///< The AABB border size used during the build of the field. (See: rcConfig::borderSize) + unsigned short maxDistance; ///< The maximum distance value of any span within the field. + unsigned short maxRegions; ///< The maximum region id of any span within the field. + float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)] + float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] + float cs; ///< The size of each cell. (On the xz-plane.) + float ch; ///< The height of each cell. (The minimum increment along the y-axis.) + rcCompactCell* cells; ///< Array of cells. [Size: #width*#height] + rcCompactSpan* spans; ///< Array of spans. [Size: #spanCount] + unsigned short* dist; ///< Array containing border distance data. [Size: #spanCount] + unsigned char* areas; ///< Array containing area id data. [Size: #spanCount] +}; + +/// Represents a heightfield layer within a layer set. +/// @see rcHeightfieldLayerSet +struct rcHeightfieldLayer +{ + float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)] + float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] + float cs; ///< The size of each cell. (On the xz-plane.) + float ch; ///< The height of each cell. (The minimum increment along the y-axis.) + int width; ///< The width of the heightfield. (Along the x-axis in cell units.) + int height; ///< The height of the heightfield. (Along the z-axis in cell units.) + int minx; ///< The minimum x-bounds of usable data. + int maxx; ///< The maximum x-bounds of usable data. + int miny; ///< The minimum y-bounds of usable data. (Along the z-axis.) + int maxy; ///< The maximum y-bounds of usable data. (Along the z-axis.) + int hmin; ///< The minimum height bounds of usable data. (Along the y-axis.) + int hmax; ///< The maximum height bounds of usable data. (Along the y-axis.) + unsigned char* heights; ///< The heightfield. [Size: width * height] + unsigned char* areas; ///< Area ids. [Size: Same as #heights] + unsigned char* cons; ///< Packed neighbor connection information. [Size: Same as #heights] +}; + +/// Represents a set of heightfield layers. +/// @ingroup recast +/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet +struct rcHeightfieldLayerSet +{ + rcHeightfieldLayer* layers; ///< The layers in the set. [Size: #nlayers] + int nlayers; ///< The number of layers in the set. +}; + +/// Represents a simple, non-overlapping contour in field space. +struct rcContour +{ + int* verts; ///< Simplified contour vertex and connection data. [Size: 4 * #nverts] + int nverts; ///< The number of vertices in the simplified contour. + int* rverts; ///< Raw contour vertex and connection data. [Size: 4 * #nrverts] + int nrverts; ///< The number of vertices in the raw contour. + unsigned short reg; ///< The region id of the contour. + unsigned char area; ///< The area id of the contour. +}; + +/// Represents a group of related contours. +/// @ingroup recast +struct rcContourSet +{ + rcContour* conts; ///< An array of the contours in the set. [Size: #nconts] + int nconts; ///< The number of contours in the set. + float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)] + float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] + float cs; ///< The size of each cell. (On the xz-plane.) + float ch; ///< The height of each cell. (The minimum increment along the y-axis.) + int width; ///< The width of the set. (Along the x-axis in cell units.) + int height; ///< The height of the set. (Along the z-axis in cell units.) + int borderSize; ///< The AABB border size used to generate the source data from which the contours were derived. + float maxError; ///< The max edge error that this contour set was simplified with. +}; + +/// Represents a polygon mesh suitable for use in building a navigation mesh. +/// @ingroup recast +struct rcPolyMesh +{ + unsigned short* verts; ///< The mesh vertices. [Form: (x, y, z) * #nverts] + unsigned short* polys; ///< Polygon and neighbor data. [Length: #maxpolys * 2 * #nvp] + unsigned short* regs; ///< The region id assigned to each polygon. [Length: #maxpolys] + unsigned short* flags; ///< The user defined flags for each polygon. [Length: #maxpolys] + unsigned char* areas; ///< The area id assigned to each polygon. [Length: #maxpolys] + int nverts; ///< The number of vertices. + int npolys; ///< The number of polygons. + int maxpolys; ///< The number of allocated polygons. + int nvp; ///< The maximum number of vertices per polygon. + float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)] + float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)] + float cs; ///< The size of each cell. (On the xz-plane.) + float ch; ///< The height of each cell. (The minimum increment along the y-axis.) + int borderSize; ///< The AABB border size used to generate the source data from which the mesh was derived. + float maxEdgeError; ///< The max error of the polygon edges in the mesh. +}; + +/// Contains triangle meshes that represent detailed height data associated +/// with the polygons in its associated polygon mesh object. +/// @ingroup recast +struct rcPolyMeshDetail +{ + unsigned int* meshes; ///< The sub-mesh data. [Size: 4*#nmeshes] + float* verts; ///< The mesh vertices. [Size: 3*#nverts] + unsigned char* tris; ///< The mesh triangles. [Size: 4*#ntris] + int nmeshes; ///< The number of sub-meshes defined by #meshes. + int nverts; ///< The number of vertices in #verts. + int ntris; ///< The number of triangles in #tris. +}; + +/// @name Allocation Functions +/// Functions used to allocate and de-allocate Recast objects. +/// @see rcAllocSetCustom +/// @{ + +/// Allocates a heightfield object using the Recast allocator. +/// @return A heightfield that is ready for initialization, or null on failure. +/// @ingroup recast +/// @see rcCreateHeightfield, rcFreeHeightField +rcHeightfield* rcAllocHeightfield(); + +/// Frees the specified heightfield object using the Recast allocator. +/// @param[in] hf A heightfield allocated using #rcAllocHeightfield +/// @ingroup recast +/// @see rcAllocHeightfield +void rcFreeHeightField(rcHeightfield* hf); + +/// Allocates a compact heightfield object using the Recast allocator. +/// @return A compact heightfield that is ready for initialization, or null on failure. +/// @ingroup recast +/// @see rcBuildCompactHeightfield, rcFreeCompactHeightfield +rcCompactHeightfield* rcAllocCompactHeightfield(); + +/// Frees the specified compact heightfield object using the Recast allocator. +/// @param[in] chf A compact heightfield allocated using #rcAllocCompactHeightfield +/// @ingroup recast +/// @see rcAllocCompactHeightfield +void rcFreeCompactHeightfield(rcCompactHeightfield* chf); + +/// Allocates a heightfield layer set using the Recast allocator. +/// @return A heightfield layer set that is ready for initialization, or null on failure. +/// @ingroup recast +/// @see rcBuildHeightfieldLayers, rcFreeHeightfieldLayerSet +rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet(); + +/// Frees the specified heightfield layer set using the Recast allocator. +/// @param[in] lset A heightfield layer set allocated using #rcAllocHeightfieldLayerSet +/// @ingroup recast +/// @see rcAllocHeightfieldLayerSet +void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset); + +/// Allocates a contour set object using the Recast allocator. +/// @return A contour set that is ready for initialization, or null on failure. +/// @ingroup recast +/// @see rcBuildContours, rcFreeContourSet +rcContourSet* rcAllocContourSet(); + +/// Frees the specified contour set using the Recast allocator. +/// @param[in] cset A contour set allocated using #rcAllocContourSet +/// @ingroup recast +/// @see rcAllocContourSet +void rcFreeContourSet(rcContourSet* cset); + +/// Allocates a polygon mesh object using the Recast allocator. +/// @return A polygon mesh that is ready for initialization, or null on failure. +/// @ingroup recast +/// @see rcBuildPolyMesh, rcFreePolyMesh +rcPolyMesh* rcAllocPolyMesh(); + +/// Frees the specified polygon mesh using the Recast allocator. +/// @param[in] pmesh A polygon mesh allocated using #rcAllocPolyMesh +/// @ingroup recast +/// @see rcAllocPolyMesh +void rcFreePolyMesh(rcPolyMesh* pmesh); + +/// Allocates a detail mesh object using the Recast allocator. +/// @return A detail mesh that is ready for initialization, or null on failure. +/// @ingroup recast +/// @see rcBuildPolyMeshDetail, rcFreePolyMeshDetail +rcPolyMeshDetail* rcAllocPolyMeshDetail(); + +/// Frees the specified detail mesh using the Recast allocator. +/// @param[in] dmesh A detail mesh allocated using #rcAllocPolyMeshDetail +/// @ingroup recast +/// @see rcAllocPolyMeshDetail +void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh); + +/// @} + +/// Heighfield border flag. +/// If a heightfield region ID has this bit set, then the region is a border +/// region and its spans are considered unwalkable. +/// (Used during the region and contour build process.) +/// @see rcCompactSpan::reg +static const unsigned short RC_BORDER_REG = 0x8000; + +/// Polygon touches multiple regions. +/// If a polygon has this region ID it was merged with or created +/// from polygons of different regions during the polymesh +/// build step that removes redundant border vertices. +/// (Used during the polymesh and detail polymesh build processes) +/// @see rcPolyMesh::regs +static const unsigned short RC_MULTIPLE_REGS = 0; + +/// Border vertex flag. +/// If a region ID has this bit set, then the associated element lies on +/// a tile border. If a contour vertex's region ID has this bit set, the +/// vertex will later be removed in order to match the segments and vertices +/// at tile boundaries. +/// (Used during the build process.) +/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts +static const int RC_BORDER_VERTEX = 0x10000; + +/// Area border flag. +/// If a region ID has this bit set, then the associated element lies on +/// the border of an area. +/// (Used during the region and contour build process.) +/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts +static const int RC_AREA_BORDER = 0x20000; + +/// Contour build flags. +/// @see rcBuildContours +enum rcBuildContoursFlags +{ + RC_CONTOUR_TESS_WALL_EDGES = 0x01, ///< Tessellate solid (impassable) edges during contour simplification. + RC_CONTOUR_TESS_AREA_EDGES = 0x02, ///< Tessellate edges between areas during contour simplification. +}; + +/// Applied to the region id field of contour vertices in order to extract the region id. +/// The region id field of a vertex may have several flags applied to it. So the +/// fields value can't be used directly. +/// @see rcContour::verts, rcContour::rverts +static const int RC_CONTOUR_REG_MASK = 0xffff; + +/// An value which indicates an invalid index within a mesh. +/// @note This does not necessarily indicate an error. +/// @see rcPolyMesh::polys +static const unsigned short RC_MESH_NULL_IDX = 0xffff; + +/// Represents the null area. +/// When a data element is given this value it is considered to no longer be +/// assigned to a usable area. (E.g. It is unwalkable.) +static const unsigned char RC_NULL_AREA = 0; + +/// The default area id used to indicate a walkable polygon. +/// This is also the maximum allowed area id, and the only non-null area id +/// recognized by some steps in the build process. +static const unsigned char RC_WALKABLE_AREA = 63; + +/// The value returned by #rcGetCon if the specified direction is not connected +/// to another span. (Has no neighbor.) +static const int RC_NOT_CONNECTED = 0x3f; + +/// @name General helper functions +/// @{ + +/// Used to ignore a function parameter. VS complains about unused parameters +/// and this silences the warning. +/// @param [in] _ Unused parameter +template<class T> void rcIgnoreUnused(const T&) { } + +/// Swaps the values of the two parameters. +/// @param[in,out] a Value A +/// @param[in,out] b Value B +template<class T> inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; } + +/// Returns the minimum of two values. +/// @param[in] a Value A +/// @param[in] b Value B +/// @return The minimum of the two values. +template<class T> inline T rcMin(T a, T b) { return a < b ? a : b; } + +/// Returns the maximum of two values. +/// @param[in] a Value A +/// @param[in] b Value B +/// @return The maximum of the two values. +template<class T> inline T rcMax(T a, T b) { return a > b ? a : b; } + +/// Returns the absolute value. +/// @param[in] a The value. +/// @return The absolute value of the specified value. +template<class T> inline T rcAbs(T a) { return a < 0 ? -a : a; } + +/// Returns the square of the value. +/// @param[in] a The value. +/// @return The square of the value. +template<class T> inline T rcSqr(T a) { return a*a; } + +/// Clamps the value to the specified range. +/// @param[in] v The value to clamp. +/// @param[in] mn The minimum permitted return value. +/// @param[in] mx The maximum permitted return value. +/// @return The value, clamped to the specified range. +template<class T> inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } + +/// Returns the square root of the value. +/// @param[in] x The value. +/// @return The square root of the vlaue. +float rcSqrt(float x); + +/// @} +/// @name Vector helper functions. +/// @{ + +/// Derives the cross product of two vectors. (@p v1 x @p v2) +/// @param[out] dest The cross product. [(x, y, z)] +/// @param[in] v1 A Vector [(x, y, z)] +/// @param[in] v2 A vector [(x, y, z)] +inline void rcVcross(float* dest, const float* v1, const float* v2) +{ + dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; + dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; + dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +/// Derives the dot product of two vectors. (@p v1 . @p v2) +/// @param[in] v1 A Vector [(x, y, z)] +/// @param[in] v2 A vector [(x, y, z)] +/// @return The dot product. +inline float rcVdot(const float* v1, const float* v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s)) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v1 The base vector. [(x, y, z)] +/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)] +/// @param[in] s The amount to scale @p v2 by before adding to @p v1. +inline void rcVmad(float* dest, const float* v1, const float* v2, const float s) +{ + dest[0] = v1[0]+v2[0]*s; + dest[1] = v1[1]+v2[1]*s; + dest[2] = v1[2]+v2[2]*s; +} + +/// Performs a vector addition. (@p v1 + @p v2) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v1 The base vector. [(x, y, z)] +/// @param[in] v2 The vector to add to @p v1. [(x, y, z)] +inline void rcVadd(float* dest, const float* v1, const float* v2) +{ + dest[0] = v1[0]+v2[0]; + dest[1] = v1[1]+v2[1]; + dest[2] = v1[2]+v2[2]; +} + +/// Performs a vector subtraction. (@p v1 - @p v2) +/// @param[out] dest The result vector. [(x, y, z)] +/// @param[in] v1 The base vector. [(x, y, z)] +/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)] +inline void rcVsub(float* dest, const float* v1, const float* v2) +{ + dest[0] = v1[0]-v2[0]; + dest[1] = v1[1]-v2[1]; + dest[2] = v1[2]-v2[2]; +} + +/// Selects the minimum value of each element from the specified vectors. +/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)] +/// @param[in] v A vector. [(x, y, z)] +inline void rcVmin(float* mn, const float* v) +{ + mn[0] = rcMin(mn[0], v[0]); + mn[1] = rcMin(mn[1], v[1]); + mn[2] = rcMin(mn[2], v[2]); +} + +/// Selects the maximum value of each element from the specified vectors. +/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)] +/// @param[in] v A vector. [(x, y, z)] +inline void rcVmax(float* mx, const float* v) +{ + mx[0] = rcMax(mx[0], v[0]); + mx[1] = rcMax(mx[1], v[1]); + mx[2] = rcMax(mx[2], v[2]); +} + +/// Performs a vector copy. +/// @param[out] dest The result. [(x, y, z)] +/// @param[in] v The vector to copy. [(x, y, z)] +inline void rcVcopy(float* dest, const float* v) +{ + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; +} + +/// Returns the distance between two points. +/// @param[in] v1 A point. [(x, y, z)] +/// @param[in] v2 A point. [(x, y, z)] +/// @return The distance between the two points. +inline float rcVdist(const float* v1, const float* v2) +{ + float dx = v2[0] - v1[0]; + float dy = v2[1] - v1[1]; + float dz = v2[2] - v1[2]; + return rcSqrt(dx*dx + dy*dy + dz*dz); +} + +/// Returns the square of the distance between two points. +/// @param[in] v1 A point. [(x, y, z)] +/// @param[in] v2 A point. [(x, y, z)] +/// @return The square of the distance between the two points. +inline float rcVdistSqr(const float* v1, const float* v2) +{ + float dx = v2[0] - v1[0]; + float dy = v2[1] - v1[1]; + float dz = v2[2] - v1[2]; + return dx*dx + dy*dy + dz*dz; +} + +/// Normalizes the vector. +/// @param[in,out] v The vector to normalize. [(x, y, z)] +inline void rcVnormalize(float* v) +{ + float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2])); + v[0] *= d; + v[1] *= d; + v[2] *= d; +} + +/// @} +/// @name Heightfield Functions +/// @see rcHeightfield +/// @{ + +/// Calculates the bounding box of an array of vertices. +/// @ingroup recast +/// @param[in] verts An array of vertices. [(x, y, z) * @p nv] +/// @param[in] nv The number of vertices in the @p verts array. +/// @param[out] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu] +/// @param[out] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu] +void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax); + +/// Calculates the grid size based on the bounding box and grid cell size. +/// @ingroup recast +/// @param[in] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu] +/// @param[in] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu] +/// @param[in] cs The xz-plane cell size. [Limit: > 0] [Units: wu] +/// @param[out] w The width along the x-axis. [Limit: >= 0] [Units: vx] +/// @param[out] h The height along the z-axis. [Limit: >= 0] [Units: vx] +void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h); + +/// Initializes a new heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] hf The allocated heightfield to initialize. +/// @param[in] width The width of the field along the x-axis. [Limit: >= 0] [Units: vx] +/// @param[in] height The height of the field along the z-axis. [Limit: >= 0] [Units: vx] +/// @param[in] bmin The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] +/// @param[in] bmax The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] +/// @param[in] cs The xz-plane cell size to use for the field. [Limit: > 0] [Units: wu] +/// @param[in] ch The y-axis cell size to use for field. [Limit: > 0] [Units: wu] +/// @returns True if the operation completed successfully. +bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, + const float* bmin, const float* bmax, + float cs, float ch); + +/// Sets the area id of all triangles with a slope below the specified value +/// to #RC_WALKABLE_AREA. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable. +/// [Limits: 0 <= value < 90] [Units: Degrees] +/// @param[in] verts The vertices. [(x, y, z) * @p nv] +/// @param[in] nv The number of vertices. +/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt] +/// @param[in] nt The number of triangles. +/// @param[out] areas The triangle area ids. [Length: >= @p nt] +void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, + const int* tris, int nt, unsigned char* areas); + +/// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable. +/// [Limits: 0 <= value < 90] [Units: Degrees] +/// @param[in] verts The vertices. [(x, y, z) * @p nv] +/// @param[in] nv The number of vertices. +/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt] +/// @param[in] nt The number of triangles. +/// @param[out] areas The triangle area ids. [Length: >= @p nt] +void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, + const int* tris, int nt, unsigned char* areas); + +/// Adds a span to the specified heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] hf An initialized heightfield. +/// @param[in] x The width index where the span is to be added. +/// [Limits: 0 <= value < rcHeightfield::width] +/// @param[in] y The height index where the span is to be added. +/// [Limits: 0 <= value < rcHeightfield::height] +/// @param[in] smin The minimum height of the span. [Limit: < @p smax] [Units: vx] +/// @param[in] smax The maximum height of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT] [Units: vx] +/// @param[in] area The area id of the span. [Limit: <= #RC_WALKABLE_AREA) +/// @param[in] flagMergeThr The merge theshold. [Limit: >= 0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y, + const unsigned short smin, const unsigned short smax, + const unsigned char area, const int flagMergeThr); + +/// Rasterizes a triangle into the specified heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] v0 Triangle vertex 0 [(x, y, z)] +/// @param[in] v1 Triangle vertex 1 [(x, y, z)] +/// @param[in] v2 Triangle vertex 2 [(x, y, z)] +/// @param[in] area The area id of the triangle. [Limit: <= #RC_WALKABLE_AREA] +/// @param[in,out] solid An initialized heightfield. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// [Limit: >= 0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, + const unsigned char area, rcHeightfield& solid, + const int flagMergeThr = 1); + +/// Rasterizes an indexed triangle mesh into the specified heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] verts The vertices. [(x, y, z) * @p nv] +/// @param[in] nv The number of vertices. +/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt] +/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] +/// @param[in] nt The number of triangles. +/// @param[in,out] solid An initialized heightfield. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// [Limit: >= 0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, + const int* tris, const unsigned char* areas, const int nt, + rcHeightfield& solid, const int flagMergeThr = 1); + +/// Rasterizes an indexed triangle mesh into the specified heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] verts The vertices. [(x, y, z) * @p nv] +/// @param[in] nv The number of vertices. +/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt] +/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] +/// @param[in] nt The number of triangles. +/// @param[in,out] solid An initialized heightfield. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// [Limit: >= 0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, + const unsigned short* tris, const unsigned char* areas, const int nt, + rcHeightfield& solid, const int flagMergeThr = 1); + +/// Rasterizes triangles into the specified heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] verts The triangle vertices. [(ax, ay, az, bx, by, bz, cx, by, cx) * @p nt] +/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] +/// @param[in] nt The number of triangles. +/// @param[in,out] solid An initialized heightfield. +/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. +/// [Limit: >= 0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, + rcHeightfield& solid, const int flagMergeThr = 1); + +/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neighbor. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. +/// [Limit: >=0] [Units: vx] +/// @param[in,out] solid A fully built heightfield. (All spans have been added.) +void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid); + +/// Marks spans that are ledges as not-walkable. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to +/// be considered walkable. [Limit: >= 3] [Units: vx] +/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. +/// [Limit: >=0] [Units: vx] +/// @param[in,out] solid A fully built heightfield. (All spans have been added.) +void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, + const int walkableClimb, rcHeightfield& solid); + +/// Marks walkable spans as not walkable if the clearence above the span is less than the specified height. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to +/// be considered walkable. [Limit: >= 3] [Units: vx] +/// @param[in,out] solid A fully built heightfield. (All spans have been added.) +void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid); + +/// Returns the number of spans contained in the specified heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] hf An initialized heightfield. +/// @returns The number of spans in the heightfield. +int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); + +/// @} +/// @name Compact Heightfield Functions +/// @see rcCompactHeightfield +/// @{ + +/// Builds a compact heightfield representing open space, from a heightfield representing solid space. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area +/// to be considered walkable. [Limit: >= 3] [Units: vx] +/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. +/// [Limit: >=0] [Units: vx] +/// @param[in] hf The heightfield to be compacted. +/// @param[out] chf The resulting compact heightfield. (Must be pre-allocated.) +/// @returns True if the operation completed successfully. +bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, + rcHeightfield& hf, rcCompactHeightfield& chf); + +/// Erodes the walkable area within the heightfield by the specified radius. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] radius The radius of erosion. [Limits: 0 < value < 255] [Units: vx] +/// @param[in,out] chf The populated compact heightfield to erode. +/// @returns True if the operation completed successfully. +bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf); + +/// Applies a median filter to walkable area types (based on area id), removing noise. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] chf A populated compact heightfield. +/// @returns True if the operation completed successfully. +bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); + +/// Applies an area id to all spans within the specified bounding box. (AABB) +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] bmin The minimum of the bounding box. [(x, y, z)] +/// @param[in] bmax The maximum of the bounding box. [(x, y, z)] +/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] +/// @param[in,out] chf A populated compact heightfield. +void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, + rcCompactHeightfield& chf); + +/// Applies the area id to the all spans within the specified convex polygon. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] verts The vertices of the polygon [Fomr: (x, y, z) * @p nverts] +/// @param[in] nverts The number of vertices in the polygon. +/// @param[in] hmin The height of the base of the polygon. +/// @param[in] hmax The height of the top of the polygon. +/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] +/// @param[in,out] chf A populated compact heightfield. +void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, + const float hmin, const float hmax, unsigned char areaId, + rcCompactHeightfield& chf); + +/// Helper function to offset voncex polygons for rcMarkConvexPolyArea. +/// @ingroup recast +/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p nverts] +/// @param[in] nverts The number of vertices in the polygon. +/// @param[out] outVerts The offset vertices (should hold up to 2 * @p nverts) [Form: (x, y, z) * return value] +/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts. +/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts. +int rcOffsetPoly(const float* verts, const int nverts, const float offset, + float* outVerts, const int maxOutVerts); + +/// Applies the area id to all spans within the specified cylinder. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)] +/// @param[in] r The radius of the cylinder. +/// @param[in] h The height of the cylinder. +/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] +/// @param[in,out] chf A populated compact heightfield. +void rcMarkCylinderArea(rcContext* ctx, const float* pos, + const float r, const float h, unsigned char areaId, + rcCompactHeightfield& chf); + +/// Builds the distance field for the specified compact heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] chf A populated compact heightfield. +/// @returns True if the operation completed successfully. +bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf); + +/// Builds region data for the heightfield using watershed partitioning. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] chf A populated compact heightfield. +/// @param[in] borderSize The size of the non-navigable border around the heightfield. +/// [Limit: >=0] [Units: vx] +/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. +/// [Limit: >=0] [Units: vx]. +/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, +/// be merged with larger regions. [Limit: >=0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, + const int borderSize, const int minRegionArea, const int mergeRegionArea); + +/// Builds region data for the heightfield by partitioning the heightfield in non-overlapping layers. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] chf A populated compact heightfield. +/// @param[in] borderSize The size of the non-navigable border around the heightfield. +/// [Limit: >=0] [Units: vx] +/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. +/// [Limit: >=0] [Units: vx]. +/// @returns True if the operation completed successfully. +bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf, + const int borderSize, const int minRegionArea); + +/// Builds region data for the heightfield using simple monotone partitioning. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in,out] chf A populated compact heightfield. +/// @param[in] borderSize The size of the non-navigable border around the heightfield. +/// [Limit: >=0] [Units: vx] +/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. +/// [Limit: >=0] [Units: vx]. +/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, +/// be merged with larger regions. [Limit: >=0] [Units: vx] +/// @returns True if the operation completed successfully. +bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, + const int borderSize, const int minRegionArea, const int mergeRegionArea); + +/// Sets the neighbor connection data for the specified direction. +/// @param[in] s The span to update. +/// @param[in] dir The direction to set. [Limits: 0 <= value < 4] +/// @param[in] i The index of the neighbor span. +inline void rcSetCon(rcCompactSpan& s, int dir, int i) +{ + const unsigned int shift = (unsigned int)dir*6; + unsigned int con = s.con; + s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift); +} + +/// Gets neighbor connection data for the specified direction. +/// @param[in] s The span to check. +/// @param[in] dir The direction to check. [Limits: 0 <= value < 4] +/// @return The neighbor connection data for the specified direction, +/// or #RC_NOT_CONNECTED if there is no connection. +inline int rcGetCon(const rcCompactSpan& s, int dir) +{ + const unsigned int shift = (unsigned int)dir*6; + return (s.con >> shift) & 0x3f; +} + +/// Gets the standard width (x-axis) offset for the specified direction. +/// @param[in] dir The direction. [Limits: 0 <= value < 4] +/// @return The width offset to apply to the current cell position to move +/// in the direction. +inline int rcGetDirOffsetX(int dir) +{ + static const int offset[4] = { -1, 0, 1, 0, }; + return offset[dir&0x03]; +} + +/// Gets the standard height (z-axis) offset for the specified direction. +/// @param[in] dir The direction. [Limits: 0 <= value < 4] +/// @return The height offset to apply to the current cell position to move +/// in the direction. +inline int rcGetDirOffsetY(int dir) +{ + static const int offset[4] = { 0, 1, 0, -1 }; + return offset[dir&0x03]; +} + +/// Gets the direction for the specified offset. One of x and y should be 0. +/// @param[in] x The x offset. [Limits: -1 <= value <= 1] +/// @param[in] y The y offset. [Limits: -1 <= value <= 1] +/// @return The direction that represents the offset. +inline int rcGetDirForOffset(int x, int y) +{ + static const int dirs[5] = { 3, 0, -1, 2, 1 }; + return dirs[((y+1)<<1)+x]; +} + +/// @} +/// @name Layer, Contour, Polymesh, and Detail Mesh Functions +/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail +/// @{ + +/// Builds a layer set from the specified compact heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] chf A fully built compact heightfield. +/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0] +/// [Units: vx] +/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area +/// to be considered walkable. [Limit: >= 3] [Units: vx] +/// @param[out] lset The resulting layer set. (Must be pre-allocated.) +/// @returns True if the operation completed successfully. +bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, + const int borderSize, const int walkableHeight, + rcHeightfieldLayerSet& lset); + +/// Builds a contour set from the region outlines in the provided compact heightfield. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] chf A fully built compact heightfield. +/// @param[in] maxError The maximum distance a simplfied contour's border edges should deviate +/// the original raw contour. [Limit: >=0] [Units: wu] +/// @param[in] maxEdgeLen The maximum allowed length for contour edges along the border of the mesh. +/// [Limit: >=0] [Units: vx] +/// @param[out] cset The resulting contour set. (Must be pre-allocated.) +/// @param[in] buildFlags The build flags. (See: #rcBuildContoursFlags) +/// @returns True if the operation completed successfully. +bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, + const float maxError, const int maxEdgeLen, + rcContourSet& cset, const int buildFlags = RC_CONTOUR_TESS_WALL_EDGES); + +/// Builds a polygon mesh from the provided contours. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] cset A fully built contour set. +/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the +/// contour to polygon conversion process. [Limit: >= 3] +/// @param[out] mesh The resulting polygon mesh. (Must be re-allocated.) +/// @returns True if the operation completed successfully. +bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh); + +/// Merges multiple polygon meshes into a single mesh. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] meshes An array of polygon meshes to merge. [Size: @p nmeshes] +/// @param[in] nmeshes The number of polygon meshes in the meshes array. +/// @param[in] mesh The resulting polygon mesh. (Must be pre-allocated.) +/// @returns True if the operation completed successfully. +bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); + +/// Builds a detail mesh from the provided polygon mesh. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] mesh A fully built polygon mesh. +/// @param[in] chf The compact heightfield used to build the polygon mesh. +/// @param[in] sampleDist Sets the distance to use when samping the heightfield. [Limit: >=0] [Units: wu] +/// @param[in] sampleMaxError The maximum distance the detail mesh surface should deviate from +/// heightfield data. [Limit: >=0] [Units: wu] +/// @param[out] dmesh The resulting detail mesh. (Must be pre-allocated.) +/// @returns True if the operation completed successfully. +bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, + const float sampleDist, const float sampleMaxError, + rcPolyMeshDetail& dmesh); + +/// Copies the poly mesh data from src to dst. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] src The source mesh to copy from. +/// @param[out] dst The resulting detail mesh. (Must be pre-allocated, must be empty mesh.) +/// @returns True if the operation completed successfully. +bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst); + +/// Merges multiple detail meshes into a single detail mesh. +/// @ingroup recast +/// @param[in,out] ctx The build context to use during the operation. +/// @param[in] meshes An array of detail meshes to merge. [Size: @p nmeshes] +/// @param[in] nmeshes The number of detail meshes in the meshes array. +/// @param[out] mesh The resulting detail mesh. (Must be pre-allocated.) +/// @returns True if the operation completed successfully. +bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); + +/// @} + +#endif // RECAST_H + +/////////////////////////////////////////////////////////////////////////// + +// Due to the large amount of detail documentation for this file, +// the content normally located at the end of the header file has been separated +// out to a file in /Docs/Extern. diff --git a/modules/worldengine/deps/recastnavigation/Recast/Include/RecastAlloc.h b/modules/worldengine/deps/recastnavigation/Recast/Include/RecastAlloc.h new file mode 100644 index 0000000000..3cdd450d42 --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Recast/Include/RecastAlloc.h @@ -0,0 +1,146 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#ifndef RECASTALLOC_H +#define RECASTALLOC_H + +#include <stddef.h> + +/// Provides hint values to the memory allocator on how long the +/// memory is expected to be used. +enum rcAllocHint +{ + RC_ALLOC_PERM, ///< Memory will persist after a function call. + RC_ALLOC_TEMP ///< Memory used temporarily within a function. +}; + +/// A memory allocation function. +// @param[in] size The size, in bytes of memory, to allocate. +// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use. +// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. +/// @see rcAllocSetCustom +typedef void* (rcAllocFunc)(size_t size, rcAllocHint hint); + +/// A memory deallocation function. +/// @param[in] ptr A pointer to a memory block previously allocated using #rcAllocFunc. +/// @see rcAllocSetCustom +typedef void (rcFreeFunc)(void* ptr); + +/// Sets the base custom allocation functions to be used by Recast. +/// @param[in] allocFunc The memory allocation function to be used by #rcAlloc +/// @param[in] freeFunc The memory de-allocation function to be used by #rcFree +void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc); + +/// Allocates a memory block. +/// @param[in] size The size, in bytes of memory, to allocate. +/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use. +/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. +/// @see rcFree +void* rcAlloc(size_t size, rcAllocHint hint); + +/// Deallocates a memory block. +/// @param[in] ptr A pointer to a memory block previously allocated using #rcAlloc. +/// @see rcAlloc +void rcFree(void* ptr); + + +/// A simple dynamic array of integers. +class rcIntArray +{ + int* m_data; + int m_size, m_cap; + + void doResize(int n); + + // Explicitly disabled copy constructor and copy assignment operator. + rcIntArray(const rcIntArray&); + rcIntArray& operator=(const rcIntArray&); + +public: + /// Constructs an instance with an initial array size of zero. + rcIntArray() : m_data(0), m_size(0), m_cap(0) {} + + /// Constructs an instance initialized to the specified size. + /// @param[in] n The initial size of the integer array. + rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); } + ~rcIntArray() { rcFree(m_data); } + + /// Specifies the new size of the integer array. + /// @param[in] n The new size of the integer array. + void resize(int n) + { + if (n > m_cap) + doResize(n); + + m_size = n; + } + + /// Push the specified integer onto the end of the array and increases the size by one. + /// @param[in] item The new value. + void push(int item) { resize(m_size+1); m_data[m_size-1] = item; } + + /// Returns the value at the end of the array and reduces the size by one. + /// @return The value at the end of the array. + int pop() + { + if (m_size > 0) + m_size--; + + return m_data[m_size]; + } + + /// The value at the specified array index. + /// @warning Does not provide overflow protection. + /// @param[in] i The index of the value. + const int& operator[](int i) const { return m_data[i]; } + + /// The value at the specified array index. + /// @warning Does not provide overflow protection. + /// @param[in] i The index of the value. + int& operator[](int i) { return m_data[i]; } + + /// The current size of the integer array. + int size() const { return m_size; } +}; + +/// A simple helper class used to delete an array when it goes out of scope. +/// @note This class is rarely if ever used by the end user. +template<class T> class rcScopedDelete +{ + T* ptr; +public: + + /// Constructs an instance with a null pointer. + inline rcScopedDelete() : ptr(0) {} + + /// Constructs an instance with the specified pointer. + /// @param[in] p An pointer to an allocated array. + inline rcScopedDelete(T* p) : ptr(p) {} + inline ~rcScopedDelete() { rcFree(ptr); } + + /// The root array pointer. + /// @return The root array pointer. + inline operator T*() { return ptr; } + +private: + // Explicitly disabled copy constructor and copy assignment operator. + rcScopedDelete(const rcScopedDelete&); + rcScopedDelete& operator=(const rcScopedDelete&); +}; + +#endif diff --git a/deps/recastnavigation/Recast/RecastAssert.h b/modules/worldengine/deps/recastnavigation/Recast/Include/RecastAssert.h index b58b8fcd28..2aca0d9a14 100644 --- a/deps/recastnavigation/Recast/RecastAssert.h +++ b/modules/worldengine/deps/recastnavigation/Recast/Include/RecastAssert.h @@ -24,7 +24,7 @@ #ifdef NDEBUG // From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ -# define rcAssert(x) do { (void)sizeof(x); } while(__LINE__==-1,false) +# define rcAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false) #else # include <assert.h> # define rcAssert assert diff --git a/deps/recastnavigation/Recast/Recast.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/Recast.cpp index d051418e81..8308d1973e 100644 --- a/deps/recastnavigation/Recast/Recast.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/Recast.cpp @@ -23,6 +23,7 @@ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> +#include <new> #include "Recast.h" #include "RecastAlloc.h" #include "RecastAssert.h" @@ -32,7 +33,26 @@ float rcSqrt(float x) return sqrtf(x); } +/// @class rcContext +/// @par +/// +/// This class does not provide logging or timer functionality on its +/// own. Both must be provided by a concrete implementation +/// by overriding the protected member functions. Also, this class does not +/// provide an interface for extracting log messages. (Only adding them.) +/// So concrete implementations must provide one. +/// +/// If no logging or timers are required, just pass an instance of this +/// class through the Recast build process. +/// +/// @par +/// +/// Example: +/// @code +/// // Where ctx is an instance of rcContext and filepath is a char array. +/// ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath); +/// @endcode void rcContext::log(const rcLogCategory category, const char* format, ...) { if (!m_logEnabled) @@ -53,23 +73,39 @@ void rcContext::log(const rcLogCategory category, const char* format, ...) rcHeightfield* rcAllocHeightfield() { - rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM); - memset(hf, 0, sizeof(rcHeightfield)); - return hf; + return new (rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM)) rcHeightfield; } -void rcFreeHeightField(rcHeightfield* hf) +rcHeightfield::rcHeightfield() + : width() + , height() + , bmin() + , bmax() + , cs() + , ch() + , spans() + , pools() + , freelist() +{ +} + +rcHeightfield::~rcHeightfield() { - if (!hf) return; // Delete span array. - rcFree(hf->spans); + rcFree(spans); // Delete span pools. - while (hf->pools) + while (pools) { - rcSpanPool* next = hf->pools->next; - rcFree(hf->pools); - hf->pools = next; + rcSpanPool* next = pools->next; + rcFree(pools); + pools = next; } +} + +void rcFreeHeightField(rcHeightfield* hf) +{ + if (!hf) return; + hf->~rcHeightfield(); rcFree(hf); } @@ -90,6 +126,27 @@ void rcFreeCompactHeightfield(rcCompactHeightfield* chf) rcFree(chf); } +rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet() +{ + rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM); + memset(lset, 0, sizeof(rcHeightfieldLayerSet)); + return lset; +} + +void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset) +{ + if (!lset) return; + for (int i = 0; i < lset->nlayers; ++i) + { + rcFree(lset->layers[i].heights); + rcFree(lset->layers[i].areas); + rcFree(lset->layers[i].cons); + } + rcFree(lset->layers); + rcFree(lset); +} + + rcContourSet* rcAllocContourSet() { rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM); @@ -143,7 +200,6 @@ void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh) rcFree(dmesh); } - void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax) { // Calculate bounding box. @@ -163,12 +219,16 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* *h = (int)((bmax[2] - bmin[2])/cs+0.5f); } -bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height, +/// @par +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcAllocHeightfield, rcHeightfield +bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, const float* bmin, const float* bmax, float cs, float ch) { - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); + rcIgnoreUnused(ctx); hf.width = width; hf.height = height; @@ -192,13 +252,21 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo rcVnormalize(norm); } -void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, - const float* verts, int /*nv*/, +/// @par +/// +/// Only sets the area id's for the walkable triangles. Does not alter the +/// area id's for unwalkable triangles. +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles +void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, + const float* verts, int nv, const int* tris, int nt, unsigned char* areas) { - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); + rcIgnoreUnused(ctx); + rcIgnoreUnused(nv); const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI); @@ -214,13 +282,20 @@ void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, } } -void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, +/// @par +/// +/// Only sets the area id's for the unwalkable triangles. Does not alter the +/// area id's for walkable triangles. +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles +void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int /*nv*/, const int* tris, int nt, unsigned char* areas) { - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); + rcIgnoreUnused(ctx); const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI); @@ -236,10 +311,9 @@ void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAng } } -int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf) +int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf) { - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); + rcIgnoreUnused(ctx); const int w = hf.width; const int h = hf.height; @@ -258,12 +332,21 @@ int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf) return spanCount; } +/// @par +/// +/// This is just the beginning of the process of fully building a compact heightfield. +/// Various filters may be applied, then the distance field and regions built. +/// E.g: #rcBuildDistanceField and #rcBuildRegions +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& hf, rcCompactHeightfield& chf) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_COMPACTHEIGHTFIELD); const int w = hf.width; const int h = hf.height; @@ -369,13 +452,13 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb) { // Mark direction as walkable. - const int idx = k - (int)nc.index; - if (idx < 0 || idx > MAX_LAYERS) + const int lidx = k - (int)nc.index; + if (lidx < 0 || lidx > MAX_LAYERS) { - tooHighNeighbour = rcMax(tooHighNeighbour, idx); + tooHighNeighbour = rcMax(tooHighNeighbour, lidx); continue; } - rcSetCon(s, dir, idx); + rcSetCon(s, dir, lidx); break; } } @@ -390,8 +473,6 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)", tooHighNeighbour, MAX_LAYERS); } - - ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD); return true; } @@ -420,4 +501,4 @@ static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf) size += sizeof(rcCompactCell) * chf.width * chf.height; return size; } -*/
\ No newline at end of file +*/ diff --git a/deps/recastnavigation/Recast/RecastAlloc.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastAlloc.cpp index 2c7396a1bf..453b5fa6a6 100644 --- a/deps/recastnavigation/Recast/RecastAlloc.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastAlloc.cpp @@ -19,8 +19,9 @@ #include <stdlib.h> #include <string.h> #include "RecastAlloc.h" +#include "RecastAssert.h" -static void *rcAllocDefault(int size, rcAllocHint) +static void *rcAllocDefault(size_t size, rcAllocHint) { return malloc(size); } @@ -33,35 +34,53 @@ static void rcFreeDefault(void *ptr) static rcAllocFunc* sRecastAllocFunc = rcAllocDefault; static rcFreeFunc* sRecastFreeFunc = rcFreeDefault; +/// @see rcAlloc, rcFree void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc) { sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault; sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault; } -void* rcAlloc(int size, rcAllocHint hint) +/// @see rcAllocSetCustom +void* rcAlloc(size_t size, rcAllocHint hint) { return sRecastAllocFunc(size, hint); } +/// @par +/// +/// @warning This function leaves the value of @p ptr unchanged. So it still +/// points to the same (now invalid) location, and not to null. +/// +/// @see rcAllocSetCustom void rcFree(void* ptr) { if (ptr) sRecastFreeFunc(ptr); } +/// @class rcIntArray +/// +/// While it is possible to pre-allocate a specific array size during +/// construction or by using the #resize method, certain methods will +/// automatically resize the array as needed. +/// +/// @warning The array memory is not initialized to zero when the size is +/// manually set during construction or when using #resize. -void rcIntArray::resize(int n) +/// @par +/// +/// Using this method ensures the array is at least large enough to hold +/// the specified number of elements. This can improve performance by +/// avoiding auto-resizing during use. +void rcIntArray::doResize(int n) { - if (n > m_cap) - { - if (!m_cap) m_cap = n; - while (m_cap < n) m_cap *= 2; - int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP); - if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int)); - rcFree(m_data); - m_data = newData; - } - m_size = n; + if (!m_cap) m_cap = n; + while (m_cap < n) m_cap *= 2; + int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP); + rcAssert(newData); + if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int)); + rcFree(m_data); + m_data = newData; } diff --git a/deps/recastnavigation/Recast/RecastArea.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastArea.cpp index c18277b878..97139cf996 100644 --- a/deps/recastnavigation/Recast/RecastArea.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastArea.cpp @@ -26,7 +26,14 @@ #include "RecastAlloc.h" #include "RecastAssert.h" - +/// @par +/// +/// Basically, any spans that are closer to a boundary or obstruction than the specified radius +/// are marked as unwalkable. +/// +/// This method is usually called immediately after the heightfield has been built. +/// +/// @see rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) { rcAssert(ctx); @@ -34,7 +41,7 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) const int w = chf.width; const int h = chf.height; - ctx->startTimer(RC_TIMER_ERODE_AREA); + rcScopedTimer timer(ctx, RC_TIMER_ERODE_AREA); unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!dist) @@ -54,14 +61,26 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) const rcCompactCell& c = chf.cells[x+y*w]; for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) { - if (chf.areas[i] != RC_NULL_AREA) + if (chf.areas[i] == RC_NULL_AREA) + { + dist[i] = 0; + } + else { const rcCompactSpan& s = chf.spans[i]; int nc = 0; for (int dir = 0; dir < 4; ++dir) { if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - nc++; + { + const int nx = x + rcGetDirOffsetX(dir); + const int ny = y + rcGetDirOffsetY(dir); + const int nidx = (int)chf.cells[nx+ny*w].index + rcGetCon(s, dir); + if (chf.areas[nidx] != RC_NULL_AREA) + { + nc++; + } + } } // At least one missing neighbour. if (nc != 4) @@ -196,8 +215,6 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) rcFree(dist); - ctx->stopTimer(RC_TIMER_ERODE_AREA); - return true; } @@ -213,7 +230,12 @@ static void insertSort(unsigned char* a, const int n) } } - +/// @par +/// +/// This filter is usually applied after applying area id's using functions +/// such as #rcMarkBoxArea, #rcMarkConvexPolyArea, and #rcMarkCylinderArea. +/// +/// @see rcCompactHeightfield bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) { rcAssert(ctx); @@ -221,7 +243,7 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) const int w = chf.width; const int h = chf.height; - ctx->startTimer(RC_TIMER_MEDIAN_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MEDIAN_AREA); unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!areas) @@ -282,18 +304,21 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) memcpy(chf.areas, areas, sizeof(unsigned char)*chf.spanCount); rcFree(areas); - - ctx->stopTimer(RC_TIMER_MEDIAN_AREA); return true; } +/// @par +/// +/// The value of spacial parameters are in world units. +/// +/// @see rcCompactHeightfield, rcMedianFilterWalkableArea void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, rcCompactHeightfield& chf) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MARK_BOX_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MARK_BOX_AREA); int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); @@ -328,9 +353,6 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne } } } - - ctx->stopTimer(RC_TIMER_MARK_BOX_AREA); - } @@ -348,13 +370,21 @@ static int pointInPoly(int nvert, const float* verts, const float* p) return c; } +/// @par +/// +/// The value of spacial parameters are in world units. +/// +/// The y-values of the polygon vertices are ignored. So the polygon is effectively +/// projected onto the xz-plane at @p hmin, then extruded to @p hmax. +/// +/// @see rcCompactHeightfield, rcMedianFilterWalkableArea void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, const float hmin, const float hmax, unsigned char areaId, rcCompactHeightfield& chf) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MARK_CONVEXPOLY_AREA); float bmin[3], bmax[3]; rcVcopy(bmin, verts); @@ -411,6 +441,151 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, } } } +} + +int rcOffsetPoly(const float* verts, const int nverts, const float offset, + float* outVerts, const int maxOutVerts) +{ + const float MITER_LIMIT = 1.20f; + + int n = 0; - ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); + for (int i = 0; i < nverts; i++) + { + const int a = (i+nverts-1) % nverts; + const int b = i; + const int c = (i+1) % nverts; + const float* va = &verts[a*3]; + const float* vb = &verts[b*3]; + const float* vc = &verts[c*3]; + float dx0 = vb[0] - va[0]; + float dy0 = vb[2] - va[2]; + float d0 = dx0*dx0 + dy0*dy0; + if (d0 > 1e-6f) + { + d0 = 1.0f/rcSqrt(d0); + dx0 *= d0; + dy0 *= d0; + } + float dx1 = vc[0] - vb[0]; + float dy1 = vc[2] - vb[2]; + float d1 = dx1*dx1 + dy1*dy1; + if (d1 > 1e-6f) + { + d1 = 1.0f/rcSqrt(d1); + dx1 *= d1; + dy1 *= d1; + } + const float dlx0 = -dy0; + const float dly0 = dx0; + const float dlx1 = -dy1; + const float dly1 = dx1; + float cross = dx1*dy0 - dx0*dy1; + float dmx = (dlx0 + dlx1) * 0.5f; + float dmy = (dly0 + dly1) * 0.5f; + float dmr2 = dmx*dmx + dmy*dmy; + bool bevel = dmr2 * MITER_LIMIT*MITER_LIMIT < 1.0f; + if (dmr2 > 1e-6f) + { + const float scale = 1.0f / dmr2; + dmx *= scale; + dmy *= scale; + } + + if (bevel && cross < 0.0f) + { + if (n+2 >= maxOutVerts) + return 0; + float d = (1.0f - (dx0*dx1 + dy0*dy1))*0.5f; + outVerts[n*3+0] = vb[0] + (-dlx0+dx0*d)*offset; + outVerts[n*3+1] = vb[1]; + outVerts[n*3+2] = vb[2] + (-dly0+dy0*d)*offset; + n++; + outVerts[n*3+0] = vb[0] + (-dlx1-dx1*d)*offset; + outVerts[n*3+1] = vb[1]; + outVerts[n*3+2] = vb[2] + (-dly1-dy1*d)*offset; + n++; + } + else + { + if (n+1 >= maxOutVerts) + return 0; + outVerts[n*3+0] = vb[0] - dmx*offset; + outVerts[n*3+1] = vb[1]; + outVerts[n*3+2] = vb[2] - dmy*offset; + n++; + } + } + + return n; +} + + +/// @par +/// +/// The value of spacial parameters are in world units. +/// +/// @see rcCompactHeightfield, rcMedianFilterWalkableArea +void rcMarkCylinderArea(rcContext* ctx, const float* pos, + const float r, const float h, unsigned char areaId, + rcCompactHeightfield& chf) +{ + rcAssert(ctx); + + rcScopedTimer timer(ctx, RC_TIMER_MARK_CYLINDER_AREA); + + float bmin[3], bmax[3]; + bmin[0] = pos[0] - r; + bmin[1] = pos[1]; + bmin[2] = pos[2] - r; + bmax[0] = pos[0] + r; + bmax[1] = pos[1] + h; + bmax[2] = pos[2] + r; + const float r2 = r*r; + + int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); + int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); + int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs); + int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs); + int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch); + int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs); + + if (maxx < 0) return; + if (minx >= chf.width) return; + if (maxz < 0) return; + if (minz >= chf.height) return; + + if (minx < 0) minx = 0; + if (maxx >= chf.width) maxx = chf.width-1; + if (minz < 0) minz = 0; + if (maxz >= chf.height) maxz = chf.height-1; + + + for (int z = minz; z <= maxz; ++z) + { + for (int x = minx; x <= maxx; ++x) + { + const rcCompactCell& c = chf.cells[x+z*chf.width]; + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + rcCompactSpan& s = chf.spans[i]; + + if (chf.areas[i] == RC_NULL_AREA) + continue; + + if ((int)s.y >= miny && (int)s.y <= maxy) + { + const float sx = chf.bmin[0] + (x+0.5f)*chf.cs; + const float sz = chf.bmin[2] + (z+0.5f)*chf.cs; + const float dx = sx - pos[0]; + const float dz = sz - pos[2]; + + if (dx*dx + dz*dz < r2) + { + chf.areas[i] = areaId; + } + } + } + } + } } diff --git a/deps/recastnavigation/Recast/RecastContour.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastContour.cpp index 4ba8deac89..277ab01501 100644 --- a/deps/recastnavigation/Recast/RecastContour.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastContour.cpp @@ -20,6 +20,7 @@ #include <math.h> #include <string.h> #include <stdio.h> +#include <stdlib.h> #include "Recast.h" #include "RecastAlloc.h" #include "RecastAssert.h" @@ -36,7 +37,7 @@ static int getCornerHeight(int x, int y, int i, int dir, unsigned int regs[4] = {0,0,0,0}; // Combine region and area codes in order to prevent - // border vertices which are in between two areas to be removed. + // border vertices which are in between two areas to be removed. regs[0] = chf.spans[i].reg | (chf.areas[i] << 16); if (rcGetCon(s, dir) != RC_NOT_CONNECTED) @@ -187,27 +188,6 @@ static float distancePtSeg(const int x, const int z, const int px, const int pz, const int qx, const int qz) { -/* float pqx = (float)(qx - px); - float pqy = (float)(qy - py); - float pqz = (float)(qz - pz); - float dx = (float)(x - px); - float dy = (float)(y - py); - float dz = (float)(z - pz); - float d = pqx*pqx + pqy*pqy + pqz*pqz; - float t = pqx*dx + pqy*dy + pqz*dz; - if (d > 0) - t /= d; - if (t < 0) - t = 0; - else if (t > 1) - t = 1; - - dx = px + t*pqx - x; - dy = py + t*pqy - y; - dz = pz + t*pqz - z; - - return dx*dx + dy*dy + dz*dz;*/ - float pqx = (float)(qx - px); float pqz = (float)(qz - pz); float dx = (float)(x - px); @@ -257,13 +237,13 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, simplified.push(points[i*4+2]); simplified.push(i); } - } + } } if (simplified.size() == 0) { // If there is no connections at all, - // create some initial points for the simplification process. + // create some initial points for the simplification process. // Find lower-left and upper-right vertices of the contour. int llx = points[0]; int lly = points[1]; @@ -311,19 +291,19 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, { int ii = (i+1) % (simplified.size()/4); - const int ax = simplified[i*4+0]; - const int az = simplified[i*4+2]; - const int ai = simplified[i*4+3]; - - const int bx = simplified[ii*4+0]; - const int bz = simplified[ii*4+2]; - const int bi = simplified[ii*4+3]; + int ax = simplified[i*4+0]; + int az = simplified[i*4+2]; + int ai = simplified[i*4+3]; + + int bx = simplified[ii*4+0]; + int bz = simplified[ii*4+2]; + int bi = simplified[ii*4+3]; // Find maximum deviation from the segment. float maxd = 0; int maxi = -1; int ci, cinc, endi; - + // Traverse the segment in lexilogical order so that the // max deviation is calculated similarly when traversing // opposite segments. @@ -338,9 +318,11 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, cinc = pn-1; ci = (bi+cinc) % pn; endi = ai; + rcSwap(ax, bx); + rcSwap(az, bz); } - // Tessellate only outer edges oredges between areas. + // Tessellate only outer edges or edges between areas. if ((points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0 || (points[ci*4+3] & RC_AREA_BORDER)) { @@ -397,11 +379,11 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, const int bx = simplified[ii*4+0]; const int bz = simplified[ii*4+2]; const int bi = simplified[ii*4+3]; - + // Find maximum deviation from the segment. int maxi = -1; int ci = (ai+1) % pn; - + // Tessellate only outer edges or edges between areas. bool tess = false; // Wall edges. @@ -469,32 +451,6 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified, } -static void removeDegenerateSegments(rcIntArray& simplified) -{ - // Remove adjacent vertices which are equal on xz-plane, - // or else the triangulator will get confused. - for (int i = 0; i < simplified.size()/4; ++i) - { - int ni = i+1; - if (ni >= (simplified.size()/4)) - ni = 0; - - if (simplified[i*4+0] == simplified[ni*4+0] && - simplified[i*4+2] == simplified[ni*4+2]) - { - // Degenerate segment, remove. - for (int j = i; j < simplified.size()/4-1; ++j) - { - simplified[j*4+0] = simplified[(j+1)*4+0]; - simplified[j*4+1] = simplified[(j+1)*4+1]; - simplified[j*4+2] = simplified[(j+1)*4+2]; - simplified[j*4+3] = simplified[(j+1)*4+3]; - } - simplified.resize(simplified.size()-4); - } - } -} - static int calcAreaOfPolygon2D(const int* verts, const int nverts) { int area = 0; @@ -507,54 +463,155 @@ static int calcAreaOfPolygon2D(const int* verts, const int nverts) return (area+1) / 2; } -inline bool ileft(const int* a, const int* b, const int* c) +// TODO: these are the same as in RecastMesh.cpp, consider using the same. +// Last time I checked the if version got compiled using cmov, which was a lot faster than module (with idiv). +inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; } +inline int next(int i, int n) { return i+1 < n ? i+1 : 0; } + +inline int area2(const int* a, const int* b, const int* c) +{ + return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]); +} + +// Exclusive or: true iff exactly one argument is true. +// The arguments are negated to ensure that they are 0/1 +// values. Then the bitwise Xor operator may apply. +// (This idea is due to Michael Baldwin.) +inline bool xorb(bool x, bool y) +{ + return !x ^ !y; +} + +// Returns true iff c is strictly to the left of the directed +// line through a to b. +inline bool left(const int* a, const int* b, const int* c) { - return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]) <= 0; + return area2(a, b, c) < 0; } -static void getClosestIndices(const int* vertsa, const int nvertsa, - const int* vertsb, const int nvertsb, - int& ia, int& ib) +inline bool leftOn(const int* a, const int* b, const int* c) { - int closestDist = 0xfffffff; - ia = -1, ib = -1; - for (int i = 0; i < nvertsa; ++i) + return area2(a, b, c) <= 0; +} + +inline bool collinear(const int* a, const int* b, const int* c) +{ + return area2(a, b, c) == 0; +} + +// Returns true iff ab properly intersects cd: they share +// a point interior to both segments. The properness of the +// intersection is ensured by using strict leftness. +static bool intersectProp(const int* a, const int* b, const int* c, const int* d) +{ + // Eliminate improper cases. + if (collinear(a,b,c) || collinear(a,b,d) || + collinear(c,d,a) || collinear(c,d,b)) + return false; + + return xorb(left(a,b,c), left(a,b,d)) && xorb(left(c,d,a), left(c,d,b)); +} + +// Returns T iff (a,b,c) are collinear and point c lies +// on the closed segement ab. +static bool between(const int* a, const int* b, const int* c) +{ + if (!collinear(a, b, c)) + return false; + // If ab not vertical, check betweenness on x; else on y. + if (a[0] != b[0]) + return ((a[0] <= c[0]) && (c[0] <= b[0])) || ((a[0] >= c[0]) && (c[0] >= b[0])); + else + return ((a[2] <= c[2]) && (c[2] <= b[2])) || ((a[2] >= c[2]) && (c[2] >= b[2])); +} + +// Returns true iff segments ab and cd intersect, properly or improperly. +static bool intersect(const int* a, const int* b, const int* c, const int* d) +{ + if (intersectProp(a, b, c, d)) + return true; + else if (between(a, b, c) || between(a, b, d) || + between(c, d, a) || between(c, d, b)) + return true; + else + return false; +} + +static bool vequal(const int* a, const int* b) +{ + return a[0] == b[0] && a[2] == b[2]; +} + +static bool intersectSegCountour(const int* d0, const int* d1, int i, int n, const int* verts) +{ + // For each edge (k,k+1) of P + for (int k = 0; k < n; k++) + { + int k1 = next(k, n); + // Skip edges incident to i. + if (i == k || i == k1) + continue; + const int* p0 = &verts[k * 4]; + const int* p1 = &verts[k1 * 4]; + if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1)) + continue; + + if (intersect(d0, d1, p0, p1)) + return true; + } + return false; +} + +static bool inCone(int i, int n, const int* verts, const int* pj) +{ + const int* pi = &verts[i * 4]; + const int* pi1 = &verts[next(i, n) * 4]; + const int* pin1 = &verts[prev(i, n) * 4]; + + // If P[i] is a convex vertex [ i+1 left or on (i-1,i) ]. + if (leftOn(pin1, pi, pi1)) + return left(pi, pj, pin1) && left(pj, pi, pi1); + // Assume (i-1,i,i+1) not collinear. + // else P[i] is reflex. + return !(leftOn(pi, pj, pi1) && leftOn(pj, pi, pin1)); +} + + +static void removeDegenerateSegments(rcIntArray& simplified) +{ + // Remove adjacent vertices which are equal on xz-plane, + // or else the triangulator will get confused. + int npts = simplified.size()/4; + for (int i = 0; i < npts; ++i) { - const int in = (i+1) % nvertsa; - const int ip = (i+nvertsa-1) % nvertsa; - const int* va = &vertsa[i*4]; - const int* van = &vertsa[in*4]; - const int* vap = &vertsa[ip*4]; + int ni = next(i, npts); - for (int j = 0; j < nvertsb; ++j) + if (vequal(&simplified[i*4], &simplified[ni*4])) { - const int* vb = &vertsb[j*4]; - // vb must be "infront" of va. - if (ileft(vap,va,vb) && ileft(va,van,vb)) + // Degenerate segment, remove. + for (int j = i; j < simplified.size()/4-1; ++j) { - const int dx = vb[0] - va[0]; - const int dz = vb[2] - va[2]; - const int d = dx*dx + dz*dz; - if (d < closestDist) - { - ia = i; - ib = j; - closestDist = d; - } + simplified[j*4+0] = simplified[(j+1)*4+0]; + simplified[j*4+1] = simplified[(j+1)*4+1]; + simplified[j*4+2] = simplified[(j+1)*4+2]; + simplified[j*4+3] = simplified[(j+1)*4+3]; } + simplified.resize(simplified.size()-4); + npts--; } } } + static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib) { const int maxVerts = ca.nverts + cb.nverts + 2; int* verts = (int*)rcAlloc(sizeof(int)*maxVerts*4, RC_ALLOC_PERM); if (!verts) return false; - + int nv = 0; - + // Copy contour A. for (int i = 0; i <= ca.nverts; ++i) { @@ -582,7 +639,7 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib) rcFree(ca.verts); ca.verts = verts; ca.nverts = nv; - + rcFree(cb.verts); cb.verts = 0; cb.nverts = 0; @@ -590,6 +647,180 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib) return true; } +struct rcContourHole +{ + rcContour* contour; + int minx, minz, leftmost; +}; + +struct rcContourRegion +{ + rcContour* outline; + rcContourHole* holes; + int nholes; +}; + +struct rcPotentialDiagonal +{ + int vert; + int dist; +}; + +// Finds the lowest leftmost vertex of a contour. +static void findLeftMostVertex(rcContour* contour, int* minx, int* minz, int* leftmost) +{ + *minx = contour->verts[0]; + *minz = contour->verts[2]; + *leftmost = 0; + for (int i = 1; i < contour->nverts; i++) + { + const int x = contour->verts[i*4+0]; + const int z = contour->verts[i*4+2]; + if (x < *minx || (x == *minx && z < *minz)) + { + *minx = x; + *minz = z; + *leftmost = i; + } + } +} + +static int compareHoles(const void* va, const void* vb) +{ + const rcContourHole* a = (const rcContourHole*)va; + const rcContourHole* b = (const rcContourHole*)vb; + if (a->minx == b->minx) + { + if (a->minz < b->minz) + return -1; + if (a->minz > b->minz) + return 1; + } + else + { + if (a->minx < b->minx) + return -1; + if (a->minx > b->minx) + return 1; + } + return 0; +} + + +static int compareDiagDist(const void* va, const void* vb) +{ + const rcPotentialDiagonal* a = (const rcPotentialDiagonal*)va; + const rcPotentialDiagonal* b = (const rcPotentialDiagonal*)vb; + if (a->dist < b->dist) + return -1; + if (a->dist > b->dist) + return 1; + return 0; +} + + +static void mergeRegionHoles(rcContext* ctx, rcContourRegion& region) +{ + // Sort holes from left to right. + for (int i = 0; i < region.nholes; i++) + findLeftMostVertex(region.holes[i].contour, ®ion.holes[i].minx, ®ion.holes[i].minz, ®ion.holes[i].leftmost); + + qsort(region.holes, region.nholes, sizeof(rcContourHole), compareHoles); + + int maxVerts = region.outline->nverts; + for (int i = 0; i < region.nholes; i++) + maxVerts += region.holes[i].contour->nverts; + + rcScopedDelete<rcPotentialDiagonal> diags((rcPotentialDiagonal*)rcAlloc(sizeof(rcPotentialDiagonal)*maxVerts, RC_ALLOC_TEMP)); + if (!diags) + { + ctx->log(RC_LOG_WARNING, "mergeRegionHoles: Failed to allocated diags %d.", maxVerts); + return; + } + + rcContour* outline = region.outline; + + // Merge holes into the outline one by one. + for (int i = 0; i < region.nholes; i++) + { + rcContour* hole = region.holes[i].contour; + + int index = -1; + int bestVertex = region.holes[i].leftmost; + for (int iter = 0; iter < hole->nverts; iter++) + { + // Find potential diagonals. + // The 'best' vertex must be in the cone described by 3 cosequtive vertices of the outline. + // ..o j-1 + // | + // | * best + // | + // j o-----o j+1 + // : + int ndiags = 0; + const int* corner = &hole->verts[bestVertex*4]; + for (int j = 0; j < outline->nverts; j++) + { + if (inCone(j, outline->nverts, outline->verts, corner)) + { + int dx = outline->verts[j*4+0] - corner[0]; + int dz = outline->verts[j*4+2] - corner[2]; + diags[ndiags].vert = j; + diags[ndiags].dist = dx*dx + dz*dz; + ndiags++; + } + } + // Sort potential diagonals by distance, we want to make the connection as short as possible. + qsort(diags, ndiags, sizeof(rcPotentialDiagonal), compareDiagDist); + + // Find a diagonal that is not intersecting the outline not the remaining holes. + index = -1; + for (int j = 0; j < ndiags; j++) + { + const int* pt = &outline->verts[diags[j].vert*4]; + bool intersect = intersectSegCountour(pt, corner, diags[i].vert, outline->nverts, outline->verts); + for (int k = i; k < region.nholes && !intersect; k++) + intersect |= intersectSegCountour(pt, corner, -1, region.holes[k].contour->nverts, region.holes[k].contour->verts); + if (!intersect) + { + index = diags[j].vert; + break; + } + } + // If found non-intersecting diagonal, stop looking. + if (index != -1) + break; + // All the potential diagonals for the current vertex were intersecting, try next vertex. + bestVertex = (bestVertex + 1) % hole->nverts; + } + + if (index == -1) + { + ctx->log(RC_LOG_WARNING, "mergeHoles: Failed to find merge points for %p and %p.", region.outline, hole); + continue; + } + if (!mergeContours(*region.outline, *hole, index, bestVertex)) + { + ctx->log(RC_LOG_WARNING, "mergeHoles: Failed to merge contours %p and %p.", region.outline, hole); + continue; + } + } +} + + +/// @par +/// +/// The raw contours will match the region outlines exactly. The @p maxError and @p maxEdgeLen +/// parameters control how closely the simplified contours will match the raw contours. +/// +/// Simplified contours are generated such that the vertices for portals between areas match up. +/// (They are considered mandatory vertices.) +/// +/// Setting @p maxEdgeLength to zero will disabled the edge length feature. +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, const float maxError, const int maxEdgeLen, rcContourSet& cset, const int buildFlags) @@ -598,13 +829,27 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, const int w = chf.width; const int h = chf.height; + const int borderSize = chf.borderSize; - ctx->startTimer(RC_TIMER_BUILD_CONTOURS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_CONTOURS); rcVcopy(cset.bmin, chf.bmin); rcVcopy(cset.bmax, chf.bmax); + if (borderSize > 0) + { + // If the heightfield was build with bordersize, remove the offset. + const float pad = borderSize*chf.cs; + cset.bmin[0] += pad; + cset.bmin[2] += pad; + cset.bmax[0] -= pad; + cset.bmax[2] -= pad; + } cset.cs = chf.cs; cset.ch = chf.ch; + cset.width = chf.width - chf.borderSize*2; + cset.height = chf.height - chf.borderSize*2; + cset.borderSize = chf.borderSize; + cset.maxError = maxError; int maxContours = rcMax((int)chf.maxRegions, 8); cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM); @@ -612,7 +857,7 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, return false; cset.nconts = 0; - rcScopedDelete<unsigned char> flags = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); + rcScopedDelete<unsigned char> flags((unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP)); if (!flags) { ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount); @@ -656,8 +901,6 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE); - ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY); - rcIntArray verts(256); rcIntArray simplified(64); @@ -680,9 +923,16 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, verts.resize(0); simplified.resize(0); + + ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE); walkContour(x, y, i, chf, flags, verts); + ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE); + + ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY); simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags); removeDegenerateSegments(simplified); + ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY); + // Store region->contour remap info. // Create contour. @@ -691,7 +941,7 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, if (cset.nconts >= maxContours) { // Allocate more contours. - // This can happen when there are tiny holes in the heightfield. + // This happens when a region has holes. const int oldMax = maxContours; maxContours *= 2; rcContour* newConts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM); @@ -704,10 +954,10 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, } rcFree(cset.conts); cset.conts = newConts; - + ctx->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours); } - + rcContour* cont = &cset.conts[cset.nconts++]; cont->nverts = simplified.size()/4; @@ -718,6 +968,16 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, return false; } memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4); + if (borderSize > 0) + { + // If the heightfield was build with bordersize, remove the offset. + for (int j = 0; j < cont->nverts; ++j) + { + int* v = &cont->verts[j*4]; + v[0] -= borderSize; + v[2] -= borderSize; + } + } cont->nrverts = verts.size()/4; cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM); @@ -727,17 +987,16 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, return false; } memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4); - -/* cont->cx = cont->cy = cont->cz = 0; - for (int i = 0; i < cont->nverts; ++i) + if (borderSize > 0) { - cont->cx += cont->verts[i*4+0]; - cont->cy += cont->verts[i*4+1]; - cont->cz += cont->verts[i*4+2]; + // If the heightfield was build with bordersize, remove the offset. + for (int j = 0; j < cont->nrverts; ++j) + { + int* v = &cont->rverts[j*4]; + v[0] -= borderSize; + v[2] -= borderSize; + } } - cont->cx /= cont->nverts; - cont->cy /= cont->nverts; - cont->cz /= cont->nverts;*/ cont->reg = reg; cont->area = area; @@ -746,57 +1005,101 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, } } - // Check and merge droppings. - // Sometimes the previous algorithms can fail and create several contours - // per area. This pass will try to merge the holes into the main region. - for (int i = 0; i < cset.nconts; ++i) + // Merge holes if needed. + if (cset.nconts > 0) { - rcContour& cont = cset.conts[i]; - // Check if the contour is would backwards. - if (calcAreaOfPolygon2D(cont.verts, cont.nverts) < 0) + // Calculate winding of all polygons. + rcScopedDelete<char> winding((char*)rcAlloc(sizeof(char)*cset.nconts, RC_ALLOC_TEMP)); + if (!winding) + { + ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'hole' (%d).", cset.nconts); + return false; + } + int nholes = 0; + for (int i = 0; i < cset.nconts; ++i) { - // Find another contour which has the same region ID. - int mergeIdx = -1; - for (int j = 0; j < cset.nconts; ++j) + rcContour& cont = cset.conts[i]; + // If the contour is wound backwards, it is a hole. + winding[i] = calcAreaOfPolygon2D(cont.verts, cont.nverts) < 0 ? -1 : 1; + if (winding[i] < 0) + nholes++; + } + + if (nholes > 0) + { + // Collect outline contour and holes contours per region. + // We assume that there is one outline and multiple holes. + const int nregions = chf.maxRegions+1; + rcScopedDelete<rcContourRegion> regions((rcContourRegion*)rcAlloc(sizeof(rcContourRegion)*nregions, RC_ALLOC_TEMP)); + if (!regions) { - if (i == j) continue; - if (cset.conts[j].nverts && cset.conts[j].reg == cont.reg) + ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'regions' (%d).", nregions); + return false; + } + memset(regions, 0, sizeof(rcContourRegion)*nregions); + + rcScopedDelete<rcContourHole> holes((rcContourHole*)rcAlloc(sizeof(rcContourHole)*cset.nconts, RC_ALLOC_TEMP)); + if (!holes) + { + ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'holes' (%d).", cset.nconts); + return false; + } + memset(holes, 0, sizeof(rcContourHole)*cset.nconts); + + for (int i = 0; i < cset.nconts; ++i) + { + rcContour& cont = cset.conts[i]; + // Positively would contours are outlines, negative holes. + if (winding[i] > 0) { - // Make sure the polygon is correctly oriented. - if (calcAreaOfPolygon2D(cset.conts[j].verts, cset.conts[j].nverts)) - { - mergeIdx = j; - break; - } + if (regions[cont.reg].outline) + ctx->log(RC_LOG_ERROR, "rcBuildContours: Multiple outlines for region %d.", cont.reg); + regions[cont.reg].outline = &cont; + } + else + { + regions[cont.reg].nholes++; } } - if (mergeIdx == -1) + int index = 0; + for (int i = 0; i < nregions; i++) { - ctx->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i); + if (regions[i].nholes > 0) + { + regions[i].holes = &holes[index]; + index += regions[i].nholes; + regions[i].nholes = 0; + } } - else + for (int i = 0; i < cset.nconts; ++i) + { + rcContour& cont = cset.conts[i]; + rcContourRegion& reg = regions[cont.reg]; + if (winding[i] < 0) + reg.holes[reg.nholes++].contour = &cont; + } + + // Finally merge each regions holes into the outline. + for (int i = 0; i < nregions; i++) { - rcContour& mcont = cset.conts[mergeIdx]; - // Merge by closest points. - int ia = 0, ib = 0; - getClosestIndices(mcont.verts, mcont.nverts, cont.verts, cont.nverts, ia, ib); - if (ia == -1 || ib == -1) + rcContourRegion& reg = regions[i]; + if (!reg.nholes) continue; + + if (reg.outline) { - ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to find merge points for %d and %d.", i, mergeIdx); - continue; + mergeRegionHoles(ctx, reg); } - if (!mergeContours(mcont, cont, ia, ib)) + else { - ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx); - continue; + // The region does not have an outline. + // This can happen if the contour becaomes selfoverlapping because of + // too aggressive simplification settings. + ctx->log(RC_LOG_ERROR, "rcBuildContours: Bad outline for region %d, contour simplification is likely too aggressive.", i); } } } + } - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY); - - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS); - return true; } diff --git a/deps/recastnavigation/Recast/RecastFilter.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastFilter.cpp index 66af37a413..9d3e63c482 100644 --- a/deps/recastnavigation/Recast/RecastFilter.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastFilter.cpp @@ -22,12 +22,22 @@ #include "Recast.h" #include "RecastAssert.h" - +/// @par +/// +/// Allows the formation of walkable regions that will flow over low lying +/// objects such as curbs, and up structures such as stairways. +/// +/// Two neighboring spans are walkable if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt> +/// +/// @warning Will override the effect of #rcFilterLedgeSpans. So if both filters are used, call +/// #rcFilterLedgeSpans after calling this filter. +/// +/// @see rcHeightfield, rcConfig void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_FILTER_LOW_OBSTACLES); + rcScopedTimer timer(ctx, RC_TIMER_FILTER_LOW_OBSTACLES); const int w = solid.width; const int h = solid.height; @@ -57,16 +67,24 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb } } } - - ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES); } - + +/// @par +/// +/// A ledge is a span with one or more neighbors whose maximum is further away than @p walkableClimb +/// from the current span's maximum. +/// This method removes the impact of the overestimation of conservative voxelization +/// so the resulting mesh will not have regions hanging in the air over ledges. +/// +/// A span is a ledge if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt> +/// +/// @see rcHeightfield, rcConfig void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& solid) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_FILTER_BORDER); + rcScopedTimer timer(ctx, RC_TIMER_FILTER_BORDER); const int w = solid.width; const int h = solid.height; @@ -136,26 +154,31 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk // The current span is close to a ledge if the drop to any // neighbour span is less than the walkableClimb. if (minh < -walkableClimb) + { s->area = RC_NULL_AREA; - + } // If the difference between all neighbours is too large, // we are at steep slope, mark the span as ledge. - if ((asmax - asmin) > walkableClimb) + else if ((asmax - asmin) > walkableClimb) { s->area = RC_NULL_AREA; } } } } - - ctx->stopTimer(RC_TIMER_FILTER_BORDER); -} +} +/// @par +/// +/// For this filter, the clearance above the span is the distance from the span's +/// maximum to the next higher span's minimum. (Same grid column.) +/// +/// @see rcHeightfield, rcConfig void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_FILTER_WALKABLE); + rcScopedTimer timer(ctx, RC_TIMER_FILTER_WALKABLE); const int w = solid.width; const int h = solid.height; @@ -176,6 +199,4 @@ void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeight } } } - - ctx->stopTimer(RC_TIMER_FILTER_WALKABLE); } diff --git a/modules/worldengine/deps/recastnavigation/Recast/Source/RecastLayers.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastLayers.cpp new file mode 100644 index 0000000000..acc97e44f0 --- /dev/null +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastLayers.cpp @@ -0,0 +1,644 @@ +// +// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. +// + +#include <float.h> +#define _USE_MATH_DEFINES +#include <math.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include "Recast.h" +#include "RecastAlloc.h" +#include "RecastAssert.h" + + +// Must be 255 or smaller (not 256) because layer IDs are stored as +// a byte where 255 is a special value. +static const int RC_MAX_LAYERS = 63; +static const int RC_MAX_NEIS = 16; + +struct rcLayerRegion +{ + unsigned char layers[RC_MAX_LAYERS]; + unsigned char neis[RC_MAX_NEIS]; + unsigned short ymin, ymax; + unsigned char layerId; // Layer ID + unsigned char nlayers; // Layer count + unsigned char nneis; // Neighbour count + unsigned char base; // Flag indicating if the region is the base of merged regions. +}; + + +static bool contains(const unsigned char* a, const unsigned char an, const unsigned char v) +{ + const int n = (int)an; + for (int i = 0; i < n; ++i) + { + if (a[i] == v) + return true; + } + return false; +} + +static bool addUnique(unsigned char* a, unsigned char& an, int anMax, unsigned char v) +{ + if (contains(a, an, v)) + return true; + + if ((int)an >= anMax) + return false; + + a[an] = v; + an++; + return true; +} + + +inline bool overlapRange(const unsigned short amin, const unsigned short amax, + const unsigned short bmin, const unsigned short bmax) +{ + return (amin > bmax || amax < bmin) ? false : true; +} + + + +struct rcLayerSweepSpan +{ + unsigned short ns; // number samples + unsigned char id; // region id + unsigned char nei; // neighbour id +}; + +/// @par +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig +bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, + const int borderSize, const int walkableHeight, + rcHeightfieldLayerSet& lset) +{ + rcAssert(ctx); + + rcScopedTimer timer(ctx, RC_TIMER_BUILD_LAYERS); + + const int w = chf.width; + const int h = chf.height; + + rcScopedDelete<unsigned char> srcReg((unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP)); + if (!srcReg) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'srcReg' (%d).", chf.spanCount); + return false; + } + memset(srcReg,0xff,sizeof(unsigned char)*chf.spanCount); + + const int nsweeps = chf.width; + rcScopedDelete<rcLayerSweepSpan> sweeps((rcLayerSweepSpan*)rcAlloc(sizeof(rcLayerSweepSpan)*nsweeps, RC_ALLOC_TEMP)); + if (!sweeps) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'sweeps' (%d).", nsweeps); + return false; + } + + + // Partition walkable area into monotone regions. + int prevCount[256]; + unsigned char regId = 0; + + for (int y = borderSize; y < h-borderSize; ++y) + { + memset(prevCount,0,sizeof(int)*regId); + unsigned char sweepId = 0; + + for (int x = borderSize; x < w-borderSize; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + const rcCompactSpan& s = chf.spans[i]; + if (chf.areas[i] == RC_NULL_AREA) continue; + + unsigned char sid = 0xff; + + // -x + if (rcGetCon(s, 0) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(0); + const int ay = y + rcGetDirOffsetY(0); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0); + if (chf.areas[ai] != RC_NULL_AREA && srcReg[ai] != 0xff) + sid = srcReg[ai]; + } + + if (sid == 0xff) + { + sid = sweepId++; + sweeps[sid].nei = 0xff; + sweeps[sid].ns = 0; + } + + // -y + if (rcGetCon(s,3) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(3); + const int ay = y + rcGetDirOffsetY(3); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3); + const unsigned char nr = srcReg[ai]; + if (nr != 0xff) + { + // Set neighbour when first valid neighbour is encoutered. + if (sweeps[sid].ns == 0) + sweeps[sid].nei = nr; + + if (sweeps[sid].nei == nr) + { + // Update existing neighbour + sweeps[sid].ns++; + prevCount[nr]++; + } + else + { + // This is hit if there is nore than one neighbour. + // Invalidate the neighbour. + sweeps[sid].nei = 0xff; + } + } + } + + srcReg[i] = sid; + } + } + + // Create unique ID. + for (int i = 0; i < sweepId; ++i) + { + // If the neighbour is set and there is only one continuous connection to it, + // the sweep will be merged with the previous one, else new region is created. + if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == (int)sweeps[i].ns) + { + sweeps[i].id = sweeps[i].nei; + } + else + { + if (regId == 255) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Region ID overflow."); + return false; + } + sweeps[i].id = regId++; + } + } + + // Remap local sweep ids to region ids. + for (int x = borderSize; x < w-borderSize; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + if (srcReg[i] != 0xff) + srcReg[i] = sweeps[srcReg[i]].id; + } + } + } + + // Allocate and init layer regions. + const int nregs = (int)regId; + rcScopedDelete<rcLayerRegion> regs((rcLayerRegion*)rcAlloc(sizeof(rcLayerRegion)*nregs, RC_ALLOC_TEMP)); + if (!regs) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'regs' (%d).", nregs); + return false; + } + memset(regs, 0, sizeof(rcLayerRegion)*nregs); + for (int i = 0; i < nregs; ++i) + { + regs[i].layerId = 0xff; + regs[i].ymin = 0xffff; + regs[i].ymax = 0; + } + + // Find region neighbours and overlapping regions. + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + + unsigned char lregs[RC_MAX_LAYERS]; + int nlregs = 0; + + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + const rcCompactSpan& s = chf.spans[i]; + const unsigned char ri = srcReg[i]; + if (ri == 0xff) continue; + + regs[ri].ymin = rcMin(regs[ri].ymin, s.y); + regs[ri].ymax = rcMax(regs[ri].ymax, s.y); + + // Collect all region layers. + if (nlregs < RC_MAX_LAYERS) + lregs[nlregs++] = ri; + + // Update neighbours + for (int dir = 0; dir < 4; ++dir) + { + if (rcGetCon(s, dir) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(dir); + const int ay = y + rcGetDirOffsetY(dir); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); + const unsigned char rai = srcReg[ai]; + if (rai != 0xff && rai != ri) + { + // Don't check return value -- if we cannot add the neighbor + // it will just cause a few more regions to be created, which + // is fine. + addUnique(regs[ri].neis, regs[ri].nneis, RC_MAX_NEIS, rai); + } + } + } + + } + + // Update overlapping regions. + for (int i = 0; i < nlregs-1; ++i) + { + for (int j = i+1; j < nlregs; ++j) + { + if (lregs[i] != lregs[j]) + { + rcLayerRegion& ri = regs[lregs[i]]; + rcLayerRegion& rj = regs[lregs[j]]; + + if (!addUnique(ri.layers, ri.nlayers, RC_MAX_LAYERS, lregs[j]) || + !addUnique(rj.layers, rj.nlayers, RC_MAX_LAYERS, lregs[i])) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: layer overflow (too many overlapping walkable platforms). Try increasing RC_MAX_LAYERS."); + return false; + } + } + } + } + + } + } + + // Create 2D layers from regions. + unsigned char layerId = 0; + + static const int MAX_STACK = 64; + unsigned char stack[MAX_STACK]; + int nstack = 0; + + for (int i = 0; i < nregs; ++i) + { + rcLayerRegion& root = regs[i]; + // Skip already visited. + if (root.layerId != 0xff) + continue; + + // Start search. + root.layerId = layerId; + root.base = 1; + + nstack = 0; + stack[nstack++] = (unsigned char)i; + + while (nstack) + { + // Pop front + rcLayerRegion& reg = regs[stack[0]]; + nstack--; + for (int j = 0; j < nstack; ++j) + stack[j] = stack[j+1]; + + const int nneis = (int)reg.nneis; + for (int j = 0; j < nneis; ++j) + { + const unsigned char nei = reg.neis[j]; + rcLayerRegion& regn = regs[nei]; + // Skip already visited. + if (regn.layerId != 0xff) + continue; + // Skip if the neighbour is overlapping root region. + if (contains(root.layers, root.nlayers, nei)) + continue; + // Skip if the height range would become too large. + const int ymin = rcMin(root.ymin, regn.ymin); + const int ymax = rcMax(root.ymax, regn.ymax); + if ((ymax - ymin) >= 255) + continue; + + if (nstack < MAX_STACK) + { + // Deepen + stack[nstack++] = (unsigned char)nei; + + // Mark layer id + regn.layerId = layerId; + // Merge current layers to root. + for (int k = 0; k < regn.nlayers; ++k) + { + if (!addUnique(root.layers, root.nlayers, RC_MAX_LAYERS, regn.layers[k])) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: layer overflow (too many overlapping walkable platforms). Try increasing RC_MAX_LAYERS."); + return false; + } + } + root.ymin = rcMin(root.ymin, regn.ymin); + root.ymax = rcMax(root.ymax, regn.ymax); + } + } + } + + layerId++; + } + + // Merge non-overlapping regions that are close in height. + const unsigned short mergeHeight = (unsigned short)walkableHeight * 4; + + for (int i = 0; i < nregs; ++i) + { + rcLayerRegion& ri = regs[i]; + if (!ri.base) continue; + + unsigned char newId = ri.layerId; + + for (;;) + { + unsigned char oldId = 0xff; + + for (int j = 0; j < nregs; ++j) + { + if (i == j) continue; + rcLayerRegion& rj = regs[j]; + if (!rj.base) continue; + + // Skip if the regions are not close to each other. + if (!overlapRange(ri.ymin,ri.ymax+mergeHeight, rj.ymin,rj.ymax+mergeHeight)) + continue; + // Skip if the height range would become too large. + const int ymin = rcMin(ri.ymin, rj.ymin); + const int ymax = rcMax(ri.ymax, rj.ymax); + if ((ymax - ymin) >= 255) + continue; + + // Make sure that there is no overlap when merging 'ri' and 'rj'. + bool overlap = false; + // Iterate over all regions which have the same layerId as 'rj' + for (int k = 0; k < nregs; ++k) + { + if (regs[k].layerId != rj.layerId) + continue; + // Check if region 'k' is overlapping region 'ri' + // Index to 'regs' is the same as region id. + if (contains(ri.layers,ri.nlayers, (unsigned char)k)) + { + overlap = true; + break; + } + } + // Cannot merge of regions overlap. + if (overlap) + continue; + + // Can merge i and j. + oldId = rj.layerId; + break; + } + + // Could not find anything to merge with, stop. + if (oldId == 0xff) + break; + + // Merge + for (int j = 0; j < nregs; ++j) + { + rcLayerRegion& rj = regs[j]; + if (rj.layerId == oldId) + { + rj.base = 0; + // Remap layerIds. + rj.layerId = newId; + // Add overlaid layers from 'rj' to 'ri'. + for (int k = 0; k < rj.nlayers; ++k) + { + if (!addUnique(ri.layers, ri.nlayers, RC_MAX_LAYERS, rj.layers[k])) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: layer overflow (too many overlapping walkable platforms). Try increasing RC_MAX_LAYERS."); + return false; + } + } + + // Update height bounds. + ri.ymin = rcMin(ri.ymin, rj.ymin); + ri.ymax = rcMax(ri.ymax, rj.ymax); + } + } + } + } + + // Compact layerIds + unsigned char remap[256]; + memset(remap, 0, 256); + + // Find number of unique layers. + layerId = 0; + for (int i = 0; i < nregs; ++i) + remap[regs[i].layerId] = 1; + for (int i = 0; i < 256; ++i) + { + if (remap[i]) + remap[i] = layerId++; + else + remap[i] = 0xff; + } + // Remap ids. + for (int i = 0; i < nregs; ++i) + regs[i].layerId = remap[regs[i].layerId]; + + // No layers, return empty. + if (layerId == 0) + return true; + + // Create layers. + rcAssert(lset.layers == 0); + + const int lw = w - borderSize*2; + const int lh = h - borderSize*2; + + // Build contracted bbox for layers. + float bmin[3], bmax[3]; + rcVcopy(bmin, chf.bmin); + rcVcopy(bmax, chf.bmax); + bmin[0] += borderSize*chf.cs; + bmin[2] += borderSize*chf.cs; + bmax[0] -= borderSize*chf.cs; + bmax[2] -= borderSize*chf.cs; + + lset.nlayers = (int)layerId; + + lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM); + if (!lset.layers) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'layers' (%d).", lset.nlayers); + return false; + } + memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers); + + + // Store layers. + for (int i = 0; i < lset.nlayers; ++i) + { + unsigned char curId = (unsigned char)i; + + rcHeightfieldLayer* layer = &lset.layers[i]; + + const int gridSize = sizeof(unsigned char)*lw*lh; + + layer->heights = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM); + if (!layer->heights) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", gridSize); + return false; + } + memset(layer->heights, 0xff, gridSize); + + layer->areas = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM); + if (!layer->areas) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'areas' (%d).", gridSize); + return false; + } + memset(layer->areas, 0, gridSize); + + layer->cons = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM); + if (!layer->cons) + { + ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'cons' (%d).", gridSize); + return false; + } + memset(layer->cons, 0, gridSize); + + // Find layer height bounds. + int hmin = 0, hmax = 0; + for (int j = 0; j < nregs; ++j) + { + if (regs[j].base && regs[j].layerId == curId) + { + hmin = (int)regs[j].ymin; + hmax = (int)regs[j].ymax; + } + } + + layer->width = lw; + layer->height = lh; + layer->cs = chf.cs; + layer->ch = chf.ch; + + // Adjust the bbox to fit the heightfield. + rcVcopy(layer->bmin, bmin); + rcVcopy(layer->bmax, bmax); + layer->bmin[1] = bmin[1] + hmin*chf.ch; + layer->bmax[1] = bmin[1] + hmax*chf.ch; + layer->hmin = hmin; + layer->hmax = hmax; + + // Update usable data region. + layer->minx = layer->width; + layer->maxx = 0; + layer->miny = layer->height; + layer->maxy = 0; + + // Copy height and area from compact heightfield. + for (int y = 0; y < lh; ++y) + { + for (int x = 0; x < lw; ++x) + { + const int cx = borderSize+x; + const int cy = borderSize+y; + const rcCompactCell& c = chf.cells[cx+cy*w]; + for (int j = (int)c.index, nj = (int)(c.index+c.count); j < nj; ++j) + { + const rcCompactSpan& s = chf.spans[j]; + // Skip unassigned regions. + if (srcReg[j] == 0xff) + continue; + // Skip of does nto belong to current layer. + unsigned char lid = regs[srcReg[j]].layerId; + if (lid != curId) + continue; + + // Update data bounds. + layer->minx = rcMin(layer->minx, x); + layer->maxx = rcMax(layer->maxx, x); + layer->miny = rcMin(layer->miny, y); + layer->maxy = rcMax(layer->maxy, y); + + // Store height and area type. + const int idx = x+y*lw; + layer->heights[idx] = (unsigned char)(s.y - hmin); + layer->areas[idx] = chf.areas[j]; + + // Check connection. + unsigned char portal = 0; + unsigned char con = 0; + for (int dir = 0; dir < 4; ++dir) + { + if (rcGetCon(s, dir) != RC_NOT_CONNECTED) + { + const int ax = cx + rcGetDirOffsetX(dir); + const int ay = cy + rcGetDirOffsetY(dir); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); + unsigned char alid = srcReg[ai] != 0xff ? regs[srcReg[ai]].layerId : 0xff; + // Portal mask + if (chf.areas[ai] != RC_NULL_AREA && lid != alid) + { + portal |= (unsigned char)(1<<dir); + // Update height so that it matches on both sides of the portal. + const rcCompactSpan& as = chf.spans[ai]; + if (as.y > hmin) + layer->heights[idx] = rcMax(layer->heights[idx], (unsigned char)(as.y - hmin)); + } + // Valid connection mask + if (chf.areas[ai] != RC_NULL_AREA && lid == alid) + { + const int nx = ax - borderSize; + const int ny = ay - borderSize; + if (nx >= 0 && ny >= 0 && nx < lw && ny < lh) + con |= (unsigned char)(1<<dir); + } + } + } + + layer->cons[idx] = (portal << 4) | con; + } + } + } + + if (layer->minx > layer->maxx) + layer->minx = layer->maxx = 0; + if (layer->miny > layer->maxy) + layer->miny = layer->maxy = 0; + } + + return true; +} diff --git a/deps/recastnavigation/Recast/RecastMesh.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastMesh.cpp index e7e2397dd6..9b6f04e309 100644 --- a/deps/recastnavigation/Recast/RecastMesh.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastMesh.cpp @@ -160,6 +160,7 @@ static unsigned short addVertex(unsigned short x, unsigned short y, unsigned sho return (unsigned short)i; } +// Last time I checked the if version got compiled using cmov, which was a lot faster than module (with idiv). inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; } inline int next(int i, int n) { return i+1 < n ? i+1 : 0; } @@ -197,7 +198,7 @@ inline bool collinear(const int* a, const int* b, const int* c) // Returns true iff ab properly intersects cd: they share // a point interior to both segments. The properness of the // intersection is ensured by using strict leftness. -bool intersectProp(const int* a, const int* b, const int* c, const int* d) +static bool intersectProp(const int* a, const int* b, const int* c, const int* d) { // Eliminate improper cases. if (collinear(a,b,c) || collinear(a,b,d) || @@ -288,6 +289,53 @@ static bool diagonal(int i, int j, int n, const int* verts, int* indices) return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices); } + +static bool diagonalieLoose(int i, int j, int n, const int* verts, int* indices) +{ + const int* d0 = &verts[(indices[i] & 0x0fffffff) * 4]; + const int* d1 = &verts[(indices[j] & 0x0fffffff) * 4]; + + // For each edge (k,k+1) of P + for (int k = 0; k < n; k++) + { + int k1 = next(k, n); + // Skip edges incident to i or j + if (!((k == i) || (k1 == i) || (k == j) || (k1 == j))) + { + const int* p0 = &verts[(indices[k] & 0x0fffffff) * 4]; + const int* p1 = &verts[(indices[k1] & 0x0fffffff) * 4]; + + if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1)) + continue; + + if (intersectProp(d0, d1, p0, p1)) + return false; + } + } + return true; +} + +static bool inConeLoose(int i, int j, int n, const int* verts, int* indices) +{ + const int* pi = &verts[(indices[i] & 0x0fffffff) * 4]; + const int* pj = &verts[(indices[j] & 0x0fffffff) * 4]; + const int* pi1 = &verts[(indices[next(i, n)] & 0x0fffffff) * 4]; + const int* pin1 = &verts[(indices[prev(i, n)] & 0x0fffffff) * 4]; + + // If P[i] is a convex vertex [ i+1 left or on (i-1,i) ]. + if (leftOn(pin1, pi, pi1)) + return leftOn(pi, pj, pin1) && leftOn(pj, pi, pi1); + // Assume (i-1,i,i+1) not collinear. + // else P[i] is reflex. + return !(leftOn(pi, pj, pi1) && leftOn(pj, pi, pin1)); +} + +static bool diagonalLoose(int i, int j, int n, const int* verts, int* indices) +{ + return inConeLoose(i, j, n, verts, indices) && diagonalieLoose(i, j, n, verts, indices); +} + + static int triangulate(int n, const int* verts, int* indices, int* tris) { int ntris = 0; @@ -328,14 +376,41 @@ static int triangulate(int n, const int* verts, int* indices, int* tris) if (mini == -1) { - // Should not happen. -/* printf("mini == -1 ntris=%d n=%d\n", ntris, n); + // We might get here because the contour has overlapping segments, like this: + // + // A o-o=====o---o B + // / |C D| \ + // o o o o + // : : : : + // We'll try to recover by loosing up the inCone test a bit so that a diagonal + // like A-B or C-D can be found and we can continue. + minLen = -1; + mini = -1; for (int i = 0; i < n; i++) { - printf("%d ", indices[i] & 0x0fffffff); + int i1 = next(i, n); + int i2 = next(i1, n); + if (diagonalLoose(i, i2, n, verts, indices)) + { + const int* p0 = &verts[(indices[i] & 0x0fffffff) * 4]; + const int* p2 = &verts[(indices[next(i2, n)] & 0x0fffffff) * 4]; + int dx = p2[0] - p0[0]; + int dy = p2[2] - p0[2]; + int len = dx*dx + dy*dy; + + if (minLen < 0 || len < minLen) + { + minLen = len; + mini = i; + } + } + } + if (mini == -1) + { + // The contour is messed up. This sometimes happens + // if the contour simplification is too aggressive. + return -ntris; } - printf("\n");*/ - return -ntris; } int i = mini; @@ -453,8 +528,8 @@ static int getPolyMergeValue(unsigned short* pa, unsigned short* pb, return dx*dx + dy*dy; } -static void mergePolys(unsigned short* pa, unsigned short* pb, int ea, int eb, - unsigned short* tmp, const int nvp) +static void mergePolyVerts(unsigned short* pa, unsigned short* pb, int ea, int eb, + unsigned short* tmp, const int nvp) { const int na = countPolyVerts(pa, nvp); const int nb = countPolyVerts(pb, nvp); @@ -472,6 +547,7 @@ static void mergePolys(unsigned short* pa, unsigned short* pb, int ea, int eb, memcpy(pa, tmp, sizeof(unsigned short)*nvp); } + static void pushFront(int v, int* arr, int& an) { an++; @@ -525,7 +601,7 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho // Find edges which share the removed vertex. const int maxEdges = numTouchedVerts*2; int nedges = 0; - rcScopedDelete<int> edges = (int*)rcAlloc(sizeof(int)*maxEdges*3, RC_ALLOC_TEMP); + rcScopedDelete<int> edges((int*)rcAlloc(sizeof(int)*maxEdges*3, RC_ALLOC_TEMP)); if (!edges) { ctx->log(RC_LOG_WARNING, "canRemoveVertex: Out of memory 'edges' (%d).", maxEdges*3); @@ -549,9 +625,9 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho // Check if the edge exists bool exists = false; - for (int k = 0; k < nedges; ++k) + for (int m = 0; m < nedges; ++m) { - int* e = &edges[k*3]; + int* e = &edges[m*3]; if (e[1] == b) { // Exists, increment vertex share count. @@ -605,7 +681,7 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short } int nedges = 0; - rcScopedDelete<int> edges = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp*4, RC_ALLOC_TEMP); + rcScopedDelete<int> edges((int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp*4, RC_ALLOC_TEMP)); if (!edges) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'edges' (%d).", numRemovedVerts*nvp*4); @@ -613,15 +689,15 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short } int nhole = 0; - rcScopedDelete<int> hole = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); + rcScopedDelete<int> hole((int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP)); if (!hole) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hole' (%d).", numRemovedVerts*nvp); return false; } - + int nhreg = 0; - rcScopedDelete<int> hreg = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); + rcScopedDelete<int> hreg((int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP)); if (!hreg) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hreg' (%d).", numRemovedVerts*nvp); @@ -629,7 +705,7 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short } int nharea = 0; - rcScopedDelete<int> harea = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); + rcScopedDelete<int> harea((int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP)); if (!harea) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'harea' (%d).", numRemovedVerts*nvp); @@ -660,7 +736,8 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short } // Remove the polygon. unsigned short* p2 = &mesh.polys[(mesh.npolys-1)*nvp*2]; - memcpy(p,p2,sizeof(unsigned short)*nvp); + if (p != p2) + memcpy(p,p2,sizeof(unsigned short)*nvp); memset(p+nvp,0xff,sizeof(unsigned short)*nvp); mesh.regs[i] = mesh.regs[mesh.npolys-1]; mesh.areas[i] = mesh.areas[mesh.npolys-1]; @@ -670,7 +747,7 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short } // Remove vertex. - for (int i = (int)rem; i < mesh.nverts; ++i) + for (int i = (int)rem; i < mesh.nverts - 1; ++i) { mesh.verts[i*3+0] = mesh.verts[(i+1)*3+0]; mesh.verts[i*3+1] = mesh.verts[(i+1)*3+1]; @@ -745,22 +822,22 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short break; } - rcScopedDelete<int> tris = (int*)rcAlloc(sizeof(int)*nhole*3, RC_ALLOC_TEMP); + rcScopedDelete<int> tris((int*)rcAlloc(sizeof(int)*nhole*3, RC_ALLOC_TEMP)); if (!tris) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tris' (%d).", nhole*3); return false; } - rcScopedDelete<int> tverts = (int*)rcAlloc(sizeof(int)*nhole*4, RC_ALLOC_TEMP); + rcScopedDelete<int> tverts((int*)rcAlloc(sizeof(int)*nhole*4, RC_ALLOC_TEMP)); if (!tverts) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tverts' (%d).", nhole*4); return false; } - rcScopedDelete<int> thole = (int*)rcAlloc(sizeof(int)*nhole, RC_ALLOC_TEMP); - if (!tverts) + rcScopedDelete<int> thole((int*)rcAlloc(sizeof(int)*nhole, RC_ALLOC_TEMP)); + if (!thole) { ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'thole' (%d).", nhole); return false; @@ -786,20 +863,20 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short } // Merge the hole triangles back to polygons. - rcScopedDelete<unsigned short> polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*(ntris+1)*nvp, RC_ALLOC_TEMP); + rcScopedDelete<unsigned short> polys((unsigned short*)rcAlloc(sizeof(unsigned short)*(ntris+1)*nvp, RC_ALLOC_TEMP)); if (!polys) { ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'polys' (%d).", (ntris+1)*nvp); return false; } - rcScopedDelete<unsigned short> pregs = (unsigned short*)rcAlloc(sizeof(unsigned short)*ntris, RC_ALLOC_TEMP); + rcScopedDelete<unsigned short> pregs((unsigned short*)rcAlloc(sizeof(unsigned short)*ntris, RC_ALLOC_TEMP)); if (!pregs) { ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pregs' (%d).", ntris); return false; } - rcScopedDelete<unsigned char> pareas = (unsigned char*)rcAlloc(sizeof(unsigned char)*ntris, RC_ALLOC_TEMP); - if (!pregs) + rcScopedDelete<unsigned char> pareas((unsigned char*)rcAlloc(sizeof(unsigned char)*ntris, RC_ALLOC_TEMP)); + if (!pareas) { ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pareas' (%d).", ntris); return false; @@ -818,7 +895,14 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short polys[npolys*nvp+0] = (unsigned short)hole[t[0]]; polys[npolys*nvp+1] = (unsigned short)hole[t[1]]; polys[npolys*nvp+2] = (unsigned short)hole[t[2]]; - pregs[npolys] = (unsigned short)hreg[t[0]]; + + // If this polygon covers multiple region types then + // mark it as such + if (hreg[t[0]] != hreg[t[1]] || hreg[t[1]] != hreg[t[2]]) + pregs[npolys] = RC_MULTIPLE_REGS; + else + pregs[npolys] = (unsigned short)hreg[t[0]]; + pareas[npolys] = (unsigned char)harea[t[0]]; npolys++; } @@ -859,8 +943,13 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short // Found best, merge. unsigned short* pa = &polys[bestPa*nvp]; unsigned short* pb = &polys[bestPb*nvp]; - mergePolys(pa, pb, bestEa, bestEb, tmpPoly, nvp); - memcpy(pb, &polys[(npolys-1)*nvp], sizeof(unsigned short)*nvp); + mergePolyVerts(pa, pb, bestEa, bestEb, tmpPoly, nvp); + if (pregs[bestPa] != pregs[bestPb]) + pregs[bestPa] = RC_MULTIPLE_REGS; + + unsigned short* last = &polys[(npolys-1)*nvp]; + if (pb != last) + memcpy(pb, last, sizeof(unsigned short)*nvp); pregs[bestPb] = pregs[npolys-1]; pareas[bestPb] = pareas[npolys-1]; npolys--; @@ -894,17 +983,24 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short return true; } - -bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh) +/// @par +/// +/// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper +/// limit must be retricted to <= #DT_VERTS_PER_POLYGON. +/// +/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig +bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_POLYMESH); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_POLYMESH); rcVcopy(mesh.bmin, cset.bmin); rcVcopy(mesh.bmax, cset.bmax); mesh.cs = cset.cs; mesh.ch = cset.ch; + mesh.borderSize = cset.borderSize; + mesh.maxEdgeError = cset.maxError; int maxVertices = 0; int maxTris = 0; @@ -924,10 +1020,10 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me return false; } - rcScopedDelete<unsigned char> vflags = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxVertices, RC_ALLOC_TEMP); + rcScopedDelete<unsigned char> vflags((unsigned char*)rcAlloc(sizeof(unsigned char)*maxVertices, RC_ALLOC_TEMP)); if (!vflags) { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'vflags' (%d).", maxVertices); return false; } memset(vflags, 0, maxVertices); @@ -938,7 +1034,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); return false; } - mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2*2, RC_ALLOC_PERM); + mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2, RC_ALLOC_PERM); if (!mesh.polys) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.polys' (%d).", maxTris*nvp*2); @@ -967,7 +1063,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me memset(mesh.regs, 0, sizeof(unsigned short)*maxTris); memset(mesh.areas, 0, sizeof(unsigned char)*maxTris); - rcScopedDelete<int> nextVert = (int*)rcAlloc(sizeof(int)*maxVertices, RC_ALLOC_TEMP); + rcScopedDelete<int> nextVert((int*)rcAlloc(sizeof(int)*maxVertices, RC_ALLOC_TEMP)); if (!nextVert) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'nextVert' (%d).", maxVertices); @@ -975,7 +1071,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me } memset(nextVert, 0, sizeof(int)*maxVertices); - rcScopedDelete<int> firstVert = (int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP); + rcScopedDelete<int> firstVert((int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP)); if (!firstVert) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); @@ -984,19 +1080,19 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i) firstVert[i] = -1; - rcScopedDelete<int> indices = (int*)rcAlloc(sizeof(int)*maxVertsPerCont, RC_ALLOC_TEMP); + rcScopedDelete<int> indices((int*)rcAlloc(sizeof(int)*maxVertsPerCont, RC_ALLOC_TEMP)); if (!indices) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'indices' (%d).", maxVertsPerCont); return false; } - rcScopedDelete<int> tris = (int*)rcAlloc(sizeof(int)*maxVertsPerCont*3, RC_ALLOC_TEMP); + rcScopedDelete<int> tris((int*)rcAlloc(sizeof(int)*maxVertsPerCont*3, RC_ALLOC_TEMP)); if (!tris) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'tris' (%d).", maxVertsPerCont*3); return false; } - rcScopedDelete<unsigned short> polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*(maxVertsPerCont+1)*nvp, RC_ALLOC_TEMP); + rcScopedDelete<unsigned short> polys((unsigned short*)rcAlloc(sizeof(unsigned short)*(maxVertsPerCont+1)*nvp, RC_ALLOC_TEMP)); if (!polys) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'polys' (%d).", maxVertsPerCont*nvp); @@ -1046,7 +1142,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me vflags[indices[j]] = 1; } } - + // Build initial polygons. int npolys = 0; memset(polys, 0xff, maxVertsPerCont*nvp*sizeof(unsigned short)); @@ -1097,8 +1193,10 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me // Found best, merge. unsigned short* pa = &polys[bestPa*nvp]; unsigned short* pb = &polys[bestPb*nvp]; - mergePolys(pa, pb, bestEa, bestEb, tmpPoly, nvp); - memcpy(pb, &polys[(npolys-1)*nvp], sizeof(unsigned short)*nvp); + mergePolyVerts(pa, pb, bestEa, bestEb, tmpPoly, nvp); + unsigned short* lastPoly = &polys[(npolys-1)*nvp]; + if (pb != lastPoly) + memcpy(pb, lastPoly, sizeof(unsigned short)*nvp); npolys--; } else @@ -1143,6 +1241,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me } // Remove vertex // Note: mesh.nverts is already decremented inside removeVertex()! + // Fixup vertex flags for (int j = i; j < mesh.nverts; ++j) vflags[j] = vflags[j+1]; --i; @@ -1155,6 +1254,37 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed."); return false; } + + // Find portal edges + if (mesh.borderSize > 0) + { + const int w = cset.width; + const int h = cset.height; + for (int i = 0; i < mesh.npolys; ++i) + { + unsigned short* p = &mesh.polys[i*2*nvp]; + for (int j = 0; j < nvp; ++j) + { + if (p[j] == RC_MESH_NULL_IDX) break; + // Skip connected edges. + if (p[nvp+j] != RC_MESH_NULL_IDX) + continue; + int nj = j+1; + if (nj >= nvp || p[nj] == RC_MESH_NULL_IDX) nj = 0; + const unsigned short* va = &mesh.verts[p[j]*3]; + const unsigned short* vb = &mesh.verts[p[nj]*3]; + + if ((int)va[0] == 0 && (int)vb[0] == 0) + p[nvp+j] = 0x8000 | 0; + else if ((int)va[2] == h && (int)vb[2] == h) + p[nvp+j] = 0x8000 | 1; + else if ((int)va[0] == w && (int)vb[0] == w) + p[nvp+j] = 0x8000 | 2; + else if ((int)va[2] == 0 && (int)vb[2] == 0) + p[nvp+j] = 0x8000 | 3; + } + } + } // Just allocate the mesh flags array. The user is resposible to fill it. mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*mesh.npolys, RC_ALLOC_PERM); @@ -1167,18 +1297,17 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& me if (mesh.nverts > 0xffff) { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff); } if (mesh.npolys > 0xffff) { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); + ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); } - ctx->stopTimer(RC_TIMER_BUILD_POLYMESH); - return true; } +/// @see rcAllocPolyMesh, rcPolyMesh bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) { rcAssert(ctx); @@ -1186,7 +1315,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r if (!nmeshes || !meshes) return true; - ctx->startTimer(RC_TIMER_MERGE_POLYMESH); + rcScopedTimer timer(ctx, RC_TIMER_MERGE_POLYMESH); mesh.nvp = meshes[0]->nvp; mesh.cs = meshes[0]->cs; @@ -1247,7 +1376,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r } memset(mesh.flags, 0, sizeof(unsigned short)*maxPolys); - rcScopedDelete<int> nextVert = (int*)rcAlloc(sizeof(int)*maxVerts, RC_ALLOC_TEMP); + rcScopedDelete<int> nextVert((int*)rcAlloc(sizeof(int)*maxVerts, RC_ALLOC_TEMP)); if (!nextVert) { ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'nextVert' (%d).", maxVerts); @@ -1255,7 +1384,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r } memset(nextVert, 0, sizeof(int)*maxVerts); - rcScopedDelete<int> firstVert = (int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP); + rcScopedDelete<int> firstVert((int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP)); if (!firstVert) { ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); @@ -1264,7 +1393,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i) firstVert[i] = -1; - rcScopedDelete<unsigned short> vremap = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVertsPerMesh, RC_ALLOC_PERM); + rcScopedDelete<unsigned short> vremap((unsigned short*)rcAlloc(sizeof(unsigned short)*maxVertsPerMesh, RC_ALLOC_PERM)); if (!vremap) { ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'vremap' (%d).", maxVertsPerMesh); @@ -1279,6 +1408,12 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r const unsigned short ox = (unsigned short)floorf((pmesh->bmin[0]-mesh.bmin[0])/mesh.cs+0.5f); const unsigned short oz = (unsigned short)floorf((pmesh->bmin[2]-mesh.bmin[2])/mesh.cs+0.5f); + bool isMinX = (ox == 0); + bool isMinZ = (oz == 0); + bool isMaxX = ((unsigned short)floorf((mesh.bmax[0] - pmesh->bmax[0]) / mesh.cs + 0.5f)) == 0; + bool isMaxZ = ((unsigned short)floorf((mesh.bmax[2] - pmesh->bmax[2]) / mesh.cs + 0.5f)) == 0; + bool isOnBorder = (isMinX || isMinZ || isMaxX || isMaxZ); + for (int j = 0; j < pmesh->nverts; ++j) { unsigned short* v = &pmesh->verts[j*3]; @@ -1299,6 +1434,36 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r if (src[k] == RC_MESH_NULL_IDX) break; tgt[k] = vremap[src[k]]; } + + if (isOnBorder) + { + for (int k = mesh.nvp; k < mesh.nvp * 2; ++k) + { + if (src[k] & 0x8000 && src[k] != 0xffff) + { + unsigned short dir = src[k] & 0xf; + switch (dir) + { + case 0: // Portal x- + if (isMinX) + tgt[k] = src[k]; + break; + case 1: // Portal z+ + if (isMaxZ) + tgt[k] = src[k]; + break; + case 2: // Portal x+ + if (isMaxX) + tgt[k] = src[k]; + break; + case 3: // Portal z- + if (isMinZ) + tgt[k] = src[k]; + break; + } + } + } + } } } @@ -1318,7 +1483,70 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); } - ctx->stopTimer(RC_TIMER_MERGE_POLYMESH); + return true; +} + +bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst) +{ + rcAssert(ctx); + + // Destination must be empty. + rcAssert(dst.verts == 0); + rcAssert(dst.polys == 0); + rcAssert(dst.regs == 0); + rcAssert(dst.areas == 0); + rcAssert(dst.flags == 0); + + dst.nverts = src.nverts; + dst.npolys = src.npolys; + dst.maxpolys = src.npolys; + dst.nvp = src.nvp; + rcVcopy(dst.bmin, src.bmin); + rcVcopy(dst.bmax, src.bmax); + dst.cs = src.cs; + dst.ch = src.ch; + dst.borderSize = src.borderSize; + dst.maxEdgeError = src.maxEdgeError; + + dst.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.nverts*3, RC_ALLOC_PERM); + if (!dst.verts) + { + ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.verts' (%d).", src.nverts*3); + return false; + } + memcpy(dst.verts, src.verts, sizeof(unsigned short)*src.nverts*3); + + dst.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys*2*src.nvp, RC_ALLOC_PERM); + if (!dst.polys) + { + ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.polys' (%d).", src.npolys*2*src.nvp); + return false; + } + memcpy(dst.polys, src.polys, sizeof(unsigned short)*src.npolys*2*src.nvp); + + dst.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM); + if (!dst.regs) + { + ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.regs' (%d).", src.npolys); + return false; + } + memcpy(dst.regs, src.regs, sizeof(unsigned short)*src.npolys); + + dst.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*src.npolys, RC_ALLOC_PERM); + if (!dst.areas) + { + ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.areas' (%d).", src.npolys); + return false; + } + memcpy(dst.areas, src.areas, sizeof(unsigned char)*src.npolys); + + dst.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM); + if (!dst.flags) + { + ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.flags' (%d).", src.npolys); + return false; + } + memcpy(dst.flags, src.flags, sizeof(unsigned short)*src.npolys); return true; } diff --git a/deps/recastnavigation/Recast/RecastMeshDetail.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastMeshDetail.cpp index ffb4b58ee9..f953132f74 100644 --- a/deps/recastnavigation/Recast/RecastMeshDetail.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastMeshDetail.cpp @@ -56,7 +56,7 @@ inline float vdist2(const float* p, const float* q) } inline float vcross2(const float* p1, const float* p2, const float* p3) -{ +{ const float u1 = p2[0] - p1[0]; const float v1 = p2[2] - p1[2]; const float u2 = p3[0] - p1[0]; @@ -68,21 +68,27 @@ static bool circumCircle(const float* p1, const float* p2, const float* p3, float* c, float& r) { static const float EPS = 1e-6f; + // Calculate the circle relative to p1, to avoid some precision issues. + const float v1[3] = {0,0,0}; + float v2[3], v3[3]; + rcVsub(v2, p2,p1); + rcVsub(v3, p3,p1); - const float cp = vcross2(p1, p2, p3); + const float cp = vcross2(v1, v2, v3); if (fabsf(cp) > EPS) { - const float p1Sq = vdot2(p1,p1); - const float p2Sq = vdot2(p2,p2); - const float p3Sq = vdot2(p3,p3); - c[0] = (p1Sq*(p2[2]-p3[2]) + p2Sq*(p3[2]-p1[2]) + p3Sq*(p1[2]-p2[2])) / (2*cp); - c[2] = (p1Sq*(p3[0]-p2[0]) + p2Sq*(p1[0]-p3[0]) + p3Sq*(p2[0]-p1[0])) / (2*cp); - r = vdist2(c, p1); + const float v1Sq = vdot2(v1,v1); + const float v2Sq = vdot2(v2,v2); + const float v3Sq = vdot2(v3,v3); + c[0] = (v1Sq*(v2[2]-v3[2]) + v2Sq*(v3[2]-v1[2]) + v3Sq*(v1[2]-v2[2])) / (2*cp); + c[1] = 0; + c[2] = (v1Sq*(v3[0]-v2[0]) + v2Sq*(v1[0]-v3[0]) + v3Sq*(v2[0]-v1[0])) / (2*cp); + r = vdist2(c, v1); + rcVadd(c, c, p1); return true; } - - c[0] = p1[0]; - c[2] = p1[2]; + + rcVcopy(c, p1); r = 0; return false; } @@ -93,7 +99,7 @@ static float distPtTri(const float* p, const float* a, const float* b, const flo rcVsub(v0, c,a); rcVsub(v1, b,a); rcVsub(v2, p,a); - + const float dot00 = vdot2(v0, v0); const float dot01 = vdot2(v0, v1); const float dot02 = vdot2(v0, v2); @@ -178,7 +184,7 @@ static float distToTriMesh(const float* p, const float* verts, const int /*nvert static float distToPoly(int nvert, const float* verts, const float* p) { - + float dmin = FLT_MAX; int i, j, c = 0; for (i = 0, j = nvert-1; i < nvert; j = i++) @@ -196,42 +202,79 @@ static float distToPoly(int nvert, const float* verts, const float* p) static unsigned short getHeight(const float fx, const float fy, const float fz, const float /*cs*/, const float ics, const float ch, - const rcHeightPatch& hp) + const int radius, const rcHeightPatch& hp) { int ix = (int)floorf(fx*ics + 0.01f); int iz = (int)floorf(fz*ics + 0.01f); - ix = rcClamp(ix-hp.xmin, 0, hp.width); - iz = rcClamp(iz-hp.ymin, 0, hp.height); + ix = rcClamp(ix-hp.xmin, 0, hp.width - 1); + iz = rcClamp(iz-hp.ymin, 0, hp.height - 1); unsigned short h = hp.data[ix+iz*hp.width]; if (h == RC_UNSET_HEIGHT) { // Special case when data might be bad. - // Find nearest neighbour pixel which has valid height. - const int off[8*2] = { -1,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1}; + // Walk adjacent cells in a spiral up to 'radius', and look + // for a pixel which has a valid height. + int x = 1, z = 0, dx = 1, dz = 0; + int maxSize = radius * 2 + 1; + int maxIter = maxSize * maxSize - 1; + + int nextRingIterStart = 8; + int nextRingIters = 16; + float dmin = FLT_MAX; - for (int i = 0; i < 8; ++i) + for (int i = 0; i < maxIter; i++) { - const int nx = ix+off[i*2+0]; - const int nz = iz+off[i*2+1]; - if (nx < 0 || nz < 0 || nx >= hp.width || nz >= hp.height) continue; - const unsigned short nh = hp.data[nx+nz*hp.width]; - if (nh == RC_UNSET_HEIGHT) continue; + const int nx = ix + x; + const int nz = iz + z; + + if (nx >= 0 && nz >= 0 && nx < hp.width && nz < hp.height) + { + const unsigned short nh = hp.data[nx + nz*hp.width]; + if (nh != RC_UNSET_HEIGHT) + { + const float d = fabsf(nh*ch - fy); + if (d < dmin) + { + h = nh; + dmin = d; + } + } + } - const float d = fabsf(nh*ch - fy); - if (d < dmin) + // We are searching in a grid which looks approximately like this: + // __________ + // |2 ______ 2| + // | |1 __ 1| | + // | | |__| | | + // | |______| | + // |__________| + // We want to find the best height as close to the center cell as possible. This means that + // if we find a height in one of the neighbor cells to the center, we don't want to + // expand further out than the 8 neighbors - we want to limit our search to the closest + // of these "rings", but the best height in the ring. + // For example, the center is just 1 cell. We checked that at the entrance to the function. + // The next "ring" contains 8 cells (marked 1 above). Those are all the neighbors to the center cell. + // The next one again contains 16 cells (marked 2). In general each ring has 8 additional cells, which + // can be thought of as adding 2 cells around the "center" of each side when we expand the ring. + // Here we detect if we are about to enter the next ring, and if we are and we have found + // a height, we abort the search. + if (i + 1 == nextRingIterStart) { - h = nh; - dmin = d; + if (h != RC_UNSET_HEIGHT) + break; + + nextRingIterStart += nextRingIters; + nextRingIters += 8; } - -/* const float dx = (nx+0.5f)*cs - fx; - const float dz = (nz+0.5f)*cs - fz; - const float d = dx*dx+dz*dz; - if (d < dmin) + + if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) { - h = nh; - dmin = d; - } */ + int tmp = dx; + dx = -dz; + dz = tmp; + } + x += dx; + z += dz; } } return h; @@ -240,8 +283,8 @@ static unsigned short getHeight(const float fx, const float fy, const float fz, enum EdgeValues { - UNDEF = -1, - HULL = -2, + EV_UNDEF = -1, + EV_HULL = -2, }; static int findEdge(const int* edges, int nedges, int s, int t) @@ -252,7 +295,7 @@ static int findEdge(const int* edges, int nedges, int s, int t) if ((e[0] == s && e[1] == t) || (e[0] == t && e[1] == s)) return i; } - return UNDEF; + return EV_UNDEF; } static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r) @@ -260,33 +303,33 @@ static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges, if (nedges >= maxEdges) { ctx->log(RC_LOG_ERROR, "addEdge: Too many edges (%d/%d).", nedges, maxEdges); - return UNDEF; + return EV_UNDEF; } - // Add edge if not already in the triangulation. + // Add edge if not already in the triangulation. int e = findEdge(edges, nedges, s, t); - if (e == UNDEF) + if (e == EV_UNDEF) { - int* e = &edges[nedges*4]; - e[0] = s; - e[1] = t; - e[2] = l; - e[3] = r; + int* edge = &edges[nedges*4]; + edge[0] = s; + edge[1] = t; + edge[2] = l; + edge[3] = r; return nedges++; } else { - return UNDEF; + return EV_UNDEF; } } static void updateLeftFace(int* e, int s, int t, int f) { - if (e[0] == s && e[1] == t && e[2] == UNDEF) + if (e[0] == s && e[1] == t && e[2] == EV_UNDEF) e[2] = f; - else if (e[1] == s && e[0] == t && e[3] == UNDEF) + else if (e[1] == s && e[0] == t && e[3] == EV_UNDEF) e[3] = f; -} +} static int overlapSegSeg2d(const float* a, const float* b, const float* c, const float* d) { @@ -298,7 +341,7 @@ static int overlapSegSeg2d(const float* a, const float* b, const float* c, const float a4 = a3 + a2 - a1; if (a3 * a4 < 0.0f) return 1; - } + } return 0; } @@ -320,28 +363,28 @@ static bool overlapEdges(const float* pts, const int* edges, int nedges, int s1, static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e) { static const float EPS = 1e-5f; - + int* edge = &edges[e*4]; // Cache s and t. int s,t; - if (edge[2] == UNDEF) + if (edge[2] == EV_UNDEF) { s = edge[0]; t = edge[1]; } - else if (edge[3] == UNDEF) + else if (edge[3] == EV_UNDEF) { s = edge[1]; t = edge[0]; } else { - // Edge already completed. + // Edge already completed. return; } - // Find best point on left of edge. + // Find best point on left of edge. int pt = npts; float c[3] = {0,0,0}; float r = -1; @@ -385,23 +428,23 @@ static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges } } - // Add new triangle or update edge info if s-t is on hull. + // Add new triangle or update edge info if s-t is on hull. if (pt < npts) { - // Update face information of edge being completed. + // Update face information of edge being completed. updateLeftFace(&edges[e*4], s, t, nfaces); - // Add new edge or update face info of old edge. + // Add new edge or update face info of old edge. e = findEdge(edges, nedges, pt, s); - if (e == UNDEF) - addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, UNDEF); + if (e == EV_UNDEF) + addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, EV_UNDEF); else updateLeftFace(&edges[e*4], pt, s, nfaces); - // Add new edge or update face info of old edge. + // Add new edge or update face info of old edge. e = findEdge(edges, nedges, t, pt); - if (e == UNDEF) - addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, UNDEF); + if (e == EV_UNDEF) + addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, EV_UNDEF); else updateLeftFace(&edges[e*4], t, pt, nfaces); @@ -409,7 +452,7 @@ static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges } else { - updateLeftFace(&edges[e*4], s, t, HULL); + updateLeftFace(&edges[e*4], s, t, EV_HULL); } } @@ -423,18 +466,18 @@ static void delaunayHull(rcContext* ctx, const int npts, const float* pts, edges.resize(maxEdges*4); for (int i = 0, j = nhull-1; i < nhull; j=i++) - addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], HULL, UNDEF); + addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], EV_HULL, EV_UNDEF); int currentEdge = 0; while (currentEdge < nedges) { - if (edges[currentEdge*4+2] == UNDEF) + if (edges[currentEdge*4+2] == EV_UNDEF) completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); - if (edges[currentEdge*4+3] == UNDEF) + if (edges[currentEdge*4+3] == EV_UNDEF) completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); currentEdge++; } - + // Create tris tris.resize(nfaces*4); for (int i = 0; i < nfaces*4; ++i) @@ -489,6 +532,97 @@ static void delaunayHull(rcContext* ctx, const int npts, const float* pts, } } +// Calculate minimum extend of the polygon. +static float polyMinExtent(const float* verts, const int nverts) +{ + float minDist = FLT_MAX; + for (int i = 0; i < nverts; i++) + { + const int ni = (i+1) % nverts; + const float* p1 = &verts[i*3]; + const float* p2 = &verts[ni*3]; + float maxEdgeDist = 0; + for (int j = 0; j < nverts; j++) + { + if (j == i || j == ni) continue; + float d = distancePtSeg2d(&verts[j*3], p1,p2); + maxEdgeDist = rcMax(maxEdgeDist, d); + } + minDist = rcMin(minDist, maxEdgeDist); + } + return rcSqrt(minDist); +} + +// Last time I checked the if version got compiled using cmov, which was a lot faster than module (with idiv). +inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; } +inline int next(int i, int n) { return i+1 < n ? i+1 : 0; } + +static void triangulateHull(const int /*nverts*/, const float* verts, const int nhull, const int* hull, rcIntArray& tris) +{ + int start = 0, left = 1, right = nhull-1; + + // Start from an ear with shortest perimeter. + // This tends to favor well formed triangles as starting point. + float dmin = 0; + for (int i = 0; i < nhull; i++) + { + int pi = prev(i, nhull); + int ni = next(i, nhull); + const float* pv = &verts[hull[pi]*3]; + const float* cv = &verts[hull[i]*3]; + const float* nv = &verts[hull[ni]*3]; + const float d = vdist2(pv,cv) + vdist2(cv,nv) + vdist2(nv,pv); + if (d < dmin) + { + start = i; + left = ni; + right = pi; + dmin = d; + } + } + + // Add first triangle + tris.push(hull[start]); + tris.push(hull[left]); + tris.push(hull[right]); + tris.push(0); + + // Triangulate the polygon by moving left or right, + // depending on which triangle has shorter perimeter. + // This heuristic was chose emprically, since it seems + // handle tesselated straight edges well. + while (next(left, nhull) != right) + { + // Check to see if se should advance left or right. + int nleft = next(left, nhull); + int nright = prev(right, nhull); + + const float* cvleft = &verts[hull[left]*3]; + const float* nvleft = &verts[hull[nleft]*3]; + const float* cvright = &verts[hull[right]*3]; + const float* nvright = &verts[hull[nright]*3]; + const float dleft = vdist2(cvleft, nvleft) + vdist2(nvleft, cvright); + const float dright = vdist2(cvright, nvright) + vdist2(cvleft, nvright); + + if (dleft < dright) + { + tris.push(hull[left]); + tris.push(hull[nleft]); + tris.push(hull[right]); + tris.push(0); + left = nleft; + } + else + { + tris.push(hull[left]); + tris.push(hull[nright]); + tris.push(hull[right]); + tris.push(0); + right = nright; + } + } +} + inline float getJitterX(const int i) { @@ -502,9 +636,9 @@ inline float getJitterY(const int i) static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, const float sampleDist, const float sampleMaxError, - const rcCompactHeightfield& chf, const rcHeightPatch& hp, - float* verts, int& nverts, rcIntArray& tris, - rcIntArray& edges, rcIntArray& samples) + const int heightSearchRadius, const rcCompactHeightfield& chf, + const rcHeightPatch& hp, float* verts, int& nverts, + rcIntArray& tris, rcIntArray& edges, rcIntArray& samples) { static const int MAX_VERTS = 127; static const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts). @@ -512,16 +646,21 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, float edge[(MAX_VERTS_PER_EDGE+1)*3]; int hull[MAX_VERTS]; int nhull = 0; - - nverts = 0; - + + nverts = nin; + for (int i = 0; i < nin; ++i) rcVcopy(&verts[i*3], &in[i*3]); - nverts = nin; + + edges.resize(0); + tris.resize(0); const float cs = chf.cs; const float ics = 1.0f/cs; + // Calculate minimum extents of the polygon based on input data. + float minExtent = polyMinExtent(verts, nverts); + // Tessellate outlines. // This is done in separate pass in order to ensure // seamless height values across the ply boundaries. @@ -567,7 +706,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, pos[0] = vj[0] + dx*u; pos[1] = vj[1] + dy*u; pos[2] = vj[2] + dz*u; - pos[1] = getHeight(pos[0],pos[1],pos[2], cs, ics, chf.ch, hp)*chf.ch; + pos[1] = getHeight(pos[0],pos[1],pos[2], cs, ics, chf.ch, heightSearchRadius, hp)*chf.ch; } // Simplify samples. int idx[MAX_VERTS_PER_EDGE] = {0,nn}; @@ -583,10 +722,10 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, int maxi = -1; for (int m = a+1; m < b; ++m) { - float d = distancePtSeg(&edge[m*3],va,vb); - if (d > maxd) + float dev = distancePtSeg(&edge[m*3],va,vb); + if (dev > maxd) { - maxd = d; + maxd = dev; maxi = m; } } @@ -628,27 +767,26 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, } } - + // If the polygon minimum extent is small (sliver or small triangle), do not try to add internal points. + if (minExtent < sampleDist*2) + { + triangulateHull(nverts, verts, nhull, hull, tris); + return true; + } + // Tessellate the base mesh. - edges.resize(0); - tris.resize(0); - - delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges); + // We're using the triangulateHull instead of delaunayHull as it tends to + // create a bit better triangulation for long thin triangles when there + // are no internal points. + triangulateHull(nverts, verts, nhull, hull, tris); if (tris.size() == 0) { // Could not triangulate the poly, make sure there is some valid data there. - ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon, adding default data."); - for (int i = 2; i < nverts; ++i) - { - tris.push(0); - tris.push(i-1); - tris.push(i); - tris.push(0); - } + ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon (%d verts).", nverts); return true; } - + if (sampleDist > 0) { // Create sample locations in a grid. @@ -676,12 +814,12 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, // Make sure the samples are not too close to the edges. if (distToPoly(nin,in,pt) > -sampleDist/2) continue; samples.push(x); - samples.push(getHeight(pt[0], pt[1], pt[2], cs, ics, chf.ch, hp)); + samples.push(getHeight(pt[0], pt[1], pt[2], cs, ics, chf.ch, heightSearchRadius, hp)); samples.push(z); samples.push(0); // Not added } } - + // Add the samples starting from the one that has the most // error. The procedure stops when all samples are added // or when the max error is within treshold. @@ -690,7 +828,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, { if (nverts >= MAX_VERTS) break; - + // Find sample with most error. float bestpt[3] = {0,0,0}; float bestd = 0; @@ -728,42 +866,38 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, edges.resize(0); tris.resize(0); delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges); - } + } } - + const int ntris = tris.size()/4; if (ntris > MAX_TRIS) { tris.resize(MAX_TRIS*4); ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Shrinking triangle count from %d to max %d.", ntris, MAX_TRIS); } - + return true; } -static void getHeightData(const rcCompactHeightfield& chf, - const unsigned short* poly, const int npoly, - const unsigned short* verts, - rcHeightPatch& hp, rcIntArray& stack) +static void seedArrayWithPolyCenter(rcContext* ctx, const rcCompactHeightfield& chf, + const unsigned short* poly, const int npoly, + const unsigned short* verts, const int bs, + rcHeightPatch& hp, rcIntArray& array) { - // Floodfill the heightfield to get 2D height data, - // starting at vertex locations as seeds. - - memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height); - - stack.resize(0); + // Note: Reads to the compact heightfield are offset by border size (bs) + // since border size offset is already removed from the polymesh vertices. static const int offset[9*2] = { 0,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0, }; - // Use poly vertices as seed points for the flood fill. - for (int j = 0; j < npoly; ++j) + // Find cell closest to a poly vertex + int startCellX = 0, startCellY = 0, startSpanIndex = -1; + int dmin = RC_UNSET_HEIGHT; + for (int j = 0; j < npoly && dmin > 0; ++j) { - int cx = 0, cz = 0, ci =-1; - int dmin = RC_UNSET_HEIGHT; - for (int k = 0; k < 9; ++k) + for (int k = 0; k < 9 && dmin > 0; ++k) { const int ax = (int)verts[poly[j]*3+0] + offset[k*2+0]; const int ay = (int)verts[poly[j]*3+1]; @@ -772,119 +906,211 @@ static void getHeightData(const rcCompactHeightfield& chf, az < hp.ymin || az >= hp.ymin+hp.height) continue; - const rcCompactCell& c = chf.cells[ax+az*chf.width]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + const rcCompactCell& c = chf.cells[(ax+bs)+(az+bs)*chf.width]; + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni && dmin > 0; ++i) { const rcCompactSpan& s = chf.spans[i]; int d = rcAbs(ay - (int)s.y); if (d < dmin) { - cx = ax; - cz = az; - ci = i; + startCellX = ax; + startCellY = az; + startSpanIndex = i; dmin = d; } } } - if (ci != -1) - { - stack.push(cx); - stack.push(cz); - stack.push(ci); - } } - // Find center of the polygon using flood fill. - int pcx = 0, pcz = 0; + rcAssert(startSpanIndex != -1); + // Find center of the polygon + int pcx = 0, pcy = 0; for (int j = 0; j < npoly; ++j) { pcx += (int)verts[poly[j]*3+0]; - pcz += (int)verts[poly[j]*3+2]; + pcy += (int)verts[poly[j]*3+2]; } pcx /= npoly; - pcz /= npoly; - - for (int i = 0; i < stack.size(); i += 3) - { - int cx = stack[i+0]; - int cy = stack[i+1]; - int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width; - hp.data[idx] = 1; - } + pcy /= npoly; - while (stack.size() > 0) + // Use seeds array as a stack for DFS + array.resize(0); + array.push(startCellX); + array.push(startCellY); + array.push(startSpanIndex); + + int dirs[] = { 0, 1, 2, 3 }; + memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height); + // DFS to move to the center. Note that we need a DFS here and can not just move + // directly towards the center without recording intermediate nodes, even though the polygons + // are convex. In very rare we can get stuck due to contour simplification if we do not + // record nodes. + int cx = -1, cy = -1, ci = -1; + while (true) { - int ci = stack.pop(); - int cy = stack.pop(); - int cx = stack.pop(); - - // Check if close to center of the polygon. - if (rcAbs(cx-pcx) <= 1 && rcAbs(cy-pcz) <= 1) + if (array.size() < 3) { - stack.resize(0); - stack.push(cx); - stack.push(cy); - stack.push(ci); + ctx->log(RC_LOG_WARNING, "Walk towards polygon center failed to reach center"); break; } - + + ci = array.pop(); + cy = array.pop(); + cx = array.pop(); + + if (cx == pcx && cy == pcy) + break; + + // If we are already at the correct X-position, prefer direction + // directly towards the center in the Y-axis; otherwise prefer + // direction in the X-axis + int directDir; + if (cx == pcx) + directDir = rcGetDirForOffset(0, pcy > cy ? 1 : -1); + else + directDir = rcGetDirForOffset(pcx > cx ? 1 : -1, 0); + + // Push the direct dir last so we start with this on next iteration + rcSwap(dirs[directDir], dirs[3]); + const rcCompactSpan& cs = chf.spans[ci]; - - for (int dir = 0; dir < 4; ++dir) + for (int i = 0; i < 4; i++) { - if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue; - - const int ax = cx + rcGetDirOffsetX(dir); - const int ay = cy + rcGetDirOffsetY(dir); - - if (ax < hp.xmin || ax >= (hp.xmin+hp.width) || - ay < hp.ymin || ay >= (hp.ymin+hp.height)) + int dir = dirs[i]; + if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue; - - if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != 0) + + int newX = cx + rcGetDirOffsetX(dir); + int newY = cy + rcGetDirOffsetY(dir); + + int hpx = newX - hp.xmin; + int hpy = newY - hp.ymin; + if (hpx < 0 || hpx >= hp.width || hpy < 0 || hpy >= hp.height) continue; - - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir); - int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width; - hp.data[idx] = 1; - - stack.push(ax); - stack.push(ay); - stack.push(ai); + if (hp.data[hpx+hpy*hp.width] != 0) + continue; + + hp.data[hpx+hpy*hp.width] = 1; + array.push(newX); + array.push(newY); + array.push((int)chf.cells[(newX+bs)+(newY+bs)*chf.width].index + rcGetCon(cs, dir)); } + + rcSwap(dirs[directDir], dirs[3]); } + array.resize(0); + // getHeightData seeds are given in coordinates with borders + array.push(cx+bs); + array.push(cy+bs); + array.push(ci); + memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height); + const rcCompactSpan& cs = chf.spans[ci]; + hp.data[cx-hp.xmin+(cy-hp.ymin)*hp.width] = cs.y; +} + - // Mark start locations. - for (int i = 0; i < stack.size(); i += 3) +static void push3(rcIntArray& queue, int v1, int v2, int v3) +{ + queue.resize(queue.size() + 3); + queue[queue.size() - 3] = v1; + queue[queue.size() - 2] = v2; + queue[queue.size() - 1] = v3; +} + +static void getHeightData(rcContext* ctx, const rcCompactHeightfield& chf, + const unsigned short* poly, const int npoly, + const unsigned short* verts, const int bs, + rcHeightPatch& hp, rcIntArray& queue, + int region) +{ + // Note: Reads to the compact heightfield are offset by border size (bs) + // since border size offset is already removed from the polymesh vertices. + + queue.resize(0); + // Set all heights to RC_UNSET_HEIGHT. + memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height); + + bool empty = true; + + // We cannot sample from this poly if it was created from polys + // of different regions. If it was then it could potentially be overlapping + // with polys of that region and the heights sampled here could be wrong. + if (region != RC_MULTIPLE_REGS) { - int cx = stack[i+0]; - int cy = stack[i+1]; - int ci = stack[i+2]; - int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width; - const rcCompactSpan& cs = chf.spans[ci]; - hp.data[idx] = cs.y; + // Copy the height from the same region, and mark region borders + // as seed points to fill the rest. + for (int hy = 0; hy < hp.height; hy++) + { + int y = hp.ymin + hy + bs; + for (int hx = 0; hx < hp.width; hx++) + { + int x = hp.xmin + hx + bs; + const rcCompactCell& c = chf.cells[x + y*chf.width]; + for (int i = (int)c.index, ni = (int)(c.index + c.count); i < ni; ++i) + { + const rcCompactSpan& s = chf.spans[i]; + if (s.reg == region) + { + // Store height + hp.data[hx + hy*hp.width] = s.y; + empty = false; + + // If any of the neighbours is not in same region, + // add the current location as flood fill start + bool border = false; + for (int dir = 0; dir < 4; ++dir) + { + if (rcGetCon(s, dir) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(dir); + const int ay = y + rcGetDirOffsetY(dir); + const int ai = (int)chf.cells[ax + ay*chf.width].index + rcGetCon(s, dir); + const rcCompactSpan& as = chf.spans[ai]; + if (as.reg != region) + { + border = true; + break; + } + } + } + if (border) + push3(queue, x, y, i); + break; + } + } + } + } } + // if the polygon does not contain any points from the current region (rare, but happens) + // or if it could potentially be overlapping polygons of the same region, + // then use the center as the seed point. + if (empty) + seedArrayWithPolyCenter(ctx, chf, poly, npoly, verts, bs, hp, queue); + static const int RETRACT_SIZE = 256; int head = 0; - while (head*3 < stack.size()) + // We assume the seed is centered in the polygon, so a BFS to collect + // height data will ensure we do not move onto overlapping polygons and + // sample wrong heights. + while (head*3 < queue.size()) { - int cx = stack[head*3+0]; - int cy = stack[head*3+1]; - int ci = stack[head*3+2]; + int cx = queue[head*3+0]; + int cy = queue[head*3+1]; + int ci = queue[head*3+2]; head++; if (head >= RETRACT_SIZE) { head = 0; - if (stack.size() > RETRACT_SIZE*3) - memmove(&stack[0], &stack[RETRACT_SIZE*3], sizeof(int)*(stack.size()-RETRACT_SIZE*3)); - stack.resize(stack.size()-RETRACT_SIZE*3); + if (queue.size() > RETRACT_SIZE*3) + memmove(&queue[0], &queue[RETRACT_SIZE*3], sizeof(int)*(queue.size()-RETRACT_SIZE*3)); + queue.resize(queue.size()-RETRACT_SIZE*3); } - + const rcCompactSpan& cs = chf.spans[ci]; for (int dir = 0; dir < 4; ++dir) { @@ -892,26 +1118,23 @@ static void getHeightData(const rcCompactHeightfield& chf, const int ax = cx + rcGetDirOffsetX(dir); const int ay = cy + rcGetDirOffsetY(dir); + const int hx = ax - hp.xmin - bs; + const int hy = ay - hp.ymin - bs; - if (ax < hp.xmin || ax >= (hp.xmin+hp.width) || - ay < hp.ymin || ay >= (hp.ymin+hp.height)) + if ((unsigned int)hx >= (unsigned int)hp.width || (unsigned int)hy >= (unsigned int)hp.height) continue; - if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != RC_UNSET_HEIGHT) + if (hp.data[hx + hy*hp.width] != RC_UNSET_HEIGHT) continue; - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir); - + const int ai = (int)chf.cells[ax + ay*chf.width].index + rcGetCon(cs, dir); const rcCompactSpan& as = chf.spans[ai]; - int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width; - hp.data[idx] = as.y; - - stack.push(ax); - stack.push(ay); - stack.push(ai); + + hp.data[hx + hy*hp.width] = as.y; + + push3(queue, ax, ay, ai); } } - } static unsigned char getEdgeFlags(const float* va, const float* vb, @@ -921,7 +1144,7 @@ static unsigned char getEdgeFlags(const float* va, const float* vb, static const float thrSqr = rcSqr(0.001f); for (int i = 0, j = npoly-1; i < npoly; j=i++) { - if (distancePtSeg2d(va, &vpoly[j*3], &vpoly[i*3]) < thrSqr && + if (distancePtSeg2d(va, &vpoly[j*3], &vpoly[i*3]) < thrSqr && distancePtSeg2d(vb, &vpoly[j*3], &vpoly[i*3]) < thrSqr) return 1; } @@ -938,16 +1161,19 @@ static unsigned char getTriFlags(const float* va, const float* vb, const float* return flags; } - - +/// @par +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& dmesh) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL); - + rcScopedTimer timer(ctx, RC_TIMER_BUILD_POLYMESHDETAIL); + if (mesh.nverts == 0 || mesh.npolys == 0) return true; @@ -955,23 +1181,25 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa const float cs = mesh.cs; const float ch = mesh.ch; const float* orig = mesh.bmin; + const int borderSize = mesh.borderSize; + const int heightSearchRadius = rcMax(1, (int)ceilf(mesh.maxEdgeError)); rcIntArray edges(64); rcIntArray tris(512); - rcIntArray stack(512); + rcIntArray arr(512); rcIntArray samples(512); float verts[256*3]; rcHeightPatch hp; int nPolyVerts = 0; int maxhw = 0, maxhh = 0; - rcScopedDelete<int> bounds = (int*)rcAlloc(sizeof(int)*mesh.npolys*4, RC_ALLOC_TEMP); + rcScopedDelete<int> bounds((int*)rcAlloc(sizeof(int)*mesh.npolys*4, RC_ALLOC_TEMP)); if (!bounds) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4); return false; } - rcScopedDelete<float> poly = (float*)rcAlloc(sizeof(float)*nvp*3, RC_ALLOC_TEMP); + rcScopedDelete<float> poly((float*)rcAlloc(sizeof(float)*nvp*3, RC_ALLOC_TEMP)); if (!poly) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3); @@ -1025,10 +1253,10 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4); return false; } - + int vcap = nPolyVerts+nPolyVerts/2; int tcap = vcap*2; - + dmesh.nverts = 0; dmesh.verts = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); if (!dmesh.verts) @@ -1037,7 +1265,7 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa return false; } dmesh.ntris = 0; - dmesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char*)*tcap*4, RC_ALLOC_PERM); + dmesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM); if (!dmesh.tris) { ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4); @@ -1065,18 +1293,19 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa hp.ymin = bounds[i*4+2]; hp.width = bounds[i*4+1]-bounds[i*4+0]; hp.height = bounds[i*4+3]-bounds[i*4+2]; - getHeightData(chf, p, npoly, mesh.verts, hp, stack); + getHeightData(ctx, chf, p, npoly, mesh.verts, borderSize, hp, arr, mesh.regs[i]); // Build detail mesh. int nverts = 0; if (!buildPolyDetail(ctx, poly, npoly, sampleDist, sampleMaxError, - chf, hp, verts, nverts, tris, + heightSearchRadius, chf, hp, + verts, nverts, tris, edges, samples)) { return false; } - + // Move detail verts to world space. for (int j = 0; j < nverts; ++j) { @@ -1091,21 +1320,21 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa poly[j*3+1] += orig[1]; poly[j*3+2] += orig[2]; } - + // Store detail submesh. const int ntris = tris.size()/4; - + dmesh.meshes[i*4+0] = (unsigned int)dmesh.nverts; dmesh.meshes[i*4+1] = (unsigned int)nverts; dmesh.meshes[i*4+2] = (unsigned int)dmesh.ntris; - dmesh.meshes[i*4+3] = (unsigned int)ntris; + dmesh.meshes[i*4+3] = (unsigned int)ntris; // Store vertices, allocate more memory if necessary. if (dmesh.nverts+nverts > vcap) { while (dmesh.nverts+nverts > vcap) vcap += 256; - + float* newv = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); if (!newv) { @@ -1151,22 +1380,21 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa dmesh.ntris++; } } - - ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL); - + return true; } +/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MERGE_POLYMESHDETAIL); - + rcScopedTimer timer(ctx, RC_TIMER_MERGE_POLYMESHDETAIL); + int maxVerts = 0; int maxTris = 0; int maxMeshes = 0; - + for (int i = 0; i < nmeshes; ++i) { if (!meshes[i]) continue; @@ -1174,7 +1402,7 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int maxTris += meshes[i]->ntris; maxMeshes += meshes[i]->nmeshes; } - + mesh.nmeshes = 0; mesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*maxMeshes*4, RC_ALLOC_PERM); if (!mesh.meshes) @@ -1182,7 +1410,7 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'pmdtl.meshes' (%d).", maxMeshes*4); return false; } - + mesh.ntris = 0; mesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxTris*4, RC_ALLOC_PERM); if (!mesh.tris) @@ -1190,7 +1418,7 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", maxTris*4); return false; } - + mesh.nverts = 0; mesh.verts = (float*)rcAlloc(sizeof(float)*maxVerts*3, RC_ALLOC_PERM); if (!mesh.verts) @@ -1214,7 +1442,7 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int dst[3] = src[3]; mesh.nmeshes++; } - + for (int k = 0; k < dm->nverts; ++k) { rcVcopy(&mesh.verts[mesh.nverts*3], &dm->verts[k*3]); @@ -1229,9 +1457,6 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int mesh.ntris++; } } - - ctx->stopTimer(RC_TIMER_MERGE_POLYMESHDETAIL); return true; } - diff --git a/deps/recastnavigation/Recast/RecastRasterization.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastRasterization.cpp index 71adfb6732..a4cef74909 100644 --- a/deps/recastnavigation/Recast/RecastRasterization.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastRasterization.cpp @@ -50,7 +50,7 @@ static rcSpan* allocSpan(rcHeightfield& hf) // Allocate memory for the new pool. rcSpanPool* pool = (rcSpanPool*)rcAlloc(sizeof(rcSpanPool), RC_ALLOC_PERM); if (!pool) return 0; - pool->next = 0; + // Add the pool into the list of pools. pool->next = hf.pools; hf.pools = pool; @@ -82,7 +82,7 @@ static void freeSpan(rcHeightfield& hf, rcSpan* ptr) hf.freelist = ptr; } -static void addSpan(rcHeightfield& hf, const int x, const int y, +static bool addSpan(rcHeightfield& hf, const int x, const int y, const unsigned short smin, const unsigned short smax, const unsigned char area, const int flagMergeThr) { @@ -90,16 +90,18 @@ static void addSpan(rcHeightfield& hf, const int x, const int y, int idx = x + y*hf.width; rcSpan* s = allocSpan(hf); + if (!s) + return false; s->smin = smin; s->smax = smax; s->area = area; s->next = 0; - // Empty cell, add he first span. + // Empty cell, add the first span. if (!hf.spans[idx]) { hf.spans[idx] = s; - return; + return true; } rcSpan* prev = 0; rcSpan* cur = hf.spans[idx]; @@ -152,47 +154,91 @@ static void addSpan(rcHeightfield& hf, const int x, const int y, s->next = hf.spans[idx]; hf.spans[idx] = s; } + + return true; } -void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y, +/// @par +/// +/// The span addition can be set to favor flags. If the span is merged to +/// another span and the new @p smax is within @p flagMergeThr units +/// from the existing span, the span flags are merged. +/// +/// @see rcHeightfield, rcSpan. +bool rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y, const unsigned short smin, const unsigned short smax, const unsigned char area, const int flagMergeThr) { -// rcAssert(ctx); - addSpan(hf, x,y, smin, smax, area, flagMergeThr); + rcAssert(ctx); + + if (!addSpan(hf, x, y, smin, smax, area, flagMergeThr)) + { + ctx->log(RC_LOG_ERROR, "rcAddSpan: Out of memory."); + return false; + } + + return true; } -static int clipPoly(const float* in, int n, float* out, float pnx, float pnz, float pd) +// divides a convex polygons into two convex polygons on both sides of a line +static void dividePoly(const float* in, int nin, + float* out1, int* nout1, + float* out2, int* nout2, + float x, int axis) { float d[12]; - for (int i = 0; i < n; ++i) - d[i] = pnx*in[i*3+0] + pnz*in[i*3+2] + pd; - - int m = 0; - for (int i = 0, j = n-1; i < n; j=i, ++i) + for (int i = 0; i < nin; ++i) + d[i] = x - in[i*3+axis]; + + int m = 0, n = 0; + for (int i = 0, j = nin-1; i < nin; j=i, ++i) { bool ina = d[j] >= 0; bool inb = d[i] >= 0; if (ina != inb) { float s = d[j] / (d[j] - d[i]); - out[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s; - out[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s; - out[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s; + out1[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s; + out1[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s; + out1[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s; + rcVcopy(out2 + n*3, out1 + m*3); m++; + n++; + // add the i'th point to the right polygon. Do NOT add points that are on the dividing line + // since these were already added above + if (d[i] > 0) + { + rcVcopy(out1 + m*3, in + i*3); + m++; + } + else if (d[i] < 0) + { + rcVcopy(out2 + n*3, in + i*3); + n++; + } } - if (inb) + else // same side { - out[m*3+0] = in[i*3+0]; - out[m*3+1] = in[i*3+1]; - out[m*3+2] = in[i*3+2]; - m++; + // add the i'th point to the right polygon. Addition is done even for points on the dividing line + if (d[i] >= 0) + { + rcVcopy(out1 + m*3, in + i*3); + m++; + if (d[i] != 0) + continue; + } + rcVcopy(out2 + n*3, in + i*3); + n++; } } - return m; + + *nout1 = m; + *nout2 = n; } -static void rasterizeTri(const float* v0, const float* v1, const float* v2, + + +static bool rasterizeTri(const float* v0, const float* v1, const float* v2, const unsigned char area, rcHeightfield& hf, const float* bmin, const float* bmax, const float cs, const float ics, const float ich, @@ -213,50 +259,59 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2, // If the triangle does not touch the bbox of the heightfield, skip the triagle. if (!overlapBounds(bmin, bmax, tmin, tmax)) - return; + return true; - // Calculate the footpring of the triangle on the grid. - int x0 = (int)((tmin[0] - bmin[0])*ics); + // Calculate the footprint of the triangle on the grid's y-axis int y0 = (int)((tmin[2] - bmin[2])*ics); - int x1 = (int)((tmax[0] - bmin[0])*ics); int y1 = (int)((tmax[2] - bmin[2])*ics); - x0 = rcClamp(x0, 0, w-1); y0 = rcClamp(y0, 0, h-1); - x1 = rcClamp(x1, 0, w-1); y1 = rcClamp(y1, 0, h-1); // Clip the triangle into all grid cells it touches. - float in[7*3], out[7*3], inrow[7*3]; + float buf[7*3*4]; + float *in = buf, *inrow = buf+7*3, *p1 = inrow+7*3, *p2 = p1+7*3; + + rcVcopy(&in[0], v0); + rcVcopy(&in[1*3], v1); + rcVcopy(&in[2*3], v2); + int nvrow, nvIn = 3; for (int y = y0; y <= y1; ++y) { - // Clip polygon to row. - rcVcopy(&in[0], v0); - rcVcopy(&in[1*3], v1); - rcVcopy(&in[2*3], v2); - int nvrow = 3; + // Clip polygon to row. Store the remaining polygon as well const float cz = bmin[2] + y*cs; - nvrow = clipPoly(in, nvrow, out, 0, 1, -cz); - if (nvrow < 3) continue; - nvrow = clipPoly(out, nvrow, inrow, 0, -1, cz+cs); + dividePoly(in, nvIn, inrow, &nvrow, p1, &nvIn, cz+cs, 2); + rcSwap(in, p1); if (nvrow < 3) continue; + // find the horizontal bounds in the row + float minX = inrow[0], maxX = inrow[0]; + for (int i=1; i<nvrow; ++i) + { + if (minX > inrow[i*3]) minX = inrow[i*3]; + if (maxX < inrow[i*3]) maxX = inrow[i*3]; + } + int x0 = (int)((minX - bmin[0])*ics); + int x1 = (int)((maxX - bmin[0])*ics); + x0 = rcClamp(x0, 0, w-1); + x1 = rcClamp(x1, 0, w-1); + + int nv, nv2 = nvrow; + for (int x = x0; x <= x1; ++x) { - // Clip polygon to column. - int nv = nvrow; + // Clip polygon to column. store the remaining polygon as well const float cx = bmin[0] + x*cs; - nv = clipPoly(inrow, nv, out, 1, 0, -cx); - if (nv < 3) continue; - nv = clipPoly(out, nv, in, -1, 0, cx+cs); + dividePoly(inrow, nv2, p1, &nv, p2, &nv2, cx+cs, 0); + rcSwap(inrow, p2); if (nv < 3) continue; // Calculate min and max of the span. - float smin = in[1], smax = in[1]; + float smin = p1[1], smax = p1[1]; for (int i = 1; i < nv; ++i) { - smin = rcMin(smin, in[i*3+1]); - smax = rcMax(smax, in[i*3+1]); + smin = rcMin(smin, p1[i*3+1]); + smax = rcMax(smax, p1[i*3+1]); } smin -= bmin[1]; smax -= bmin[1]; @@ -271,33 +326,50 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2, unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, RC_SPAN_MAX_HEIGHT); unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), (int)ismin+1, RC_SPAN_MAX_HEIGHT); - addSpan(hf, x, y, ismin, ismax, area, flagMergeThr); + if (!addSpan(hf, x, y, ismin, ismax, area, flagMergeThr)) + return false; } } + + return true; } -void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, +/// @par +/// +/// No spans will be added if the triangle does not overlap the heightfield grid. +/// +/// @see rcHeightfield +bool rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, const unsigned char area, rcHeightfield& solid, const int flagMergeThr) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; - rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); + if (!rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr)) + { + ctx->log(RC_LOG_ERROR, "rcRasterizeTriangle: Out of memory."); + return false; + } - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); + return true; } -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, +/// @par +/// +/// Spans will only be added for triangles that overlap the heightfield grid. +/// +/// @see rcHeightfield +bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, const int* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -308,19 +380,28 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, const float* v1 = &verts[tris[i*3+1]*3]; const float* v2 = &verts[tris[i*3+2]*3]; // Rasterize. - rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); + if (!rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr)) + { + ctx->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory."); + return false; + } } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); + + return true; } -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, +/// @par +/// +/// Spans will only be added for triangles that overlap the heightfield grid. +/// +/// @see rcHeightfield +bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, const unsigned short* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -331,18 +412,27 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, const float* v1 = &verts[tris[i*3+1]*3]; const float* v2 = &verts[tris[i*3+2]*3]; // Rasterize. - rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); + if (!rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr)) + { + ctx->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory."); + return false; + } } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); + + return true; } -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, +/// @par +/// +/// Spans will only be added for triangles that overlap the heightfield grid. +/// +/// @see rcHeightfield +bool rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -353,8 +443,12 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned cha const float* v1 = &verts[(i*3+1)*3]; const float* v2 = &verts[(i*3+2)*3]; // Rasterize. - rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); + if (!rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr)) + { + ctx->log(RC_LOG_ERROR, "rcRasterizeTriangles: Out of memory."); + return false; + } } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); + + return true; } diff --git a/deps/recastnavigation/Recast/RecastRegion.cpp b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastRegion.cpp index c624bf6619..4a87133f2a 100644 --- a/deps/recastnavigation/Recast/RecastRegion.cpp +++ b/modules/worldengine/deps/recastnavigation/Recast/Source/RecastRegion.cpp @@ -286,7 +286,10 @@ static bool floodRegion(int x, int y, int i, if (nr & RC_BORDER_REG) // Do not take borders into account. continue; if (nr != 0 && nr != r) + { ar = nr; + break; + } const rcCompactSpan& as = chf.spans[ai]; @@ -298,9 +301,12 @@ static bool floodRegion(int x, int y, int i, const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2); if (chf.areas[ai2] != area) continue; - unsigned short nr = srcReg[ai2]; - if (nr != 0 && nr != r) - ar = nr; + unsigned short nr2 = srcReg[ai2]; + if (nr2 != 0 && nr2 != r) + { + ar = nr2; + break; + } } } } @@ -309,6 +315,7 @@ static bool floodRegion(int x, int y, int i, srcReg[ci] = 0; continue; } + count++; // Expand neighbours. @@ -321,16 +328,13 @@ static bool floodRegion(int x, int y, int i, const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir); if (chf.areas[ai] != area) continue; - if (chf.dist[ai] >= lev) + if (chf.dist[ai] >= lev && srcReg[ai] == 0) { - if (srcReg[ai] == 0) - { - srcReg[ai] = r; - srcDist[ai] = 0; - stack.push(ax); - stack.push(ay); - stack.push(ai); - } + srcReg[ai] = r; + srcDist[ai] = 0; + stack.push(ax); + stack.push(ay); + stack.push(ai); } } } @@ -343,30 +347,44 @@ static unsigned short* expandRegions(int maxIter, unsigned short level, rcCompactHeightfield& chf, unsigned short* srcReg, unsigned short* srcDist, unsigned short* dstReg, unsigned short* dstDist, - rcIntArray& stack) + rcIntArray& stack, + bool fillStack) { const int w = chf.width; const int h = chf.height; - // Find cells revealed by the raised level. - stack.resize(0); - for (int y = 0; y < h; ++y) + if (fillStack) { - for (int x = 0; x < w; ++x) + // Find cells revealed by the raised level. + stack.resize(0); + for (int y = 0; y < h; ++y) { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + for (int x = 0; x < w; ++x) { - if (chf.dist[i] >= level && srcReg[i] == 0 && chf.areas[i] != RC_NULL_AREA) + const rcCompactCell& c = chf.cells[x+y*w]; + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) { - stack.push(x); - stack.push(y); - stack.push(i); + if (chf.dist[i] >= level && srcReg[i] == 0 && chf.areas[i] != RC_NULL_AREA) + { + stack.push(x); + stack.push(y); + stack.push(i); + } } } } } - + else // use cells in the input stack + { + // mark all cells which already have a region + for (int j=0; j<stack.size(); j+=3) + { + int i = stack[j+2]; + if (srcReg[i] != 0) + stack[j+2] = -1; + } + } + int iter = 0; while (stack.size() > 0) { @@ -437,6 +455,61 @@ static unsigned short* expandRegions(int maxIter, unsigned short level, } + +static void sortCellsByLevel(unsigned short startLevel, + rcCompactHeightfield& chf, + unsigned short* srcReg, + unsigned int nbStacks, rcIntArray* stacks, + unsigned short loglevelsPerStack) // the levels per stack (2 in our case) as a bit shift +{ + const int w = chf.width; + const int h = chf.height; + startLevel = startLevel >> loglevelsPerStack; + + for (unsigned int j=0; j<nbStacks; ++j) + stacks[j].resize(0); + + // put all cells in the level range into the appropriate stacks + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + if (chf.areas[i] == RC_NULL_AREA || srcReg[i] != 0) + continue; + + int level = chf.dist[i] >> loglevelsPerStack; + int sId = startLevel - level; + if (sId >= (int)nbStacks) + continue; + if (sId < 0) + sId = 0; + + stacks[sId].push(x); + stacks[sId].push(y); + stacks[sId].push(i); + } + } + } +} + + +static void appendStacks(rcIntArray& srcStack, rcIntArray& dstStack, + unsigned short* srcReg) +{ + for (int j=0; j<srcStack.size(); j+=3) + { + int i = srcStack[j+2]; + if ((i < 0) || (srcReg[i] != 0)) + continue; + dstStack.push(srcStack[j]); + dstStack.push(srcStack[j+1]); + dstStack.push(srcStack[j+2]); + } +} + struct rcRegion { inline rcRegion(unsigned short i) : @@ -444,7 +517,11 @@ struct rcRegion id(i), areaType(0), remap(false), - visited(false) + visited(false), + overlap(false), + connectsToBorder(false), + ymin(0xffff), + ymax(0) {} int spanCount; // Number of spans belonging to this region @@ -452,6 +529,9 @@ struct rcRegion unsigned char areaType; // Are type. bool remap; bool visited; + bool overlap; + bool connectsToBorder; + unsigned short ymin, ymax; rcIntArray connections; rcIntArray floors; }; @@ -681,25 +761,26 @@ static void walkContour(int x, int y, int i, int dir, // Remove adjacent duplicates. if (cont.size() > 1) { - for (int i = 0; i < cont.size(); ) + for (int j = 0; j < cont.size(); ) { - int ni = (i+1) % cont.size(); - if (cont[i] == cont[ni]) + int nj = (j+1) % cont.size(); + if (cont[j] == cont[nj]) { - for (int j = i; j < cont.size()-1; ++j) - cont[j] = cont[j+1]; + for (int k = j; k < cont.size()-1; ++k) + cont[k] = cont[k+1]; cont.pop(); } else - ++i; + ++j; } } } -static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegionSize, - unsigned short& maxRegionId, - rcCompactHeightfield& chf, - unsigned short* srcReg) + +static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRegionSize, + unsigned short& maxRegionId, + rcCompactHeightfield& chf, + unsigned short* srcReg, rcIntArray& overlaps) { const int w = chf.width; const int h = chf.height; @@ -708,7 +789,7 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP); if (!regions) { - ctx->log(RC_LOG_ERROR, "filterSmallRegions: Out of memory 'regions' (%d).", nreg); + ctx->log(RC_LOG_ERROR, "mergeAndFilterRegions: Out of memory 'regions' (%d).", nreg); return false; } @@ -731,7 +812,6 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio rcRegion& reg = regions[r]; reg.spanCount++; - // Update floors. for (int j = (int)c.index; j < ni; ++j) { @@ -739,6 +819,8 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio unsigned short floorId = srcReg[j]; if (floorId == 0 || floorId >= nreg) continue; + if (floorId == r) + reg.overlap = true; addUniqueFloorRegion(reg, floorId); } @@ -809,14 +891,14 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio connectsToBorder = true; continue; } - rcRegion& nreg = regions[creg.connections[j]]; - if (nreg.visited) + rcRegion& neireg = regions[creg.connections[j]]; + if (neireg.visited) continue; - if (nreg.id == 0 || (nreg.id & RC_BORDER_REG)) + if (neireg.id == 0 || (neireg.id & RC_BORDER_REG)) continue; // Visit - stack.push(nreg.id); - nreg.visited = true; + stack.push(neireg.id); + neireg.visited = true; } } @@ -834,7 +916,7 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio } } } - + // Merge too small regions to neighbour regions. int mergeCount = 0 ; do @@ -844,7 +926,9 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio { rcRegion& reg = regions[i]; if (reg.id == 0 || (reg.id & RC_BORDER_REG)) - continue; + continue; + if (reg.overlap) + continue; if (reg.spanCount == 0) continue; @@ -861,7 +945,7 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio { if (reg.connections[j] & RC_BORDER_REG) continue; rcRegion& mreg = regions[reg.connections[j]]; - if (mreg.id == 0 || (mreg.id & RC_BORDER_REG)) continue; + if (mreg.id == 0 || (mreg.id & RC_BORDER_REG) || mreg.overlap) continue; if (mreg.spanCount < smallest && canMergeWithRegion(reg, mreg) && canMergeWithRegion(mreg, reg)) @@ -931,6 +1015,224 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio if ((srcReg[i] & RC_BORDER_REG) == 0) srcReg[i] = regions[srcReg[i]].id; } + + // Return regions that we found to be overlapping. + for (int i = 0; i < nreg; ++i) + if (regions[i].overlap) + overlaps.push(regions[i].id); + + for (int i = 0; i < nreg; ++i) + regions[i].~rcRegion(); + rcFree(regions); + + + return true; +} + + +static void addUniqueConnection(rcRegion& reg, int n) +{ + for (int i = 0; i < reg.connections.size(); ++i) + if (reg.connections[i] == n) + return; + reg.connections.push(n); +} + +static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea, + unsigned short& maxRegionId, + rcCompactHeightfield& chf, + unsigned short* srcReg, rcIntArray& /*overlaps*/) +{ + const int w = chf.width; + const int h = chf.height; + + const int nreg = maxRegionId+1; + rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP); + if (!regions) + { + ctx->log(RC_LOG_ERROR, "mergeAndFilterLayerRegions: Out of memory 'regions' (%d).", nreg); + return false; + } + + // Construct regions + for (int i = 0; i < nreg; ++i) + new(®ions[i]) rcRegion((unsigned short)i); + + // Find region neighbours and overlapping regions. + rcIntArray lregs(32); + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + + lregs.resize(0); + + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + const rcCompactSpan& s = chf.spans[i]; + const unsigned short ri = srcReg[i]; + if (ri == 0 || ri >= nreg) continue; + rcRegion& reg = regions[ri]; + + reg.spanCount++; + + reg.ymin = rcMin(reg.ymin, s.y); + reg.ymax = rcMax(reg.ymax, s.y); + + // Collect all region layers. + lregs.push(ri); + + // Update neighbours + for (int dir = 0; dir < 4; ++dir) + { + if (rcGetCon(s, dir) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(dir); + const int ay = y + rcGetDirOffsetY(dir); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); + const unsigned short rai = srcReg[ai]; + if (rai > 0 && rai < nreg && rai != ri) + addUniqueConnection(reg, rai); + if (rai & RC_BORDER_REG) + reg.connectsToBorder = true; + } + } + + } + + // Update overlapping regions. + for (int i = 0; i < lregs.size()-1; ++i) + { + for (int j = i+1; j < lregs.size(); ++j) + { + if (lregs[i] != lregs[j]) + { + rcRegion& ri = regions[lregs[i]]; + rcRegion& rj = regions[lregs[j]]; + addUniqueFloorRegion(ri, lregs[j]); + addUniqueFloorRegion(rj, lregs[i]); + } + } + } + + } + } + + // Create 2D layers from regions. + unsigned short layerId = 1; + + for (int i = 0; i < nreg; ++i) + regions[i].id = 0; + + // Merge montone regions to create non-overlapping areas. + rcIntArray stack(32); + for (int i = 1; i < nreg; ++i) + { + rcRegion& root = regions[i]; + // Skip already visited. + if (root.id != 0) + continue; + + // Start search. + root.id = layerId; + + stack.resize(0); + stack.push(i); + + while (stack.size() > 0) + { + // Pop front + rcRegion& reg = regions[stack[0]]; + for (int j = 0; j < stack.size()-1; ++j) + stack[j] = stack[j+1]; + stack.resize(stack.size()-1); + + const int ncons = (int)reg.connections.size(); + for (int j = 0; j < ncons; ++j) + { + const int nei = reg.connections[j]; + rcRegion& regn = regions[nei]; + // Skip already visited. + if (regn.id != 0) + continue; + // Skip if the neighbour is overlapping root region. + bool overlap = false; + for (int k = 0; k < root.floors.size(); k++) + { + if (root.floors[k] == nei) + { + overlap = true; + break; + } + } + if (overlap) + continue; + + // Deepen + stack.push(nei); + + // Mark layer id + regn.id = layerId; + // Merge current layers to root. + for (int k = 0; k < regn.floors.size(); ++k) + addUniqueFloorRegion(root, regn.floors[k]); + root.ymin = rcMin(root.ymin, regn.ymin); + root.ymax = rcMax(root.ymax, regn.ymax); + root.spanCount += regn.spanCount; + regn.spanCount = 0; + root.connectsToBorder = root.connectsToBorder || regn.connectsToBorder; + } + } + + layerId++; + } + + // Remove small regions + for (int i = 0; i < nreg; ++i) + { + if (regions[i].spanCount > 0 && regions[i].spanCount < minRegionArea && !regions[i].connectsToBorder) + { + unsigned short reg = regions[i].id; + for (int j = 0; j < nreg; ++j) + if (regions[j].id == reg) + regions[j].id = 0; + } + } + + // Compress region Ids. + for (int i = 0; i < nreg; ++i) + { + regions[i].remap = false; + if (regions[i].id == 0) continue; // Skip nil regions. + if (regions[i].id & RC_BORDER_REG) continue; // Skip external regions. + regions[i].remap = true; + } + + unsigned short regIdGen = 0; + for (int i = 0; i < nreg; ++i) + { + if (!regions[i].remap) + continue; + unsigned short oldId = regions[i].id; + unsigned short newId = ++regIdGen; + for (int j = i; j < nreg; ++j) + { + if (regions[j].id == oldId) + { + regions[j].id = newId; + regions[j].remap = false; + } + } + } + maxRegionId = regIdGen; + + // Remap regions. + for (int i = 0; i < chf.spanCount; ++i) + { + if ((srcReg[i] & RC_BORDER_REG) == 0) + srcReg[i] = regions[srcReg[i]].id; + } for (int i = 0; i < nreg; ++i) regions[i].~rcRegion(); @@ -940,11 +1242,22 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio } + +/// @par +/// +/// This is usually the second to the last step in creating a fully built +/// compact heightfield. This step is required before regions are built +/// using #rcBuildRegions or #rcBuildRegionsMonotone. +/// +/// After this step, the distance data is available via the rcCompactHeightfield::maxDistance +/// and rcCompactHeightfield::dist fields. +/// +/// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_DISTANCEFIELD); if (chf.dist) { @@ -968,25 +1281,23 @@ bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) unsigned short maxDist = 0; - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); - - calculateDistanceField(chf, src, maxDist); - chf.maxDistance = maxDist; - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); - - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); - - // Blur - if (boxBlur(chf, 1, src, dst) != src) - rcSwap(src, dst); - - // Store distance. - chf.dist = src; - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); + { + rcScopedTimer timerDist(ctx, RC_TIMER_BUILD_DISTANCEFIELD_DIST); + + calculateDistanceField(chf, src, maxDist); + chf.maxDistance = maxDist; + } - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD); + { + rcScopedTimer timerBlur(ctx, RC_TIMER_BUILD_DISTANCEFIELD_BLUR); + + // Blur + if (boxBlur(chf, 1, src, dst) != src) + rcSwap(src, dst); + + // Store distance. + chf.dist = src; + } rcFree(dst); @@ -1022,18 +1333,37 @@ struct rcSweepSpan unsigned short nei; // neighbour id }; +/// @par +/// +/// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour. +/// Contours will form simple polygons. +/// +/// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be +/// re-assigned to the zero (null) region. +/// +/// Partitioning can result in smaller than necessary regions. @p mergeRegionArea helps +/// reduce unecessarily small regions. +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// The region data will be available via the rcCompactHeightfield::maxRegions +/// and rcCompactSpan::reg fields. +/// +/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions. +/// +/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_REGIONS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_REGIONS); const int w = chf.width; const int h = chf.height; unsigned short id = 1; - rcScopedDelete<unsigned short> srcReg = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); + rcScopedDelete<unsigned short> srcReg((unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP)); if (!srcReg) { ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'src' (%d).", chf.spanCount); @@ -1042,7 +1372,7 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, memset(srcReg,0,sizeof(unsigned short)*chf.spanCount); const int nsweeps = rcMax(chf.width,chf.height); - rcScopedDelete<rcSweepSpan> sweeps = (rcSweepSpan*)rcAlloc(sizeof(rcSweepSpan)*nsweeps, RC_ALLOC_TEMP); + rcScopedDelete<rcSweepSpan> sweeps((rcSweepSpan*)rcAlloc(sizeof(rcSweepSpan)*nsweeps, RC_ALLOC_TEMP)); if (!sweeps) { ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'sweeps' (%d).", nsweeps); @@ -1061,6 +1391,8 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++; paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++; paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++; + + chf.borderSize = borderSize; } rcIntArray prev(256); @@ -1154,35 +1486,56 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, } } - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); - // Filter out small regions. - chf.maxRegions = id; - if (!filterSmallRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg)) - return false; + { + rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER); - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); + // Merge regions and filter out small regions. + rcIntArray overlaps; + chf.maxRegions = id; + if (!mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg, overlaps)) + return false; + + // Monotone partitioning does not generate overlapping regions. + } // Store the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); return true; } +/// @par +/// +/// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour. +/// Contours will form simple polygons. +/// +/// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be +/// re-assigned to the zero (null) region. +/// +/// Watershed partitioning can result in smaller than necessary regions, especially in diagonal corridors. +/// @p mergeRegionArea helps reduce unecessarily small regions. +/// +/// See the #rcConfig documentation for more information on the configuration parameters. +/// +/// The region data will be available via the rcCompactHeightfield::maxRegions +/// and rcCompactSpan::reg fields. +/// +/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions. +/// +/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_REGIONS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_REGIONS); const int w = chf.width; const int h = chf.height; - rcScopedDelete<unsigned short> buf = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount*4, RC_ALLOC_TEMP); + rcScopedDelete<unsigned short> buf((unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount*4, RC_ALLOC_TEMP)); if (!buf) { ctx->log(RC_LOG_ERROR, "rcBuildRegions: Out of memory 'tmp' (%d).", chf.spanCount*4); @@ -1190,7 +1543,13 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, } ctx->startTimer(RC_TIMER_BUILD_REGIONS_WATERSHED); - + + const int LOG_NB_STACKS = 3; + const int NB_STACKS = 1 << LOG_NB_STACKS; + rcIntArray lvlStacks[NB_STACKS]; + for (int i=0; i<NB_STACKS; ++i) + lvlStacks[i].resize(1024); + rcIntArray stack(1024); rcIntArray visited(1024); @@ -1211,52 +1570,75 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, // const int expandIters = 4 + walkableRadius * 2; const int expandIters = 8; - // Mark border regions. - paintRectRegion(0, borderSize, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - paintRectRegion(w-borderSize, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - paintRectRegion(0, w, 0, borderSize, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - paintRectRegion(0, w, h-borderSize, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; + if (borderSize > 0) + { + // Make sure border will not overflow. + const int bw = rcMin(w, borderSize); + const int bh = rcMin(h, borderSize); + + // Paint regions + paintRectRegion(0, bw, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; + paintRectRegion(w-bw, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; + paintRectRegion(0, w, 0, bh, regionId|RC_BORDER_REG, chf, srcReg); regionId++; + paintRectRegion(0, w, h-bh, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; + + chf.borderSize = borderSize; + } + int sId = -1; while (level > 0) { level = level >= 2 ? level-2 : 0; - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_EXPAND); - - // Expand current regions until no empty connected cells found. - if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg) + sId = (sId+1) & (NB_STACKS-1); + +// ctx->startTimer(RC_TIMER_DIVIDE_TO_LEVELS); + + if (sId == 0) + sortCellsByLevel(level, chf, srcReg, NB_STACKS, lvlStacks, 1); + else + appendStacks(lvlStacks[sId-1], lvlStacks[sId], srcReg); // copy left overs from last level + +// ctx->stopTimer(RC_TIMER_DIVIDE_TO_LEVELS); + { - rcSwap(srcReg, dstReg); - rcSwap(srcDist, dstDist); + rcScopedTimer timerExpand(ctx, RC_TIMER_BUILD_REGIONS_EXPAND); + + // Expand current regions until no empty connected cells found. + if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, lvlStacks[sId], false) != srcReg) + { + rcSwap(srcReg, dstReg); + rcSwap(srcDist, dstDist); + } } - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_EXPAND); - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FLOOD); - - // Mark new regions with IDs. - for (int y = 0; y < h; ++y) { - for (int x = 0; x < w; ++x) + rcScopedTimer timerFloor(ctx, RC_TIMER_BUILD_REGIONS_FLOOD); + + // Mark new regions with IDs. + for (int j = 0; j<lvlStacks[sId].size(); j += 3) { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + int x = lvlStacks[sId][j]; + int y = lvlStacks[sId][j+1]; + int i = lvlStacks[sId][j+2]; + if (i >= 0 && srcReg[i] == 0) { - if (chf.dist[i] < level || srcReg[i] != 0 || chf.areas[i] == RC_NULL_AREA) - continue; - if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack)) + { + if (regionId == 0xFFFF) + { + ctx->log(RC_LOG_ERROR, "rcBuildRegions: Region ID overflow"); + return false; + } + regionId++; + } } } } - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FLOOD); - } // Expand current regions until no empty connected cells found. - if (expandRegions(expandIters*8, 0, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg) + if (expandRegions(expandIters*8, 0, chf, srcReg, srcDist, dstReg, dstDist, stack, true) != srcReg) { rcSwap(srcReg, dstReg); rcSwap(srcDist, dstDist); @@ -1264,22 +1646,179 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, ctx->stopTimer(RC_TIMER_BUILD_REGIONS_WATERSHED); - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Filter out small regions. - chf.maxRegions = regionId; - if (!filterSmallRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg)) - return false; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); + { + rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER); + + // Merge regions and filter out smalle regions. + rcIntArray overlaps; + chf.maxRegions = regionId; + if (!mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg, overlaps)) + return false; + + // If overlapping regions were found during merging, split those regions. + if (overlaps.size() > 0) + { + ctx->log(RC_LOG_ERROR, "rcBuildRegions: %d overlapping regions.", overlaps.size()); + } + } // Write the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); - return true; } +bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf, + const int borderSize, const int minRegionArea) +{ + rcAssert(ctx); + + rcScopedTimer timer(ctx, RC_TIMER_BUILD_REGIONS); + + const int w = chf.width; + const int h = chf.height; + unsigned short id = 1; + + rcScopedDelete<unsigned short> srcReg((unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP)); + if (!srcReg) + { + ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'src' (%d).", chf.spanCount); + return false; + } + memset(srcReg,0,sizeof(unsigned short)*chf.spanCount); + + const int nsweeps = rcMax(chf.width,chf.height); + rcScopedDelete<rcSweepSpan> sweeps((rcSweepSpan*)rcAlloc(sizeof(rcSweepSpan)*nsweeps, RC_ALLOC_TEMP)); + if (!sweeps) + { + ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'sweeps' (%d).", nsweeps); + return false; + } + + + // Mark border regions. + if (borderSize > 0) + { + // Make sure border will not overflow. + const int bw = rcMin(w, borderSize); + const int bh = rcMin(h, borderSize); + // Paint regions + paintRectRegion(0, bw, 0, h, id|RC_BORDER_REG, chf, srcReg); id++; + paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++; + paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++; + paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++; + + chf.borderSize = borderSize; + } + + rcIntArray prev(256); + + // Sweep one line at a time. + for (int y = borderSize; y < h-borderSize; ++y) + { + // Collect spans from this row. + prev.resize(id+1); + memset(&prev[0],0,sizeof(int)*id); + unsigned short rid = 1; + + for (int x = borderSize; x < w-borderSize; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + const rcCompactSpan& s = chf.spans[i]; + if (chf.areas[i] == RC_NULL_AREA) continue; + + // -x + unsigned short previd = 0; + if (rcGetCon(s, 0) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(0); + const int ay = y + rcGetDirOffsetY(0); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0); + if ((srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai]) + previd = srcReg[ai]; + } + + if (!previd) + { + previd = rid++; + sweeps[previd].rid = previd; + sweeps[previd].ns = 0; + sweeps[previd].nei = 0; + } + + // -y + if (rcGetCon(s,3) != RC_NOT_CONNECTED) + { + const int ax = x + rcGetDirOffsetX(3); + const int ay = y + rcGetDirOffsetY(3); + const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3); + if (srcReg[ai] && (srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai]) + { + unsigned short nr = srcReg[ai]; + if (!sweeps[previd].nei || sweeps[previd].nei == nr) + { + sweeps[previd].nei = nr; + sweeps[previd].ns++; + prev[nr]++; + } + else + { + sweeps[previd].nei = RC_NULL_NEI; + } + } + } + + srcReg[i] = previd; + } + } + + // Create unique ID. + for (int i = 1; i < rid; ++i) + { + if (sweeps[i].nei != RC_NULL_NEI && sweeps[i].nei != 0 && + prev[sweeps[i].nei] == (int)sweeps[i].ns) + { + sweeps[i].id = sweeps[i].nei; + } + else + { + sweeps[i].id = id++; + } + } + + // Remap IDs + for (int x = borderSize; x < w-borderSize; ++x) + { + const rcCompactCell& c = chf.cells[x+y*w]; + + for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) + { + if (srcReg[i] > 0 && srcReg[i] < rid) + srcReg[i] = sweeps[srcReg[i]].id; + } + } + } + + + { + rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER); + + // Merge monotone regions to layers and remove small regions. + rcIntArray overlaps; + chf.maxRegions = id; + if (!mergeAndFilterLayerRegions(ctx, minRegionArea, chf.maxRegions, chf, srcReg, overlaps)) + return false; + } + + + // Store the result out. + for (int i = 0; i < chf.spanCount; ++i) + chf.spans[i].reg = srcReg[i]; + + return true; +} diff --git a/modules/worldengine/nucleus/src/Utilities/StringFormat.h b/modules/worldengine/nucleus/src/Utilities/StringFormat.h new file mode 100644 index 0000000000..9e7bd1b61c --- /dev/null +++ b/modules/worldengine/nucleus/src/Utilities/StringFormat.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * 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 __STRING_FORMAT_H__ +#define __STRING_FORMAT_H__ + +#include <memory> +#include <iostream> +#include <string> +#include <cstdio> + +namespace Trinity +{ + /// Default TC string format function. + template<typename... Args> + inline std::string StringFormat(const std::string& format, Args const&... args) + { + size_t size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0' + unique_ptr<char[]> buf(new char[size]); + std::snprintf(buf.get(), size, format.c_str(), args ...); + return std::string(buf.get(), buf.get() + size - 1); // We don + } + + /// Returns true if the given char pointer is null. + inline bool IsFormatEmptyOrNull(const char* fmt) + { + return fmt == nullptr; + } + + /// Returns true if the given std::string is empty. + inline bool IsFormatEmptyOrNull(std::string const& fmt) + { + return fmt.empty(); + } +} + +#endif diff --git a/src/cmake/compiler/msvc/settings.cmake b/src/cmake/compiler/msvc/settings.cmake index caca79ee37..7ce1f7f200 100644 --- a/src/cmake/compiler/msvc/settings.cmake +++ b/src/cmake/compiler/msvc/settings.cmake @@ -59,7 +59,7 @@ endif() # Fixes a compiler-problem when using PCH - the /Ym flag is adjusted by the compiler in MSVC2012, hence we need to set an upper limit with /Zm to avoid discrepancies) # (And yes, this is a verified , unresolved bug with MSVC... *sigh*) string(REGEX REPLACE "/Zm[0-9]+ *" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm500" CACHE STRING "" FORCE) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm500") # Enable and treat as errors the following warnings to easily detect virtual function signature failures: # 'function' : member function does not override any base class virtual member function diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h index f12cd11841..842fe47fbf 100644 --- a/src/common/Collision/Management/MMapManager.h +++ b/src/common/Collision/Management/MMapManager.h @@ -14,7 +14,7 @@ #include "World.h" // memory management -inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/) +inline void* dtCustomAlloc(size_t size, dtAllocHint /*hint*/) { return (void*)new unsigned char[size]; } diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 8dc9d770de..6897ffa56a 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -1,7 +1,19 @@ /* - * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2 - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * Copyright (C) + * Copyright (C) + * + * 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/>. */ #include <iostream> @@ -26,6 +38,7 @@ namespace VMAP { VMapManager2::VMapManager2() { + GetLiquidFlagsPtr = &GetLiquidFlagsDummy; } VMapManager2::~VMapManager2(void) @@ -76,7 +89,7 @@ namespace VMAP } // load one tile (internal use only) - bool VMapManager2::_loadMap(unsigned int mapId, const std::string& basePath, uint32 tileX, uint32 tileY) + bool VMapManager2::_loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) { InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree == iInstanceMapTrees.end()) @@ -84,10 +97,10 @@ namespace VMAP std::string mapFileName = getMapFileName(mapId); StaticMapTree* newTree = new StaticMapTree(mapId, basePath); if (!newTree->InitMap(mapFileName, this)) - { - delete newTree; + { + delete newTree; return false; - } + } instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first; } @@ -236,7 +249,7 @@ namespace VMAP floor = info.ground_Z; ASSERT(floor < std::numeric_limits<float>::max()); type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc - if (reqLiquidType && !(GetLiquidFlags(type) & reqLiquidType)) + if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) return false; if (info.hitInstance->GetLiquidLevel(pos, info, level)) return true; @@ -276,7 +289,6 @@ namespace VMAP { //! Critical section, thread safe access to iLoadedModelFiles TRINITY_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock); - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); if (model == iLoadedModelFiles.end()) { @@ -298,4 +310,4 @@ namespace VMAP return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y); } -} // namespace VMAP +} // namespace VMAP
\ No newline at end of file diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index f4455fc72d..ac07d79458 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -1,7 +1,19 @@ /* - * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2 - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * Copyright (C) + * Copyright (C) + * + * 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 _VMAPMANAGER2_H @@ -66,6 +78,8 @@ namespace VMAP bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ + static uint32 GetLiquidFlagsDummy(uint32) { return 0; } + public: // public for debug G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; @@ -102,7 +116,10 @@ namespace VMAP virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y); public: void getInstanceMapTree(InstanceTreeMap &instanceMapTree); + + typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType); + GetLiquidFlagsFn GetLiquidFlagsPtr; }; } -#endif +#endif
\ No newline at end of file diff --git a/src/common/Collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h index be11c256b5..d93662d7fc 100644 --- a/src/common/Collision/Maps/TileAssembler.h +++ b/src/common/Collision/Maps/TileAssembler.h @@ -34,7 +34,7 @@ namespace VMAP float iScale; void init() { - iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iDir.y/180.f, G3D::pi()*iDir.x/180.f, G3D::pi()*iDir.z/180.f); + iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iDir.y/180.f, G3D::pif()*iDir.x/180.f, G3D::pif()*iDir.z/180.f); } G3D::Vector3 transform(const G3D::Vector3& pIn) const; void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } diff --git a/src/common/Database/Implementation/CharacterDatabase.cpp b/src/common/Database/Implementation/CharacterDatabase.cpp index a656b66884..c1ace0ccaa 100644 --- a/src/common/Database/Implementation/CharacterDatabase.cpp +++ b/src/common/Database/Implementation/CharacterDatabase.cpp @@ -136,7 +136,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_ACCOUNT_INSTANCE_LOCK_TIMES, "DELETE FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_ACCOUNT_INSTANCE_LOCK_TIMES, "INSERT INTO account_instance_times (accountId, instanceId, releaseTime) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating, maxMMR FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT ? AS account,(SELECT COUNT(*) FROM characters WHERE account =?) AS cnt", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_NAME, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/common/Database/Implementation/LoginDatabase.cpp b/src/common/Database/Implementation/LoginDatabase.cpp index 2f24eb49e0..66d1755c7a 100644 --- a/src/common/Database/Implementation/LoginDatabase.cpp +++ b/src/common/Database/Implementation/LoginDatabase.cpp @@ -57,6 +57,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_UPD_MUTE_TIME_LOGIN, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = online | (1<<(?-1)) WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS, "DELETE FROM account_access WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, "DELETE FROM account_access WHERE id = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_ASYNC); diff --git a/src/common/Database/Implementation/LoginDatabase.h b/src/common/Database/Implementation/LoginDatabase.h index d745d44c8f..0bde70d161 100644 --- a/src/common/Database/Implementation/LoginDatabase.h +++ b/src/common/Database/Implementation/LoginDatabase.h @@ -77,6 +77,7 @@ enum LoginDatabaseStatements LOGIN_UPD_MUTE_TIME_LOGIN, LOGIN_UPD_LAST_IP, LOGIN_UPD_ACCOUNT_ONLINE, + LOGIN_UPD_UPTIME_PLAYERS, LOGIN_DEL_OLD_LOGS, LOGIN_DEL_ACCOUNT_ACCESS, LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, diff --git a/src/common/Database/Implementation/WorldDatabase.cpp b/src/common/Database/Implementation/WorldDatabase.cpp index 77b3ca2a62..2dd28018ed 100644 --- a/src/common/Database/Implementation/WorldDatabase.cpp +++ b/src/common/Database/Implementation/WorldDatabase.cpp @@ -70,8 +70,8 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? AND (phaseMask & ?) <> 0 ORDER BY order_", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? AND (phaseMask & ?) <> 0 ORDER BY order_", CONNECTION_SYNCH); PrepareStatement(WORLD_INS_CREATURE, "INSERT INTO creature (guid, id , map, spawnMask, phaseMask, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint, curhealth, curmana, MovementType, npcflag, unit_flags, dynamicflags) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_DEL_GAME_EVENT_CREATURE, "DELETE FROM game_event_creature WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP, "DELETE FROM game_event_model_equip WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/scripts/Commands/cs_mmaps.cpp b/src/scripts/Commands/cs_mmaps.cpp new file mode 100644 index 0000000000..831539ce2f --- /dev/null +++ b/src/scripts/Commands/cs_mmaps.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2008-2016 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/>. + */ + +/** +* @file cs_mmaps.cpp +* @brief .mmap related commands +* +* This file contains the CommandScripts for all +* mmap sub-commands +*/ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "DisableMgr.h" +#include "ObjectMgr.h" +#include "Player.h" +#include "PointMovementGenerator.h" +#include "PathGenerator.h" +#include "MMapFactory.h" +#include "Map.h" +#include "TargetedMovementGenerator.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +class mmaps_commandscript : public CommandScript +{ +public: + mmaps_commandscript() : CommandScript("mmaps_commandscript") { } + + std::vector<ChatCommand> GetCommands() const override + { + static std::vector<ChatCommand> mmapCommandTable = + { + { "loadedtiles", SEC_ADMINISTRATOR, false, &HandleMmapLoadedTilesCommand, "" }, + { "loc", SEC_ADMINISTRATOR, false, &HandleMmapLocCommand, "" }, + { "path", SEC_ADMINISTRATOR, false, &HandleMmapPathCommand, "" }, + { "stats", SEC_ADMINISTRATOR, false, &HandleMmapStatsCommand, "" }, + { "testarea", SEC_ADMINISTRATOR, false, &HandleMmapTestArea, "" }, + }; + + static std::vector<ChatCommand> commandTable = + { + { "mmap", SEC_ADMINISTRATOR, true, NULL, "", mmapCommandTable }, + }; + return commandTable; + } + + static bool HandleMmapPathCommand(ChatHandler* handler, char const* args) + { + if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap path:"); + + // units + Player* player = handler->GetSession()->GetPlayer(); + Unit* target = handler->getSelectedUnit(); + if (!player || !target) + { + handler->PSendSysMessage("Invalid target/source selection."); + return true; + } + + char* para = strtok((char*)args, " "); + + bool useStraightPath = false; + if (para && strcmp(para, "true") == 0) + useStraightPath = true; + + bool useStraightLine = false; + if (para && strcmp(para, "line") == 0) + useStraightLine = true; + + // unit locations + float x, y, z; + player->GetPosition(x, y, z); + + // path + PathGenerator path(target); + path.SetUseStraightPath(useStraightPath); + bool result = path.CalculatePath(x, y, z, false); + + Movement::PointsArray const& pointPath = path.GetPath(); + handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); + handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : useStraightLine ? "Raycast" : "SmoothPath"); + handler->PSendSysMessage("Result: %s - Length: %zu - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); + + G3D::Vector3 const &start = path.GetStartPosition(); + G3D::Vector3 const &end = path.GetEndPosition(); + G3D::Vector3 const &actualEnd = path.GetActualEndPosition(); + + handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z); + handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z); + handler->PSendSysMessage("ActualEndPosition (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); + + if (!player->IsGameMaster()) + handler->PSendSysMessage("Enable GM mode to see the path points."); + + for (uint32 i = 0; i < pointPath.size(); ++i) + player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); + + return true; + } + + static bool HandleMmapLocCommand(ChatHandler* handler, char const* /*args*/) + { + handler->PSendSysMessage("mmap tileloc:"); + + // grid tile location + Player* player = handler->GetSession()->GetPlayer(); + + int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; + int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + + handler->PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gx, gy); + handler->PSendSysMessage("gridloc [%i, %i]", gy, gx); + + // calculate navmesh tile location + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + float const* min = navmesh->getParams()->orig; + float x, y, z; + player->GetPosition(x, y, z); + float location[VERTEX_SIZE] = {y, z, x}; + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; + + int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); + int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); + + handler->PSendSysMessage("Calc [%02i, %02i]", tilex, tiley); + + // navmesh poly -> navmesh tile location + dtQueryFilter filter = dtQueryFilter(); + dtPolyRef polyRef = INVALID_POLYREF; + if (dtStatusFailed(navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL))) + { + handler->PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)"); + return true; + } + + if (polyRef == INVALID_POLYREF) + handler->PSendSysMessage("Dt [??, ??] (invalid poly, probably no tile loaded)"); + else + { + dtMeshTile const* tile; + dtPoly const* poly; + if (dtStatusSucceed(navmesh->getTileAndPolyByRef(polyRef, &tile, &poly))) + { + if (tile) + { + handler->PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y); + return false; + } + } + + handler->PSendSysMessage("Dt [??,??] (no tile loaded)"); + } + + return true; + } + + static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/) + { + uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId(); + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId()); + if (!navmesh || !navmeshquery) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + handler->PSendSysMessage("mmap loadedtiles:"); + + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + dtMeshTile const* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + handler->PSendSysMessage("[%02i, %02i]", tile->header->x, tile->header->y); + } + + return true; + } + + static bool HandleMmapStatsCommand(ChatHandler* handler, char const* /*args*/) + { + handler->PSendSysMessage("mmap stats:"); + //handler->PSendSysMessage(" global mmap pathfinding is %sabled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis"); + + MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); + handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); + + dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + if (!navmesh) + { + handler->PSendSysMessage("NavMesh not loaded for current map."); + return true; + } + + uint32 tileCount = 0; + uint32 nodeCount = 0; + uint32 polyCount = 0; + uint32 vertCount = 0; + uint32 triCount = 0; + uint32 triVertCount = 0; + uint32 dataSize = 0; + for (int32 i = 0; i < navmesh->getMaxTiles(); ++i) + { + dtMeshTile const* tile = navmesh->getTile(i); + if (!tile || !tile->header) + continue; + + tileCount++; + nodeCount += tile->header->bvNodeCount; + polyCount += tile->header->polyCount; + vertCount += tile->header->vertCount; + triCount += tile->header->detailTriCount; + triVertCount += tile->header->detailVertCount; + dataSize += tile->dataSize; + } + + handler->PSendSysMessage("Navmesh stats:"); + handler->PSendSysMessage(" %u tiles loaded", tileCount); + handler->PSendSysMessage(" %u BVTree nodes", nodeCount); + handler->PSendSysMessage(" %u polygons (%u vertices)", polyCount, vertCount); + handler->PSendSysMessage(" %u triangles (%u vertices)", triCount, triVertCount); + handler->PSendSysMessage(" %.2f MB of data (not including pointers)", ((float)dataSize / sizeof(unsigned char)) / 1048576); + + return true; + } + + static bool HandleMmapTestArea(ChatHandler* handler, char const* /*args*/) + { + float radius = 40.0f; + WorldObject* object = handler->GetSession()->GetPlayer(); + + CellCoord pair(Trinity::ComputeCellCoord(object->GetPositionX(), object->GetPositionY())); + Cell cell(pair); + cell.SetNoCreate(); + + std::list<Creature*> creatureList; + + Trinity::AnyUnitInObjectRangeCheck go_check(object, radius); + Trinity::CreatureListSearcher<Trinity::AnyUnitInObjectRangeCheck> go_search(object, creatureList, go_check); + TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AnyUnitInObjectRangeCheck>, GridTypeMapContainer> go_visit(go_search); + + // Get Creatures + cell.Visit(pair, go_visit, *(object->GetMap()), *object, radius); + + if (!creatureList.empty()) + { + handler->PSendSysMessage("Found %zu Creatures.", creatureList.size()); + + uint32 paths = 0; + uint32 uStartTime = getMSTime(); + + float gx, gy, gz; + object->GetPosition(gx, gy, gz); + for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + { + PathGenerator path(*itr); + path.CalculatePath(gx, gy, gz); + ++paths; + } + + uint32 uPathLoadTime = getMSTimeDiff(uStartTime, getMSTime()); + handler->PSendSysMessage("Generated %i paths in %i ms", paths, uPathLoadTime); + } + else + handler->PSendSysMessage("No creatures in %f yard range.", radius); + + return true; + } +}; + +void AddSC_mmaps_commandscript() +{ + new mmaps_commandscript(); +} diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 3af8f9adc3..f133d0b35e 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -429,7 +429,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Map entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.map); return false; } - if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && !GetAreaEntryByAreaID(e.event.respawn.area)) + if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_AREA && !sAreaTableStore.LookupEntry(e.event.respawn.area)) { sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Area entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.respawn.area); return false; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 66b713d594..3b02da9c64 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1731,7 +1731,7 @@ class SmartAIMgr bool IsItemValid(SmartScriptHolder const& e, uint32 entry) { - if (!sItemStore.LookupEntry(entry)) + if (!sObjectMgr->GetItemTemplate(entry)) { sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Item entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); return false; diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 881bc09ce2..ac8d218c1b 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -167,7 +167,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return true; } case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA: - if (!GetAreaEntryByAreaID(area.id)) + if (!sAreaTableStore.LookupEntry(area.id)) { sLog->outErrorDb("Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) has wrong area id in value1 (%u), ignored.", criteria->ID, criteria->requiredType, dataType, area.id); @@ -358,12 +358,18 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un return false; return target->getGender() == gender.gender; case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT: - return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target)); + return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target), criteria_id); case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY: + { if (source->GetMap()->IsRaid()) if (source->GetMap()->Is25ManRaid() != ((difficulty.difficulty & RAID_DIFFICULTY_MASK_25MAN) != 0)) return false; - return source->GetMap()->GetSpawnMode() >= difficulty.difficulty; + + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(criteria_id); + uint8 spawnMode = source->GetMap()->GetSpawnMode(); + // Dungeons completed on heroic mode count towards both in general achievement, but not in statistics. + return sAchievementMgr->IsStatisticCriteria(criteria) ? spawnMode == difficulty.difficulty : spawnMode >= difficulty.difficulty; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT: return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM: @@ -1277,17 +1283,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui bool matchFound = false; for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j) { - uint32 area_id = worldOverlayEntry->areatableID[j]; - if (!area_id) // array have 0 only in empty tail + AreaTableEntry const* area = sAreaTableStore.LookupEntry(worldOverlayEntry->areatableID[j]); + if (!area) break; - int32 exploreFlag = GetAreaFlagByAreaID(area_id); - if (exploreFlag < 0) + uint32 playerIndexOffset = uint32(area->exploreFlag) / 32; + if (playerIndexOffset >= PLAYER_EXPLORED_ZONES_SIZE) continue; - uint32 playerIndexOffset = uint32(exploreFlag) / 32; - uint32 mask = 1<< (uint32(exploreFlag) % 32); - + uint32 mask = 1 << (uint32(area->exploreFlag) % 32); if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) { matchFound = true; @@ -1661,8 +1665,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } + case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA { + // those requirements couldn't be found in the dbc + AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria); + if (!data || !data->Meets(GetPlayer(), NULL)) + continue; + // Check map id requirement if (miscValue1 == achievementCriteria->win_arena.mapID) SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); @@ -1678,7 +1688,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; // FIXME: not triggered in code as result, need to implement case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID: - case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK: case ACHIEVEMENT_CRITERIA_TYPE_TOTAL: break; // Not implemented yet :( @@ -1876,6 +1885,7 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED: case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN: case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS: + case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA: default: break; } @@ -2163,9 +2173,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) } } - // don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement - // TODO: where do set this instead? - if (!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) sAchievementMgr->SetRealmCompleted(achievement); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, achievement->ID); @@ -2307,6 +2315,61 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, return true; } +bool AchievementGlobalMgr::IsStatisticCriteria(AchievementCriteriaEntry const* achievementCriteria) const +{ + return isStatisticAchievement(sAchievementStore.LookupEntry(achievementCriteria->referredAchievement)); +} + +bool AchievementGlobalMgr::isStatisticAchievement(AchievementEntry const* achievement) const +{ + if (!achievement) + return false; + + AchievementCategoryEntry const* cat = sAchievementCategoryStore.LookupEntry(achievement->categoryId); + do { + switch(cat->ID) { + case ACHIEVEMENT_CATEGORY_STATISTICS: + return true; + case ACHIEVEMENT_CATEOGRY_GENERAL: + return false; + default: + cat = sAchievementCategoryStore.LookupEntry(cat->parentCategory); + break; + } + } while (cat); + + return false; +} + +bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement) const +{ + auto itr = m_allCompletedAchievements.find(achievement->ID); + if (itr == m_allCompletedAchievements.end()) + return false; + + if (itr->second == std::chrono::system_clock::time_point::min()) + return false; + + if (itr->second == std::chrono::system_clock::time_point::max()) + return true; + + // Allow completing the realm first kill for entire minute after first person did it + // it may allow more than one group to achieve it (highly unlikely) + // but apparently this is how blizz handles it as well + if (achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL) + return (std::chrono::system_clock::now() - itr->second) > std::chrono::minutes(1); + + return true; +} + +void AchievementGlobalMgr::SetRealmCompleted(AchievementEntry const* achievement) +{ + if (IsRealmCompleted(achievement)) + return; + + m_allCompletedAchievements[achievement->ID] = std::chrono::system_clock::now(); +} + //========================================================== void AchievementGlobalMgr::LoadAchievementCriteriaList() { @@ -2628,6 +2691,14 @@ void AchievementGlobalMgr::LoadCompletedAchievements() QueryResult result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); + // Populate _allCompletedAchievements with all realm first achievement ids to make multithreaded access safer + // while it will not prevent races, it will prevent crashes that happen because std::unordered_map key was added + // instead the only potential race will happen on value associated with the key + for (uint32 i = 0; i < sAchievementStore.GetNumRows(); ++i) + if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(i)) + if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + m_allCompletedAchievements[achievement->ID] = std::chrono::system_clock::time_point::min(); + if (!result) { sLog->outString(">> Loaded 0 completed achievements. DB table `character_achievement` is empty."); @@ -2655,7 +2726,7 @@ void AchievementGlobalMgr::LoadCompletedAchievements() continue; } else if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) - m_allCompletedAchievements.insert(achievementId); + m_allCompletedAchievements[achievementId] = std::chrono::system_clock::time_point::max(); } while (result->NextRow()); sLog->outString(">> Loaded %lu completed achievements in %u ms", (unsigned long)m_allCompletedAchievements.size(), GetMSTimeDiffToNow(oldMSTime)); diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index 390a0cb589..74fe0046ef 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -8,6 +8,7 @@ #include <map> #include <string> +#include <chrono> #include "Common.h" #include <ace/Singleton.h> @@ -55,9 +56,14 @@ enum AchievementCriteriaDataType ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23 // title_id known (pvp) title, values from dbc }; - #define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum +enum AchievementCommonCategories +{ + ACHIEVEMENT_CATEOGRY_GENERAL = -1, + ACHIEVEMENT_CATEGORY_STATISTICS = 1 +}; + class Player; class Unit; @@ -294,6 +300,9 @@ class AchievementGlobalMgr ~AchievementGlobalMgr() {} public: + bool IsStatisticCriteria(AchievementCriteriaEntry const* achievementCriteria) const; + bool isStatisticAchievement(AchievementEntry const* achievement) const; + AchievementCriteriaEntryList const* GetAchievementCriteriaByType(AchievementCriteriaTypes type) const { return &m_AchievementCriteriasByType[type]; @@ -348,15 +357,8 @@ class AchievementGlobalMgr return iter != m_criteriaDataMap.end() ? &iter->second : NULL; } - bool IsRealmCompleted(AchievementEntry const* achievement) const - { - return m_allCompletedAchievements.find(achievement->ID) != m_allCompletedAchievements.end(); - } - - void SetRealmCompleted(AchievementEntry const* achievement) - { - m_allCompletedAchievements.insert(achievement->ID); - } + bool IsRealmCompleted(AchievementEntry const* achievement) const; + void SetRealmCompleted(AchievementEntry const* achievement); void LoadAchievementCriteriaList(); void LoadAchievementCriteriaData(); @@ -375,7 +377,7 @@ class AchievementGlobalMgr // store achievements by referenced achievement id to speed up lookup AchievementListByReferencedId m_AchievementListByReferencedId; - typedef std::set<uint32> AllCompletedAchievements; + typedef UNORDERED_MAP<uint32 /*achievementId*/, std::chrono::system_clock::time_point /*completionTime*/> AllCompletedAchievements; AllCompletedAchievements m_allCompletedAchievements; AchievementRewards m_achievementRewards; diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 144eb65465..e4ac0d3901 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -956,6 +956,8 @@ void Battleground::EndBattleground(TeamId winnerTeamId) // Arena lost => reset the win_rated_arena having the "no_lose" condition player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE, 0); } + + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA, GetMapId()); } uint32 winner_kills = player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST; diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 2d6aae341a..2b4f7c26ae 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -111,8 +111,8 @@ set(game_STAT_SRCS include_directories( ${game_INCLUDE_DIRS} ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Detour/Include + ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Recast/Include ${CMAKE_SOURCE_DIR}/deps/g3dlite/include ${CMAKE_SOURCE_DIR}/deps/SFMT ${CMAKE_SOURCE_DIR}/deps/zlib diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 9e94ec8ee3..79986a7538 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -301,11 +301,11 @@ bool ChatHandler::ExecuteCommandInTable(std::vector<ChatCommand> const& table, c uint32 areaId = player->GetAreaId(); std::string areaName = "Unknown"; std::string zoneName = "Unknown"; - if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId)) { int locale = GetSessionDbcLocale(); areaName = area->area_name[locale]; - if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone)) + if (AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone)) zoneName = zone->area_name[locale]; } diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index ee334106c2..ccf36914cf 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1658,7 +1658,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) } case CONDITION_ZONEID: { - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->ConditionValue1); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(cond->ConditionValue1); if (!areaEntry) { sLog->outErrorDb("ZoneID condition has non existing area (%u), skipped", cond->ConditionValue1); diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index f9c2648116..d92d3f78a2 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -38,15 +38,14 @@ struct WMOAreaTableTripple typedef std::map<WMOAreaTableTripple, WMOAreaTableEntry const*> WMOAreaInfoByTripple; -DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt); +DBCStorage <AreaTableEntry> sAreaTableStore(AreaTableEntryfmt); DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt); DBCStorage <AreaPOIEntry> sAreaPOIStore(AreaPOIEntryfmt); -static AreaFlagByAreaID sAreaFlagByAreaID; -static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files static WMOAreaInfoByTripple sWMOAreaInfoByTripple; DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt); +DBCStorage <AchievementCategoryEntry> sAchievementCategoryStore(AchievementCategoryfmt); DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore(AchievementCriteriafmt); DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt); DBCStorage <AuctionHouseEntry> sAuctionHouseStore(AuctionHouseEntryfmt); @@ -100,7 +99,6 @@ DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptf DBCStorage <HolidaysEntry> sHolidaysStore(Holidaysfmt); -DBCStorage <ItemEntry> sItemStore(Itemfmt); DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore(ItemBagFamilyfmt); //DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt); DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); @@ -255,23 +253,10 @@ void LoadDBCStores(const std::string& dataPath) StoreProblemList bad_dbc_files; uint32 availableDbcLocales = 0xFFFFFFFF; - LoadDBC(availableDbcLocales, bad_dbc_files, sAreaStore, dbcPath, "AreaTable.dbc"); - - // must be after sAreaStore loading - for (uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0 - { - if (AreaTableEntry const* area = sAreaStore.LookupEntry(i)) - { - // fill AreaId->DBC records - sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID), area->exploreFlag)); - - // fill MapId->DBC records (skip sub zones and continents) - if (area->zone == 0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571) - sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid, area->exploreFlag)); - } - } + LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTableStore, dbcPath, "AreaTable.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementStore, dbcPath, "Achievement.dbc", &CustomAchievementfmt, &CustomAchievementIndex); + LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCategoryStore, dbcPath, "Achievement_Category.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAchievementCriteriaStore, dbcPath, "Achievement_Criteria.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaTriggerStore, dbcPath, "AreaTrigger.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sAreaGroupStore, dbcPath, "AreaGroup.dbc"); @@ -346,7 +331,6 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sHolidaysStore, dbcPath, "Holidays.dbc"); - LoadDBC(availableDbcLocales, bad_dbc_files, sItemStore, dbcPath, "Item.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemBagFamilyStore, dbcPath, "ItemBagFamily.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sItemDisplayInfoStore, dbcPath, "ItemDisplayInfo.dbc"); //LoadDBC(dbcCount, availableDbcLocales, bad_dbc_files, sItemCondExtCostsStore, dbcPath, "ItemCondExtCosts.dbc"); @@ -626,10 +610,9 @@ void LoadDBCStores(const std::string& dataPath) } // Check loaded DBC files proper version - if (!sAreaStore.LookupEntry(3617) || // last area (areaflag) added in 3.3.5a + if (!sAreaTableStore.LookupEntry(4987) || // last area added in 3.3.5a !sCharTitlesStore.LookupEntry(177) || // last char title added in 3.3.5a !sGemPropertiesStore.LookupEntry(1629) || // last added spell in 3.3.5a - !sItemStore.LookupEntry(56806) || // last gem property added in 3.3.5a !sItemExtendedCostStore.LookupEntry(2997) || // last item extended cost added in 3.3.5a !sMapStore.LookupEntry(724) || // last map added in 3.3.5a !sSpellStore.LookupEntry(80864) ) // last client known item added in 3.3.5a @@ -678,50 +661,12 @@ uint32 GetTalentSpellCost(uint32 spellId) return 0; } -int32 GetAreaFlagByAreaID(uint32 area_id) -{ - AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); - if (i == sAreaFlagByAreaID.end()) - return -1; - - return i->second; -} - WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid) { WMOAreaInfoByTripple::iterator i = sWMOAreaInfoByTripple.find(WMOAreaTableTripple(rootid, adtid, groupid)); - if (i == sWMOAreaInfoByTripple.end()) - return NULL; - return i->second; -} - -AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id) -{ - int32 areaflag = GetAreaFlagByAreaID(area_id); - if (areaflag < 0) + if (i == sWMOAreaInfoByTripple.end()) return NULL; - - return sAreaStore.LookupEntry(areaflag); -} - -AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id) -{ - if (area_flag) - return sAreaStore.LookupEntry(area_flag); - - if (MapEntry const* mapEntry = sMapStore.LookupEntry(map_id)) - return GetAreaEntryByAreaID(mapEntry->linked_zone); - - return NULL; -} - -uint32 GetAreaFlagByMapId(uint32 mapid) -{ - AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid); - if (i == sAreaFlagByMapID.end()) - return 0; - else - return i->second; + return i->second; } uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index d69d2132b9..5b241f6fcb 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -20,11 +20,6 @@ char* GetPetName(uint32 petfamily, uint32 dbclang); uint32 GetTalentSpellCost(uint32 spellId); TalentSpellPos const* GetTalentSpellPos(uint32 spellId); -int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found -AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id); -AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag, uint32 map_id); -uint32 GetAreaFlagByMapId(uint32 mapid); - WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid); uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId); @@ -58,7 +53,8 @@ uint32 GetDefaultMapLight(uint32 mapId); extern DBCStorage <AchievementEntry> sAchievementStore; extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore; -extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions +extern DBCStorage <AchievementCategoryEntry> sAchievementCategoryStore; +extern DBCStorage <AreaTableEntry> sAreaTableStore; extern DBCStorage <AreaGroupEntry> sAreaGroupStore; extern DBCStorage <AreaPOIEntry> sAreaPOIStore; extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore; @@ -104,7 +100,6 @@ extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore; extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore; extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore; extern DBCStorage <HolidaysEntry> sHolidaysStore; -extern DBCStorage <ItemEntry> sItemStore; extern DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore; extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 3b7ecee547..e43351b9dd 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -46,7 +46,7 @@ struct AchievementEntry struct AchievementCategoryEntry { uint32 ID; // 0 - uint32 parentCategory; // 1 -1 for main category + int32 parentCategory; // 1 -1 for main category //char *name[16]; // 2-17 //uint32 name_flags; // 18 //uint32 sortOrder; // 19 @@ -1092,18 +1092,6 @@ struct HolidaysEntry //uint32 flags; // 54 m_flags (0 = Darkmoon Faire, Fishing Contest and Wotlk Launch, rest is 1) }; -struct ItemEntry -{ - uint32 ID; // 0 - uint32 Class; // 1 - uint32 SubClass; // 2 some items have strange subclasses - int32 SoundOverrideSubclass; // 3 - int32 Material; // 4 - uint32 DisplayId; // 5 - uint32 InventoryType; // 6 - uint32 Sheath; // 7 -}; - struct ItemBagFamilyEntry { uint32 ID; // 0 diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 395de0fe9d..8e1a6c3395 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -10,8 +10,9 @@ char const Achievementfmt[] = "niixssssssssssssssssxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii"; const std::string CustomAchievementfmt="pppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaapapaaaaaaaaaaaaaaaaaapp"; const std::string CustomAchievementIndex = "ID"; +char const AchievementCategoryfmt[] = "nixxxxxxxxxxxxxxxxxx"; char const AchievementCriteriafmt[] = "niiiiiiiixxxxxxxxxxxxxxxxxiiiix"; -char const AreaTableEntryfmt[] = "iiinixxxxxissssssssssssssssxiiiiixxx"; +char const AreaTableEntryfmt[] = "niiiixxxxxissssssssssssssssxiiiiixxx"; char const AreaGroupEntryfmt[] = "niiiiiii"; char const AreaPOIEntryfmt[] = "niiiiiiiiiiifffixixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix"; char const AreaTriggerEntryfmt[] = "niffffffff"; @@ -57,7 +58,6 @@ char const GtOCTRegenHPfmt[] = "f"; char const GtRegenHPPerSptfmt[] = "f"; char const GtRegenMPPerSptfmt[] = "f"; char const Holidaysfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiixxsiix"; -char const Itemfmt[] = "niiiiiii"; char const ItemBagFamilyfmt[] = "nxxxxxxxxxxxxxxxxx"; char const ItemDisplayTemplateEntryfmt[] = "nxxxxsxxxxxxxxxxxxxxxxxxx"; //char const ItemCondExtCostsEntryfmt[] = "xiii"; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 176315d742..8a2a0f3a13 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -353,7 +353,7 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData* data) // Load creature equipment if (!data || data->equipmentId == 0) // use default from the template - LoadEquipment(GetCreatureData() ? GetOriginalEquipmentId() : 1); + LoadEquipment(); else if (data && data->equipmentId != 0) // override, 0 means no equipment { m_originalEquipmentId = data->equipmentId; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index f3091758f6..d1731510ea 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1095,9 +1095,13 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const if (!IsInMap(obj)) return false; - float ox, oy, oz; - obj->GetPosition(ox, oy, oz); - return IsWithinLOS(ox, oy, oz); + float x, y, z; + if (obj->GetTypeId() == TYPEID_PLAYER) + obj->GetPosition(x, y, z); + else + obj->GetHitSpherePointFor(GetPosition(), x, y, z); + + return IsWithinLOS(x, y, z); } bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const @@ -1107,11 +1111,36 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);*/ if (IsInWorld()) - return GetMap()->isInLineOfSight(GetPositionX(), GetPositionY(), GetPositionZ()+2.f, ox, oy, oz+2.f, GetPhaseMask()); + { + float x, y, z; + if (GetTypeId() == TYPEID_PLAYER) + GetPosition(x, y, z); + else + GetHitSpherePointFor({ ox, oy, oz }, x, y, z); + + return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask()); + } return true; } +Position WorldObject::GetHitSpherePointFor(Position const& dest) const +{ + G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ()); + G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); + G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(this), GetObjectSize()); + + return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y)); +} + +void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const +{ + Position pos = GetHitSpherePointFor(dest); + x = pos.GetPositionX(); + y = pos.GetPositionY(); + z = pos.GetPositionZ(); +} + bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const { float dx1 = GetPositionX() - obj1->GetPositionX(); @@ -2402,123 +2431,33 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, else UpdateAllowedPositionZ(x, y, z); - /* // if detection disabled, return first point - if (!sWorld->getIntConfig(CONFIG_DETECT_POS_COLLISION)) - { - UpdateGroundPositionZ(x, y, z); // update to LOS height if available + if (!sWorld->getBoolConfig(CONFIG_DETECT_POS_COLLISION)) return; - } - // or remember first point - float first_x = x; - float first_y = y; - bool first_los_conflict = false; // first point LOS problems - - // prepare selector for work - ObjectPosSelector selector(GetPositionX(), GetPositionY(), GetObjectSize(), distance2d+searcher_size); - - // adding used positions around object - { - CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY())); - Cell cell(p); - cell.SetNoCreate(); - - Trinity::NearUsedPosDo u_do(*this, searcher, absAngle, selector); - Trinity::WorldObjectWorker<Trinity::NearUsedPosDo> worker(this, u_do); - - TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker); - TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker); - - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap(), *this, distance2d); - cell_lock->Visit(cell_lock, world_obj_worker, *GetMap(), *this, distance2d); - } - - // maybe can just place in primary position - if (selector.CheckOriginal()) - { - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - - first_los_conflict = true; // first point have LOS problems - } - - float angle; // candidate of angle for free pos - - // special case when one from list empty and then empty side preferred - if (selector.FirstAngle(angle)) - { - GetNearPoint2D(x, y, distance2d, absAngle+angle); - z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - } - - // set first used pos in lists - selector.InitializeAngle(); - - // select in positions after current nodes (selection one by one) - while (selector.NextAngle(angle)) // angle for free pos - { - GetNearPoint2D(x, y, distance2d, absAngle+angle); - z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - - if (IsWithinLOS(x, y, z)) - return; - } - - // BAD NEWS: not free pos (or used or have LOS problems) - // Attempt find _used_ pos without LOS problem - - if (!first_los_conflict) - { - x = first_x; - y = first_y; - - UpdateGroundPositionZ(x, y, z); // update to LOS height if available + // return if the point is already in LoS + if (IsWithinLOS(x, y, z)) return; - } - - // special case when one from list empty and then empty side preferred - if (selector.IsNonBalanced()) - { - if (!selector.FirstAngle(angle)) // _used_ pos - { - GetNearPoint2D(x, y, distance2d, absAngle+angle); - z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - if (IsWithinLOS(x, y, z)) - return; - } - } - - // set first used pos in lists - selector.InitializeAngle(); + // remember first point + float first_x = x; + float first_y = y; + float first_z = z; - // select in positions after current nodes (selection one by one) - while (selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem + // loop in a circle to look for a point in LoS using small steps + for (float angle = float(M_PI) / 8; angle < float(M_PI) * 2; angle += float(M_PI) / 8) { - GetNearPoint2D(x, y, distance2d, absAngle+angle); + GetNearPoint2D(x, y, distance2d + searcher_size, absAngle + angle); z = GetPositionZ(); - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - + UpdateAllowedPositionZ(x, y, z); if (IsWithinLOS(x, y, z)) return; } - // BAD BAD NEWS: all found pos (free and used) have LOS problem :( + // still not in LoS, give up and return first position found x = first_x; y = first_y; - - UpdateGroundPositionZ(x, y, z); // update to LOS height if available - */ + z = first_z; } bool WorldObject::GetClosePoint(float &x, float &y, float &z, float size, float distance2d, float angle, const WorldObject* forWho, bool force) const diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 123b1aa08e..68b8bda28c 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -365,6 +365,17 @@ class Object struct Position { + Position(float x = 0, float y = 0, float z = 0, float o = 0) + : m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { } + + Position(Position const& loc) { Relocate(loc); } + + struct PositionXYStreamer + { + explicit PositionXYStreamer(Position& pos) : Pos(&pos) { } + Position* Pos; + }; + struct PositionXYZStreamer { explicit PositionXYZStreamer(Position& pos) : m_pos(&pos) {} @@ -382,19 +393,38 @@ struct Position float m_positionZ; float m_orientation; + bool operator==(Position const &a); + + inline bool operator!=(Position const &a) + { + return !(operator==(a)); + } + void Relocate(float x, float y) - { m_positionX = x; m_positionY = y;} + { + m_positionX = x; m_positionY = y; + } void Relocate(float x, float y, float z) - { m_positionX = x; m_positionY = y; m_positionZ = z; } + { + m_positionX = x; m_positionY = y; m_positionZ = z; + } void Relocate(float x, float y, float z, float orientation) - { m_positionX = x; m_positionY = y; m_positionZ = z; m_orientation = orientation; } + { + m_positionX = x; m_positionY = y; m_positionZ = z; m_orientation = orientation; + } void Relocate(const Position &pos) - { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; m_orientation = pos.m_orientation; } + { + m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; m_orientation = pos.m_orientation; + } void Relocate(const Position* pos) - { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; m_orientation = pos->m_orientation; } + { + m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; m_orientation = pos->m_orientation; + } void RelocateOffset(const Position &offset); void SetOrientation(float orientation) - { m_orientation = orientation; } + { + m_orientation = orientation; + } float GetPositionX() const { return m_positionX; } float GetPositionY() const { return m_positionY; } @@ -402,17 +432,26 @@ struct Position float GetOrientation() const { return m_orientation; } void GetPosition(float &x, float &y) const - { x = m_positionX; y = m_positionY; } + { + x = m_positionX; y = m_positionY; + } void GetPosition(float &x, float &y, float &z) const - { x = m_positionX; y = m_positionY; z = m_positionZ; } + { + x = m_positionX; y = m_positionY; z = m_positionZ; + } void GetPosition(float &x, float &y, float &z, float &o) const - { x = m_positionX; y = m_positionY; z = m_positionZ; o = m_orientation; } + { + x = m_positionX; y = m_positionY; z = m_positionZ; o = m_orientation; + } void GetPosition(Position* pos) const { if (pos) pos->Relocate(m_positionX, m_positionY, m_positionZ, m_orientation); } + Position GetPosition() const { return *this; } + + Position::PositionXYZStreamer PositionXYZStream() { return PositionXYZStreamer(*this); @@ -425,39 +464,65 @@ struct Position bool IsPositionValid() const; float GetExactDist2dSq(float x, float y) const - { float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; } + { + float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; + } float GetExactDist2d(const float x, const float y) const - { return sqrt(GetExactDist2dSq(x, y)); } + { + return sqrt(GetExactDist2dSq(x, y)); + } float GetExactDist2dSq(const Position* pos) const - { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; } + { + float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; + } float GetExactDist2d(const Position* pos) const - { return sqrt(GetExactDist2dSq(pos)); } + { + return sqrt(GetExactDist2dSq(pos)); + } float GetExactDistSq(float x, float y, float z) const - { float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; } + { + float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; + } float GetExactDist(float x, float y, float z) const - { return sqrt(GetExactDistSq(x, y, z)); } + { + return sqrt(GetExactDistSq(x, y, z)); + } float GetExactDistSq(const Position* pos) const - { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; } + { + float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; + } float GetExactDist(const Position* pos) const - { return sqrt(GetExactDistSq(pos)); } + { + return sqrt(GetExactDistSq(pos)); + } void GetPositionOffsetTo(const Position & endPos, Position & retOffset) const; float GetAngle(const Position* pos) const; float GetAngle(float x, float y) const; float GetRelativeAngle(const Position* pos) const - { return GetAngle(pos) - m_orientation; } + { + return GetAngle(pos) - m_orientation; + } float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; } void GetSinCos(float x, float y, float &vsin, float &vcos) const; bool IsInDist2d(float x, float y, float dist) const - { return GetExactDist2dSq(x, y) < dist * dist; } + { + return GetExactDist2dSq(x, y) < dist * dist; + } bool IsInDist2d(const Position* pos, float dist) const - { return GetExactDist2dSq(pos) < dist * dist; } + { + return GetExactDist2dSq(pos) < dist * dist; + } bool IsInDist(float x, float y, float z, float dist) const - { return GetExactDistSq(x, y, z) < dist * dist; } + { + return GetExactDistSq(x, y, z) < dist * dist; + } bool IsInDist(const Position* pos, float dist) const - { return GetExactDistSq(pos) < dist * dist; } + { + return GetExactDistSq(pos) < dist * dist; + } bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const; bool HasInArc(float arcangle, const Position* pos, float targetRadius = 0.0f) const; @@ -479,10 +544,13 @@ struct Position return fmod(o, 2.0f * static_cast<float>(M_PI)); } }; -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); +ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer); +ByteBuffer& operator >> (ByteBuffer& buf, Position::PositionXYStreamer const& streamer); ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); -ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); +ByteBuffer& operator >> (ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); +ByteBuffer& operator >> (ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); + struct MovementInfo { @@ -785,6 +853,8 @@ class WorldObject : public Object, public WorldLocation } bool IsWithinLOS(float x, float y, float z) const; bool IsWithinLOSInMap(const WorldObject* obj) const; + Position GetHitSpherePointFor(Position const& dest) const; + void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const; bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const; bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const; bool IsInRange2d(float x, float y, float minRange, float maxRange) const; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 4d064f5afc..e887d6cb60 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -960,6 +960,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) SetCreateHealth(4 * petlevel); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - 30 - (petlevel / 4) + m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.006f)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel - 30 + (petlevel / 4) + m_owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.006f)); + SetReactState(REACT_DEFENSIVE); break; } case NPC_ARMY_OF_THE_DEAD: diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 41c4f3a1af..ece890078a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2189,8 +2189,8 @@ void Player::SendTeleportAckPacket() GetSession()->SendPacket(&data); } -bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options) -{ +bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options /*= 0*/, Unit *target /*= nullptr*/) +{ if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation)) { sLog->outError("TeleportTo: invalid map (%d) or invalid coordinates (X: %f, Y: %f, Z: %f, O: %f) given when teleporting player (GUID: %u, name: %s, map: %d, X: %f, Y: %f, Z: %f, O: %f).", @@ -2288,6 +2288,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (duel && GetMapId() != mapid && GetMap()->GetGameObject(GetUInt64Value(PLAYER_DUEL_ARBITER))) DuelComplete(DUEL_FLED); + if (!sScriptMgr->OnBeforePlayerTeleport(this, mapid, x, y, z, orientation, options, target)) + return false; + if (GetMapId() == mapid) { //lets reset far teleport flag if it wasn't reset during chained teleports @@ -3026,11 +3029,7 @@ void Player::SetGameMaster(bool on) else { // restore phase - uint32 newPhase = 0; - AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE); - if (!phases.empty()) - for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - newPhase |= (*itr)->GetMiscValue(); + uint32 newPhase = GetPhaseByAuras(); if (!newPhase) newPhase = PHASEMASK_NORMAL; @@ -3063,14 +3062,21 @@ void Player::SetGameMaster(bool on) } void Player::SetGMVisible(bool on) -{ +{ + const uint32 VISUAL_AURA = 37800; + if (on) { + if (HasAura(VISUAL_AURA, 0)) + RemoveAurasDueToSpell(VISUAL_AURA); + m_ExtraFlags &= ~PLAYER_EXTRA_GM_INVISIBLE; //remove flag m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GM, SEC_PLAYER); } else { + AddAura(VISUAL_AURA, this); + m_ExtraFlags |= PLAYER_EXTRA_GM_INVISIBLE; //add flag SetAcceptWhispers(false); @@ -5286,7 +5292,7 @@ void Player::CreateCorpse() return; } - _uf = GetUInt32Value(UNIT_FIELD_BYTES_0); + _uf = getRace(); _pb = GetUInt32Value(PLAYER_BYTES); _pb2 = GetUInt32Value(PLAYER_BYTES_2); @@ -5577,11 +5583,11 @@ void Player::RepopAtGraveyard() // note: this can be called also when the player is alive // for example from WorldSession::HandleMovementOpcodes - AreaTableEntry const* zone = GetAreaEntryByAreaID(GetAreaId()); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetAreaId()); // Such zones are considered unreachable as a ghost and the player must be automatically revived // Xinef: Get Transport Check is not needed - if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) /*|| GetTransport()*/ || GetPositionZ() < -500.0f) + if ((!IsAlive() && zone && zone->flags & AREA_FLAG_NEED_FLY) /*|| GetTransport()*/ || GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY())) { ResurrectPlayer(0.5f); SpawnCorpseBones(); @@ -5618,8 +5624,10 @@ void Player::RepopAtGraveyard() GetSession()->SendPacket(&data); } } - else if (GetPositionZ() < -500.0f) + else if (GetPositionZ() < GetMap()->GetMinHeight(GetPositionX(), GetPositionY())) TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); + + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS); } bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone) @@ -5671,7 +5679,7 @@ void Player::UpdateLocalChannels(uint32 newZone) if (GetSession()->PlayerLoading() && !IsBeingTeleportedFar()) return; // The client handles it automatically after loading, but not after teleporting - AreaTableEntry const* current_zone = GetAreaEntryByAreaID(newZone); + AreaTableEntry const* current_zone = sAreaTableStore.LookupEntry(newZone); if (!current_zone) return; @@ -6894,45 +6902,46 @@ void Player::CheckAreaExploreAndOutdoor() return; bool isOutdoor = IsOutdoors(); - uint32 areaFlag = GetAreaFlagByAreaID(GetAreaId()); - + uint32 areaId = GetBaseMap()->GetAreaId(GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); + if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK) && !isOutdoor) RemoveAurasWithAttribute(SPELL_ATTR0_OUTDOORS_ONLY); - if (areaFlag == 0xffff) + if (!areaId) return; - int offset = areaFlag / 32; + + if (!areaEntry) + { + sLog->outError("Player '%s' (%u) discovered unknown area (x: %f y: %f z: %f map: %u)", + GetName().c_str(), GetGUIDLow(), GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId()); + return; + } + + uint32 offset = areaEntry->exploreFlag / 32; if (offset >= PLAYER_EXPLORED_ZONES_SIZE) { #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outError("Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < %u ).", areaFlag, GetPositionX(), GetPositionY(), offset, offset, PLAYER_EXPLORED_ZONES_SIZE); + sLog->outError("Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < %u ).", areaEntry->flags, GetPositionX(), GetPositionY(), offset, offset, PLAYER_EXPLORED_ZONES_SIZE); #endif return; } - uint32 val = (uint32)(1 << (areaFlag % 32)); + uint32 val = (uint32)(1 << (areaEntry->exploreFlag % 32)); uint32 currFields = GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); if (!(currFields & val)) { SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA, GetAreaId()); - - AreaTableEntry const* areaEntry = GetAreaEntryByAreaFlagAndMap(areaFlag, GetMapId()); - if (!areaEntry) - { - sLog->outError("Player %u discovered unknown area (x: %f y: %f z: %f map: %u", GetGUIDLow(), GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId()); - return; - } + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA, areaId); if (areaEntry->area_level > 0) { - uint32 area = areaEntry->ID; if (getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { - SendExplorationExperience(area, 0); + SendExplorationExperience(areaId, 0); } else { @@ -6958,10 +6967,10 @@ void Player::CheckAreaExploreAndOutdoor() } GiveXP(XP, NULL); - SendExplorationExperience(area, XP); + SendExplorationExperience(areaId, XP); } #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - sLog->outDetail("Player %u discovered a new area: %u", GetGUIDLow(), area); + sLog->outDetail("Player %u discovered a new area: %u", GetGUIDLow(), areaId); #endif } } @@ -7528,12 +7537,14 @@ void Player::UpdateArea(uint32 newArea) // pussywizard: inform instance, needed for Icecrown Citadel if (InstanceScript* instance = GetInstanceScript()) instance->OnPlayerAreaUpdate(this, m_areaUpdateId, newArea); + + sScriptMgr->OnPlayerUpdateArea(this, m_areaUpdateId, newArea); // FFA_PVP flags are area and not zone id dependent // so apply them accordingly m_areaUpdateId = newArea; - AreaTableEntry const* area = GetAreaEntryByAreaID(newArea); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(newArea); bool oldFFAPvPArea = pvpInfo.IsInFFAPvPArea; pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA); UpdatePvPState(true); @@ -7568,7 +7579,7 @@ void Player::UpdateArea(uint32 newArea) } // Xinef: area should inherit zone flags - AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone); uint32 areaFlags = area->flags; bool isSanctuary = area->IsSanctuary(); bool isInn = area->IsInn(GetTeamId(true)); @@ -7656,7 +7667,7 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) // zone changed, so area changed as well, update it UpdateArea(newArea); - AreaTableEntry const* zone = GetAreaEntryByAreaID(newZone); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(newZone); if (!zone) return; @@ -9258,6 +9269,12 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->FillLoot(creature->GetCreatureTemplate()->SkinLootId, LootTemplates_Skinning, this, true); permission = OWNER_PERMISSION; + //Inform instance if creature is skinned. + if (InstanceScript* mapInstance = creature->GetInstanceScript()) + { + mapInstance->CreatureLooted(creature, LOOT_SKINNING); + } + // Xinef: Set new loot recipient creature->SetLootRecipient(this, false); } @@ -20736,7 +20753,7 @@ void Player::Say(const std::string& text, const uint32 language) sScriptMgr->OnPlayerChat(this, CHAT_MSG_SAY, language, _text); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, Language(language), this, this, text); + ChatHandler::BuildChatPacket(data, CHAT_MSG_SAY, Language(language), this, this, _text); SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true); } @@ -20746,7 +20763,7 @@ void Player::Yell(const std::string& text, const uint32 language) sScriptMgr->OnPlayerChat(this, CHAT_MSG_YELL, language, _text); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, Language(language), this, this, text); + ChatHandler::BuildChatPacket(data, CHAT_MSG_YELL, Language(language), this, this, _text); SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true); } @@ -20756,7 +20773,7 @@ void Player::TextEmote(const std::string& text) sScriptMgr->OnPlayerChat(this, CHAT_MSG_EMOTE, LANG_UNIVERSAL, _text); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, text); + ChatHandler::BuildChatPacket(data, CHAT_MSG_EMOTE, LANG_UNIVERSAL, this, this, _text); SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT)); } @@ -20773,14 +20790,14 @@ void Player::Whisper(const std::string& text, uint32 language, uint64 receiver) sScriptMgr->OnPlayerChat(this, CHAT_MSG_WHISPER, language, _text, rPlayer); WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, Language(language), this, this, text); + ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, Language(language), this, this, _text); rPlayer->GetSession()->SendPacket(&data); // rest stuff shouldn't happen in case of addon message if (isAddonMessage) return; - ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER_INFORM, Language(language), rPlayer, rPlayer, text); + ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER_INFORM, Language(language), rPlayer, rPlayer, _text); GetSession()->SendPacket(&data); if (!isAcceptWhispers() && !IsGameMaster() && !rPlayer->IsGameMaster()) @@ -22658,19 +22675,30 @@ bool Player::IsVisibleGloballyFor(Player const* u) const } template<class T> -inline void UpdateVisibilityOf_helper(T* /*target*/, std::vector<Unit*>& /*v*/) +inline void UpdateVisibilityOf_helper(Player::ClientGUIDs& s64, T* target, std::vector<Unit*>& /*v*/) +{ + s64.insert(target->GetGUID()); +} + +template<> +inline void UpdateVisibilityOf_helper(Player::ClientGUIDs& s64, GameObject* target, std::vector<Unit*>& /*v*/) { + // @HACK: This is to prevent objects like deeprun tram from disappearing when player moves far from its spawn point while riding it + if ((target->GetGOInfo()->type != GAMEOBJECT_TYPE_TRANSPORT)) + s64.insert(target->GetGUID()); } template<> -inline void UpdateVisibilityOf_helper(Creature* target, std::vector<Unit*>& v) +inline void UpdateVisibilityOf_helper(Player::ClientGUIDs& s64, Creature* target, std::vector<Unit*>& v) { + s64.insert(target->GetGUID()); v.push_back(target); } template<> -inline void UpdateVisibilityOf_helper(Player* target, std::vector<Unit*>& v) +inline void UpdateVisibilityOf_helper(Player::ClientGUIDs& s64, Player* target, std::vector<Unit*>& v) { + s64.insert(target->GetGUID()); v.push_back(target); } @@ -22784,9 +22812,7 @@ void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::vector<Unit*>& if (CanSeeOrDetect(target, false, true)) { target->BuildCreateUpdateBlockForPlayer(&data, this); - m_clientGUIDs.insert(target->GetGUID()); - - UpdateVisibilityOf_helper(target, visibleNow); + UpdateVisibilityOf_helper(m_clientGUIDs, target, visibleNow); } } } @@ -23610,8 +23636,8 @@ void Player::UpdateForQuestWorldObjects() GetSession()->SendPacket(&packet); } -void Player::SummonIfPossible(bool agree) -{ +void Player::SummonIfPossible(bool agree, uint32 summoner_guid) +{ if (!agree) { m_summon_expire = 0; @@ -23631,7 +23657,7 @@ void Player::SummonIfPossible(bool agree) UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1); - TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z, GetOrientation()); + TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z, GetOrientation(), 0, ObjectAccessor::FindPlayer(summoner_guid)); } void Player::RemoveItemDurations(Item* item) @@ -25226,22 +25252,19 @@ void Player::_LoadSkills(PreparedQueryResult result) } uint32 Player::GetPhaseMaskForSpawn() const -{ - uint32 phase = PHASEMASK_NORMAL; - if (!IsGameMaster()) - phase = GetPhaseMask(); - else - { - AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE); - if (!phases.empty()) - phase = phases.front()->GetMiscValue(); - } +{ + uint32 phase = IsGameMaster() ? GetPhaseByAuras() : GetPhaseMask(); + + if (!phase) + phase = PHASEMASK_NORMAL; + // some aura phases include 1 normal map in addition to phase itself - if (uint32 n_phase = phase & ~PHASEMASK_NORMAL) + uint32 n_phase = phase & ~PHASEMASK_NORMAL; + if (n_phase > 0) return n_phase; - return PHASEMASK_NORMAL; + return phase; } InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limit_count) const diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index a0f3ec042d..3e879bf1e6 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1096,10 +1096,10 @@ class Player : public Unit, public GridObject<Player> SetFloatValue(UNIT_FIELD_COMBATREACH, scale * DEFAULT_COMBAT_REACH); } - bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); - bool TeleportTo(WorldLocation const &loc, uint32 options = 0) + bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0, Unit *target = nullptr); + bool TeleportTo(WorldLocation const &loc, uint32 options = 0, Unit *target = nullptr) { - return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options); + return TeleportTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation(), options, target); } bool TeleportToEntryPoint(); @@ -1114,7 +1114,7 @@ class Player : public Unit, public GridObject<Player> } bool IsSummonAsSpectator() const { return m_summon_asSpectator && m_summon_expire >= time(NULL); } void SetSummonAsSpectator(bool on) { m_summon_asSpectator = on; } - void SummonIfPossible(bool agree); + void SummonIfPossible(bool agree, uint32 summoner_guid); time_t GetSummonExpireTimer() const { return m_summon_expire; } bool Create(uint32 guidlow, CharacterCreateInfo* createInfo); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5166c71504..d0bcf5d290 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3395,6 +3395,15 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const return 0; } +bool Unit::CanMoveDuringChannel() const +{ + if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + if (spell->getState() != SPELL_STATE_FINISHED) + return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && spell->IsChannelActive(); + + return false; +} + bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const { return IsWithinDistInMap(target, distance) && HasInArc(arc, target); @@ -13690,7 +13699,7 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* if (!spellInfo || castTime < 0) return; - if (spellInfo->IsChanneled() && !(spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)) + if (spellInfo->IsChanneled() && spellInfo->HasAura(SPELL_AURA_MOUNTED)) return; // called from caster @@ -14493,7 +14502,7 @@ void CharmInfo::InitPossessCreateSpells() { uint32 spellId = _unit->ToCreature()->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (spellInfo && !spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD)) + if (spellInfo) { if (spellInfo->IsPassive()) _unit->CastSpell(_unit, spellInfo, true); @@ -14523,7 +14532,7 @@ void CharmInfo::InitCharmCreateSpells() uint32 spellId = _unit->ToCreature()->m_spells[x]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo || spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD)) + if (!spellInfo) { _charmspells[x].SetActionAndType(spellId, ACT_DISABLED); continue; @@ -17547,6 +17556,17 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, i return missChance; } +uint32 Unit::GetPhaseByAuras() const +{ + uint32 currentPhase = 0; + AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE); + if (!phases.empty()) + for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) + currentPhase |= (*itr)->GetMiscValue(); + + return currentPhase; +} + void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) { if (newPhaseMask == GetPhaseMask()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a390a6359d..bb8dca9134 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2048,6 +2048,9 @@ class Unit : public WorldObject // delayed+channeled spells are always interrupted void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0, bool withInstant = true, bool bySelf = false); + // Check if our current channel spell has attribute SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING + bool CanMoveDuringChannel() const; + Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; } Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; } Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; @@ -2122,6 +2125,7 @@ class Unit : public WorldObject void SetModelVisible(bool on); // common function for visibility checks for player/creatures with detection code + uint32 GetPhaseByAuras() const; void SetPhaseMask(uint32 newPhaseMask, bool update);// overwrite WorldObject::SetPhaseMask void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false); diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 096825803b..26670a333a 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -19,6 +19,8 @@ #include "GameObjectAI.h" #include "Transport.h" +#include <time.h> + bool GameEventMgr::CheckOneGameEvent(uint16 entry) const { switch (mGameEvent[entry].state) @@ -194,8 +196,8 @@ void GameEventMgr::LoadFromDB() { { uint32 oldMSTime = getMSTime(); - // 1 2 3 4 5 6 7 8 - QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, description, world_event FROM game_event"); + // 1 2 3 4 5 6 7 8 9 + QueryResult result = WorldDatabase.Query("SELECT eventEntry, UNIX_TIMESTAMP(start_time), UNIX_TIMESTAMP(end_time), occurence, length, holiday, holidayStage, description, world_event FROM game_event"); if (!result) { mGameEvent.clear(); @@ -225,9 +227,13 @@ void GameEventMgr::LoadFromDB() pGameEvent.length = fields[4].GetUInt64(); pGameEvent.holiday_id = HolidayIds(fields[5].GetUInt32()); - pGameEvent.state = (GameEventState)(fields[7].GetUInt8()); + pGameEvent.holidayStage = fields[6].GetUInt8(); + pGameEvent.description = fields[7].GetString(); + pGameEvent.state = (GameEventState)(fields[8].GetUInt8()); pGameEvent.nextstart = 0; + ++count; + if (pGameEvent.length == 0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check { sLog->outErrorDb("`game_event` game event id (%i) isn't a world event and has length = 0, thus it can't be used.", event_id); @@ -241,11 +247,10 @@ void GameEventMgr::LoadFromDB() sLog->outErrorDb("`game_event` game event id (%i) have not existed holiday id %u.", event_id, pGameEvent.holiday_id); pGameEvent.holiday_id = HOLIDAY_NONE; } - } - pGameEvent.description = fields[6].GetString(); + SetHolidayEventTime(pGameEvent); + } - ++count; } while (result->NextRow()); @@ -951,6 +956,45 @@ void GameEventMgr::LoadFromDB() } } +void GameEventMgr::LoadHolidayDates() +{ + uint32 oldMSTime = getMSTime(); + + // 0 1 2 + QueryResult result = WorldDatabase.Query("SELECT id, date_id, date_value FROM holiday_dates"); + + if (!result) + { + sLog->outString(">> Loaded 0 holiday dates. DB table `holiday_dates` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + uint32 holidayId = fields[0].GetUInt32(); + HolidaysEntry* entry = const_cast<HolidaysEntry*>(sHolidaysStore.LookupEntry(holidayId)); + if (!entry) + { + sLog->outErrorDb("holiday_dates entry has invalid holiday id %u.", holidayId); + continue; + } + uint8 dateId = fields[1].GetUInt8(); + if (dateId >= MAX_HOLIDAY_DATES) + { + sLog->outErrorDb("holiday_dates entry has out of range date_id %u.", dateId); + continue; + } + entry->Date[dateId] = fields[2].GetUInt32(); + modifiedHolidays.insert(entry->Id); + ++count; + + } while (result->NextRow()); + + sLog->outString(">> Loaded %u holiday dates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); +} + uint32 GameEventMgr::GetNPCFlag(Creature* cr) { uint32 mask = 0; @@ -1669,6 +1713,83 @@ void GameEventMgr::RunSmartAIScripts(uint16 event_id, bool activate) } } +void GameEventMgr::SetHolidayEventTime(GameEventData& event) +{ + if (!event.holidayStage) // Ignore holiday + return; + + const HolidaysEntry* holiday = sHolidaysStore.LookupEntry(event.holiday_id); + + if (!holiday->Date[0] || !holiday->Duration[0]) // Invalid definitions + { + sLog->outErrorDb("Missing date or duration for holiday %u.", event.holiday_id); + return; + } + + uint8 stageIndex = event.holidayStage - 1; + event.length = holiday->Duration[stageIndex] * HOUR / MINUTE; + + time_t stageOffset = 0; + for (int i = 0; i < stageIndex; ++i) + stageOffset += holiday->Duration[i] * HOUR; + + switch (holiday->CalendarFilterType) + { + case -1: // Yearly + event.occurence = YEAR / MINUTE; // Not all too useful + break; + case 0: // Weekly + event.occurence = WEEK / MINUTE; + break; + case 1: // Defined dates only (Darkmoon Faire) + break; + case 2: // Only used for looping events (Call to Arms) + break; + } + + if (holiday->Looping) + { + event.occurence = 0; + for (int i = 0; i < MAX_HOLIDAY_DURATIONS && holiday->Duration[i]; ++i) + event.occurence += holiday->Duration[i] * HOUR / MINUTE; + } + + bool singleDate = ((holiday->Date[0] >> 24) & 0x1F) == 31; // Events with fixed date within year have - 1 + + time_t curTime = time(NULL); + for (int i = 0; i < MAX_HOLIDAY_DATES && holiday->Date[i]; ++i) + { + uint32 date = holiday->Date[i]; + + tm timeInfo; + if (singleDate) + timeInfo.tm_year = localtime(&curTime)->tm_year - 1; // First try last year (event active through New Year) + else + timeInfo.tm_year = ((date >> 24) & 0x1F) + 100; + timeInfo.tm_mon = (date >> 20) & 0xF; + timeInfo.tm_mday = ((date >> 14) & 0x3F) + 1; + timeInfo.tm_hour = (date >> 6) & 0x1F; + timeInfo.tm_min = date & 0x3F; + timeInfo.tm_sec = 0; + timeInfo.tm_isdst = -1; + tm tmCopy = timeInfo; + + time_t startTime = mktime(&timeInfo); + if (curTime < startTime + event.length * MINUTE) + { + event.start = startTime + stageOffset; + return; + } + else if (singleDate) + { + tmCopy.tm_year = localtime(&curTime)->tm_year; // This year + event.start = mktime(&tmCopy) + stageOffset; + return; + } + } + sLog->outString("No suitable start date found for holiday %u.", event.holiday_id); +} + bool IsHolidayActive(HolidayIds id) { if (id == HOLIDAY_NONE) diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index 91eb981102..64f1659882 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -50,6 +50,7 @@ struct GameEventData uint32 occurence; // time between end and start uint32 length; // length of the event (minutes) after finishing all conditions HolidayIds holiday_id; + uint8 holidayStage; GameEventState state; // state of the game event, these are saved into the game_event table on change! GameEventConditionMap conditions; // conditions to finish std::set<uint16 /*gameevent id*/> prerequisite_events; // events that must be completed before starting this event @@ -95,6 +96,7 @@ class GameEventMgr bool CheckOneGameEvent(uint16 entry) const; uint32 NextCheck(uint16 entry) const; void LoadFromDB(); + void LoadHolidayDates(); uint32 Update(); bool IsActiveEvent(uint16 event_id) { return (m_ActiveEvents.find(event_id) != m_ActiveEvents.end()); } uint32 StartSystem(); @@ -128,6 +130,7 @@ class GameEventMgr bool hasGameObjectQuestActiveEventExcept(uint32 quest_id, uint16 event_id); bool hasCreatureActiveEventExcept(uint32 creature_guid, uint16 event_id); bool hasGameObjectActiveEventExcept(uint32 go_guid, uint16 event_id); + void SetHolidayEventTime(GameEventData& event); typedef std::list<uint32> GuidList; typedef std::list<uint32> IdList; @@ -162,6 +165,7 @@ class GameEventMgr public: GameEventGuidMap mGameEventCreatureGuids; GameEventGuidMap mGameEventGameobjectGuids; + std::set<uint32> modifiedHolidays; }; #define sGameEventMgr ACE_Singleton<GameEventMgr, ACE_Null_Mutex>::instance() diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 125b6d6c7c..c82ad20e9c 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1171,9 +1171,9 @@ void ObjectMgr::LoadEquipmentTemplates() if (!equipmentInfo.ItemEntry[i]) continue; - ItemEntry const* dbcItem = sItemStore.LookupEntry(equipmentInfo.ItemEntry[i]); + const ItemTemplate* item = GetItemTemplate(equipmentInfo.ItemEntry[i]); - if (!dbcItem) + if (!item) { sLog->outErrorDb("Unknown item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u, forced to 0.", equipmentInfo.ItemEntry[i], i+1, entry); @@ -1181,15 +1181,15 @@ void ObjectMgr::LoadEquipmentTemplates() continue; } - if (dbcItem->InventoryType != INVTYPE_WEAPON && - dbcItem->InventoryType != INVTYPE_SHIELD && - dbcItem->InventoryType != INVTYPE_RANGED && - dbcItem->InventoryType != INVTYPE_2HWEAPON && - dbcItem->InventoryType != INVTYPE_WEAPONMAINHAND && - dbcItem->InventoryType != INVTYPE_WEAPONOFFHAND && - dbcItem->InventoryType != INVTYPE_HOLDABLE && - dbcItem->InventoryType != INVTYPE_THROWN && - dbcItem->InventoryType != INVTYPE_RANGEDRIGHT) + if (item->InventoryType != INVTYPE_WEAPON && + item->InventoryType != INVTYPE_SHIELD && + item->InventoryType != INVTYPE_RANGED && + item->InventoryType != INVTYPE_2HWEAPON && + item->InventoryType != INVTYPE_WEAPONMAINHAND && + item->InventoryType != INVTYPE_WEAPONOFFHAND && + item->InventoryType != INVTYPE_HOLDABLE && + item->InventoryType != INVTYPE_THROWN && + item->InventoryType != INVTYPE_RANGEDRIGHT) { sLog->outErrorDb("Item (entry=%u) in creature_equip_template.itemEntry%u for entry = %u is not equipable in a hand, forced to 0.", equipmentInfo.ItemEntry[i], i+1, entry); @@ -2266,7 +2266,6 @@ void ObjectMgr::LoadItemTemplates() _itemTemplateStore.rehash(result->GetRowCount()); uint32 count = 0; - bool enforceDBCAttributes = sWorld->getBoolConfig(CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES); do { @@ -2383,53 +2382,6 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.FlagsCu = fields[137].GetUInt32(); // Checks - - ItemEntry const* dbcitem = sItemStore.LookupEntry(entry); - - if (dbcitem) - { - if (itemTemplate.Class != dbcitem->Class) - { - sLog->outErrorDb("Item (Entry: %u) does not have a correct class %u, must be %u .", entry, itemTemplate.Class, dbcitem->Class); - if (enforceDBCAttributes) - itemTemplate.Class = dbcitem->Class; - } - - if (itemTemplate.SoundOverrideSubclass != dbcitem->SoundOverrideSubclass) - { - sLog->outError("Item (Entry: %u) does not have a correct SoundOverrideSubclass (%i), must be %i .", entry, itemTemplate.SoundOverrideSubclass, dbcitem->SoundOverrideSubclass); - if (enforceDBCAttributes) - itemTemplate.SoundOverrideSubclass = dbcitem->SoundOverrideSubclass; - } - if (itemTemplate.Material != dbcitem->Material) - { - sLog->outErrorDb("Item (Entry: %u) does not have a correct material (%i), must be %i .", entry, itemTemplate.Material, dbcitem->Material); - if (enforceDBCAttributes) - itemTemplate.Material = dbcitem->Material; - } - if (itemTemplate.InventoryType != dbcitem->InventoryType) - { - sLog->outErrorDb("Item (Entry: %u) does not have a correct inventory type (%u), must be %u .", entry, itemTemplate.InventoryType, dbcitem->InventoryType); - if (enforceDBCAttributes) - itemTemplate.InventoryType = dbcitem->InventoryType; - } - if (itemTemplate.DisplayInfoID != dbcitem->DisplayId) - { - sLog->outErrorDb("Item (Entry: %u) does not have a correct display id (%u), must be %u .", entry, itemTemplate.DisplayInfoID, dbcitem->DisplayId); - if (enforceDBCAttributes) - itemTemplate.DisplayInfoID = dbcitem->DisplayId; - } - if (itemTemplate.Sheath != dbcitem->Sheath) - { - sLog->outErrorDb("Item (Entry: %u) does not have a correct sheathid (%u), must be %u .", entry, itemTemplate.Sheath, dbcitem->Sheath); - if (enforceDBCAttributes) - itemTemplate.Sheath = dbcitem->Sheath; - } - - } - else - sLog->outErrorDb("Item (Entry: %u) does not exist in item.dbc! (not correct id?).", entry); - if (itemTemplate.Class >= MAX_ITEM_CLASS) { sLog->outErrorDb("Item (Entry: %u) has wrong Class value (%u)", entry, itemTemplate.Class); @@ -2720,7 +2672,7 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.ItemSet = 0; } - if (itemTemplate.Area && !GetAreaEntryByAreaID(itemTemplate.Area)) + if (itemTemplate.Area && !sAreaTableStore.LookupEntry(itemTemplate.Area)) sLog->outErrorDb("Item (Entry: %u) has wrong Area (%u)", entry, itemTemplate.Area); if (itemTemplate.Map && !sMapStore.LookupEntry(itemTemplate.Map)) @@ -4022,7 +3974,7 @@ void ObjectMgr::LoadQuests() // client quest log visual (area case) if (qinfo->ZoneOrSort > 0) { - if (!GetAreaEntryByAreaID(qinfo->ZoneOrSort)) + if (!sAreaTableStore.LookupEntry(qinfo->ZoneOrSort)) { sLog->outErrorDb("Quest %u has `ZoneOrSort` = %u (zone case) but zone with this id does not exist.", qinfo->GetQuestId(), qinfo->ZoneOrSort); @@ -5845,7 +5797,7 @@ void ObjectMgr::LoadGraveyardZones() continue; } - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(zoneId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId); if (!areaEntry) { sLog->outErrorDb("Table `game_graveyard_zone` has a record for not existing zone id (%u), skipped.", zoneId); @@ -7893,7 +7845,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel() uint32 entry = fields[0].GetUInt32(); int32 skill = fields[1].GetInt16(); - AreaTableEntry const* fArea = GetAreaEntryByAreaID(entry); + AreaTableEntry const* fArea = sAreaTableStore.LookupEntry(entry); if (!fArea) { sLog->outErrorDb("AreaId %u defined in `skill_fishing_base_level` does not exist", entry); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index d85705b00c..1340400aa6 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -721,6 +721,7 @@ class ObjectMgr CreatureAddon const* GetCreatureTemplateAddon(uint32 entry); ItemTemplate const* GetItemTemplate(uint32 entry); ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; } + std::vector<ItemTemplate*> const* GetItemTemplateStoreFast() const { return &_itemTemplateStoreFast; } ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId) { diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h index ab35c901fd..5554a731e4 100644 --- a/src/server/game/Grids/GridDefines.h +++ b/src/server/game/Grids/GridDefines.h @@ -23,7 +23,7 @@ class Player; #define MAX_NUMBER_OF_GRIDS 64 -#define SIZE_OF_GRIDS 533.33333f +#define SIZE_OF_GRIDS 533.3333f #define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2) #define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) @@ -213,7 +213,7 @@ namespace Trinity inline bool IsValidMapCoord(float x, float y, float z) { - return IsValidMapCoord(x, y) && isfinite(z); + return IsValidMapCoord(x, y) && IsValidMapCoord(z); } inline bool IsValidMapCoord(float x, float y, float z, float o) diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 888bf00d77..c09ce07a12 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -34,6 +34,7 @@ Copied events should probably have a new owner #include "GuildMgr.h" #include "ArenaTeamMgr.h" #include "WorldSession.h" +#include "GameEventMgr.h" void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) { @@ -139,11 +140,10 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) data.append(dataBuffer); // TODO: Fix this, how we do know how many and what holidays to send? - uint32 holidayCount = 0; - data << uint32(holidayCount); - for (uint32 i = 0; i < holidayCount; ++i) + data << uint32(sGameEventMgr->modifiedHolidays.size()); + for (uint32 entry : sGameEventMgr->modifiedHolidays) { - HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(666); + HolidaysEntry const* holiday = sHolidaysStore.LookupEntry(entry); data << uint32(holiday->Id); // m_ID data << uint32(holiday->Region); // m_region, might be looping diff --git a/src/server/game/Handlers/ChannelHandler.cpp b/src/server/game/Handlers/ChannelHandler.cpp index 9b0cddccfc..a74a3e91c6 100644 --- a/src/server/game/Handlers/ChannelHandler.cpp +++ b/src/server/game/Handlers/ChannelHandler.cpp @@ -27,7 +27,7 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) if (!channel) return; - AreaTableEntry const* zone = GetAreaEntryByAreaID(GetPlayer()->GetZoneId()); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(GetPlayer()->GetZoneId()); if (!zone || !GetPlayer()->CanJoinConstantChannelInZone(channel, zone)) return; } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 5abcd8a8e9..3679c824ca 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1979,30 +1979,50 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData) item = _player->GetItemByGuid(itemGuid); uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8); + + InventoryResult msg; + + Item* uItem = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); + if (uItem) { + if (uItem->IsEquipped()) { + msg = _player->CanUnequipItem(dstpos, true); + if (msg != EQUIP_ERR_OK) { + _player->SendEquipError(msg, uItem, NULL); + continue; + } + } - if (!item) - { - Item* uItem = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i); - if (!uItem) - continue; - - ItemPosCountVec sDest; - InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false); - if (msg == EQUIP_ERR_OK) + if (!item) { - _player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true); - _player->StoreItem(sDest, uItem, true); - } - else - _player->SendEquipError(msg, uItem, NULL); + ItemPosCountVec sDest; + msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, uItem, false); + if (msg == EQUIP_ERR_OK) + { + _player->RemoveItem(INVENTORY_SLOT_BAG_0, i, true); + _player->StoreItem(sDest, uItem, true); + } + else + _player->SendEquipError(msg, uItem, NULL); - continue; + continue; + } } - if (item->GetPos() == dstpos) - continue; + if (item) { + if (item->GetPos() == dstpos) + continue; - _player->SwapItem(item->GetPos(), dstpos); + if (!item->IsEquipped()) { + uint16 _candidatePos; + msg = _player->CanEquipItem(NULL_SLOT, _candidatePos, item, true); + if (msg != EQUIP_ERR_OK) { + _player->SendEquipError(msg, item, NULL); + continue; + } + } + + _player->SwapItem(item->GetPos(), dstpos); + } } WorldPacket data(SMSG_EQUIPMENT_SET_USE_RESULT, 1); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index bf15832c50..ec48d7221b 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -360,7 +360,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData) continue; std::string aname; - if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId())) + if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(itr->second->GetZoneId())) aname = areaEntry->area_name[GetSessionDbcLocale()]; bool s_show = true; @@ -1934,7 +1934,7 @@ void WorldSession::HandleHearthAndResurrect(WorldPacket& /*recv_data*/) return; } - AreaTableEntry const* atEntry = GetAreaEntryByAreaID(_player->GetAreaId()); + AreaTableEntry const* atEntry = sAreaTableStore.LookupEntry(_player->GetAreaId()); if (!atEntry || !(atEntry->flags & AREA_FLAG_WINTERGRASP_2)) return; diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 1feb9ac65e..8d435b303d 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -474,16 +474,26 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); - if (movementInfo.pos.GetPositionZ() < -500.0f) + if (movementInfo.pos.GetPositionZ() < plrMover->GetMap()->GetMinHeight(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY())) if (!plrMover->GetBattleground() || !plrMover->GetBattleground()->HandlePlayerUnderMap(_player)) { if (plrMover->IsAlive()) { + plrMover->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS); plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // player can be alive if GM if (plrMover->IsAlive()) plrMover->KillPlayer(); } + else if (!plrMover->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IS_OUT_OF_BOUNDS)) + { + WorldSafeLocsEntry const* grave = sObjectMgr->GetClosestGraveyard(plrMover->GetPositionX(), plrMover->GetPositionY(), plrMover->GetPositionZ(), plrMover->GetMapId(), plrMover->GetTeamId()); + + if ( grave) + plrMover->TeleportTo(grave->map_id, grave->x, grave->y, grave->z, plrMover->GetOrientation()); + plrMover->Relocate(grave->x, grave->y, grave->z, plrMover->GetOrientation()); + } + plrMover->StopMovingOnCurrentPos(); // pussywizard: moving corpse can't release spirit } } @@ -711,5 +721,5 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recvData) agree = false; } _player->SetSummonAsSpectator(false); - _player->SummonIfPossible(agree); + _player->SummonIfPossible(agree, summoner_guid); } diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 70c1b5c176..3d1958d604 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -134,6 +134,9 @@ class InstanceScript : public ZoneScript //On load virtual void Load(char const* data) { LoadBossState(data); } + //Called when creature is Looted + virtual void CreatureLooted(Creature* /*creature*/, LootType) {} + //When save is needed, this function generates the data virtual std::string GetSaveData() { return GetBossSaveData(); } diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index f1f2875dcf..e25cd1c362 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -84,7 +84,7 @@ class LootTemplate::LootGroup // A set of loot def bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry bool HasQuestDropForPlayer(Player const* player) const; // The same for active quests of the player - void Process(Loot& loot, uint16 lootMode) const; // Rolls an item from the group (if any) and adds the item to the loot + void Process(Loot& loot, Player const *player, LootStore const& lootstore, uint16 lootMode) const; // Rolls an item from the group (if any) and adds the item to the loot float RawTotalChance() const; // Overall chance for the group (without equal chanced items) float TotalChance() const; // Overall chance for the group @@ -98,7 +98,7 @@ class LootTemplate::LootGroup // A set of loot def LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance - LootStoreItem const* Roll(Loot& loot, uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances + LootStoreItem const* Roll(Loot& loot, Player const *player, LootStore const& store, uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances // This class must never be copied - storing pointers LootGroup(LootGroup const&); @@ -279,19 +279,23 @@ void LootStore::ReportNotExistedId(uint32 id) const // Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation) // RATE_DROP_ITEMS is no longer used for all types of entries -bool LootStoreItem::Roll(bool rate) const +bool LootStoreItem::Roll(bool rate, Player const *player, Loot& loot, LootStore const& store) const { - if (chance >= 100.0f) + float _chance = chance; + + sScriptMgr->OnItemRoll(player, this, _chance, loot, store); + + if (_chance >= 100.0f) return true; if (mincountOrRef < 0) // reference case - return roll_chance_f(chance* (rate ? sWorld->getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f)); + return roll_chance_f(_chance* (rate ? sWorld->getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f)); ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid); float qualityModifier = pProto && rate ? sWorld->getRate(qualityToRate[pProto->Quality]) : 1.0f; - return roll_chance_f(chance*qualityModifier); + return roll_chance_f(_chance*qualityModifier); } // Checks correctness of values @@ -462,7 +466,7 @@ bool Loot::FillLoot(uint32 lootId, LootStore const& store, Player* lootOwner, bo items.reserve(MAX_NR_LOOT_ITEMS); quest_items.reserve(MAX_NR_QUEST_ITEMS); - tab->Process(*this, store.IsRatesAllowed(), lootMode, lootOwner); // Processing is done there, callback via Loot::AddItem() + tab->Process(*this, store, lootMode, lootOwner); // Processing is done there, callback via Loot::AddItem() // Setting access rights for group loot case Group* group = lootOwner->GetGroup(); @@ -1102,7 +1106,7 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem* item) } // Rolls an item from the group, returns NULL if all miss their chances -LootStoreItem const* LootTemplate::LootGroup::Roll(Loot& loot, uint16 lootMode) const +LootStoreItem const* LootTemplate::LootGroup::Roll(Loot& loot, Player const *player, LootStore const& store, uint16 lootMode) const { LootStoreItemList possibleLoot = ExplicitlyChanced; possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode)); @@ -1114,10 +1118,14 @@ LootStoreItem const* LootTemplate::LootGroup::Roll(Loot& loot, uint16 lootMode) for (LootStoreItemList::const_iterator itr = possibleLoot.begin(); itr != possibleLoot.end(); ++itr) // check each explicitly chanced entry in the template and modify its chance based on quality. { LootStoreItem* item = *itr; - if (item->chance >= 100.0f) + float chance = item->chance; + + sScriptMgr->OnItemRoll(player, item, chance, loot, store); + + if (chance >= 100.0f) return item; - roll -= item->chance; + roll -= chance; if (roll < 0) return item; } @@ -1169,9 +1177,9 @@ void LootTemplate::LootGroup::CopyConditions(ConditionList /*conditions*/) } // Rolls an item from the group (if any takes its chance) and adds the item to the loot -void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode) const +void LootTemplate::LootGroup::Process(Loot& loot, Player const *player, LootStore const& store, uint16 lootMode) const { - if (LootStoreItem const* item = Roll(loot, lootMode)) + if (LootStoreItem const* item = Roll(loot, player, store, lootMode)) loot.AddItem(*item); } @@ -1297,8 +1305,10 @@ void LootTemplate::CopyConditions(LootItem* li) const } // Rolls for every item in the template and adds the rolled items the the loot -void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, Player const* player, uint8 groupId) const +void LootTemplate::Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId) const { + bool rate = store.IsRatesAllowed(); + if (groupId) // Group reference uses own processing of the group { if (groupId > Groups.size()) @@ -1307,7 +1317,7 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, Player const* if (!Groups[groupId - 1]) return; - Groups[groupId-1]->Process(loot, lootMode); + Groups[groupId-1]->Process(loot, player, store, lootMode); return; } @@ -1318,7 +1328,7 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, Player const* if (!(item->lootmode & lootMode)) // Do not add if mode mismatch continue; - if (!item->Roll(rate)) + if (!item->Roll(rate, player, loot, store)) continue; // Bad luck for the entry if (item->mincountOrRef < 0) // References processing @@ -1328,12 +1338,12 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, Player const* continue; // Error message already printed at loading stage uint32 maxcount = uint32(float(item->maxcount) * sWorld->getRate(RATE_DROP_ITEM_REFERENCED_AMOUNT)); - sScriptMgr->OnAfterRefCount(item, maxcount); + sScriptMgr->OnAfterRefCount(player, loot, rate, lootMode, item, maxcount, store); for (uint32 loop = 0; loop < maxcount; ++loop) // Ref multiplicator - Referenced->Process(loot, rate, lootMode, player, item->group); + Referenced->Process(loot, store, lootMode, player, item->group); } else { // Plain entries (not a reference, not grouped) - sScriptMgr->OnBeforeDropAddItem(player, loot, item); + sScriptMgr->OnBeforeDropAddItem(player, loot, rate, lootMode, item, store); loot.AddItem(*item); // Chance is already checked, just add } } @@ -1341,7 +1351,7 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, Player const* // Now processing groups for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i) if (LootGroup* group = *i) - group->Process(loot, lootMode); + group->Process(loot, player, store, lootMode); } // True if template includes at least 1 quest drop entry @@ -1598,8 +1608,8 @@ void LoadLootTemplates_Fishing() uint32 count = LootTemplates_Fishing.LoadAndCollectLootIds(lootIdSet); // remove real entries and check existence loot - for (uint32 i = 1; i < sAreaStore.GetNumRows(); ++i) - if (AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(i)) + for (uint32 i = 1; i < sAreaTableStore.GetNumRows(); ++i) + if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(i)) if (lootIdSet.find(areaEntry->ID) != lootIdSet.end()) lootIdSet.erase(areaEntry->ID); @@ -1784,8 +1794,8 @@ void LoadLootTemplates_Mail() uint32 count = LootTemplates_Mail.LoadAndCollectLootIds(lootIdSet); // remove real entries and check existence loot - for (uint32 i = 1; i < sMailTemplateStore.GetNumRows(); ++i) - if (sMailTemplateStore.LookupEntry(i)) + for (uint32 i = 1; i < sAreaTableStore.GetNumRows(); ++i) + if (sAreaTableStore.LookupEntry(i)) if (lootIdSet.find(i) != lootIdSet.end()) lootIdSet.erase(i); diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index 4af00d3f8b..fc08f030af 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -110,6 +110,7 @@ enum LootSlotType class Player; class LootStore; class ConditionMgr; +struct Loot; struct LootStoreItem { @@ -129,7 +130,7 @@ struct LootStoreItem group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount) {} - bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation) + bool Roll(bool rate, Player const *player, Loot& loot, LootStore const& store) const; // Checks if the entry takes it's chance (at loot generation) bool IsValid(LootStore const& store, uint32 entry) const; // Checks correctness of values }; @@ -178,7 +179,6 @@ struct QuestItem : index(_index), is_looted(_islooted) {} }; -struct Loot; class LootTemplate; typedef std::vector<QuestItem> QuestItemList; @@ -237,7 +237,7 @@ class LootTemplate // Adds an entry to the group (at loading stage) void AddEntry(LootStoreItem* item); // Rolls for every item in the template and adds the rolled items the the loot - void Process(Loot& loot, bool rate, uint16 lootMode, Player const* player, uint8 groupId = 0) const; + void Process(Loot& loot, LootStore const& store, uint16 lootMode, Player const* player, uint8 groupId = 0) const; void CopyConditions(ConditionList conditions); void CopyConditions(LootItem* li) const; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index a14b89306d..4e6a595a55 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -32,7 +32,7 @@ union u_map_magic }; u_map_magic MapMagic = { {'M','A','P','S'} }; -u_map_magic MapVersionMagic = { {'v','1','.','3'} }; +u_map_magic MapVersionMagic = { {'v','1','.','8'} }; u_map_magic MapAreaMagic = { {'A','R','E','A'} }; u_map_magic MapHeightMagic = { {'M','H','G','T'} }; u_map_magic MapLiquidMagic = { {'M','L','I','Q'} }; @@ -1200,13 +1200,15 @@ GridMap::GridMap() _flags = 0; // Area data _gridArea = 0; - _areaMap = NULL; + _areaMap = nullptr; // Height level data _gridHeight = INVALID_HEIGHT; _gridGetHeight = &GridMap::getHeightFromFlat; _gridIntHeightMultiplier = 0; - m_V9 = NULL; - m_V8 = NULL; + m_V9 = nullptr; + m_V8 = nullptr; + _maxHeight = nullptr; + _minHeight = nullptr; // Liquid data _liquidType = 0; _liquidOffX = 0; @@ -1214,9 +1216,9 @@ GridMap::GridMap() _liquidWidth = 0; _liquidHeight = 0; _liquidLevel = INVALID_HEIGHT; - _liquidEntry = NULL; - _liquidFlags = NULL; - _liquidMap = NULL; + _liquidEntry = nullptr; + _liquidFlags = nullptr; + _liquidMap = nullptr; } GridMap::~GridMap() @@ -1277,15 +1279,19 @@ void GridMap::unloadData() delete[] _areaMap; delete[] m_V9; delete[] m_V8; + delete[] _maxHeight; + delete[] _minHeight; delete[] _liquidEntry; delete[] _liquidFlags; delete[] _liquidMap; - _areaMap = NULL; - m_V9 = NULL; - m_V8 = NULL; - _liquidEntry = NULL; - _liquidFlags = NULL; - _liquidMap = NULL; + _areaMap = nullptr; + m_V9 = nullptr; + m_V8 = nullptr; + _maxHeight = nullptr; + _minHeight = nullptr; + _liquidEntry = nullptr; + _liquidFlags = nullptr; + _liquidMap = nullptr; _gridGetHeight = &GridMap::getHeightFromFlat; } @@ -1350,6 +1356,16 @@ bool GridMap::loadHeightData(FILE* in, uint32 offset, uint32 /*size*/) } else _gridGetHeight = &GridMap::getHeightFromFlat; + + if (header.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS) + { + _maxHeight = new int16[3 * 3]; + _minHeight = new int16[3 * 3]; + if (fread(_maxHeight, sizeof(int16), 3 * 3, in) != 3 * 3 || + fread(_minHeight, sizeof(int16), 3 * 3, in) != 3 * 3) + return false; + } + return true; } @@ -1620,6 +1636,66 @@ float GridMap::getHeightFromUint16(float x, float y) const return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight; } +float GridMap::getMinHeight(float x, float y) const +{ + if (!_minHeight) + return -500.0f; + + static uint32 const indices[] = + { + 3, 0, 4, + 0, 1, 4, + 1, 2, 4, + 2, 5, 4, + 5, 8, 4, + 8, 7, 4, + 7, 6, 4, + 6, 3, 4 + }; + + static float const boundGridCoords[] = + { + 0.0f, 0.0f, + 0.0f, -266.66666f, + 0.0f, -533.33331f, + -266.66666f, 0.0f, + -266.66666f, -266.66666f, + -266.66666f, -533.33331f, + -533.33331f, 0.0f, + -533.33331f, -266.66666f, + -533.33331f, -533.33331f + }; + + Cell cell(x, y); + float gx = x - (int32(cell.GridX()) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS; + float gy = y - (int32(cell.GridY()) - CENTER_GRID_ID + 1) * SIZE_OF_GRIDS; + + uint32 quarterIndex = 0; + if (cell.CellY() < MAX_NUMBER_OF_CELLS / 2) + { + if (cell.CellX() < MAX_NUMBER_OF_CELLS / 2) + { + quarterIndex = 4 + (gy > gx); + } + else + quarterIndex = 2 + ((-SIZE_OF_GRIDS - gx) > gy); + } + else if (cell.CellX() < MAX_NUMBER_OF_CELLS / 2) + { + quarterIndex = 6 + ((-SIZE_OF_GRIDS - gx) <= gy); + } + else + quarterIndex = gx > gy; + + quarterIndex *= 3; + + return G3D::Plane( + G3D::Vector3(boundGridCoords[indices[quarterIndex + 0] * 2 + 0], boundGridCoords[indices[quarterIndex + 0] * 2 + 1], _minHeight[indices[quarterIndex + 0]]), + G3D::Vector3(boundGridCoords[indices[quarterIndex + 1] * 2 + 0], boundGridCoords[indices[quarterIndex + 1] * 2 + 1], _minHeight[indices[quarterIndex + 1]]), + G3D::Vector3(boundGridCoords[indices[quarterIndex + 2] * 2 + 0], boundGridCoords[indices[quarterIndex + 2] * 2 + 1], _minHeight[indices[quarterIndex + 2]]) + ).distance(G3D::Vector3(gx, gy, 0.0f)); +} + float GridMap::getLiquidLevel(float x, float y) const { if (!_liquidMap) @@ -1679,12 +1755,12 @@ inline ZLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 R uint32 liqTypeIdx = liquidEntry->Type; if (entry < 21) { - if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(getArea(x, y), MAPID_INVALID)) + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(getArea(x, y))) { uint32 overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; if (!overrideLiquid && area->zone) { - area = GetAreaEntryByAreaID(area->zone); + area = sAreaTableStore.LookupEntry(area->zone); if (area) overrideLiquid = area->LiquidTypeOverride[liquidEntry->Type]; } @@ -1835,7 +1911,7 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float // we are already under the surface or vmap height above map heigt // or if the distance of the vmap height is less the land height distance - if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z)) + if (vmapHeight > mapHeight || fabs(mapHeight-z) > fabs(vmapHeight-z)) return vmapHeight; else return mapHeight; // better use .map surface height @@ -1847,6 +1923,15 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float return mapHeight; // explicitly use map data } +float Map::GetMinHeight(float x, float y) const +{ + if (GridMap const* grid = const_cast<Map*>(this)->GetGrid(x, y)) + return grid->getMinHeight(x, y); + + return -500.0f; +} + + inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, int32 /*groupId*/, WMOAreaTableEntry const* wmoEntry, AreaTableEntry const* atEntry) { bool outdoor = true; @@ -1887,7 +1972,7 @@ bool Map::IsOutdoors(float x, float y, float z) const #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) sLog->outStaticDebug("Got WMOAreaTableEntry! flag %u, areaid %u", wmoEntry->Flags, wmoEntry->areaId); #endif - atEntry = GetAreaEntryByAreaID(wmoEntry->areaId); + atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId); } return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); } @@ -1911,7 +1996,7 @@ bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, in return false; } -uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const +uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const { uint32 mogpFlags; int32 adtId, rootId, groupId; @@ -1924,20 +2009,20 @@ uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const haveAreaInfo = true; wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); if (wmoEntry) - atEntry = GetAreaEntryByAreaID(wmoEntry->areaId); + atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId); } - uint16 areaflag; + uint16 areaId = 0; if (atEntry) - areaflag = atEntry->exploreFlag; + areaId = atEntry->ID; else { if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y)) - areaflag = gmap->getArea(x, y); + areaId = gmap->getArea(x, y); // this used while not all *.map files generated (instances) - else - areaflag = GetAreaFlagByMapId(i_mapEntry->MapID); + if (!areaId) + areaId = i_mapEntry->linked_zone; } if (isOutdoors) @@ -1947,8 +2032,31 @@ uint16 Map::GetAreaFlag(float x, float y, float z, bool *isOutdoors) const else *isOutdoors = true; } - return areaflag; - } + return areaId; +} + +uint32 Map::GetAreaId(float x, float y, float z) const +{ + return GetAreaId(x, y, z, nullptr); +} + +uint32 Map::GetZoneId(float x, float y, float z) const +{ + uint32 areaId = GetAreaId(x, y, z); + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId)) + if (area->zone) + return area->zone; + + return areaId; +} + +void Map::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const +{ + areaid = zoneid = GetAreaId(x, y, z); + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid)) + if (area->zone) + zoneid = area->zone; +} uint8 Map::GetTerrainType(float x, float y) const { @@ -1986,12 +2094,12 @@ ZLiquidStatus Map::getLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp if (liquid_type && liquid_type < 21) { - if (AreaTableEntry const* area = GetAreaEntryByAreaFlagAndMap(GetAreaFlag(x, y, z), GetId())) + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(x, y, z))) { uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; if (!overrideLiquid && area->zone) { - area = GetAreaEntryByAreaID(area->zone); + area = sAreaTableStore.LookupEntry(area->zone); if (area) overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; } @@ -2053,34 +2161,6 @@ float Map::GetWaterLevel(float x, float y) const return 0; } -uint32 Map::GetAreaIdByAreaFlag(uint16 areaflag, uint32 map_id) -{ - AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id); - - if (entry) - return entry->ID; - else - return 0; -} - -uint32 Map::GetZoneIdByAreaFlag(uint16 areaflag, uint32 map_id) -{ - AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id); - - if (entry) - return (entry->zone != 0) ? entry->zone : entry->ID; - else - return 0; -} - -void Map::GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag, uint32 map_id) -{ - AreaTableEntry const* entry = GetAreaEntryByAreaFlagAndMap(areaflag, map_id); - - areaid = entry ? entry->ID : 0; - zoneid = entry ? ((entry->zone != 0) ? entry->zone : entry->ID) : 0; -} - bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const { return VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2) diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 93061f4a3f..aa8939638e 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -85,9 +85,10 @@ struct map_areaHeader uint16 gridArea; }; -#define MAP_HEIGHT_NO_HEIGHT 0x0001 -#define MAP_HEIGHT_AS_INT16 0x0002 -#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_NO_HEIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008 struct map_heightHeader { @@ -153,6 +154,8 @@ class GridMap uint16* m_uint16_V8; uint8* m_uint8_V8; }; + int16* _maxHeight; + int16* _minHeight; // Height level data float _gridHeight; float _gridIntHeightMultiplier; @@ -193,6 +196,7 @@ public: uint16 getArea(float x, float y) const; inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);} + float getMinHeight(float x, float y) const; float getLiquidLevel(float x, float y) const; uint8 getTerrainType(float x, float y) const; ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); @@ -327,12 +331,16 @@ class Map : public GridRefManager<NGridType> // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + float GetMinHeight(float x, float y) const; Transport* GetTransportForPos(uint32 phase, float x, float y, float z, WorldObject* worldobject = NULL); ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0) const; - uint16 GetAreaFlag(float x, float y, float z, bool *isOutdoors=0) const; - bool GetAreaInfo(float x, float y, float z, uint32 &mogpflags, int32 &adtId, int32 &rootId, int32 &groupId) const; + uint32 GetAreaId(float x, float y, float z, bool *isOutdoors) const; + bool GetAreaInfo(float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; + uint32 GetAreaId(float x, float y, float z) const; + uint32 GetZoneId(float x, float y, float z) const; + void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const; bool IsOutdoors(float x, float y, float z) const; @@ -341,25 +349,6 @@ class Map : public GridRefManager<NGridType> bool IsInWater(float x, float y, float z, LiquidData* data = 0) const; bool IsUnderWater(float x, float y, float z) const; - static uint32 GetAreaIdByAreaFlag(uint16 areaflag, uint32 map_id); - static uint32 GetZoneIdByAreaFlag(uint16 areaflag, uint32 map_id); - static void GetZoneAndAreaIdByAreaFlag(uint32& zoneid, uint32& areaid, uint16 areaflag, uint32 map_id); - - uint32 GetAreaId(float x, float y, float z) const - { - return GetAreaIdByAreaFlag(GetAreaFlag(x, y, z), GetId()); - } - - uint32 GetZoneId(float x, float y, float z) const - { - return GetZoneIdByAreaFlag(GetAreaFlag(x, y, z), GetId()); - } - - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const - { - GetZoneAndAreaIdByAreaFlag(zoneid, areaid, GetAreaFlag(x, y, z), GetId()); - } - void MoveAllCreaturesInMoveList(); void MoveAllGameObjectsInMoveList(); void MoveAllDynamicObjectsInMoveList(); diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index fc7c158da8..d8ca015251 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -36,22 +36,20 @@ class MapManager return (iter == i_maps.end() ? NULL : iter->second); } - uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const - { - Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); - return m->GetAreaFlag(x, y, z); - } uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { - return Map::GetAreaIdByAreaFlag(GetAreaFlag(mapid, x, y, z), mapid); + Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); + return m->GetAreaId(x, y, z); } uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { - return Map::GetZoneIdByAreaFlag(GetAreaFlag(mapid, x, y, z), mapid); + Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); + return m->GetZoneId(x, y, z); } void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) { - Map::GetZoneAndAreaIdByAreaFlag(zoneid, areaid, GetAreaFlag(mapid, x, y, z), mapid); + Map const* m = const_cast<MapManager*>(this)->CreateBaseMap(mapid); + m->GetZoneAndAreaId(zoneid, areaid, x, y, z); } void Initialize(void); diff --git a/src/server/game/Misc/WhoListCache.cpp b/src/server/game/Misc/WhoListCache.cpp index b945a61dfd..7b6873f1c7 100644 --- a/src/server/game/Misc/WhoListCache.cpp +++ b/src/server/game/Misc/WhoListCache.cpp @@ -35,7 +35,7 @@ void WhoListCacheMgr::Update() wstrToLower(wgname); std::string aname; - if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(itr->second->GetZoneId())) + if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(itr->second->GetZoneId())) aname = areaEntry->area_name[sWorld->GetDefaultDbcLocale()]; if (itr->second->IsSpectator()) diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index ee6b5b4262..751024f46a 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -444,7 +444,7 @@ enum SpellAttr4 enum SpellAttr5 { - SPELL_ATTR5_UNK0 = 0x00000001, // 0 + SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING = 0x00000001, // 0 SPELL_ATTR5_NO_REAGENT_WHILE_PREP = 0x00000002, // 1 not need reagents if UNIT_FLAG_PREPARATION SPELL_ATTR5_REMOVE_ON_ARENA_ENTER = 0x00000004, // 2 xinef: remove this aura on arena enter SPELL_ATTR5_USABLE_WHILE_STUNNED = 0x00000008, // 3 usable while stunned @@ -3531,7 +3531,7 @@ enum PartyResult }; #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' -#define MMAP_VERSION 3 +#define MMAP_VERSION 8 struct MmapTileHeader { @@ -3539,12 +3539,23 @@ struct MmapTileHeader uint32 dtVersion; uint32 mmapVersion; uint32 size; - bool usesLiquids : 1; + char usesLiquids; + char padding[3]; MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), - mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {} + mmapVersion(MMAP_VERSION), size(0), usesLiquids(true), padding() { } }; +// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files +static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size"); +static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) + + sizeof(MmapTileHeader::dtVersion) + + sizeof(MmapTileHeader::mmapVersion) + + sizeof(MmapTileHeader::size) + + sizeof(MmapTileHeader::usesLiquids) + + sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields"); + + enum NavTerrain { NAV_EMPTY = 0x00, diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 0962c63aa5..0e74cdbdb8 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -12,6 +12,7 @@ #include "MoveSplineInit.h" #include "MoveSpline.h" #include "Player.h" +#include "VMapFactory.h" #define MIN_QUIET_DISTANCE 28.0f #define MAX_QUIET_DISTANCE 43.0f @@ -32,6 +33,19 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner) if (!_getPoint(owner, x, y, z)) return; + // Add LOS check for target point + bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(), + owner->GetPositionX(), + owner->GetPositionY(), + owner->GetPositionZ() + 2.0f, + x, y, z + 2.0f); + + if (!isInLOS) + { + i_nextCheckTime.Reset(500); + return; + } + owner->AddUnitState(UNIT_STATE_FLEEING_MOVE); Movement::MoveSplineInit init(owner); diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp index c42ae417d2..0a55b66d23 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp @@ -152,9 +152,10 @@ dtPolyRef PathGenerator::GetPolyByLocation(float* point, float* distance) const // still nothing .. // try with bigger search box - extents[1] = 80.0f; - result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint); - if (DT_SUCCESS == result && polyRef != INVALID_POLYREF) + // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly) + extents[1] = 50.0f; + + if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) { *distance = dtVdist(closestPoint, point); return polyRef; @@ -339,7 +340,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con if (startPoly != endPoly || !endInWaterFar) { float closestPoint[VERTEX_SIZE]; - if (DT_SUCCESS == _navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) + if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint, NULL))) { dtVcopy(endPoint, closestPoint); SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1])); @@ -416,7 +417,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data float suffixEndPoint[VERTEX_SIZE]; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, NULL))) { // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that // try to recover by using prev polyref @@ -424,7 +425,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con if (prefixPolyLength) { suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; - if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) + if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint,NULL))) error = true; } else @@ -445,7 +446,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con (int*)&suffixPolyLength, MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path - if (!suffixPolyLength || dtResult != DT_SUCCESS) + if (!_polyLength || dtStatusFailed(dtResult)) { // this is probably an error state, but we'll leave it // and hopefully recover on the next Update @@ -470,7 +471,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con (int*)&_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path - if (!_polyLength || dtResult != DT_SUCCESS) + if (!_polyLength || dtStatusFailed(dtResult)) { // only happens if we passed bad data to findPath(), or navmesh is messed up BuildShortcut(); @@ -499,7 +500,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con (int*)&_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path - if (!_polyLength || dtResult != DT_SUCCESS) + if (!_polyLength || dtStatusFailed(dtResult)) { // only happens if we passed bad data to findPath(), or navmesh is messed up BuildShortcut(); @@ -658,7 +659,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin _pointPathLimit); // maximum number of points } - if (pointCount < 2 || dtResult != DT_SUCCESS) + if (pointCount < 2 || dtStatusFailed(dtResult)) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here @@ -784,7 +785,7 @@ bool PathGenerator::HaveTile(const G3D::Vector3& p) const if (tx < 0 || ty < 0) return false; - return (_navMesh->getTileAt(tx, ty) != NULL); + return (_navMesh->getTileAt(tx, ty, 0) != NULL); } uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) @@ -844,7 +845,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, uint32 nsteerPath = 0; dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); - if (!nsteerPath || DT_SUCCESS != dtResult) + if (!nsteerPath || dtStatusFailed(dtResult)) return false; // Find vertex far enough to steer to. @@ -908,7 +909,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo // Find movement delta. float delta[VERTEX_SIZE]; dtVsub(delta, steerPos, iterPos); - float len = dtSqrt(dtVdot(delta,delta)); + float len = dtMathSqrtf(dtVdot(delta, delta)); // If the steer target is end of path or off-mesh link, do not move past the location. if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) len = 1.0f; diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.h b/src/server/game/Movement/MovementGenerators/PathGenerator.h index 7632c47409..b6c6e72e0d 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.h @@ -38,7 +38,7 @@ class Unit; #define ALLOWED_DIST_FROM_POLY 2.5f #define ADDED_Z_FOR_POLY_LOOKUP 0.3f #define DISALLOW_TIME_AFTER_FAIL 3 // secs -#define MAX_FIXABLE_Z_ERROR 12.0f +#define MAX_FIXABLE_Z_ERROR 7.0f #define VERTEX_SIZE 3 #define INVALID_POLYREF 0 diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index dd5bf42511..97ffaa4437 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -30,6 +30,9 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) return; + if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel()) + return; + float x, y, z; bool isPlayerPet = owner->IsPet() && IS_PLAYER_GUID(owner->GetOwnerGUID()); bool sameTransport = owner->GetTransport() && owner->GetTransport() == i_target->GetTransport(); @@ -44,11 +47,17 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini (i_target->GetTypeId() == TYPEID_PLAYER && i_target->ToPlayer()->IsGameMaster()); // for .npc follow bool forcePoint = ((!isPlayerPet || owner->GetMapId() == 618) && (forceDest || !useMMaps)) || sameTransport; + if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature()) && !sameTransport && !forceDest && !forcePoint) + return; + lastOwnerXYZ.Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ()); lastTargetXYZ.Relocate(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ()); if (!i_offset) { + if (i_target->IsWithinDistInMap(owner, CONTACT_DISTANCE)) + return; + float allowedRange = MELEE_RANGE; if ((!initial || (owner->movespline->Finalized() && this->GetMovementGeneratorType() == CHASE_MOTION_TYPE)) && i_target->IsWithinMeleeRange(owner, allowedRange) && i_target->IsWithinLOS(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ())) return; @@ -60,6 +69,9 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini owner->m_targetsNotAcceptable[i_target->GetGUID()] = MMapTargetData(sWorld->GetGameTime()+DISALLOW_TIME_AFTER_FAIL, owner, i_target.getTarget()); return; } + + // to nearest contact position + i_target->GetContactPoint(owner, x, y, z); } else { @@ -167,6 +179,7 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini else { owner->m_targetsNotAcceptable.erase(i_target->GetGUID()); + owner->AddUnitState(UNIT_STATE_CHASE); init.MovebyPath(i_path->GetPath()); if (i_angle == 0.f) @@ -180,6 +193,8 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T* owner, bool ini // if failed to generate, just use normal MoveTo } + owner->AddUnitState(UNIT_STATE_CHASE); + init.MoveTo(x,y,z); // Using the same condition for facing target as the one that is used for SetInFront on movement end // - applies to ChaseMovementGenerator mostly @@ -206,7 +221,7 @@ bool TargetedMovementGeneratorMedium<T,D>::DoUpdate(T* owner, uint32 time_diff) } // prevent movement while casting spells with cast time or channel time - if (owner->HasUnitState(UNIT_STATE_CASTING)) + if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel()) { bool stop = true; if (Spell* spell = owner->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 876c63e4c5..2c2bf165c6 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1148,13 +1148,13 @@ void ScriptMgr::OnShutdown() FOREACH_SCRIPT(WorldScript)->OnShutdown(); } -bool ScriptMgr::OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target) +bool ScriptMgr::OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target, uint32 criteria_id) { ASSERT(source); // target can be NULL. GET_SCRIPT_RET(AchievementCriteriaScript, scriptId, tmpscript, false); - return tmpscript->OnCheck(source, target); + return tmpscript->OnCheck(source, target, criteria_id); } // Player @@ -1303,6 +1303,21 @@ void ScriptMgr::OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newAre FOREACH_SCRIPT(PlayerScript)->OnUpdateZone(player, newZone, newArea); } +void ScriptMgr::OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea) +{ + FOREACH_SCRIPT(PlayerScript)->OnUpdateArea(player, oldArea, newArea); +} + +bool ScriptMgr::OnBeforePlayerTeleport(Player* player, uint32 mapid, float x, float y, float z, float orientation, uint32 options, Unit *target) +{ + bool ret=true; + FOR_SCRIPTS_RET(PlayerScript, itr, end, ret) // return true by default if not scripts + if (!itr->second->OnBeforeTeleport(player, mapid, x, y, z, orientation, options, target)) + ret=false; // we change ret value only when scripts return false + + return ret; +} + void ScriptMgr::OnPlayerUpdateFaction(Player* player) { FOREACH_SCRIPT(PlayerScript)->OnUpdateFaction(player); @@ -1494,14 +1509,18 @@ void ScriptMgr::OnBeforeUpdateArenaPoints(ArenaTeam* at, std::map<uint32, uint32 FOREACH_SCRIPT(GlobalScript)->OnBeforeUpdateArenaPoints(at,ap); } -void ScriptMgr::OnAfterRefCount(LootStoreItem* LootStoreItem, uint32 &maxcount) +void ScriptMgr::OnAfterRefCount(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, uint32 &maxcount, LootStore const& store) { - FOREACH_SCRIPT(GlobalScript)->OnAfterRefCount(LootStoreItem, maxcount); + FOREACH_SCRIPT(GlobalScript)->OnAfterRefCount(player, LootStoreItem, loot, canRate, lootMode, maxcount, store); } -void ScriptMgr::OnBeforeDropAddItem(Player const* player, Loot& loot, LootStoreItem* LootStoreItem) +void ScriptMgr::OnBeforeDropAddItem(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, LootStore const& store) { - FOREACH_SCRIPT(GlobalScript)->OnBeforeDropAddItem(player, loot, LootStoreItem); + FOREACH_SCRIPT(GlobalScript)->OnBeforeDropAddItem(player, loot, canRate, lootMode, LootStoreItem, store); +} + +void ScriptMgr::OnItemRoll(Player const* player, LootStoreItem const* LootStoreItem, float &chance, Loot& loot, LootStore const& store) { + FOREACH_SCRIPT(GlobalScript)->OnItemRoll(player, LootStoreItem, chance, loot, store); } void ScriptMgr::OnInitializeLockedDungeons(Player* player, uint8& level, uint32& lockData) diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 260d8d666c..c71c45dbff 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -747,7 +747,11 @@ class AchievementCriteriaScript : public ScriptObject bool IsDatabaseBound() const { return true; } // Called when an additional criteria is checked. - virtual bool OnCheck(Player* source, Unit* target) = 0; + virtual bool OnCheck(Player* source, Unit* target, uint32 /*criteria_id*/) { + return OnCheck(source, target); + } + // deprecated/legacy + virtual bool OnCheck(Player* /*source*/, Unit* /*target*/) { return true; }; }; class PlayerScript : public ScriptObject @@ -838,9 +842,15 @@ class PlayerScript : public ScriptObject // Called when a player switches to a new zone virtual void OnUpdateZone(Player* /*player*/, uint32 /*newZone*/, uint32 /*newArea*/) { } + // Called when a player switches to a new area (more accurate than UpdateZone) + virtual void OnUpdateArea(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) { } + // Called when a player changes to a new map (after moving to new map) virtual void OnMapChanged(Player* /*player*/) { } + // Called before a player is being teleported to new coords + virtual bool OnBeforeTeleport(Player* /*player*/, uint32 /*mapid*/, float /*x*/, float /*y*/, float /*z*/, float /*orientation*/, uint32 /*options*/, Unit* /*target*/) { return true; } + // Called when team/faction is set on player virtual void OnUpdateFaction(Player* /*player*/) { } @@ -994,8 +1004,11 @@ class GlobalScript : public ScriptObject // items virtual void OnItemDelFromDB(SQLTransaction& /*trans*/, uint32 /*itemGuid*/) { } virtual void OnMirrorImageDisplayItem(const Item* /*item*/, uint32& /*display*/) { } - virtual void OnAfterRefCount(LootStoreItem* /*LootStoreItem*/, uint32& /*maxcount*/) { } - virtual void OnBeforeDropAddItem(Player const* /*player*/, Loot& /*loot*/, LootStoreItem* /*LootStoreItem*/) { } + + // loot + virtual void OnAfterRefCount(Player const* /*player*/, LootStoreItem* /*LootStoreItem*/, Loot& /*loot*/, bool /*canRate*/, uint16 /*lootMode*/, uint32& /*maxcount*/, LootStore const& /*store*/) { } + virtual void OnBeforeDropAddItem(Player const* /*player*/, Loot& /*loot*/, bool /*canRate*/, uint16 /*lootMode*/, LootStoreItem* /*LootStoreItem*/, LootStore const& /*store*/) { } + virtual void OnItemRoll(Player const* /*player*/, LootStoreItem const* /*LootStoreItem*/, float& /*chance*/, Loot& /*loot*/, LootStore const& /*store*/) { }; virtual void OnInitializeLockedDungeons(Player* /*player*/, uint8& /*level*/, uint32& /*lockData*/) { } virtual void OnAfterInitializeLockedDungeons(Player* /*player*/) { } @@ -1176,7 +1189,7 @@ class ScriptMgr public: /* AchievementCriteriaScript */ - bool OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target); + bool OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target, uint32 criteria_id); public: /* PlayerScript */ @@ -1210,6 +1223,8 @@ class ScriptMgr void OnPlayerDelete(uint64 guid); void OnPlayerBindToInstance(Player* player, Difficulty difficulty, uint32 mapid, bool permanent); void OnPlayerUpdateZone(Player* player, uint32 newZone, uint32 newArea); + void OnPlayerUpdateArea(Player* player, uint32 oldArea, uint32 newArea); + bool OnBeforePlayerTeleport(Player* player, uint32 mapid, float x, float y, float z, float orientation, uint32 options, Unit *target); void OnPlayerUpdateFaction(Player* player); void OnPlayerAddToBattleground(Player* player, Battleground* bg); void OnPlayerRemoveFromBattleground(Player* player, Battleground* bg); @@ -1264,8 +1279,9 @@ class ScriptMgr void OnGlobalItemDelFromDB(SQLTransaction& trans, uint32 itemGuid); void OnGlobalMirrorImageDisplayItem(const Item *item, uint32 &display); void OnBeforeUpdateArenaPoints(ArenaTeam* at, std::map<uint32, uint32> &ap); - void OnAfterRefCount(LootStoreItem* LootStoreItem, uint32 &maxcount); - void OnBeforeDropAddItem(Player const* player, Loot& loot, LootStoreItem* LootStoreItem); + void OnAfterRefCount(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, uint32 &maxcount, LootStore const& store); + void OnBeforeDropAddItem(Player const* player, Loot& loot, bool canRate, uint16 lootMode, LootStoreItem* LootStoreItem, LootStore const& store); + void OnItemRoll(Player const* player, LootStoreItem const* LootStoreItem, float &chance, Loot& loot, LootStore const& store); void OnInitializeLockedDungeons(Player* player, uint8& level, uint32& lockData); void OnAfterInitializeLockedDungeons(Player* player); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b0e436efb5..99759c7329 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1711,20 +1711,16 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app Unit* target = aurApp->GetTarget(); // no-phase is also phase state so same code for apply and remove - uint32 newPhase = 0; - Unit::AuraEffectList const& phases = target->GetAuraEffectsByType(SPELL_AURA_PHASE); - if (!phases.empty()) - for (Unit::AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - newPhase |= (*itr)->GetMiscValue(); + uint32 newPhase = target->GetPhaseByAuras(); if (Player* player = target->ToPlayer()) { if (!newPhase) newPhase = PHASEMASK_NORMAL; - // GM-mode have mask 0xFFFFFFFF + // do not change phase to GM with all phases enabled if (player->IsGameMaster()) - newPhase = 0xFFFFFFFF; + newPhase = PHASEMASK_ANYWHERE; player->SetPhaseMask(newPhase, false); player->GetSession()->SendSetPhaseShift(newPhase); @@ -1769,7 +1765,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mode, bool apply) const { - if (!(mode & AURA_EFFECT_HANDLE_REAL)) + if (!(mode & AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK)) return; Unit* target = aurApp->GetTarget(); @@ -3582,6 +3578,9 @@ void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 switch (GetId()) { + case 46924: // BladeStorm + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + break; case 34471: // The Beast Within case 19574: // Bestial Wrath mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index d1736893f3..c50ecc2bc0 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -395,7 +395,7 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owne Aura::Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, uint64 casterGUID) : m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID()), -m_castItemGuid(castItem ? castItem->GetGUID() : 0), m_applyTime(time(NULL)), +m_castItemGuid(castItem ? castItem->GetGUID() : 0),m_castItemEntry(castItem ? castItem->GetEntry() : 0), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false) diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 30f25dae9b..1587f9fadf 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -96,6 +96,7 @@ class Aura uint32 GetId() const{ return GetSpellInfo()->Id; } uint64 GetCastItemGUID() const { return m_castItemGuid; } + uint32 GetCastItemEntry() const { return m_castItemEntry; } uint64 GetCasterGUID() const { return m_casterGuid; } Unit* GetCaster() const; WorldObject* GetOwner() const { return m_owner; } @@ -235,6 +236,7 @@ class Aura SpellInfo const* const m_spellInfo; uint64 const m_casterGuid; uint64 const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted + uint32 const m_castItemEntry; // when deleted, we could retrieve some information from template instead time_t const m_applyTime; WorldObject* const m_owner; // diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f1aa91af71..8bf57153b9 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -287,6 +287,16 @@ Corpse* SpellCastTargets::GetCorpseTarget() const return NULL; } +void SpellCastTargets::SetCorpseTarget(Corpse* target) +{ + if (!target) + return; + + m_objectTarget = target; + m_objectTargetGUID = target->GetGUID(); + m_targetMask |= TARGET_FLAG_CORPSE_MASK; +} + WorldObject* SpellCastTargets::GetObjectTarget() const { return m_objectTarget; @@ -1306,7 +1316,8 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis; float x, y, z, angle; angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f); - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle); + //m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle); this contains extra code that breaks fishing + m_caster->GetNearPoint(m_caster, x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, m_caster->GetOrientation() + angle); float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z, true, 120.0f); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; @@ -2395,6 +2406,23 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= // Increase time interval for reflected spells by 1.5 m_caster->m_Events.AddEvent(new ReflectEvent(m_caster->GetGUID(), targetInfo.targetGUID, m_spellInfo), m_caster->m_Events.CalculateTime(targetInfo.timeDelay)); targetInfo.timeDelay += targetInfo.timeDelay >> 1; + + // HACK: workaround check for succubus seduction case + // TODO: seduction should be casted only on humanoids (not demons) + if (m_caster->IsPet()) + { + CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(m_caster->GetEntry()); + switch (ci->family) + { + case CREATURE_FAMILY_SUCCUBUS: + { + if (m_spellInfo->SpellIconID != 694) // Soothing Kiss + cancel(); + } + break; + return; + } + } } else targetInfo.reflectResult = SPELL_MISS_NONE; @@ -4545,14 +4573,14 @@ void Spell::WriteAmmoToPacket(WorldPacket* data) { if (uint32 item_id = m_caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i)) { - if (ItemEntry const* itemEntry = sItemStore.LookupEntry(item_id)) + if (ItemTemplate const* itemEntry = sObjectMgr->GetItemTemplate(item_id)) { if (itemEntry->Class == ITEM_CLASS_WEAPON) { switch (itemEntry->SubClass) { case ITEM_SUBCLASS_WEAPON_THROWN: - ammoDisplayID = itemEntry->DisplayId; + ammoDisplayID = itemEntry->DisplayInfoID; ammoInventoryType = itemEntry->InventoryType; break; case ITEM_SUBCLASS_WEAPON_BOW: @@ -5788,7 +5816,7 @@ SpellCastResult Spell::CheckCast(bool strict) m_pathFinder = new PathGenerator(m_caster); m_pathFinder->CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ+0.15f, false); G3D::Vector3 endPos = m_pathFinder->GetEndPosition(); // also check distance between target and the point calculated by mmaps - if (m_pathFinder->GetPathType()&PATHFIND_NOPATH || target->GetExactDistSq(endPos.x, endPos.y, endPos.z) > maxdist*maxdist || m_pathFinder->getPathLength() > (40.0f + (m_caster->HasAura(58097) ? 5.0f : 0.0f))) + if (m_pathFinder->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE) || target->GetExactDistSq(endPos.x, endPos.y, endPos.z) > maxdist*maxdist || m_pathFinder->getPathLength() > (40.0f + (m_caster->HasAura(58097) ? 5.0f : 0.0f))) return SPELL_FAILED_NOPATH; } break; @@ -6200,7 +6228,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_originalCaster && m_originalCaster->GetTypeId() == TYPEID_PLAYER && m_originalCaster->IsAlive()) { Battlefield* Bf = sBattlefieldMgr->GetBattlefieldToZoneId(m_originalCaster->GetZoneId()); - if (AreaTableEntry const* pArea = GetAreaEntryByAreaID(m_originalCaster->GetAreaId())) + if (AreaTableEntry const* pArea = sAreaTableStore.LookupEntry(m_originalCaster->GetAreaId())) if ((pArea->flags & AREA_FLAG_NO_FLY_ZONE) || (Bf && !Bf->CanFlyIn())) return SPELL_FAILED_NOT_HERE; } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index dd1241ea10..880bb1fdc8 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -107,6 +107,7 @@ class SpellCastTargets uint64 GetCorpseTargetGUID() const; Corpse* GetCorpseTarget() const; + void SetCorpseTarget(Corpse* target); WorldObject* GetObjectTarget() const; uint64 GetObjectTargetGUID() const; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 547a713c4d..4ec091f78a 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3218,7 +3218,7 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/) return; // xinef: Hand of Reckoning, cast before checing canhavethreatlist. fixes damage against pets - if (m_spellInfo->Id == 62124 && unitTarget->GetVictim() != m_caster && !unitTarget->IsTotem()) + if (m_spellInfo->Id == 62124 && unitTarget->GetVictim() != m_caster) m_caster->CastSpell(unitTarget, 67485, true); // this effect use before aura Taunt apply for prevent taunt already attacking target @@ -4241,14 +4241,14 @@ void Spell::EffectDuel(SpellEffIndex effIndex) return; // Players can only fight a duel in zones with this flag - AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetAreaId()); + AreaTableEntry const* casterAreaEntry = sAreaTableStore.LookupEntry(caster->GetAreaId()); if (casterAreaEntry && !(casterAreaEntry->flags & AREA_FLAG_ALLOW_DUELS)) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here return; } - AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetAreaId()); + AreaTableEntry const* targetAreaEntry = sAreaTableStore.LookupEntry(target->GetAreaId()); if (targetAreaEntry && !(targetAreaEntry->flags & AREA_FLAG_ALLOW_DUELS)) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 098b5af9c6..d8dbd3aa8f 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1069,7 +1069,7 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 if (!player) return false; - AreaTableEntry const* pArea = GetAreaEntryByAreaID(player->GetAreaId()); + AreaTableEntry const* pArea = sAreaTableStore.LookupEntry(player->GetAreaId()); if (!(pArea && pArea->flags & AREA_FLAG_NO_FLY_ZONE)) return false; if (!player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !player->HasAuraType(SPELL_AURA_FLY)) @@ -2513,7 +2513,7 @@ void SpellMgr::LoadSpellAreas() } } - if (spellArea.areaId && !GetAreaEntryByAreaID(spellArea.areaId)) + if (spellArea.areaId && !sAreaTableStore.LookupEntry(spellArea.areaId)) { sLog->outErrorDb("Spell %u listed in `spell_area` have wrong area (%u) requirement", spell, spellArea.areaId); continue; @@ -6243,8 +6243,8 @@ void SpellMgr::LoadDbcDataCorrections() } // Xinef: The Veiled Sea area in outlands (Draenei zone), client blocks casting flying mounts - for (uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) - if (AreaTableEntry* areaEntry = const_cast<AreaTableEntry*>(sAreaStore.LookupEntry(i))) + for (uint32 i = 0; i < sAreaTableStore.GetNumRows(); ++i) + if (AreaTableEntry* areaEntry = const_cast<AreaTableEntry*>(sAreaTableStore.LookupEntry(i))) { if (areaEntry->ID == 3479) areaEntry->flags |= AREA_FLAG_NO_FLY_ZONE; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index e7cdd9aa35..3ec460da9e 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -75,6 +75,7 @@ #include "WhoListCache.h" #include "AsyncAuctionListing.h" #include "SavingSystem.h" +#include <VMapManager2.h> ACE_Atomic_Op<ACE_Thread_Mutex, bool> World::m_stopEvent = false; uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; @@ -909,6 +910,12 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_UPTIME_UPDATE] = 1; } + if (reload) + { + m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS); + m_timers[WUPDATE_UPTIME].Reset(); + } + // log db cleanup interval m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = sConfigMgr->GetIntDefault("LogDB.Opt.ClearInterval", 10); if (int32(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]) <= 0) @@ -1218,9 +1225,6 @@ void World::LoadConfigSettings(bool reload) // Dungeon finder m_int_configs[CONFIG_LFG_OPTIONSMASK] = sConfigMgr->GetIntDefault("DungeonFinder.OptionsMask", 3); - // DBC_ItemAttributes - m_bool_configs[CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES] = sConfigMgr->GetBoolDefault("DBC.EnforceItemAttributes", true); - // Max instances per hour m_int_configs[CONFIG_MAX_INSTANCES_PER_HOUR] = sConfigMgr->GetIntDefault("AccountInstancesPerHour", 5); @@ -1276,6 +1280,12 @@ void World::SetInitialWorldSettings() sLog->outString("Initializing Scripts..."); sScriptMgr->Initialize(); + ///- Initialize VMapManager function pointers (to untangle game/collision circular deps) + if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager())) + { + vmmgr2->GetLiquidFlagsPtr = &GetLiquidFlags; + } + ///- Initialize config settings LoadConfigSettings(); @@ -1520,7 +1530,8 @@ void World::SetInitialWorldSettings() sPoolMgr->LoadFromDB(); sLog->outString("Loading Game Event Data..."); // must be after loading pools fully - sGameEventMgr->LoadFromDB(); + sGameEventMgr->LoadHolidayDates(); // Must be after loading DBC + sGameEventMgr->LoadFromDB(); // Must be after loading holiday dates sLog->outString("Loading UNIT_NPC_FLAG_SPELLCLICK Data..."); // must be after LoadQuests sObjectMgr->LoadNPCSpellClickSpells(); @@ -1752,11 +1763,16 @@ void World::SetInitialWorldSettings() m_gameTime = time(NULL); m_startTime = m_gameTime; + LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')", + realmID, uint32(m_startTime), _FULLVERSION); // One-time query + m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetCurrent(MINUTE*IN_MILLISECONDS); + m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS); + //Update "uptime" table based on configuration entry in minutes. m_timers[WUPDATE_CORPSES].SetInterval(20 * MINUTE * IN_MILLISECONDS); //erase corpses every 20 minutes @@ -2077,7 +2093,25 @@ void World::Update(uint32 diff) // execute callbacks from sql queries that were queued recently ProcessQueryCallbacks(); - + + /// <li> Update uptime table + if (m_timers[WUPDATE_UPTIME].Passed()) + { + uint32 tmpDiff = uint32(m_gameTime - m_startTime); + uint32 maxOnlinePlayers = GetMaxPlayerCount(); + + m_timers[WUPDATE_UPTIME].Reset(); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_UPTIME_PLAYERS); + + stmt->setUInt32(0, tmpDiff); + stmt->setUInt16(1, uint16(maxOnlinePlayers)); + stmt->setUInt32(2, realmID); + stmt->setUInt32(3, uint32(m_startTime)); + + LoginDatabase.Execute(stmt); + } + ///- Erase corpses once every 20 minutes if (m_timers[WUPDATE_CORPSES].Passed()) { @@ -2765,6 +2799,7 @@ void World::UpdateRealmCharCount(uint32 accountId) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_COUNT); stmt->setUInt32(0, accountId); + stmt->setUInt32(1, accountId); PreparedQueryResultFuture result = CharacterDatabase.AsyncQuery(stmt); m_realmCharCallbacks.insert(result); } diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 96eecf073d..6408e0d2dd 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -60,6 +60,7 @@ enum WorldTimers { WUPDATE_AUCTIONS, WUPDATE_WEATHERS, + WUPDATE_UPTIME, WUPDATE_CORPSES, WUPDATE_EVENTS, WUPDATE_CLEANDB, @@ -147,7 +148,6 @@ enum WorldBoolConfigs CONFIG_AUTOBROADCAST, CONFIG_ALLOW_TICKETS, CONFIG_DELETE_CHARACTER_TICKET_TRACE, - CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES, CONFIG_PRESERVE_CUSTOM_CHANNELS, CONFIG_WINTERGRASP_ENABLE, CONFIG_PDUMP_NO_PATHS, diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 6804d939fe..a3373a007d 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -78,8 +78,8 @@ message("") include_directories( ${scripts_INCLUDE_DIRS} ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Recast + ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Detour/Include + ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Recast/Include ${CMAKE_SOURCE_DIR}/deps/g3dlite/include ${CMAKE_SOURCE_DIR}/deps/SFMT ${CMAKE_SOURCE_DIR}/deps/zlib diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index 6b9bb2a892..f1e5aa4932 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -31,6 +31,7 @@ set(scripts_STAT_SRCS Commands/cs_lookup.cpp Commands/cs_message.cpp Commands/cs_misc.cpp + Commands/cs_mmaps.cpp Commands/cs_modify.cpp Commands/cs_npc.cpp Commands/cs_quest.cpp diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 9268272d2d..0967aa170d 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -191,14 +191,10 @@ public: return false; } - const uint32 VISUAL_AURA = 37800; std::string param = (char*)args; if (param == "on") { - if (_player->HasAura(VISUAL_AURA, 0)) - _player->RemoveAurasDueToSpell(VISUAL_AURA); - _player->SetGMVisible(true); //_player->UpdateObjectVisibility(); handler->GetSession()->SendNotification(LANG_INVISIBLE_VISIBLE); @@ -208,7 +204,6 @@ public: if (param == "off") { - _player->AddAura(VISUAL_AURA, _player); _player->SetGMVisible(false); //_player->UpdateObjectVisibility(); handler->GetSession()->SendNotification(LANG_INVISIBLE_INVISIBLE); diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 66a7d5f306..4a6235ddee 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -417,7 +417,7 @@ public: uint32 areaId = id ? (uint32)atoi(id) : player->GetZoneId(); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); if (x < 0 || x > 100 || y < 0 || y > 100 || !areaEntry) { @@ -427,7 +427,7 @@ public: } // update to parent zone if exist (client map show only zones without parents) - AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; + AreaTableEntry const* zoneEntry = areaEntry->zone ? sAreaTableStore.LookupEntry(areaEntry->zone) : areaEntry; Map const* map = sMapMgr->CreateBaseMap(zoneEntry->mapid); diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index cdfc508d85..9d1c34c5a1 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -548,6 +548,7 @@ public: stmt->setFloat(5, player->GetPositionY()); stmt->setFloat(6, player->GetPositionZ()); stmt->setFloat(7, distance * distance); + stmt->setFloat(8, player->GetPhaseMask()); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index d81ce581da..60f5ce165c 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -86,9 +86,9 @@ public: wstrToLower(wNamePart); // Search in AreaTable.dbc - for (uint32 areaflag = 0; areaflag < sAreaStore.GetNumRows(); ++areaflag) + for (uint32 i = 0; i < sAreaTableStore.GetNumRows(); ++i) { - AreaTableEntry const* areaEntry = sAreaStore.LookupEntry(areaflag); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(i); if (areaEntry) { int locale = handler->GetSessionDbcLocale(); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 058290c9e3..268248f5bb 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -400,8 +400,8 @@ public: object->GetZoneAndAreaId(zoneId, areaId); MapEntry const* mapEntry = sMapStore.LookupEntry(object->GetMapId()); - AreaTableEntry const* zoneEntry = GetAreaEntryByAreaID(zoneId); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(areaId); + AreaTableEntry const* zoneEntry = sAreaTableStore.LookupEntry(zoneId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); float zoneX = object->GetPositionX(); float zoneY = object->GetPositionY(); @@ -612,8 +612,8 @@ public: else _player->SaveRecallPosition(); - _player->TeleportTo(target->GetMapId(), target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+0.25f, _player->GetOrientation(), TELE_TO_GM_MODE); - _player->SetPhaseMask(target->GetPhaseMask() | 1, false); + if (_player->TeleportTo(target->GetMapId(), target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+0.25f, _player->GetOrientation(), TELE_TO_GM_MODE, target)) + _player->SetPhaseMask(target->GetPhaseMask() | 1, false); } else { @@ -734,8 +734,8 @@ public: // before GM float x, y, z; handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, target->GetObjectSize()); - target->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation()); - target->SetPhaseMask(handler->GetSession()->GetPlayer()->GetPhaseMask(), false); + if (target->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, target->GetOrientation(), 0, handler->GetSession()->GetPlayer())) + target->SetPhaseMask(handler->GetSession()->GetPlayer()->GetPhaseMask(), false); } else { @@ -845,7 +845,7 @@ public: // before GM float x, y, z; handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, player->GetObjectSize()); - player->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, player->GetOrientation()); + player->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, player->GetOrientation(), 0, handler->GetSession()->GetPlayer()); } return true; @@ -1280,7 +1280,7 @@ public: uint32 zoneId = player->GetZoneId(); - AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(zoneId); + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId); if (!areaEntry || areaEntry->zone !=0) { handler->PSendSysMessage(LANG_COMMAND_GRAVEYARDWRONGZONE, graveyardId, zoneId); @@ -1411,17 +1411,23 @@ public: return false; } - int32 area = GetAreaFlagByAreaID(atoi((char*)args)); - int32 offset = area / 32; - uint32 val = uint32((1 << (area % 32))); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(atoi(args)); + if (!area) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } - if (area<0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + int32 offset = area->exploreFlag / 32; + if (offset >= PLAYER_EXPLORED_ZONES_SIZE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } + uint32 val = uint32((1 << (area->exploreFlag % 32))); uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields | val))); @@ -1442,17 +1448,23 @@ public: return false; } - int32 area = GetAreaFlagByAreaID(atoi((char*)args)); - int32 offset = area / 32; - uint32 val = uint32((1 << (area % 32))); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(atoi(args)); + if (!area) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } - if (area < 0 || offset >= PLAYER_EXPLORED_ZONES_SIZE) + int32 offset = area->exploreFlag / 32; + if (offset >= PLAYER_EXPLORED_ZONES_SIZE) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } + uint32 val = uint32((1 << (area->exploreFlag % 32))); uint32 currFields = playerTarget->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset); playerTarget->SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, uint32((currFields ^ val))); @@ -2025,12 +2037,12 @@ public: MapEntry const* map = sMapStore.LookupEntry(mapId); - AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId); if (area) { areaName = area->area_name[locale]; - AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(area->zone); if (zone) zoneName = zone->area_name[locale]; } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 075eae219c..928569fbc7 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -668,6 +668,7 @@ public: stmt->setFloat(5, player->GetPositionY()); stmt->setFloat(6, player->GetPositionZ()); stmt->setFloat(7, distance * distance); + stmt->setFloat(8, player->GetPhaseMask()); PreparedQueryResult result = WorldDatabase.Query(stmt); if (result) diff --git a/src/server/scripts/Custom/README.md b/src/server/scripts/Custom/README.md index 7b9e83d4e0..05944b8706 100644 --- a/src/server/scripts/Custom/README.md +++ b/src/server/scripts/Custom/README.md @@ -6,14 +6,20 @@ They will be git-ignored Remember to use cmake macro inside your CMakeLists.txt to correctly add scripts to project solution. -BTW, **We strongly suggest you** to use our module system to create your custom + + +/!\ BTW, **We strongly suggest you** to use our module system to create your custom powerful module instead of simple scripts. ----------------- -CMakeLists.txt example: +How to: + +1) Create a CMakeLists.txt in this directory + +Example (everything below is needed, just replace with your scripts' names): set(scripts_STAT_SRCS ${scripts_STAT_SRCS} @@ -24,3 +30,8 @@ set(scripts_STAT_SRCS AC_ADD_SCRIPT_LOADER("Custom" "ScriptLoader.h") message(" -> Prepared: My custom scripts") + + +2) Add them to ../ScriptLoader.cpp + +Open the file and go at the end of the file to know what to edit. diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h index fd073b5a74..4073401b96 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h @@ -110,4 +110,9 @@ enum GameObjectsIds GO_UROK_PILE = 175621, }; +enum npcspells +{ + SPELL_FINKLE_IS_EINHORN = 16710 +}; + #endif diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp index 751f58635b..98bd6fbec6 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp @@ -67,6 +67,19 @@ public: memset(go_emberseerrunes, 0, sizeof(go_emberseerrunes)); } + void CreatureLooted(Creature* creature, LootType loot) + { + switch (creature->GetEntry()) + { + case NPC_THE_BEAST: + if (loot == LOOT_SKINNING) + { + creature->CastSpell(creature, SPELL_FINKLE_IS_EINHORN, true); + } + break; + } + } + void OnCreatureCreate(Creature* creature) { switch (creature->GetEntry()) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp index 3c279ba2f7..5b44d39437 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp @@ -61,6 +61,17 @@ class boss_golemagg : public CreatureScript { BossAI::EnterCombat(victim); events.ScheduleEvent(EVENT_PYROBLAST, 7000); + + // The two ragers should join the fight alongside me against my foes. + std::list<Creature *> ragers; + me->GetCreaturesWithEntryInRange(ragers, 100, NPC_CORE_RAGER); + for (Creature * i : ragers) + { + if (i && i->IsAlive() && !i->IsInCombat()) + { + i->AI()->AttackStart(victim); + } + } } void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType, SpellSchoolMask) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp index 1b515591c7..0908b5b107 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp @@ -4,12 +4,12 @@ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> */ -/* ScriptData -SDName: Boss_Magmadar -SD%Complete: 75 -SDComment: Conflag on ground nyi -SDCategory: Molten Core -EndScriptData */ + /* ScriptData + SDName: Boss_Magmadar + SD%Complete: 75 + SDComment: Conflag on ground nyi + SDCategory: Molten Core + EndScriptData */ #include "ObjectMgr.h" #include "ScriptMgr.h" @@ -18,93 +18,229 @@ EndScriptData */ enum Texts { - EMOTE_FRENZY = 0 + EMOTE_FRENZY = 0, + EMOTE_SMOLDERING = 0, + EMOTE_IGNITE = 1, }; enum Spells { - SPELL_FRENZY = 19451, - SPELL_MAGMA_SPIT = 19449, - SPELL_PANIC = 19408, - SPELL_LAVA_BOMB = 19428, + SPELL_FRENZY = 19451, + SPELL_MAGMA_SPIT = 19449, + SPELL_PANIC = 19408, + SPELL_LAVA_BOMB = 19428, + SPELL_SERRATED_BITE = 19771, }; enum Events { - EVENT_FRENZY = 1, - EVENT_PANIC = 2, - EVENT_LAVA_BOMB = 3, + EVENT_FRENZY = 1, + EVENT_PANIC = 2, + EVENT_LAVA_BOMB = 3, + EVENT_SERRATED_BITE = 1, + EVENT_IGNITE = 2, }; class boss_magmadar : public CreatureScript { - public: - boss_magmadar() : CreatureScript("boss_magmadar") { } +public: + boss_magmadar() : CreatureScript("boss_magmadar") { } - struct boss_magmadarAI : public BossAI + struct boss_magmadarAI : public BossAI + { + boss_magmadarAI(Creature* creature) : BossAI(creature, BOSS_MAGMADAR) { - boss_magmadarAI(Creature* creature) : BossAI(creature, BOSS_MAGMADAR) - { - } + } + + void Reset() + { + BossAI::Reset(); + DoCast(me, SPELL_MAGMA_SPIT, true); + } + + void EnterCombat(Unit* victim) + { + BossAI::EnterCombat(victim); + events.ScheduleEvent(EVENT_FRENZY, 30000); + events.ScheduleEvent(EVENT_PANIC, 20000); + events.ScheduleEvent(EVENT_LAVA_BOMB, 12000); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); - void Reset() + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - BossAI::Reset(); - DoCast(me, SPELL_MAGMA_SPIT, true); + switch (eventId) + { + case EVENT_FRENZY: + Talk(EMOTE_FRENZY); + DoCast(me, SPELL_FRENZY); + events.ScheduleEvent(EVENT_FRENZY, 15000); + break; + case EVENT_PANIC: + DoCastVictim(SPELL_PANIC); + events.ScheduleEvent(EVENT_PANIC, 35000); + break; + case EVENT_LAVA_BOMB: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LAVA_BOMB)) + DoCast(target, SPELL_LAVA_BOMB); + events.ScheduleEvent(EVENT_LAVA_BOMB, 12000); + break; + default: + break; + } } - void EnterCombat(Unit* victim) + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_magmadarAI(creature); + } +}; + +// Serrated Bites timer may be wrong +class npc_magmadar_core_hound : public CreatureScript +{ +public: + npc_magmadar_core_hound() : CreatureScript("npc_magmadar_core_hound") { } + + struct npc_magmadar_core_houndAI : public CreatureAI + { + npc_magmadar_core_houndAI(Creature* creature) : CreatureAI(creature) + { + } + + EventMap events; + std::list<Creature *> hounds; + bool smoldering = false; + Unit* killer; + + void removeFeignDeath() { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); + me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT); + me->ClearUnitState(UNIT_STATE_DIED); + me->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + me->DisableRotate(false); + } + + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) + { + if (me->HealthBelowPctDamaged(0, damage)) { - BossAI::EnterCombat(victim); - events.ScheduleEvent(EVENT_FRENZY, 30000); - events.ScheduleEvent(EVENT_PANIC, 20000); - events.ScheduleEvent(EVENT_LAVA_BOMB, 12000); + if (!smoldering) + { + killer = attacker; + events.ScheduleEvent(EVENT_IGNITE, 10000); + me->SetHealth(1); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); + me->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->AddUnitMovementFlag(MOVEMENTFLAG_ROOT); + me->AddUnitState(UNIT_STATE_DIED); + me->AddUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + me->DisableRotate(true); + Talk(EMOTE_SMOLDERING); + } + damage = 0; + smoldering = true; } + } - void UpdateAI(uint32 diff) - { - if (!UpdateVictim()) - return; + void Reset() { + removeFeignDeath(); + } + + void JustDied(Unit* /*killer*/) { + removeFeignDeath(); + } - events.Update(diff); + void EnterCombat(Unit* /*victim*/) + { + events.ScheduleEvent(EVENT_SERRATED_BITE, 10000); // timer may be wrong + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim() && !smoldering) + return; - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) + case EVENT_SERRATED_BITE: + if (UpdateVictim() && !smoldering) { + DoCast(me->GetVictim(), SPELL_SERRATED_BITE); + events.ScheduleEvent(EVENT_SERRATED_BITE, 10000); // again, timer may be wrong + } + break; + case EVENT_IGNITE: + smoldering = false; + me->GetCreaturesWithEntryInRange(hounds, 80, NPC_CORE_HOUND); + for (Creature * i : hounds) { - case EVENT_FRENZY: - Talk(EMOTE_FRENZY); - DoCast(me, SPELL_FRENZY); - events.ScheduleEvent(EVENT_FRENZY, 15000); - break; - case EVENT_PANIC: - DoCastVictim(SPELL_PANIC); - events.ScheduleEvent(EVENT_PANIC, 35000); - break; - case EVENT_LAVA_BOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LAVA_BOMB)) - DoCast(target, SPELL_LAVA_BOMB); - events.ScheduleEvent(EVENT_LAVA_BOMB, 12000); - break; - default: - break; + if (i && i->IsAlive() && i->IsInCombat() && !i->HasUnitState(UNIT_STATE_DIED)) + { + Talk(EMOTE_IGNITE); + me->SetFullHealth(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); + me->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT); + me->ClearUnitState(UNIT_STATE_DIED); + me->ClearUnitState(UNIT_STATE_CANNOT_AUTOATTACK); + me->DisableRotate(false); + me->AI()->AttackStart(i->GetVictim()); + return; + } } + if (me->HasUnitState(UNIT_STATE_DIED)) + { + if (killer) + { + me->Kill(killer, me); + } + else + { + me->Kill(me, me); + } + } + break; + default: + break; } - - DoMeleeAttackIfReady(); } - }; - CreatureAI* GetAI(Creature* creature) const - { - return new boss_magmadarAI(creature); + DoMeleeAttackIfReady(); } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_magmadar_core_houndAI(creature); + } }; void AddSC_boss_magmadar() { new boss_magmadar(); + new npc_magmadar_core_hound(); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp index 357ea5dd7d..ebf5aa3a2d 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp @@ -80,6 +80,8 @@ class boss_majordomo : public CreatureScript events.ScheduleEvent(EVENT_DAMAGE_REFLECTION, 15000); events.ScheduleEvent(EVENT_BLAST_WAVE, 10000); events.ScheduleEvent(EVENT_TELEPORT, 20000); + // Call every flamewaker around him + me->CallForHelp(30); } void UpdateAI(uint32 diff) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index c4c415b9af..dceeab6c86 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -61,6 +61,7 @@ enum Events EVENT_INTRO_5 = 12 }; + class boss_ragnaros : public CreatureScript { public: @@ -83,6 +84,7 @@ class boss_ragnaros : public CreatureScript _hasSubmergedOnce = false; _isBanished = false; me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); + me->SetOrientation(0.8f); } void EnterCombat(Unit* victim) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp index c97684c65a..8b0fba3cc9 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp @@ -20,15 +20,15 @@ EndScriptData */ Position const SummonPositions[10] = { - {737.850f, -1145.35f, -120.288f, 4.71368f}, - {744.162f, -1151.63f, -119.726f, 4.58204f}, - {751.247f, -1152.82f, -119.744f, 4.49673f}, - {759.206f, -1155.09f, -120.051f, 4.30104f}, - {755.973f, -1152.33f, -120.029f, 4.25588f}, - {731.712f, -1147.56f, -120.195f, 4.95955f}, - {726.499f, -1149.80f, -120.156f, 5.24055f}, - {722.408f, -1152.41f, -120.029f, 5.33087f}, - {718.994f, -1156.36f, -119.805f, 5.75738f}, + {759.542f, -1173.43f, -118.974f, 3.3048f}, + {761.652f, -1164.30f, -119.533f, 3.3919f}, + {747.323f, -1149.24f, -120.060f, 3.6629f}, + {766.734f, -1183.16f, -119.292f, 2.9889f}, + {757.364f, -1198.31f, -118.652f, 2.3095f}, + {752.349f, -1159.19f, -119.261f, 3.6032f}, + {738.015f, -1152.22f, -119.512f, 4.0792f}, + {757.246f, -1189.79f, -118.633f, 2.5333f}, + {745.916f, -1199.35f, -118.119f, 1.8932f}, {838.510f, -829.840f, -232.000f, 2.00000f}, }; @@ -45,29 +45,17 @@ class instance_molten_core : public InstanceMapScript _golemaggTheIncineratorGUID = 0; _majordomoExecutusGUID = 0; _cacheOfTheFirelordGUID = 0; - _executusSchedule = NULL; _deadBossCount = 0; _ragnarosAddDeaths = 0; - _isLoading = false; - _summonedExecutus = false; } - ~instance_molten_core_InstanceMapScript() + void OnPlayerEnter(Player* /*player*/) override { - delete _executusSchedule; + if (CheckMajordomoExecutus()) + SummonMajordomoExecutus(); } - void OnPlayerEnter(Player* /*player*/) - { - if (_executusSchedule) - { - SummonMajordomoExecutus(*_executusSchedule); - delete _executusSchedule; - _executusSchedule = NULL; - } - } - - void OnCreatureCreate(Creature* creature) + void OnCreatureCreate(Creature* creature) override { switch (creature->GetEntry()) { @@ -82,19 +70,40 @@ class instance_molten_core : public InstanceMapScript } } - void OnGameObjectCreate(GameObject* go) + void OnGameObjectCreate(GameObject* go) override { switch (go->GetEntry()) { case GO_CACHE_OF_THE_FIRELORD: _cacheOfTheFirelordGUID = go->GetGUID(); break; + case GO_CIRCLE_BARON: + _circlesGUIDs[5] = go->GetGUID(); + break; + case GO_CIRCLE_GARR: + _circlesGUIDs[3] = go->GetGUID(); + break; + case GO_CIRCLE_GEHENNAS: + _circlesGUIDs[2] = go->GetGUID(); + break; + case GO_CIRCLE_GOLEMAGG: + _circlesGUIDs[7] = go->GetGUID(); + break; + case GO_CIRCLE_MAGMADAR: + _circlesGUIDs[1] = go->GetGUID(); + break; + case GO_CIRCLE_SHAZZRAH: + _circlesGUIDs[4] = go->GetGUID(); + break; + case GO_CIRCLE_SULFURON: + _circlesGUIDs[6] = go->GetGUID(); + break; default: break; } } - void SetData(uint32 type, uint32 data) + void SetData(uint32 type, uint32 data) override { if (type == DATA_RAGNAROS_ADDS) { @@ -105,7 +114,7 @@ class instance_molten_core : public InstanceMapScript } } - uint32 GetData(uint32 type) const + uint32 GetData(uint32 type) const override { switch (type) { @@ -116,7 +125,7 @@ class instance_molten_core : public InstanceMapScript return 0; } - uint64 GetData64(uint32 type) const + uint64 GetData64(uint32 type) const override { switch (type) { @@ -129,33 +138,28 @@ class instance_molten_core : public InstanceMapScript return 0; } - bool SetBossState(uint32 bossId, EncounterState state) + bool SetBossState(uint32 bossId, EncounterState state) override { if (!InstanceScript::SetBossState(bossId, state)) return false; - + if (state == DONE && bossId < BOSS_MAJORDOMO_EXECUTUS) - ++_deadBossCount; - - if (_isLoading) - return true; - - if (_deadBossCount == 8) - SummonMajordomoExecutus(false); - - if (bossId == BOSS_MAJORDOMO_EXECUTUS && state == DONE) + if (CheckMajordomoExecutus()) + SummonMajordomoExecutus(); + + if (bossId == BOSS_MAJORDOMO_EXECUTUS && state == DONE) { DoRespawnGameObject(_cacheOfTheFirelordGUID, 7 * DAY); + } return true; } - void SummonMajordomoExecutus(bool done) + void SummonMajordomoExecutus() { - if (_summonedExecutus) + if (_majordomoExecutusGUID) return; - _summonedExecutus = true; - if (!done) + if (GetBossState(BOSS_MAJORDOMO_EXECUTUS) != DONE) { instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, SummonPositions[0]); instance->SummonCreature(NPC_FLAMEWAKER_HEALER, SummonPositions[1]); @@ -168,10 +172,22 @@ class instance_molten_core : public InstanceMapScript instance->SummonCreature(NPC_FLAMEWAKER_ELITE, SummonPositions[8]); } else if (TempSummon* summon = instance->SummonCreature(NPC_MAJORDOMO_EXECUTUS, RagnarosTelePos)) - summon->AI()->DoAction(ACTION_START_RAGNAROS_ALT); + summon->AI()->DoAction(ACTION_START_RAGNAROS_ALT); } - std::string GetSaveData() + bool CheckMajordomoExecutus() const + { + if (GetBossState(BOSS_RAGNAROS) == DONE) + return false; + + for (uint8 i = 0; i < BOSS_MAJORDOMO_EXECUTUS; ++i) + if (GetBossState(i) != DONE) + return false; + + return true; + } + + std::string GetSaveData() override { OUT_SAVE_INST_DATA; @@ -182,7 +198,7 @@ class instance_molten_core : public InstanceMapScript return saveStream.str(); } - void Load(char const* data) + void Load(char const* data) override { if (!data) { @@ -190,7 +206,6 @@ class instance_molten_core : public InstanceMapScript return; } - _isLoading = true; OUT_LOAD_INST_DATA(data); char dataHead1, dataHead2; @@ -200,44 +215,32 @@ class instance_molten_core : public InstanceMapScript if (dataHead1 == 'M' && dataHead2 == 'C') { - EncounterState states[MAX_ENCOUNTER]; - uint8 executusCounter = 0; - - // need 2 loops to check spawning executus/ragnaros for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) { uint32 tmpState; loadStream >> tmpState; if (tmpState == IN_PROGRESS || tmpState > TO_BE_DECIDED) tmpState = NOT_STARTED; - states[i] = EncounterState(tmpState); - - if (tmpState == DONE && i < BOSS_MAJORDOMO_EXECUTUS) - ++executusCounter; - } - if (executusCounter >= 8 && states[BOSS_RAGNAROS] != DONE) - _executusSchedule = new bool(states[BOSS_MAJORDOMO_EXECUTUS] == DONE); + SetBossState(i, EncounterState(tmpState)); + } - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - SetBossState(i, states[i]); + if (CheckMajordomoExecutus()) + SummonMajordomoExecutus(); } else OUT_LOAD_INST_DATA_FAIL; OUT_LOAD_INST_DATA_COMPLETE; - _isLoading = false; } private: uint64 _golemaggTheIncineratorGUID; uint64 _majordomoExecutusGUID; uint64 _cacheOfTheFirelordGUID; - bool* _executusSchedule; uint8 _deadBossCount; uint8 _ragnarosAddDeaths; - bool _isLoading; - bool _summonedExecutus; + std::unordered_map<uint8, uint64> _circlesGUIDs; }; InstanceScript* GetInstanceScript(InstanceMap* map) const diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h index 4c2f6ca393..ae4531435d 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h @@ -47,11 +47,20 @@ enum Creatures NPC_RAGNAROS = 11502, NPC_FLAMEWAKER_HEALER = 11663, NPC_FLAMEWAKER_ELITE = 11664, + NPC_CORE_RAGER = 11672, + NPC_CORE_HOUND = 11671, }; enum GameObjects { GO_CACHE_OF_THE_FIRELORD = 179703, + GO_CIRCLE_SULFURON = 178187, + GO_CIRCLE_BARON = 178188, + GO_CIRCLE_SHAZZRAH = 178189, + GO_CIRCLE_GOLEMAGG = 178190, + GO_CIRCLE_GARR = 178191, + GO_CIRCLE_MAGMADAR = 178192, + GO_CIRCLE_GEHENNAS = 178193, }; enum Data diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index 55c745a8a8..3278c123f4 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -196,11 +196,13 @@ class boss_ayamiss : public CreatureScript events.ScheduleEvent(EVENT_SWARMER_ATTACK, 60000); break; case EVENT_SUMMON_SWARMER: + { Position Pos; me->GetRandomPoint(SwarmerPos, 80.0f, Pos); me->SummonCreature(NPC_SWARMER, Pos); events.ScheduleEvent(EVENT_SUMMON_SWARMER, 5000); break; + } case EVENT_TRASH: DoCastVictim(SPELL_TRASH); events.ScheduleEvent(EVENT_TRASH, urand(5000, 7000)); diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index f16be1443d..5f48069dd1 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -880,7 +880,7 @@ public: } else { - NextWaveTimer = 65000; + NextWaveTimer = 150000; uint8 num_to_activate = 5; if (WaveNumber <= 2) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index e33efd3fa5..dd4f6b2e76 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -107,7 +107,7 @@ enum Spells SPELL_RISEN_WITCH_DOCTOR_SPAWN = 69639, SPELL_SUMMON_SHAMBLING_HORROR = 70372, SPELL_SUMMON_DRUDGE_GHOULS = 70358, - SPELL_INFEST = 70541, + SPELL_INFEST = 70541, //cast time 2 sec SPELL_NECROTIC_PLAGUE = 70337, SPELL_NECROTIC_PLAGUE_JUMP = 70338, SPELL_PLAGUE_SIPHON = 74074, @@ -116,12 +116,12 @@ enum Spells SPELL_SHADOW_TRAP_KNOCKBACK = 73529, // Phase 2 - SPELL_DEFILE = 72762, + SPELL_DEFILE = 72762, //cast time 2 sec SPELL_DEFILE_AURA = 72743, SPELL_DEFILE_GROW = 72756, - SPELL_SOUL_REAPER = 69409, + SPELL_SOUL_REAPER = 69409, // instant SPELL_SOUL_REAPER_BUFF = 69410, - SPELL_SUMMON_VALKYR = 69037, + SPELL_SUMMON_VALKYR = 69037, // instant SPELL_SUMMON_VALKYR_PERIODIC = 74361, SPELL_WINGS_OF_THE_DAMNED = 74352, SPELL_VALKYR_TARGET_SEARCH = 69030, @@ -980,10 +980,10 @@ class boss_the_lich_king : public CreatureScript case EVENT_QUAKE: _phase = PHASE_TWO; events.CancelEventGroup(EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_INFEST, 8000, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_SUMMON_VALKYR, 15000, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_SOUL_REAPER, 22000, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_DEFILE, 32500, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_INFEST, 14000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SUMMON_VALKYR, 20000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SOUL_REAPER, 40000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_DEFILE, 38000, EVENT_GROUP_ABILITIES); me->InterruptNonMeleeSpells(false); me->ClearUnitState(UNIT_STATE_CASTING); @@ -995,10 +995,10 @@ class boss_the_lich_king : public CreatureScript case EVENT_QUAKE_2: _phase = PHASE_THREE; events.CancelEventGroup(EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_SOUL_REAPER, 25000, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_DEFILE, 32500, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_VILE_SPIRITS, 18000, EVENT_GROUP_VILE_SPIRITS); - events.ScheduleEvent(IsHeroic() ? EVENT_HARVEST_SOULS : EVENT_HARVEST_SOUL, 11000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SOUL_REAPER, 40000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_DEFILE, 38000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_VILE_SPIRITS, 20000, EVENT_GROUP_VILE_SPIRITS); + events.ScheduleEvent(IsHeroic() ? EVENT_HARVEST_SOULS : EVENT_HARVEST_SOUL, 14000, EVENT_GROUP_ABILITIES); me->InterruptNonMeleeSpells(false); me->ClearUnitState(UNIT_STATE_CASTING); @@ -1020,7 +1020,7 @@ class boss_the_lich_king : public CreatureScript break; case EVENT_INFEST: me->CastSpell(me, SPELL_INFEST, false); - events.ScheduleEvent(EVENT_INFEST, urand(21000, 22000), EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_INFEST, 22500, EVENT_GROUP_ABILITIES); break; case EVENT_NECROTIC_PLAGUE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NecroticPlagueTargetCheck(me, NECROTIC_PLAGUE_LK, NECROTIC_PLAGUE_PLR))) @@ -1040,7 +1040,7 @@ class boss_the_lich_king : public CreatureScript case EVENT_PAIN_AND_SUFFERING: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - events.DelayEventsToMax(500, EVENT_GROUP_ABILITIES); + //events.DelayEventsToMax(500, EVENT_GROUP_ABILITIES); me->SetOrientation(me->GetAngle(target)); me->CastSpell(target, SPELL_PAIN_AND_SUFFERING, false); } @@ -1058,33 +1058,43 @@ class boss_the_lich_king : public CreatureScript case EVENT_DEFILE: { uint32 evTime = events.GetNextEventTime(EVENT_SUMMON_VALKYR); - if (evTime && (events.GetTimer() > evTime || evTime - events.GetTimer() < 5000)) // defile cast 2sec -> valkyr in less than 3 secs after defile appears + // if defile (cast time 2sec) is less than 3 before valkyr appears + // we've to decide + if (evTime && (events.GetTimer() > evTime || evTime - events.GetTimer() < 5000)) { - if (events.GetTimer() > evTime || evTime - events.GetTimer() < 3500) // valkyr is less than 1.5 secs after defile - reschedule defile + // if valkyr is less than 1.5 secs after defile (cast time 2 sec) then we've a sync issue, so + // we need to cancel it (break) and schedule a defile to be casted 5 or 4 seconds after valkyr + if (events.GetTimer() > evTime || evTime - events.GetTimer() < 3500) { uint32 t = events.GetTimer() > evTime ? 0 : evTime - events.GetTimer(); events.ScheduleEvent(EVENT_DEFILE, t+(Is25ManRaid() ? 5000 : 4000), EVENT_GROUP_ABILITIES); break; - } + } + + // if valkyr is coming between 1.5 and 3 seconds after defile then we've to // delay valkyr just a bit events.RescheduleEvent(EVENT_SUMMON_VALKYR, 5000, EVENT_GROUP_ABILITIES); } + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, DefileTargetSelector(me))) { Talk(EMOTE_DEFILE_WARNING); me->CastSpell(target, SPELL_DEFILE, false); - events.ScheduleEvent(EVENT_DEFILE, urand(31000, 34000), EVENT_GROUP_ABILITIES); + // defile has a fixed CD (from dbm) that can be variable only + // if no target has been found at the moment (schedule after 1 second) + events.ScheduleEvent(EVENT_DEFILE, 32500, EVENT_GROUP_ABILITIES); + } + else { + // be sure it happen trying each seconds if no target + events.ScheduleEvent(EVENT_DEFILE, 1000, EVENT_GROUP_ABILITIES); } - else - events.ScheduleEvent(EVENT_DEFILE, 2000, EVENT_GROUP_ABILITIES); } break; case EVENT_SOUL_REAPER: if (me->IsWithinMeleeRange(me->GetVictim())) { me->CastSpell(me->GetVictim(), SPELL_SOUL_REAPER, false); - events.DelayEventsToMax(12000, EVENT_GROUP_ABILITIES); - events.ScheduleEvent(EVENT_SOUL_REAPER, 30000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SOUL_REAPER, 30500, EVENT_GROUP_ABILITIES); } else events.ScheduleEvent(EVENT_SOUL_REAPER, 1000, EVENT_GROUP_ABILITIES); @@ -1094,12 +1104,15 @@ class boss_the_lich_king : public CreatureScript me->GetMap()->SetZoneMusic(AREA_THE_FROZEN_THRONE, MUSIC_SPECIAL); Talk(SAY_LK_SUMMON_VALKYR); me->CastSpell((Unit*)NULL, SUMMON_VALKYR, false); - events.ScheduleEvent(EVENT_SUMMON_VALKYR, urand(45000, 48000), EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_SUMMON_VALKYR, 45000, EVENT_GROUP_ABILITIES); + // schedule a defile (or reschedule it) if next defile event + // doesn't exist ( now > next defile ) or defile is coming too soon uint32 minTime = (Is25ManRaid() ? 5000 : 4000); if (uint32 evTime = events.GetNextEventTime(EVENT_DEFILE)) - if (events.GetTimer() > evTime || evTime - events.GetTimer() < minTime) + if (events.GetTimer() > evTime || evTime - events.GetTimer() < minTime) { events.RescheduleEvent(EVENT_DEFILE, minTime, EVENT_GROUP_ABILITIES); + } } break; case EVENT_VILE_SPIRITS: @@ -1112,7 +1125,7 @@ class boss_the_lich_king : public CreatureScript { Talk(SAY_LK_HARVEST_SOUL); me->CastSpell(target, SPELL_HARVEST_SOUL, false); - events.ScheduleEvent(EVENT_HARVEST_SOUL, 70000, EVENT_GROUP_ABILITIES); + events.ScheduleEvent(EVENT_HARVEST_SOUL, 75000, EVENT_GROUP_ABILITIES); } else events.ScheduleEvent(EVENT_HARVEST_SOUL, 10000, EVENT_GROUP_ABILITIES); @@ -3789,4 +3802,4 @@ void AddSC_boss_the_lich_king() new npc_lk_wicked_spirit(); new achievement_been_waiting_long_time(); new achievement_neck_deep_in_vile(); -}
\ No newline at end of file +} diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index d1adf13cd9..b6d11e8967 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -1548,7 +1548,8 @@ class instance_icecrown_citadel : public InstanceMapScript std::ostringstream saveStream; saveStream << "I C " << GetBossSaveData() << HeroicAttempts << ' ' << ColdflameJetsState << ' ' << BloodQuickeningState << ' ' << BloodQuickeningMinutes << ' ' << WeeklyQuestId10 << ' ' << PutricideEventProgress << ' ' - << uint32(LichKingHeroicAvailable ? 1 : 0) << ' ' << BloodPrinceTrashCount; + << uint32(LichKingHeroicAvailable ? 1 : 0) << ' ' << BloodPrinceTrashCount << ' ' << uint32(IsBuffAvailable ? 1 : 0); + OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); @@ -1600,6 +1601,8 @@ class instance_icecrown_citadel : public InstanceMapScript loadStream >> temp; LichKingHeroicAvailable = temp ? true : false; loadStream >> BloodPrinceTrashCount; + loadStream >> temp; + SetData(DATA_BUFF_AVAILABLE, temp ? true : false); } else OUT_LOAD_INST_DATA_FAIL; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index 1b8f6de3e7..461ce780a9 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -49,9 +49,9 @@ public: return new boss_anubrekhanAI (pCreature); } - struct boss_anubrekhanAI : public ScriptedAI + struct boss_anubrekhanAI : public BossAI { - boss_anubrekhanAI(Creature *c) : ScriptedAI(c), summons(me) + boss_anubrekhanAI(Creature *c) : BossAI(c, BOSS_ANUB), summons(me) { pInstance = c->GetInstanceScript(); sayGreet = false; @@ -71,15 +71,15 @@ public: } } - void Reset() + void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); SummonCryptGuards(); if (pInstance) { - pInstance->SetData(EVENT_ANUB, NOT_STARTED); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE))) go->SetGoState(GO_STATE_ACTIVE); } @@ -107,13 +107,13 @@ public: void SummonedCreatureDespawn(Creature* cr) { summons.Despawn(cr); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); summons.DespawnAll(); if (pInstance) { pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - pInstance->SetData(EVENT_ANUB, DONE); } } @@ -132,13 +132,13 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->CallForHelp(30.0f); // catch helpers Talk(SAY_AGGRO); if (pInstance) { - pInstance->SetData(EVENT_ANUB, IN_PROGRESS); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_ANUB_GATE))) go->SetGoState(GO_STATE_READY); } @@ -179,12 +179,14 @@ public: events.RepeatEvent(20000); break; case EVENT_SPELL_LOCUST_SWARM: + { me->CastSpell(me, RAID_MODE(SPELL_LOCUST_SWARM_10, SPELL_LOCUST_SWARM_25), false); Position pos; - me->GetNearPosition(pos, 10.0f, rand_norm()*2*M_PI); + me->GetNearPosition(pos, 10.0f, rand_norm() * 2 * M_PI); me->SummonCreature(NPC_CRYPT_GUARD, pos); events.RepeatEvent(90000); break; + } case EVENT_SPELL_BERSERK: me->CastSpell(me, SPELL_BERSERK, true); events.PopEvent(); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 65545bba68..96961d1ae2 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -49,9 +49,9 @@ public: return new boss_faerlinaAI (pCreature); } - struct boss_faerlinaAI : public ScriptedAI + struct boss_faerlinaAI : public BossAI { - boss_faerlinaAI(Creature *c) : ScriptedAI(c), summons(me) + boss_faerlinaAI(Creature *c) : BossAI(c, BOSS_FAERLINA), summons(me) { pInstance = me->GetInstanceScript(); sayGreet = false; @@ -81,24 +81,21 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); SummonHelpers(); - if (pInstance) - pInstance->SetData(EVENT_FAERLINA, NOT_STARTED); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { - me->SetInCombatWithZone(); + BossAI::EnterCombat(who); + summons.DoZoneInCombat(); Talk(SAY_AGGRO); events.ScheduleEvent(EVENT_SPELL_POISON_BOLT, urand(12000,15000)); events.ScheduleEvent(EVENT_SPELL_RAIN_OF_FIRE, urand(6000,18000)); events.ScheduleEvent(EVENT_SPELL_FRENZY, urand(60000,80000), 1); events.SetPhase(1); - - if (pInstance) - pInstance->SetData(EVENT_FAERLINA, IN_PROGRESS); } void MoveInLineOfSight(Unit *who) @@ -124,11 +121,10 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); Talk(SAY_DEATH); - if (pInstance) - pInstance->SetData(EVENT_FAERLINA, DONE); } void UpdateAI(uint32 diff) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index 36c8b29979..21cff6286e 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -121,9 +121,9 @@ public: return new boss_four_horsemenAI (pCreature); } - struct boss_four_horsemenAI : public ScriptedAI + struct boss_four_horsemenAI : public BossAI { - boss_four_horsemenAI(Creature *c) : ScriptedAI(c) + boss_four_horsemenAI(Creature *c) : BossAI(c, BOSS_HORSEMAN) { pInstance = me->GetInstanceScript(); switch (me->GetEntry()) @@ -174,15 +174,13 @@ public: void Reset() { + BossAI::Reset(); me->SetPosition(me->GetHomePosition()); movementPhase = MOVE_PHASE_NONE; currentWaypoint = 0; me->SetReactState(REACT_AGGRESSIVE); events.Reset(); - if (pInstance) - pInstance->SetData(EVENT_HORSEMAN, NOT_STARTED); - // Schedule Events events.RescheduleEvent(EVENT_SPELL_MARK_CAST, 24000); events.RescheduleEvent(EVENT_BERSERK, 100*15000); @@ -248,25 +246,24 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); if (pInstance) { - pInstance->SetData(EVENT_HORSEMAN, DONE); - if (pInstance->GetData(EVENT_HORSEMAN) == DONE) + if (pInstance->GetBossState(BOSS_HORSEMAN) == DONE) { if (!me->GetMap()->GetPlayers().isEmpty()) if (Player* player = me->GetMap()->GetPlayers().getFirst()->GetSource()) player->SummonGameObject(RAID_MODE(GO_HORSEMEN_CHEST_10, GO_HORSEMEN_CHEST_25), 2514.8f, -2944.9f, 245.55f, 5.51f, 0, 0, 0, 0, 0); + } } Talk(SAY_DEATH); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { - if (pInstance) - pInstance->SetData(EVENT_HORSEMAN, IN_PROGRESS); - + BossAI::EnterCombat(who); if (movementPhase == MOVE_PHASE_NONE) { Talk(SAY_AGGRO); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 5a39e88fef..fdc4a5e6a8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -52,9 +52,9 @@ public: return new boss_gluthAI (pCreature); } - struct boss_gluthAI : public ScriptedAI + struct boss_gluthAI : public BossAI { - boss_gluthAI(Creature *c) : ScriptedAI(c), summons(me) + boss_gluthAI(Creature *c) : BossAI(c, BOSS_GLUTH), summons(me) { pInstance = me->GetInstanceScript(); } @@ -66,14 +66,12 @@ public: void Reset() { + BossAI::Reset(); me->ApplySpellImmune(29306, IMMUNITY_ID, 29306, true); events.Reset(); summons.DespawnAll(); gazeTarget = 0; me->SetReactState(REACT_AGGRESSIVE); - - if (pInstance) - pInstance->SetData(EVENT_GLUTH, NOT_STARTED); } void MoveInLineOfSight(Unit *who) @@ -87,8 +85,9 @@ public: ScriptedAI::MoveInLineOfSight(who); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->SetInCombatWithZone(); events.ScheduleEvent(EVENT_SPELL_MORTAL_WOUND, 10000); events.ScheduleEvent(EVENT_SPELL_ENRAGE, 30000); @@ -96,9 +95,6 @@ public: events.ScheduleEvent(EVENT_SPELL_BERSERK, 8*60000); events.ScheduleEvent(EVENT_SUMMON_ZOMBIE, 10000); events.ScheduleEvent(EVENT_CAN_EAT_ZOMBIE, 1000); - - if (pInstance) - pInstance->SetData(EVENT_GLUTH, IN_PROGRESS); } void JustSummoned(Creature *summon) @@ -120,11 +116,10 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit*) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); summons.DespawnAll(); - if (pInstance) - pInstance->SetData(EVENT_GLUTH, DONE); } bool SelectPlayerInRoom() diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 10330f28ab..897103e475 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -135,9 +135,9 @@ public: return new boss_gothikAI (pCreature); } - struct boss_gothikAI : public ScriptedAI + struct boss_gothikAI : public BossAI { - boss_gothikAI(Creature *c) : ScriptedAI(c), summons(me) + boss_gothikAI(Creature *c) : BossAI(c, BOSS_GOTHIK), summons(me) { pInstance = me->GetInstanceScript(); } @@ -162,6 +162,7 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_DISABLE_MOVE); @@ -172,7 +173,6 @@ public: if (pInstance) { - pInstance->SetData(EVENT_GOTHIK, NOT_STARTED); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE))) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) @@ -182,8 +182,9 @@ public: } } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->SetInCombatWithZone(); Talk(SAY_SPEECH); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); @@ -194,7 +195,6 @@ public: if (pInstance) { - pInstance->SetData(EVENT_GOTHIK, IN_PROGRESS); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE))) go->SetGoState(GO_STATE_READY); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) @@ -225,14 +225,14 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); Talk(SAY_DEATH); summons.DespawnAll(); if (pInstance) { - pInstance->SetData(EVENT_GOTHIK, DONE); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_ENTER_GATE))) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_GOTHIK_INNER_GATE))) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index e0ab0e9a58..aa8b87531b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -45,9 +45,9 @@ public: return new boss_grobbulusAI (pCreature); } - struct boss_grobbulusAI : public ScriptedAI + struct boss_grobbulusAI : public BossAI { - boss_grobbulusAI(Creature *c) : ScriptedAI(c), summons(me) + boss_grobbulusAI(Creature *c) : BossAI(c, BOSS_GROBBULUS), summons(me) { pInstance = me->GetInstanceScript(); } @@ -59,24 +59,20 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); dropSludgeTimer = 0; - - if (pInstance) - pInstance->SetData(EVENT_GROBBULUS, NOT_STARTED); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->SetInCombatWithZone(); events.ScheduleEvent(EVENT_SPELL_POISON_CLOUD, 15000); events.ScheduleEvent(EVENT_SPELL_MUTATING_INJECTION, 20000); events.ScheduleEvent(EVENT_SPELL_SLIME_SPRAY, 10000); events.ScheduleEvent(EVENT_SPELL_BERSERK, RAID_MODE(12*MINUTE*IN_MILLISECONDS, 9*MINUTE*IN_MILLISECONDS)); - - if (pInstance) - pInstance->SetData(EVENT_GROBBULUS, IN_PROGRESS); } void SpellHitTarget(Unit *target, const SpellInfo* spellInfo) @@ -95,11 +91,10 @@ public: void SummonedCreatureDespawn(Creature* summon){ summons.Despawn(summon); } - void JustDied(Unit*) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); summons.DespawnAll(); - if (pInstance) - pInstance->SetData(EVENT_GROBBULUS, DONE); } void KilledUnit(Unit* who) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index 1c7461c92c..c6039bac60 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -48,9 +48,9 @@ public: return new boss_heiganAI (pCreature); } - struct boss_heiganAI : public ScriptedAI + struct boss_heiganAI : public BossAI { - boss_heiganAI(Creature *c) : ScriptedAI(c) + boss_heiganAI(Creature *c) : BossAI(c, BOSS_HEIGAN) { pInstance = me->GetInstanceScript(); } @@ -63,6 +63,7 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); currentPhase = 0; currentSection = 3; @@ -70,7 +71,6 @@ public: if (pInstance) { - pInstance->SetData(EVENT_HEIGAN, NOT_STARTED); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE))) go->SetGoState(GO_STATE_ACTIVE); } @@ -88,20 +88,19 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); Talk(SAY_DEATH); - if (pInstance) - pInstance->SetData(EVENT_HEIGAN, DONE); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->SetInCombatWithZone(); Talk(SAY_AGGRO); if (pInstance) { - pInstance->SetData(EVENT_HEIGAN, IN_PROGRESS); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_HEIGAN_ENTER_GATE))) go->SetGoState(GO_STATE_READY); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 0e9f2148f8..5af8fbd6aa 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -115,9 +115,9 @@ public: return new boss_kelthuzadAI (pCreature); } - struct boss_kelthuzadAI : public ScriptedAI + struct boss_kelthuzadAI : public BossAI { - boss_kelthuzadAI(Creature* c) : ScriptedAI(c), summons(me) + boss_kelthuzadAI(Creature* c) : BossAI(c, BOSS_KELTHUZAD), summons(me) { pInstance = me->GetInstanceScript(); } @@ -162,6 +162,7 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_DISABLE_MOVE); @@ -169,7 +170,6 @@ public: if (pInstance) { - pInstance->SetData(EVENT_KELTHUZAD, NOT_STARTED); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR))) { go->SetPhaseMask(1, true); @@ -198,12 +198,11 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); summons.DespawnAll(); Talk(SAY_DEATH); - if (pInstance) - pInstance->SetData(EVENT_KELTHUZAD, DONE); } void MoveInLineOfSight(Unit* who) @@ -212,8 +211,9 @@ public: AttackStart(who); } - void EnterCombat(Unit* /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); Talk(SAY_SUMMON_MINIONS); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); me->RemoveAllAttackers(); @@ -229,7 +229,6 @@ public: events.ScheduleEvent(EVENT_START_SECOND_PHASE, 228000); if (pInstance) { - pInstance->SetData(EVENT_KELTHUZAD, IN_PROGRESS); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_KELTHUZAD_FLOOR))) { events.ScheduleEvent(EVENT_FLOOR_CHANGE, 15000); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index dca14d834f..165ff01329 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -42,9 +42,9 @@ public: return new boss_loathebAI (pCreature); } - struct boss_loathebAI : public ScriptedAI + struct boss_loathebAI : public BossAI { - boss_loathebAI(Creature *c) : ScriptedAI(c) + boss_loathebAI(Creature *c) : BossAI(c, BOSS_LOATHEB) { pInstance = me->GetInstanceScript(); } @@ -54,10 +54,10 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); if (pInstance) { - pInstance->SetData(EVENT_LOATHEB, NOT_STARTED); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE))) go->SetGoState(GO_STATE_ACTIVE); } @@ -77,11 +77,11 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); if (pInstance) { - pInstance->SetData(EVENT_LOATHEB, IN_PROGRESS); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_LOATHEB_GATE))) go->SetGoState(GO_STATE_READY); } @@ -93,12 +93,6 @@ public: events.ScheduleEvent(EVENT_SPELL_BERSERK, 720000); } - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(EVENT_LOATHEB, DONE); - } - void UpdateAI(uint32 diff) { if (!UpdateVictim()) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index ad9515e9de..f93e5758cb 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -53,9 +53,9 @@ public: return new boss_maexxnaAI (pCreature); } - struct boss_maexxnaAI : public ScriptedAI + struct boss_maexxnaAI : public BossAI { - boss_maexxnaAI(Creature *c) : ScriptedAI(c), summons(me) + boss_maexxnaAI(Creature *c) : BossAI(c, BOSS_MAEXXNA), summons(me) { pInstance = me->GetInstanceScript(); } @@ -77,20 +77,21 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); if (pInstance) { - pInstance->SetData(EVENT_MAEXXNA, NOT_STARTED); - if (pInstance->GetData(EVENT_FAERLINA) == DONE) + if (pInstance->GetData(BOSS_FAERLINA) == DONE) if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE))) go->SetGoState(GO_STATE_ACTIVE); } } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->SetInCombatWithZone(); events.ScheduleEvent(EVENT_WEB_WRAP, 20000); events.ScheduleEvent(EVENT_SPELL_WEB_SPRAY, 40000); @@ -101,18 +102,11 @@ public: if (pInstance) { - pInstance->SetData(EVENT_MAEXXNA, IN_PROGRESS); if (GameObject* go = me->GetMap()->GetGameObject(pInstance->GetData64(DATA_MAEXXNA_GATE))) go->SetGoState(GO_STATE_READY); } } - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(EVENT_MAEXXNA, DONE); - } - void JustSummoned(Creature* cr) { if (cr->GetEntry() == NPC_MAEXXNA_SPIDERLING) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index aa0cdeada6..95f81ca99b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -66,9 +66,9 @@ public: return new boss_nothAI (pCreature); } - struct boss_nothAI : public ScriptedAI + struct boss_nothAI : public BossAI { - boss_nothAI(Creature *c) : ScriptedAI(c), summons(me) + boss_nothAI(Creature *c) : BossAI(c, BOSS_NOTH), summons(me) { pInstance = me->GetInstanceScript(); } @@ -123,14 +123,12 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); me->SetControlled(false, UNIT_STATE_ROOT); me->SetReactState(REACT_AGGRESSIVE); events.SetPhase(0); - - if (pInstance) - pInstance->SetData(EVENT_NOTH, NOT_STARTED); } void EnterEvadeMode() @@ -139,12 +137,10 @@ public: ScriptedAI::EnterEvadeMode(); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); Talk(SAY_AGGRO); - if (pInstance) - pInstance->SetData(EVENT_NOTH, IN_PROGRESS); - StartGroundPhase(); } @@ -154,11 +150,10 @@ public: summon->SetInCombatWithZone(); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); Talk(SAY_DEATH); - if (pInstance) - pInstance->SetData(EVENT_NOTH, DONE); } void KilledUnit(Unit* who) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp index 05b5b4649a..18910bbcd3 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -47,9 +47,9 @@ public: return new boss_patchwerkAI (pCreature); } - struct boss_patchwerkAI : public ScriptedAI + struct boss_patchwerkAI : public BossAI { - boss_patchwerkAI(Creature *c) : ScriptedAI(c) + boss_patchwerkAI(Creature *c) : BossAI(c, BOSS_PATCHWERK) { pInstance = me->GetInstanceScript(); } @@ -59,9 +59,8 @@ public: void Reset() { + BossAI::Reset(); events.Reset(); - if (pInstance) - pInstance->SetData(EVENT_PATCHWERK, NOT_STARTED); } void KilledUnit(Unit* who) @@ -76,15 +75,15 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); Talk(SAY_DEATH); - if (pInstance) - pInstance->SetData(EVENT_PATCHWERK, DONE); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); Talk(SAY_AGGRO); me->SetInCombatWithZone(); @@ -95,7 +94,6 @@ public: if (pInstance) { pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - pInstance->SetData(EVENT_PATCHWERK, IN_PROGRESS); } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp index 418fae7324..def339cf5e 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp @@ -60,9 +60,9 @@ public: return new boss_razuviousAI (pCreature); } - struct boss_razuviousAI : public ScriptedAI + struct boss_razuviousAI : public BossAI { - boss_razuviousAI(Creature *c) : ScriptedAI(c), summons(me) + boss_razuviousAI(Creature *c) : BossAI(c, BOSS_RAZUVIOUS), summons(me) { pInstance = me->GetInstanceScript(); } @@ -86,11 +86,10 @@ public: void Reset() { + BossAI::Reset(); summons.DespawnAll(); events.Reset(); SpawnHelpers(); - if (pInstance) - pInstance->SetData(EVENT_RAZUVIOUS, NOT_STARTED); } void KilledUnit(Unit* who) @@ -115,18 +114,18 @@ public: me->LowerPlayerDamageReq(damage); } - void JustDied(Unit* /*killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); DoPlaySoundToSet(me, SOUND_DEATH); me->MonsterYell("An honorable... death...", LANG_UNIVERSAL, 0); me->CastSpell(me, SPELL_HOPELESS, true); - if (pInstance) - pInstance->SetData(EVENT_RAZUVIOUS, DONE); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); switch (urand(0,2)) { case 0: @@ -147,8 +146,6 @@ public: events.ScheduleEvent(EVENT_SPELL_DISRUPTING_SHOUT, 25000); events.ScheduleEvent(EVENT_SPELL_JAGGED_KNIFE, 15000); events.ScheduleEvent(EVENT_PLAY_COMMAND, 40000); - if (pInstance) - pInstance->SetData(EVENT_RAZUVIOUS, IN_PROGRESS); summons.DoZoneInCombat(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index d0b8bb5d15..2514682c95 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -77,9 +77,9 @@ public: return new boss_sapphironAI (pCreature); } - struct boss_sapphironAI : public ScriptedAI + struct boss_sapphironAI : public BossAI { - boss_sapphironAI(Creature* c) : ScriptedAI(c) + boss_sapphironAI(Creature* c) : BossAI(c, BOSS_SAPPHIRON) { pInstance = me->GetInstanceScript(); } @@ -113,6 +113,7 @@ public: void Reset() { + BossAI::Reset(); if (me->IsVisible()) me->SetReactState(REACT_AGGRESSIVE); @@ -121,9 +122,6 @@ public: spawnTimer = 0; currentTarget = 0; blockList.clear(); - - if (pInstance) - pInstance->SetData(EVENT_SAPPHIRON, NOT_STARTED); } void EnterCombatSelfFunction() @@ -147,8 +145,9 @@ public: } } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); EnterCombatSelfFunction(); me->CastSpell(me, RAID_MODE(SPELL_FROST_AURA_10, SPELL_FROST_AURA_25), true); @@ -159,16 +158,12 @@ public: events.ScheduleEvent(EVENT_SPELL_BLIZZARD, 21000); events.ScheduleEvent(EVENT_FLIGHT_START, 45000); events.ScheduleEvent(EVENT_HUNDRED_CLUB, 5000); - - if (pInstance) - pInstance->SetData(EVENT_SAPPHIRON, IN_PROGRESS); } - void JustDied(Unit* /*who*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); me->CastSpell(me, SPELL_SAPPHIRON_DIES, true); - if (pInstance) - pInstance->SetData(EVENT_SAPPHIRON, DONE); } void DoAction(int32 param) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index 0e5648f779..51e8f5b6ca 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -94,9 +94,9 @@ public: return new boss_thaddiusAI (pCreature); } - struct boss_thaddiusAI : public ScriptedAI + struct boss_thaddiusAI : public BossAI { - boss_thaddiusAI(Creature *c) : ScriptedAI(c), summons(me) + boss_thaddiusAI(Creature *c) : BossAI(c, BOSS_THADDIUS), summons(me) { pInstance = me->GetInstanceScript(); } @@ -139,8 +139,9 @@ public: } } - void Reset() + void Reset() { + BossAI::Reset(); events.Reset(); summons.DespawnAll(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -149,9 +150,6 @@ public: resetTimer = 1; me->SetPosition(me->GetHomePosition()); - if (pInstance) - pInstance->SetData(EVENT_THADDIUS, NOT_STARTED); - me->SummonCreature(NPC_STALAGG, 3450.45f, -2931.42f, 312.091f, 5.49779f); me->SummonCreature(NPC_FEUGEN, 3508.14f, -2988.65f, 312.092f, 2.37365f); if (Creature* cr = me->SummonCreature(NPC_TESLA_COIL, 3527.34f, -2951.56f, 318.75f, 0.0f)) @@ -182,12 +180,12 @@ public: pInstance->SetData(DATA_IMMORTAL_FAIL, 0); } - void JustDied(Unit* /*Killer*/) + void JustDied(Unit* killer) { + BossAI::JustDied(killer); Talk(SAY_DEATH); if (pInstance) { - pInstance->SetData(EVENT_THADDIUS, DONE); pInstance->DoRemoveAurasDueToSpellOnPlayers(28059); pInstance->DoRemoveAurasDueToSpellOnPlayers(28084); } @@ -195,14 +193,12 @@ public: void JustSummoned(Creature* cr) { summons.Summon(cr); } - void EnterCombat(Unit * /*who*/) + void EnterCombat(Unit * who) { + BossAI::EnterCombat(who); me->SetInCombatWithZone(); summons.DoZoneInCombat(NPC_FEUGEN); summons.DoZoneInCombat(NPC_STALAGG); - - if (pInstance) - pInstance->SetData(EVENT_THADDIUS, IN_PROGRESS); } void UpdateAI(uint32 diff) diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index d9017164cd..93db29caea 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -49,7 +49,7 @@ public: { instance_naxxramas_InstanceMapScript(Map* pMap) : InstanceScript(pMap) { - memset(&Encounters, 0, sizeof(Encounters)); + SetBossNumber(MAX_ENCOUNTERS); for (uint8 i = 0; i < 4; ++i) HeiganEruption[i].clear(); @@ -101,7 +101,6 @@ public: immortalAchievement = 1; } - uint32 Encounters[MAX_ENCOUNTERS]; std::set<GameObject*> HeiganEruption[4]; // GOs @@ -169,17 +168,17 @@ public: } } - bool IsEncounterInProgress() const + bool IsEncounterInProgress() const override { for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) { - if (Encounters[i] == IN_PROGRESS) + if (GetBossState(i) == IN_PROGRESS) return true; } return false; } - void OnCreatureCreate(Creature* creature) + void OnCreatureCreate(Creature* creature) override { switch(creature->GetEntry()) { @@ -216,7 +215,7 @@ public: } } - void OnGameObjectCreate(GameObject* pGo) + void OnGameObjectCreate(GameObject* pGo) override { if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287) { @@ -228,57 +227,57 @@ public: { case GO_PATCHWERK_GATE: _patchwerkGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_PATCHWERK] == DONE) + if (GetBossState(BOSS_PATCHWERK) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_GLUTH_GATE: _gluthGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_GLUTH] == DONE) + if (GetBossState(BOSS_GLUTH) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_NOTH_GATE: _nothGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_NOTH] == DONE) + if (GetBossState(BOSS_NOTH) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_HEIGAN_ENTERANCE_GATE: _heiganGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_HEIGAN] == DONE || Encounters[EVENT_NOTH] == DONE) + if (GetBossState(BOSS_HEIGAN) == DONE || GetBossState(BOSS_NOTH) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_HEIGAN_EXIT_GATE: _heiganGateExitGUID = pGo->GetGUID(); - if (Encounters[EVENT_HEIGAN] == DONE) + if (GetBossState(BOSS_HEIGAN) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_LOATHEB_GATE: _loathebGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_LOATHEB] == DONE) + if (GetBossState(BOSS_LOATHEB) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_ANUB_GATE: _anubGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_ANUB] == DONE) + if (GetBossState(BOSS_ANUB) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_ANUB_NEXT_GATE: _anubNextGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_ANUB] == DONE) + if (GetBossState(BOSS_ANUB) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_FAERLINA_GATE: _faerlinaGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_FAERLINA] == DONE) + if (GetBossState(BOSS_FAERLINA) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_MAEXXNA_GATE: _maexxnaGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_FAERLINA] == DONE) // faerlina is correct + if (GetBossState(BOSS_FAERLINA) == DONE) // faerlina is correct pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_THADDIUS_GATE: _thaddiusGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_GLUTH] == DONE) // gluth is correct + if (GetBossState(BOSS_GLUTH) == DONE) // gluth is correct pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_GOTHIK_ENTER_GATE: @@ -289,12 +288,12 @@ public: break; case GO_GOTHIK_EXIT_GATE: _gothikExitGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_GOTHIK] == DONE) + if (GetBossState(BOSS_GOTHIK) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_HORSEMAN_GATE: _horsemanGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_GOTHIK] == DONE) // correct + if (GetBossState(BOSS_GOTHIK) == DONE) // correct pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_KELTHUZAD_FLOOR: @@ -305,33 +304,33 @@ public: break; case GO_SAPPHIRON_GATE: _sapphironGateGUID = pGo->GetGUID(); - if (Encounters[EVENT_SAPPHIRON] == DONE) + if (GetBossState(BOSS_SAPPHIRON) == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_DEATHKNIGHT_WING: _loathebPortalGUID = pGo->GetGUID(); - if (Encounters[EVENT_LOATHEB] == DONE) + if (GetBossState(BOSS_LOATHEB) == DONE) pGo->SetPhaseMask(1, true); break; case GO_THADDIUS_PORTAL: _thaddiusPortalGUID = pGo->GetGUID(); - if (Encounters[EVENT_THADDIUS] == DONE) + if (GetBossState(BOSS_THADDIUS) == DONE) pGo->SetPhaseMask(1, true); break; case GO_MAEXXNA_PORTAL: _maexxnaPortalGUID = pGo->GetGUID(); - if (Encounters[EVENT_MAEXXNA] == DONE) + if (GetBossState(BOSS_MAEXXNA) == DONE) pGo->SetPhaseMask(1, true); break; case GO_HORSEMAN_PORTAL: _horsemanPortalGUID = pGo->GetGUID(); - if (Encounters[EVENT_HORSEMAN] == DONE) + if (GetBossState(BOSS_HORSEMAN) == DONE) pGo->SetPhaseMask(1, true); break; } } - void OnGameObjectRemove(GameObject* pGo) + void OnGameObjectRemove(GameObject* pGo) override { if (pGo->GetGOInfo()->displayId == 6785 || pGo->GetGOInfo()->displayId == 1287) { @@ -345,7 +344,7 @@ public: cr->AI()->DoAction(ACTION_SAPPHIRON_BIRTH); } - bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override { switch(criteria_id) { @@ -389,7 +388,7 @@ public: { uint8 count = 0; for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) - if (Encounters[i] == NOT_STARTED) + if (GetBossState(i) == NOT_STARTED) ++count; return !count && immortalAchievement; @@ -398,57 +397,10 @@ public: return false; } - void SetData(uint32 id, uint32 data) + void SetData(uint32 id, uint32 data) override { - // Bosses data switch(id) { - case EVENT_PATCHWERK: - case EVENT_GROBBULUS: - case EVENT_GLUTH: - case EVENT_NOTH: - case EVENT_ANUB: - case EVENT_MAEXXNA: - case EVENT_RAZUVIOUS: - case EVENT_GOTHIK: - // EVENT_HORSEMAN HANDLED BELOW - Encounters[id] = data; - break; - case EVENT_KELTHUZAD: - if (data == NOT_STARTED) - abominationsKilled = 0; - Encounters[id] = data; - break; - case EVENT_FAERLINA: - if (data == NOT_STARTED) - faerlinaAchievement = true; - Encounters[id] = data; - break; - case EVENT_THADDIUS: - if (data == NOT_STARTED) - thaddiusAchievement = true; - Encounters[id] = data; - break; - case EVENT_LOATHEB: - if (data == NOT_STARTED) - loathebAchievement = true; - Encounters[id] = data; - break; - case EVENT_HEIGAN: - if (data == NOT_STARTED) - heiganAchievement = true; - Encounters[id] = data; - break; - case DATA_HEIGAN_ERUPTION: - HeiganEruptSections(data); - return; - case EVENT_SAPPHIRON: - Encounters[id] = data; - if (data == DONE) - _speakTimer = 1; - else if (data == NOT_STARTED) - sapphironAchievement = true; - break; case DATA_ABOMINATION_KILLED: abominationsKilled++; return; @@ -471,17 +423,24 @@ public: immortalAchievement = 0; SaveToDB(); return; + case DATA_HEIGAN_ERUPTION: + HeiganEruptSections(data); + return; } - + } + + bool SetBossState(uint32 bossId, EncounterState state) override + { // Horseman handling - if (id == EVENT_HORSEMAN) + if (bossId == BOSS_HORSEMAN) { - if (data == DONE) + if (state == DONE) { _horsemanTimer++; _horsemanKilled++; - if (_horsemanKilled < 4) - return; + if (_horsemanKilled < 4) { + return false; + } // All horsemans are killed if (Creature* cr = instance->GetCreature(_blaumeuxGUID)) @@ -489,7 +448,7 @@ public: } // respawn - else if (data == NOT_STARTED && _horsemanKilled > 0) + else if (state == NOT_STARTED && _horsemanKilled > 0) { Creature* cr; _horsemanKilled = 0; @@ -518,7 +477,7 @@ public: cr->Respawn(); } } - else if (data == IN_PROGRESS) + else if (state == IN_PROGRESS) { Creature* cr; if ((cr = instance->GetCreature(_blaumeuxGUID))) @@ -531,66 +490,99 @@ public: cr->SetInCombatWithZone(); } - if (data == NOT_STARTED) + if (state == NOT_STARTED) _horsemanTimer = 0; - - Encounters[id] = data; } - + + + if (!InstanceScript::SetBossState(bossId, state)) + return false; + + // Bosses data + switch(bossId) + { + case BOSS_KELTHUZAD: + if (state == NOT_STARTED) + abominationsKilled = 0; + break; + case BOSS_FAERLINA: + if (state == NOT_STARTED) + faerlinaAchievement = true; + break; + case BOSS_THADDIUS: + if (state == NOT_STARTED) + thaddiusAchievement = true; + break; + case BOSS_LOATHEB: + if (state == NOT_STARTED) + loathebAchievement = true; + break; + case BOSS_HEIGAN: + if (state == NOT_STARTED) + heiganAchievement = true; + break; + case BOSS_SAPPHIRON: + if (state == DONE) + _speakTimer = 1; + else if (state == NOT_STARTED) + sapphironAchievement = true; + break; + } + // Save instance and open gates - if (data == DONE) + if (state == DONE) { SaveToDB(); - switch (id) + switch (bossId) { - case EVENT_PATCHWERK: + case BOSS_PATCHWERK: if (GameObject* go = instance->GetGameObject(_patchwerkGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_GLUTH: + case BOSS_GLUTH: if (GameObject* go = instance->GetGameObject(_gluthGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_thaddiusGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_NOTH: + case BOSS_NOTH: if (GameObject* go = instance->GetGameObject(_nothGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_heiganGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_HEIGAN: + case BOSS_HEIGAN: if (GameObject* go = instance->GetGameObject(_heiganGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_heiganGateExitGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_LOATHEB: + case BOSS_LOATHEB: if (GameObject* go = instance->GetGameObject(_loathebGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_loathebPortalGUID)) go->SetPhaseMask(1, true); break; - case EVENT_ANUB: + case BOSS_ANUB: if (GameObject* go = instance->GetGameObject(_anubGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_anubNextGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_FAERLINA: + case BOSS_FAERLINA: if (GameObject* go = instance->GetGameObject(_faerlinaGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_MAEXXNA: + case BOSS_MAEXXNA: if (GameObject* go = instance->GetGameObject(_maexxnaGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_maexxnaPortalGUID)) go->SetPhaseMask(1, true); break; - case EVENT_GOTHIK: + case BOSS_GOTHIK: if (GameObject* go = instance->GetGameObject(_gothikEnterGateGUID)) go->SetGoState(GO_STATE_ACTIVE); if (GameObject* go = instance->GetGameObject(_gothikExitGateGUID)) @@ -598,33 +590,25 @@ public: if (GameObject* go = instance->GetGameObject(_horsemanGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_SAPPHIRON: + case BOSS_SAPPHIRON: if (GameObject* go = instance->GetGameObject(_sapphironGateGUID)) go->SetGoState(GO_STATE_ACTIVE); break; - case EVENT_THADDIUS: + case BOSS_THADDIUS: if (GameObject* go = instance->GetGameObject(_thaddiusPortalGUID)) go->SetPhaseMask(1, true); break; - case EVENT_HORSEMAN: + case BOSS_HORSEMAN: if (GameObject* go = instance->GetGameObject(_horsemanPortalGUID)) go->SetPhaseMask(1, true); break; } } + + return true; } - uint32 GetData(uint32 identifier) const - { - switch(identifier) - { - case EVENT_HORSEMAN: - return Encounters[identifier]; - } - return 0; - } - - void Update(uint32 diff) + void Update(uint32 diff) override { if (_speakTimer) { @@ -666,7 +650,7 @@ public: _horsemanTimer += diff; } - uint64 GetData64(uint32 id) const + uint64 GetData64(uint32 id) const override { switch (id) { @@ -703,21 +687,18 @@ public: return 0; } - std::string GetSaveData() + std::string GetSaveData() override { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << "N X X " << Encounters[0] << ' ' << Encounters[1] << ' ' << Encounters[2] << ' ' << Encounters[3] - << ' ' << Encounters[4] << ' ' << Encounters[5] << ' ' << Encounters[6] << ' ' << Encounters[7] - << ' ' << Encounters[8] << ' ' << Encounters[9] << ' ' << Encounters[10] << ' ' << Encounters[11] - << ' ' << Encounters[12] << ' ' << Encounters[13] << ' ' << Encounters[14] << ' ' << immortalAchievement; + saveStream << "N X X " << GetBossSaveData() << ' ' << immortalAchievement; OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); } - void Load(const char* in) + void Load(const char* in) override { if (!in) { @@ -735,9 +716,12 @@ public: { for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) { - loadStream >> Encounters[i]; - if (Encounters[i] == IN_PROGRESS) - Encounters[i] = NOT_STARTED; + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS) + tmpState = NOT_STARTED; + + SetBossState(i, EncounterState(tmpState)); } loadStream >> immortalAchievement; diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 10bce8cbb1..25a1bed6d4 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -7,23 +7,23 @@ #include "ScriptPCH.h" -enum NXEncounter +enum Encouters { - EVENT_PATCHWERK = 0, - EVENT_GROBBULUS = 1, - EVENT_GLUTH = 2, - EVENT_NOTH = 3, - EVENT_HEIGAN = 4, - EVENT_LOATHEB = 5, - EVENT_ANUB = 6, - EVENT_FAERLINA = 7, - EVENT_MAEXXNA = 8, - EVENT_THADDIUS = 9, - EVENT_RAZUVIOUS = 10, - EVENT_GOTHIK = 11, - EVENT_HORSEMAN = 12, - EVENT_SAPPHIRON = 13, - EVENT_KELTHUZAD = 14, + BOSS_PATCHWERK = 0, + BOSS_GROBBULUS = 1, + BOSS_GLUTH = 2, + BOSS_NOTH = 3, + BOSS_HEIGAN = 4, + BOSS_LOATHEB = 5, + BOSS_ANUB = 6, + BOSS_FAERLINA = 7, + BOSS_MAEXXNA = 8, + BOSS_THADDIUS = 9, + BOSS_RAZUVIOUS = 10, + BOSS_GOTHIK = 11, + BOSS_HORSEMAN = 12, + BOSS_SAPPHIRON = 13, + BOSS_KELTHUZAD = 14, MAX_ENCOUNTERS, }; diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index a88a56359b..50db4397db 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -1264,6 +1264,108 @@ public: }; +enum BloodsporeRuination +{ + NPC_BLOODMAGE_LAURITH = 25381, + SAY_BLOODMAGE_LAURITH = 0, + EVENT_TALK = 1, + EVENT_RESET_ORIENTATION +}; + +class spell_q11719_bloodspore_ruination_45997 : public SpellScriptLoader +{ +public: + spell_q11719_bloodspore_ruination_45997() : SpellScriptLoader("spell_q11719_bloodspore_ruination_45997") { } + + class spell_q11719_bloodspore_ruination_45997_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q11719_bloodspore_ruination_45997_SpellScript); + + void HandleEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + if (Creature* laurith = caster->FindNearestCreature(NPC_BLOODMAGE_LAURITH, 100.0f)) + laurith->AI()->SetGUID(caster->GetGUID()); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_q11719_bloodspore_ruination_45997_SpellScript::HandleEffect, EFFECT_1, SPELL_EFFECT_SEND_EVENT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_q11719_bloodspore_ruination_45997_SpellScript(); + } +}; + +class npc_bloodmage_laurith : public CreatureScript +{ +public: + npc_bloodmage_laurith() : CreatureScript("npc_bloodmage_laurith") { } + + struct npc_bloodmage_laurithAI : public ScriptedAI + { + npc_bloodmage_laurithAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() override + { + _events.Reset(); + _playerGUID = 0; + } + + void SetGUID(uint64 guid, int32 /*action*/) override + { + if (_playerGUID) + return; + + _playerGUID = guid; + + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + me->SetFacingToObject(player); + + _events.ScheduleEvent(EVENT_TALK, 1000); + } + + void UpdateAI(uint32 diff) override + { + if (UpdateVictim()) + { + DoMeleeAttackIfReady(); + return; + } + + _events.Update(diff); + + if (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_TALK: + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) + Talk(SAY_BLOODMAGE_LAURITH, player); + _playerGUID = 0; + _events.ScheduleEvent(EVENT_RESET_ORIENTATION, 5000); + break; + case EVENT_RESET_ORIENTATION: + me->SetFacingTo(me->GetHomePosition().GetOrientation()); + break; + } + } + } + + private: + EventMap _events; + uint64 _playerGUID; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_bloodmage_laurithAI(creature); + } +}; + void AddSC_borean_tundra() { // Ours @@ -1283,4 +1385,6 @@ void AddSC_borean_tundra() new npc_valiance_keep_cannoneer(); new npc_warmage_coldarra(); new npc_hidden_cultist(); + new spell_q11719_bloodspore_ruination_45997(); + new npc_bloodmage_laurith(); } diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp index 367b5231f1..140029352a 100644 --- a/src/server/scripts/Northrend/zone_dalaran.cpp +++ b/src/server/scripts/Northrend/zone_dalaran.cpp @@ -576,13 +576,15 @@ class npc_minigob_manabonk : public CreatureScript events.ScheduleEvent(EVENT_BLINK, 3*IN_MILLISECONDS); break; case EVENT_BLINK: + { DoCast(me, SPELL_IMPROVED_BLINK); Position pos; me->GetRandomNearPosition(pos, (urand(15, 40))); me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - events.ScheduleEvent(EVENT_DESPAWN, 3*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_DESPAWN, 3 * IN_MILLISECONDS); events.ScheduleEvent(EVENT_DESPAWN_VISUAL, 2.5*IN_MILLISECONDS); break; + } case EVENT_DESPAWN_VISUAL: DoCast(me, SPELL_TELEPORT_VISUAL); break; diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp index 0a9b095316..5297bbc4ce 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp @@ -104,11 +104,13 @@ class boss_mechano_lord_capacitus : public CreatureScript events.ScheduleEvent(EVENT_REFLECTIVE_DAMAGE_SHIELD, 20000); break; case EVENT_SUMMON_NETHER_CHARGE: + { Position pos; me->GetRandomNearPosition(pos, 8.0f); me->SummonCreature(NPC_NETHER_CHARGE, pos, TEMPSUMMON_TIMED_DESPAWN, 18000); events.ScheduleEvent(EVENT_SUMMON_NETHER_CHARGE, 5000); break; + } case EVENT_POSITIVE_SHIFT: me->CastSpell(me, SPELL_POLARITY_SHIFT, true); events.ScheduleEvent(EVENT_POSITIVE_SHIFT, 30000); diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index a8089857b9..4642e9a131 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -52,6 +52,7 @@ class npc_pet_mage_mirror_image : public CreatureScript uint32 selectionTimer; uint64 _ebonGargoyleGUID; + uint32 checktarget; void InitializeAI() { @@ -135,7 +136,7 @@ class npc_pet_mage_mirror_image : public CreatureScript } } - bool MySelectNextTarget() + void MySelectNextTarget() { if (_ebonGargoyleGUID) { @@ -153,21 +154,27 @@ class npc_pet_mage_mirror_image : public CreatureScript // target has cc, search target without cc! if (selection->HasBreakableByDamageCrowdControlAura() || !me->IsValidAttackTarget(selection)) { - return false; + EnterEvadeMode(); + return; } me->getThreatManager().resetAllAggro(); me->AddThreat(selection, 1000000.0f); - AttackStart(selection); - return true; + + if (owner->IsInCombat()) + AttackStart(selection); + } } - return false; + + if (!me->GetVictim() || !me->GetVictim()->IsAlive()) + return; } void Reset() { selectionTimer = 0; + checktarget = 0; } void UpdateAI(uint32 diff) @@ -182,12 +189,15 @@ class npc_pet_mage_mirror_image : public CreatureScript return; } - if (me->GetVictim()->HasBreakableByDamageCrowdControlAura() || !me->GetVictim()->IsAlive()) + checktarget += diff; + if (checktarget >= 1000) { - me->InterruptNonMeleeSpells(false); - if (!MySelectNextTarget()) - EnterEvadeMode(); - return; + if (me->GetVictim()->HasBreakableByDamageCrowdControlAura() || !me->GetVictim()->IsAlive()) + { + MySelectNextTarget(); + me->InterruptNonMeleeSpells(true); // Stop casting if target is C or not Alive. + return; + } } selectionTimer += diff; diff --git a/src/server/scripts/ScriptLoader.cpp b/src/server/scripts/ScriptLoader.cpp index d948a18c55..a5e9f710e9 100644 --- a/src/server/scripts/ScriptLoader.cpp +++ b/src/server/scripts/ScriptLoader.cpp @@ -46,6 +46,7 @@ void AddSC_list_commandscript(); void AddSC_lookup_commandscript(); void AddSC_message_commandscript(); void AddSC_misc_commandscript(); +void AddSC_mmaps_commandscript(); void AddSC_modify_commandscript(); void AddSC_npc_commandscript(); void AddSC_quest_commandscript(); @@ -616,6 +617,7 @@ void AddCommandScripts() AddSC_lookup_commandscript(); AddSC_message_commandscript(); AddSC_misc_commandscript(); + AddSC_mmaps_commandscript(); AddSC_modify_commandscript(); AddSC_npc_commandscript(); AddSC_quest_commandscript(); @@ -1169,3 +1171,15 @@ void AddOutdoorPvPScripts() #endif } + +//~ ********************** Put your custom scripts below, like the commented examples, uncomment and edit ************************************* + + +//~ void AddSC_MySuperScript(); + +void AddCustomScripts() +{ +#ifdef SCRIPTS + //~ AddSC_MySuperScript(); +#endif +} diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index fbbbbbe15a..27263233f8 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -1545,12 +1545,16 @@ class spell_dk_death_grip : public SpellScriptLoader { PrepareSpellScript(spell_dk_death_grip_SpellScript); - SpellCastResult CheckPvPRange() + SpellCastResult CheckCast() { Unit* caster = GetCaster(); - if (Unit* target = GetExplTargetUnit()) - if (target->GetTypeId() == TYPEID_PLAYER && caster->GetExactDist(target) < 8.0f) // xinef: should be 8.0f, but we have to add target size (1.5f) - return SPELL_FAILED_TOO_CLOSE; + Unit* target = GetExplTargetUnit(); + + if (target->GetTypeId() == TYPEID_PLAYER && caster->GetExactDist(target) < 8.0f) // xinef: should be 8.0f, but we have to add target size (1.5f) + return SPELL_FAILED_TOO_CLOSE; + + if (caster->HasUnitState(UNIT_STATE_JUMPING) || caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) + return SPELL_FAILED_MOVING; return SPELL_CAST_OK; } @@ -1560,9 +1564,22 @@ class spell_dk_death_grip : public SpellScriptLoader Unit* caster = GetCaster(); Unit* target = GetHitUnit(); Unit* baseTarget = GetExplTargetUnit(); + Creature* targetCreature = GetHitCreature(); if (caster != target) - caster->CastSpell(target, 49560, true); + { + if (targetCreature && (targetCreature->isWorldBoss() || targetCreature->IsDungeonBoss())) + { + return; + } + else + { + caster->CastSpell(target, 49560, true); + const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(1766); // Rogue kick + if (!target->IsImmunedToSpellEffect(spellInfo, EFFECT_0)) + target->InterruptNonMeleeSpells(true); + } + } else baseTarget->CastSpell(caster, 49560, true); } @@ -1592,7 +1609,7 @@ class spell_dk_death_grip : public SpellScriptLoader { if (m_scriptSpellId == 49576) // xinef: base death grip, add pvp range restriction { - OnCheckCast += SpellCheckCastFn(spell_dk_death_grip_SpellScript::CheckPvPRange); + OnCheckCast += SpellCheckCastFn(spell_dk_death_grip_SpellScript::CheckCast); OnEffectHitTarget += SpellEffectFn(spell_dk_death_grip_SpellScript::HandleBaseDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } else diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 4821e57555..f0ac73e39c 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4431,10 +4431,7 @@ class spell_gen_mount : public SpellScriptLoader if (map == 530 || (map == 571 && target->HasSpell(SPELL_COLD_WEATHER_FLYING))) canFly = true; - float x, y, z; - target->GetPosition(x, y, z); - uint32 areaFlag = target->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* area = sAreaStore.LookupEntry(areaFlag); + AreaTableEntry const* area = sAreaTableStore.LookupEntry(target->GetAreaId()); // Xinef: add battlefield check Battlefield* Bf = sBattlefieldMgr->GetBattlefieldToZoneId(target->GetZoneId()); if (!area || (canFly && ((area->flags & AREA_FLAG_NO_FLY_ZONE) || (Bf && !Bf->CanFlyIn())))) diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 2ea90c230c..45b3ac2640 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -592,7 +592,7 @@ class spell_warr_overpower : public SpellScriptLoader if (Player* target = GetHitPlayer()) if (target->HasUnitState(UNIT_STATE_CASTING)) - target->CastSpell(target, spellId, true); + target->CastSpell(target, spellId, true, 0, 0, GetCaster()->GetGUID()); } void Register() diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index a0a9f893b5..95c4db4801 100644 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -112,10 +112,10 @@ class achievement_bg_sa_artillery : public AchievementCriteriaScript } }; -class achievement_arena_kills : public AchievementCriteriaScript +class achievement_arena_by_type : public AchievementCriteriaScript { public: - achievement_arena_kills(char const* name, uint8 arenaType) : AchievementCriteriaScript(name), + achievement_arena_by_type(char const* name, uint8 arenaType) : AchievementCriteriaScript(name), _arenaType(arenaType) { } @@ -129,7 +129,6 @@ class achievement_arena_kills : public AchievementCriteriaScript uint8 const _arenaType; }; - class achievement_sickly_gazelle : public AchievementCriteriaScript { public: @@ -254,9 +253,9 @@ void AddSC_achievement_scripts() new achievement_sickly_gazelle(); new achievement_everything_counts(); new achievement_bg_av_perfection(); - new achievement_arena_kills("achievement_arena_2v2_kills", ARENA_TYPE_2v2); - new achievement_arena_kills("achievement_arena_3v3_kills", ARENA_TYPE_3v3); - new achievement_arena_kills("achievement_arena_5v5_kills", ARENA_TYPE_5v5); + new achievement_arena_by_type("achievement_arena_2v2_check", ARENA_TYPE_2v2); + new achievement_arena_by_type("achievement_arena_3v3_check", ARENA_TYPE_3v3); + new achievement_arena_by_type("achievement_arena_5v5_check", ARENA_TYPE_5v5); new achievement_sa_defense_of_the_ancients(); new achievement_tilted(); new achievement_not_even_a_scratch(); diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 58ec995c4e..fdc17078bc 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -44,7 +44,7 @@ endif() include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/deps/g3dlite/include - ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/deps/recastnavigation/Detour/Include ${CMAKE_SOURCE_DIR}/deps/gsoap ${CMAKE_SOURCE_DIR}/deps/sockets/include ${CMAKE_SOURCE_DIR}/deps/SFMT diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 5ad7a5bc3b..66fa7fb615 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1434,16 +1434,6 @@ DeletedCharacterTicketTrace = 0 DungeonFinder.OptionsMask = 1 - -# -# DBC.EnforceItemAttributes -# Description: Disallow overriding item attributes stored in DBC files with values from the -# database. -# Default: 1 - (Enabled, Enforce DBC values) -# 0 - (Disabled, Use database values) - -DBC.EnforceItemAttributes = 1 - # # AccountInstancesPerHour # Description: Controls the max amount of different instances player can enter within hour diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index 2c00a7e130..f127b496a1 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -12,8 +12,10 @@ file(GLOB_RECURSE sources *.cpp *.h) set(include_Dirs + ${CMAKE_SOURCE_DIR}/src/common/Utilities ${CMAKE_SOURCE_DIR}/src/common ${CMAKE_SOURCE_DIR}/deps/libmpq + ${CMAKE_SOURCE_DIR}/modules/worldengine/deps/g3dlite/include ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/loadlib ) diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index defab209d7..a22abb3ded 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -20,9 +20,12 @@ #include "dbcfile.h" #include "mpq_libmpq04.h" +#include "StringFormat.h" #include "adt.h" #include "wdt.h" + +#include "G3D/Plane.h" #include <fcntl.h> #if defined( __GNUC__ ) @@ -49,11 +52,10 @@ typedef struct } map_id; map_id *map_ids; -uint16 *areas; uint16 *LiqType; -char output_path[128] = "."; -char input_path[128] = "."; -uint32 maxAreaId = 0; +#define MAX_PATH_LENGTH 128 +char output_path[MAX_PATH_LENGTH] = "."; +char input_path[MAX_PATH_LENGTH] = "."; // ************************************************** // Extractor options @@ -244,30 +246,6 @@ uint32 ReadMapDBC() return map_count; } -void ReadAreaTableDBC() -{ - printf("Read AreaTable.dbc file..."); - DBCFile dbc("DBFilesClient\\AreaTable.dbc"); - - if(!dbc.open()) - { - printf("Fatal error: Invalid AreaTable.dbc file format!\n"); - exit(1); - } - - size_t area_count = dbc.getRecordCount(); - size_t maxid = dbc.getMaxId(); - areas = new uint16[maxid + 1]; - memset(areas, 0xff, (maxid + 1) * sizeof(uint16)); - - for(uint32 x = 0; x < area_count; ++x) - areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); - - maxAreaId = dbc.getMaxId(); - - printf("Done! (%u areas loaded)\n", (uint32)area_count); -} - void ReadLiquidTypeTableDBC() { printf("Read LiquidType.dbc file..."); @@ -295,7 +273,7 @@ void ReadLiquidTypeTableDBC() // Map file format data static char const* MAP_MAGIC = "MAPS"; -static char const* MAP_VERSION_MAGIC = "v1.3"; +static char const* MAP_VERSION_MAGIC = "v1.8"; static char const* MAP_AREA_MAGIC = "AREA"; static char const* MAP_HEIGHT_MAGIC = "MHGT"; static char const* MAP_LIQUID_MAGIC = "MLIQ"; @@ -324,9 +302,10 @@ struct map_areaHeader uint16 gridArea; }; -#define MAP_HEIGHT_NO_HEIGHT 0x0001 -#define MAP_HEIGHT_AS_INT16 0x0002 -#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_NO_HEIGHT 0x0001 +#define MAP_HEIGHT_AS_INT16 0x0002 +#define MAP_HEIGHT_AS_INT8 0x0004 +#define MAP_HEIGHT_HAS_FLIGHT_BOUNDS 0x0008 struct map_heightHeader { @@ -371,7 +350,7 @@ float selectUInt16StepStore(float maxDiff) return 65535 / maxDiff; } // Temporary grid data store -uint16 area_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; +uint16 area_ids[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; float V8[ADT_GRID_SIZE][ADT_GRID_SIZE]; float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; @@ -385,17 +364,20 @@ uint8 liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE]; float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; -bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, uint32 build) +int16 flight_box_max[3][3]; +int16 flight_box_min[3][3]; + +bool ConvertADT(std::string const& inputPath, std::string const& outputPath, int /*cell_y*/, int /*cell_x*/, uint32 build) { ADT_file adt; - if (!adt.loadFile(filename)) + if (!adt.loadFile(inputPath)) return false; adt_MCIN *cells = adt.a_grid->getMCIN(); if (!cells) { - printf("Can't find cells in '%s'\n", filename); + printf("Can't find cells in '%s'\n", inputPath.c_str()); return false; } @@ -405,39 +387,25 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // Prepare map header map_fileheader map; - map.mapMagic = *(uint32 const*)MAP_MAGIC; - map.versionMagic = *(uint32 const*)MAP_VERSION_MAGIC; + map.mapMagic = *reinterpret_cast<uint32 const*>(MAP_MAGIC); + map.versionMagic = *reinterpret_cast<uint32 const*>(MAP_VERSION_MAGIC); map.buildMagic = build; // Get area flags data - for (int i=0;i<ADT_CELLS_PER_GRID;i++) - { - for(int j=0;j<ADT_CELLS_PER_GRID;j++) - { - adt_MCNK * cell = cells->getMCNK(i,j); - uint32 areaid = cell->areaid; - if(areaid && areaid <= maxAreaId) - { - if(areas[areaid] != 0xffff) - { - area_flags[i][j] = areas[areaid]; - continue; - } - printf("File: %s\nCan't find area flag for areaid %u [%d, %d].\n", filename, areaid, cell->ix, cell->iy); - } - area_flags[i][j] = 0xffff; - } - } + for (int i = 0; i < ADT_CELLS_PER_GRID; i++) + for (int j = 0; j < ADT_CELLS_PER_GRID; j++) + area_ids[i][j] = cells->getMCNK(i, j)->areaid; + //============================================ // Try pack area data //============================================ bool fullAreaData = false; - uint32 areaflag = area_flags[0][0]; - for (int y=0;y<ADT_CELLS_PER_GRID;y++) + uint32 areaId = area_ids[0][0]; + for (int y = 0; y < ADT_CELLS_PER_GRID; ++y) { - for(int x=0;x<ADT_CELLS_PER_GRID;x++) + for (int x = 0; x < ADT_CELLS_PER_GRID; ++x) { - if(area_flags[y][x]!=areaflag) + if (area_ids[y][x] != areaId) { fullAreaData = true; break; @@ -449,27 +417,27 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, map.areaMapSize = sizeof(map_areaHeader); map_areaHeader areaHeader; - areaHeader.fourcc = *(uint32 const*)MAP_AREA_MAGIC; + areaHeader.fourcc = *reinterpret_cast<uint32 const*>(MAP_AREA_MAGIC); areaHeader.flags = 0; if (fullAreaData) { areaHeader.gridArea = 0; - map.areaMapSize+=sizeof(area_flags); + map.areaMapSize += sizeof(area_ids); } else { areaHeader.flags |= MAP_AREA_NO_AREA; - areaHeader.gridArea = (uint16)areaflag; + areaHeader.gridArea = static_cast<uint16>(areaId); } // // Get Height map from grid // - for (int i=0;i<ADT_CELLS_PER_GRID;i++) + for (int i = 0; i<ADT_CELLS_PER_GRID; i++) { - for(int j=0;j<ADT_CELLS_PER_GRID;j++) + for (int j = 0; j<ADT_CELLS_PER_GRID; j++) { - adt_MCNK * cell = cells->getMCNK(i,j); + adt_MCNK * cell = cells->getMCNK(i, j); if (!cell) continue; // Height values for triangles stored in order: @@ -489,22 +457,22 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // . . . . . . . . // Set map height as grid height - for (int y=0; y <= ADT_CELL_SIZE; y++) + for (int y = 0; y <= ADT_CELL_SIZE; y++) { int cy = i*ADT_CELL_SIZE + y; - for (int x=0; x <= ADT_CELL_SIZE; x++) + for (int x = 0; x <= ADT_CELL_SIZE; x++) { int cx = j*ADT_CELL_SIZE + x; - V9[cy][cx]=cell->ypos; + V9[cy][cx] = cell->ypos; } } - for (int y=0; y < ADT_CELL_SIZE; y++) + for (int y = 0; y < ADT_CELL_SIZE; y++) { int cy = i*ADT_CELL_SIZE + y; - for (int x=0; x < ADT_CELL_SIZE; x++) + for (int x = 0; x < ADT_CELL_SIZE; x++) { int cx = j*ADT_CELL_SIZE + x; - V8[cy][cx]=cell->ypos; + V8[cy][cx] = cell->ypos; } } // Get custom height @@ -512,23 +480,23 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, if (!v) continue; // get V9 height map - for (int y=0; y <= ADT_CELL_SIZE; y++) + for (int y = 0; y <= ADT_CELL_SIZE; y++) { int cy = i*ADT_CELL_SIZE + y; - for (int x=0; x <= ADT_CELL_SIZE; x++) + for (int x = 0; x <= ADT_CELL_SIZE; x++) { int cx = j*ADT_CELL_SIZE + x; - V9[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+x]; + V9[cy][cx] += v->height_map[y*(ADT_CELL_SIZE * 2 + 1) + x]; } } // get V8 height map - for (int y=0; y < ADT_CELL_SIZE; y++) + for (int y = 0; y < ADT_CELL_SIZE; y++) { int cy = i*ADT_CELL_SIZE + y; - for (int x=0; x < ADT_CELL_SIZE; x++) + for (int x = 0; x < ADT_CELL_SIZE; x++) { int cx = j*ADT_CELL_SIZE + x; - V8[cy][cx]+=v->height_map[y*(ADT_CELL_SIZE*2+1)+ADT_CELL_SIZE+1+x]; + V8[cy][cx] += v->height_map[y*(ADT_CELL_SIZE * 2 + 1) + ADT_CELL_SIZE + 1 + x]; } } } @@ -538,18 +506,18 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, //============================================ float maxHeight = -20000; float minHeight = 20000; - for (int y=0; y<ADT_GRID_SIZE; y++) + for (int y = 0; y<ADT_GRID_SIZE; y++) { - for(int x=0;x<ADT_GRID_SIZE;x++) + for (int x = 0; x<ADT_GRID_SIZE; x++) { float h = V8[y][x]; if (maxHeight < h) maxHeight = h; if (minHeight > h) minHeight = h; } } - for (int y=0; y<=ADT_GRID_SIZE; y++) + for (int y = 0; y <= ADT_GRID_SIZE; y++) { - for(int x=0;x<=ADT_GRID_SIZE;x++) + for(int x = 0; x<= ADT_GRID_SIZE; x++) { float h = V9[y][x]; if (maxHeight < h) maxHeight = h; @@ -560,12 +528,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // Check for allow limit minimum height (not store height in deep ochean - allow save some memory) if (CONF_allow_height_limit && minHeight < CONF_use_minHeight) { - for (int y=0; y<ADT_GRID_SIZE; y++) - for(int x=0;x<ADT_GRID_SIZE;x++) + for (int y = 0; y<ADT_GRID_SIZE; y++) + for (int x = 0; x<ADT_GRID_SIZE; x++) if (V8[y][x] < CONF_use_minHeight) V8[y][x] = CONF_use_minHeight; - for (int y=0; y<=ADT_GRID_SIZE; y++) - for(int x=0;x<=ADT_GRID_SIZE;x++) + for (int y = 0; y <= ADT_GRID_SIZE; y++) + for (int x = 0; x <= ADT_GRID_SIZE; x++) if (V9[y][x] < CONF_use_minHeight) V9[y][x] = CONF_use_minHeight; if (minHeight < CONF_use_minHeight) @@ -574,11 +542,19 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, maxHeight = CONF_use_minHeight; } + bool hasFlightBox = false; + if (adt_MFBO* mfbo = adt.a_grid->getMFBO()) + { + memcpy(flight_box_max, &mfbo->max, sizeof(flight_box_max)); + memcpy(flight_box_min, &mfbo->min, sizeof(flight_box_min)); + hasFlightBox = true; + } + map.heightMapOffset = map.areaMapOffset + map.areaMapSize; map.heightMapSize = sizeof(map_heightHeader); map_heightHeader heightHeader; - heightHeader.fourcc = *(uint32 const*)MAP_HEIGHT_MAGIC; + heightHeader.fourcc = *reinterpret_cast<uint32 const*>(MAP_HEIGHT_MAGIC); heightHeader.flags = 0; heightHeader.gridHeight = minHeight; heightHeader.gridMaxHeight = maxHeight; @@ -589,6 +565,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // Not need store if flat surface if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_height_delta_limit) heightHeader.flags |= MAP_HEIGHT_NO_HEIGHT; + + if (hasFlightBox) + { + heightHeader.flags |= MAP_HEIGHT_HAS_FLIGHT_BOUNDS; + map.heightMapSize += sizeof(flight_box_max) + sizeof(flight_box_min); + } // Try store as packed in uint16 or uint8 values if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT)) @@ -600,12 +582,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, float diff = maxHeight - minHeight; if (diff < CONF_float_to_int8_limit) // As uint8 (max accuracy = CONF_float_to_int8_limit/256) { - heightHeader.flags|=MAP_HEIGHT_AS_INT8; + heightHeader.flags |= MAP_HEIGHT_AS_INT8; step = selectUInt8StepStore(diff); } else if (diff<CONF_float_to_int16_limit) // As uint16 (max accuracy = CONF_float_to_int16_limit/65536) { - heightHeader.flags|=MAP_HEIGHT_AS_INT16; + heightHeader.flags |= MAP_HEIGHT_AS_INT16; step = selectUInt16StepStore(diff); } } @@ -613,32 +595,32 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // Pack it to int values if need if (heightHeader.flags&MAP_HEIGHT_AS_INT8) { - for (int y=0; y<ADT_GRID_SIZE; y++) - for(int x=0;x<ADT_GRID_SIZE;x++) + for (int y = 0; y<ADT_GRID_SIZE; y++) + for (int x = 0; x<ADT_GRID_SIZE; x++) uint8_V8[y][x] = uint8((V8[y][x] - minHeight) * step + 0.5f); - for (int y=0; y<=ADT_GRID_SIZE; y++) - for(int x=0;x<=ADT_GRID_SIZE;x++) + for (int y = 0; y <= ADT_GRID_SIZE; y++) + for (int x = 0; x <= ADT_GRID_SIZE; x++) uint8_V9[y][x] = uint8((V9[y][x] - minHeight) * step + 0.5f); - map.heightMapSize+= sizeof(uint8_V9) + sizeof(uint8_V8); + map.heightMapSize += sizeof(uint8_V9) + sizeof(uint8_V8); } else if (heightHeader.flags&MAP_HEIGHT_AS_INT16) { - for (int y=0; y<ADT_GRID_SIZE; y++) - for(int x=0;x<ADT_GRID_SIZE;x++) + for (int y = 0; y<ADT_GRID_SIZE; y++) + for (int x = 0; x<ADT_GRID_SIZE; x++) uint16_V8[y][x] = uint16((V8[y][x] - minHeight) * step + 0.5f); - for (int y=0; y<=ADT_GRID_SIZE; y++) - for(int x=0;x<=ADT_GRID_SIZE;x++) + for (int y = 0; y <= ADT_GRID_SIZE; y++) + for (int x = 0; x <= ADT_GRID_SIZE; x++) uint16_V9[y][x] = uint16((V9[y][x] - minHeight) * step + 0.5f); - map.heightMapSize+= sizeof(uint16_V9) + sizeof(uint16_V8); + map.heightMapSize += sizeof(uint16_V9) + sizeof(uint16_V8); } else - map.heightMapSize+= sizeof(V9) + sizeof(V8); + map.heightMapSize += sizeof(V9) + sizeof(V8); } // Get from MCLQ chunk (old) for (int i = 0; i < ADT_CELLS_PER_GRID; i++) { - for(int j = 0; j < ADT_CELLS_PER_GRID; j++) + for (int j = 0; j < ADT_CELLS_PER_GRID; j++) { adt_MCNK *cell = cells->getMCNK(i, j); if (!cell) @@ -658,7 +640,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, if (liquid->flags[y][x] != 0x0F) { liquid_show[cy][cx] = true; - if (liquid->flags[y][x] & (1<<7)) + if (liquid->flags[y][x] & (1 << 7)) liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER; ++count; } @@ -666,17 +648,17 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, } uint32 c_flag = cell->flags; - if (c_flag & (1<<2)) + if (c_flag & (1 << 2)) { liquid_entry[i][j] = 1; liquid_flags[i][j] |= MAP_LIQUID_TYPE_WATER; // water } - if (c_flag & (1<<3)) + if (c_flag & (1 << 3)) { liquid_entry[i][j] = 2; liquid_flags[i][j] |= MAP_LIQUID_TYPE_OCEAN; // ocean } - if (c_flag & (1<<4)) + if (c_flag & (1 << 4)) { liquid_entry[i][j] = 3; liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA; // magma/slime @@ -734,7 +716,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, case LIQUID_TYPE_MAGMA: liquid_flags[i][j] |= MAP_LIQUID_TYPE_MAGMA; break; case LIQUID_TYPE_SLIME: liquid_flags[i][j] |= MAP_LIQUID_TYPE_SLIME; break; default: - printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, filename, i, j); + printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, inputPath.c_str(), i, j); break; } // Dark water detect @@ -877,17 +859,17 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, map.holesSize = 0; // Ok all data prepared - store it - FILE* output = fopen(filename2, "wb"); + FILE* output = fopen(outputPath.c_str(), "wb"); if (!output) { - printf("Can't create the output file '%s'\n", filename2); + printf("Can't create the output file '%s'\n", outputPath.c_str()); return false; } fwrite(&map, sizeof(map), 1, output); // Store area data fwrite(&areaHeader, sizeof(areaHeader), 1, output); if (!(areaHeader.flags&MAP_AREA_NO_AREA)) - fwrite(area_flags, sizeof(area_flags), 1, output); + fwrite(area_ids, sizeof(area_ids), 1, output); // Store height data fwrite(&heightHeader, sizeof(heightHeader), 1, output); @@ -910,6 +892,12 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, } } + if (heightHeader.flags & MAP_HEIGHT_HAS_FLIGHT_BOUNDS) + { + fwrite(flight_box_max, sizeof(flight_box_max), 1, output); + fwrite(flight_box_min, sizeof(flight_box_min), 1, output); + } + // Store liquid data if need if (map.liquidMapOffset) { @@ -937,15 +925,14 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, void ExtractMapsFromMpq(uint32 build) { - char mpq_filename[1024]; - char output_filename[1024]; - char mpq_map_name[1024]; + std::string mpqFileName; + std::string outputFileName; + std::string mpqMapName; printf("Extracting maps...\n"); uint32 map_count = ReadMapDBC(); - ReadAreaTableDBC(); ReadLiquidTypeTableDBC(); std::string path = output_path; @@ -957,9 +944,9 @@ void ExtractMapsFromMpq(uint32 build) { printf("Extract %s (%d/%u) \n", map_ids[z].name, z+1, map_count); // Loadup map grid data - sprintf(mpq_map_name, "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name); + mpqMapName = Trinity::StringFormat("World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name); WDT_file wdt; - if (!wdt.loadFile(mpq_map_name, false)) + if (!wdt.loadFile(mpqMapName, false)) { // printf("Error loading %s map wdt data\n", map_ids[z].name); continue; @@ -971,17 +958,16 @@ void ExtractMapsFromMpq(uint32 build) { if (!wdt.main->adt_list[y][x].exist) continue; - sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y); - sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x); - ConvertADT(mpq_filename, output_filename, y, x, build); + mpqFileName = Trinity::StringFormat("World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y); + outputFileName = Trinity::StringFormat("%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x); + ConvertADT(mpqFileName, outputFileName, y, x, build); } // draw progress bar printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE); } } printf("\n"); - delete [] areas; - delete [] map_ids; + delete[] map_ids; } bool ExtractFile( char const* mpq_name, std::string const& filename ) diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp index 574167c216..257d0171aa 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -9,15 +9,16 @@ #include "adt.h" // Helper -int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; -int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; +int holetab_h[4] = { 0x1111, 0x2222, 0x4444, 0x8888 }; +int holetab_v[4] = { 0x000F, 0x00F0, 0x0F00, 0xF000 }; -u_map_fcc MHDRMagic = { {'R','D','H','M'} }; -u_map_fcc MCINMagic = { {'N','I','C','M'} }; -u_map_fcc MH2OMagic = { {'O','2','H','M'} }; -u_map_fcc MCNKMagic = { {'K','N','C','M'} }; -u_map_fcc MCVTMagic = { {'T','V','C','M'} }; -u_map_fcc MCLQMagic = { {'Q','L','C','M'} }; +u_map_fcc MHDRMagic = { { 'R','D','H','M' } }; +u_map_fcc MCINMagic = { { 'N','I','C','M' } }; +u_map_fcc MH2OMagic = { { 'O','2','H','M' } }; +u_map_fcc MCNKMagic = { { 'K','N','C','M' } }; +u_map_fcc MCVTMagic = { { 'T','V','C','M' } }; +u_map_fcc MCLQMagic = { { 'Q','L','C','M' } }; +u_map_fcc MFBOMagic = { { 'O','B','F','M' } }; bool isHole(int holes, int i, int j) { @@ -69,7 +70,7 @@ bool adt_MHDR::prepareLoadedData() if (fcc != MHDRMagic.fcc) return false; - if (size!=sizeof(adt_MHDR)-8) + if (size != sizeof(adt_MHDR) - 8) return false; // Check and prepare MCIN @@ -80,6 +81,9 @@ bool adt_MHDR::prepareLoadedData() if (offsMH2O && !getMH2O()->prepareLoadedData()) return false; + if (offsMFBO && flags & 1 && !getMFBO()->prepareLoadedData()) + return false; + return true; } @@ -142,3 +146,8 @@ bool adt_MCLQ::prepareLoadedData() return true; } + +bool adt_MFBO::prepareLoadedData() +{ + return fcc == MFBOMagic.fcc; +} diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h index 71e83cd999..94b830c4ef 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -248,6 +248,27 @@ public: }; +// Adt file min/max height chunk +// +class adt_MFBO +{ + union + { + uint32 fcc; + char fcc_txt[4]; + }; +public: + uint32 size; + struct plane + { + int16 coords[9]; + }; + plane max; + plane min; + + bool prepareLoadedData(); +}; + // // Adt file header chunk // @@ -260,12 +281,12 @@ class adt_MHDR public: uint32 size; - uint32 pad; + uint32 flags; uint32 offsMCIN; // MCIN - uint32 offsTex; // MTEX - uint32 offsModels; // MMDX - uint32 offsModelsIds; // MMID - uint32 offsMapObejcts; // MWMO + uint32 offsTex; // MTEX + uint32 offsModels; // MMDX + uint32 offsModelsIds; // MMID + uint32 offsMapObejcts; // MWMO uint32 offsMapObejctsIds; // MWID uint32 offsDoodsDef; // MDDF uint32 offsObjectsDef; // MODF @@ -278,9 +299,22 @@ public: uint32 data5; public: bool prepareLoadedData(); - adt_MCIN *getMCIN(){ return (adt_MCIN *)((uint8 *)&pad+offsMCIN);} - adt_MH2O *getMH2O(){ return offsMH2O ? (adt_MH2O *)((uint8 *)&pad+offsMH2O) : 0;} - + adt_MCIN* getMCIN() + { + return reinterpret_cast<adt_MCIN*>(reinterpret_cast<uint8*>(&flags) + offsMCIN); + } + adt_MH2O* getMH2O() + { + if (offsMH2O) + return reinterpret_cast<adt_MH2O*>(reinterpret_cast<uint8*>(&flags) + offsMH2O); + return nullptr; + } + adt_MFBO* getMFBO() + { + if (flags & 1 && offsMFBO) + return reinterpret_cast<adt_MFBO*>(reinterpret_cast<uint8*>(&flags) + offsMFBO); + return nullptr; + } }; class ADT_file : public FileLoader{ diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index 2a3b0482f5..1219ef78b5 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -26,14 +26,14 @@ FileLoader::~FileLoader() free(); } -bool FileLoader::loadFile(char *filename, bool log) +bool FileLoader::loadFile(std::string const& fileName, bool log) { free(); - MPQFile mf(filename); + MPQFile mf(fileName.c_str()); if(mf.isEof()) { if (log) - printf("No such file %s\n", filename); + printf("No such file %s\n", fileName.c_str()); return false; } @@ -45,7 +45,7 @@ bool FileLoader::loadFile(char *filename, bool log) if (prepareLoadedData()) return true; - printf("Error loading %s", filename); + printf("Error loading %s", fileName.c_str()); mf.close(); free(); return false; diff --git a/src/tools/map_extractor/loadlib/loadlib.h b/src/tools/map_extractor/loadlib/loadlib.h index a2169b6b4b..e500f25e6e 100644 --- a/src/tools/map_extractor/loadlib/loadlib.h +++ b/src/tools/map_extractor/loadlib/loadlib.h @@ -7,6 +7,8 @@ #ifndef LOAD_LIB_H #define LOAD_LIB_H +#include <string> + #ifdef _WIN32 typedef __int64 int64; typedef __int32 int32; @@ -65,7 +67,7 @@ public: file_MVER *version; FileLoader(); ~FileLoader(); - bool loadFile(char *filename, bool log = true); + bool loadFile(std::string const& filename, bool log = true); virtual void free(); }; #endif diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h index bf98e65f01..2daa23d854 100644 --- a/src/tools/mesh_extractor/Utils.h +++ b/src/tools/mesh_extractor/Utils.h @@ -341,7 +341,7 @@ public: }; #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' -#define MMAP_VERSION 3 +#define MMAP_VERSION 8 struct MmapTileHeader { diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index e5edd4a611..94780d7422 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -17,14 +17,13 @@ #include "DisableMgr.h" #include <ace/OS_NS_unistd.h> -uint32 GetLiquidFlags(uint32 /*liquidType*/) { return 0; } namespace DisableMgr { bool IsDisabledFor(DisableType /*type*/, uint32 /*entry*/, Unit const* /*unit*/, uint8 /*flags*/ /*= 0*/) { return false; } } #define MMAP_MAGIC 0x4d4d4150 // 'MMAP' -#define MMAP_VERSION 3 +#define MMAP_VERSION 8 struct MmapTileHeader { @@ -32,12 +31,22 @@ struct MmapTileHeader uint32 dtVersion; uint32 mmapVersion; uint32 size; - bool usesLiquids : 1; + char usesLiquids; + char padding[3]; MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), - mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) {} + mmapVersion(MMAP_VERSION), size(0), usesLiquids(true), padding() {} }; +// All padding fields must be handled and initialized to ensure mmaps_generator will produce binary-identical *.mmtile files +static_assert(sizeof(MmapTileHeader) == 20, "MmapTileHeader size is not correct, adjust the padding field size"); +static_assert(sizeof(MmapTileHeader) == (sizeof(MmapTileHeader::mmapMagic) + + sizeof(MmapTileHeader::dtVersion) + + sizeof(MmapTileHeader::mmapVersion) + + sizeof(MmapTileHeader::size) + + sizeof(MmapTileHeader::usesLiquids) + + sizeof(MmapTileHeader::padding)), "MmapTileHeader has uninitialized padding fields"); + namespace MMAP { MapBuilder::MapBuilder(float maxWalkableAngle, bool skipLiquid, @@ -57,6 +66,10 @@ namespace MMAP m_rcContext = new rcContext(false); + // percentageDone - Initializing + m_totalTiles = 0; + m_totalTilesBuilt = 0; + discoverTiles(); } @@ -65,8 +78,8 @@ namespace MMAP { for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - (*it).second->clear(); - delete (*it).second; + (*it).m_tiles->clear(); + delete (*it).m_tiles; } delete m_terrainBuilder; @@ -85,9 +98,9 @@ namespace MMAP for (uint32 i = 0; i < files.size(); ++i) { mapID = uint32(atoi(files[i].substr(0,3).c_str())); - if (m_tiles.find(mapID) == m_tiles.end()) + if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end()) { - m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, new std::set<uint32>)); + m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>)); count++; } } @@ -97,8 +110,11 @@ namespace MMAP for (uint32 i = 0; i < files.size(); ++i) { mapID = uint32(atoi(files[i].substr(0,3).c_str())); - m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, new std::set<uint32>)); - count++; + if (std::find(m_tiles.begin(), m_tiles.end(), mapID) == m_tiles.end()) + { + m_tiles.emplace_back(MapTiles(mapID, new std::set<uint32>)); + count++; + } } printf("found %u.\n", count); @@ -106,8 +122,8 @@ namespace MMAP printf("Discovering tiles... "); for (TileList::iterator itr = m_tiles.begin(); itr != m_tiles.end(); ++itr) { - std::set<uint32>* tiles = (*itr).second; - mapID = (*itr).first; + std::set<uint32>* tiles = (*itr).m_tiles; + mapID = (*itr).m_mapId; sprintf(filter, "%03u*.vmtile", mapID); files.clear(); @@ -136,17 +152,20 @@ namespace MMAP } } printf("found %u.\n\n", count); + + // percentageDone - total tiles to process + m_totalTiles = count; } /**************************************************************************/ std::set<uint32>* MapBuilder::getTileList(uint32 mapID) { - TileList::iterator itr = m_tiles.find(mapID); + TileList::iterator itr = std::find(m_tiles.begin(), m_tiles.end(), mapID); if (itr != m_tiles.end()) - return (*itr).second; + return (*itr).m_tiles; std::set<uint32>* tiles = new std::set<uint32>(); - m_tiles.insert(std::pair<uint32, std::set<uint32>*>(mapID, tiles)); + m_tiles.emplace_back(MapTiles(mapID, tiles)); return tiles; } @@ -157,9 +176,14 @@ namespace MMAP BuilderThreadPool* pool = threads > 0 ? new BuilderThreadPool() : NULL; + m_tiles.sort([](MapTiles a, MapTiles b) + { + return a.m_tiles->size() > b.m_tiles->size(); + }); + for (TileList::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - uint32 mapID = it->first; + uint32 mapID = it->m_mapId; if (!shouldSkipMap(mapID)) { if (threads > 0) @@ -183,12 +207,14 @@ namespace MMAP } /**************************************************************************/ - void MapBuilder::getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY) + void MapBuilder::getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY) const { - maxX = INT_MAX; - maxY = INT_MAX; - minX = INT_MIN; - minY = INT_MIN; + // min and max are initialized to invalid values so the caller iterating the [min, max] range + // will never enter the loop unless valid min/max values are found + maxX = 0; + maxY = 0; + minX = std::numeric_limits<uint32>::max(); + minY = std::numeric_limits<uint32>::max(); float bmin[3] = { 0, 0, 0 }; float bmax[3] = { 0, 0, 0 }; @@ -329,7 +355,7 @@ namespace MMAP void MapBuilder::buildMap(uint32 mapID) { #ifndef __APPLE__ - printf("[Thread %u] Building map %03u:\n", uint32(ACE_Thread::self()), mapID); + //printf("[Thread %u] Building map %03u:\n", uint32(ACE_Thread::self()), mapID); #endif std::set<uint32>* tiles = getTileList(mapID); @@ -382,7 +408,8 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh) { - printf("[Map %03i] Building tile [%02u,%02u]\n", mapID, tileX, tileY); + // percentageDone - added, now it will show addional reference percentage done of the overall process + printf("%u%% [Map %03i] Building tile [%02u,%02u]\n", percentageDone(m_totalTiles, m_totalTilesBuilt), mapID, tileX, tileY); MeshData meshData; @@ -416,6 +443,9 @@ namespace MMAP // build navmesh tile buildMoveMapTile(mapID, tileX, tileY, meshData, bmin, bmax, navMesh); + + // percentageDone - increment tiles built + m_totalTilesBuilt++; } /**************************************************************************/ @@ -429,7 +459,7 @@ namespace MMAP //if (tileBits < 1) tileBits = 1; // need at least one bit! //int polyBits = sizeof(dtPolyRef)*8 - SALT_MIN_BITS - tileBits; - int polyBits = STATIC_POLY_BITS; + int polyBits = DT_POLY_BITS; int maxTiles = tiles->size(); int maxPolysPerTile = 1 << polyBits; @@ -541,7 +571,9 @@ namespace MMAP config.borderSize = config.walkableRadius + 3; config.maxEdgeLen = VERTEX_PER_TILE + 1; // anything bigger than tileSize config.walkableHeight = m_bigBaseUnit ? 3 : 6; - config.walkableClimb = m_bigBaseUnit ? 2 : 4; // keep less than walkableHeight + // a value >= 3|6 allows npcs to walk over some fences + // a value >= 4|8 allows npcs to walk over all fences + config.walkableClimb = m_bigBaseUnit ? 4 : 8; config.minRegionArea = rcSqr(60); config.mergeRegionArea = rcSqr(50); config.maxSimplificationError = 1.8f; // eliminates most jagged edges (tiny polygons) @@ -665,7 +697,7 @@ namespace MMAP iv.polyMesh = rcAllocPolyMesh(); if (!iv.polyMesh) { - printf("%s alloc iv.polyMesh FIALED!\n", tileString); + printf("%s alloc iv.polyMesh FAILED!\n", tileString); delete[] pmmerge; delete[] dmmerge; delete[] tiles; @@ -676,7 +708,7 @@ namespace MMAP iv.polyMeshDetail = rcAllocPolyMeshDetail(); if (!iv.polyMeshDetail) { - printf("%s alloc m_dmesh FIALED!\n", tileString); + printf("%s alloc m_dmesh FAILED!\n", tileString); delete[] pmmerge; delete[] dmmerge; delete[] tiles; @@ -741,12 +773,12 @@ namespace MMAP if (params.nvp > DT_VERTS_PER_POLYGON) { printf("%s Invalid verts-per-polygon value! \n", tileString); - continue; + break; } if (params.vertCount >= 0xffff) { printf("%s Too many vertices! \n", tileString); - continue; + break; } if (!params.vertCount || !params.verts) { @@ -754,8 +786,8 @@ namespace MMAP // loaded but those models don't span into this tile // message is an annoyance - //printf("%sNo vertices to build tile! \n", tileString); - continue; + printf("%sNo vertices to build tile! \n", tileString); + break; } if (!params.polyCount || !params.polys || TILES_PER_MAP*TILES_PER_MAP == params.polyCount) @@ -764,19 +796,19 @@ namespace MMAP // keep in mind that we do output those into debug info // drop tiles with only exact count - some tiles may have geometry while having less tiles printf("%s No polygons to build on tile! \n", tileString); - continue; + break; } if (!params.detailMeshes || !params.detailVerts || !params.detailTris) { printf("%s No detail mesh to build tile! \n", tileString); - continue; + break; } printf("%s Building navmesh tile...\n", tileString); if (!dtCreateNavMeshData(¶ms, &navData, &navDataSize)) { printf("%s Failed building navmesh tile! \n", tileString); - continue; + break; } dtTileRef tileRef = 0; @@ -787,7 +819,7 @@ namespace MMAP if (!tileRef || dtResult != DT_SUCCESS) { printf("%s Failed adding tile to navmesh! \n", tileString); - continue; + break; } // file output @@ -800,7 +832,7 @@ namespace MMAP sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName); perror(message); navMesh->removeTile(tileRef, NULL, NULL); - continue; + break; } printf("%s Writing to file...\n", tileString); @@ -970,5 +1002,13 @@ namespace MMAP return true; } + + /**************************************************************************/ + uint32 MapBuilder::percentageDone(uint32 totalTiles, uint32 totalTilesBuilt) + { + if (totalTiles) + return totalTilesBuilt * 100 / totalTiles; + return 0; + } } diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h index c99b8da0ea..877102af7e 100644 --- a/src/tools/mmaps_generator/MapBuilder.h +++ b/src/tools/mmaps_generator/MapBuilder.h @@ -9,7 +9,9 @@ #include <vector> #include <set> +#include <atomic> #include <map> +#include <list> #include "TerrainBuilder.h" #include "IntermediateValues.h" @@ -27,7 +29,24 @@ using namespace VMAP; namespace MMAP { - typedef std::map<uint32, std::set<uint32>*> TileList; + struct MapTiles + { + MapTiles() : m_mapId(uint32(-1)), m_tiles(NULL) {} + + MapTiles(uint32 id, std::set<uint32>* tiles) : m_mapId(id), m_tiles(tiles) {} + ~MapTiles() {} + + uint32 m_mapId; + std::set<uint32>* m_tiles; + + bool operator==(uint32 id) + { + return m_mapId == id; + } + }; + + typedef std::list<MapTiles> TileList; + struct Tile { Tile() : chf(NULL), solid(NULL), cset(NULL), pmesh(NULL), dmesh(NULL) {} @@ -49,7 +68,7 @@ namespace MMAP class MapBuilder { public: - MapBuilder(float maxWalkableAngle = 55.f, + MapBuilder(float maxWalkableAngle = 70.f, bool skipLiquid = false, bool skipContinents = false, bool skipJunkMaps = true, @@ -91,11 +110,13 @@ namespace MMAP void getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax); - void getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY); + void getGridBounds(uint32 mapID, uint32 &minX, uint32 &minY, uint32 &maxX, uint32 &maxY) const; bool shouldSkipMap(uint32 mapID); bool isTransportMap(uint32 mapID); bool shouldSkipTile(uint32 mapID, uint32 tileX, uint32 tileY); + // percentageDone - method to calculate percentage + uint32 percentageDone(uint32 totalTiles, uint32 totalTilesDone); TerrainBuilder* m_terrainBuilder; TileList m_tiles; @@ -109,6 +130,9 @@ namespace MMAP float m_maxWalkableAngle; bool m_bigBaseUnit; + // percentageDone - variables to calculate percentage + uint32 m_totalTiles; + std::atomic<uint32> m_totalTilesBuilt; // build performance - not really used for now rcContext* m_rcContext; diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 477f974021..e3f23b1a76 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -7,11 +7,9 @@ #ifndef _MMAP_COMMON_H #define _MMAP_COMMON_H +#include "Common.h" #include <string> #include <vector> -#include <ace/OS_NS_sys_time.h> - -#include "Define.h" #ifndef _WIN32 #include <stddef.h> @@ -53,7 +51,7 @@ namespace MMAP if (*++filter == '\0') // wildcard at end of filter means all remaing chars match return true; - while (true) + for (;;) { if (*filter == *str) break; @@ -125,26 +123,6 @@ namespace MMAP return LISTFILE_OK; } - - inline uint32 getMSTime() - { - static const ACE_Time_Value ApplicationStartTime = ACE_OS::gettimeofday(); - return (ACE_OS::gettimeofday() - ApplicationStartTime).msec(); - } - - inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) - { - // getMSTime() have limited data range and this is case when it overflow in this tick - if (oldMSTime > newMSTime) - return (0xFFFFFFFF - oldMSTime) + newMSTime; - else - return newMSTime - oldMSTime; - } - - inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime) - { - return getMSTimeDiff(oldMSTime, getMSTime()); - } } #endif diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 16201eba1a..1ce6137fc2 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -6,6 +6,7 @@ #include "PathCommon.h" #include "MapBuilder.h" +#include "Timer.h" using namespace MMAP; @@ -230,7 +231,7 @@ int finish(const char* message, int returnValue) int main(int argc, char** argv) { int threads = 3, mapnum = -1; - float maxAngle = 55.0f; + float maxAngle = 70.0f; int tileX = -1, tileY = -1; bool skipLiquid = false, skipContinents = false, @@ -263,7 +264,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); diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 260bb6da7e..3445013bd8 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -70,7 +70,7 @@ struct map_liquidHeader namespace MMAP { - char const* MAP_VERSION_MAGIC = "v1.3"; + char const* MAP_VERSION_MAGIC = "v1.8"; TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ } TerrainBuilder::~TerrainBuilder() { } @@ -700,7 +700,7 @@ namespace MMAP uint8 type = NAV_EMPTY; // convert liquid type to NavTerrain - switch (liquid->GetType()) + switch (liquid->GetType() & 3) { case 0: case 1: @@ -754,12 +754,12 @@ namespace MMAP } uint32 liqOffset = meshData.liquidVerts.size() / 3; - for (uint32 i = 0; i < liqVerts.size(); ++i) - meshData.liquidVerts.append(liqVerts[i].y, liqVerts[i].z, liqVerts[i].x); + for (uint32 j = 0; j < liqVerts.size(); ++j) + meshData.liquidVerts.append(liqVerts[j].y, liqVerts[j].z, liqVerts[j].x); - for (uint32 i = 0; i < liqTris.size() / 3; ++i) + for (uint32 j = 0; j < liqTris.size() / 3; ++j) { - meshData.liquidTris.append(liqTris[i*3+1] + liqOffset, liqTris[i*3+2] + liqOffset, liqTris[i*3] + liqOffset); + meshData.liquidTris.append(liqTris[j*3+1] + liqOffset, liqTris[j*3+2] + liqOffset, liqTris[j*3] + liqOffset); meshData.liquidType.append(type); } } @@ -894,7 +894,7 @@ namespace MMAP float p0[3], p1[3]; uint32 mid, tx, ty; float size; - if (sscanf(buf, "%d %d,%d (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, + if (sscanf(buf, "%u %u,%u (%f %f %f) (%f %f %f) %f", &mid, &tx, &ty, &p0[0], &p0[1], &p0[2], &p1[0], &p1[1], &p1[2], &size) != 10) continue; diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h index 0bb29fef47..52773320fd 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.h +++ b/src/tools/mmaps_generator/TerrainBuilder.h @@ -69,11 +69,13 @@ namespace MMAP TerrainBuilder(bool skipLiquid); ~TerrainBuilder(); + TerrainBuilder(const TerrainBuilder &tb) = delete; + void loadMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); bool loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData); void loadOffMeshConnections(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData, const char* offMeshFilePath); - bool usesLiquids() { return !m_skipLiquid; } + bool usesLiquids() const { return !m_skipLiquid; } // vert and triangle methods static void transform(std::vector<G3D::Vector3> &original, std::vector<G3D::Vector3> &transformed, @@ -109,10 +111,6 @@ namespace MMAP /// Get the liquid type for a specific position uint8 getLiquidType(int square, const uint8 liquid_type[16][16]); - - // hide parameterless and copy constructor - TerrainBuilder(); - TerrainBuilder(const TerrainBuilder &tb); }; } diff --git a/src/tools/vmap4_extractor/loadlib/loadlib.h b/src/tools/vmap4_extractor/loadlib/loadlib.h index e55b4a7c56..989f665934 100644 --- a/src/tools/vmap4_extractor/loadlib/loadlib.h +++ b/src/tools/vmap4_extractor/loadlib/loadlib.h @@ -7,6 +7,8 @@ #ifndef LOAD_LIB_H #define LOAD_LIB_H +#include <string> + #ifdef WIN32 typedef __int64 int64; typedef __int32 int32; @@ -59,7 +61,7 @@ public: file_MVER *version; FileLoader(); ~FileLoader(); - bool loadFile(char *filename, bool log = true); + bool loadFile(std::string const& filename, bool log = true); virtual void free(); }; #endif diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 28c1bad31b..07f1f3ec16 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -84,17 +84,31 @@ bool Model::ConvertToVMAPModel(const char * outfilename) wsize = sizeof(uint32) + sizeof(unsigned short) * nIndexes; fwrite(&wsize, sizeof(int), 1, output); fwrite(&nIndexes, sizeof(uint32), 1, output); - if (nIndexes >0) + if (nIndexes > 0) + { + for (uint32 i = 0; i < nIndexes; ++i) + { + if ((i % 3) - 1 == 0 && i + 1 < nIndexes) + { + uint16 tmp = indices[i]; + indices[i] = indices[i + 1]; + indices[i + 1] = tmp; + } + } fwrite(indices, sizeof(unsigned short), nIndexes, output); - + } fwrite("VERT", 4, 1, output); wsize = sizeof(int) + sizeof(float) * 3 * nVertices; fwrite(&wsize, sizeof(int), 1, output); fwrite(&nVertices, sizeof(int), 1, output); if (nVertices >0) { - for(uint32 vpos=0; vpos <nVertices; ++vpos) - std::swap(vertices[vpos].y, vertices[vpos].z); + for (uint32 vpos = 0; vpos < nVertices; ++vpos) + { + float tmp = vertices[vpos].y; + vertices[vpos].y = -vertices[vpos].z; + vertices[vpos].z = tmp; + } fwrite(vertices, sizeof(float)*3, nVertices, output); } @@ -169,7 +183,6 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID int realy1 = (int) ((float) pos.z / 533.333333f); int realx2 = (int) ((float) pos.x / 533.333333f); int realy2 = (int) ((float) pos.z / 533.333333f); - fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n", MapName, ModelInstName, |