diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 03a4e5b25..8e7707361 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,7 @@ variables: # This will suppress any download for dependencies and plugins or upload messages which would clutter the console log. # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work. - MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true -Xmx3g" + MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true -Xmx4g -Xms2g" # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used # when running from the command line. MAVEN_CLI_OPTS: "--batch-mode --errors --fail-fast --show-version" diff --git a/Server/data/ObjectParser.xml b/Server/data/ObjectParser.xml deleted file mode 100644 index bfd1c5167..000000000 --- a/Server/data/ObjectParser.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Server/data/botdata/botnames.txt b/Server/data/botdata/botnames.txt index 22c5715a8..e16423b0c 100644 --- a/Server/data/botdata/botnames.txt +++ b/Server/data/botdata/botnames.txt @@ -1,43 +1,22 @@ --Kevo -0 S O -0 4 1 1 -0 4 7 -0 HBK 0 -0 Khan 0 -0 LM +Kevo 0 Quest Ptz 0 Undead 532 0 hits -0 s m a n -0-0000000000 -00 zarour 00 -000eggs -004 n 007 Double O 007Banshee 00eeeee58 00eeeeeHC 00oo00oo00z 010elpibexx0 -014ankh -01690 017Lucas 01Ares 01eon 01ogre -020893 024elyograG 02RS 02homestar -031 -0315 -0416347345 -054 -055027584 05miller5 05venom04 -06 59 -0600 06sz 07 Account 07 Adept @@ -50,11 +29,9 @@ 07 Officer 07 Rz 07 Sicario -07 T Bone 07 iron 07 kiero X 07 nice jake -070623 07Ashley 07Ben 07Geno @@ -66,18 +43,10 @@ 07Rockysbudy 07coco 07guthix07 -07wan -080 -0800 -0800952449 -0837 -09 -0920 09Ash 09Ashley 09Ato09 09Chris -09Dans 09Paul 09Reaper 09Rhys @@ -86,42 +55,29 @@ 09TroyScape 09milo456 09scaping -09wan -0BAMA 0Behind0You0 -0CdanC0 0G 0GCore 0Giesel42O -0IIll0llIIII -0JL 0Joker0 0KAT -0LKI 0MEGA PVM 0MG ST3PSIS -0MW2PVM 0Manbearpig0 -0MrJ 0PC 0Pwnseason 0S Iluvatar 0SFX 0Tempest0 -0WEK 0X010 0_BADASS_0 0anabanthis0 -0bD0G 0bankspace 0bby -0bby Man 0belix 0bscure0ne 0ctopus -0dds r u win 0desza -0dexy 0dyssey 0ff Task 0ffline @@ -137,8 +93,6 @@ 0im2old4this 0inke 0k -0l -0l m 0ld Mate 0leaguespace 0li @@ -162,11 +116,9 @@ 0neski 0netruememe 0niichan -0njon 0nlyClouds 0nmy 0ops -0oqs 0pSe 0pen 0pen Al @@ -177,13 +129,9 @@ 0rl 0rnstein 0rphaned -0samaBdabbin -0sc4r -0smasher0 0so 0ssimpwner 0syb -0t 0taku 0taylor 0verHyped @@ -204,35 +152,15 @@ 0xocube 0xp Fail 0xygen -1 -1 0 1 0 -1 1 4 -1 2 2 -1 337 -1 3s -1 4 11 -1 54 -1 9 7 -1 A M O R -1 A N D 1 1 Account -1 Corin 6 9 -1 DC -1 Flicki Boi 1 Free Ryde 1 Ham 1 K0 Is Back 1 Line 1 Lion Tell -1 P P 1 1 Percent -1 Waffle 1 and only -1 is ln of e -1 kc 1 pet -1 parhaista -1 s t Blood -1-800DILLDOE +1st Blood 1-GrayStone 10 Four 100 Duke @@ -241,57 +169,26 @@ 1000 Ways 10000Fists 1000PingOnly -100Cl 100Grabb -100g 100kyews 100m gp 100xcoin -101000101010 -1017Trev -101e 101evil101 101rootbeer -104512 -105 -107M -1085 -1099s -10Hz -10R80 -10b -10cc -10lachs 10mm mafia 10th Reaper 10v10 10v10v 10v10v10v 10x Brew -1101953119 -1111 -11111111111d 111fishkite1 112OceanAve -116 -116 123 -1183kenny -118s 11inchlimp -11l1 -12 -12 49 12 XP 12 hours -120u -1212ajs2 123 Zeus -123456205 123Four 123bear5 -123tseemijni -1272172 -1288 12bar 12bar_ty 12blackeagle @@ -299,24 +196,6 @@ 12earlycob 12in 12millionGP -12oss -12oz -12th -13 37 -13 Daas -1300 -130SS -130rk -1312AFCA -1313 -131kg -1337 af -1337Trevor -1350 -138hans -13D -13LACK0N3 -13O 13alerion 13ayek 13ehh @@ -328,98 +207,44 @@ 13purecs 13ruce 13th Witness -14 wides -1400 -14060M -144 -1441 -144forever -1453 FSM -149122089147 -14Fre-e -14GT -14Words 15 min Break 150 kilos 1520sedgwick 15b name -15mg -16 Fly Tell +16 FlyTell 16 Fps -1602 16bumpysnow -16lB -16le -17 76 -170 IQ -17222 -1780 -17Kc -17_FLHXS 17rune2277 18 Or Older 18 Points 18 girlll -18-06-2022 x -1800BetsOff -1802M -180555 -181 -1817 -1827 -1845 -184910381412 -187 -187 781 -1877 187PIGMORGUE 187er -1889 18cast1935 -18hr 18killz -18s 19 KAPLAN 05 -19088ml -1942 -1948 -199 -1992 -1994 -19O7 19edgebee 19puxx -1AB 1After909 1Alfa -1Ali1Plane -1BGP -1Bio 1Buck1Love -1C2R 1C3 W4RR10R 1CuteBot -1Fbs -1G1D 1GramIronMan 1Hit2Lum 1Hunnid -1I1I1IIll1l 1InchWalrus 1Iron Reborn 1Kyle 1Lank 1ManGangBang 1Mayze -1NANO -1NU 1Nikolai 1Nut Dude 1O1Barz 1Ogp 1P Game 1Parthannax2 -1RlE 1ST KC 1Shadow9Fist 1Shark @@ -431,7 +256,6 @@ 1TickShit 1Unforgiven8 1_BLEED_BLUE -1ars 1badprogram 1bankingnoob 1blackhawk17 @@ -450,8 +274,6 @@ 1imp1jar 1isa 1itemtbow -1jbone -1john 1k no zik 1kDuramax 1kMaster QXD @@ -469,11 +291,9 @@ 1nVaSioN 1ndy 1ne life -1nfiniti 1nsane str5 1nv1s 1nvercargill -1o 8 1ocation 1please 1powerhydra @@ -484,46 +304,31 @@ 1st ed mint 1st son 1stHCwasPKED -1stlrfan 1stnoob7 1t8w 1tapaturma 1tickspecwep 1trueMortyy 1ucif3ro -1v1d a sedan 1w1lll0se 1wayEscape -1wwdwd2e21ed 1yfe -1zet -2 0 1 4 2 1Savage -2 2 7 7 -2 2 8 9 -2 3 7 5 -2 9 2 Big tities -2 Brothers 2 Much Tuna -2 P A C 2 Rich 4 Dis 2 Silent 540 2 Smooth 2 ball cane 2 funny bro 2 grls 1 Jad -2 h p -2 in +2 hp 2 kups -2 lN 2 more min 20 20 vision 20 Agi irl 20 On Pump 3 -200 200 Cook -2000 2001Arwen 2006nope 2007scape @@ -536,94 +341,35 @@ 200mslay1day 2011Turmoil 2013 Rt -20130406655 -20136 2027Parzival -202o2 -204 Wootang 205alphago -208 -209th -20Four -20I0 -20JuanSavag3 -20ms -21 5 21 Average 21 Musketeer 21 Savage 2137 gp -215O -2173 -21JJ 21SavageX2C 21unit -22 69 -22 Geese -22 Gz -22 darnoc 22 -22 day fury -220mg -226559 -227 7 -2277 2277 Beast 2277 Soon TM 2277MaybeNvr -2277kg -22O5 -22X7 22btc 22harry 22mario 22whitewolf -23 x 3 232o2oo -234071973416 -23463564 -235iii6i666i -2376Total -2376ed -23847239571 -23CD -23I 23coalcare 24 Hour -24000 -241 -241196 -2424 -245 -247 365 -2488 -24YO -24l7 -24w -25 S 25simulator -26 th 260sheepdog -265344626546 -26ll98 26pandas 26th -27 5 -27 M -271MPN -27ml -2841280 28BagsOfSalt 28goldpieces -290x -29384652 -2996 29Pons30 29enchant821 29robdead 2B Nier 2Broke4Coke -2C-T-2 -2D E F2 2D pantsut 2Edgy4Meme 2Far @@ -634,21 +380,11 @@ 2Goblins1Jug 2Guys1Wyvern 2Guys1dds -2I40 2InchLift 2InchPnisher -2JZ GTE -2JZ Soup -2JZ-GTE Mk4 2Jerry 2Lit -2M0X1 -2MIN -2Men 2MinNoodles -2O xp -2O07 -2OO7 2QC 2Rare2Die 2Secs @@ -675,14 +411,12 @@ 2girls1Tbow 2girls1bed 2girls1troll -2girlz1jbird 2gurls1tick 2h ur azzzzz 2hopp 2hot2touch 2hot2touch2 2hs -2id 2kav 2late2team 2logx @@ -696,120 +430,61 @@ 2pacs 2plush 2sm0keyyyyyy -2steps -2th7 2tickin 2tti -2two77 -2uBz -2ual -2ugi 2woke -2x92is99 -2ze 2zick1zussy -3 Hit V -3 5 P -3 50 -3 77 3 Moons -3 S I X E S +3 SIXES 3 SwordStyle -3 T C -3 arcanes ty +3 arcanes 3 me0 3-age 30 yo b00mer 300m MPS -3019 -30FF 30SHOTFOCUS -30XY 30thNovember -30zl -311s -3155 -315lbs 315squatreps -3160 316Austin 32 kay -320m 33 Dust Cat -335K -33jf -33zero2 -3400 -341all -34241245321 -345138 -34HL6432G6L2 -34T -34rj394thgro -351329 35ankoumoon 35cm bicep 360 Labels 360backhand 365 day 369x -36ACT 36answersay -379 -37Kg -37kg -381N 38CoolestMan 38drivelift 39 PETS 3BigDoobie 3D AnimeTits 3D Dorito -3E8 -3G -3III -3L1QZaD 3LetterName 3Miller3 3TicYaMum 3TickEat 3Ticks 3WordName -3a B0ng -3aly -3amf 3arbeed 3ash 3awe -3b 3bay -3bobyshmurda -3d age boots -3d354 -3dderino 3erzerk 3h scimitar -3ibal0e9 3inchsoft -3ioc 3iron5u -3km 3lPatron 3lack 3litz 3lilbirbs -3lit3 3liteSupreme 3lven 3lyrie 3lys -3niZ -3nosedmonkey -3nps -3oh5 3pic 3ragesave 3rd Age Ryan -3rd Age THC 3rd Age Toes 3rd Age Wife 3rd Hunter @@ -819,38 +494,21 @@ 3rdAgeHunt 3rdAgeSlayer 3rdMistake -3sd -3sl +3d age boots 3stripe -3uck -3uzi -3verD3ad 3vil 3vil Giraffe 3vil Lawyer -3we 3x3i 3xDestroyer 3xtra-1arge 3yes -3zR -3zi 4 Bros Info 4 Man Nex 4 inch demon 4 inches now -40 IQ -400L -400s -403 b -40699 Crabs -40Atk -40ms -40oz -412087542131 413 JokeR 416MiIf Jade -41O 42 Mime 2462 42 Reasons 42 skankhunt @@ -868,27 +526,11 @@ 420licious 420michael13 420tarmslyng -42342343342 42Def -42O42O -42nd 432andone 43technetium -44 bot -4400 -44444444444 45 fail -4500c -4564 -457 45smith2345 -478k -47an -47th -48H -48hour -49 r -492117837813 49forcerage 4ALLYaYa03 4D Entity @@ -899,8 +541,6 @@ 4K MrKrabs 4KT Youngboy 4Kath -4L O K O -4LDO 4LeafCIover 4Lt Goon Bag 4MoistScoops @@ -915,15 +555,12 @@ 4are 4asphalt4 4biddin3 -4cof -4dan2 4dapigs 4dosemonster 4ever 4everdry 4got2pull0ut 4gottenvoid -4hQ 4hit pl0x 4holyhydra 4iend @@ -937,63 +574,32 @@ 4rKsTon3 4sen 4th lesson -4th8 -4the 4themininoob 4thunderbolt 4ur Elise -4werty4 -5 56 -5 Nine -5 Oh -5 mil -5 ms 5-Bet Fold 50 DKP Minus 500 BJ -5000men4 -505 50Dkp_Minus 50TintenUwMa 50bitsnka -510 51Highlander 51xp 528racklover -5304 530pm 53R10U5 53m0g 54 Slayer -548 -55mg -562 -5639 -56667 -56771910 -56O -570215 -5771 57tallfred 57wraith2076 -5876 -58th -59OG 5ADx 5Aces -5BY5 5G fries 5GCovidTower 5H4NKS 5IRLOIN -5Id3Track -5M3H -5M9SNH31KAOI -5NAX -5OP 5Orudis5 5UBLlME -5a9 5alood 5alve 5ammito @@ -1001,69 +607,28 @@ 5eekingdeath 5eizures 5g Internet -5gum 5harp5hoota -5hauny -5hayWh1te 5head 5inch Floppy -5is -5j5 5kc Zulrah -5l9 -5lNS 5lap 5nis 5parrow 5quid -5st -5t h 5th Blessing 5th hcim LUL -5trm -5wan 5wattia -5x3 -5xr2 -6 57 6 9buttholes 6 Donuts 6 Drive Fox -6 Foot 5 -6 I X GOD -6 M 6 Mil 6 Qp -600 Years -605 -60min is 1hr -617 -61V -6264 -629fm 62steeplist -6384 -647 -64DD -64th -6535 -6620 -666 317 -666 J -666 is leet -666Ds -666Duuvel666 666drkwizard 66Cute 66sick -675 -67M -67jj6j7 68 savage -6822ii 68pickleman -69 L OR D 69 -6942O 69KolaOlli73 69Skrrt420 69bbygurl @@ -1072,17 +637,10 @@ 6ESkarmory 6LACKY 6PaperJoint -6R6 6T9sofine -6TMG 6Tilbud -6UGG 6cansOfBeer 6cythe -6dr3w9 -6e -6enny -6ess 6et Schwifty 6h Logout 6in9 @@ -1090,72 +648,25 @@ 6ixty 6ixx 6jadkiller -6km 6lb brownie -6mat -6ong -6p8o6 6pathsofpein -6qp 6shooter 6uapo -6uh 6utt9lug -6y6y6y2 -7 7 MAFIA -7 Curry 7 DeadlySins -7 Fat Drake -7 Of Nine -7 Trouts -7 pets chimp -7 seconds -7042 70Point1 lol 70rangeboy -70to120 -710 710 710 -716 -718m -71rc -72005sc -73 and Kree -734590325839 -737 73Head 73HoundKey -73gp -742617OOOO27 74ChaosLTUU 75 IQ -76frozen44 -76ms -7738 777slayer777 -77Dunamis77 77Stingray -77ms -782 -784162 79giantfoot -7AYL0R -7D9 7Esconar7 7Ethereal -7F9 -7GB -7God -7H3 -7J4FXEL7YFW5 -7Lazy7 -7RAC -7T -7TF 7Vick 7Viggie -7ZP -7abibi -7amowdahli 7aq 7asty 7ate9 @@ -1165,20 +676,13 @@ 7ckng Mad 7claudia7 7crypto7 -7emo -7emp 7emptest 7fisherdog 7havage -7min -7mins -7mni -7om 7ourney 7out 7rad3 7raphouse -7rev 7ridley 7scaryfire 7th Chamber @@ -1186,104 +690,45 @@ 7uP joAo 7wizard10 7xshadowx7 -8 1 O -8 3B -8 Sue Build -8 alien 8 -8 bit bling -8 oh 8 8008tator 808Southside 80leavefox 82 Sue Say -8282 831pride -832arba -8485 -849 84Bandit -85 N -8502 -852K -858 -85U -85dakota85 -88 Odd Wand -8800 -8885 -88gg -89devoid1329 8ASS 8BootRaw6220 -8ElMandinga8 -8J8 -8O8O8O8O8O8O 8ass 8balknowsall 8balled 8eauty 8h of sleep 8ind -8l0wm3 -8lackMamba24 8loodrune 8lue Phat 8owser 8qxkf02v 8tail 8uD -8yrs -9 9 Problems -9 B 0 -9 DUIS -9 Tick Brain -9 mb +99 Problems 900mexp 901Grizzlies -90804 -9092514 90tegguy -91 91 Tin Idea 911_Nate -91414 91CAL 91flip 92 way there 920 Bdops -9227 -9297 -92t 92times2is99 -94 xp 94AR BTW 95EliasAw -95LH -95p7 96 WINDSTAR -9687 96fastfrog -97DEF 97ccman97 -97fsh -98 BEDARD -98 Civic -982 -98Bn 98max1 -99 Doobies -99 Grill -99 Grinding -99 Mage -99 Rats -99 StaKe LvL -99 Steeze -99 oz -99 rwt 991atatime -9991499 99BnkStnding -99Juuling 99Lives 99S2HP 99Scents @@ -1294,40 +739,24 @@ 99_Maxed 99bottin 99charming -99hh 99moretimes -99ox 99problems4 -99ss 99sweatlvl -99wc500m 9Bar 9Barr -9CX 9D9Skillzz 9Dimensional 9GAG Reflex -9JR 9KL00AZIIZ9K -9O 9 9PetsSoFar -9T3 9TY9_Sailing -9UNIT 9cansRavioli -9ieman 9inchStepBro -9mm ko 9mmlesah -9ne -9ond 9till5slave 9ussy 9yearoldpops A 2 The Aron -A 3 -A 45 -A 7 F O L D A Articuno A Bad IGN A Bad Meme @@ -1346,15 +775,12 @@ A Cityzen A Claptrap A Classy Boy A Crazy Cook -A Crisp Sock -A Curry A Cute Snail A Dreamer A Drunk Beer -A Du Ma A F K Scape A F KING -A F M Scape +A F Scape A Fat Deer A Fat Pike A Fat Swede @@ -1364,20 +790,10 @@ A Godsword A H Fire A Half Fool A Hofasho -A I D E N -A I I e n -A II D A Iron Yoshi -A J -A JJug A Jack O Lit A Jug A Kimura -A L 3 X -A L C A P WN -A L E K S -A L I S H A -A L T A Lava Lamp A LifeTime A Lilypad @@ -1407,8 +823,6 @@ A Pot Head A Psy A Quest God A Quickie -A R H -A R Z A Raccoon A Random 4nr A Real Bamf @@ -1437,64 +851,44 @@ A Wise Sloth A X Y S A Yang A Yep -A Zee -A Zeer A Zoo Keeper -A Zuk -A Zuzakini A aron A bit north A broke 126 A capybara A cclimation -A d e b y +A deby A dam A damm A dammmm -A e d o -A e s i r +A edo +A esir A f r a i d -A gg -A lba -A ll F A llan A llstar A ltar A m a nd a A n d re -A nz A rdy A rmin A rmoa A rrow A stoner guy -A to teh Jay -A ug A y s a A z k e n A z t e r A-Chronic A-F-Kaveman -A123 A13X -A15 A1KMAN A1nz00alGown A1rhook -A2 -A22Y A47 Soldier -A543 -A7MED -A84 -AAA GG AAAAAFK AAAAAddy AAIGHT AAsamba AB Dash -AB84 -ABEC ABG Huntr ABILITEETTI ABearCat @@ -1502,8 +896,6 @@ ABlazys97 ABlueShirt AC Dicing AC TEMP IQ -AC0T -ACDC ACatGirl uwu AColdBeer AComp @@ -1540,11 +932,8 @@ AFKspiracy AFTW AFX64 AFrickinLion -AGIT8 -AGP3 AGRONOMlST AGSpec -AGWA AGlassOfH2O AGorski AH Energy @@ -1556,7 +945,6 @@ AHarmlesKitn AHlager AHriMTaLeZ AI Fighter -AI0 AII 99 AIchemyz AIecko @@ -1566,26 +954,14 @@ AIixs AIlByMyself AIm23ARDesti AIways sm1le -AJ R -AJ Skills -AJ4J -AJTracey -AJ_24 -AJisHere93 -AJsk AK Alpha AK Sam -AK47 -AK4LF -AK5C AKI-47 AKK1E -AKM AKSpring AKinkyMonkey AL-Trojans AL3CX -AL7 ALBlNO ALEXppresso ALLCAPS @@ -1602,18 +978,14 @@ ALonelyKurt ALonelySpoon ALonelyTaco ALv3Magikarp -AMAWM AMC Millions -AMD352 AMDOSRSIRON2 AMGS65 AMRSY -AMST AN07HER AN0NYM0OOOUS AN1MAL1ST1SK ANDERDAPLUG -ANDR3 ANDREVVTATE ANDROlD 18 ANGL0 SAX0N @@ -1630,14 +1002,8 @@ AOT GOAT APC L000000L APTZ27 APrince -AQ COCUGU -AQMD -AQUAMARROCKZ -AR Brah AR Fifteen AR15ONA -AR1F -AR53 ARCANO RS ARCHER ARCHIT3CTS @@ -1670,7 +1036,6 @@ ATastyPastry ATurboVirgin AU6URY AUD1O -AURl AUSLANDER AUSTlN AUTOart @@ -1689,8 +1054,6 @@ AXL gun ROSE AYRI DMM AZER AZNPanda -A_G_4 -A_Wuh AaaBiiCee Aaalmost Aadalyn @@ -1712,35 +1075,12 @@ Aaron Btw Aaron Quiz Aaron Samuel Aaron11700 -AaronJMLP AaronPVM -Aarsworm -Aarti -Aary -Aaryn -AashUnce Aastradsen AatroxLife Aauburn AavikonGaara -Aayraz -AbInito -Abaay -Abacraumbii -Abaiz -Abaker -Abaqus Abariel -Abbas Elect -Abbey -Abbey Ruins -Abbo baker -Abbyscimmy -Abc easy as -Abdallah6 -Abdirahman -Abe lnnkon -Abe numse AbeTheHobo Abengers Abernasty @@ -1748,7 +1088,6 @@ AbiChillii Abide Abido Abigayyl -Abismaalinen Abito Abiuro Ablazin @@ -1796,11 +1135,6 @@ Abstractable AbsurdGreek Absurdly Gay Absynthial -Abu Chungus -Abu Salih -Abuk -Abulssoni -Abuv Abyission AbysmalGrind Abyss Laps @@ -1850,7 +1184,6 @@ Aces Aces x3 Acesuke Acesupersoak -Acetazolamid Acha9 Achaeos Ache @@ -1862,7 +1195,6 @@ Achilles Low Achilles XXI AchillesFist Acholight -Achuu11 Acid Acid Cat420 Acid Christ @@ -1877,9 +1209,7 @@ AcidHouse Acide Acidic Acidylia -Acir Ack Varmland -Acke AckeSSBM Ackman67 Acko @@ -2071,11 +1401,6 @@ Aeugh Aev Aeyriex Aezolix -Aff it -Affaires -Affan Khan -Affect -Affectie Affidra Affinivax Affirmed @@ -2101,26 +1426,6 @@ Afkin Afkoelen Afkstar Afkwarrio6 -Aflamed -Afnacho1 -Afonso -Afperser -Afrecan -AfricaSavior -Africagamer1 -AfricanMelon -Afrie -Afrikka -Afriquee -Afro -Afro Deagle -AfroFishh -AfroShay -Afrojofe -Afroman -Afromann -Afromouse87 -Afrothunder Aft3rmath After Dark After3Scoops @@ -2204,10 +1509,6 @@ Ahriah Ahrim Job420 Ahrou Ahvexx -Ai Haibara -Ai activated -Ai u -AiMienOortje AiNebesvaik AiXiao Aiai8 @@ -2255,11 +1556,6 @@ Airstone Airstrike Airstrikes Airwalk -Airwipp -Aishi owo -Aisyah -Aivery -Aiwe Aixaa Aixleft Aiyaaaa @@ -2267,21 +1563,6 @@ Aiyzer Aizor Aizzz Aj Blitz -Ajamian -Ajarn -Ajaxius -Ajdj -Ajeh -Ajeti -Ajikk -Ajinz -Ajt141 -Ajushox -Ajuus -Ajx -Ak 4854 -Ak5u -Aka God AkaSpecs Akadian Akagi @@ -2292,13 +1573,6 @@ AkaseAkari Akasha Akashy Akatsuki -Akaza -Akduman -Akeno -Akhasa -Akhavan -Akhotha -Akiha Akihiko Main Akilled Akimbo Gmaul @@ -2332,17 +1606,6 @@ Akustic Akvarij Akyba Akyle -Al Go Rhythm -Al e x x -Al ex G -Al-Kimiya -AlCaponee -AlFromOhio -AlIigator -AlMusallam95 -Alabandus -Alabarce -Aladfar Alak4zam Alakazoom Alakazzaror @@ -2371,9 +1634,6 @@ Albertttt AlbiBambi Albin0z Albinos10 -AlboBloodZ -Alboy -AlbusTheDood Albuun Alc1 Alcadeias @@ -2464,27 +1724,6 @@ Alexx2G Alexxandraa AlexxisTexas Alexzilla -Alf11 -AlfaAleksi -AlfaQ -Alfahane -Alfahanne -Alfication -Alfie 96 -Alfonga -Alfonso -AlfonsoKhan -AlfredTB -Alfrid -Alfuh -Algiebeer -Alharbi -Alhyrr -Ali Shuffle -AliThePvmer -Alibaba -Alicander -Alicc Alice Alice x AliceOMalice @@ -2498,7 +1737,6 @@ AlienVoucher Alienmage Aliens Aliii33 -Alijr AliksOh Alioman AlistarTb21 @@ -2628,21 +1866,10 @@ Alrite Alry Alsatian Alsatians -Also -Also Jack -Also Luci -Also Lucky -Also Nexxtar -Also Noexi -Also Schlak -Also kawkky -AlsoAlso AlsoRabbit Alst Alston Alt Ctrl -Alt G boys -Alt Juana Alt Redshok Alt prepot Alt3rbridg3 @@ -2698,12 +1925,6 @@ Alwin S Alxs Alyks Alysanne -Alyv -Alzad -Alzuraak -Alzz -Am eer -Am ity Am ln Danger AmCatWhatDo Ama zon @@ -2751,22 +1972,6 @@ Amend Amenity Ameno l Americlaps -AmiableDingo -Amibis -Amida -Amigeau -Amigo -Amigos -Amillie -Amin -Amir Psycho -Amis -Amitwin -Amityz -AmixBeast -Amjad -Amjar -Amka0s Amkings Amlodipinee Ammastian @@ -2852,8 +2057,6 @@ Ancientz pal Ancitif Ancona Ancow -And e -And r ew AndSo AndYetISmile Andardenn @@ -2870,7 +2073,6 @@ Andiamo98 Andipyrus Andirath Anditre -Andj Andoyen Andrade149 AndreasBL5 @@ -2957,15 +2159,6 @@ AngryNachos AngryPickle AngryScape AngryWizard -Angsti -AngusM -AnhTaDuong -Anhedoniaa -Anid -Anida Hanjab -Anidien -Anieli -Aniheyu Anim Anima Animal @@ -3131,15 +2324,7 @@ Anzie Anzied Anzu Anzypoo -AoA Jammer -AobaJohsai -Aog -Aoh -Aohc -Aohu Aoi Tetsu -Aokijahr -Aokijii AonEne Aonyx AoooA @@ -3150,16 +2335,11 @@ Aozaa Ap0logy Ap0phis Ap3x -Ap870 -ApRoMn -Apaat -Apaatje Apache Apache30 Aparlo ApartAbyss Apathetik -ApdoJ Apdomine Ape Cape Ape Dos Mil @@ -3169,7 +2349,6 @@ ApetimusPrym Apex Apex Pro Apex-scaper -ApexGT Apexflashy Apexist Apgujeong @@ -3495,14 +2674,6 @@ Arrowtower Ars Nova Arsaydar Arsenals -Arsene rar -Arsenic -ArsenicEyes -Arsenn -Arshal -Arsi -Arslen -Arson ArsonScape Arst Arstan Selmy @@ -3767,17 +2938,13 @@ Atvinnulaus Atylos Atza Au 0srs -Au 1 -Au Bar Au Barrett Au Joel Au Shooty -Au92 AuRoyce AuStarZ Aubrey Aubrey UIM -AubsG Auburn Lax Aubzzz Auclaw @@ -3800,8 +2967,6 @@ August AugustAmes Augustiner16 Augutis -Auhdy -Auja3 AuksoAlt Aulono Aumoki @@ -3828,7 +2993,6 @@ Aurtle AurumFoxfire Auryn Aus -Aus 2277 Aus Shizam AusBruto AusGram @@ -4005,9 +3169,6 @@ Ayenull Ayetg Ayfi Aylia -Aylward -Ayman -Ayo4Yayo AyoSteeze Ayoe Ayonikz @@ -4016,41 +3177,11 @@ Ayri Ayrton Aysuu Ayveros -Ayy Nakana -Ayy bae bae -Ayy q p -Ayyye -Ayyyon -Ayzo -Az PVM -Aza zel -Azad -Azad Kashmir -Azala -Azami -Azandari Azathor Azathoth26 Azathrir Azazel OSRS Azeenil -Azemu -Azerma -Azez -Azimut -Azimuthaal -Aziz -Aziz7 -Azkaton -Azken -Azkybot -Azlo -Azmataz -Aznbabe -Aznmixboy -Azom -AzorAhaiBTW -Azotize Azoxy Azpa AzraelReaper @@ -4082,69 +3213,8 @@ Azzanadraa Azzax Azzgarnia Azzz -B 0 B S -B 0 S S -B 0 U J E E -B 3R -B 58 -B A F F E Y -B A MF -B A U W S -B B Bouncy -B C 2 -B C M -B CA -B D Y -B E E G -B E R T A -B E R t I 3 -B ELA -B Gates -B Gonkeybron -B I G G L E -B I R T -B Ian -B J O R N -B L 4 N K -B L A D E Z -B L A N E -B L A Y E D -B L ANK -B L I X T -B Milesy -B Minor -B O G S -B O O T H -B O Y E A -B R A l N -B R II A N -B R l C E -B S -B SlDE -B T J -B Victor B -B W 1 -B W A K -B aylor -B aze -B ecky -B eeez -B iggles -B la z e -B las -B r a g g -B r eezy -B rads -B raes i -B ruised Lee -B u bs -B ug -B un -B utt -B w -B-0-SS-M-A-N -B-Dollaz -B-Lal +B0BS +B0SS B00 KAW KEY B00Lici0us B00MERAT3R @@ -4187,14 +3257,7 @@ B1gTTgothGF B1gd0wg B1ink B1mboBambi -B1zrme -B2AD -B2F -B2J3 B2bZeroSpecs -B2rad -B3A5T -B3CK B3NJAMOON B3NT D0ver B3TTERLUCK @@ -4202,15 +3265,6 @@ B3Y0ND B3njamima B3njamin B3nny Blanco -B46 -B4RR -B4S -B4llista -B6a -B6i -B70 -B747B -B8 H8ER BACKURBOI BACONisgd4me BADASS @@ -4229,17 +3283,12 @@ BASEDQwert BATATUNGA BATH0RY BAYLlFE -BBBBBONKA -BBGL -BBK BBKwenie BBL RIZZY BBQs BBW Pizza BBarnzeyy BBeepLettuce -BBoys Father -BCBDestroyer BCC YT BCDOJRP BCK CigButts @@ -4255,7 +3304,6 @@ BEEA BEG0N BEG0NE BEINGMAXDSUX -BELSJ BEMBOU BEST BET5 @@ -4271,7 +3319,6 @@ BIGD05 BIGDROPHUNTR BIGFERGLOAD BIGHEADSMASH -BIGJP BIGMINK BIGSITUATI0N BIKlIllIlIIE @@ -4279,14 +3326,11 @@ BILR0Y BIOATED BIRD SHlT BIRP -BIRWAAA BIS Monster BIaded BIadet BIapa BIood Prince -BJ Applegate -BJ M BJPlaysRS BKBB BKK @@ -4298,7 +3342,6 @@ BLACK DOG NI BLASE BLGesus BLICKYSTIFFI -BLOBi WRX BLOOD BLUEPIZZAMAN BLXCKPINK @@ -4308,10 +3351,6 @@ BMEUR BMooldijk BMrgn BO0MERSO0NER -BOA Liger -BOBGIGALUCKY -BOBYAHMDGECI -BOER KAMIEL BOGOBoneless BOL0CKS BOLSOONARO @@ -4329,11 +3368,8 @@ BOlNEXTDOOR BPNS Hawk BPTheIronOne BPrimitive -BR0 BRO BR00KES BR0CE -BR0ER -BR0THERS BR3AKABLE BRA71L BRACULA @@ -4345,7 +3381,6 @@ BRUTAL BRabbit25 BRlOCHE BSB Howie -BSNR BST Steve BSickler BSven-B @@ -4356,13 +3391,9 @@ BTW Beirre BTW idgaf BTW vs RNG BTWSaberlion -BTWsanta BU1MER -BUHLL -BUILD BUILD PONYS BULLlSH -BUNDHA BUNStheGOD BUR13D AL1VE BURYT0MORROW @@ -4371,33 +3402,11 @@ BUTTB0NERED BUTTCOlN BV Martyr BWheatZ -BYEq -BYOBOOZE114 -Ba1i -Ba5b0y -Ba6y -Ba77erY -Baa m -Baaaats -Baal157 -BaalZvuv Baals Baalthas Baamf Baami Baandos -Baarb Lahey -Baas -Baba -Baba Booey9 -Baba Borgar -BabaLovesKos -BabaSlaaf -BabaSleep -BabaTarzan -Babafasa -Babayaga-9 -Babayaga2121 Baberrandrid Babica Mraz Babiez @@ -4519,26 +3528,11 @@ Baekah Bag it Bag of Yay BagFryLife -Bagadigi -Bagan -Bageera -BagelSpanker -Bagels -Baggyshaw -Baghdad -Baginga -Bagis Bagokk Bags Bags n Beer Bagsnacks Bagz -BahRitTanEe4 -BahamutLimit -Bahn -Bahnzeen -Bahp -Bai Ningyang Baib Bail Jait Baileys @@ -4551,22 +3545,6 @@ BainoLad Bainz Bairac Baites -Baja Baja -Bajan -Bajart -Bajcolado -Bajela -Bajere -Bajhole -Bajista -Bajji -Bajkami -Bajsanus -Baju -Bak cornet -BakIron -Baka Mop -Baka Prase BakaOsaka BakaPho Bakazuro @@ -4604,12 +3582,7 @@ BalazinGIM Balboa Park Balbuli Bald -Bald Arab -Bald Male -Bald Shupa -Bald Sicknez Bald To Bold -Bald Wookiee Bald at 29 BaldKnees BaldMansKenn @@ -4646,36 +3619,23 @@ Balob Balontra Balou Balrogs Hell -Balthazar BL -Baltimohr -Baltimore MD Baltoth -Baltramiejus Baltzerboii Balu Balu Titan Baluk Bam Achilles Bam Grizz -Bambi0326 BambiSlayer Bamboo Bamboo James BambooPandas Bambuliuss Bamf -BamfJoe -Bamfbeav -Bamiman -Bamse -Bamztile -Banan Banefish Banerz Banio Bank Stander -Bankaiz -Banki 1 1 Banzu Bape BapeNation @@ -6146,7 +5106,6 @@ Bmoot BmwNerd BnB Bnaar -Bo Ed Bo Selecta Bo0nies BoBgss126 @@ -6171,29 +5130,15 @@ Bob44th BobBojangles BobCatMilk BobGuenille -BobNegao BobRossDied BobTheDaddy BobaNeZmogus Bobakadush BobbaStanley Bobbanxd -Bobbiie -Bobby -Bobby Brawl -Bobby JoJo -Bobby Lash7 -BobbyBigLips -BobbyBonk -BobbyShurda -BobbySmooth -Bobbyccf Bobbydrake09 -Bobbysweggg BobbyyHill -Bobi Bobicles2 -Bobidabob Bobite92 Bobo Bagins Bobrobber @@ -6604,22 +5549,16 @@ Boze Worm Boze mol BozeOog Bozut -Br ay -Br ibb -Br yan Br00dje Br0ox Br0wnSpit Br3ws Br4dders -Br4w Br5andon BraBraBrad Braaamps Brabbss Brad -Brad RS -Brad T King Brad017 BradIsAChad BradIsChad @@ -6680,7 +5619,6 @@ Brando23x Brandog Brandon Brandon 126 -Brandon TJ Brandon9250 BrandonLarge Brandonp32 @@ -6718,7 +5656,6 @@ Brazeheart Brazzerker Brb Delivery Brblol -Brdy Breaches Bread Bread Again @@ -8231,9 +7168,7 @@ Cewl Cewl Hwip Cexilius Ceyyl -Cf b4 Cfretz244 -Ch i Ch i c k en Ch ief Ch00bies @@ -10096,11 +9031,6 @@ Cvanz Cvbgn Cvrkster Cvrsn -Cw90 -Cwab -Cwazza -Cweavy -Cwer Cwick Cwioktopus Cxffee @@ -10111,7 +9041,6 @@ Cyal8rnub Cyan Cyan Ablaze Cyasoon -Cybb Cyber Mind Cyber n Bug Cyber172 @@ -10180,78 +9109,6 @@ Czechmate Czha Czivend123 Czk -D A I J I N -D A L M -D A M 0 -D A M I A N -D A M N L0L -D A N G I T -D A N N Yy -D A T H I T -D B A -D B Z pker -D Blo -D Clawz -D Darkblader -D Derbles -D Dragon124 -D Duberstein -D E C O -D E F Q 0 N -D E F Q O N -D E R P -D E V I N -D F U Q -D I Q -D I R T Y Ko -D J Diddles -D Long -D M T Elves -D O D -D O M M E L -D R 6 K E -D R l Z Z T -D Rack4 -D S A V -D Squarius -D U R K -D Wilson -D Wreck -D a mo -D a r t s -D a rk -D a u t o -D a v i d -D amz -D arking -D arkoz -D as -D ashing -D avey -D axe -D db -D ebol -D ecimate -D eej -D eek -D eep -D eez -D en -D enial -D entist -D i l a n -D i x o n -D i zz y -D iesel -D iizzy -D imi -D imitri -D onda -D onger -D oo l ey -D op e -D utchgr -D-D-A D00DLES D00dey9 D0CTOR @@ -10301,16 +9158,9 @@ D4nnyy D4rels D4rk D4rth -D7NNY -D9 -D9R DA ODB KIDZ DA0IST DA3N33RY -DA4N -DAD563884271 -DADDYS IR0N -DAHDB DARCHANG3L DARGON DASH @@ -10318,14 +9168,10 @@ DAWGPOUND DArtspret DBA Paulo DBKangaroo -DBO90 DBOL TRICEPS DBUZZ DC Flubber -DC-8-51 DCreek -DD 214 -DD G DD2I4 DDAlt DDSurWrists @@ -10341,17 +9187,12 @@ DESPA SIITTO DESPAlRGE DESTYLAT DFez -DG 00 DGAF DH Marker -DH btw DHIBZ DHSC4EVER DHally -DHlN DHoShow -DIDZZ -DIETDRDIET DINGO SCUM DIORITIC DIORITlC @@ -10380,19 +9221,9 @@ DJMileyCyrus DJMuscleBram DJOFULLIN DJSeinfeld -DKHo -DKJN -DMM 2 07 -DMM Gp Swap -DMM Ryu -DMT Dad -DMT Satan -DMTDAN -DMTe DMagnum 10 DMessengerS DN Atro -DN20 DNFL DNLD DO0FY @@ -10405,12 +9236,10 @@ DONJOHNNNY DOOMBRlNGER DOOMSlayer DOSNE -DP776 DPRNS DPS Disciple DPvM DPvM Jordan -DQ9 DR PAAAK DR VABA DRAEG0 @@ -10453,9 +9282,6 @@ Da Nils Da Puppy13 Da Sniper007 Da T Virus -Da d dy -Da t -Da then bh Da1ton DaBears DaBoz @@ -10519,9 +9345,6 @@ Dachowski Dackel Dackenerino Dacune -Dad Goals -Dad Sean -DadBurrys DadGoingMad DadLeft DadRanarrWay @@ -10529,8 +9352,6 @@ DadamoSte Dadbackward Dadbackwards Dadbod4lyfe -Daddaforce -Daddy Daddy Bundy Daddy Chaman Daddy Chubs @@ -10562,7 +9383,6 @@ Dadfield Dadi415 Dadorii Dadosaur -Dads Dadukez DadurQa Dadyankee3 @@ -10610,8 +9430,6 @@ Dahlareen Dahls Dahlson Dahmonkey -Dahrmata -Dahrr Dahumbug Daijoukay Daiju Spede @@ -10778,15 +9596,11 @@ Daniella DanielleOfc Danielmcken1 Daniels -Danielwat -Daniiieell -Danijenn1211 Danilin Danimal DanisH96 DanishAdonis DanishGoat -Danje Dank Dank Chef Dank Exp @@ -11070,14 +9884,6 @@ DavidPH Davidisiscoo Davidopathy Davis751 -Davlan -Davo -Davord -Davoron -Davros70 -Davshing -Davu -Dawaj Lama Dawg Dynasty Dawkins Dawn @@ -11120,13 +9926,7 @@ Daze DazedDave DazednConfsd Dazzler95 -Dazzz -Dbeatz -Dbewt -Dbmx -Dboot Dbricke -Dbz Pride Dc B L I N D Dc Hakkarn Dc IronMan @@ -11139,8 +9939,6 @@ Dday6Jun1944 Ddestroyer56 Ddos Dds4theko -Ddsing -Ddsme De Algerijn De Baardman De Eryngy @@ -11158,7 +9956,6 @@ De Redacteur De Sam Matie De monic De stoutsten -De us De1icioso DeAndre DeDawgTubb @@ -11170,7 +9967,6 @@ DeHijskraan DeIronMan DeIronedMan DeKawika -DeLL DeLooter DeLouuu DePope @@ -16770,20 +15566,15 @@ Fyrox Fyszz Fyzio Fziaa -G G 0 A T G A F F E R G Alfansos G Ape -G B S G Check G Fruit G GAMER GIRL G I M Danny G Iron Adam -G L E N -G L H F -G M B G Man9822 G Mauls G O O D @@ -16791,36 +15582,21 @@ G O O S E Y G R E E N G R I L L O G Terminator -G X F C G Zus G a r t y G a t t s u -G ante -G dot C G e n g a r -G eeb -G i j s G i l b o -G iG G imme -G iooo G l R L G laze -G no Z -G o G G u -G o h o -G o th i X G oldd G oldeen G oofy -G ozz G rafix G ronimo27 G root -G shi G u a m s -G unitt -G-F-M G-IronKuv G-Thug Nasty G-knowww @@ -17064,15 +15840,8 @@ GTRKingZilla GUBIDUBII GUCCI SENPAI GUCCl -GUJ0 GUNMAN683 -GURRD GUUMBY -GVSU -GYDtown -GZA -GZX -Ga l Ga7ba Gaara Gaara Sand @@ -17270,7 +16039,6 @@ Gastje888 Gastronaught Gate Gateofdoom -Gath Gato GatoNaranja Gator @@ -17297,9 +16065,7 @@ Gavy Gawd Bodi Gawk5000 Gawkes -Gawkss Gawt -Gawz Gay 4 Guthix Gay Bear Gay Bear Cub @@ -17557,23 +16323,11 @@ Geuld Gew Gewoon Gezang -Gf g Gf4tiuser GfRsIGotAGf -Gfi -Gh3t0 T4nk3r -Ghafir -Ghaipol -Ghandizy -Ghandy -Gharron -Ghckkrchkrer -Ghda -Gheed Ghentiana Gherkins Ghetto -Ghhjgwsr Ghidorah Ghillie Suit Ghilly @@ -17793,10 +16547,6 @@ Gixerikan Gizmoed Gizmoo247 Gizzy-71 -Gj nice -Gjerloew -Gjonunaki -Gktr Gl Bob Gl Im Dandy Gl Im Tom @@ -18905,36 +17655,6 @@ Gytisr9 Gyts Gyym Gz Parsec -GzBs -H 0 U N D -H 2R -H A D O -H A I D E S -H A M M E H -H A R L S -H A T -H A X 3 D -H D M P -H E A L E R -H E J S A N -H O L M E -H Q Killer -H S 7 -H U L K K -H U N A J A -H a t y -H a w n y -H abs -H alo -H ch -H e c t o r -H i n e s -H l E U -H obbs -H owl -H rekDoer -H uff -H-tsi H0B0 H0DEX H0LINESS @@ -18942,8 +17662,6 @@ H0NA H0PES H0RSEFIGHTER H0RY -H0j -H0j00 H0lyPorkyPig H0me H0nestyBe @@ -20120,7 +18838,7 @@ Hislordship HisokaX4 Hispeeed Hissi-Timo -Hit U +Hit U Hit By Car Hit Points Hit The Guam @@ -20153,7 +18871,6 @@ Hldz Hlep Hlnub Hm -Hmg Hawj Str Hmm Fr Bruh HmmKoekjes Hmmer @@ -20297,8 +19014,6 @@ Hompski Hon Honaz Honchcrow -Honda Coupes -HondaXJ20 Honden Hondo Ohnaka Hondsvot @@ -20800,9 +19515,7 @@ Hyun Hyxbe Hyze Hyzers -I M I Skilz I -I ADK I I AM DROID I Am Arun I Am Calysto @@ -20817,7 +19530,6 @@ I Am Vexed I Am Vono I Am Xyience I Am Yesac -I B Z I Barak I I Be Vibing I Be Yankin @@ -20860,12 +19572,9 @@ I Heal DHers I Herb Store I Hunt Pets I Hustle Man -I I ODIN I I I JANGLER I I Judgee Yu -I Ko U Lol 1 I L0ve Lolis -I LOTR I I LV PEACH X I Lezima I I Liam I @@ -20882,8 +19591,6 @@ I Luci I Luhhya I Luv tSwift I M A P nuss -I M Ket -I M S N Y I M The Weed I Maxed OSRS I May Be @@ -20894,10 +19601,7 @@ I Need 1M I Need Succ I Need aBeer I Novato I -I Nz I -I OX I Owning -I P0 I P0KY I I Parry I I Peter I @@ -20906,10 +19610,6 @@ I Plank Lots I Play Aegis I Pod335 I Pri -I Q T -I R N B R U -I R O N 99 -I RC I ReAPeR I I Roll Need I Ron Man @@ -20981,7 +19681,6 @@ I sak I smell zaza I so pale I squared R -I t I s I tbag cows I used to Rc I van @@ -20989,11 +19688,6 @@ I vinrox I w4ste xp I wana dew u I want wings -I-IEEBO -I-Iulk -I00OOOOOO00I -I2P -I2m I2ocky I2ossiiii I3ET @@ -21004,9 +19698,7 @@ I3ox I3rucex I3ubbles I3ulow -I7I I7iablo -IA IAM HARDWELL IAMBillNye IAMDouble_C @@ -21035,10 +19727,7 @@ IBloodwing IBuyGF5GP IBuyPowers IBuyShungite -IC 3 -IC XC NI KA ICE GIANTT -ICNK ICantFit ICauseRage ICrazyCamelI @@ -21050,12 +19739,6 @@ IDiabloI IDustie IEATEDYU IFALL3NI -IFIFIFFIFIF -IFIFIFIFFIFI -IFIFIFlFIFIF -IFRC -IFRS -IFRS 9 IFartOnBaby IFernedYou IFistBonk @@ -21074,31 +19757,19 @@ IHuntKoalas II Fabi II II Gots Piie II Mossy II -II TurMz -II0III -II0v0II IICyRaNoKII III SLAYR -III jin III -IIIBCIII IIIGavinIII IIIel0n IIIusionist -IIKOO -IIPAC IIPrincesaII II_Blanx_II IIamaman IIflemishII -IIlIIAS -IIlIIoIIlII -IIllIll -IIlllllIIlIl IIndy IIrisviel IIsaac IIx Link xII -IJzer Bal IJzermeneer IK Pegasi IKotol @@ -21188,9 +19859,7 @@ IMAEATURASSS IMAFKNNONCE2 IMGOKU1 IMHankey -IMHky IMJeffG -IMMezzo IMNagrom IMPERlO IMPlayerjohn @@ -21264,18 +19933,11 @@ ITIajestic ITIallen ITIasKilleR ITIassacre -ITIatty -ITIerica -ITIiko -ITIoj -ITIoosh -ITIr ITSPYRO ITV X IThe Beatles ITrimGlories ITurtlekunI -IUR IUntradeable IV Luke IV skin @@ -21296,8 +19958,6 @@ IVIush IVIxtthew IVOXYGEN IW Lytheria -IW4M -IWGP I_Eat_Ass04 I_Inity I_Noodz_I @@ -21494,8 +20154,6 @@ IkkleHorvick Il Il MrBorn lI IlIBooieIlI -IlIIIIlIIIlI -IlIIlIllIlII IlINard0IlI IlRisklIlIlI Ileeze @@ -21569,12 +20227,10 @@ Im Hawkward Im Hersh Im Huck Im Hunta -Im Hussain Im Iron Im Iron WTF Im Jags Im Jokers -Im Jovian Im Just Ken Im Krazy Im Kyle Btw @@ -21715,7 +20371,6 @@ ImVanilla ImWargasm ImWilbur ImYourDadBTW -ImZe ImZorp Im_Stone126 Ima Guy @@ -21792,8 +20447,6 @@ Improv Improved Impulsive Au Impurest678 -Imql -Imre Imsain Imsokwtie Imstratss @@ -22026,7 +20679,6 @@ Ionia Iono Iou689 Iowa146 -IowaCJ Ioyal Ioyins IpeeInTheSea @@ -22044,9 +20696,6 @@ Ir0nMammoth Ir0nMish Ir0nPuma Ir0nRagnarok -IrDA -Iralimir -Irha Irid Irie IrieLuDa @@ -22919,95 +21568,6 @@ Izvorul Izzy IzzyBigBoy Izzyboy300 -J 0 S H Y -J 0 S H l -J 4 6 -J 4 K E -J 6 -J A B S -J A I D A N -J A M A L -J A N K I -J A U N U S -J A W D -J Breezi -J C Trousers -J D -J D Ballew -J Dahmer -J E E V E 5 -J E T -J F -J Fred Run -J I M M -J I MM Y -J Kole -J Kribzz -J L A -J MF B -J Neat -J O E G -J O L T I K -J O T A -J O3Y -J R O C -J R V -J Rat Cow -J S 2 M -J S Z M -J Saints -J Suave -J U S T A S -J U Z -J a c k a l -J a c k son -J a c k y -J a mie -J a n i -J ackal -J al -J ameper -J anii -J appie -J asnah -J ason -J asyra -J ayson -J bellfortt -J bird shady -J e sse -J eff -J effy -J ensen -J esse -J essica -J imme -J imy -J imz -J ipr -J lMM Y -J o b e -J o e -J o ey -J o f -J o s h y -J oep -J ohannes -J ointz -J oke R -J or G -J oshh -J oshhh -J osie -J u wu -J ung -J unko -J utch -J uun -J uwu -J x B -J yy -J-2tha-R-O-C J-Man 93 J-Turn J-Yeezy @@ -23034,22 +21594,7 @@ J0seph J0shh J1MB0H J1NBE -J1ub -J2TR J2caine45 -J2ck -J328 -J3Ciron -J3JU -J3S5E -J3rkkuHD -J41AL -J45e0wns -J4QS -J4S -J4gga -J4my -J95 JAABASNABBA JACK3DJOHNNY JACKYOUNG93 @@ -23061,79 +21606,30 @@ JAVON 9-INCH JAYJ51 JAYR0CKBABY JAlDYN -JB 2K -JB87 JBGard JBrody JBuck057 JBux -JC-1989 -JCS07 -JCole -JCon -JCutler -JD MD -JD4 -JDBass -JDEP -JDFlaSh -JDJM -JDez -JDlion -JDredd66 -JDuck -JE B JEEZE JENNY JENNY DEATH JERN SVIN TO JETSNBEERS JF Kennedy -JFB -JFCK JFK gone AFK JFKautopilot -JFL JField JFrog JFryGuy JGIRONTG -JGIV -JGlen97 -JH3305 -JH91xx -JHINitalia -JIGGYWIGGY -JIIVEE94 -JJ-M -JJ23 -JJAAKKO -JJBW -JJPowers -JJROCKETS -JJRicky -JJS BBQ -JJSM_Dulker -JJchris66 -JJoe -JJumalwelho JK Rowling -JKMi -JKTimbo -JKUR ON 40S -JKeM -JKingJ777 JKrollin JKuyaa -JLG JLowe JLsone -JMI NG JMTaipei JMack JMiddd -JOBBO -JOCKO00O0O0O JOE EROTIC JOKER 709 JON3ZYY94 @@ -23149,9 +21645,6 @@ JPantless JPatness JPence JPountney -JPudz -JR05E -JR0D JRBeast JRC Crypto JROGU @@ -23167,32 +21660,12 @@ JSilvester08 JSlice94 JSplash JStepho -JT5 -JTAG -JTCS -JTI ain -JTIAIC -JTM33 -JTscape -JUGIB -JUIBE JUICEWRLD9 9 JULlAN JUST JUST A HlPPO JUST Nikk JUSTICE -JWRLD -JXJ -JZB -JZX1O0 -Ja k ey -Ja m e s -Ja mes A -Ja se -Ja sn -JaBouris -JaDig JaStraater Ja_Fireking Jaaaakkoooo @@ -23300,32 +21773,11 @@ JadsVag Jaecob JaegerBoom Jaeson -Jafacakeman -Jafanto -JafarTooHigh -Jaffa Jake -Jaffar -Jaffywaffy -Jafsx -Jagdpanther JagerBombski JagerIron Jagermeister Jagged Jaggen -Jaghatai K -Jagoodiii -Jah toch -JahIthBer -Jahaerhys -Jahaok -Jaharred -Jahbby -JahgexPlzzz -Jahmay -Jahmerica -Jahngles -JaiSiaRamJai Jaiden184 Jailbreak455 Jaime 427 @@ -23354,13 +21806,6 @@ Jakey Jakey C Jakeyosaurus Jakeyz -Jaknop -Jakrem -Jakrojan -Jakuli226 -Jal-Nib-Jmal -JalNib -Jalduii Jaleesa Jales Jalim Rabei @@ -23394,24 +21839,17 @@ James Kelp James Poncho James PvE James Rolfe -James c James osrs James1087 -James2709 -James9 -James945848 -James9520 JamesBondss JamesCUFC JamesDaWizar JamesHaliday -JamesJ2019 JamesLango JamesMaynard JamesNI JamesPratt94 JamesShotGG -James_22 Jamesay Jamesbombom Jamesrb1 @@ -23440,9 +21878,6 @@ Jamosbondos Jamppa Jampy Jampyre -Jamuli -Jamurazi -Jamwa Jamyroo531 Jamzylockz Jamzz @@ -23479,21 +21914,6 @@ Janne JannpajII JanoPotato Jansky -Jansz101 -Jante -Jantex -JantheBear -Jaooa -Japanese -Japhur -Japiohh -Japles1 -Japoolie -Jappieee -Jappieness -Jappo -Jaqen -Jaqquu Jar Of Pets Jar Uh Dirt Jar of Pukes @@ -23622,47 +22042,8 @@ Jayster Jaytea Jayteaf Jaytee1262 -Jaywub -Jayy -Jayy Slays -Jayy x -Jayzar -Jaz Coleman -Jazo -Jazpurs -Jazz -JazzFlap -JazzMaster09 -Jazzeh -Jazzjr89 -Jazzly -Jazzy -JazzyFlips -Jb Godranger -Jba123 -Jbevzzz -Jblieves88 -Jbob72 -Jbt -Jbvff -Jc_TheCops -Jcb4646 -Jcdelavici -Jchn -Jcmalone23 -Jcolts20 -Jcourt1 -Jdaws -Jdidy -Jdoggy2018 -Jdp3 -Je nny -Je pppe -JeBoyHiddema JeIlo JeIly Man -JeJoat -JeK0 Jean Jean belette Jean man @@ -23739,7 +22120,6 @@ Jelen Jelenner Jelior Jella -Jelle Jelle Bouma Jellie40 Jellisme_99 @@ -23755,12 +22135,9 @@ JellyBeanRs JellyGenix Jellydonuts Jellyfishes -Jelziin -Jelzini Jemades Jemelope Jemile -Jen na Jen0va JenaTulwarts Jenessa @@ -23826,128 +22203,6 @@ Jerry Maine JerryChinger JerryMina Jerryy -Jers -Jers Knot -Jersh -Jershawerr -Jersion -Jertz -Jeru -Jerunox -Jerusalenm -Jerziii -Jerzy -Jes2x -Jeseeka -Jesh g -Jesh-mar -JeshusChrist -Jesiah -Jesk -Jesliq -Jesper Bratt -Jesper135 -Jesperyo -Jess -Jesse -Jesse Top -Jesseq -Jessica -Jessie -Jessie Jones -Jesspresso -Jessy -JessyTrip -JessycaOSRS -Jester Head -Jesterbubba -Jesus -Jesus I love -Jesus MPhys -Jesus Saved -JesusComing -JesusRedeems -Jet Jaguar8D -Jet3010 -JetFlame -Jeththe -Jetlag -Jetma -Jetridder11 -Jetski -Jetsmoke -Jettiesimp -Jettrider -Jeugd -Jev21 -Jevel -JewFroBro -Jewbaaca -Jewbakah -Jewbang -JewishRob -Jewy -Jexlad -Jexlo -Jeyos -Jeyzuz -Jezeus -Jezkoz -Jezuux -JezzaripHD -Jezzie -Jezzx -Jf-n03 -Jfleeze -Jfrith -Jfuzzy -Jglove -Jgus88 -Jgy1889 -Jhackal -Jhb -Jhebs -Jhny -Jhonlovin -Jhoocy -Jhoocy Moot -JhormanCovid -JhosS -Jhow -Ji bs -Ji m m -Jia Lissa -Jian -Jiara -Jibajaba -Jibberflexed -Jibbllyy -JibinSui -Jibneh -JibrilMaster -Jiffee -Jig Bugs -Jiga Chad -Jiggalagg -JiggerJoe -Jiggity -Jigglyboy -Jigglywoo -Jiggypufff -Jignite -Jigoogly -Jih -Jihe -Jihne -JiiU -Jiiko -Jiim Lahey -Jiiraiiya -JikdarShark -Jikkurr -Jiklim -Jill Hyde -Jille Man Jim Jim Sauce Jim Shorts @@ -24006,9 +22261,7 @@ Jims Ironing Jimsterjim Jimver Jin Oh -Jin R n G JinDoritos -JinJ0 nJuice Jinb JingleBiloba Jingy @@ -24046,22 +22299,12 @@ Jixr Jixx0x Jiyool Jizt -Jj Dynomite -Jj Jerk2 -Jjar127 -Jjjjjj210 -Jjozzie Jk Esq Jkdogg Jkhby Jkl Kalja Jkolrur Jkrexx -Jku45 -Jl-SOO -JlGA -JlLLY -JlMMB0 JlZZB0SS Jlarge Jlova @@ -24081,27 +22324,9 @@ Jmz Jnas JnrSeneca Jnsthenx -Jnup -Jnwp -Jo Pain -Jo de Coeckh -Jo h 2 -Jo iron -Jo rd an -Jo shua -Jo we -Jo0l -Jo3 H -Jo3p -Jo5p -Jo6p -Jo711 JoE ShMoee JoEiSaFiShEr -JoJi -JoJo JoJo Skriver -JoJo79 JoJoJoUrBoat JoKerRtheGOD JoMoe @@ -24156,7 +22381,6 @@ Joee P Joeholding Joekle Joel -Joel 9444 Joel In Pain Joel Lobster JoelBtw @@ -24246,16 +22470,6 @@ Johnsters4 Johny Johny Aus JohnyLocoo -Johnyy -Johuab -Johzyn -Joizz -Jojis -Jojj -Jojkan -Jojo Rabbit -Jojora -Jojy Jok Jokar Joke @@ -24432,46 +22646,6 @@ Josh x Josh013 Josh2Godly JoshD -JoshDagainz -JoshGymnast -JoshMarksman -JoshYewAhh -Joshalog -Joshan -Joshery -Joshh -Joshhhh -Joshii -Joshimitzu -Joshism -Joshjoshin -Joshmaster31 -Joshpaul -Joshua -Joshuaaaah -JoshyCii -Josiah Higha -Josiahs -Josoust -Joss -Josse -Jostavo -Josti O_o -Jostle -Josue -Josukes -Josylvio -Jota_420 -Jote -Jothha -Jotjemenotje -Jotq -Jottini -Jotunheimar -Jotwe -Joueur4376 -Joulaha -Jovial Jovilius JovyGaming Jowah @@ -24491,21 +22665,9 @@ Jpan1 Jpellican Jpq Jqwss -Jr Metro -Jr Muffin -Jr Stigel -Jr2k13 -Jrabbat -Jrby -Jrdn Jreppks Jrey Jroanirr -Jrodjok -Jrogo -JsJays -JsN4 -Jsag Jsi7111 Jsnn Jsony @@ -24595,18 +22757,6 @@ JuicyTigr JuicyWetNut Juicy_Newfie JuiicyAF -Juikki -Juint -Juipp_Iron -Juisy -Juk e -JukeLess -Jukebot -Juked -JukeduM -Juko -Juktes -Jul es Jules Julesbak Julia @@ -24764,100 +22914,9 @@ Juun Solo Juuna Juunaz2chips Juustis -Juuzo -Juvi -Juvian -Juzzy -Jvzy -Jwad -Jwcsg -Jwd -Jwett -Jwu -JxJxV -JxcelD -Jxck -Jxcx -Jxdidiah -Jxdooo -Jxhnn -Jxke -Jxmeson -Jxnas -Jxni -Jxstxn -Jxxst -JxyStorm -Jy -Jybais -Jyeronese -Jygers -Jyhlln -Jyhy -Jype -Jyppedi1992 -Jysk -Jyura -Jyy -Jyypy -JyzzBrah -Jz -Jzbeta -K 1 L L A -K 1 P -K AMI -K B D autism -K E K E B -K E L A -K E T CHUM -K E V 0_O -K Hades -K K Boef -K NW -K O L L I -K O M P I S -K OOOOOOOOOO -K P N -K P Sweet -K Smalls -K W -K W A L A -K Y Y -K a l e w i -K a z a -K aarel -K ayyla -K eller -K elvin -K en -K etaminer -K ev -K iNG IRON -K idd -K ilo -K im -K l 9 -K l N G S -K nauss -K nut -K o j o -K o o s a -K ohen -K orruptt -K ree -K rs -K t r n e -K una -K ushi -K uz -K voth e -K y u m a -K yogre -K-Diddy K-epan K-market K0 -K0 4 K00LBR33ZE K0F K0L0S @@ -24873,7 +22932,6 @@ K0rnuit K0tleciokas K0veras K0zor -K19 K1ERZ K1LLY K1ddl3 @@ -24883,8 +22941,6 @@ K1ngo K1ngshredder K1r1t0123 K2 Jung -K32 -K38 K3KSE K3U S2 K3azkoks @@ -24892,26 +22948,18 @@ K3fka K3kt K3mi K3nn3d -K44K -K4IF20 K8iee -K99 2 -K9Father K9lenny K9rk -KA97 KABBABEAST KAKAGUATE0 KAKERANDELIN KAL-JML KAMlX KAT alyzt -KB1988 KBARAKAT KBX0 KC Chiefz -KC M0 -KC8 KCRB KChiefn KDOG1419 @@ -24938,7 +22986,6 @@ KGP KGee KGoldy KHADER -KIIIIIIIIIIH KILLER COMBO KILO KIMB0 @@ -26887,58 +24934,6 @@ KyuubiKurama Kywt Kyykin Kzyl -L 0 S T Y -L 3 G 4 C Y -L 67 -L A R A M S -L Ben -L CBO -L D A -L E G E N D -L E G O -L E L O -L E P I -L F C -L FC -L Hus -L I N U X -L I V M -L OAFS -L S Q -L U I G -L U U K E -L X R D S -L achie -L aika -L aka -L ama -L ang -L apras -L atias -L aw Rune -L aze -L e an -L eafErikson -L egs -L ek -L emaster -L ev -L i m a a -L iamm -L iar -L ilo -L inox -L ions -L o w g -L ockdown -L ofty -L osi -L paradoxum -L u m i -L u mi -L u x -L ucas -L unatic L00000 L00M L00OL0OO00OL @@ -27026,8 +25021,6 @@ LIMEWORLD LIQUICITY LITEIT LITHITS -LJ 8 -LJAP LJPalmer LKIT LL Trigger @@ -27056,10 +25049,7 @@ LOSTinGAMES LOUlSlANA LOWIQXD LP Smokie -LRG -LRGD LRichyy -LS1 LS3D LSD-25 LSDDS @@ -29076,81 +27066,6 @@ Lyyli PL Lyzu Lzin Lzs -M A G 3 -M 1 KE -M 3 3 P -M 4 T R I X -M 8 A 1 -M A D O X -M A D Storm -M A T E J -M A X O U T -M A X PAYNE -M B Z -M E H I S -M E L D O -M E T R O -M E X I -M I K B A R -M I T H O X -M I U -M I Z Z O U -M INDGAME -M Itty -M K J -M O B I L 3 -M O C 0 -M O C H -M O ID O K -M R NaCl -M Super Buu -M T C -M U D K l P -M X G P -M a V 3 Rick -M a d Shrumn -M a k a i -M age -M aikel -M ak0 -M ammoth -M ana -M ankDemes -M anu -M aples -M arcel -M arquim -M artin -M ask -M athis -M axou -M azzz -M c -M elz -M enzy -M ga -M gh -M i t c h y -M i y a -M ikasa -M ike -M imik -M int -M itchel -M ittens -M l Q Q -M merz poL9 -M o C e -M o r t e n -M oist -M onkfish -M orytania -M the Maxed -M ugger -M ulas -M urphy 2 -M usashi -M-theory M00CHIE M00SE M00SE M01 @@ -29271,55 +27186,38 @@ MCHammered MCKenny91 MCSIZZLE MCmattt -MD7 -MD96 MDE Presents MDPS -MDaher MDucks MEAT G0D MEAT HEAD36 MEGATRON -MEK4KK4KK4KK MELAN00MA MELT METM0NKEY METR0lD METS0 MEV4NS -MF DC MF MORTEN MF SofaKing MF TEE -MFE MFKU MFLI MFSTEVE -MG5 MGFS MGKRevs MGM WAY MGreengrass MH Therapist -MHA C -MHBC -MHS MIDAs MILFmauler MILSHAKE -MINH MISOGl MISSYGAMlNG MIST MITCHY MIX0R -MJ23 -MJKaboose2 -MJT MK-HARDSTYLE -MK6R -MKAM -MLB MLTEEZY MLaidman MMMahogany @@ -29332,10 +27230,6 @@ MOMHUNTER666 MON5TER MOODSWlNGS MOOSEM3AT -MOTM -MP17 -MP9 -MPB MR JOHN WlCK MR LETHAL2u MR REET @@ -29347,7 +27241,6 @@ MRC Tugboat MRGAMEZ MRHD MRLARGE -MRM MRPlZZAPRIZE MRWHlTE MR_MAITO @@ -29355,18 +27248,12 @@ MSPaint64 MSceneFF MSpacePotato MStarkz -MTBMB -MTPETE -MTV CRlBS -MTXP MUISSS911 MULHERndaEXP MUMM0 MURMELl MUSK MUSK0KA -MUSUMUMM -MUZAMMIL MV Flow MV Welshy MVIII @@ -29375,7 +27262,6 @@ MVP HERO MVP Mahomes MVRDA MVTIASD -MWwarzone MY L U N A MYRSKYVIITTA MYTHICROYXLE @@ -29383,7 +27269,6 @@ M_Sariol Ma Band Ma Dood Ma Titi -Ma t t h e w Ma5onx Ma7e MaCoMb @@ -31670,26 +29555,6 @@ MoetIkLopen Mofaer45 MoffelRS Mofleminator -Mofo Lt -Mofo Shadow -MofoMo92 -Mofoe -Mog Time xD -Mogcow -Moggok -Mogtime -Moh -Mohahm -Mohamedss -Mohanad -Mohannah -Moheed -Mohh -Mohib -Mohlo -Mohnday -Mohphy -Moiqol Moist Moist Dreamz Moist Holy @@ -31702,8 +29567,6 @@ MoistWreck Moistium Mojimot0 Mojito -Mojo Fiki -Mojojojo171 Moju Moju GG Mojurico @@ -32488,7 +30351,6 @@ MrsSocorelis Mrslipkn0t Mrwaffleses Ms Goblin -Ms K Ms Lizziard Ms Trap Ms Zik @@ -32529,47 +30391,6 @@ Muckball Muco Mud Cricket Mud Temple -Mud9 -MudCatBigDog -Mudda Focha -Muddas Main -Muddy patch -Mudguard -Mudkins -Mudkip -Mudmur -Mueezy -MuerteBella -Mues -Mufasa -Mufasa IXI -MufffinKing -Mufficer -MuffinActual -Muffinkyutie -Muffins -Muffinyatta -Mufz -Mugarooni -Mugen -Mugge -Muggerman3 -Muggled -Muggles -Muggtjuven -Mugrub -Mugy -Mugzy -Muhaji -Muhamed -Muhfn -Muhkea -Mui Gokuu -Muilpeer -Muki -Mukkaram7861 -Mukkey -Muktheduck MulasRevenge Mulberry Mtn Muleleaveox @@ -32720,8 +30541,6 @@ Muziek Smurf Muzket Muzz Muzzle -Mv P -MvP ov RnG Mvk Mvko Mvp Scrub @@ -32851,51 +30670,16 @@ Mythrin III Myto Myuf Myuk -Mywa -Myz Myzi Mzaa Mziy -Mzr Mztar -N 10 -N 55 -N A l N E R -N E L L -N E N E N Gallagher -N I GH T96 -N I N O X -N I S H -N ICK Y -N O B S Y -N U B U -N W M -N a t t z -N ang -N anko -N arb -N dejay p -N e a k i le -N e i l -N e0 -N iall -N ibbler -N ightgleam -N l C K O -N l E V E -N o m a d -N occo -N oggin -N u d -N uggies -N-J-R N0 H34RT N0 Invictus N0 pid N00biistyl N00bslayer27 -N04me N0B4Marri4g3 N0Ballz N0ID @@ -32912,26 +30696,12 @@ N0t Maxed N0t special N0tliketh1s N0ul -N1 CK N17 Jake -N1C3 N1NJASK1LLZZ N1ckai N1cwho N1nja N1njaCat -N3XX -N3p -N3se -N3x -N4L -N4ruto -N4styNat3 -N7N -N8vy -N9NE420 -N9T7 -N9U NABEEL RJ NAGAKAMAL NANORA @@ -32940,14 +30710,6 @@ NASDBOY NASSERN NASTY NAVl -NB8K 2K13 -NBA -NBA NewMain -NBA Youngb0i -NC90 -NCG -NCG 2 -NCPS NEBR0SKY NECR0DANCER NEEDAMETHYST @@ -32964,14 +30726,9 @@ NEXFARMER NEYOVIC NFed NHL Blues -NHrn NIIXIIK NINJABLEV1NS NINJATMNT -NITR00 -NJC20 -NJWW -NKJ NL Chronos NL Gilbert NLDeluXe @@ -32995,32 +30752,15 @@ NOTaPancake NOmki NPC Healer NPC Icedrake -NPYJ -NRA -NSFL -NSHN NST Praise NT FiSHvv -NT Y NTBeerBandit NTMR RADIO NUEL NULLI NULLlN KUPPl NUTSHOT -NVQ -NWHL -NWI 219 RAT -NY -NY C -NY G -NY x LEGiiT -NZ Dave -NZL -N_MB N_other_day -Na Mn Or I -NaCl NaCl Sprite NaCl is salt NaQ @@ -33045,15 +30785,6 @@ Nacho Alt Nacho2030 NachoByte NachoDragon -NachoPapi -Nacht -Nachtkastje -NachuiTuda -Nadaa -Nadeo -Nader -Nadsage -Nadund Naethera Naftininkas Naga @@ -33110,26 +30841,12 @@ Namine Silke Namir Nammer Namuko -Nana -Nana Steel -Nanado -Nanciscor Nancyy Nander Nandos Nandos Man NangMan Nangdalorian -Nanimavi -Naniva -Nannertee -Nanno -Nannu Baba -NannyCam69 -Nanoh -Nanoman360 -Nanonymouse -Nanook IV Nanoray Nanotech Nans @@ -33179,38 +30896,6 @@ Naru808 Naruto Narval Narvalow -Narwallus -Narwhal1731 -Narx4 -Nas is like -Nasa -Nasaman -Nascar -Naseeph -Nashh -Nashluffy -Nashonic -Nashy -Naskarsdad -Nasko 07 -Nasper -Nasrullah -Nasseee -Nassim -Nast -Nastacov -Nastie -Nastik -Nasty -Nasty107red7 -NastyAss -NastyCasual -NastyDonger -NastyGarbage -NastyGeUsers -NastyV6 -Nasuuu -Nat Scheetje Natalie Natby Nate @@ -33479,8 +31164,6 @@ Nerf Bowfa Nerf Coffee Nerf Th1s NerfMePlz -NerfTG -Nergegante Nergg Nerio x Nerithma @@ -35685,24 +33368,15 @@ Ozzy Hobbit Ozzykye Ozzys Ozzzyy -P 0 W N E D -P 0 E F -P 0 R G I E -P A M K A -P A P Z -P A R N Y P DIRTY SODA P EDRAO P Eng -P I T P K P O L I S H P O T A T O P O V I P Purts P R O X -P R S -P V M Lew P W A Y P Y R O P a n x o @@ -35764,7 +33438,6 @@ P4sk P5ythix P6D P7DRO -P9 PA N I C PACK WATCH PACKETLOSS @@ -36344,11 +34017,7 @@ Pb and Jd Pbby Pbkillua PbyOne -PdaddyReborn PdfPKerNoGF -PdiddyReborn -Pe en -Pe t er Pe1ipp3r Peabody PeacandLove @@ -38185,12 +35854,6 @@ Pyzdalupi PzK Pzju PzzaPredator -Q 1 -Q K M Nophis -Q Proserpina -Q S L -Q cs -Q l ii Ma X Q of Spade Q uincy Q-Dance Jr @@ -49584,7 +47247,6 @@ USirHaveLost USirHaveWon UTT UWCB -UWF UWUSTELIJA UZY VS JAD Ualt @@ -49597,7 +47259,6 @@ Uber Yeats Uberamazing Ubersmind Ubicorn -Ubu Uccino Uchiwa Uchr @@ -49619,7 +47280,6 @@ Uh-0h Uhbove UhhhBoneless Uhhhh Wut -Uhm Uhscended Uidi One Uim Beyonce @@ -49679,7 +47339,6 @@ Umiland Ummfufu Ummz Un Dutchable -Un M-U-T-3-D Un puma Un-Expected UnDutchable @@ -54506,7 +52165,6 @@ apou appelkneuz applee aqp frog -aqqqqqqqqqqq aquafx araenel13 aratsanus @@ -54515,20 +52173,7 @@ archyiop arcvnaxiii arcwriter ard lad 06 -ardazz ardy guardy -arengs -arevles -arexmeister -arfih -argilah -ari abdul -ari shaffir -ariman22 -arkoudaphile -armadyyyyldo -armyofkids -arnr arocardo arookie arouze @@ -54559,7 +52204,6 @@ asian asianbunnyx asibioass asidb -asm asmoooo ason jones aspiraring1 @@ -54571,9 +52215,6 @@ assbergerler assdrag asseaterbtw assoffire -astgferallah -asuhcuh -at0 atob7 atoma619 attaaM @@ -54582,7 +52223,6 @@ auditore28 audrey audrey horne auma -aus j osh aussieyobbo aut AT5 aut1st1c @@ -54623,22 +52263,6 @@ azilim aziz8mohd azj azura -b a g -b a l r a j -b b o x x -b eeg -b enjy -b ezos -b i g s t -b kuz -b l u rr -b oe -b on ass -b oo n -b ooth -b u l -b ulba -b-ray29 b00ty b00tyw1zard b0btehcool @@ -54950,10 +52574,6 @@ bisse bitten by bitter bitter fruit -bj0rne -bjassen -bjpc -bjuti bkguytd6 bl00d twinz bl00dShaman @@ -55026,23 +52646,10 @@ blutorch blvckstvrr blynaas bman5 -bmeow -bnff bnndt bnqy -bo bby -bo nk bo2Lawrence bo3rke -bo4r -bob bob bob -bobby ross -bobby45153 -bobbyb727 -bobbyitsme -bobbyjoe -bobbytronx -bober vvittu bobfish66 bobness bobondowski @@ -55124,10 +52731,8 @@ boycie420 boydi boydt boyuniverse -boz pwr boze bozo -bp9 br0wnardRS braap poster bradrian @@ -55263,18 +52868,6 @@ byEmilsson byll byrny bzerk -c a b l a y -c bro -c greyson -c h u c kles -c hainz -c j t -c m l -c o 1 a -c onorr -c rompt -c ubic -c xx zz c c-ross93 c00lbeer c0vid @@ -59902,14 +57495,7 @@ mlong06 mmaxie mmigo mmmkay02 -mmmmmmmmhmm -mmmmmmnmmnm -mmmuurrddaaa -mndo mniml -mno -mnt -mo an mobile moer mogwire @@ -60014,13 +57600,6 @@ mstr nay nay mtash96 mthic muchderanged -mucserup -mudbitedlite -mufassa -muffing -muggfac -mugii -muh muh sheen muhName muhnamezjeff @@ -60075,12 +57654,6 @@ myrtlecat mys_try mystic myturngranny -mzsc -n a g a -n k h -n o m i s -n oge -n os n00b tax n00btube n00dIe @@ -60091,14 +57664,7 @@ n0rthmemphis n1ch0las n1ghtmares n3cromans3r -n4ts -n8m -n8n nSubordinate -nVox -nYer -n_koo -na cba naamarihomo naapurintati nabritches @@ -60383,17 +57949,10 @@ nymue nysyGG nzskater o Buffy o -o Galaxy -o Jay o -o NEK o o Pug o o SiLeNce o o Steven o o c c u l t -o chem -o n e i n v -o tp -o tu o0 Rang0r 0o o00dan00o o0Ganktank0o @@ -60656,9 +58215,6 @@ oxyy oysni tu ozos ozztrevor -p hd -p n g -p x v x m p000r p0ge p0tat0_baked @@ -60730,7 +58286,6 @@ pazmar pb tiramisu pbagel pbj eater -pbjt pcce pd3 pdi @@ -61057,9 +58612,6 @@ pzqlpwbma q Aleks q Nossie p q b0nkerz q -q f z -q l l u -q sl q-Mini-p q0k q9q9q @@ -61117,15 +58669,6 @@ qwruqwpourqr qy qz qzxz -r a i n i n -r a i q -r d x -r eflex -r ehab -r i ley -r n g o d -r o c h i -r pt r u a pussy r0adh0g r0jasss @@ -62393,12 +59936,6 @@ syytu szer szeth17 sztuk -t iel -t imbo -t r a m -t rio -t u k e -t ux t-Wrench t-painn t0_valhalla @@ -62657,11 +60194,7 @@ tjd1233 tjomka tksnevrlucky tmahones -tmeer -tmeer 18 -tmjdx tmued -to dd to0Oldf0r1t to_o toad @@ -62729,7 +60262,6 @@ toxiclun toxicsaitama toy Owner tozmic -tq tr0nberg tr0nd tra1nwr3ck13 @@ -62993,12 +60525,6 @@ uz x uzei uzis akimbo uzui -v Simba v -v olksu -v oltage -v tsng -v uka -v yp v-yordan0702 v0i kehveli v0mbat @@ -63172,10 +60698,6 @@ vw vzi vzkg w Danko -w e b r l -w en -w ert -w vy w00_88 w00d pecker w00tgh0st @@ -63330,7 +60852,6 @@ whyamisofat whynotp2p whyuboolyme whyzerkbro -wi f wibeton widefang wiegehtsmir @@ -63375,12 +60896,10 @@ wiw wizard129 wizardyoda7 wizkid499 -wjsn wkurtin wlkerTXrangr wndow wndy -wngo woah wocket wodg @@ -63431,17 +60950,10 @@ wutzgood wutzit wwTakun wweadge2 -www -wwwMusic-Map -wyat wyattearp99 wyked wytch wyverns4days -wzav423 -wzrdddddyo -wzrds -wzs x 0lev x x ABBlE x Argonath x @@ -63482,10 +60994,7 @@ x iyad x x lollage x x mk ultra x preska x -x r x warri0r121 -x zi -x zn x073x x0Mag x0Tub @@ -63594,15 +61103,6 @@ xHugsi xHussla xI3reeze xIron Senpai -xJeb -xJiren -xJlN -xJolt -xJord -xJordd -xJulia -xJuve -xKAJJEx xKadi xKdpunx xKing @@ -63822,7 +61322,6 @@ xtyrantix xvn xvrph xvza -xwl xwuwesxdrf xx darkminer xxDerp @@ -63843,8 +61342,6 @@ xzb xzizzil xzn 2 xzwu -y om -y w y0y0keepitup y37ir y8s1 @@ -63869,10 +61366,6 @@ yapgragim yasuo god69 yayasquirrel ydoc -ye idc -ye ki M -ye p to -yea im jebus yeahboi9992 yeahsmitty yeahyoink @@ -63897,9 +61390,7 @@ ykO Ops ykeL yleisradio ylliB -ym y ymca4life -yna yo eight yo itz ep yobacha @@ -63914,32 +61405,6 @@ yooyeet yorkietootz yorue you died123 -you r a qt -youb1n -youneedcope -young meows -young vibby -youngbriks -youngmachine -youngtrop21 -youngwings -youpougou -your -your thrall -youralterego -youssef -yowasupppbra -yoyoma361 -yp -ypoodle -ypool4 -ypools -yragbackward -yrhs -yribbles -ytsud mi -ytuiop -yugiiii yuh huh yum yummybolete @@ -63960,13 +61425,6 @@ yyknaH J yyttam yyzanadu94 yzyzyzy -z 5 x -z Animal z -z Rhodes -z Shane -z a p s -z iQ -z man827 z0nk z0rrda z0up @@ -63999,10 +61457,6 @@ zSlay zSpaceRaptor zSwanny zTitan -zWxLF -za2 -za33erklan -zaaza zacharial zachhy zachte @@ -64029,7 +61483,6 @@ zazyga zbra zclx zcollins -zdi zdin zdya ze4l @@ -64091,10 +61544,6 @@ zionari zippp zirreael ziurbtw -ziuys -ziyi_wangler -zjh -zjind zlayaa zlink10 zlliM @@ -64124,7 +61573,6 @@ zruG zrzwns ztaM ztkfps -zu b zubor1 zuenzima zujal @@ -64139,8 +61587,6 @@ zummorak zurcc zurlond zuuryy -zw -zwah zwint zwolle zwqpDEOXl23 @@ -64152,9 +61598,6 @@ zykez zymaa zymz zysuna -zzad -zzai zzben zzero -zzigma -zzzJonno +zzigma \ No newline at end of file diff --git a/Server/data/configs/object_overrides.json b/Server/data/configs/object_overrides.json new file mode 100644 index 000000000..c00cbf672 --- /dev/null +++ b/Server/data/configs/object_overrides.json @@ -0,0 +1,165 @@ +[ + { + "mode": "add", + "id": "1814", + "location": "3090, 3475, 0", + "type": "4", + "direction": "nw" + }, + { + "mode": "add", + "id": "2646", + "location": "2445, 3413, 0", + "direction": "nw" + }, + { + "mode": "add", + "id": "2646", + "location": "2447, 3414, 0", + "direction": "e" + }, + { + "mode": "add", + "id": "2646", + "location": "2447, 3421, 0", + "direction": "nw" + }, + { + "comment": "Prison Pete Random", + "mode": "add", + "id": "36788", + "location": "2094, 4465, 0", + "type": "10", + "direction": "e" + }, + { + "comment": "Green Portal", + "mode": "remove", + "id": "11371", + "location": "2085, 4457, 0" + }, + { + "comment": "Lever", + "mode": "remove", + "id": "10817", + "location": "2083, 4460, 0" + }, + { + "comment": "Lever", + "mode": "add", + "id": "26191", + "location": "2083, 4460, 0", + "type": "10", + "direction": "e" + }, + { + "comment": "Window", + "mode": "add", + "id": "26184", + "location": "2084, 4459, 0", + "type": "0", + "direction": "n" + }, + { + "comment": "Door", + "mode": "add", + "id": "26186", + "location": "2085, 4459, 0", + "type": "0", + "direction": "n" + }, + { + "comment": "Door", + "mode": "add", + "id": "26188", + "location": "2086, 4459, 0", + "type": "0", + "direction": "n" + }, + { + "comment": "Window", + "mode": "add", + "id": "26184", + "location": "2087, 4459, 0", + "type": "0", + "direction": "n" + }, + { + "mode": "remove", + "id": "37670", + "location": "3292, 3299, 0" + }, + { + "mode": "add", + "id": "37304", + "location": "3292, 3299, 0" + }, + { + "mode": "add", + "id": "20987", + "location": "3821, 2996, 0" + }, + { + "mode": "remove", + "id": "356", + "location": "2804, 3428, 0" + }, + { + "mode": "add", + "id": "356", + "location": "2804, 3428, 0" + }, + { + "mode": "remove", + "id": "20228", + "location": "2537, 3573, 0" + }, + { + "mode": "add", + "id": "27663", + "location": "2537, 3573, 0", + "direction": "w" + }, + { + "mode": "add", + "id": "39237", + "location": "2957, 3266, 0", + "direction": "n" + }, + { + "mode": "add", + "id": "39245", + "location": "2956, 3270, 0", + "direction": "se" + }, + { + "mode": "add", + "id": "39242", + "location": "2955, 3273, 0", + "direction": "w" + }, + { + "mode": "add", + "id": "39241", + "location": "2955, 3274, 0" + }, + { + "mode": "add", + "id": "20987", + "location": "2821, 2996, 0", + "direction": "s" + }, + { + "mode": "add", + "id": "21301", + "location": "2662, 3162, 0", + "direction": "e" + }, + { + "mode": "add", + "id": "4176", + "location": "2629, 3661, 2", + "type": "4", + "direction": "e" + } +] diff --git a/Server/pom.xml b/Server/pom.xml index 5c93c44d2..ffc43d1c8 100644 --- a/Server/pom.xml +++ b/Server/pom.xml @@ -252,6 +252,7 @@ false false + -Xmx4g -Xms2g 2.22.0 diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt index 074ab27a6..6a7b8802a 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStar.kt @@ -99,12 +99,18 @@ class ShootingStar(var level: ShootingStarType = ShootingStarType.values().rando return ShootingStarType.values()[level.ordinal - 1] } + /** + * Clears the current star object or sprite + */ + fun clear() { + SceneryBuilder.remove(starObject) + clearSprite() + } + /** * Fires the shooting star (spawns a new one). Only used when spawning new shooting stars, not for downgrading existing ones. */ fun fire() { - SceneryBuilder.remove(starObject) - clearSprite() SceneryBuilder.add(starObject) if(!isSpawned) { (0..2).forEach { diff --git a/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt b/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt index 7368b7689..0c938aec5 100644 --- a/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt +++ b/Server/src/main/content/global/activity/shootingstar/ShootingStarPlugin.kt @@ -17,6 +17,7 @@ import core.game.world.GameWorld import core.tools.Log import core.tools.secondsToTicks import content.data.Quests +import core.game.node.scenery.SceneryBuilder class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Commands, StartupListener { override fun login(player: Player) { @@ -46,6 +47,7 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com // Check if it's time to fire a new one if (star.ticks >= tickDelay && !star.spriteSpawned) { + star.clear() star.rebuildVars() star.fire() } @@ -133,11 +135,12 @@ class ShootingStarPlugin : LoginListener, InteractionListener, TickListener, Com } override fun defineCommands() { - define("tostar", Privilege.ADMIN, description = "Teleports you adjacent to the currently active star.") { player, _ -> - teleport(player, star.starObject.location.transform(1,1,0)) + define("tostar", Privilege.ADMIN, description = "Teleports you inside the currently active star.") { player, _ -> + teleport(player, star.starObject.location.transform(0, 0, 0)) } define("submit", Privilege.ADMIN, description = "Rebuilds and fires the shooting star event immediately.") { _, _ -> + star.clear() star.rebuildVars() star.fire() } diff --git a/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt b/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt index 5b065f567..c945d2f6e 100644 --- a/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt +++ b/Server/src/main/content/global/ame/events/evilchicken/EvilChickenNPC.kt @@ -8,12 +8,15 @@ import core.game.node.item.Item import core.tools.RandomFunction import org.rs09.consts.Items import content.global.ame.RandomEventNPC +import core.api.sendMessage import core.api.utils.WeightBasedTable +import core.game.world.map.MapDistance val ids = (2463..2468).toList() class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(2463) { val phrases = arrayOf("Bwuk","Bwuk bwuk bwuk","Flee from me, @name!","Begone, @name!","Bwaaaauuuk bwuk bwuk","MUAHAHAHAHAAA!") + var sentMessage = false override fun talkTo(npc: NPC) {} override fun init() { @@ -31,13 +34,17 @@ class EvilChickenNPC(override var loot: WeightBasedTable? = null) : RandomEventN } override fun tick() { - if(!player.location.withinDistance(this.location,8)){ - this.terminate() - } - if(getWorldTicks() % 10 == 0){ - sendChat(phrases.random().replace("@name",player.username.capitalize())) + if (!sentMessage) { + if (!player.location.withinDistance(this.location, 8)) { + // https://www.youtube.com/watch?v=v9p_I_Tq3JE + sendMessage(player, "The Evil Chicken realises you're out of range and vanishes.") + sentMessage = true + terminate() + } + if (getWorldTicks() % 10 == 0) { + sendChat(phrases.random().replace("@name", player.username.capitalize())) + } } super.tick() - if(!player.viewport.currentPlane.npcs.contains(this)) this.clear() } } diff --git a/Server/src/main/content/global/ame/events/maze/MazeInterface.kt b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt index c3c1ab7f4..5376e870c 100644 --- a/Server/src/main/content/global/ame/events/maze/MazeInterface.kt +++ b/Server/src/main/content/global/ame/events/maze/MazeInterface.kt @@ -15,6 +15,7 @@ import core.game.node.entity.player.Player import core.game.system.task.Pulse import core.game.world.GameWorld.Pulser import core.game.world.map.Location +import core.game.world.map.RegionManager import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneRestriction import core.game.world.update.flag.context.Graphics @@ -109,73 +110,17 @@ class MazeInterface : InteractionListener, EventHook, MapArea { addItemOrDrop(player, REWARD_ITEM[randomNumber], itemQuantity.toInt()) } } - - /** - * Chest Location to rotation mapping. - * This is needed as it is impossible to obtain the underlying chest scenery for the rotation. - * 0: Facing North, 1: Facing East, 2: Facing South, 3: Facing West - */ - val chestLocationRotationMap = mapOf( - Location(2930, 4595, 0).toString() to 2, - Location(2924, 4572, 0).toString() to 2, - Location(2925, 4573, 0).toString() to 0, - Location(2900, 4578, 0).toString() to 2, - Location(2901, 4560, 0).toString() to 1, - Location(2890, 4599, 0).toString() to 2, - Location(2896, 4591, 0).toString() to 2, - Location(2895, 4592, 0).toString() to 1, - Location(2901, 4560, 0).toString() to 3, - Location(2918, 4590, 0).toString() to 1, - Location(2917, 4590, 0).toString() to 3, - ) - - /** - * Chest Interaction workaround - * - * The issue here is that the walls(3626) of the Maze are overlapping some(not all) chest sceneries. - * - * The types for the wallScenery: - * Type 0 - flat panel | - * Type 2 - right angle panel with rotation 0:r 1:7 2:> 3:L - * Type 3 - corner post . for angle edges of walls - */ - fun overrideScenery(wallScenery: core.game.node.scenery.Scenery, chestSceneryId: Int): core.game.node.scenery.Scenery { - if (wallScenery.id == chestSceneryId) { - replaceScenery(wallScenery, Scenery.CHEST_3636, 30) - wallScenery.isActive = true - return wallScenery // Return the chest scenery as the wallScenery isn't there. - } - - addScenery(Scenery.CHEST_3636, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10) - addScenery(wallScenery) - // replaceScenery(newChestScenery, Scenery.CHEST_3636, 3) // didn't work for an underlying scenery - // I did a world pulse since everyone will get to see the chest open. - Pulser.submit(object : Pulse(30) { - override fun pulse(): Boolean { - addScenery(Scenery.CHEST_3635, wallScenery.location, chestLocationRotationMap[wallScenery.location.toString()] ?: 0, 10) - addScenery(wallScenery) - return true - } - }) - // Return the chest scenery to replace PacketProcessor so that MISMATCH will not happen. - return core.game.node.scenery.Scenery( - chestSceneryId, - wallScenery.location, - chestLocationRotationMap[wallScenery.location.toString()] ?: 0 - ) - } } override fun defineListeners() { - - // This somehow doesn't trigger as the scenery.id != objId (3626 != 3635) on(Scenery.CHEST_3635, IntType.SCENERY, "open") { player, node -> + lock(player, 3) + animate(player, 536) + replaceScenery(node.asScenery(), Scenery.CHEST_3636, 3) if (getAttribute(player, MAZE_ATTRIBUTE_TICKS_LEFT, 0) > 0 && getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0) < 10) { - animate(player, 536) - // val actualScenery = RegionManager.getObject(node.location.z, node.location.x, node.location.y, 3626) val tableRoll = CHEST_REWARDS.roll() addItemOrBank(player, tableRoll[0].id, tableRoll[0].amount) - when (tableRoll[0].id){ + when (tableRoll[0].id) { Items.AIR_RUNE_556 -> sendItemDialogue(player, Items.AIR_RUNE_556, "You've found some air runes!") Items.WATER_RUNE_555 -> sendItemDialogue(player, Items.WATER_RUNE_555, "You've found some water runes!") Items.EARTH_RUNE_557 -> sendItemDialogue(player, Items.EARTH_RUNE_557, "You've found some earth runes!") @@ -187,7 +132,7 @@ class MazeInterface : InteractionListener, EventHook, MapArea { Items.STRENGTH_POTION2_117 -> sendItemDialogue(player, Items.STRENGTH_POTION2_117, "You've found a strength potion!") Items.DEFENCE_POTION2_135 -> sendItemDialogue(player, Items.DEFENCE_POTION2_135, "You've found a defence potion!") } - setAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0)) + setAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, getAttribute(player, MAZE_ATTRIBUTE_CHESTS_OPEN, 0) + 1) } else { sendMessage(player,"You find nothing of interest.") } diff --git a/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt b/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt index dff28d7e9..50888b63e 100644 --- a/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt +++ b/Server/src/main/content/global/ame/events/rivertroll/RiverTrollRENPC.kt @@ -3,7 +3,9 @@ package content.global.ame.events.rivertroll import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC +import core.api.getWorldTicks import core.api.utils.WeightBasedTable +import core.game.world.map.MapDistance val ids = (391..396).toList() @@ -21,10 +23,12 @@ class RiverTrollRENPC(override var loot: WeightBasedTable? = null) : RandomEvent super.finalizeDeath(killer) } override fun tick() { - if(!player.location.withinDistance(this.location,8)){ + if (!player.location.withinDistance(this.location, 8)) { this.terminate() } super.tick() - if(!player.viewport.currentPlane.npcs.contains(this)) this.clear() + if (!player.location.withinDistance(this.location, MapDistance.RENDERING.distance)) { + this.clear() + } } } \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt b/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt index eb3399657..68bd92beb 100644 --- a/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt +++ b/Server/src/main/content/global/ame/events/rockgolem/RockGolemRENPC.kt @@ -3,7 +3,9 @@ package content.global.ame.events.rockgolem import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC +import core.api.getWorldTicks import core.api.utils.WeightBasedTable +import core.game.world.map.MapDistance val ids = (413..418).toList() @@ -21,10 +23,12 @@ class RockGolemRENPC(override var loot: WeightBasedTable? = null) : RandomEventN super.finalizeDeath(killer) } override fun tick() { - if(!player.location.withinDistance(this.location,8)){ + if (!player.location.withinDistance(this.location, 8)) { this.terminate() } super.tick() - if(!player.viewport.currentPlane.npcs.contains(this)) this.clear() + if (!player.location.withinDistance(this.location, MapDistance.RENDERING.distance)) { + this.clear() + } } } \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt b/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt index 60a0f57ae..14bcdd609 100644 --- a/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt +++ b/Server/src/main/content/global/ame/events/shade/ShadeRENPC.kt @@ -3,7 +3,9 @@ package content.global.ame.events.shade import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC +import core.api.getWorldTicks import core.api.utils.WeightBasedTable +import core.game.world.map.MapDistance class ShadeRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(425){ val ids = (425..430).toList() @@ -20,10 +22,12 @@ class ShadeRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(4 super.finalizeDeath(killer) } override fun tick() { - if(!player.location.withinDistance(this.location,8)){ + if (!player.location.withinDistance(this.location, 8)) { this.terminate() } super.tick() - if(!player.viewport.currentPlane.npcs.contains(this)) this.clear() + if (!player.location.withinDistance(this.location, MapDistance.RENDERING.distance)) { + this.clear() + } } } diff --git a/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt b/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt index 3b0033972..0bba8e2b5 100644 --- a/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt +++ b/Server/src/main/content/global/ame/events/treespirit/TreeSpiritRENPC.kt @@ -3,7 +3,9 @@ package content.global.ame.events.treespirit import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC +import core.api.getWorldTicks import core.api.utils.WeightBasedTable +import core.game.world.map.MapDistance val ids = (438..443).toList() @@ -21,10 +23,12 @@ class TreeSpiritRENPC(override var loot: WeightBasedTable? = null) : RandomEvent super.finalizeDeath(killer) } override fun tick() { - if(!player.location.withinDistance(this.location,8)){ + if (!player.location.withinDistance(this.location, 8)) { this.terminate() } super.tick() - if(!player.viewport.currentPlane.npcs.contains(this)) this.clear() + if (!player.location.withinDistance(this.location, MapDistance.RENDERING.distance)) { + this.clear() + } } } \ No newline at end of file diff --git a/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt b/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt index 6b43d54b4..ebe4465bc 100644 --- a/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt +++ b/Server/src/main/content/global/ame/events/zombie/ZombieRENPC.kt @@ -3,7 +3,9 @@ package content.global.ame.events.zombie import core.game.node.entity.Entity import core.game.node.entity.npc.NPC import content.global.ame.RandomEventNPC +import core.api.getWorldTicks import core.api.utils.WeightBasedTable +import core.game.world.map.MapDistance class ZombieRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(419){ val ids = (419..424).toList() @@ -20,10 +22,12 @@ class ZombieRENPC(override var loot: WeightBasedTable? = null) : RandomEventNPC( super.finalizeDeath(killer) } override fun tick() { - if(!player.location.withinDistance(this.location,8)){ + if (!player.location.withinDistance(this.location, 8)) { this.terminate() } super.tick() - if(!player.viewport.currentPlane.npcs.contains(this)) this.clear() + if (!player.location.withinDistance(this.location, MapDistance.RENDERING.distance)) { + this.clear() + } } } diff --git a/Server/src/main/content/global/bots/Adventurer.kt b/Server/src/main/content/global/bots/Adventurer.kt index 916503945..62464bbf2 100644 --- a/Server/src/main/content/global/bots/Adventurer.kt +++ b/Server/src/main/content/global/bots/Adventurer.kt @@ -21,6 +21,7 @@ import core.game.bots.CombatBotAssembler import core.game.bots.Script import core.game.interaction.IntType import core.game.interaction.InteractionListeners +import core.game.world.repository.Repository import core.tools.Log import java.io.File import java.io.FileReader @@ -114,7 +115,7 @@ class Adventurer(val style: CombatStyle): Script() { } private fun otherPlayersNearby(): Boolean { - val localPlayers = RegionManager.getLocalPlayers(bot) + val localPlayers = RegionManager.getLocalPlayers(bot.location) val otherPlayers = localPlayers.filter { it.name != bot.name } return otherPlayers.isNotEmpty() } @@ -503,7 +504,7 @@ class Adventurer(val style: CombatStyle): Script() { dateCode == 404 -> lineAlt = dialogue.getLines("easter").rand() } - var localPlayers = RegionManager.getLocalPlayers(bot) + val localPlayers = RegionManager.getLocalPlayers(bot.location) if (localPlayers.isNotEmpty()) { val localPlayer = localPlayers .filter { it.name != bot.name } diff --git a/Server/src/main/content/global/bots/CannonballSmelter.kt b/Server/src/main/content/global/bots/CannonballSmelter.kt index 8ac77f7e1..bc921111b 100644 --- a/Server/src/main/content/global/bots/CannonballSmelter.kt +++ b/Server/src/main/content/global/bots/CannonballSmelter.kt @@ -58,7 +58,7 @@ class CannonballSmelter : Script() { } else if(!coalMine.insideBorder(bot)){ scriptAPI.walkTo(coalMine.randomLoc) } else { - val rock = scriptAPI.getNearestObjectByPredicate({node -> node?.name?.equals("rocks", true)!! && MiningNode.forId(node?.id!!).reward == Items.COAL_453 }) + val rock = scriptAPI.getNearestObjectByPredicate({node -> node?.name?.equals("rocks", true)!! && MiningNode.forId(node.id)?.reward == Items.COAL_453 }) if(rock != null) { scriptAPI.interact(bot, rock, "mine") } else { @@ -75,7 +75,7 @@ class CannonballSmelter : Script() { var loc = ironMine.randomLoc scriptAPI.walkTo(loc) } else { - val rock = scriptAPI.getNearestObjectByPredicate({node -> node?.name?.equals("rocks", true)!! && MiningNode.forId(node?.id!!).reward == Items.IRON_ORE_440 }) + val rock = scriptAPI.getNearestObjectByPredicate({node -> node?.name?.equals("rocks", true)!! && MiningNode.forId(node.id)?.reward == Items.IRON_ORE_440 }) //rock?.let { InteractionListeners.run(rock.id, IntType.SCENERY,"mine",bot,rock) } if(rock != null) { scriptAPI.interact(bot, rock, "mine") diff --git a/Server/src/main/content/global/bots/DoublingMoney.kt b/Server/src/main/content/global/bots/DoublingMoney.kt index 785fd8690..8840191eb 100644 --- a/Server/src/main/content/global/bots/DoublingMoney.kt +++ b/Server/src/main/content/global/bots/DoublingMoney.kt @@ -22,6 +22,7 @@ import core.game.bots.Script import core.game.interaction.IntType import core.game.interaction.InteractionListeners import core.game.world.ImmerseWorld +import core.game.world.repository.Repository import java.io.File import java.io.FileReader import java.util.Random @@ -262,10 +263,12 @@ class DoublingMoney : Script() { minDist = min(minDist, loc.getDistance(bot.location)) } if (minDist > 1) return 2 - RegionManager.forId(bot.location.regionId).planes[bot.location.z].players.forEach { - if (AIRepository.PulseRepository[it?.username?.lowercase()]?.botScript is DoublingMoney - && it != bot - && it.location.getDistance(bot.location) <= 1) { + val region = RegionManager.forId(bot.location.regionId) + val players = region.assemblePlayerList(bot.location.z) + for (player in players) { + if (AIRepository.PulseRepository[player.username.lowercase()]?.botScript is DoublingMoney + && player != bot + && player.location.getDistance(bot.location) <= 1) { return 2 } } diff --git a/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java index b3e276dcd..08b180396 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/ChainhitSpecialHandler.java @@ -79,7 +79,7 @@ public final class ChainhitSpecialHandler extends RangeSwingHandler implements P if (!((Player) entity).getSettings().drainSpecial(SPECIAL_ENERGY)) { return -1; } - state.setStyle(CombatStyle.RANGE); + state.setStyle(CombatStyle.RANGE); if (victim instanceof NPC) { NPC npc = victim.asNpc(); if (npc.getId() == 2440) { @@ -186,9 +186,9 @@ public final class ChainhitSpecialHandler extends RangeSwingHandler implements P if (list == null) { int distance = 5; if (victim instanceof NPC) { - e.setAttribute("chain-hit_v", list = RegionManager.getLocalNpcs(e, distance)); + e.setAttribute("chain-hit_v", list = RegionManager.getLocalNPCs(e.getLocation(), distance)); } else { - e.setAttribute("chain-hit_v", list = RegionManager.getLocalPlayers(e, distance)); + e.setAttribute("chain-hit_v", list = RegionManager.getLocalPlayers(e.getLocation(), distance)); } list.remove(e); list.remove(victim); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java index a0801835e..0523f8753 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/ChinchompaSwingHandler.java @@ -13,7 +13,6 @@ import core.game.world.map.RegionManager; import core.game.world.update.flag.context.Graphics; import core.tools.RandomFunction; -import java.util.ArrayList; import java.util.List; /** @@ -56,14 +55,18 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler { return -1; } - // ! Initial capacity of 14, but has dynamic size? i.e. we are not restricting to a max of 14 targets hit here now - List targetCandidates = new ArrayList<>(14); - targetCandidates.addAll(RegionManager.getSurroundingNPCs(victim, 14, entity)); - targetCandidates.addAll(RegionManager.getSurroundingPlayers(victim, 14, entity)); + // https://oldschool.runescape.wiki/w/Chinchompa - shit source but it's better than what was here before + @SuppressWarnings("rawtypes") List targetCandidates; + if (victim instanceof Player) { + targetCandidates = RegionManager.getSurroundingPlayers(victim, 9); + } else { + targetCandidates = RegionManager.getSurroundingNPCs(victim, 11); + } BattleState[] targets = new BattleState[targetCandidates.size()]; int count = 0; - for (Entity e : targetCandidates) { - if (canSwing(entity, e) != InteractionType.NO_INTERACT && e.isAttackable(entity, CombatStyle.RANGE, false)) { + for (Object o : targetCandidates) { + Entity e = (Entity) o; + if (e != entity && canSwing(entity, e) != InteractionType.NO_INTERACT && e.isAttackable(entity, CombatStyle.RANGE, false)) { BattleState s = targets[count++] = new BattleState(entity, e); s.setStyle(CombatStyle.RANGE); int hit = 0; diff --git a/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java index ba3ff8ed0..0b09a3c2c 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/PowerstabSpecialHandler.java @@ -76,12 +76,12 @@ public final class PowerstabSpecialHandler extends MeleeSwingHandler implements return super.swing(entity, victim, state); } @SuppressWarnings("rawtypes") - List list = victim instanceof NPC ? RegionManager.getSurroundingNPCs(entity, 9, entity) : RegionManager.getSurroundingPlayers(entity, 9, entity); + List list = victim instanceof NPC ? RegionManager.getSurroundingNPCs(entity, 9) : RegionManager.getSurroundingPlayers(entity, 9); BattleState[] targets = new BattleState[list.size()]; int count = 0; for (Object o : list) { Entity e = (Entity) o; - if (CombatStyle.RANGE.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT && e.isAttackable(entity, CombatStyle.RANGE, false)) { + if (e != entity && CombatStyle.RANGE.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT && e.isAttackable(entity, CombatStyle.RANGE, false)) { BattleState s = targets[count++] = new BattleState(entity, e); int hit = 0; if (isAccurateImpact(entity, e)) { diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java index 2595b0479..4ae69ddc2 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SpearWallSpecialHandler.java @@ -77,12 +77,12 @@ public final class SpearWallSpecialHandler extends MeleeSwingHandler implements return super.swing(entity, victim, state); } @SuppressWarnings("rawtypes") - List list = victim instanceof NPC ? RegionManager.getSurroundingNPCs(entity, 9, entity) : RegionManager.getSurroundingPlayers(entity, 9, entity); + List list = victim instanceof NPC ? RegionManager.getSurroundingNPCs(entity, 9) : RegionManager.getSurroundingPlayers(entity, 9); BattleState[] targets = new BattleState[list.size()]; int count = 0; for (Object o : list) { Entity e = (Entity) o; - if (CombatStyle.RANGE.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT && e.isAttackable(entity, CombatStyle.RANGE, false)) { + if (e != entity && CombatStyle.RANGE.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT && e.isAttackable(entity, CombatStyle.RANGE, false)) { BattleState s = targets[count++] = new BattleState(entity, e); int hit = 0; hit = RandomFunction.random(calculateHit(entity, e, 1.0) + 1); diff --git a/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java b/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java index 6c4b9cedc..c51e3532e 100644 --- a/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java +++ b/Server/src/main/content/global/handlers/item/equipment/special/SweepSpecialHandler.java @@ -2,7 +2,9 @@ package content.global.handlers.item.equipment.special; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; +import core.game.world.repository.Repository; import core.plugin.Initializable; import content.global.skill.summoning.familiar.Familiar; import core.game.node.entity.Entity; @@ -98,7 +100,10 @@ public final class SweepSpecialHandler extends MeleeSwingHandler implements Plug Direction dir = Direction.getDirection(x - entity.getLocation().getX(), y - entity.getLocation().getY()); List l = new ArrayList<>(20); l.add(new BattleState(entity, victim)); - for (Entity n : victim instanceof NPC ? RegionManager.getSurroundingNPCs(victim, 9, entity, victim) : RegionManager.getSurroundingPlayers(victim, 9, entity, victim)) { + for (Entity n : victim instanceof NPC ? RegionManager.getSurroundingNPCs(victim, 9) : RegionManager.getSurroundingPlayers(victim, 9)) { + if (n == entity) { + continue; + } if (n instanceof Familiar) { continue; } diff --git a/Server/src/main/content/global/handlers/item/withitem/SoftclayPlugin.java b/Server/src/main/content/global/handlers/item/withitem/SoftclayPlugin.java index 37ff46584..fc63daa34 100644 --- a/Server/src/main/content/global/handlers/item/withitem/SoftclayPlugin.java +++ b/Server/src/main/content/global/handlers/item/withitem/SoftclayPlugin.java @@ -21,47 +21,47 @@ import java.util.Objects; @Initializable public final class SoftclayPlugin extends UseWithHandler { - /** - * Represents the clay item. - */ - private static final Item CLAY = new Item(Items.CLAY_434); + /** + * Represents the clay item. + */ + private static final Item CLAY = new Item(Items.CLAY_434); - /** - * Represents the soft clay item. - */ - private static final Item SOFT_CLAY = new Item(Items.SOFT_CLAY_1761); + /** + * Represents the soft clay item. + */ + private static final Item SOFT_CLAY = new Item(Items.SOFT_CLAY_1761); - /** - * Represents the bowl of water item. - */ - private static final Item BOWL_OF_WATER = new Item(Items.BOWL_OF_WATER_1921); + /** + * Represents the bowl of water item. + */ + private static final Item BOWL_OF_WATER = new Item(Items.BOWL_OF_WATER_1921); - /** - * Represents the empty bowl item. - */ - private static final Item BOWL = new Item(Items.BOWL_1923); + /** + * Represents the empty bowl item. + */ + private static final Item BOWL = new Item(Items.BOWL_1923); - /** - * Represents the empty bucket item. - */ - private static final Item BUCKET = new Item(Items.BUCKET_1925); + /** + * Represents the empty bucket item. + */ + private static final Item BUCKET = new Item(Items.BUCKET_1925); /** * Represents the bucket of water item. */ private static final Item BUCKET_OF_WATER = new Item(Items.BUCKET_OF_WATER_1929); - /** - * Represents the jug item. - */ - private static final Item JUG = new Item(Items.JUG_1935); + /** + * Represents the jug item. + */ + private static final Item JUG = new Item(Items.JUG_1935); /** * Represents the jug of water item. */ private static final Item JUG_OF_WATER = new Item(Items.JUG_OF_WATER_1937); - /** + /** * Constructs a new {@code SoftclayPlugin} {@code Object}. */ public SoftclayPlugin() { @@ -70,7 +70,7 @@ public final class SoftclayPlugin extends UseWithHandler { @Override public Plugin newInstance(Object arg) throws Throwable { - addHandler(1921, ITEM_TYPE, this); + addHandler(1921, ITEM_TYPE, this); addHandler(1929, ITEM_TYPE, this); addHandler(1937, ITEM_TYPE, this); return this; @@ -115,33 +115,33 @@ public final class SoftclayPlugin extends UseWithHandler { * @return {@code True} if so. */ private boolean create(final Player player, NodeUsageEvent event) { - Item removeItem = null; - Item returnItem = null; - if (event.getUsedItem().getId() == Items.BUCKET_OF_WATER_1929 || event.getBaseItem().getId() == Items.BUCKET_OF_WATER_1929) { - removeItem = BUCKET_OF_WATER; - returnItem = BUCKET; - } - if (event.getUsedItem().getId() == Items.BOWL_OF_WATER_1921 || event.getBaseItem().getId() == Items.BOWL_OF_WATER_1921) { - removeItem = BOWL_OF_WATER; - returnItem = BOWL; - } - if (event.getUsedItem().getId() == Items.JUG_OF_WATER_1937 || event.getBaseItem().getId() == Items.JUG_OF_WATER_1937) { - removeItem = JUG_OF_WATER; - returnItem = JUG; - } + Item removeItem = null; + Item returnItem = null; + if (event.getUsedItem().getId() == Items.BUCKET_OF_WATER_1929 || event.getBaseItem().getId() == Items.BUCKET_OF_WATER_1929) { + removeItem = BUCKET_OF_WATER; + returnItem = BUCKET; + } + if (event.getUsedItem().getId() == Items.BOWL_OF_WATER_1921 || event.getBaseItem().getId() == Items.BOWL_OF_WATER_1921) { + removeItem = BOWL_OF_WATER; + returnItem = BOWL; + } + if (event.getUsedItem().getId() == Items.JUG_OF_WATER_1937 || event.getBaseItem().getId() == Items.JUG_OF_WATER_1937) { + removeItem = JUG_OF_WATER; + returnItem = JUG; + } if (player.getInventory().containsItem(CLAY) && player.getInventory().containsItem(Objects.requireNonNull(removeItem))) { - player.getInventory().remove(removeItem); - player.getInventory().remove(CLAY); - player.getPacketDispatch().sendMessage("You mix the clay and water. You now have some soft, workable clay."); - player.getInventory().add(SOFT_CLAY); - player.getInventory().add(returnItem); - if (!player.getAchievementDiaryManager().hasCompletedTask(DiaryType.LUMBRIDGE, 0, 6) && player.getViewport().getRegion().getId() == 12341) { - player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 6); - } + player.getInventory().remove(removeItem); + player.getInventory().remove(CLAY); + player.getPacketDispatch().sendMessage("You mix the clay and water. You now have some soft, workable clay."); + player.getInventory().add(SOFT_CLAY); + player.getInventory().add(returnItem); + if (!player.getAchievementDiaryManager().hasCompletedTask(DiaryType.LUMBRIDGE, 0, 6) && player.getLocation().getRegionId() == 12341) { + player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 6); + } return true; } else { - return false; - } + return false; + } } } diff --git a/Server/src/main/content/global/handlers/item/withobject/WaterSourceListener.kt b/Server/src/main/content/global/handlers/item/withobject/WaterSourceListener.kt index 75652b75d..dfa302014 100644 --- a/Server/src/main/content/global/handlers/item/withobject/WaterSourceListener.kt +++ b/Server/src/main/content/global/handlers/item/withobject/WaterSourceListener.kt @@ -15,30 +15,19 @@ import org.rs09.consts.Sounds * @author Ceikry */ class WaterSourceListener : InteractionListener { - // NOTE '9695' should be removed from the array below once the sink object can be used directly, this is a temporary - // solution. - // this is ugly! - private val waterSources = intArrayOf(21355, 16302, 6827, 11661, 24160, 34577, 15936, 15937, 15938, 23920, 35469, 24265, 153, 879, 880, 2864, 6232, 10436, 10437, 10827, 11007, 11759, 21764, 22973, 24161, 24214, 24265, 28662, 30223, 30820, 34579, 36781, 873, 874, 4063, 6151, 8699, 9143, 9684, 9695, 10175, 12279, 12974, 13563, 13564, 14868, 14917, 14918, 15678, 16704, 16705, 20358, 22715, 24112, 24314, 25729, 25929, 26966, 29105, 33458, 34082, 34411, 34496, 34547, 34566, 35762, 36971, 37154, 37155, 878, 884, 3264, 3305, 3359, 4004, 4005, 6097, 6249, 6549, 8747, 8927, 11793, 12201, 12897, 24166, 26945, 31359, 32023, 32024, 34576, 35671, 40063, 13561, 13563, 13559, 12089) + private val waterSources = intArrayOf(21355, 16302, 6827, 11661, 24160, 34577, 15936, 15937, 15938, 23920, 35469, 24265, 153, 879, 880, 2864, 6232, 10436, 10437, 10827, 11007, 11759, 21764, 22973, 24161, 24214, 24265, 28662, 30223, 30820, 34579, 36781, 873, 874, 4063, 6151, 8699, 9143, 9684, 10175, 12279, 12974, 13563, 13564, 14868, 14917, 14918, 15678, 16704, 16705, 20358, 22715, 24112, 24314, 25729, 25929, 26966, 29105, 33458, 34082, 34411, 34496, 34547, 34566, 35762, 36971, 37154, 37155, 878, 884, 3264, 3305, 3359, 4004, 4005, 6097, 6249, 6549, 8747, 8927, 11793, 12201, 12897, 24166, 26945, 31359, 32023, 32024, 34576, 35671, 40063, 13561, 13563, 13559, 12089) private val nonWellableMsg = "If I drop my @ down there, I don't think I'm likely to get it back." private val animation = Animation(832) - override fun defineListeners() - { + override fun defineListeners() { onUseWith(IntType.SCENERY, WaterVessel.getInputs(), *waterSources){ player, used, with -> val vessel = WaterVessel.forId(used.id) ?: return@onUseWith false - if(with.name.contains("well", ignoreCase = true) && !vessel.wellable) { sendMessage(player, formatMsgText(used.name, nonWellableMsg)) return@onUseWith true } - - if(with.id == 9695 && player.location.regionId != 11571) - { - return@onUseWith false - } - //ugly achievement code, achievement system sux if(vessel == WaterVessel.BUCKET && with.id == 11661) { @@ -67,15 +56,6 @@ class WaterSourceListener : InteractionListener { return@onUseWith true } - - // This is needed to make the crafting guild sink work, but technically it's wrong as it is the noticeboard and - // not the sink being used. This is a temporary solution until the sink object can be used directly. - setDest(IntType.SCENERY, intArrayOf(9695), "use") { player, node -> - if (player.location.regionId == 11571){ - return@setDest Location.create(2934, 3280, 0) - } - return@setDest node.location - } } private fun formatMsgText(name: String, template: String): String diff --git a/Server/src/main/content/global/handlers/scenery/TableListener.kt b/Server/src/main/content/global/handlers/scenery/TableListener.kt index c35ebd27b..c89c6262b 100644 --- a/Server/src/main/content/global/handlers/scenery/TableListener.kt +++ b/Server/src/main/content/global/handlers/scenery/TableListener.kt @@ -413,7 +413,7 @@ class TableListener : InteractionListener { } val droppedItem = used.dropItem if (droppedItem.id == Items.COINS_995) playAudio(player, DROP_COINS_SOUND) else playAudio(player, DROP_ITEM_SOUND) - GroundItemManager.create(droppedItem, Location(nearestX, nearestY), player) + GroundItemManager.create(droppedItem, Location(nearestX, nearestY, player.location.z), player) setAttribute(player, "droppedItem:${droppedItem.id}", getWorldTicks() + 2) PlayerParser.save(player) diff --git a/Server/src/main/content/global/skill/agility/brimhaven/BrimhavenArena.java b/Server/src/main/content/global/skill/agility/brimhaven/BrimhavenArena.java index 13a6a4ad6..c046d73f7 100644 --- a/Server/src/main/content/global/skill/agility/brimhaven/BrimhavenArena.java +++ b/Server/src/main/content/global/skill/agility/brimhaven/BrimhavenArena.java @@ -19,6 +19,7 @@ import core.game.world.GameWorld; import core.game.world.map.*; import core.game.world.map.zone.MapZone; import core.game.world.map.zone.ZoneBuilder; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; @@ -37,300 +38,302 @@ import static core.api.ContentAPIKt.*; @Initializable public final class BrimhavenArena extends MapZone implements Plugin { - /** - * The location based traps. - */ - private static final Map LOCATION_TRAPS = new HashMap<>(); + /** + * The location based traps. + */ + private static final Map LOCATION_TRAPS = new HashMap<>(); - /** - * The overlay component. - */ - private static final Component OVERLAY = new Component(5); + /** + * The overlay component. + */ + private static final Component OVERLAY = new Component(5); - /** - * The ticket dispenser locations. - */ - private static final Location[] DISPENSERS = new Location[24]; + /** + * The ticket dispenser locations. + */ + private static final Location[] DISPENSERS = new Location[24]; - /** - * The agility ticket reward item. - */ - private static final Item TICKET = new Item(2996); + /** + * The agility ticket reward item. + */ + private static final Item TICKET = new Item(2996); - /** - * If the saw blade is currently active. - */ - public static boolean sawBladeActive; + /** + * If the saw blade is currently active. + */ + public static boolean sawBladeActive; - /** - * Constructs a new {@code BrimhavenArena} {@code Object}. - */ - public BrimhavenArena() { - super("Brimhaven agility arena", true); - } + /** + * Constructs a new {@code BrimhavenArena} {@code Object}. + */ + public BrimhavenArena() { + super("Brimhaven agility arena", true); + } - /** - * Sets the current ticket dispenser target. - * - * @param player The player. - */ - private void setDispenser(Player player) { - if (!player.getAttribute("brim-tagged", false)) { - player.setAttribute("brim-tagcount", 0); - } - player.setAttribute("brim-tagged", false); - setVarp(player, 309, 0); - int index = RandomFunction.randomize(DISPENSERS.length); - if (index == player.getAttribute("brim-tag", -1)) { - index = (index + 1) % DISPENSERS.length; - } - int iconSlot = player.getAttribute("brim-icon", -1); - if (iconSlot > -1) { - HintIconManager.removeHintIcon(player, iconSlot); - } - player.setAttribute("brim-tag", index); - player.setAttribute("brim-icon", HintIconManager.registerHeightHintIcon(player, DISPENSERS[index], 50)); - } + /** + * Sets the current ticket dispenser target. + * + * @param player The player. + */ + private void setDispenser(Player player) { + if (!player.getAttribute("brim-tagged", false)) { + player.setAttribute("brim-tagcount", 0); + } + player.setAttribute("brim-tagged", false); + setVarp(player, 309, 0); + int index = RandomFunction.randomize(DISPENSERS.length); + if (index == player.getAttribute("brim-tag", -1)) { + index = (index + 1) % DISPENSERS.length; + } + int iconSlot = player.getAttribute("brim-icon", -1); + if (iconSlot > -1) { + HintIconManager.removeHintIcon(player, iconSlot); + } + player.setAttribute("brim-tag", index); + player.setAttribute("brim-icon", HintIconManager.registerHeightHintIcon(player, DISPENSERS[index], 50)); + } - @Override - public boolean enter(Entity entity) { - if (entity instanceof Player) { - Player player = (Player) entity; - player.getInterfaceManager().openOverlay(OVERLAY); - setDispenser(player); - } - return super.enter(entity); - } + @Override + public boolean enter(Entity entity) { + if (entity instanceof Player) { + Player player = (Player) entity; + player.getInterfaceManager().openOverlay(OVERLAY); + setDispenser(player); + } + return super.enter(entity); + } - @Override - public boolean leave(Entity entity, boolean logout) { - if (entity instanceof Player && !logout) { - Player player = (Player) entity; - player.getInterfaceManager().closeOverlay(); - player.removeAttribute("brim-tag"); - player.removeAttribute("brim-tagcount"); - int iconSlot = player.getAttribute("brim-icon", -1); - if (iconSlot > -1) { - HintIconManager.removeHintIcon(player, iconSlot); - player.removeAttribute("brim-icon"); - } - } - return super.enter(entity); - } + @Override + public boolean leave(Entity entity, boolean logout) { + if (entity instanceof Player && !logout) { + Player player = (Player) entity; + player.getInterfaceManager().closeOverlay(); + player.removeAttribute("brim-tag"); + player.removeAttribute("brim-tagcount"); + int iconSlot = player.getAttribute("brim-icon", -1); + if (iconSlot > -1) { + HintIconManager.removeHintIcon(player, iconSlot); + player.removeAttribute("brim-icon"); + } + } + return super.enter(entity); + } - @Override - public boolean interact(Entity entity, Node node, Option option) { - if (node instanceof Scenery) { - Scenery object = (Scenery) node; - if (object.getId() == 3610) { - ClimbActionHandler.climb((Player) entity, Animation.create(828), object.getLocation().transform(0, 0, 3)); - return true; - } - if (object.getId() == 3608 || object.getId() == 3581) { - Player player = (Player) entity; - if (!object.getLocation().equals(DISPENSERS[player.getAttribute("brim-tag", 0)])) { - player.getPacketDispatch().sendMessage("Tag the pillar indicated by the yellow arrow to get an Agility ticket."); - return true; - } - if (player.getAttribute("brim-tagged", false)) { - player.getPacketDispatch().sendMessage("You have already tagged this pillar."); - return true; - } - player.setAttribute("brim-tagged", true); - int tags = player.getAttribute("brim-tagcount", 0) + 1; - player.setAttribute("brim-tagcount", tags); - setVarp(player, 309, 4); - if (tags > 1) { - int amount = 1; - if (!player.getInventory().add(new Item(TICKET.getId(), amount))) { - GroundItemManager.create(new GroundItem(new Item(TICKET.getId(), amount), player.getLocation(), player)); - } - player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 1, 0); - player.getDialogueInterpreter().sendItemMessage(TICKET.getId(), "You have received an Agility Arena Ticket!"); - player.getPacketDispatch().sendMessage("You have received an Agility Arena Ticket!"); - return true; - } - player.getPacketDispatch().sendMessage("You get tickets by tagging more than one pillar in a row, tag the next pillar!"); - player.getDialogueInterpreter().sendDialogue("You get tickets by tagging more than one pillar in a row. Tag the", "next pillar for a ticket!"); - return true; - } - } - return false; - } + @Override + public boolean interact(Entity entity, Node node, Option option) { + if (node instanceof Scenery) { + Scenery object = (Scenery) node; + if (object.getId() == 3610) { + ClimbActionHandler.climb((Player) entity, Animation.create(828), object.getLocation().transform(0, 0, 3)); + return true; + } + if (object.getId() == 3608 || object.getId() == 3581) { + Player player = (Player) entity; + if (!object.getLocation().equals(DISPENSERS[player.getAttribute("brim-tag", 0)])) { + player.getPacketDispatch().sendMessage("Tag the pillar indicated by the yellow arrow to get an Agility ticket."); + return true; + } + if (player.getAttribute("brim-tagged", false)) { + player.getPacketDispatch().sendMessage("You have already tagged this pillar."); + return true; + } + player.setAttribute("brim-tagged", true); + int tags = player.getAttribute("brim-tagcount", 0) + 1; + player.setAttribute("brim-tagcount", tags); + setVarp(player, 309, 4); + if (tags > 1) { + int amount = 1; + if (!player.getInventory().add(new Item(TICKET.getId(), amount))) { + GroundItemManager.create(new GroundItem(new Item(TICKET.getId(), amount), player.getLocation(), player)); + } + player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 1, 0); + player.getDialogueInterpreter().sendItemMessage(TICKET.getId(), "You have received an Agility Arena Ticket!"); + player.getPacketDispatch().sendMessage("You have received an Agility Arena Ticket!"); + return true; + } + player.getPacketDispatch().sendMessage("You get tickets by tagging more than one pillar in a row, tag the next pillar!"); + player.getDialogueInterpreter().sendDialogue("You get tickets by tagging more than one pillar in a row. Tag the", "next pillar for a ticket!"); + return true; + } + } + return false; + } - @Override - public boolean move(Entity e, Location loc, Location dest) { - if (!e.getLocks().isMovementLocked() && e instanceof Player) { - MovementHook hook = LOCATION_TRAPS.get(loc); - if (hook != null) { - e.setDirection(Direction.getLogicalDirection(loc, dest)); - return hook.handle(e, loc); - } - } - return super.move(e, loc, dest); - } + @Override + public boolean move(Entity e, Location loc, Location dest) { + if (!e.getLocks().isMovementLocked() && e instanceof Player) { + MovementHook hook = LOCATION_TRAPS.get(loc); + if (hook != null) { + e.setDirection(Direction.getLogicalDirection(loc, dest)); + return hook.handle(e, loc); + } + } + return super.move(e, loc, dest); + } - @Override - public void locationUpdate(Entity e, Location last) { - if (!e.getLocks().isMovementLocked() && e instanceof Player) { - MovementHook hook = LOCATION_TRAPS.get(e.getLocation()); - if (hook != null) { - if (!hook.handle(e, e.getLocation())) { - if (e.getPulseManager().isMovingPulse()) { - e.getPulseManager().clear(); - } - e.getWalkingQueue().reset(); - } - } - } - } + @Override + public void locationUpdate(Entity e, Location last) { + if (!e.getLocks().isMovementLocked() && e instanceof Player) { + MovementHook hook = LOCATION_TRAPS.get(e.getLocation()); + if (hook != null) { + if (!hook.handle(e, e.getLocation())) { + if (e.getPulseManager().isMovingPulse()) { + e.getPulseManager().clear(); + } + e.getWalkingQueue().reset(); + } + } + } + } - @Override - public void configure() { - registerRegion(11157); - PressurePad pad = new PressurePad(); - LOCATION_TRAPS.put(Location.create(2800, 9579, 3), pad); - LOCATION_TRAPS.put(Location.create(2799, 9579, 3), pad); - LOCATION_TRAPS.put(Location.create(2800, 9557, 3), pad); - LOCATION_TRAPS.put(Location.create(2799, 9557, 3), pad); - LOCATION_TRAPS.put(Location.create(2772, 9585, 3), pad); - LOCATION_TRAPS.put(Location.create(2772, 9584, 3), pad); - FloorSpikes spikes = new FloorSpikes(); - LOCATION_TRAPS.put(Location.create(2800, 9568, 3), spikes); - LOCATION_TRAPS.put(Location.create(2799, 9568, 3), spikes); - LOCATION_TRAPS.put(Location.create(2772, 9552, 3), spikes); - LOCATION_TRAPS.put(Location.create(2772, 9551, 3), spikes); - LOCATION_TRAPS.put(Location.create(2761, 9573, 3), spikes); - LOCATION_TRAPS.put(Location.create(2761, 9574, 3), spikes); - DartTrap dart = new DartTrap(); - LOCATION_TRAPS.put(Location.create(2788, 9557, 3), dart); - LOCATION_TRAPS.put(Location.create(2789, 9557, 3), dart); - LOCATION_TRAPS.put(Location.create(2794, 9573, 3), dart); - LOCATION_TRAPS.put(Location.create(2794, 9574, 3), dart); - LOCATION_TRAPS.put(Location.create(2777, 9568, 3), dart); - LOCATION_TRAPS.put(Location.create(2778, 9568, 3), dart); - SpinningBlades blade = new SpinningBlades(); - LOCATION_TRAPS.put(Location.create(2778, 9579, 3), blade); - LOCATION_TRAPS.put(Location.create(2783, 9574, 3), blade); - LOCATION_TRAPS.put(Location.create(2778, 9557, 3), blade); - BladeTrap trap = new BladeTrap(); - LOCATION_TRAPS.put(Location.create(2788, 9579, 3), trap); - LOCATION_TRAPS.put(Location.create(2789, 9579, 3), trap); - LOCATION_TRAPS.put(Location.create(2783, 9551, 3), trap); - LOCATION_TRAPS.put(Location.create(2783, 9552, 3), trap); - LOCATION_TRAPS.put(Location.create(2761, 9584, 3), trap); - LOCATION_TRAPS.put(Location.create(2761, 9585, 3), trap); - int index = 0; - for (int x = 2761; x < 2815; x += 11) { - for (int y = 9546; y < 9600; y += 11) { - if (x == 2805 && y == 9590) { - continue; - } - DISPENSERS[index++] = Location.create(x, y, 3); - } - } + @Override + public void configure() { + registerRegion(11157); + PressurePad pad = new PressurePad(); + LOCATION_TRAPS.put(Location.create(2800, 9579, 3), pad); + LOCATION_TRAPS.put(Location.create(2799, 9579, 3), pad); + LOCATION_TRAPS.put(Location.create(2800, 9557, 3), pad); + LOCATION_TRAPS.put(Location.create(2799, 9557, 3), pad); + LOCATION_TRAPS.put(Location.create(2772, 9585, 3), pad); + LOCATION_TRAPS.put(Location.create(2772, 9584, 3), pad); + FloorSpikes spikes = new FloorSpikes(); + LOCATION_TRAPS.put(Location.create(2800, 9568, 3), spikes); + LOCATION_TRAPS.put(Location.create(2799, 9568, 3), spikes); + LOCATION_TRAPS.put(Location.create(2772, 9552, 3), spikes); + LOCATION_TRAPS.put(Location.create(2772, 9551, 3), spikes); + LOCATION_TRAPS.put(Location.create(2761, 9573, 3), spikes); + LOCATION_TRAPS.put(Location.create(2761, 9574, 3), spikes); + DartTrap dart = new DartTrap(); + LOCATION_TRAPS.put(Location.create(2788, 9557, 3), dart); + LOCATION_TRAPS.put(Location.create(2789, 9557, 3), dart); + LOCATION_TRAPS.put(Location.create(2794, 9573, 3), dart); + LOCATION_TRAPS.put(Location.create(2794, 9574, 3), dart); + LOCATION_TRAPS.put(Location.create(2777, 9568, 3), dart); + LOCATION_TRAPS.put(Location.create(2778, 9568, 3), dart); + SpinningBlades blade = new SpinningBlades(); + LOCATION_TRAPS.put(Location.create(2778, 9579, 3), blade); + LOCATION_TRAPS.put(Location.create(2783, 9574, 3), blade); + LOCATION_TRAPS.put(Location.create(2778, 9557, 3), blade); + BladeTrap trap = new BladeTrap(); + LOCATION_TRAPS.put(Location.create(2788, 9579, 3), trap); + LOCATION_TRAPS.put(Location.create(2789, 9579, 3), trap); + LOCATION_TRAPS.put(Location.create(2783, 9551, 3), trap); + LOCATION_TRAPS.put(Location.create(2783, 9552, 3), trap); + LOCATION_TRAPS.put(Location.create(2761, 9584, 3), trap); + LOCATION_TRAPS.put(Location.create(2761, 9585, 3), trap); + int index = 0; + for (int x = 2761; x < 2815; x += 11) { + for (int y = 9546; y < 9600; y += 11) { + if (x == 2805 && y == 9590) { + continue; + } + DISPENSERS[index++] = Location.create(x, y, 3); + } + } GameWorld.getPulser().submit(new Pulse(1) { - @Override - public boolean pulse() { - Region r = RegionManager.forId(11157); - if (!r.isActive()) { - return false; - } - if (GameWorld.getTicks() % 100 == 0) { - for (RegionPlane plane : r.getPlanes()) { - for (Player player : plane.getPlayers()) { - setDispenser(player); - } - } - handlePlankSwitching(); - } - int ticks = 3; - if (GameWorld.getTicks() % ticks == 0) { - sawBladeActive = !sawBladeActive; - if (sawBladeActive) { - Scenery object = RegionManager.getObject(3, 2788, 9579); - SceneryBuilder.replace(object, object.transform(3567, object.getRotation(), 10), ticks); - object = RegionManager.getObject(3, 2789, 9579); - SceneryBuilder.replace(object, object.transform(0), ticks); + @Override + public boolean pulse() { + Region r = RegionManager.forId(11157); + if (!r.isActive()) { + return false; + } + if (GameWorld.getTicks() % 100 == 0) { + for (int z = 0; z < 4; z++) { + for (Player player : r.assemblePlayerList(z)) { + if (player != null) { + setDispenser(player); + } + } + } + handlePlankSwitching(); + } + int ticks = 3; + if (GameWorld.getTicks() % ticks == 0) { + sawBladeActive = !sawBladeActive; + if (sawBladeActive) { + Scenery object = RegionManager.getObject(3, 2788, 9579); + SceneryBuilder.replace(object, object.transform(3567, object.getRotation(), 10), ticks); + object = RegionManager.getObject(3, 2789, 9579); + SceneryBuilder.replace(object, object.transform(0), ticks); - object = RegionManager.getObject(3, 2783, 9551); - SceneryBuilder.replace(object, object.transform(3567, object.getRotation(), 10), ticks); - object = RegionManager.getObject(3, 2783, 9552); - SceneryBuilder.replace(object, object.transform(0), ticks); + object = RegionManager.getObject(3, 2783, 9551); + SceneryBuilder.replace(object, object.transform(3567, object.getRotation(), 10), ticks); + object = RegionManager.getObject(3, 2783, 9552); + SceneryBuilder.replace(object, object.transform(0), ticks); - object = RegionManager.getObject(3, 2761, 9584); - SceneryBuilder.replace(object, object.transform(3567, object.getRotation(), 10), ticks); - object = RegionManager.getObject(3, 2761, 9585); - SceneryBuilder.replace(object, object.transform(0), ticks); - } - } - return false; - } - }); - } + object = RegionManager.getObject(3, 2761, 9584); + SceneryBuilder.replace(object, object.transform(3567, object.getRotation(), 10), ticks); + object = RegionManager.getObject(3, 2761, 9585); + SceneryBuilder.replace(object, object.transform(0), ticks); + } + } + return false; + } + }); + } - /** - * Switches the plank states. - */ - private static void handlePlankSwitching() { - boolean[] available = new boolean[3]; - for (int i = 0; i < 1 + RandomFunction.randomize(2); i++) { - available[RandomFunction.randomize(3)] = true; - } - for (int i = 0; i < 3; i++) { - boolean avail = available[i]; - for (PlankSet set : PlankSet.values()) { - Location l = set.entrance[i]; - for (int x = 1; x < set.exit[i].getX() - l.getX(); x++) { - Scenery object = RegionManager.getObject(l.transform(x, 0, 0)); - if(object != null) - SceneryBuilder.replace(object, object.transform(avail ? 3573 : 3576)); - } - RegionManager.getObject(set.entrance[i]).setCharge(avail ? 1000 : 500); - RegionManager.getObject(set.exit[i]).setCharge(avail ? 1000 : 500); - } - } - } + /** + * Switches the plank states. + */ + private static void handlePlankSwitching() { + boolean[] available = new boolean[3]; + for (int i = 0; i < 1 + RandomFunction.randomize(2); i++) { + available[RandomFunction.randomize(3)] = true; + } + for (int i = 0; i < 3; i++) { + boolean avail = available[i]; + for (PlankSet set : PlankSet.values()) { + Location l = set.entrance[i]; + for (int x = 1; x < set.exit[i].getX() - l.getX(); x++) { + Scenery object = RegionManager.getObject(l.transform(x, 0, 0)); + if(object != null) + SceneryBuilder.replace(object, object.transform(avail ? 3573 : 3576)); + } + RegionManager.getObject(set.entrance[i]).setCharge(avail ? 1000 : 500); + RegionManager.getObject(set.exit[i]).setCharge(avail ? 1000 : 500); + } + } + } - /** - * The plank obstacles. - * - * @author Emperor - */ - private static enum PlankSet { - FIRST(new Location[]{Location.create(2797, 9591, 3), Location.create(2797, 9590, 3), Location.create(2797, 9589, 3)}, new Location[]{Location.create(2802, 9591, 3), Location.create(2802, 9590, 3), Location.create(2802, 9589, 3)}), SECOND(new Location[]{Location.create(2764, 9558, 3), Location.create(2764, 9557, 3), Location.create(2764, 9556, 3)}, new Location[]{Location.create(2769, 9558, 3), Location.create(2769, 9557, 3), Location.create(2769, 9556, 3)}); + /** + * The plank obstacles. + * + * @author Emperor + */ + private static enum PlankSet { + FIRST(new Location[]{Location.create(2797, 9591, 3), Location.create(2797, 9590, 3), Location.create(2797, 9589, 3)}, new Location[]{Location.create(2802, 9591, 3), Location.create(2802, 9590, 3), Location.create(2802, 9589, 3)}), SECOND(new Location[]{Location.create(2764, 9558, 3), Location.create(2764, 9557, 3), Location.create(2764, 9556, 3)}, new Location[]{Location.create(2769, 9558, 3), Location.create(2769, 9557, 3), Location.create(2769, 9556, 3)}); - /** - * Constructs a new {@code PlankSet} {@code Object}. - * - * @param entrance The entrance locations for each plank. - * @param exit The exit locations for each plank. - */ - private PlankSet(Location[] entrance, Location[] exit) { - this.entrance = entrance; - this.exit = exit; - } + /** + * Constructs a new {@code PlankSet} {@code Object}. + * + * @param entrance The entrance locations for each plank. + * @param exit The exit locations for each plank. + */ + private PlankSet(Location[] entrance, Location[] exit) { + this.entrance = entrance; + this.exit = exit; + } - /** - * The entrance location of the plank. - */ - Location[] entrance; + /** + * The entrance location of the plank. + */ + Location[] entrance; - /** - * The exit location of the plank. - */ - Location[] exit; - } + /** + * The exit location of the plank. + */ + Location[] exit; + } - @Override - public Plugin newInstance(Object arg) throws Throwable { - ZoneBuilder.configure(this); - return this; - } + @Override + public Plugin newInstance(Object arg) throws Throwable { + ZoneBuilder.configure(this); + return this; + } - @Override - public Object fireEvent(String identifier, Object... args) { - return null; - } + @Override + public Object fireEvent(String identifier, Object... args) { + return null; + } } diff --git a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java index b74e99cb3..9e9dde9df 100644 --- a/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java +++ b/Server/src/main/content/global/skill/construction/BuildRoomDialogue.java @@ -241,7 +241,7 @@ public final class BuildRoomDialogue extends DialoguePlugin { } int rotation = directions[index].toInteger(); boundaries.clear(); - Location base = player.getViewport().getRegion().getBaseLocation().transform(roomX << 3, roomY << 3, player.getLocation().getZ()); + Location base = player.getLocation().getRegion().getBaseLocation().transform(roomX << 3, roomY << 3, player.getLocation().getZ()); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { Scenery[] objects = room.getChunk().getObjects(x, y); diff --git a/Server/src/main/content/global/skill/construction/BuildingUtils.java b/Server/src/main/content/global/skill/construction/BuildingUtils.java index 2ee636337..158d7abbb 100644 --- a/Server/src/main/content/global/skill/construction/BuildingUtils.java +++ b/Server/src/main/content/global/skill/construction/BuildingUtils.java @@ -8,10 +8,7 @@ import core.game.node.item.Item; import core.game.node.scenery.Scenery; import core.game.node.scenery.SceneryBuilder; import core.game.system.task.Pulse; -import core.game.world.map.BuildRegionChunk; -import core.game.world.map.Direction; -import core.game.world.map.Location; -import core.game.world.map.Region; +import core.game.world.map.*; import core.game.world.update.flag.context.Animation; import core.net.packet.PacketRepository; import core.net.packet.context.ContainerContext; @@ -250,7 +247,7 @@ public final class BuildingUtils { if (reg == null) { continue; } - BuildRegionChunk chunk = (BuildRegionChunk) reg.getPlanes()[plane % 3].getChunks()[l.getChunkX()][l.getChunkY()]; + RegionChunk chunk = reg.getChunks()[l.getChunkX()][l.getChunkY()][plane % 3]; Scenery[] objects = chunk.getObjects(h.getCurrentX(), h.getCurrentY()); for (Scenery o : objects) { if (o != null && o.getType() == object.getType()) { @@ -284,14 +281,15 @@ public final class BuildingUtils { hotspot.setDecorationIndex(decIndex); break; case RECURSIVE: - BuildRegionChunk chunk = (BuildRegionChunk) region.getPlanes()[l.getZ()].getChunks()[l.getChunkX()][l.getChunkY()]; + RegionChunk chunk = region.getChunks()[l.getChunkX()][l.getChunkY()][l.getZ()]; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { Hotspot h = room.getHotspot(hotspot.getHotspot(), x, y); if (h != null) { h.setDecorationIndex(decIndex); int objectId = hotspot.getHotspot().getObjectId(style); - Scenery o = chunk.get(x, y, chunk.getIndex(x, y, objectId)); + int index = chunk.getIndex(x, y, objectId, -1); + Scenery o = chunk.getObjects()[index][x][y]; if (o != null && objectId == o.getId()) { SceneryBuilder.replace(o, o.transform(hotspot.getHotspot().getDecorations()[decIndex].getObjectId(style))); } @@ -301,7 +299,7 @@ public final class BuildingUtils { break; case LINKED: BuildHotspot[] linkedHotspots = BuildHotspot.getLinkedHotspots(hotspot.getHotspot()); - chunk = (BuildRegionChunk) region.getPlanes()[l.getZ()].getChunks()[l.getChunkX()][l.getChunkY()]; + chunk = region.getChunks()[l.getChunkX()][l.getChunkY()][l.getZ()]; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { for (BuildHotspot bh : linkedHotspots) { @@ -309,7 +307,8 @@ public final class BuildingUtils { if (h != null) { h.setDecorationIndex(decIndex); int objectId = bh.getObjectId(style); - Scenery o = chunk.get(x, y, chunk.getIndex(x, y, objectId)); + int index = chunk.getIndex(x, y, objectId, -1); + Scenery o = chunk.getObjects()[index][x][y]; if (o != null && objectId == o.getId()) { SceneryBuilder.replace(o, o.transform(bh.getDecorations()[decIndex].getObjectId(style))); } @@ -385,7 +384,7 @@ public final class BuildingUtils { if (reg == null) { continue; } - BuildRegionChunk chunk = (BuildRegionChunk) reg.getPlanes()[plane % 3].getChunks()[l.getChunkX()][l.getChunkY()]; + RegionChunk chunk = reg.getChunks()[l.getChunkX()][l.getChunkY()][plane % 3]; Scenery[] objects = chunk.getObjects(h.getCurrentX(), h.getCurrentY()); for (Scenery o : objects) { if (o != null && o.getType() == object.getType()) { @@ -417,13 +416,14 @@ public final class BuildingUtils { hotspot.setDecorationIndex(-1); break; case RECURSIVE: - BuildRegionChunk chunk = (BuildRegionChunk) region.getPlanes()[l.getZ()].getChunks()[l.getChunkX()][l.getChunkY()]; + RegionChunk chunk = region.getChunks()[l.getChunkX()][l.getChunkY()][l.getZ()]; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { Hotspot h = room.getHotspot(hotspot.getHotspot(), x, y); if (h != null) { int objectId = hotspot.getHotspot().getDecorations()[h.getDecorationIndex()].getObjectId(style); - Scenery o = chunk.get(x, y, chunk.getIndex(x, y, objectId)); + int index = chunk.getIndex(x, y, objectId, -1); + Scenery o = chunk.getObjects()[index][x][y]; h.setDecorationIndex(-1); if (o != null && objectId == o.getId()) { SceneryBuilder.replace(o, o.transform(hotspot.getHotspot().getObjectId(style))); @@ -434,14 +434,15 @@ public final class BuildingUtils { break; case LINKED: BuildHotspot[] linkedHotspots = BuildHotspot.getLinkedHotspots(hotspot.getHotspot()); - chunk = (BuildRegionChunk) region.getPlanes()[l.getZ()].getChunks()[l.getChunkX()][l.getChunkY()]; + chunk = region.getChunks()[l.getChunkX()][l.getChunkY()][l.getZ()]; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { for (BuildHotspot bh : linkedHotspots) { Hotspot h = room.getHotspot(bh, x, y); if (h != null) { int objectId = bh.getDecorations()[h.getDecorationIndex()].getObjectId(style); - Scenery o = chunk.get(x, y, chunk.getIndex(x, y, objectId)); + int index = chunk.getIndex(x, y, objectId, -1); + Scenery o = chunk.getObjects()[index][x][y]; h.setDecorationIndex(-1); if (o != null && objectId == o.getId()) { SceneryBuilder.replace(o, o.transform(bh.getObjectId(style))); diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index 4db8e8191..884ce5a7f 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -10,6 +10,7 @@ import core.game.world.map.*; import core.game.world.map.build.DynamicRegion; import core.game.world.map.zone.ZoneBorders; import core.game.world.map.zone.ZoneBuilder; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.tools.Log; import org.jetbrains.annotations.NotNull; @@ -20,6 +21,7 @@ import core.game.world.GameWorld; import org.rs09.consts.Sounds; import java.awt.*; +import java.util.ArrayList; import static core.api.ContentAPIKt.*; import static core.api.regionspec.RegionSpecificationKt.fillWith; @@ -195,8 +197,8 @@ public final class HouseManager { } private void updateVarbits(Player player, boolean build) { - setVarp(player, 261, build ? 1 : 0); - setVarp(player, 262, getRoomAmount()); + setVarp(player, 261, build ? 1 : 0); + setVarp(player, 262, getRoomAmount()); } private void unlockMusicTrack(Player player) { @@ -241,13 +243,13 @@ public final class HouseManager { * Reloads the house. * @param player The player. * @param buildingMode If building mode should be enabled. - * NOTE: I think we should avoid this method, it might be causing some issues. It's actually really suspicious... + * NOTE: I think we should avoid this method, it might be causing some issues. It's actually really suspicious... */ public void reload(Player player, boolean buildingMode) { int diffX = player.getLocation().getLocalX(); int diffY = player.getLocation().getLocalY(); int diffZ = player.getLocation().getZ(); - boolean inDungeon = player.getViewport().getRegion() == dungeonRegion; + boolean inDungeon = player.getLocation().getRegion() == dungeonRegion; this.buildingMode = buildingMode; construct(); Location newLoc = (dungeonRegion == null ? houseRegion : (inDungeon ? dungeonRegion : houseRegion)).getBaseLocation().transform(diffX,diffY,diffZ); @@ -260,22 +262,17 @@ public final class HouseManager { */ public void expelGuests(Player player) { if (isLoaded()) { - for (RegionPlane plane : houseRegion.getPlanes()) { - for (Player p : plane.getPlayers()) { + for (int z = 0; z < 4; z++) { + ArrayList players = new ArrayList<>(houseRegion.assemblePlayerList(z)); + if (dungeonRegion != null) { + players.addAll(dungeonRegion.assemblePlayerList(z)); + } + for (Player p : players) { if (p != player) { leave(p); } } } - if (dungeonRegion != null) { - for (RegionPlane plane : dungeonRegion.getPlanes()) { - for (Player p : plane.getPlayers()) { - if (p != player) { - leave(p); - } - } - } - } } } @@ -375,7 +372,6 @@ public final class HouseManager { ZoneBorders borders = DynamicRegion.reserveArea(8,8); DynamicRegion region = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6); region.setBorders(borders); - region.setUpdateAllPlanes(true); region.setBuild(true); RegionManager.addRegion(region.getId(), region); return region; @@ -393,12 +389,12 @@ public final class HouseManager { } @Override - public BuildRegionChunk getChunk(int x, int y, int plane, @NotNull DynamicRegion dyn) { - return rooms[plane][x][y].getChunk().copy(dyn.getPlanes()[plane]); + public @Nullable RegionChunk getChunk(int x, int y, int plane, @NotNull DynamicRegion dyn) { + return rooms[plane][x][y].getChunk().copy(); } @Override - public void afterSetting(@Nullable BuildRegionChunk chunk, int x, int y, int plane, @NotNull DynamicRegion dyn) { + public void afterSetting(@Nullable RegionChunk chunk, int x, int y, int plane, @NotNull DynamicRegion dyn) { rooms[plane][x][y].loadDecorations(dyn != manager.dungeonRegion ? plane : 3, chunk, manager); } } @@ -406,8 +402,8 @@ public final class HouseManager { private void prepareHouseChunks(HousingStyle style, DynamicRegion target, boolean buildingMode, Room[][][] rooms) { Region from = RegionManager.forId(style.getRegionId()); Region.load(from, true); - RegionChunk defaultChunk = from.getPlanes()[style.getPlane()].getRegionChunk(1, 0); - RegionChunk defaultSkyChunk = from.getPlanes()[1].getRegionChunk(0,0); + RegionChunk defaultChunk = from.getChunks()[1][0][style.getPlane()]; + RegionChunk defaultSkyChunk = from.getChunks()[0][0][1]; RoomLoadContract loadRooms = new RoomLoadContract(this, buildingMode, rooms); RegionSpecification spec = new RegionSpecification( @@ -430,7 +426,7 @@ public final class HouseManager { private void prepareDungeonChunks(HousingStyle style, DynamicRegion target, DynamicRegion house, boolean buildingMode, Room[][] rooms) { Region from = RegionManager.forId(style.getRegionId()); Region.load(from, true); - RegionChunk defaultChunk = from.getPlanes()[style.getPlane()].getRegionChunk(3, 0); + RegionChunk defaultChunk = from.getChunks()[3][0][style.getPlane()]; RoomLoadContract loadRooms = new RoomLoadContract(this, buildingMode, new Room[][][]{rooms}); RegionSpecification spec = new RegionSpecification( @@ -688,7 +684,7 @@ public final class HouseManager { * @return {@code True} if so. */ public boolean isInHouse(Player player) { - return isLoaded() && (player.getViewport().getRegion() == houseRegion || player.getViewport().getRegion() == dungeonRegion); + return isLoaded() && (player.getLocation().getRegion() == houseRegion || player.getLocation().getRegion() == dungeonRegion); } /** @@ -697,7 +693,7 @@ public final class HouseManager { * @return {@code True} if so. */ public static boolean isInDungeon(Player player) { - return player.getViewport().getRegion() == player.getHouseManager().dungeonRegion; + return player.getLocation().getRegion() == player.getHouseManager().dungeonRegion; } /** diff --git a/Server/src/main/content/global/skill/construction/HousingStyle.java b/Server/src/main/content/global/skill/construction/HousingStyle.java index eace0e7bb..b9df17417 100644 --- a/Server/src/main/content/global/skill/construction/HousingStyle.java +++ b/Server/src/main/content/global/skill/construction/HousingStyle.java @@ -12,36 +12,35 @@ import java.util.Arrays; */ public enum HousingStyle { - // open door ids are doorId + 1 - - BASIC_WOOD (1, 5000, 7503, 0, 13100, 13101, 13098, Decoration.BASIC_WOOD_WINDOW), - BASIC_STONE (10, 5000, 7503, 1, 13094, 13096, 1902, Decoration.BASIC_STONE_WINDOW), - WHITEWASHED_STONE (20, 7500, 7503, 2, 13006, 13007, 1415, Decoration.WHITEWASHED_STONE_WINDOW), - FREMENNIK_STYLE_WOOD(30, 10000, 7503, 3, 13109, 13107, 13111, Decoration.FREMENNIK_WINDOW), - TROPICAL_WOOD (40, 15000, 7759, 0, 13016, 13015, 13011, Decoration.TROPICAL_WOOD_WINDOW), - FANCY_STONE (50, 25000, 7759, 1, 13119, 13118, 13116, Decoration.FANCY_STONE_WINDOW); + // open door ids are doorId + 1 + BASIC_WOOD (1, 5000, 7503, 0, 13100, 13101, 13098, 13098, Decoration.BASIC_WOOD_WINDOW), + BASIC_STONE (10, 5000, 7503, 1, 13094, 13096, 1902, 13090, Decoration.BASIC_STONE_WINDOW), + WHITEWASHED_STONE (20, 7500, 7503, 2, 13006, 13007, 1415, 1415, Decoration.WHITEWASHED_STONE_WINDOW), + FREMENNIK_STYLE_WOOD(30, 10000, 7503, 3, 13109, 13107, 13111, 13111, Decoration.FREMENNIK_WINDOW), + TROPICAL_WOOD (40, 15000, 7759, 0, 13016, 13015, 13011, 13011, Decoration.TROPICAL_WOOD_WINDOW), + FANCY_STONE (50, 25000, 7759, 1, 13119, 13118, 13116, 13116, Decoration.FANCY_STONE_WINDOW); - /** - * Array of all Dungeon Wall IDs. - * From Region 7503, Location.create(1898, 5084, 0) - */ - private static final int[] DUNGEON_WALL_IDS = { - 13019, 13020, 13021, 13022, 13023, 13024, 13025, 13026, 13027, 13028, - 13029, 13030, 13031, 13032, 13033, 13034, 13035, 13036, 13037, 13046, - 13048, 13049, 13050, 13051, 13055, 13056, 13058, 13059, 13060, 13061, - 13062, 13063, 13065, 13066, 13067, 13068, 13069, 13070, 13072, 13073, - 13074, 13075, 13076, 13077, 13079, 13080, 13081, 13082, 13083, 13084, - 13086, 13087, 13088, 13089 - }; + /** + * Array of all Dungeon Wall IDs. + * From Region 7503, Location.create(1898, 5084, 0) + */ + private static final int[] DUNGEON_WALL_IDS = { + 13019, 13020, 13021, 13022, 13023, 13024, 13025, 13026, 13027, 13028, + 13029, 13030, 13031, 13032, 13033, 13034, 13035, 13036, 13037, 13046, + 13048, 13049, 13050, 13051, 13055, 13056, 13058, 13059, 13060, 13061, + 13062, 13063, 13065, 13066, 13067, 13068, 13069, 13070, 13072, 13073, + 13074, 13075, 13076, 13077, 13079, 13080, 13081, 13082, 13083, 13084, + 13086, 13087, 13088, 13089 + }; - /** - * Checks if the provided ID is a dungeon wall. - * @param id The object ID. - * @return {@code true} if it's a dungeon wall. - */ - public static boolean isDungeonWall(int id) { - return Arrays.binarySearch(DUNGEON_WALL_IDS, id) >= 0; - } + /** + * Checks if the provided ID is a dungeon wall. + * @param id The object ID. + * @return {@code true} if it's a dungeon wall. + */ + public static boolean isDungeonWall(int id) { + return Arrays.binarySearch(DUNGEON_WALL_IDS, id) >= 0; + } /** * The level required. @@ -77,21 +76,26 @@ public enum HousingStyle { * The wall id. */ private final int wallId; + + /** + * A second wall id, used for walls behind fireplaces in some house styles. + * Only used for the basic stone house style, who knows why. Same as wallId for other house styles. + */ + private final int secondWallId; /** * The window style */ private final Decoration window; - /** - * Checks if the player has the level. - * - * @param player the player. - * @return {@code True} if so. - */ - public boolean hasLevel(Player player) { - return player.getSkills().getStaticLevel(Skills.CONSTRUCTION) >= levelRequirement; - } + /** + * Checks if the player has the level. + * @param player the player. + * @return {@code True} if so. + */ + public boolean hasLevel(Player player) { + return player.getSkills().getStaticLevel(Skills.CONSTRUCTION) >= levelRequirement; + } /** * Constructs a new {@code HousingStyle} {@code Object} @@ -100,8 +104,11 @@ public enum HousingStyle { * @param regionId The region id for this style. * @param plane The plane for this style. * @param doorId The door object id used in this style. + * @param secondDoorId The second-door object id used in this style. + * @param wallId The wall object id used in this style. + * @param secondWallId The second-wall object id used in this style. */ - private HousingStyle(int level, int cost, int regionId, int plane, int doorId, int secondDoorId, int wallId, Decoration window) { + HousingStyle(int level, int cost, int regionId, int plane, int doorId, int secondDoorId, int wallId, int secondWallId, Decoration window) { this.levelRequirement = level; this.cost = cost; this.regionId = regionId; @@ -109,6 +116,7 @@ public enum HousingStyle { this.doorId = doorId; this.secondDoorId = secondDoorId; this.wallId = wallId; + this.secondWallId = secondWallId; this.window = window; } @@ -159,7 +167,15 @@ public enum HousingStyle { public int getWallId() { return wallId; } - + + /** + * Gets the second wall used in this style. + * @return The wall object id. + */ + public int getSecondWallId() { + return secondWallId; + } + /** * Gets the window id for this style of house * @return The windows object id @@ -175,4 +191,4 @@ public enum HousingStyle { public int getSecondDoorId() { return secondDoorId; } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/construction/Room.java b/Server/src/main/content/global/skill/construction/Room.java index ac7b56cec..28f068ac4 100644 --- a/Server/src/main/content/global/skill/construction/Room.java +++ b/Server/src/main/content/global/skill/construction/Room.java @@ -1,6 +1,5 @@ package content.global.skill.construction; - import core.game.node.entity.player.Player; import core.game.node.scenery.Constructed; import core.game.node.scenery.Scenery; @@ -16,7 +15,6 @@ import static core.api.ContentAPIKt.log; * */ public final class Room { - /** * The default room type. */ @@ -95,7 +93,7 @@ public final class Room { public void decorate(HousingStyle style) { Region region = RegionManager.forId(style.getRegionId()); Region.load(region, true); - chunk = region.getPlanes()[style.getPlane()].getRegionChunk(properties.getChunkX(), properties.getChunkY()); + chunk = region.getChunks()[properties.getChunkX()][properties.getChunkY()][style.getPlane()]; } /** @@ -126,28 +124,24 @@ public final class Room { * Loads all the decorations. * @param housePlane The plane. * @param chunk The chunk used in the dynamic region. - */ - public void loadDecorations(int housePlane, BuildRegionChunk chunk, HouseManager house) { - for (int i = 0; i < hotspots.length; i++) { - Hotspot spot = hotspots[i]; + */ + public void loadDecorations(int housePlane, RegionChunk chunk, HouseManager house) { + for (Hotspot spot : hotspots) { int x = spot.getChunkX(); int y = spot.getChunkY(); - if (spot.getHotspot() == null) { - continue; - } - int index = chunk.getIndex(x, y, spot.getHotspot().getObjectId(house.getStyle())); - Scenery[][] objects = chunk.getObjects(index); + int id = spot.getHotspot().getObjectId(house.getStyle()); + int index = chunk.getIndex(x, y, id, -1); + Scenery[][] objects = chunk.getObjects()[index]; Scenery object = objects[x][y]; if (object != null && object.getId() == spot.getHotspot().getObjectId(house.getStyle())) { if (spot.getDecorationIndex() > -1 && spot.getDecorationIndex() < spot.getHotspot().getDecorations().length) { - int id = spot.getHotspot().getDecorations()[spot.getDecorationIndex()].getObjectId(house.getStyle()); + id = spot.getHotspot().getDecorations()[spot.getDecorationIndex()].getObjectId(house.getStyle()); if (spot.getHotspot().getType() == BuildHotspotType.CREST) { id += house.getCrest().ordinal(); } SceneryBuilder.replace(object, object.transform(id, object.getRotation(), chunk.getCurrentBase().transform(x, y, 0))); - } - else if (object.getId() == BuildHotspot.WINDOW.getObjectId(house.getStyle()) || (!house.isBuildingMode() && object.getId() == BuildHotspot.CHAPEL_WINDOW.getObjectId(house.getStyle()))) { - chunk.add(object.transform(house.getStyle().getWindowStyle().getObjectId(house.getStyle()), object.getRotation(), object.getType())); + } else if (object.getId() == BuildHotspot.WINDOW.getObjectId(house.getStyle()) || (!house.isBuildingMode() && object.getId() == BuildHotspot.CHAPEL_WINDOW.getObjectId(house.getStyle()))) { + SceneryBuilder.replace(object, object.transform(house.getStyle().getWindowStyle().getObjectId(house.getStyle()), object.getRotation(), object.getType())); } int[] pos = RegionChunk.getRotatedPosition(x, y, object.getSizeX(), object.getSizeY(), 0, rotation.toInteger()); spot.setCurrentX(pos[0]); @@ -159,30 +153,29 @@ public final class Room { } if (!house.isBuildingMode()) { placeDoors(housePlane, house, chunk); - removeHotspots(housePlane, house, chunk); + removeHotspots(house, chunk); } } /** * Removes the building hotspots from the room. - * @param housePlane The room's plane in house. * @param house The house manager. * @param chunk The region chunk used. */ - private void removeHotspots(int housePlane, HouseManager house, BuildRegionChunk chunk) { + private void removeHotspots(HouseManager house, RegionChunk chunk) { if (properties.isRoof()) return; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { - for (int i = 0; i < BuildRegionChunk.ARRAY_SIZE; i++) { - Scenery object = chunk.get(x, y, i); + for (int i = 0; i < RegionChunk.ARRAY_SIZE; i++) { + Scenery object = chunk.getObjects()[i][x][y]; if (object != null) { - int id = object.getId(); - boolean isBuilt = object instanceof Constructed; - boolean isWall = HousingStyle.isDungeonWall(id) || id == house.getStyle().getWallId(); - boolean isDoor = id == house.getStyle().getDoorId() || id == house.getStyle().getSecondDoorId(); - if (!isBuilt && !isWall && !isDoor) { + int id = object.getId(); + boolean isBuilt = !object.getDefinition().hasAction("build"); + boolean isGround = object.getType() == 22 && !object.getDefinition().hasOptions(); + boolean isWall = HousingStyle.isDungeonWall(id) || id == house.getStyle().getWallId() || id == house.getStyle().getSecondWallId(); + boolean isDoor = id == house.getStyle().getDoorId() || id == house.getStyle().getSecondDoorId(); + if (!isBuilt && !isGround && !isWall && !isDoor) { SceneryBuilder.remove(object); - chunk.remove(object); } } } @@ -197,14 +190,14 @@ public final class Room { * @param house The house manager. * @param chunk The region chunk used. */ - private void placeDoors(int housePlane, HouseManager house, BuildRegionChunk chunk) { + private void placeDoors(int housePlane, HouseManager house, RegionChunk chunk) { Room[][][] rooms = house.getRooms(); int rx = chunk.getCurrentBase().getChunkX(); int ry = chunk.getCurrentBase().getChunkY(); - for (int i = 0; i < BuildRegionChunk.ARRAY_SIZE; i++) { + for (int i = 0; i < RegionChunk.ARRAY_SIZE; i++) { for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { - Scenery object = chunk.get(x, y, i); + Scenery object = chunk.getObjects()[i][x][y]; if (object != null && BuildingUtils.isDoorHotspot(object)) { boolean edge = false; Room otherRoom = null; @@ -274,7 +267,7 @@ public final class Room { return object.getId() % 2 != 0 ? house.getStyle().getDoorId() : house.getStyle().getSecondDoorId(); } } - return room.getProperties().isDungeon() ? 13065 : house.getStyle().getWallId(); + return room.getProperties().isDungeon() ? 13065 : house.getStyle().getWallId(); //otherWallId is only used behind fireplaces } /** @@ -423,5 +416,4 @@ public final class Room { public Direction getRotation() { return rotation; } - } diff --git a/Server/src/main/content/global/skill/construction/RoomProperties.java b/Server/src/main/content/global/skill/construction/RoomProperties.java index 80bc6e6ed..f4199d46f 100644 --- a/Server/src/main/content/global/skill/construction/RoomProperties.java +++ b/Server/src/main/content/global/skill/construction/RoomProperties.java @@ -920,7 +920,7 @@ public enum RoomProperties { public boolean[] getExits() { Region region = RegionManager.forId(7503); Region.load(region, true); - RegionChunk chunk = region.getPlanes()[0].getRegionChunk(chunkX, chunkY); + RegionChunk chunk = region.getChunks()[chunkX][chunkY][0]; return new boolean[] { isExit(chunk, 7, 3), isExit(chunk, 3, 0), isExit(chunk, 0, 3), isExit(chunk, 3, 7) }; } diff --git a/Server/src/main/content/global/skill/construction/decoration/StaircasePlugin.java b/Server/src/main/content/global/skill/construction/decoration/StaircasePlugin.java index 8c22d84ab..73a4cb12c 100644 --- a/Server/src/main/content/global/skill/construction/decoration/StaircasePlugin.java +++ b/Server/src/main/content/global/skill/construction/decoration/StaircasePlugin.java @@ -29,18 +29,18 @@ public final class StaircasePlugin extends OptionHandler { public Plugin newInstance(Object arg) throws Throwable { ClassScanner.definePlugin(new BuildDialogue()); ClassScanner.definePlugin(new ClimbPohLadder()); - // 13497 - 13502 are normal stairs - // 13503 - 13506 are spiral stairs + // 13497 - 13502 are normal stairs + // 13503 - 13506 are spiral stairs for (int i = 13497; i <= 13506; i++) { SceneryDefinition.forId(i).getHandlers().put("option:climb", this); SceneryDefinition.forId(i).getHandlers().put("option:climb-up", this); SceneryDefinition.forId(i).getHandlers().put("option:climb-down", this); SceneryDefinition.forId(i).getHandlers().put("option:remove-room", this); } - // 13409 is dungeon entrance + // 13409 is dungeon entrance SceneryDefinition.forId(13409).getHandlers().put("option:enter", this); SceneryDefinition.forId(13409).getHandlers().put("option:remove-room", this); - // 13328 - 13330 are dungeon ladders + // 13328 - 13330 are dungeon ladders for (int id = 13328; id <= 13330; id++) { SceneryDefinition.forId(id).getHandlers().put("option:climb", this); SceneryDefinition.forId(id).getHandlers().put("option:remove-room", this); @@ -74,43 +74,43 @@ public final class StaircasePlugin extends OptionHandler { return true; case "remove-room": - int currentZ = player.getLocation().getZ(); - int chunkX = player.getLocation().getChunkX(); - int chunkY = player.getLocation().getChunkY(); + int currentZ = player.getLocation().getZ(); + int chunkX = player.getLocation().getChunkX(); + int chunkY = player.getLocation().getChunkY(); - // must be in building mode - if(!player.getHouseManager().isBuildingMode()) { - player.getPacketDispatch().sendMessage("You can only do this in building mode."); - return true; - } + // must be in building mode + if(!player.getHouseManager().isBuildingMode()) { + player.getPacketDispatch().sendMessage("You can only do this in building mode."); + return true; + } - // if you're in the dungeon, try and remove the room at Z = 0 from the house region. - if (HouseManager.isInDungeon(player)) { - player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, 0); + // if you're in the dungeon, try and remove the room at Z = 0 from the house region. + if (HouseManager.isInDungeon(player)) { + player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, 0); - // From ground floor (z=0), stairs could lead to 1st floor (z=1) or the dungeon (z=3) - } else { - // garden dungeon entrance and oubliette ladders don't need a height selection - if(node.getId() == 13409 || node.getId() == 13675 || node.getId() == 13676 || node.getId() == 13677 || node.getId() == 13678 || node.getId() == 13679 || node.getId() == 13680) { - player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, 3); - } else { - player.getDialogueInterpreter().sendOptions("Remove which room?", "Room Above", "Room Below", "Cancel"); - player.getDialogueInterpreter().addAction((interId, btn) -> { - if (btn == 2) { // Above - player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, currentZ + 1); - } else if (btn == 3) { // Below - if (currentZ - 1 == -1) { - player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, 3); - } else { - player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, currentZ - 1); - } + // From ground floor (z=0), stairs could lead to 1st floor (z=1) or the dungeon (z=3) + } else { + // garden dungeon entrance and oubliette ladders don't need a height selection + if(node.getId() == 13409 || node.getId() == 13675 || node.getId() == 13676 || node.getId() == 13677 || node.getId() == 13678 || node.getId() == 13679 || node.getId() == 13680) { + player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, 3); + } else { + player.getDialogueInterpreter().sendOptions("Remove which room?", "Room Above", "Room Below", "Cancel"); + player.getDialogueInterpreter().addAction((interId, btn) -> { + if (btn == 2) { // Above + player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, currentZ + 1); + } else if (btn == 3) { // Below + if (currentZ - 1 == -1) { + player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, 3); + } else { + player.getDialogueInterpreter().open("con:remove", null, new int[]{chunkX, chunkY}, currentZ - 1); + } - } - }); - } + } + }); + } - } - return true; + } + return true; case "climb": if (HouseManager.isInDungeon(player)) { @@ -151,7 +151,7 @@ public final class StaircasePlugin extends OptionHandler { if (plane < 0) { //Dungeon plane = 3; } - else if (player.getViewport().getRegion() == house.getDungeonRegion() && plane == 1) {//going up + else if (player.getLocation().getRegion() == house.getDungeonRegion() && plane == 1) {//going up plane = 0; } Room room = house.getRooms()[plane][roomX][roomY]; @@ -165,7 +165,7 @@ public final class StaircasePlugin extends OptionHandler { } } else { Location destination = l.transform(0, 0, z); - if (player.getViewport().getRegion() == house.getDungeonRegion()) { + if (player.getLocation().getRegion() == house.getDungeonRegion()) { destination = house.getHouseRegion().getBaseLocation().transform(l.getLocalX(), l.getLocalY(), 0); } else if (plane == 3) { @@ -417,7 +417,7 @@ public final class StaircasePlugin extends OptionHandler { for (Direction d : dirs) { if (d == room.getRotation()) { r.setRotation(d); - // todo this just puts a default set of stairs in the dungeon. The below code works for skill/quest hall, but not a dungeon entrance. + // todo this just puts a default set of stairs in the dungeon. The below code works for skill/quest hall, but not a dungeon entrance. //Hotspot stairs = room.getStairs(); //int index = stairs != null ? stairs.getDecorationIndex() : -1; BuildingUtils.buildRoom(player, r, plane, roomX, roomY, r.getExits(), true); diff --git a/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java b/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java index ddb967ebe..412f96da3 100644 --- a/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java +++ b/Server/src/main/content/global/skill/construction/npc/HouseServantDialogue.java @@ -525,7 +525,7 @@ public class HouseServantDialogue extends DialoguePlugin { @Override public boolean pulse() { - if (player == null || player.getHouseManager().getHouseRegion() != player.getViewport().getRegion()) { //TODO: Check if in dungeon? + if (player == null || player.getHouseManager().getHouseRegion() != player.getLocation().getRegion()) { //TODO: Check if in dungeon? return true; } int amt = player.getBank().getAmount(item.getId()); diff --git a/Server/src/main/content/global/skill/crafting/spinning/SpinningPulse.java b/Server/src/main/content/global/skill/crafting/spinning/SpinningPulse.java index ae652f9a8..b7efeae3a 100644 --- a/Server/src/main/content/global/skill/crafting/spinning/SpinningPulse.java +++ b/Server/src/main/content/global/skill/crafting/spinning/SpinningPulse.java @@ -20,62 +20,62 @@ import static core.api.ContentAPIKt.playAudio; */ public final class SpinningPulse extends SkillPulse { - /** - * Represents the animation to use. - */ - private static final Animation ANIMATION = new Animation(896); + /** + * Represents the animation to use. + */ + private static final Animation ANIMATION = new Animation(896); - /** - * Represents the type of spinning item. - */ - private final SpinningItem type; + /** + * Represents the type of spinning item. + */ + private final SpinningItem type; - /** - * Represents the amount to spin. - */ - private int ammount; + /** + * Represents the amount to spin. + */ + private int ammount; - /** - * Represents the ticks passed. - */ - private int ticks; + /** + * Represents the ticks passed. + */ + private int ticks; - /** - * Constructs a new {@code SpinningPulse.java} {@Code Object} - * - * @param player - * @param node - */ - public SpinningPulse(Player player, Item node, int ammount, SpinningItem def) { - super(player, node); - this.type = def; - this.ammount = ammount; - } + /** + * Constructs a new {@code SpinningPulse.java} {@Code Object} + * + * @param player + * @param node + */ + public SpinningPulse(Player player, Item node, int ammount, SpinningItem def) { + super(player, node); + this.type = def; + this.ammount = ammount; + } - @Override - public boolean checkRequirements() { - player.getInterfaceManager().close(); - if (player.getSkills().getLevel(Skills.CRAFTING) < type.getLevel()) { - player.getPacketDispatch().sendMessage("You need a crafting level of " + type.getLevel() + " to make this."); - return false; - } - if (!player.getInventory().contains(type.getNeed(), 1)) { - player.getPacketDispatch().sendMessage("You need " + ItemDefinition.forId(type.getNeed()).getName() + " to do this."); - return false; - } - return true; - } + @Override + public boolean checkRequirements() { + player.getInterfaceManager().close(); + if (player.getSkills().getLevel(Skills.CRAFTING) < type.getLevel()) { + player.getPacketDispatch().sendMessage("You need a crafting level of " + type.getLevel() + " to make this."); + return false; + } + if (!player.getInventory().contains(type.getNeed(), 1)) { + player.getPacketDispatch().sendMessage("You need " + ItemDefinition.forId(type.getNeed()).getName() + " to do this."); + return false; + } + return true; + } - @Override - public void animate() { - if (ticks % 5 == 0) { - player.animate(ANIMATION); - playAudio(player, Sounds.SPINNING_2590); - } - } + @Override + public void animate() { + if (ticks % 5 == 0) { + player.animate(ANIMATION); + playAudio(player, Sounds.SPINNING_2590); + } + } - @Override - public boolean reward() { + @Override + public boolean reward() { int tickThreshhold = 4; if (player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(2) && player.getLocation().withinDistance(Location.create(2711,3471,1)) @@ -83,31 +83,31 @@ public final class SpinningPulse extends SkillPulse { && player.getEquipment().get(EquipmentContainer.SLOT_HAT).getId() == 14631) { tickThreshhold = 2; } - if (++ticks % tickThreshhold != 0) { - return false; - } - if (player.getInventory().remove(new Item(type.getNeed(), 1))) { - final Item item = new Item(type.getProduct(), 1); - player.getInventory().add(item); - player.getSkills().addExperience(Skills.CRAFTING, type.getExp(), true); + if (++ticks % tickThreshhold != 0) { + return false; + } + if (player.getInventory().remove(new Item(type.getNeed(), 1))) { + final Item item = new Item(type.getProduct(), 1); + player.getInventory().add(item); + player.getSkills().addExperience(Skills.CRAFTING, type.getExp(), true); - // Seers achievement diary - if (player.getViewport().getRegion().getId() == 10806 - && !player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(0, 4)) { - if (player.getAttribute("diary:seers:bowstrings-spun", 0) >= 4) { - player.setAttribute("/save:diary:seers:bowstrings-spun", 5); - player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 0, 4); - } else { - player.setAttribute("/save:diary:seers:bowstrings-spun", player.getAttribute("diary:seers:bowstrings-spun", 0) + 1); - } - } - } - ammount--; - return ammount < 1; - } + // Seers achievement diary + if (player.getLocation().getRegionId() == 10806 + && !player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(0, 4)) { + if (player.getAttribute("diary:seers:bowstrings-spun", 0) >= 4) { + player.setAttribute("/save:diary:seers:bowstrings-spun", 5); + player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 0, 4); + } else { + player.setAttribute("/save:diary:seers:bowstrings-spun", player.getAttribute("diary:seers:bowstrings-spun", 0) + 1); + } + } + } + ammount--; + return ammount < 1; + } - @Override - public void message(int type) { - } + @Override + public void message(int type) { + } } diff --git a/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java b/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java index 50b969efd..7fc0b070e 100644 --- a/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java +++ b/Server/src/main/content/global/skill/firemaking/FireMakingPulse.java @@ -138,7 +138,7 @@ public final class FireMakingPulse extends SkillPulse { player.faceLocation(object.getFaceLocation(player.getLocation())); player.getSkills().addExperience(Skills.FIREMAKING,fire.getXp()); - int playerRegion = player.getViewport().getRegion().getId(); + int playerRegion = player.getLocation().getRegionId(); setLastFire(); player.dispatch(new LitFireEvent(fire.getLogId())); diff --git a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt index 5a4a137b8..41261ec05 100644 --- a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt +++ b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingListener.kt @@ -29,6 +29,7 @@ import core.game.node.scenery.SceneryBuilder import core.game.system.command.sets.STATS_BASE import core.game.system.command.sets.STATS_LOGS import core.game.world.map.RegionManager +import core.game.world.repository.Repository import core.tools.RandomFunction import org.rs09.consts.Items import org.rs09.consts.NPCs @@ -212,14 +213,13 @@ class WoodcuttingListener : InteractionListener { fun animateWoodcutting(player: Player) { if (!player.animator.isAnimating) { player.animate(SkillingTool.getHatchet(player).animation) - val playersAroundMe: List = RegionManager.getLocalPlayers(player, 2) + val playersAroundMe: List = RegionManager.getLocalPlayers(player.location, 2) .stream() - .filter { p: Player -> p.username != player.username } + .filter { p -> p.name != player.name } .toList() val soundIndex = RandomFunction.random(0, woodcuttingSounds.size) - - for (p in playersAroundMe) { - playAudio(p, woodcuttingSounds[soundIndex]) + for (player in playersAroundMe) { + playAudio(player, woodcuttingSounds[soundIndex]) } } } @@ -260,7 +260,7 @@ class WoodcuttingListener : InteractionListener { } // Seers village medium reward - extra normal log while in seer's village - if (reward == 1511 && player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(1) && player.getViewport().getRegion().getId() == 10806) { + if (reward == 1511 && player.achievementDiaryManager.getDiary(DiaryType.SEERS_VILLAGE).isComplete(1) && player.getLocation().regionId == 10806) { amount = 2 } return amount diff --git a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java index d69c7fea1..cf0a4557a 100644 --- a/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java +++ b/Server/src/main/content/global/skill/gather/woodcutting/WoodcuttingSkillPulse.java @@ -21,6 +21,7 @@ import core.game.node.scenery.SceneryBuilder; import core.game.system.task.Pulse; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.tools.RandomFunction; import org.rs09.consts.Sounds; @@ -38,248 +39,244 @@ import static core.game.system.command.sets.StatAttributeKeysKt.STATS_LOGS; * @author ceik */ public class WoodcuttingSkillPulse extends Pulse { - private int[] woodcuttingSounds = { - Sounds.WOODCUTTING_HIT_3038, - Sounds.WOODCUTTING_HIT_3039, - Sounds.WOODCUTTING_HIT_3040, - Sounds.WOODCUTTING_HIT_3041, - Sounds.WOODCUTTING_HIT_3042 - }; + private int[] woodcuttingSounds = { + Sounds.WOODCUTTING_HIT_3038, + Sounds.WOODCUTTING_HIT_3039, + Sounds.WOODCUTTING_HIT_3040, + Sounds.WOODCUTTING_HIT_3041, + Sounds.WOODCUTTING_HIT_3042 + }; - private WoodcuttingNode resource; - private int ticks; - private Player player; - private Scenery node; - protected boolean resetAnimation = true; + private WoodcuttingNode resource; + private int ticks; + private Player player; + private Scenery node; + protected boolean resetAnimation = true; - public WoodcuttingSkillPulse(Player player, Scenery node) { - super(1, player, node); - this.player = player; - this.node = node; - super.stop(); - } + public WoodcuttingSkillPulse(Player player, Scenery node) { + super(1, player, node); + this.player = player; + this.node = node; + super.stop(); + } - public void message(int type) { - if (type == 0) { - player.getPacketDispatch().sendMessage("You swing your axe at the tree..."); - } - } + public void message(int type) { + if (type == 0) { + player.getPacketDispatch().sendMessage("You swing your axe at the tree..."); + } + } - @Override - public boolean pulse() { - if (!checkRequirements()) { - return true; - } - animate(); - return reward(); - } + @Override + public boolean pulse() { + if (!checkRequirements()) { + return true; + } + animate(); + return reward(); + } - @Override - public void stop() { - if (resetAnimation) { - player.animate(new Animation(-1, Animator.Priority.HIGH)); - } - super.stop(); - message(1); - } + @Override + public void stop() { + if (resetAnimation) { + player.animate(new Animation(-1, Animator.Priority.HIGH)); + } + super.stop(); + message(1); + } - @Override - public void start() { - resource = WoodcuttingNode.forId(node.getId()); - if (resource == null) { - return; - } - if (checkRequirements()) { - super.start(); - message(0); - } - } + @Override + public void start() { + resource = WoodcuttingNode.forId(node.getId()); + if (resource == null) { + return; + } + if (checkRequirements()) { + super.start(); + message(0); + } + } - public boolean checkRequirements() { - if (player.getSkills().getLevel(Skills.WOODCUTTING) < resource.getLevel()) { - player.getPacketDispatch().sendMessage("You need a woodcutting level of " + resource.getLevel() + " to chop this tree."); - return false; - } - if (SkillingTool.getHatchet(player) == null) { - player.getPacketDispatch().sendMessage("You do not have an axe to use."); - return false; - } - if (player.getInventory().freeSlots() < 1) { - player.getDialogueInterpreter().sendDialogue("Your inventory is too full to hold any more " + ItemDefinition.forId(resource.getReward()).getName().toLowerCase() + "."); - return false; - } - return true; - } + public boolean checkRequirements() { + if (player.getSkills().getLevel(Skills.WOODCUTTING) < resource.getLevel()) { + player.getPacketDispatch().sendMessage("You need a woodcutting level of " + resource.getLevel() + " to chop this tree."); + return false; + } + if (SkillingTool.getHatchet(player) == null) { + player.getPacketDispatch().sendMessage("You do not have an axe to use."); + return false; + } + if (player.getInventory().freeSlots() < 1) { + player.getDialogueInterpreter().sendDialogue("Your inventory is too full to hold any more " + ItemDefinition.forId(resource.getReward()).getName().toLowerCase() + "."); + return false; + } + return true; + } - public void animate() { - if(!player.getAnimator().isAnimating()) { - player.animate(SkillingTool.getHatchet(player).getAnimation()); + public void animate() { + if (!player.getAnimator().isAnimating()) { + player.animate(SkillingTool.getHatchet(player).getAnimation()); + for (Player p : RegionManager.getLocalPlayers(player.getLocation(), 2)) { + if (p.getName() == player.getName()) { + continue; + } + int soundIndex = RandomFunction.random(0, woodcuttingSounds.length); + playAudio(p, woodcuttingSounds[soundIndex]); + } + } + } - List playersAroundMe = RegionManager.getLocalPlayers(player, 2) - .stream() - .filter(p -> !p.getUsername().equals(player.getUsername())) - .collect(Collectors.toList()); + public boolean reward() { + if (++ticks % 4 != 0) { + return false; + } + if (node.getId() == 10041) { + player.getDialogueInterpreter().sendDialogues(2574, FacialExpression.FURIOUS, RandomFunction.random(2) == 1 ? "You'll blow my cover! I'm meant to be hidden!" : "Will you stop that?"); + return true; + } + if (!checkReward(SkillingTool.getHatchet(player))) { + return false; + } - int soundIndex = RandomFunction.random(0, woodcuttingSounds.length); + // 20% chance to auto burn logs when using "inferno adze" item + if (SkillingTool.getHatchet(player).getId() == 13661 && RandomFunction.random(100) < 25) { + player.sendMessage("You chop some logs. The heat of the inferno adze incinerates them."); + Projectile.create(player, null, 1776, 35, 30, 20, 25).transform(player, new Location(player.getLocation().getX() + 2, player.getLocation().getY()), true, 25, 25).send(); + player.getSkills().addExperience(Skills.WOODCUTTING, resource.getExperience()); + player.getSkills().addExperience(Skills.FIREMAKING, resource.getExperience()); + return rollDepletion(); + } - for (Player p : playersAroundMe) { - playAudio(p, woodcuttingSounds[soundIndex]); - } - } - } + //actual reward calculations + int reward = resource.getReward(); + int rewardAmount = 0; + if (reward > 0) { + reward = calculateReward(reward); // calculate rewards + rewardAmount = calculateRewardAmount(reward); // calculate amount - public boolean reward() { - if (++ticks % 4 != 0) { - return false; - } - if (node.getId() == 10041) { - player.getDialogueInterpreter().sendDialogues(2574, FacialExpression.FURIOUS, RandomFunction.random(2) == 1 ? "You'll blow my cover! I'm meant to be hidden!" : "Will you stop that?"); - return true; - } - if (!checkReward(SkillingTool.getHatchet(player))) { - return false; - } + //add experience + double experience = calculateExperience(resource.reward, rewardAmount); - // 20% chance to auto burn logs when using "inferno adze" item - if (SkillingTool.getHatchet(player).getId() == 13661 && RandomFunction.random(100) < 25) { - player.sendMessage("You chop some logs. The heat of the inferno adze incinerates them."); - Projectile.create(player, null, 1776, 35, 30, 20, 25).transform(player, new Location(player.getLocation().getX() + 2, player.getLocation().getY()), true, 25, 25).send(); - player.getSkills().addExperience(Skills.WOODCUTTING, resource.getExperience()); - player.getSkills().addExperience(Skills.FIREMAKING, resource.getExperience()); - return rollDepletion(); - } + player.getSkills().addExperience(Skills.WOODCUTTING, experience, true); - //actual reward calculations - int reward = resource.getReward(); - int rewardAmount = 0; - if (reward > 0) { - reward = calculateReward(reward); // calculate rewards - rewardAmount = calculateRewardAmount(reward); // calculate amount + //send the message for the resource reward + player.getPacketDispatch().sendMessage("You get some " + ItemDefinition.forId(reward).getName().toLowerCase() + "."); + //give the reward + player.getInventory().add(new Item(reward, rewardAmount)); + player.dispatch(new ResourceProducedEvent(reward, rewardAmount, node, -1)); + int cutLogs = player.getAttribute(STATS_BASE + ":" + STATS_LOGS,0); + player.setAttribute("/save:" + STATS_BASE + ":" + STATS_LOGS,++cutLogs); - //add experience - double experience = calculateExperience(resource.reward, rewardAmount); + //calculate bonus bird nest for mining + int chance = 282; + if (RandomFunction.random(chance) == chance / 2) { + if(SkillcapePerks.isActive(SkillcapePerks.NEST_HUNTER,player)){ + if(!player.getInventory().add(BirdNest.getRandomNest(false).getNest())){ + BirdNest.drop(player); + } + } else { + BirdNest.drop(player); + } + } - player.getSkills().addExperience(Skills.WOODCUTTING, experience, true); + } - //send the message for the resource reward - player.getPacketDispatch().sendMessage("You get some " + ItemDefinition.forId(reward).getName().toLowerCase() + "."); - //give the reward - player.getInventory().add(new Item(reward, rewardAmount)); - player.dispatch(new ResourceProducedEvent(reward, rewardAmount, node, -1)); - int cutLogs = player.getAttribute(STATS_BASE + ":" + STATS_LOGS,0); - player.setAttribute("/save:" + STATS_BASE + ":" + STATS_LOGS,++cutLogs); + return rollDepletion(); + } - //calculate bonus bird nest for mining - int chance = 282; - if (RandomFunction.random(chance) == chance / 2) { - if(SkillcapePerks.isActive(SkillcapePerks.NEST_HUNTER,player)){ - if(!player.getInventory().add(BirdNest.getRandomNest(false).getNest())){ - BirdNest.drop(player); - } - } else { - BirdNest.drop(player); - } - } + private boolean rollDepletion() { + //transform to depleted version + //OSRS and RS3 Wikis both agree: All trees present in 2009 are a 1/8 fell chance, aside from normal trees/dead trees which are 100% + //OSRS: https://oldschool.runescape.wiki/w/Woodcutting scroll down to the mechanics section + //RS3 : https://runescape.wiki/w/Woodcutting scroll down to the mechanics section, and expand the tree felling chances table + if (resource.getRespawnRate() > 0) { + if (RandomFunction.roll(8) || resource.identifier == 1 || resource.identifier == 2 || resource.identifier == 3 || resource.identifier == 6) { + if (resource.isFarming()) { + FarmingPatch fPatch = FarmingPatch.forObject(node.asScenery()); + if(fPatch != null) { + Patch patch = fPatch.getPatchFor(player, true); + patch.setCurrentState(patch.getCurrentState() + 1); + } + return true; + } + if (resource.getEmptyId() > -1) { + SceneryBuilder.replace(node, node.transform(resource.getEmptyId()), resource.getRespawnDuration()); + } else { + SceneryBuilder.replace(node, node.transform(0), resource.getRespawnDuration()); + } + node.setActive(false); - } + playAudio(player, Sounds.TREE_FALLING_2734); + return true; + } + } + return false; + } - return rollDepletion(); - } + private int calculateRewardAmount(int reward) { + int amount = 1; - private boolean rollDepletion() { - //transform to depleted version - //OSRS and RS3 Wikis both agree: All trees present in 2009 are a 1/8 fell chance, aside from normal trees/dead trees which are 100% - //OSRS: https://oldschool.runescape.wiki/w/Woodcutting scroll down to the mechanics section - //RS3 : https://runescape.wiki/w/Woodcutting scroll down to the mechanics section, and expand the tree felling chances table - if (resource.getRespawnRate() > 0) { - if (RandomFunction.roll(8) || resource.identifier == 1 || resource.identifier == 2 || resource.identifier == 3 || resource.identifier == 6) { - if (resource.isFarming()) { - FarmingPatch fPatch = FarmingPatch.forObject(node.asScenery()); - if(fPatch != null) { - Patch patch = fPatch.getPatchFor(player, true); - patch.setCurrentState(patch.getCurrentState() + 1); - } - return true; - } - if (resource.getEmptyId() > -1) { - SceneryBuilder.replace(node, node.transform(resource.getEmptyId()), resource.getRespawnDuration()); - } else { - SceneryBuilder.replace(node, node.transform(0), resource.getRespawnDuration()); - } - node.setActive(false); + // 3239: Hollow tree (bark) 10% chance of obtaining + if (reward == 3239 && RandomFunction.random(100) >= 10) { + amount = 0; + } - playAudio(player, Sounds.TREE_FALLING_2734); - return true; - } - } - return false; - } + // Seers village medium reward - extra normal log while in seer's village + if (reward == 1511 + && player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(1) + && player.getLocation().getRegionId() == 10806) { + amount = 2; + } - private int calculateRewardAmount(int reward) { - int amount = 1; + return amount; + } - // 3239: Hollow tree (bark) 10% chance of obtaining - if (reward == 3239 && RandomFunction.random(100) >= 10) { - amount = 0; - } + private double calculateExperience(int reward, int amount) { + double experience = resource.getExperience(); - // Seers village medium reward - extra normal log while in seer's village - if (reward == 1511 - && player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(1) - && player.getViewport().getRegion().getId() == 10806) { - amount = 2; - } + if(player.getLocation().getRegionId() == 10300){ + return 1.0; + } - return amount; - } + // Bark + if (reward == 3239) { + // If we receive the item, give the full experience points otherwise give the base amount + if (amount >= 1) { + experience = 275.2; + } else { + amount = 1; + } + } - private double calculateExperience(int reward, int amount) { - double experience = resource.getExperience(); + // Seers village medium reward - extra 10% xp from maples while wearing headband + if (reward == 1517 + && player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(1) + && player.getEquipment().get(EquipmentContainer.SLOT_HAT) != null + && player.getEquipment().get(EquipmentContainer.SLOT_HAT).getId() == 14631) { + experience *= 1.10; + } - if(player.getLocation().getRegionId() == 10300){ - return 1.0; - } + return experience * amount; + } - // Bark - if (reward == 3239) { - // If we receive the item, give the full experience points otherwise give the base amount - if (amount >= 1) { - experience = 275.2; - } else { - amount = 1; - } - } + private int calculateReward(int reward) { + return reward; + } - // Seers village medium reward - extra 10% xp from maples while wearing headband - if (reward == 1517 - && player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(1) - && player.getEquipment().get(EquipmentContainer.SLOT_HAT) != null - && player.getEquipment().get(EquipmentContainer.SLOT_HAT).getId() == 14631) { - experience *= 1.10; - } - - return experience * amount; - } - - private int calculateReward(int reward) { - return reward; - } - - /** - * Checks if the player gets rewarded. - * - * @return {@code True} if so. - */ - private boolean checkReward(SkillingTool tool) { - int skill = Skills.WOODCUTTING; - int level = player.getSkills().getLevel(skill) + player.getFamiliarManager().getBoost(skill); - double hostRatio = RandomFunction.randomDouble(100.0); - double lowMod = tool == SkillingTool.BLACK_AXE ? resource.tierModLow / 2 : resource.tierModLow; - double low = resource.baseLow + (tool.ordinal() * lowMod); - double highMod = tool == SkillingTool.BLACK_AXE ? resource.tierModHigh / 2 : resource.tierModHigh; - double high = resource.baseHigh + (tool.ordinal() * highMod); - double clientRatio = RandomFunction.getSkillSuccessChance(low,high,level); - return hostRatio < clientRatio; - } + /** + * Checks if the player gets rewarded. + * + * @return {@code True} if so. + */ + private boolean checkReward(SkillingTool tool) { + int skill = Skills.WOODCUTTING; + int level = player.getSkills().getLevel(skill) + player.getFamiliarManager().getBoost(skill); + double hostRatio = RandomFunction.randomDouble(100.0); + double lowMod = tool == SkillingTool.BLACK_AXE ? resource.tierModLow / 2 : resource.tierModLow; + double low = resource.baseLow + (tool.ordinal() * lowMod); + double highMod = tool == SkillingTool.BLACK_AXE ? resource.tierModHigh / 2 : resource.tierModHigh; + double high = resource.baseHigh + (tool.ordinal() * highMod); + double clientRatio = RandomFunction.getSkillSuccessChance(low,high,level); + return hostRatio < clientRatio; + } } diff --git a/Server/src/main/content/global/skill/hunter/implings/ImplingData.kt b/Server/src/main/content/global/skill/hunter/implings/ImplingData.kt index affe2032c..e2b8df17b 100644 --- a/Server/src/main/content/global/skill/hunter/implings/ImplingData.kt +++ b/Server/src/main/content/global/skill/hunter/implings/ImplingData.kt @@ -173,6 +173,6 @@ enum class ImplingSpawnLocations (val type: ImplingSpawnTypes, vararg val locati object ImplingClipper : ClipMaskSupplier { override fun getClippingFlag (z: Int, x: Int, y: Int) : Int { var flag = RegionManager.getClippingFlag(z, x, y) - return flag and (RegionFlags.SOLID_TILE.inv()) and (RegionFlags.TILE_OBJECT.inv()) //Allow walking on water and flying over small objects, but keep all other tile flags the same. + return flag and (ChunkFlags.SOLID_TILE.inv()) and (ChunkFlags.TILE_OBJECT.inv()) //Allow walking on water and flying over small objects, but keep all other tile flags the same. } } diff --git a/Server/src/main/content/global/skill/magic/lunar/HealSpell.java b/Server/src/main/content/global/skill/magic/lunar/HealSpell.java index f79c85728..82b036755 100644 --- a/Server/src/main/content/global/skill/magic/lunar/HealSpell.java +++ b/Server/src/main/content/global/skill/magic/lunar/HealSpell.java @@ -2,6 +2,7 @@ package content.global.skill.magic.lunar; import core.game.node.entity.combat.spell.MagicSpell; import core.game.node.entity.combat.spell.Runes; +import core.game.world.repository.Repository; import core.plugin.Initializable; import core.game.node.entity.skill.Skills; import core.game.node.Node; @@ -111,14 +112,14 @@ public final class HealSpell extends MagicSpell { playGlobalAudio(o.getLocation(), Sounds.LUNAR_HEAL_OTHER_INDIVIDUAL_2892); o.graphics(GRAPHICS); } else { - List players = RegionManager.getLocalPlayers(player, 1); - if (!super.meetsRequirements(player, true, true)) { + if (!super.meetsRequirements(player, true, true)) { return false; } int percentage = (int) Math.ceil(player.getSkills().getLifepoints() * 0.75); + List players = RegionManager.getLocalPlayers(player.getLocation(), 1); for (Iterator it = players.iterator(); it.hasNext();) { Player p = it.next(); - if (p == player || !p.getSettings().isAcceptAid() || !p.isActive() || p.getSkills().getLifepoints() == p.getSkills().getMaximumLifepoints()) { + if (p.getName() == player.getName() || !p.getSettings().isAcceptAid() || !p.isActive() || p.getSkills().getLifepoints() == p.getSkills().getMaximumLifepoints()) { it.remove(); } } diff --git a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt index 8d70f99cb..c32a4b69d 100644 --- a/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt +++ b/Server/src/main/content/global/skill/magic/lunar/LunarListeners.kt @@ -497,16 +497,16 @@ class LunarListeners : SpellListener("lunar"), Commands { removeRunes(player, true) visualizeSpell(player, Animations.LUNAR_SPELLBOOK_CURE_GROUP_4409, Graphics.LUNAR_SPELLBOOK_CURE_GROUP_744, 130, Sounds.LUNAR_CURE_GROUP_2882) curePoison(player) - for(acct in RegionManager.getLocalPlayers(player, 1)) { - if(!acct.isActive || acct.locks.isInteractionLocked) { + for (player in RegionManager.getLocalPlayers(player.location, 1)) { + if (!player.isActive || player.locks.isInteractionLocked) { continue } - if(!acct.settings.isAcceptAid) { + if (!player.settings.isAcceptAid) { continue } - curePoison(acct) - sendMessage(acct, "You have been cured of poison.") - visualizeSpell(acct, -1, Graphics.LUNAR_SPELLBOOK_CURE_GROUP_744, 130, Sounds.LUNAR_CURE_OTHER_INDIVIDUAL_2889) + curePoison(player) + sendMessage(player, "You have been cured of poison.") + visualizeSpell(player, -1, Graphics.LUNAR_SPELLBOOK_CURE_GROUP_744, 130, Sounds.LUNAR_CURE_OTHER_INDIVIDUAL_2889) } addXP(player, 74.0) } @@ -818,12 +818,12 @@ class LunarListeners : SpellListener("lunar"), Commands { } private fun sendGroupTeleport(player: Player, xp: Double, destName: String, loc: Location){ - RegionManager.getLocalPlayers(player, 1).forEach { - if(it == player) return@forEach - if(it.isTeleBlocked) return@forEach - if(!it.isActive) return@forEach - if(!it.settings.isAcceptAid) return@forEach - if(it.ironmanManager.isIronman) return@forEach + RegionManager.getLocalPlayers(player.location, 1).forEach { + if (it.name == player.name) return@forEach + if (it.isTeleBlocked) return@forEach + if (!it.isActive) return@forEach + if (!it.settings.isAcceptAid) return@forEach + if (it.ironmanManager.isIronman) return@forEach setAttribute(it, "t-o_location", loc) openInterface(it, Components.TELEPORT_OTHER_326) setInterfaceText(it, player.username, Components.TELEPORT_OTHER_326, 1) diff --git a/Server/src/main/content/global/skill/magic/lunar/StatBoostSpell.java b/Server/src/main/content/global/skill/magic/lunar/StatBoostSpell.java index 61aeee5f7..d86f83b07 100644 --- a/Server/src/main/content/global/skill/magic/lunar/StatBoostSpell.java +++ b/Server/src/main/content/global/skill/magic/lunar/StatBoostSpell.java @@ -12,6 +12,7 @@ import core.game.bots.AIPlayer; import core.game.node.entity.player.link.SpellBookManager.SpellBook; import core.game.node.item.Item; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.plugin.Initializable; @@ -52,19 +53,17 @@ public final class StatBoostSpell extends MagicSpell { player.getPacketDispatch().sendMessage("You can't cast this spell on that item."); return false; } - List pl = RegionManager.getLocalPlayers(player, 1); - int plSize = pl.size() - 1; + List pl = RegionManager.getLocalPlayers(player.getLocation(), 1); int doses = potion.getDose(item); - if (pl.size() == 0) { + if (pl.isEmpty()) { return false; } if (!super.meetsRequirements(player, true, false)) { return false; } int size = 0; - for (Player players : pl) { - Player o = (Player) players; - if (size >= doses) break; + for (Player o : pl) { + if (size >= doses) break; if (!o.isActive() || o.getLocks().isInteractionLocked() || o == player) { continue; } @@ -86,11 +85,11 @@ public final class StatBoostSpell extends MagicSpell { player.animate(ANIMATION); player.graphics(GRAPHICS); player.getInventory().remove(item); - int newIndex = (potion.getIds().length - doses) + size; - if (newIndex > potion.getIds().length - 1) { - player.getInventory().add(new Item(229)); - return true; - } + int newIndex = (potion.getIds().length - doses) + size; + if (newIndex > potion.getIds().length - 1) { + player.getInventory().add(new Item(229)); + return true; + } player.getInventory().add(new Item(potion.getIds()[newIndex])); return true; } diff --git a/Server/src/main/content/global/skill/magic/lunar/StatRestoreSpell.java b/Server/src/main/content/global/skill/magic/lunar/StatRestoreSpell.java index 1f984d2da..71b9ebf82 100644 --- a/Server/src/main/content/global/skill/magic/lunar/StatRestoreSpell.java +++ b/Server/src/main/content/global/skill/magic/lunar/StatRestoreSpell.java @@ -2,6 +2,7 @@ package content.global.skill.magic.lunar; import content.data.consumables.Consumables; import core.game.consumable.Potion; +import core.game.world.repository.Repository; import core.plugin.Initializable; import core.game.node.entity.combat.spell.MagicSpell; import core.game.node.entity.combat.spell.Runes; @@ -27,7 +28,7 @@ public class StatRestoreSpell extends MagicSpell { private static final Animation ANIMATION = new Animation(4413); private static final Graphics GRAPHICS = new Graphics(733, 130); - private static final Consumables[] acceptedPotions = new Consumables[] { Consumables.RESTORE, Consumables.SUPER_RESTO, Consumables.PRAYER, Consumables.ENERGY, Consumables.SUPER_ENERGY }; + private static final Consumables[] acceptedPotions = new Consumables[] { Consumables.RESTORE, Consumables.SUPER_RESTO, Consumables.PRAYER, Consumables.ENERGY, Consumables.SUPER_ENERGY }; public StatRestoreSpell() { super(SpellBook.LUNAR, 81, 84, null, null, null, new Item[] { new Item(Runes.ASTRAL_RUNE.getId(), 2), new Item(Runes.EARTH_RUNE.getId(), 10), new Item(Runes.WATER_RUNE.getId(), 10) }); @@ -45,34 +46,32 @@ public class StatRestoreSpell extends MagicSpell { Item item = ((Item) target); player.getInterfaceManager().setViewedTab(6); - if (Consumables.getConsumableById(item.getId()) == null) { - player.getPacketDispatch().sendMessage("You can only cast this spell on a potion."); - return false; - } + if (Consumables.getConsumableById(item.getId()) == null) { + player.getPacketDispatch().sendMessage("You can only cast this spell on a potion."); + return false; + } final Potion potion = (Potion) Consumables.getConsumableById(item.getId()).getConsumable(); if (potion == null) { - player.getPacketDispatch().sendMessage("You can only cast this spell on a potion."); + player.getPacketDispatch().sendMessage("You can only cast this spell on a potion."); return false; } if (!item.getDefinition().isTradeable() || !isRestore(potion)) { player.getPacketDispatch().sendMessage("You can't cast this spell on that item."); return false; } - List pl = RegionManager.getLocalPlayers(player, 2); - int plSize = pl.size() - 1; + List pl = RegionManager.getLocalPlayers(player.getLocation(), 2); int doses = potion.getDose(item); - if (pl.size() == 0) { + if (pl.isEmpty()) { return false; } if (!super.meetsRequirements(player, true, false)) { return false; } int size = 0; - for (Player players : pl) { - if (size >= doses) break; - Player o = (Player) players; + for (Player o : pl) { + if (size >= doses) break; if (!o.isActive() || o.getLocks().isInteractionLocked() || o == player) { continue; } @@ -93,20 +92,20 @@ public class StatRestoreSpell extends MagicSpell { player.animate(ANIMATION); player.graphics(GRAPHICS); player.getInventory().remove(item); - int newIndex = (potion.getIds().length - doses) + size; - if (newIndex > potion.getIds().length - 1) { - player.getInventory().add(new Item(229)); - return true; - } + int newIndex = (potion.getIds().length - doses) + size; + if (newIndex > potion.getIds().length - 1) { + player.getInventory().add(new Item(229)); + return true; + } player.getInventory().add(new Item(potion.getIds()[newIndex])); return true; } private boolean isRestore(Potion p) { - for (int i = 0; i < acceptedPotions.length; i++) { - if (p == acceptedPotions[i].getConsumable()) - return true; - } + for (int i = 0; i < acceptedPotions.length; i++) { + if (p == acceptedPotions[i].getConsumable()) + return true; + } return false; } diff --git a/Server/src/main/content/global/skill/summoning/familiar/ForgeRegentNPC.java b/Server/src/main/content/global/skill/summoning/familiar/ForgeRegentNPC.java index 3c560fc41..294a535fd 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/ForgeRegentNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/ForgeRegentNPC.java @@ -152,9 +152,9 @@ public class ForgeRegentNPC extends Familiar { familiar.moveStep(); GroundItemManager.destroy(ground); player.getSkills().addExperience(Skills.FIREMAKING, log.getXp() + 10); - familiar.faceLocation(object.getFaceLocation(familiar.getLocation())); + familiar.faceLocation(object.getFaceLocation(familiar.getLocation())); SceneryBuilder.add(object, log.getLife(), FireMakingPulse.getAsh(player, log, object)); - if (player.getViewport().getRegion().getId() == 10806) { + if (player.getLocation().getRegionId() == 10806) { player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 9); } return true; diff --git a/Server/src/main/content/global/skill/summoning/familiar/GiantChinchompaNPC.java b/Server/src/main/content/global/skill/summoning/familiar/GiantChinchompaNPC.java index c0c57202a..ec8479e9a 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/GiantChinchompaNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/GiantChinchompaNPC.java @@ -56,7 +56,7 @@ public class GiantChinchompaNPC extends Familiar { if (!isOwnerAttackable()) { return false; } - final List entitys = RegionManager.getLocalEntitys(owner, 6); + final List entitys = RegionManager.getLocalEntities(owner.getLocation(), 6); entitys.remove(owner); entitys.remove(this); sendChat("Squeak!"); diff --git a/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java b/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java index c4672b643..fc867c0d3 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/PyreLordNPC.java @@ -133,7 +133,7 @@ public class PyreLordNPC extends Familiar { player.getSkills().addExperience(Skills.FIREMAKING, log.getXp() + 10); familiar.faceLocation(object.getFaceLocation(familiar.getLocation())); SceneryBuilder.add(object, log.getLife(), FireMakingPulse.getAsh(player, log, object)); - if (player.getViewport().getRegion().getId() == 10806) { + if (player.getLocation().getRegionId() == 10806) { player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 9); } return true; diff --git a/Server/src/main/content/global/skill/summoning/familiar/SmokeDevilNPC.java b/Server/src/main/content/global/skill/summoning/familiar/SmokeDevilNPC.java index 49a79fa6a..65f8fea75 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/SmokeDevilNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/SmokeDevilNPC.java @@ -70,7 +70,7 @@ public class SmokeDevilNPC extends Familiar { if (!isOwnerAttackable()) { return false; } - final List entitys = RegionManager.getLocalEntitys(this, 1); + final List entitys = RegionManager.getLocalEntities(location, 1); entitys.remove(this); entitys.remove(owner); visualize(Animation.create(7820), Graphics.create(1375)); diff --git a/Server/src/main/content/global/skill/summoning/familiar/SpiritTzKihNPC.java b/Server/src/main/content/global/skill/summoning/familiar/SpiritTzKihNPC.java index 19f97c6ba..e48196763 100644 --- a/Server/src/main/content/global/skill/summoning/familiar/SpiritTzKihNPC.java +++ b/Server/src/main/content/global/skill/summoning/familiar/SpiritTzKihNPC.java @@ -41,7 +41,7 @@ public class SpiritTzKihNPC extends Familiar { @Override protected boolean specialMove(FamiliarSpecial special) { - final List entitys = RegionManager.getLocalEntitys(owner, 8); + final List entitys = RegionManager.getLocalEntities(owner.getLocation(), 8); if (entitys.size() == 0) { return false; } diff --git a/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java b/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java index 24a387d18..9f5ce24ae 100644 --- a/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java +++ b/Server/src/main/content/global/skill/summoning/pet/KittenInteractDialogue.java @@ -72,7 +72,7 @@ public final class KittenInteractDialogue extends DialoguePlugin { player.sendChat("Go on puss...kill that rat!"); boolean cant = true; NPC rat = null; - for (NPC n : RegionManager.getLocalNpcs(player.getLocation(), 10)) { + for (NPC n : RegionManager.getLocalNPCs(player.getLocation(), 10)) { if (!n.getName().contains("rat")) { cant = false; continue; diff --git a/Server/src/main/content/global/skill/thieving/StallThiefPulse.java b/Server/src/main/content/global/skill/thieving/StallThiefPulse.java index b08185335..b3a5ea755 100644 --- a/Server/src/main/content/global/skill/thieving/StallThiefPulse.java +++ b/Server/src/main/content/global/skill/thieving/StallThiefPulse.java @@ -115,7 +115,7 @@ public final class StallThiefPulse extends SkillPulse { SceneryBuilder.replace(node, node.transform(stall.getEmpty(node.getId())), stall.getDelay()); } final Item item = stall.getRandomLoot(); - player.getInventory().add(item); + player.getInventory().add(item); player.getSkills().addExperience(Skills.THIEVING, stall.getExperience(), true); if (item.getId() == 1987) { player.getPacketDispatch().sendMessage("You steal grapes from the grape stall."); @@ -135,9 +135,9 @@ public final class StallThiefPulse extends SkillPulse { if(stall == Stall.CANDLES) { return; } - if (type == 0) { - player.getPacketDispatch().sendMessage("You attempt to steal some " + stall.msgItem + " from the " + stall.name().toLowerCase().replace('_', ' ')); - } + if (type == 0) { + player.getPacketDispatch().sendMessage("You attempt to steal some " + stall.msgItem + " from the " + stall.name().toLowerCase().replace('_', ' ')); + } } /** @@ -156,7 +156,7 @@ public final class StallThiefPulse extends SkillPulse { player.sendMessage("A higher power smites you"); return false; } - for (NPC npc : RegionManager.getLocalNpcs(player.getLocation(), 8)) { + for (NPC npc : RegionManager.getLocalNPCs(player.getLocation(), 8)) { if (!npc.getProperties().getCombatPulse().isAttacking() && (npc.getId() == 32 || npc.getId() == 2236)) { npc.sendChat("Hey! Get your hands off there!"); npc.getProperties().getCombatPulse().attack(player); diff --git a/Server/src/main/content/minigame/barrows/BarrowsActivityPlugin.java b/Server/src/main/content/minigame/barrows/BarrowsActivityPlugin.java index 48b95f68f..3654658bc 100644 --- a/Server/src/main/content/minigame/barrows/BarrowsActivityPlugin.java +++ b/Server/src/main/content/minigame/barrows/BarrowsActivityPlugin.java @@ -19,8 +19,11 @@ import content.global.skill.summoning.familiar.Familiar; import core.game.node.scenery.Scenery; import core.game.system.task.Pulse; import core.game.world.map.Location; +import core.game.world.map.Region; +import core.game.world.map.RegionChunk; import core.game.world.map.RegionManager; import core.game.world.map.zone.ZoneBorders; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Graphics; import core.net.packet.PacketRepository; import core.net.packet.context.CameraContext; @@ -32,6 +35,7 @@ import core.plugin.Initializable; import core.tools.RandomFunction; import core.game.world.GameWorld; import core.plugin.ClassScanner; +import org.jetbrains.annotations.NotNull; import java.util.stream.IntStream; @@ -84,37 +88,41 @@ public final class BarrowsActivityPlugin extends ActivityPlugin { @Override public boolean pulse() { boolean end = true; - for (Player p : RegionManager.getRegionPlayers(14231)) { - end = false; - int index = p.getAttribute("barrow:drain-index", -1); - if (index > -1) { - p.removeAttribute("barrow:drain-index"); - p.getPacketDispatch().sendItemOnInterface(-1, 1, 24, index); - continue; - } - if (p.getLocation().getZ() == 0 && p.getAttribute("barrow:looted", false) && getWorldTicks() % 3 == 0) { - if (RandomFunction.random(15) == 0) { - p.getImpactHandler().manualHit(p, RandomFunction.random(5), HitsplatType.NORMAL); - Graphics.send(Graphics.create(405), p.getLocation()); + Region region = RegionManager.forId(14231); + Region.load(region); + for (int z = 0; z < 4; z++) { + for (Player p : region.assemblePlayerList(z)) { + end = false; + int index = p.getAttribute("barrow:drain-index", -1); + if (index > -1) { + p.removeAttribute("barrow:drain-index"); + p.getPacketDispatch().sendItemOnInterface(-1, 1, 24, index); + continue; } - } - int drain = 8; + if (p.getLocation().getZ() == 0 && p.getAttribute("barrow:looted", false) && getWorldTicks() % 3 == 0) { + if (RandomFunction.random(15) == 0) { + p.getImpactHandler().manualHit(p, RandomFunction.random(5), HitsplatType.NORMAL); + Graphics.send(Graphics.create(405), p.getLocation()); + } + } + int drain = 8; - //if (p.getLocks().isLocked("barrow:drain") || RandomFunction.random(100) % 2 == 0) { - // continue; - //} - for (boolean killed : p.getSavedData().getActivityData().getBarrowBrothers()) { - if (killed) { - drain += 1; + //if (p.getLocks().isLocked("barrow:drain") || RandomFunction.random(100) % 2 == 0) { + // continue; + //} + for (boolean killed : p.getSavedData().getActivityData().getBarrowBrothers()) { + if (killed) { + drain += 1; + } + } + if (getWorldTicks() % 30 == 0) { + p.getSkills().decrementPrayerPoints(drain); + p.getLocks().lock("barrow:drain", (3 + RandomFunction.random(15)) * 3); + index = 1 + RandomFunction.random(6); + p.setAttribute("barrow:drain-index", index); + p.getPacketDispatch().sendItemZoomOnInterface(4761 + RandomFunction.random(12), 100, 24, index); + p.getPacketDispatch().sendAnimationInterface(9810, 24, index); } - } - if(getWorldTicks() % 30 == 0){ - p.getSkills().decrementPrayerPoints(drain); - p.getLocks().lock("barrow:drain", (3 + RandomFunction.random(15)) * 3); - index = 1 + RandomFunction.random(6); - p.setAttribute("barrow:drain-index", index); - p.getPacketDispatch().sendItemZoomOnInterface(4761 + RandomFunction.random(12), 100, 24, index); - p.getPacketDispatch().sendAnimationInterface(9810, 24, index); } } return end; @@ -130,7 +138,7 @@ public final class BarrowsActivityPlugin extends ActivityPlugin { @Override public void locationUpdate(Entity e, Location last) { - if (e instanceof Player && e.getViewport().getRegion().getId() == 14231) { + if (e instanceof Player && e.getLocation().getRegionId() == 14231) { boolean tunnel = false; for (ZoneBorders border : MINI_TUNNELS) { if (border.insideBorder(e)) { @@ -140,7 +148,7 @@ public final class BarrowsActivityPlugin extends ActivityPlugin { } Player player = (Player) e; if ((getVarp(player, 1270) == 1) != tunnel) { - setVarp(player, 1270, tunnel ? 3 : 0, true); + setVarp(player, 1270, tunnel ? 3 : 0, true); } } } @@ -213,7 +221,7 @@ public final class BarrowsActivityPlugin extends ActivityPlugin { public static void shuffleCatacombs(Player player) { int value = TUNNEL_CONFIGS[RandomFunction.random(TUNNEL_CONFIGS.length)]; value |= 1 << (6 + RandomFunction.random(4)); - setVarp(player, 452, value); + setVarp(player, 452, value); } @Override @@ -293,10 +301,10 @@ public final class BarrowsActivityPlugin extends ActivityPlugin { return true; case 6774: player.lock(1); - int brother = player.getSavedData().getActivityData().getBarrowTunnelIndex(); - if (!player.getSavedData().getActivityData().getBarrowBrothers()[brother] && !player.getAttribute("brother:" + brother, false)) { - BarrowsCrypt.getCrypt(brother).spawnBrother(player, RegionManager.getTeleportLocation(target.getCenterLocation(), 4)); - } + int brother = player.getSavedData().getActivityData().getBarrowTunnelIndex(); + if (!player.getSavedData().getActivityData().getBarrowBrothers()[brother] && !player.getAttribute("brother:" + brother, false)) { + BarrowsCrypt.getCrypt(brother).spawnBrother(player, RegionManager.getTeleportLocation(target.getCenterLocation(), 4)); + } player.setAttribute("barrow:opened_chest", true); sendConfiguration(player); return true; @@ -335,7 +343,7 @@ public final class BarrowsActivityPlugin extends ActivityPlugin { if (player.getAttribute("barrow:opened_chest", false)) { config |= 1 << 16; } - setVarp(player, 453, config); + setVarp(player, 453, config); } @Override diff --git a/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java b/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java index 72728d1e6..00486fad4 100644 --- a/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java +++ b/Server/src/main/content/minigame/mta/TelekineticGrabSpell.java @@ -100,8 +100,9 @@ public final class TelekineticGrabSpell extends MagicSpell { @Override public boolean cast(final Entity entity, final Node target) { - if (!(target instanceof GroundItem)) - return false; + if (!(target instanceof GroundItem)) { + return false; + } final GroundItem ground = (GroundItem) target; if (!canCast(entity, ground)) { return false; @@ -131,32 +132,34 @@ public final class TelekineticGrabSpell extends MagicSpell { Player player = entity instanceof Player ? (Player) entity : null; GroundItem g = GroundItemManager.get(ground.getId(), ground.getLocation(), player); if (g == null) { - player.getPacketDispatch().sendMessage("Too late!"); + if (player != null) { + player.getPacketDispatch().sendMessage("Too late!"); + } return true; } - if (g == SpecialGroundItems.AHAB_BEER.asGroundItem()){ - player.getDialogueInterpreter().open(2692, new NPC(2692), true); + if (g == SpecialGroundItems.AHAB_BEER.asGroundItem()) { + if (player != null) { + player.getDialogueInterpreter().open(2692, new NPC(2692), true); + } return true; } if (player == null) { return true; } boolean teleZone = player.getZoneMonitor().isInZone("Telekinetic Theatre") && g.getId() == 6888; - if (player != null) { - if (g == null || !g.isActive()) { - player.getPacketDispatch().sendMessage("Too late!"); - return true; - } - playAudio(player, Sounds.VULNERABILITY_IMPACT_3008); - if (!teleZone) { - player.getInventory().add(new Item(g.getId(), g.getAmount(), g.getCharge())); - } else { - TelekineticZone zone = TelekineticZone.getZone(player); - zone.moveStatue(); - player.lock(getDelay()); - } - player.getPacketDispatch().sendPositionedGraphics(END_GRAPHIC, ground.getLocation()); + if (!g.isActive()) { + player.getPacketDispatch().sendMessage("Too late!"); + return true; } + playAudio(player, Sounds.VULNERABILITY_IMPACT_3008); + if (!teleZone) { + player.getInventory().add(new Item(g.getId(), g.getAmount(), g.getCharge())); + } else { + TelekineticZone zone = TelekineticZone.getZone(player); + zone.moveStatue(); + player.lock(getDelay()); + } + player.getPacketDispatch().sendPositionedGraphics(END_GRAPHIC, ground.getLocation()); if (!teleZone) { GroundItemManager.destroy(g); } diff --git a/Server/src/main/content/minigame/pestcontrol/PCObjectHandler.java b/Server/src/main/content/minigame/pestcontrol/PCObjectHandler.java index 741bbc4df..650842a1f 100644 --- a/Server/src/main/content/minigame/pestcontrol/PCObjectHandler.java +++ b/Server/src/main/content/minigame/pestcontrol/PCObjectHandler.java @@ -140,7 +140,7 @@ public final class PCObjectHandler extends OptionHandler { handleTurretTower(player, session, object); return true; } - if (!object.isActive() || !session.getBarricades().contains(object)) { + if (!object.isActive() || (getObjectType(object.getId()) == 9 && !session.getBarricades().contains(object))) { return true; } if (option.equals("repair")) { // Handle barricades @@ -229,16 +229,15 @@ public final class PCObjectHandler extends OptionHandler { int dir = open ? object.getRotation() : rotation; Direction direction = Direction.get(!open ? dir : ((3 + dir) % 4)); if (session.getBarricades().contains(object) && session.getBarricades().contains(second)) { - session.getBarricades().remove(object); - session.getBarricades().remove(second); - Location l = object.getLocation().transform(direction.getStepX(), direction.getStepY(), 0); Scenery replacement = new Scenery(object.getId() + (open ? 1 : -1), l, 0, open ? rotation : ((direction.toInteger() + 3) % 4)); + session.getBarricades().remove(object); SceneryBuilder.replace(object, replacement); session.getBarricades().add(replacement); l = second.getLocation().transform(direction.getStepX(), direction.getStepY(), 0); replacement = new Scenery(second.getId() + (open ? 1 : -1), l, 0, open ? getRotation(second) : ((direction.toInteger() + 3) % 4)); + session.getBarricades().remove(second); SceneryBuilder.replace(second, replacement); session.getBarricades().add(replacement); } @@ -295,7 +294,7 @@ public final class PCObjectHandler extends OptionHandler { * @param objectId The object id. * @return The object type. */ - private static int getObjectType(int objectId) { + static int getObjectType(int objectId) { if (objectId == 14225 || objectId == 14226 || objectId == 14228 || objectId == 14229) { return 9; } diff --git a/Server/src/main/content/minigame/pestcontrol/PCPortalNPC.java b/Server/src/main/content/minigame/pestcontrol/PCPortalNPC.java index 0bddb9a24..b28fa05c2 100644 --- a/Server/src/main/content/minigame/pestcontrol/PCPortalNPC.java +++ b/Server/src/main/content/minigame/pestcontrol/PCPortalNPC.java @@ -8,12 +8,9 @@ import core.game.node.entity.combat.BattleState; import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; -import core.game.world.map.Direction; -import core.game.world.map.Location; -import core.game.world.map.RegionPlane; +import core.game.world.map.*; import core.game.world.update.flag.context.Animation; import core.tools.RandomFunction; -import content.minigame.pestcontrol.monsters.PCRavagerNPC; import content.minigame.pestcontrol.monsters.PCSpinnerNPC; /** @@ -146,8 +143,8 @@ public final class PCPortalNPC extends AbstractNPC { public void tick() { super.tick(); if (session != null) { - RegionPlane plane = getViewport().getCurrentPlane(); - if (plane != null && session.getTicks() % 35 - plane.getPlayers().size() == 0 && plane.getNpcs().size() < 100) { + Region region = RegionManager.forId(location.getRegionId()); + if (session.getTicks() % 35 - region.assemblePlayerList(0).size() == 0 && region.assembleNpcList(0).size() < 100) { spawnNPCs(); } if (updateLifepoints && session.getTicks() % 10 == 0) { @@ -187,9 +184,7 @@ public final class PCPortalNPC extends AbstractNPC { int index = getDifficultyIndex(); Random r = RandomFunction.RANDOM; int amount = index + 1; - if (getViewport().getCurrentPlane() != null) { - amount += getViewport().getCurrentPlane().getPlayers().size() / 10; - } + amount += RegionManager.getLocalPlayers(location).size() / 10; if (getDifficultyIndex() == 0) { amount += ((getDifficultyIndex() + 1) * 3) / 2; } diff --git a/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java b/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java index f1fb680a0..a570ede1c 100644 --- a/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java +++ b/Server/src/main/content/minigame/pestcontrol/PestControlActivityPlugin.java @@ -20,10 +20,12 @@ import core.game.node.item.Item; import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; +import core.game.world.map.RegionChunk; import core.game.world.map.build.DynamicRegion; import core.game.world.map.zone.RegionZone; import core.game.world.map.zone.ZoneBuilder; import core.game.world.map.zone.ZoneRestriction; +import core.game.world.repository.Repository; import core.plugin.Initializable; import core.plugin.ClassScanner; import core.tools.RandomFunction; @@ -125,40 +127,48 @@ public final class PestControlActivityPlugin extends ActivityPlugin { if (!session.isActive()) { return; } - for (final Player p : session.getRegion().getPlanes()[0].getPlayers()) { - p.getProperties().setTeleportLocation(getLeaveLocation()); - if (!success) { - p.getDialogueInterpreter().open(3781, true, 0, true); - // default, - // type, - // default - } else if (success && p.getAttribute("pc_zeal", 0) >= 50) { - int amount = type.ordinal() + 2; - p.getSavedData().getActivityData().increasePestPoints(amount); - Item coins = new Item(995, p.getProperties().getCurrentCombatLevel() * 10); - if (!p.getInventory().add(coins)) { - GroundItemManager.create(coins, p); + RegionChunk[][][] chunks = session.getRegion().getChunks(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + RegionChunk chunk = chunks[x][y][z]; + for (Player p : chunk.getPlayers()) { + p.getProperties().setTeleportLocation(getLeaveLocation()); + if (!success) { + p.getDialogueInterpreter().open(3781, true, 0, true); + // default, + // type, + // default + } else if (p.getAttribute("pc_zeal", 0) >= 50) { + int amount = type.ordinal() + 2; + p.getSavedData().getActivityData().increasePestPoints(amount); + Item coins = new Item(995, p.getProperties().getCurrentCombatLevel() * 10); + if (!p.getInventory().add(coins)) { + GroundItemManager.create(coins, p); + } + // default, type, name + p.getDialogueInterpreter().open(3781, true, 1, type.ordinal() == 0 ? "two" : type.ordinal() == 1 ? "three" : "four"); + } else { + // default type, default + p.getDialogueInterpreter().open(3781, true, 2, true); + } + p.removeAttribute("pc_zeal"); + p.removeExtension(PestControlSession.class); + p.fullRestore(); + if (isPoisoned(p)) { + curePoison(p); + } + PulseManager.cancelDeathTask(p); + GameWorld.getPulser().submit(new Pulse(1, p) { + @Override + public boolean pulse() { + p.getSkills().restore(); + return true; + } + }); + } } - // default, type, name - p.getDialogueInterpreter().open(3781, true, 1, type.ordinal() == 0 ? "two" : type.ordinal() == 1 ? "three" : "four"); - } else { - // default type, default - p.getDialogueInterpreter().open(3781, true, 2, true); } - p.removeAttribute("pc_zeal"); - p.removeExtension(PestControlSession.class); - p.fullRestore(); - if (isPoisoned(p)) { - curePoison(p); - } - PulseManager.cancelDeathTask(p); - GameWorld.getPulser().submit(new Pulse(1, p) { - @Override - public boolean pulse() { - p.getSkills().restore(); - return true; - } - }); } session.getRegion().getRegionZones().clear(); session.setActive(false); @@ -293,7 +303,7 @@ public final class PestControlActivityPlugin extends ActivityPlugin { @Override public boolean death(Entity e, Entity killer) { - if (e instanceof Player && e.getViewport().getRegion().getRegionId() == 10536) { + if (e instanceof Player && e.getLocation().getRegion().getRegionId() == 10536) { PestControlSession session = e.getExtension(PestControlSession.class); if (session != null) { Location l = session.getRegion().getBaseLocation(); diff --git a/Server/src/main/content/minigame/pestcontrol/PestControlSession.java b/Server/src/main/content/minigame/pestcontrol/PestControlSession.java index 8396f97b8..f24197b85 100644 --- a/Server/src/main/content/minigame/pestcontrol/PestControlSession.java +++ b/Server/src/main/content/minigame/pestcontrol/PestControlSession.java @@ -8,8 +8,6 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; import core.game.world.map.Location; -import core.game.world.map.Point; -import core.game.world.map.RegionPlane; import core.game.world.map.build.DynamicRegion; import core.tools.RandomFunction; @@ -21,12 +19,6 @@ import static core.api.ContentAPIKt.*; * @author Emperor */ public final class PestControlSession { - - /** - * The barricade object offsets. - */ - private static final Point[] OBJECT_OFFSETS = { new Point(46, 33), new Point(46, 32), new Point(32, 25), new Point(33, 25), new Point(19, 32), new Point(19, 33), new Point(49, 33), new Point(49, 32), new Point(49, 31), new Point(49, 30), new Point(52, 27), new Point(52, 26), new Point(52, 25), new Point(52, 24), new Point(52, 14), new Point(52, 13), new Point(52, 12), new Point(52, 11), new Point(42, 18), new Point(43, 18), new Point(44, 18), new Point(45, 18), new Point(32, 15), new Point(33, 15), new Point(34, 15), new Point(35, 15), new Point(23, 18), new Point(24, 18), new Point(25, 18), new Point(26, 18), new Point(13, 11), new Point(13, 12), new Point(13, 13), new Point(13, 14), new Point(12, 28), new Point(12, 29), new Point(12, 30), new Point(12, 31), }; - /** * The object ids of non-attackable barricades/gates. */ @@ -123,7 +115,7 @@ public final class PestControlSession { * @param message The message to send. */ public void sendMessage(String message) { - for (Player p : region.getPlanes()[0].getPlayers()) { + for (Player p : region.assemblePlayerList(0)) { if (p.isActive()) { p.getPacketDispatch().sendMessage(message); } @@ -136,7 +128,7 @@ public final class PestControlSession { * @param child The child id. */ public void sendString(String message, int child) { - for (Player p : region.getPlanes()[0].getPlayers()) { + for (Player p : region.assemblePlayerList(0)) { if (p.isActive()) { p.getPacketDispatch().sendString(message, 408, child); } @@ -164,9 +156,9 @@ public final class PestControlSession { * @param value The message value to send. */ public void sendConfig(int value) { - for (Player p : region.getPlanes()[0].getPlayers()) { + for (Player p : region.assemblePlayerList(0)) { if (p.isActive()) { - setVarp(p, 719, value); + setVarp(p, 719, value); } } } @@ -191,7 +183,7 @@ public final class PestControlSession { message = "The red, south-western portal shield has dropped!"; break; } - for (Player p : region.getPlanes()[0].getPlayers()) { + for (Player p : region.assemblePlayerList(0)) { if (p.isActive()) { p.getPacketDispatch().sendInterfaceConfig(408, 18 + (index << 1), true); p.getPacketDispatch().sendMessage(message); @@ -233,8 +225,7 @@ public final class PestControlSession { } } - for (Player p : remainingPlayers) - { + for (Player p : remainingPlayers) { int priority = p.getAttribute("pc_prior", 0) + 1; p.getPacketDispatch().sendMessage("You have been given priority level " + priority + " over other players in joining the next"); p.getPacketDispatch().sendMessage("game."); @@ -264,7 +255,7 @@ public final class PestControlSession { Random r = RandomFunction.RANDOM; Location l = region.getBaseLocation(); p.getProperties().setTeleportLocation(l.transform(32 + r.nextInt(4), 49 + r.nextInt(6), 0)); - setVarp(p, 1147, 0); + setVarp(p, 1147, 0); p.getDialogueInterpreter().sendDialogues(3781, FacialExpression.FURIOUS, "You must defend the Void Knight while the portals are", "unsummoned. The ritual takes twenty minutes though,", "so you can help out by destroying them yourselves!", "Now GO GO GO!"); } @@ -272,9 +263,17 @@ public final class PestControlSession { * Initializes the barricades list. */ private void initBarricadesList() { - RegionPlane p = region.getPlanes()[0]; - for (Point point : OBJECT_OFFSETS) { - barricades.add(p.getObjects()[point.getX()][point.getY()]); + for (int chunkX = 0; chunkX < 8; chunkX++) { + for (int chunkY = 0; chunkY < 8; chunkY++) { + List objects = region.getChunks()[chunkX][chunkY][0].assembleObjectList(); + for (Scenery object : objects) { + boolean isActualBarricade = PCObjectHandler.getObjectType(object.getId()) == 9; + boolean isGate = object.getId() > 14232; + if (isActualBarricade || isGate) { + barricades.add(object); + } + } + } } } @@ -385,5 +384,4 @@ public final class PestControlSession { public List getBarricades() { return barricades; } - } diff --git a/Server/src/main/content/minigame/pestcontrol/SquireDialogue.java b/Server/src/main/content/minigame/pestcontrol/SquireDialogue.java index c0e7ca1de..c1c2a11c7 100644 --- a/Server/src/main/content/minigame/pestcontrol/SquireDialogue.java +++ b/Server/src/main/content/minigame/pestcontrol/SquireDialogue.java @@ -46,7 +46,7 @@ public class SquireDialogue extends DialoguePlugin { interpreter.sendDialogues(3781, FacialExpression.HALF_GUILTY, "Congratulations! You managed to destroy all the portals!", "We've awarded you " + points + " Void Knight Commendation", "points. Please also accept these coins as a reward."); stage = 100; } else {// won and not awarded. - interpreter.sendDialogues(3781, FacialExpression.HALF_GUILTY, "Congratulations! You managed to destroy all the portals!", "However, you did not succeed in reaching the required", "amount of damage delt we cannot grant you a reward."); + interpreter.sendDialogues(3781, FacialExpression.HALF_GUILTY, "Congratulations! You managed to destroy all the portals!", "However, you did not succeed in reaching the required", "amount of damage dealt we cannot grant you a reward."); stage = 101; } return true; diff --git a/Server/src/main/content/minigame/pestcontrol/VoidSealPlugin.java b/Server/src/main/content/minigame/pestcontrol/VoidSealPlugin.java index 95244ea66..d6c475b5b 100644 --- a/Server/src/main/content/minigame/pestcontrol/VoidSealPlugin.java +++ b/Server/src/main/content/minigame/pestcontrol/VoidSealPlugin.java @@ -29,7 +29,7 @@ public final class VoidSealPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { - if (player.getViewport().getRegion().getRegionId() != 10536) { + if (player.getLocation().getRegionId() != 10536) { player.getPacketDispatch().sendMessage("You can only use the seal in Pest Control."); return true; } @@ -48,7 +48,7 @@ public final class VoidSealPlugin extends OptionHandler { player.getInventory().replace(replace, item.getSlot()); } player.graphics(Graphics.create(1177)); - for (NPC npc : RegionManager.getLocalNpcs(player, 2)) { + for (NPC npc : RegionManager.getLocalNPCs(player.getLocation(), 2)) { if (canTarget(npc)) { npc.getImpactHandler().manualHit(player, 7 + RandomFunction.randomize(5), HitsplatType.NORMAL, 1); npc.graphics(Graphics.create(1176)); diff --git a/Server/src/main/content/minigame/pestcontrol/bots/CombatState.kt b/Server/src/main/content/minigame/pestcontrol/bots/CombatState.kt index dbfb2ee4a..d03ef42a6 100644 --- a/Server/src/main/content/minigame/pestcontrol/bots/CombatState.kt +++ b/Server/src/main/content/minigame/pestcontrol/bots/CombatState.kt @@ -7,8 +7,6 @@ import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.path.Pathfinder import core.tools.RandomFunction -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import content.minigame.pestcontrol.PestControlHelper.GATE_ENTRIES import content.minigame.pestcontrol.PestControlHelper.getMyPestControlSession1 import core.game.world.GameWorld @@ -63,7 +61,7 @@ class CombatState(val bot: PestControlTestBot) { if (portal != null) { if(bot.location.withinDistance(portal.location,10) && portal.isActive){ val spinners = ArrayList() - RegionManager.getLocalNpcs(bot).forEach { + RegionManager.getLocalNPCs(bot.location).forEach { if(it.name.toLowerCase().equals("spinner") && it.location.withinDistance(bot.location,10)) spinners.add(it) } if(spinners.isNotEmpty()){ diff --git a/Server/src/main/content/minigame/pestcontrol/bots/CombatStateIntermediate.kt b/Server/src/main/content/minigame/pestcontrol/bots/CombatStateIntermediate.kt index fbea681bd..669eca80b 100644 --- a/Server/src/main/content/minigame/pestcontrol/bots/CombatStateIntermediate.kt +++ b/Server/src/main/content/minigame/pestcontrol/bots/CombatStateIntermediate.kt @@ -7,8 +7,6 @@ import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.path.Pathfinder import core.tools.RandomFunction -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import content.minigame.pestcontrol.PestControlHelper.GATE_ENTRIES import content.minigame.pestcontrol.PestControlHelper.getMyPestControlSession2 import core.game.world.GameWorld @@ -62,7 +60,7 @@ class CombatStateIntermediate(val bot: PestControlTestBot2) { if (portal != null) { if(bot.location.withinDistance(portal.location,10) && portal.isActive){ val spinners = ArrayList() - RegionManager.getLocalNpcs(bot).forEach { + RegionManager.getLocalNPCs(bot.location).forEach { if(it.name.toLowerCase().equals("spinner") && it.location.withinDistance(bot.location,10)) spinners.add(it) } if(spinners.isNotEmpty()){ diff --git a/Server/src/main/content/minigame/pestcontrol/monsters/PCRavagerNPC.java b/Server/src/main/content/minigame/pestcontrol/monsters/PCRavagerNPC.java index 4fba76be2..4d45fee9b 100644 --- a/Server/src/main/content/minigame/pestcontrol/monsters/PCRavagerNPC.java +++ b/Server/src/main/content/minigame/pestcontrol/monsters/PCRavagerNPC.java @@ -114,7 +114,7 @@ public class PCRavagerNPC extends AbstractNPC { GameWorld.getPulser().submit(new Pulse(1, this, o) { @Override public boolean pulse() { - if (getViewport().getRegion().isActive() && session.getBarricades().remove(o)) { + if (getLocation().getRegion().isActive() && session.getBarricades().remove(o)) { session.getBarricades().add(newTarget); SceneryBuilder.replace(o, newTarget); } @@ -173,10 +173,10 @@ public class PCRavagerNPC extends AbstractNPC { return true; } - @Override - public boolean shouldPreventStacking(Entity mover) { - return mover instanceof NPC; - } + @Override + public boolean shouldPreventStacking(Entity mover) { + return mover instanceof NPC; + } @Override public void onImpact(final Entity entity, BattleState state) { diff --git a/Server/src/main/content/minigame/pestcontrol/monsters/PCSpinnerNPC.java b/Server/src/main/content/minigame/pestcontrol/monsters/PCSpinnerNPC.java index 60cc22a37..4bfedb5e0 100644 --- a/Server/src/main/content/minigame/pestcontrol/monsters/PCSpinnerNPC.java +++ b/Server/src/main/content/minigame/pestcontrol/monsters/PCSpinnerNPC.java @@ -15,6 +15,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.tools.RandomFunction; @@ -100,9 +101,9 @@ public final class PCSpinnerNPC extends AbstractNPC { */ public void explode() { animate(getProperties().getDeathAnimation()); - for (Player p : RegionManager.getLocalPlayers(this, 1)) { + for (Player p : RegionManager.getLocalPlayers(location, 1)) { p.getImpactHandler().manualHit(this, 5, HitsplatType.POISON); - applyPoison(p, this, 1); + applyPoison(p, this, 1); } GameWorld.getPulser().submit(new Pulse(1, this) { @Override diff --git a/Server/src/main/content/minigame/pestcontrol/monsters/PCSplatterNPC.java b/Server/src/main/content/minigame/pestcontrol/monsters/PCSplatterNPC.java index 5e5111211..cb8c83764 100644 --- a/Server/src/main/content/minigame/pestcontrol/monsters/PCSplatterNPC.java +++ b/Server/src/main/content/minigame/pestcontrol/monsters/PCSplatterNPC.java @@ -75,10 +75,10 @@ public final class PCSplatterNPC extends AbstractNPC { } } - @Override - public boolean shouldPreventStacking(Entity mover) { - return mover instanceof NPC; - } + @Override + public boolean shouldPreventStacking(Entity mover) { + return mover instanceof NPC; + } @Override public void onImpact(final Entity entity, BattleState state) { @@ -132,10 +132,10 @@ public final class PCSplatterNPC extends AbstractNPC { } } } - for (Player p : RegionManager.getLocalPlayers(this, 1)) { + for (Player p : RegionManager.getLocalPlayers(location, 1)) { p.getImpactHandler().manualHit(this, RandomFunction.random(minimum, maximum), null); } - for (NPC npc : RegionManager.getLocalNpcs(this, 1)) { + for (NPC npc : RegionManager.getLocalNPCs(location, 1)) { if (npc != this) { npc.getImpactHandler().manualHit(this, RandomFunction.random(minimum, maximum), null); } diff --git a/Server/src/main/content/minigame/puropuro/ImpDefenderBehavior.kt b/Server/src/main/content/minigame/puropuro/ImpDefenderBehavior.kt index 2c1bb509e..0dd282ed5 100644 --- a/Server/src/main/content/minigame/puropuro/ImpDefenderBehavior.kt +++ b/Server/src/main/content/minigame/puropuro/ImpDefenderBehavior.kt @@ -11,6 +11,7 @@ import core.game.world.map.zone.ZoneBorders import core.game.world.map.RegionManager import core.game.system.task.Pulse import content.global.skill.hunter.bnet.BNetTypes +import core.game.world.repository.Repository import org.rs09.consts.Items @@ -27,7 +28,7 @@ class ImpDefenderBehavior : NPCBehavior(6074) { var nextCaptureTick = getAttribute(self, "next-capture-tick", 0) if (getWorldTicks() < nextCaptureTick) return true - var players = RegionManager.getLocalPlayers(self, 2) + var players = RegionManager.getLocalPlayers(self.location, 2) for (player in players) { var lowestTierImpling = BNetTypes.getImpling(player) if (lowestTierImpling == null) continue diff --git a/Server/src/main/content/minigame/sorceress/SorceressElementalNPC.java b/Server/src/main/content/minigame/sorceress/SorceressElementalNPC.java index af3dbc8e7..ce1c6133c 100644 --- a/Server/src/main/content/minigame/sorceress/SorceressElementalNPC.java +++ b/Server/src/main/content/minigame/sorceress/SorceressElementalNPC.java @@ -1,7 +1,5 @@ package content.minigame.sorceress; -import java.util.List; - import core.game.component.Component; import core.game.node.entity.Entity; import core.game.node.entity.combat.CombatSwingHandler; @@ -12,6 +10,8 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Direction; import core.game.world.map.Location; +import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.net.packet.PacketRepository; @@ -194,20 +194,11 @@ public final class SorceressElementalNPC extends AbstractNPC { return respawn; } - /** - * Gets the tilesIndex. - * @return The tilesIndex. - */ - public int getTilesIndex() { - return tilesIndex; - } - @Override public void tick() { super.tick(); - List players = getViewport().getCurrentPlane().getPlayers(); - for (Player player : players) { - if (player == null || !player.isActive() || player.getLocks().isInteractionLocked() || DeathTask.isDead(player) || !canTeleport(player) || !CombatSwingHandler.isProjectileClipped(this, player, false)) { + for (Player player : RegionManager.getLocalPlayers(location)) { + if (!player.isActive() || player.getLocks().isInteractionLocked() || DeathTask.isDead(player) || !canTeleport(player) || !CombatSwingHandler.isProjectileClipped(this, player, false)) { continue; } animate(new Animation(5803)); diff --git a/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt b/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt index 04fe7686a..bf7c42467 100644 --- a/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt +++ b/Server/src/main/content/minigame/vinesweeper/Vinesweeper.kt @@ -1,8 +1,6 @@ package content.minigame.vinesweeper -import BlinkinDialogue -import FarmerDialogue.Companion.FARMER_FLAG_LINES -import WinkinDialogue +import content.minigame.vinesweeper.FarmerDialogue.Companion.FARMER_FLAG_LINES import content.minigame.vinesweeper.Vinesweeper.Companion.FARMERS import content.minigame.vinesweeper.Vinesweeper.Companion.FARMER_CLEAR_RADIUS import content.minigame.vinesweeper.Vinesweeper.Companion.HOLES @@ -492,10 +490,10 @@ class Vinesweeper : InteractionListener, InterfaceListener, MapArea { dest.player.incrementAttribute("/save:vinesweeper:points", points) dest.player.inventory.add(Item(Items.FLAG_12625, 1)) sendUpdatedPoints(dest.player) - for (neighbor in RegionManager.getLocalPlayers(npc)) { - if (neighbor != dest.player) { - neighbor.incrementAttribute("/save:vinesweeper:points", points / 2) - sendUpdatedPoints(neighbor) + for (player in RegionManager.getLocalPlayers(npc.location)) { + if (player.name != dest.player.name) { + player.incrementAttribute("/save:vinesweeper:points", points / 2) + sendUpdatedPoints(player) } } } @@ -572,21 +570,23 @@ class VinesweeperNPC : AbstractNPC { } override fun handleTickActions() { val dest = seedDestinations.find { sd -> sd.loc == location } - if (locks.isMovementLocked() || locks.isInteractionLocked()) + if (locks.isMovementLocked || locks.isInteractionLocked) return - if(dest != null) { - for(npc in RegionManager.getRegionPlane(location).npcs) { - if(npc is VinesweeperNPC) { - npc.seedDestinations.remove(dest) - npc.resetWalk() + if (dest != null) { + val npcs = location.region.assembleNpcList(0) + for (npc in npcs) { + if (npc !is VinesweeperNPC || npc.seedDestinations.isEmpty() /*npc is not currently walking towards a seed*/) { + continue } + npc.seedDestinations.remove(dest) + npc.resetWalk() } val scenery = getScenery(dest.loc) - if(scenery != null) { - if(id in RABBITS) { + if (scenery != null) { + if (id in RABBITS) { handleRabbitSeed(scenery, dest) } else { - if(dest.alive) { + if (dest.alive) { handleFarmerFlag(scenery, dest) } else { handleFarmerSeed(scenery, dest) @@ -653,13 +653,13 @@ class VinesweeperNPC : AbstractNPC { animate(Animation(Animations.GNOME_FARMER_DIG_FLAG_8725)) GameWorld.Pulser.submit(object: Pulse(3) { override fun pulse(): Boolean { - when(i++) { + when (i++) { 0 -> { sendChat(FARMER_FLAG_LINES.FIND_FLAG.line) } 1 -> { SceneryBuilder.replace(scenery, scenery.transform(HOLES[0])) - if(SEED_LOCS.contains(dest.loc)) { + if (SEED_LOCS.contains(dest.loc)) { sendChat(FARMER_FLAG_LINES.FIND_SEED.line) animate(Animation(Animations.GNOME_FARMER_HOORAY_8731)) sendPoints(npc,dest) diff --git a/Server/src/main/content/minigame/vinesweeper/VinesweeperDialogues.kt b/Server/src/main/content/minigame/vinesweeper/VinesweeperDialogues.kt index 23c012487..49f50f72e 100644 --- a/Server/src/main/content/minigame/vinesweeper/VinesweeperDialogues.kt +++ b/Server/src/main/content/minigame/vinesweeper/VinesweeperDialogues.kt @@ -1,3 +1,5 @@ +package content.minigame.vinesweeper + import core.game.component.Component import core.game.node.item.GroundItemManager import core.game.node.item.Item diff --git a/Server/src/main/content/region/asgarnia/burthorpe/handlers/BurthorpeTrainNPC.java b/Server/src/main/content/region/asgarnia/burthorpe/handlers/BurthorpeTrainNPC.java index 518c70715..36db1cfee 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/handlers/BurthorpeTrainNPC.java +++ b/Server/src/main/content/region/asgarnia/burthorpe/handlers/BurthorpeTrainNPC.java @@ -126,7 +126,7 @@ public class BurthorpeTrainNPC extends AbstractNPC { case 1061:// sergant sendChat(MESSAGES[RandomFunction.random(MESSAGES.length)]); delay = System.currentTimeMillis() + 9000 + RandomFunction.random(1000, 5000); - final List soldiers = RegionManager.getLocalNpcs(this); + final List soldiers = RegionManager.getLocalNPCs(location); NPC soldier = null; while (soldier == null) { soldier = soldiers.get(RandomFunction.random(soldiers.size())); @@ -164,7 +164,7 @@ public class BurthorpeTrainNPC extends AbstractNPC { GameWorld.getPulser().submit(new Pulse(2) { @Override public boolean pulse() { - final List soldiers = RegionManager.getLocalNpcs(BurthorpeTrainNPC.this, 12); + final List soldiers = RegionManager.getLocalNPCs(location, 12); for (NPC n : soldiers) { if (n.getId() != 1064) { continue; diff --git a/Server/src/main/content/region/asgarnia/burthorpe/handlers/wguild/dummy/DummyRoom.java b/Server/src/main/content/region/asgarnia/burthorpe/handlers/wguild/dummy/DummyRoom.java index bc1ad6f5a..6a9a2e1a1 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/handlers/wguild/dummy/DummyRoom.java +++ b/Server/src/main/content/region/asgarnia/burthorpe/handlers/wguild/dummy/DummyRoom.java @@ -111,12 +111,18 @@ public final class DummyRoom extends OptionHandler { setDelay(10); timeStamp = GameWorld.getTicks(); dummy = RandomFunction.getRandomElement(Dummy.values()); - SceneryBuilder.replace(RegionManager.getObject(dummy.getObject().getLocation()), dummy.getObject(), 11); + Scenery dummyObject = RegionManager.getObject(dummy.getObject().getLocation()); + if (dummyObject != null) { + SceneryBuilder.replace(dummyObject, dummy.getObject(), 11); + } activeDummy = true; if (dummy == Dummy.CONTROLLED && controlled == null) { Location l = Location.create(2860, 3551, 0); controlled = new Scenery(dummy.getObject().getId(), l, 10, 1); - SceneryBuilder.replace(RegionManager.getObject(l), controlled, 11); + Scenery controlledObject = RegionManager.getObject(l); + if (controlledObject != null) { + SceneryBuilder.replace(controlledObject, controlled, 11); + } } return false; } diff --git a/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt b/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt index aac922c9a..93a55d438 100644 --- a/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt +++ b/Server/src/main/content/region/asgarnia/falador/diary/FaladorAchievementDiary.kt @@ -143,7 +143,7 @@ class FaladorAchievementDiary : DiaryEventHookBase(DiaryType.FALADOR) { ) override fun onInteracted(player: Player, event: InteractionEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12084 -> { if (event.option == "burst" && event.target.id in PARTY_BALLOONS) { finishTask( @@ -179,7 +179,7 @@ class FaladorAchievementDiary : DiaryEventHookBase(DiaryType.FALADOR) { } override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 11828 -> when (event.itemId) { Items.YEW_LOGS_1515, Items.MAGIC_LOGS_1513 -> { if (inBorders(player, PARK_TREE_PATCH_AREA)) { @@ -195,7 +195,7 @@ class FaladorAchievementDiary : DiaryEventHookBase(DiaryType.FALADOR) { } override fun onNpcKilled(player: Player, event: NPCKillEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 11828 -> if (event.npc.id in PARK_DUCKS && inBorders(event.npc, PARK_POND_AREA)) { finishTask( player, diff --git a/Server/src/main/content/region/asgarnia/falador/handlers/GiantMoleNPC.java b/Server/src/main/content/region/asgarnia/falador/handlers/GiantMoleNPC.java index 20edbb3ac..e9f3735e5 100644 --- a/Server/src/main/content/region/asgarnia/falador/handlers/GiantMoleNPC.java +++ b/Server/src/main/content/region/asgarnia/falador/handlers/GiantMoleNPC.java @@ -26,6 +26,7 @@ import core.game.world.map.Direction; import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.map.zone.impl.DarkZone; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.net.packet.PacketRepository; diff --git a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/FortressGuardDialogue.java b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/FortressGuardDialogue.java index 51fa14058..7910ec29c 100644 --- a/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/FortressGuardDialogue.java +++ b/Server/src/main/content/region/asgarnia/falador/quest/blackknightsfortress/FortressGuardDialogue.java @@ -201,7 +201,7 @@ public class FortressGuardDialogue extends DialoguePlugin { case 54: end(); DoorActionHandler.handleAutowalkDoor(player, RegionManager.getObject(0, 3020, 3515)); - List npcs = RegionManager.getLocalNpcs(player); + List npcs = RegionManager.getLocalNPCs(player.getLocation()); for (NPC npc : npcs) { if (npc.getId() == 179) { npc.getProperties().getCombatPulse().attack(player); diff --git a/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillageNPC.java b/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillageNPC.java index 0c34e38d0..e5128d1ba 100644 --- a/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillageNPC.java +++ b/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillageNPC.java @@ -103,7 +103,7 @@ public final class GoblinVillageNPC extends AbstractNPC { if (delay < System.currentTimeMillis() && !getProperties().getCombatPulse().isAttacking()) { final int rand = RandomFunction.random(1, 4); if (rand == 2) { - final List surronding = RegionManager.getLocalNpcs(this, 10); + final List surronding = RegionManager.getLocalNPCs(location, 10); for (NPC n : surronding) { if (n.getId() == getId()) { continue; diff --git a/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillagePopulationListener.kt b/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillagePopulationListener.kt index 401d09d54..79102017a 100644 --- a/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillagePopulationListener.kt +++ b/Server/src/main/content/region/asgarnia/goblinvillage/handlers/GoblinVillagePopulationListener.kt @@ -3,14 +3,14 @@ package content.region.asgarnia.goblinvillage.handlers import core.game.interaction.IntType import core.game.interaction.InteractionListener import core.game.node.entity.combat.DeathTask -import core.game.world.map.RegionManager.getLocalNpcs +import core.game.world.map.RegionManager.getLocalNPCs import org.rs09.consts.Scenery class GoblinVillagePopulationListener : InteractionListener{ override fun defineListeners() { on(Scenery.SIGNPOST_31301, IntType.SCENERY, "read") { player, node -> var population = 3 // This covers General Wartface, General Bentnoze and Grubfoot - val npcs = getLocalNpcs(player, 50) // This radius covers more than the goblin village. + val npcs = getLocalNPCs(player.location, 50) // This radius covers more than the goblin village. // There should be 18 Goblins walking around. // 10 are within the village walls where the generals are. // 8 of them are fighting each other on the west of the path to the village. diff --git a/Server/src/main/content/region/asgarnia/handlers/WineOfZamorakInteraction.kt b/Server/src/main/content/region/asgarnia/handlers/WineOfZamorakInteraction.kt index d908028b4..f11eef2a7 100644 --- a/Server/src/main/content/region/asgarnia/handlers/WineOfZamorakInteraction.kt +++ b/Server/src/main/content/region/asgarnia/handlers/WineOfZamorakInteraction.kt @@ -15,7 +15,7 @@ class WineOfZamorakInteraction : InteractionListener { PickupHandler.take(player, wine as GroundItem) return@on true } - val npcs = RegionManager.getLocalNpcs(player) + val npcs = RegionManager.getLocalNPCs(player.location) for (n in npcs) { if (n.id == 188) { n.sendChat("Hands off zamorak's wine!") diff --git a/Server/src/main/content/region/asgarnia/taverley/dialogue/PetshopOwnerTaverly.java b/Server/src/main/content/region/asgarnia/taverley/dialogue/PetshopOwnerTaverly.java index 39f24867c..42a750302 100644 --- a/Server/src/main/content/region/asgarnia/taverley/dialogue/PetshopOwnerTaverly.java +++ b/Server/src/main/content/region/asgarnia/taverley/dialogue/PetshopOwnerTaverly.java @@ -53,7 +53,7 @@ public final class PetshopOwnerTaverly extends DialoguePlugin { @Override public boolean open(Object... args) { if (args.length > 1) { - List npcs = RegionManager.getLocalNpcs(player); + List npcs = RegionManager.getLocalNPCs(player.getLocation()); for (NPC n : npcs) { if (n.getId() == 6893) { npc = n; diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/NoraTHaggNPC.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/NoraTHaggNPC.java index 2192bf840..30d12d34a 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/NoraTHaggNPC.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/NoraTHaggNPC.java @@ -9,6 +9,8 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Direction; import core.game.world.map.Location; +import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.net.packet.PacketRepository; @@ -28,122 +30,122 @@ import java.util.List; @Initializable public class NoraTHaggNPC extends AbstractNPC { - boolean walkdir; + boolean walkdir; - public NoraTHaggNPC() { - super(896, Location.create(2904, 3463, 0)); - } - private Location getRespawnLocation() { - return Location.create(2900, 3473, 0); - } + public NoraTHaggNPC() { + super(896, Location.create(2904, 3463, 0)); + } + private Location getRespawnLocation() { + return Location.create(2900, 3473, 0); + } - private NoraTHaggNPC(int id, Location location) { - super(id, location); - } + private NoraTHaggNPC(int id, Location location) { + super(id, location); + } - @Override - public Plugin newInstance(Object arg) throws Throwable { - this.configure(); - init(); - return super.newInstance(arg); - } + @Override + public Plugin newInstance(Object arg) throws Throwable { + this.configure(); + init(); + return super.newInstance(arg); + } - private boolean canTeleport(Entity t) { - int playerX = t.getLocation().getX(); - int npcX = getLocation().getX(); - int[] sectors = { 2904, 2907, 2910, 2914, 2918, 2922, 2926, 2928 }; - for (int i = 0; i < sectors.length -1; i++) { - if (npcX >= sectors[i] && npcX <= sectors[i+1] && playerX >= sectors[i] && playerX <= sectors[i+1]) { - if (playerX < npcX && getDirection() == Direction.WEST || playerX > npcX && getDirection() == Direction.EAST) { - return true; - } - if (playerX == npcX) { - return true; - } - } - } - return false; - } + private boolean canTeleport(Entity t) { + int playerX = t.getLocation().getX(); + int npcX = getLocation().getX(); + int[] sectors = { 2904, 2907, 2910, 2914, 2918, 2922, 2926, 2928 }; + for (int i = 0; i < sectors.length -1; i++) { + if (npcX >= sectors[i] && npcX <= sectors[i+1] && playerX >= sectors[i] && playerX <= sectors[i+1]) { + if (playerX < npcX && getDirection() == Direction.WEST || playerX > npcX && getDirection() == Direction.EAST) { + return true; + } + if (playerX == npcX) { + return true; + } + } + } + return false; + } - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new NoraTHaggNPC(id, location); - } + @Override + public AbstractNPC construct(int id, Location location, Object... objects) { + return new NoraTHaggNPC(id, location); + } - @Override - public int[] getIds() { - return new int[] { 896 }; - } + @Override + public int[] getIds() { + return new int[] { 896 }; + } - @Override - public int getWalkRadius() { - return 50; - } + @Override + public int getWalkRadius() { + return 50; + } - public void configure() { - super.configure(); - setWalks(false); - setPathBoundMovement(true); - } + public void configure() { + super.configure(); + setWalks(false); + setPathBoundMovement(true); + } - private void sendTeleport(final Player player) { - player.lock(); - GameWorld.getPulser().submit(new Pulse(1) { - int delay = 0; + private void sendTeleport(final Player player) { + player.lock(); + GameWorld.getPulser().submit(new Pulse(1) { + int delay = 0; - @Override - public boolean pulse() { - if (delay == 0) { - face(player); - player.getInventory().remove(WitchsHousePlugin.BALL); - player.getInventory().remove(WitchsHousePlugin.KEY); - player.getInventory().remove(WitchsHousePlugin.DOOR_KEY); - sendChat("Stop! Thief!"); - player.getPacketDispatch().sendMessage("You've been spotted by the witch."); - player.graphics(new Graphics(110, 100)); - PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2)); - } else if (delay == 2) { - sendChat("Klarata... Seppteno... Valkan!"); - face(null); - } else if (delay == 4) { - player.getProperties().setTeleportLocation(Location.create(getRespawnLocation())); - PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0)); - face(null); - player.unlock(); - return true; - } - delay++; - return false; - } - }); - } + @Override + public boolean pulse() { + if (delay == 0) { + face(player); + player.getInventory().remove(WitchsHousePlugin.BALL); + player.getInventory().remove(WitchsHousePlugin.KEY); + player.getInventory().remove(WitchsHousePlugin.DOOR_KEY); + sendChat("Stop! Thief!"); + player.getPacketDispatch().sendMessage("You've been spotted by the witch."); + player.graphics(new Graphics(110, 100)); + PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 2)); + } else if (delay == 2) { + sendChat("Klarata... Seppteno... Valkan!"); + face(null); + } else if (delay == 4) { + player.getProperties().setTeleportLocation(Location.create(getRespawnLocation())); + PacketRepository.send(MinimapState.class, new MinimapStateContext(player, 0)); + face(null); + player.unlock(); + return true; + } + delay++; + return false; + } + }); + } - @Override - public void tick() { - super.tick(); - List players = getViewport().getCurrentPlane().getPlayers(); - if(getLocation().getX() == 2930){ - walkdir = false; - } else if(getLocation().getX() == 2904){ - walkdir = true; - } - for (Player player : players) { - if (player == null || !player.isActive() || player.getLocks().isInteractionLocked() || DeathTask.isDead(player) || !canTeleport(player) || !CombatSwingHandler.isProjectileClipped(this, player, false)) { - continue; - } - animate(new Animation(5803)); - sendTeleport(player); - player.getPacketDispatch().sendMessage("" + getLocation() + " matches? " + (getLocation().getX() == 2904)); - } - if (location.getX() != 2930 && walkdir) { - this.getWalkingQueue().reset(); - this.getWalkingQueue().addPath(location.getX() + 1,3463,true); - } else if (location.getX() != 2904 && !walkdir) { - this.getWalkingQueue().reset(); - this.getWalkingQueue().addPath(location.getX() - 1,3463,true); - } - } + @Override + public void tick() { + super.tick(); + List players = RegionManager.getLocalPlayers(location); + if(getLocation().getX() == 2930){ + walkdir = false; + } else if(getLocation().getX() == 2904){ + walkdir = true; + } + for (Player player : players) { + if (player == null || !player.isActive() || player.getLocks().isInteractionLocked() || DeathTask.isDead(player) || !canTeleport(player) || !CombatSwingHandler.isProjectileClipped(this, player, false)) { + continue; + } + animate(new Animation(5803)); + sendTeleport(player); + player.getPacketDispatch().sendMessage("" + getLocation() + " matches? " + (getLocation().getX() == 2904)); + } + if (location.getX() != 2930 && walkdir) { + this.getWalkingQueue().reset(); + this.getWalkingQueue().addPath(location.getX() + 1,3463,true); + } else if (location.getX() != 2904 && !walkdir) { + this.getWalkingQueue().reset(); + this.getWalkingQueue().addPath(location.getX() - 1,3463,true); + } + } } diff --git a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsExperimentNPC.java b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsExperimentNPC.java index 5f1e46e06..8a99ad831 100644 --- a/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsExperimentNPC.java +++ b/Server/src/main/content/region/asgarnia/taverley/quest/witchshouse/WitchsExperimentNPC.java @@ -19,165 +19,165 @@ import core.plugin.Initializable; @Initializable public class WitchsExperimentNPC extends AbstractNPC { - private ExperimentType type; - private boolean commenced; - Player p; + private ExperimentType type; + private boolean commenced; + Player p; - public WitchsExperimentNPC() { - super(0, null); - } + public WitchsExperimentNPC() { + super(0, null); + } - WitchsExperimentNPC(int id, Location location, Player player) { - super(id, location); - this.setWalks(true); - this.setRespawn(false); - this.type = WitchsExperimentNPC.ExperimentType.forId(id); - p = player; - } + WitchsExperimentNPC(int id, Location location, Player player) { + super(id, location); + this.setWalks(true); + this.setRespawn(false); + this.type = WitchsExperimentNPC.ExperimentType.forId(id); + p = player; + } - @Override - public void handleTickActions() { - super.handleTickActions(); - if(!p.isActive() || !RegionManager.getLocalPlayers(this).contains(p)){ - p.removeAttribute("witchs-experiment:npc_spawned"); - clear(); - } - if (!getProperties().getCombatPulse().isAttacking()) { - getProperties().getCombatPulse().attack(p); - } - } + @Override + public void handleTickActions() { + super.handleTickActions(); + if (!p.isActive() || !RegionManager.getLocalPlayers(location).contains(p)) { + p.removeAttribute("witchs-experiment:npc_spawned"); + clear(); + } + if (!getProperties().getCombatPulse().isAttacking()) { + getProperties().getCombatPulse().attack(p); + } + } - @Override - public void startDeath(Entity killer) { - if (killer == p) { - type.transform(this, p); - return; - } - super.startDeath(killer); - } + @Override + public void startDeath(Entity killer) { + if (killer == p) { + type.transform(this, p); + return; + } + super.startDeath(killer); + } - @Override - public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { - return p == entity; - } + @Override + public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { + return p == entity; + } - @Override - public boolean canSelectTarget(Entity target) { - if (target instanceof Player) { - Player p = (Player) target; - return p == this.p; - } - return true; - } + @Override + public boolean canSelectTarget(Entity target) { + if (target instanceof Player) { + Player p = (Player) target; + return p == this.p; + } + return true; + } - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new WitchsExperimentNPC(id, location, null); - } + @Override + public AbstractNPC construct(int id, Location location, Object... objects) { + return new WitchsExperimentNPC(id, location, null); + } - @Override - public int[] getIds() { - return new int[] { 897, 898, 899, 900 }; - } + @Override + public int[] getIds() { + return new int[] { 897, 898, 899, 900 }; + } - public void setType(ExperimentType type) { - this.type = type; - } + public void setType(ExperimentType type) { + this.type = type; + } - public ExperimentType getType() { - return type; - } + public ExperimentType getType() { + return type; + } - public void setCommenced(boolean commenced) { - this.commenced = commenced; - } + public void setCommenced(boolean commenced) { + this.commenced = commenced; + } - public enum ExperimentType { - FIRST(897, ""), - SECOND(898, "The shapeshifter's body begins to deform!", "The shapeshifter turns into a spider!"), - THIRD(899, "The shapeshifter's body begins to twist!", "The shapeshifter turns into a bear!"), - FOURTH(900, "The shapeshifter's body pulses!", "The shapeshifter turns into a wolf!"), - END(-1, ""), + public enum ExperimentType { + FIRST(897, ""), + SECOND(898, "The shapeshifter's body begins to deform!", "The shapeshifter turns into a spider!"), + THIRD(899, "The shapeshifter's body begins to twist!", "The shapeshifter turns into a bear!"), + FOURTH(900, "The shapeshifter's body pulses!", "The shapeshifter turns into a wolf!"), + END(-1, ""), - ; + ; - private int id; - private String[] message; + private int id; + private String[] message; - ExperimentType(int id, String... message) { - this.id = id; - this.message = message; - } + ExperimentType(int id, String... message) { + this.id = id; + this.message = message; + } - /** - * Transforms the new npc. - */ - public void transform(final WitchsExperimentNPC npc, final Player player) { - final ExperimentType newType = next(); - npc.lock(); - npc.getPulseManager().clear(); - npc.getWalkingQueue().reset(); - player.setAttribute("/save:witchs_house:experiment_id",this.id); - GameWorld.getPulser().submit(new Pulse(1, npc, player) { - int counter; + /** + * Transforms the new npc. + */ + public void transform(final WitchsExperimentNPC npc, final Player player) { + final ExperimentType newType = next(); + npc.lock(); + npc.getPulseManager().clear(); + npc.getWalkingQueue().reset(); + player.setAttribute("/save:witchs_house:experiment_id",this.id); + GameWorld.getPulser().submit(new Pulse(1, npc, player) { + int counter; - @Override - public boolean pulse() { - switch (++counter) { + @Override + public boolean pulse() { + switch (++counter) { - case 1: - npc.unlock(); - npc.getAnimator().reset(); - npc.fullRestore(); - npc.setType(newType); - npc.transform(newType.getId()); - npc.getImpactHandler().setDisabledTicks(1); - if (newType != END) { - npc.getProperties().getCombatPulse().attack(player); - } - if (newType.getMessage() != null && newType != END) { - player.sendMessage(newType.getMessage()[0]); - player.sendMessage(newType.getMessage()[1]); - } - if (newType == END) { - player.setAttribute("witchs_house:experiment_killed",true); - npc.clear(); - return false; - } - player.unlock(); - return true; - } - return false; - } + case 1: + npc.unlock(); + npc.getAnimator().reset(); + npc.fullRestore(); + npc.setType(newType); + npc.transform(newType.getId()); + npc.getImpactHandler().setDisabledTicks(1); + if (newType != END) { + npc.getProperties().getCombatPulse().attack(player); + } + if (newType.getMessage() != null && newType != END) { + player.sendMessage(newType.getMessage()[0]); + player.sendMessage(newType.getMessage()[1]); + } + if (newType == END) { + player.setAttribute("witchs_house:experiment_killed",true); + npc.clear(); + return false; + } + player.unlock(); + return true; + } + return false; + } - }); - } + }); + } - public static ExperimentType forId(int id) { - for (ExperimentType type : values()) { - if (type.getId() == id) { - return type; - } - } - return null; - } + public static ExperimentType forId(int id) { + for (ExperimentType type : values()) { + if (type.getId() == id) { + return type; + } + } + return null; + } - private static ExperimentType[] experimentTypes = values(); + private static ExperimentType[] experimentTypes = values(); - public ExperimentType next() - { - return experimentTypes[this.ordinal() + 1]; - } + public ExperimentType next() + { + return experimentTypes[this.ordinal() + 1]; + } - public int getId() { - return id; - } + public int getId() { + return id; + } - public String[] getMessage() { - return message; - } + public String[] getMessage() { + return message; + } - } + } } diff --git a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDGraardorSwingHandler.java b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDGraardorSwingHandler.java index 540d48f02..551b314b6 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDGraardorSwingHandler.java +++ b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDGraardorSwingHandler.java @@ -12,8 +12,10 @@ import core.game.node.entity.combat.equipment.ArmourSet; import core.game.node.entity.impl.Projectile; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.npc.NPC; +import core.game.node.entity.player.Player; import core.game.world.map.RegionManager; import core.game.world.map.zone.ZoneBorders; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.tools.RandomFunction; @@ -66,7 +68,7 @@ public final class GWDGraardorSwingHandler extends CombatSwingHandler { ticks += (int) Math.ceil(entity.getLocation().getDistance(victim.getLocation()) * 0.3); NPC npc = (NPC) entity; List list = new ArrayList<>(20); - for (Entity t : RegionManager.getLocalPlayers(npc, 28)) { + for (Player t : RegionManager.getLocalPlayers(npc.getLocation(), 28)) { if (!CHAMBER.insideBorder(t.getLocation())) { continue; } diff --git a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDKreeArraSwingHandler.java b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDKreeArraSwingHandler.java index 925f917fd..56176d84b 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDKreeArraSwingHandler.java +++ b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDKreeArraSwingHandler.java @@ -12,10 +12,12 @@ import core.game.node.entity.combat.equipment.ArmourSet; import core.game.node.entity.impl.Projectile; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.npc.NPC; +import core.game.node.entity.player.Player; import core.game.world.map.Direction; import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.map.zone.ZoneBorders; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.tools.RandomFunction; @@ -83,7 +85,7 @@ public final class GWDKreeArraSwingHandler extends CombatSwingHandler { ticks += (int) Math.ceil(entity != null ? entity.getLocation().getDistance(victim.getLocation()) : 0.0 * 0.3); NPC npc = (NPC) entity; List list = new ArrayList<>(20); - for (Entity t : RegionManager.getLocalPlayers(npc, 28)) { + for (Player t : RegionManager.getLocalPlayers(npc.getLocation(), 28)) { if (!CHAMBER.insideBorder(t.getLocation())) { continue; } diff --git a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDZilyanaSwingHandler.java b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDZilyanaSwingHandler.java index a1f060d9a..4fa4fea33 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDZilyanaSwingHandler.java +++ b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GWDZilyanaSwingHandler.java @@ -11,7 +11,9 @@ import core.game.node.entity.combat.InteractionType; import core.game.node.entity.combat.equipment.ArmourSet; import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.npc.NPC; +import core.game.node.entity.player.Player; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.tools.RandomFunction; @@ -59,7 +61,7 @@ public class GWDZilyanaSwingHandler extends CombatSwingHandler { } else { NPC npc = (NPC) entity; List list = new ArrayList<>(20); - for (Entity t : RegionManager.getLocalPlayers(npc.getCenterLocation(), (npc.size() >> 1) + 2)) { + for (Player t : RegionManager.getLocalPlayers(npc.getCenterLocation(), (npc.size() >> 1) + 2)) { if (t.getLocation().getX() < 2908 && t.isAttackable(npc, CombatStyle.MAGIC, false)) { list.add(new BattleState(entity, t)); } diff --git a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodWarsNPC.java b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodWarsNPC.java index 215de9f11..4dae4b212 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodWarsNPC.java +++ b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodWarsNPC.java @@ -61,7 +61,7 @@ public final class GodWarsNPC extends AbstractNPC { @Override public List getPossibleTargets(Entity entity, int radius) { List targets = new ArrayList<>(20); - for (Player player : RegionManager.getLocalPlayers(entity, radius)) { + for (Player player : RegionManager.getLocalPlayers(entity.getLocation(), radius)) { if (canSelectTarget(entity, player)) { targets.add(player); } @@ -69,7 +69,7 @@ public final class GodWarsNPC extends AbstractNPC { if (!targets.isEmpty()) { return targets; } - for (NPC npc : RegionManager.getLocalNpcs(entity, radius)) { + for (NPC npc : RegionManager.getLocalNPCs(entity.getLocation(), radius)) { if (canSelectTarget(entity, npc)) { targets.add(npc); } @@ -115,9 +115,9 @@ public final class GodWarsNPC extends AbstractNPC { @Override public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { if (style == CombatStyle.MELEE && faction == GodWarsFaction.ARMADYL && entity instanceof Player) { - if(message) { - ((Player) entity).getPacketDispatch().sendMessage("The aviansie is flying too high for you to attack using melee."); - } + if(message) { + ((Player) entity).getPacketDispatch().sendMessage("The aviansie is flying too high for you to attack using melee."); + } return false; } return super.isAttackable(entity, style, message); diff --git a/Server/src/main/content/region/desert/alkharid/handlers/AlKharidWarriorNPC.kt b/Server/src/main/content/region/desert/alkharid/handlers/AlKharidWarriorNPC.kt index ba1b4662d..0f56be285 100644 --- a/Server/src/main/content/region/desert/alkharid/handlers/AlKharidWarriorNPC.kt +++ b/Server/src/main/content/region/desert/alkharid/handlers/AlKharidWarriorNPC.kt @@ -49,7 +49,7 @@ class AlKharidWarriorNPC : AbstractNPC { if (entity is Player) { if (target == null) { target = entity - RegionManager.getLocalNpcs(entity, supportRange).forEach { + RegionManager.getLocalNPCs(entity.location, supportRange).forEach { if (it.id == NPCs.AL_KHARID_WARRIOR_18 && !it.properties.combatPulse.isAttacking && it != this) { it.sendChat("Brother, I shall help thee with this infidel!") it.attack(entity) diff --git a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java index 038567099..2c8985dec 100644 --- a/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java +++ b/Server/src/main/content/region/desert/alkharid/quest/princealirescue/LadyKeliDialogue.java @@ -64,7 +64,7 @@ public final class LadyKeliDialogue extends DialoguePlugin { case 60: case 100: npc.sendChat("You tricked me, and tied me up, Guards kill this stranger!"); - List npcc = RegionManager.getLocalNpcs(player); + List npcc = RegionManager.getLocalNPCs(player.getLocation()); for (NPC n : npcc) { if (n.getId() == 917) { n.sendChat("Yes M'lady"); diff --git a/Server/src/main/content/region/desert/bandits/handlers/BanditNPC.kt b/Server/src/main/content/region/desert/bandits/handlers/BanditNPC.kt index 29a7809d1..beadf788e 100644 --- a/Server/src/main/content/region/desert/bandits/handlers/BanditNPC.kt +++ b/Server/src/main/content/region/desert/bandits/handlers/BanditNPC.kt @@ -23,8 +23,7 @@ class BanditNPC(id: Int = NPCs.BANDIT_1926, location: Location? = null) : Abstra override fun tick() { if (!inCombat()) { - val players = RegionManager.getLocalPlayers(this, 5) - for (player in players) { + for (player in RegionManager.getLocalPlayers(location, 5)) { if (player.inCombat()) continue if (hasGodItem(player, God.SARADOMIN)) { sendChat("Time to die, Saradominist filth!") @@ -47,7 +46,7 @@ class BanditNPC(id: Int = NPCs.BANDIT_1926, location: Location? = null) : Abstra override fun onImpact(entity: Entity?, state: BattleState?) { if (entity is Player) { - RegionManager.getLocalNpcs(entity, supportRange).forEach { + RegionManager.getLocalNPCs(entity.location, supportRange).forEach { if (it.id == NPCs.BANDIT_1926 && !it.properties.combatPulse.isAttacking && it != this) { it.sendChat("You picked the wrong place to start trouble!") it.attack(entity) diff --git a/Server/src/main/content/region/desert/bedabin/handlers/BedabinPlugin.java b/Server/src/main/content/region/desert/bedabin/handlers/BedabinPlugin.java index a0a2870a9..99411ee68 100644 --- a/Server/src/main/content/region/desert/bedabin/handlers/BedabinPlugin.java +++ b/Server/src/main/content/region/desert/bedabin/handlers/BedabinPlugin.java @@ -47,7 +47,7 @@ public final class BedabinPlugin extends OptionHandler { player.getPacketDispatch().sendMessage("You walk back out the tent."); break; } - player.getDialogueInterpreter().open(834, RegionManager.getNpc(player, 834)); + player.getDialogueInterpreter().open(834, RegionManager.getNpc(player.getLocation(), 834, 16)); break; } break; diff --git a/Server/src/main/content/region/desert/handlers/KalphiteQueenNPC.java b/Server/src/main/content/region/desert/handlers/KalphiteQueenNPC.java index 39dbc9399..7637a1baf 100644 --- a/Server/src/main/content/region/desert/handlers/KalphiteQueenNPC.java +++ b/Server/src/main/content/region/desert/handlers/KalphiteQueenNPC.java @@ -19,6 +19,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.plugin.Initializable; @@ -211,7 +212,7 @@ public final class KalphiteQueenNPC extends AbstractNPC { */ private BattleState[] getRangeTargets(Entity e, Entity victim) { List list = new ArrayList<>(20); - for (Entity t : RegionManager.getLocalPlayers(victim, -1 + (int) e.getCenterLocation().getDistance(victim.getLocation()))) { + for (Player t : RegionManager.getLocalPlayers(victim.getLocation(), -1 + (int) e.getCenterLocation().getDistance(victim.getLocation()))) { if (t.isAttackable(e, CombatStyle.RANGE, false)) { list.add(new BattleState(e, t)); } @@ -315,12 +316,12 @@ public final class KalphiteQueenNPC extends AbstractNPC { return; } if (style == CombatStyle.MAGIC) { - BattleState[] states = new BattleState[entity.getViewport().getCurrentPlane().getPlayers().size() + 1]; + BattleState[] states = new BattleState[RegionManager.getLocalPlayers(entity.getLocation()).size() + 1]; int index = 1; if (states.length == 0) { return; } - for (Player p : entity.getViewport().getCurrentPlane().getPlayers()) { + for (Player p : RegionManager.getLocalPlayers(entity.getLocation())) { if (p != victim) { states[index++] = new BattleState(entity, p); } diff --git a/Server/src/main/content/region/desert/handlers/KhardianInteractionPlugin.java b/Server/src/main/content/region/desert/handlers/KhardianInteractionPlugin.java index c2dbc4200..89d5dc1ab 100644 --- a/Server/src/main/content/region/desert/handlers/KhardianInteractionPlugin.java +++ b/Server/src/main/content/region/desert/handlers/KhardianInteractionPlugin.java @@ -80,7 +80,7 @@ public final class KhardianInteractionPlugin extends OptionHandler { if (!failed) { player.getSkills().addExperience(Skills.WOODCUTTING, 10, true); } - SceneryBuilder.replace(((Scenery) node), new Scenery(DRY_CACTUS, node.getLocation()), SPAWN_DELAY + RandomFunction.random(RegionManager.getLocalPlayers(player).size() / 2)); + SceneryBuilder.replace(((Scenery) node), new Scenery(DRY_CACTUS, node.getLocation()), SPAWN_DELAY + RandomFunction.random(RegionManager.getLocalPlayers(player.getLocation()).size() / 2)); break; } return true; diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java index efb949796..ed8bb63a9 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/AnaDialogue.java @@ -108,7 +108,7 @@ public final class AnaDialogue extends DialoguePlugin { case 3: player.getInventory().add(TouristTrap.WROUGHT_IRON_KEY, player); player.getPacketDispatch().sendMessage("Ana spots Irena and waves..."); - NPC irena = RegionManager.getNpc(player, 4986); + NPC irena = RegionManager.getNpc(player.getLocation(), 4986, 16); irena.sendChat("Hi Ana!"); quest.setStage(player, 98); end(); diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java b/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java index 9c9a08367..623a4ecef 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/DesertGuardDialogue.java @@ -12,6 +12,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.plugin.ClassScanner; import core.tools.RandomFunction; @@ -307,8 +308,8 @@ public final class DesertGuardDialogue extends DialoguePlugin { * Method used to warn players whom are breaking rules. */ private void warn() { - final List players = RegionManager.getLocalPlayers(this); - for (final Player player : players) { + final List players = RegionManager.getLocalPlayers(location); + for (Player player : players) { if (player.getAttribute("guard-warning", 0) > GameWorld.getTicks() || !player.getZoneMonitor().isInZone("mining camp") || player.inCombat() || !player.getLocation().withinDistance(this.getLocation(), 8)) { continue; } diff --git a/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java b/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java index 463d61272..e486577e7 100644 --- a/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java +++ b/Server/src/main/content/region/desert/quest/thetouristrap/TouristTrapPlugin.java @@ -49,1653 +49,1653 @@ import static core.api.ContentAPIKt.*; */ public final class TouristTrapPlugin extends OptionHandler { - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(2673).getHandlers().put("option:open", this); - SceneryDefinition.forId(2674).getHandlers().put("option:open", this); - SceneryDefinition.forId(2673).getHandlers().put("option:search", this); - SceneryDefinition.forId(2674).getHandlers().put("option:search", this); - SceneryDefinition.forId(2688).getHandlers().put("option:open", this); - SceneryDefinition.forId(2688).getHandlers().put("option:search", this); - SceneryDefinition.forId(2687).getHandlers().put("option:open", this); - SceneryDefinition.forId(2687).getHandlers().put("option:search", this); - SceneryDefinition.forId(2685).getHandlers().put("option:open", this); - SceneryDefinition.forId(2685).getHandlers().put("option:open", this); - SceneryDefinition.forId(2686).getHandlers().put("option:search", this); - SceneryDefinition.forId(2686).getHandlers().put("option:search", this); - SceneryDefinition.forId(18958).getHandlers().put("option:search", this); - SceneryDefinition.forId(18958).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18959).getHandlers().put("option:search", this); - SceneryDefinition.forId(18959).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18888).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18888).getHandlers().put("option:operate", this); - SceneryDefinition.forId(36748).getHandlers().put("option:talk-to", this); - SceneryDefinition.forId(18869).getHandlers().put("option:bend", this); - SceneryDefinition.forId(18870).getHandlers().put("option:escape", this); - SceneryDefinition.forId(2689).getHandlers().put("option:open", this); - SceneryDefinition.forId(1528).getHandlers().put("option:open", this); - SceneryDefinition.forId(1529).getHandlers().put("option:close", this); - SceneryDefinition.forId(18899).getHandlers().put("option:search", this); - SceneryDefinition.forId(18899).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18878).getHandlers().put("option:search", this); - SceneryDefinition.forId(18878).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18879).getHandlers().put("option:search", this); - SceneryDefinition.forId(18879).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18898).getHandlers().put("option:search", this); - SceneryDefinition.forId(18898).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18902).getHandlers().put("option:search", this); - SceneryDefinition.forId(18871).getHandlers().put("option:climb", this); - SceneryDefinition.forId(18923).getHandlers().put("option:climb-up", this); - SceneryDefinition.forId(18924).getHandlers().put("option:climb-down", this); - SceneryDefinition.forId(2676).getHandlers().put("option:open", this); - SceneryDefinition.forId(2675).getHandlers().put("option:open", this); - SceneryDefinition.forId(2676).getHandlers().put("option:watch", this); - SceneryDefinition.forId(2675).getHandlers().put("option:watch", this); - SceneryDefinition.forId(2690).getHandlers().put("option:open", this); - SceneryDefinition.forId(2691).getHandlers().put("option:open", this); - SceneryDefinition.forId(2698).getHandlers().put("option:walk through", this); - SceneryDefinition.forId(2699).getHandlers().put("option:walk through", this); - SceneryDefinition.forId(2677).getHandlers().put("option:open", this); - SceneryDefinition.forId(2678).getHandlers().put("option:search", this); - SceneryDefinition.forId(2684).getHandlers().put("option:search", this); - SceneryDefinition.forId(2684).getHandlers().put("option:look at", this); - SceneryDefinition.forId(2680).getHandlers().put("option:search", this); - SceneryDefinition.forId(2680).getHandlers().put("option:look-in", this); - SceneryDefinition.forId(2681).getHandlers().put("option:search", this); - SceneryDefinition.forId(2681).getHandlers().put("option:look in", this); - SceneryDefinition.forId(18962).getHandlers().put("option:search", this); - SceneryDefinition.forId(18962).getHandlers().put("option:look in", this); - SceneryDefinition.forId(18963).getHandlers().put("option:search", this); - SceneryDefinition.forId(18963).getHandlers().put("option:look in", this); - SceneryDefinition.forId(18951).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18951).getHandlers().put("option:use", this); - SceneryDefinition.forId(2684).getHandlers().put("option:search", this); - SceneryDefinition.forId(2684).getHandlers().put("option:look at", this); - SceneryDefinition.forId(18875).getHandlers().put("option:inspect", this); - NPCDefinition.forId(830).getHandlers().put("option:watch", this); - NPCDefinition.forId(4975).getHandlers().put("option:talk-to", this); - NPCDefinition.forId(4976).getHandlers().put("option:talk-to", this); - NPCDefinition.forId(4977).getHandlers().put("option:talk-to", this); - NPCDefinition.forId(4978).getHandlers().put("option:talk-to", this); - NPCDefinition.forId(5002).getHandlers().put("option:talk-to", this); - TouristTrap.TECHNICAL_PLANS.getDefinition().getHandlers().put("option:read", this); - TouristTrap.ANNA_BARREL.getDefinition().getHandlers().put("option:look", this); - TouristTrap.ANNA_BARREL.getDefinition().getHandlers().put("option:drop", this); - ClassScanner.definePlugin(new BedabinKeyHandler()); - ClassScanner.definePlugin(new BedabinAnvilHandler()); - ClassScanner.definePlugin(new BarrelDialogue()); - ClassScanner.definePlugin(new WinchDialogue()); - ClassScanner.definePlugin(new MineCartDialogue()); - ClassScanner.definePlugin(new AnnaCartHandler()); - ClassScanner.definePlugin(new AnnaCartCutscene()); - ClassScanner.definePlugin(new AnnaWinchHandler()); - ClassScanner.definePlugin(new WinchCutscene()); - ClassScanner.definePlugin(new CartDialogue()); - return this; - } - - @Override - public boolean handle(final Player player, Node node, String option) { - final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); - final int id = node.getId(); - switch (option) { - case "read": - player.getDialogueInterpreter().sendDialogue("The plans look very technical! But you can see that this item will", "require a bronze bar and at least 10 feathers."); - break; - case "watch": - switch (id) { - case 2676: - case 2675: - player.getDialogueInterpreter().sendDialogue("You watch the doors for some time. You notice that only slaves seem", "to do down there. You might be able to sneak down if you pass as a", "slave."); - break; - default: - player.getDialogueInterpreter().sendDialogue("You watch the Mercenary Captain for some time. He has a large", "metal key attached to his belt. You notice that he usually gets his", "men to do his dirty work."); - break; - } - break; - case "walk through": - switch (id) { - case 2698: - case 2699: - if (quest.getStage(player) < 60) { - player.getDialogueInterpreter().sendDialogues(5001, null, "Hey you! You're not allowed in there."); - break; - } - if (!TouristTrap.hasSlaveClothes(player)) { - player.getDialogueInterpreter().sendDialogues(5001, null, "Hey you're not a slave!"); - break; - } - player.getProperties().setTeleportLocation(player.getLocation().transform(player.getLocation().getX() >= 3284 ? -4 : 4, 0, 0)); - player.getPacketDispatch().sendMessages("You walk into the darkness of the cavern...", "... and emerge in a different part of this huge underground complex."); - break; - } - break; - case "look": - player.getDialogueInterpreter().sendDialogues(823, null, "Let me out of here, I feel sick!"); - break; - case "drop": - player.getDialogueInterpreter().sendDialogues(823, null, "Don't let me out!"); - break; - case "open": - switch (id) { - case 2688: - case 2687: - if (!player.getInventory().containsItem(TouristTrap.WROUGHT_IRON_KEY)) { - player.getPacketDispatch().sendMessage("This gate looks like it needs a key to open it."); - break; - } - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - break; - case 2686: - case 2685: - player.getDialogueInterpreter().sendDialogues(4999, null, "Hey, move away from the gate. There's nothing", "interesting for you here."); - break; - case 2677: - if (!player.getInventory().containsItem(TouristTrap.BEDABIN_KEY)) { - player.getPacketDispatch().sendMessage("This chest needs a key to unlock it."); - break; - } - if (quest.getStage(player) <= 54 && quest.getStage(player) != 53) { - player.getPacketDispatch().sendMessage("The captain spots you before you manage to open the chest..."); - player.lock(3); - GameWorld.getPulser().submit(new Pulse(2, player) { - @Override - public boolean pulse() { - player.getDialogueInterpreter().open(831, RegionManager.getNpc(player, 831)); - return true; - } - }); - } else if (quest.getStage(player) == 53) { - if (!player.hasItem(TouristTrap.TECHNICAL_PLANS)) { - player.getDialogueInterpreter().sendItemMessage(TouristTrap.TECHNICAL_PLANS, "While the Captain's distracted, you quickly unlock the", "chest with the Bedabins' copy of the key. You take out", "the plans."); - player.getInventory().add(TouristTrap.TECHNICAL_PLANS, player); - } - } - break; - case 2690: - case 2691: - player.setAttribute("ana-delay", GameWorld.getTicks() + 2); - player.getProperties().setTeleportLocation(Location.create(3301, 3035, 0)); - break; - case 2676: - case 2675: - if (!TouristTrap.hasSlaveClothes(player)) { - player.getDialogueInterpreter().sendDialogues(4997, null, "Watch it! Only slaves can travel into the mine."); - break; - } - player.setAttribute("ana-delay", GameWorld.getTicks() + 2); - player.getProperties().setTeleportLocation(Location.create(3278, 9427, 0)); - player.getDialogueInterpreter().sendDialogue("The huge doors open into a dark, dank and smelly tunnel. The", "associated smells of a hundred sweaty miners greets your nostrils.", "And your ears ring with the 'CLANG CLANG CLANG' as metal hits", "rock."); - break; - case 2674: - case 2673: - if (quest.getStage(player) > 60 && quest.getStage(player) < 98 && player.getInventory().containsItem(TouristTrap.ANNA_BARREL)) { - player.lock(); - player.getDialogueInterpreter().sendDialogues(4999, null, true, "Would you like me to take that heavy barrel", "for you?"); - GameWorld.getPulser().submit(new Pulse(4, player) { - int counter; - - @Override - public boolean pulse() { - switch (++counter) { - case 1: - player.getDialogueInterpreter().sendDialogues(player, null, "No, please don't."); - break; - case 2: - player.getDialogueInterpreter().close(); - player.getPacketDispatch().sendMessage("The guards search you!"); - break; - case 3: - player.getPacketDispatch().sendMessage("You are roughed up by the guards and manhandled into a cell."); - break; - case 4: - player.unlock(); - player.getInventory().remove(TouristTrap.ANNA_BARREL); - TouristTrap.addConfig(player, (1 << 4)); - quest.setStage(player, 61); - player.getProperties().setTeleportLocation(Location.create(3285, 3034, 0)); - return true; - } - return false; - } - }); - return true; - } - if (node.getLocation().withinDistance(new Location(3273, 3028, 0)) && !((player.getLocation().getX() >= 3274))) { - if (!player.getInventory().containsItem(TouristTrap.METAL_KEY)) { - player.getPacketDispatch().sendMessage("The gate needs a key in order to be opened."); - return true; - } - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - player.getPacketDispatch().sendMessage("The guards search you thoroughly as you go through the gates."); - return true; - } - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - break; - case 2689: - if (!player.getInventory().containsItem(TouristTrap.CELL_DOOR_KEY)) { - player.getPacketDispatch().sendMessage("The door seems to be pretty locked."); - break; - } - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - break; - case 1528: - SceneryBuilder.replace((Scenery) node, ((Scenery) node).transform(1529)); - break; - } - break; - case "close": - if (id == 1529) { - SceneryBuilder.replace((Scenery) node, ((Scenery) node).transform(1528)); - } - break; - case "look-in": - case "look in": - switch (id) { - case 2681: - case 18962: - case 18963: - player.getDialogueInterpreter().sendDialogue("This looks like an empty mining barrel. Slaves use this to load up the", "rocks and stones that they're mining."); - break; - case 2680: - player.getDialogueInterpreter().sendDialogue("You search the full barrel... It's full of rocks."); - break; - } - break; - case "use": - if (id == 18951) { - player.getDialogueInterpreter().open("winch dialogue"); - } - break; - case "search": - switch (id) { - case 2688: - case 2687: - player.getDialogueInterpreter().sendDialogue("These wrought iron gates look like they're designed to keep people out.", "it looks like you'll need a key to get past these."); - break; - case 2686: - case 2685: - player.getDialogueInterpreter().sendDialogue("It looks as if this is where very difficult prisoners are sent as a", "punishment."); - break; - case 2681: - case 18962: - case 18963: - player.getDialogueInterpreter().open("barrel dialogue", node); - break; - case 2680:// barrel of rocks. - player.getDialogueInterpreter().sendDialogue("This looks like a full mining barrel. Slaves use this to load up the", "rocks and stones that they're mining. This barrel is full of rocks."); - break; - case 2684:// cart - player.getDialogueInterpreter().open("cart dialogue", node); - break; - case 2678: - if (quest.getStage(player) == 51) { - quest.setStage(player, 52); - } - player.getDialogueInterpreter().sendItemMessage(9904, "You notice several books on the subject of sailing."); - break; - case 2673: - case 2674: - player.getDialogueInterpreter().sendDialogue("You see what looks like a mining compound. There seems to be people", "mining rocks. They look as if they're chained to the rocks and they're", "being watched over by the guards. It's not a very happy place."); - break; - case 18958: - case 18959: - if (quest.getStage(player) == 90) { - player.getDialogueInterpreter().open("ana cart dialogue"); - break; - } - player.getPacketDispatch().sendMessage("This looks like a mine cart which takes barrels out of the encampment to Al Kharid."); - break; - case 18899: - case 18898: - case 18878: - case 18879: - player.getDialogueInterpreter().sendDialogue("You search the footsteps more closely. You can see that there are", "five sets of footprints. One set of footprints seem lighter than the", "others. The four other footsteps were made by heavier people", "with boots."); - break; - case 18902: - if (hasItem(player, TouristTrap.CELL_DOOR_KEY)) { - player.getInventory().add(TouristTrap.CELL_DOOR_KEY, player); - player.getDialogueInterpreter().sendItemMessage(TouristTrap.CELL_DOOR_KEY, "You find a cell door key."); - break; - } else if (hasItem(player, TouristTrap.WROUGHT_IRON_KEY) && player.getQuestRepository().isComplete(Quests.THE_TOURIST_TRAP)) { - player.getInventory().add(TouristTrap.WROUGHT_IRON_KEY, player); - player.getDialogueInterpreter().sendItemMessage(TouristTrap.WROUGHT_IRON_KEY, "You find the key to the main gate."); - break; - } - player.getPacketDispatch().sendMessage("You search the captains desk while he's not looking..."); - player.getPacketDispatch().sendMessage("...but you find nothing of interest."); - break; - } - break; - case "operate": - if (quest.getStage(player) != 71) { - player.getDialogueInterpreter().sendDialogue("There doesn't seem anything to lift."); - break; - } - ActivityManager.start(player, "winch cutscene", false); - break; - case "look at": - switch (id) { - case 18888: - player.getDialogueInterpreter().sendDialogue("This looks like a winch, it probably brings rocks up from", "underground."); - break; - case 18951: - player.getDialogueInterpreter().sendDialogue("This looks like a lift of some sort. You see barrels of rocks being", "placed on the lift and they're hauled up to the surface."); - break; - case 2684: - if (node.getLocation().getX() == 3318) { - player.getDialogueInterpreter().sendDialogue("This mine cart is being loaded up with new rocks and stone.", "It gets sent to a different section of the mine for unloading."); - break; - } - player.getDialogueInterpreter().sendDialogue("This cart is being unloaded into this section of the mine. Before being", "sent back to another section for another load."); - break; - case 18958: - case 18959: - player.getDialogueInterpreter().sendDialogue("A sturdy looking cart for carrying barrels of rocks out of ", "the mining camp."); - break; - case 18900: - case 18899: - case 18898: - case 18887: - case 18886: - case 18885: - case 18884: - case 18883: - case 18882: - case 18881: - case 18880: - case 18879: - case 18878: - case 18877: - player.getDialogueInterpreter().sendDialogue("This looks like some disturbed sand. Footsteps seem to be heading off", "towards the South."); - break; - } - break; - case "talk-to": - switch (id) { - case 5002: - ((NPC) node).sendChat("Move along please, don't want any trouble today!"); - break; - case 36748: - player.getDialogueInterpreter().sendDialogues(player, null, "Mmm... looks like that camel would make a nice kebab."); - break; - case 4975: - case 4977: - case 4978: - case 4976: - ((NPC) node).sendChat("Hey leave me alone, can't you see that i'm busy?"); - break; - } - break; - case "bend": - player.animate(Animation.create(5037)); - GameWorld.getPulser().submit(new Pulse(5, player) { - @Override - public boolean pulse() { - player.getPacketDispatch().sendMessage("You bend the bars back."); - setVarp(player, 907, getVarp(player, 907) + 1); - return true; - } - }); - break; - case "escape": - player.getPacketDispatch().sendMessage("You prepare to squeeze through the bars."); - AgilityHandler.forceWalk(player, 0, player.getLocation(), player.getLocation().transform(player.getLocation().getX() <= node.getLocation().getX() ? 1 : -1, 0, 0), Animation.create(5038), 4, 0.0, null); - break; - case "climb": - player.getPacketDispatch().sendMessage("You scrape your hands and knees as you climb up."); - AgilityHandler.forceWalk(player, 0, player.getLocation(), Location.create(3279, 3037, 0), Animation.create(5041), 10, 0, null); - GameWorld.getPulser().submit(new Pulse(3, player) { - @Override - public boolean pulse() { - player.getAnimator().reset(); - return true; - } - }); - break; - case "climb-up": - if (id == 18923) { - if (player.getLocation().getX() <= 3278) { - return true; - } - player.animate(Animation.create(5039)); - GameWorld.getPulser().submit(new Pulse(6, player) { - @Override - public boolean pulse() { - player.getAnimator().reset(); - player.getProperties().setTeleportLocation(Location.create(3278, 3037, 0)); - return true; - } - }); - } - break; - case "climb-down": - if (id == 18924) { - if (player.getLocation().getX() <= 3273) { - return true; - } - AgilityHandler.forceWalk(player, 0, player.getLocation(), Location.create(3270, 3039, 0), Animation.create(5040), 20, 0, null); - GameWorld.getPulser().submit(new Pulse(3, player) { - @Override - public boolean pulse() { - player.getAnimator().reset(); - return true; - } - }); - } - break; - case "inspect": - if (id == 18875) { - sendDialogue(player, "You remember that Irena mentioned something about Ana wearing a red scarf before she left for the desert."); - } - break; - } - return true; - } - - @Override - public boolean isWalk(final Player player, Node node) { - return !(node instanceof Item); - } - - @Override - public boolean isWalk() { - return false; - } - - @Override - public Location getDestination(Node node, Node n) { - if (n.getId() == 18923) { - return new Location(3279, 3037, 0); - } - return null; - } - - /** - * Checks if the player contains an item. - * - * @param player the player. - * @param item the item. - * @return the item. - */ - private boolean hasItem(final Player player, final Item item) { - return !player.getInventory().containsItem(item) && !player.getBank().containsItem(item); - } - - /** - * The winch dialogue plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class WinchDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code WinchDialogue} {@code Object}. - */ - public WinchDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code WinchDialogue} {@code Object}. - * - * @param player the player. - */ - public WinchDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new WinchDialogue(player); - } - - @Override - public boolean open(Object... args) { - if (args.length >= 1) { - interpreter.sendDialogue("The guard notices the barrel (with Ana in it) that you're carrying."); - stage = 500; - return true; - } - interpreter.sendDialogues(4999, null, "Hey there, what do you want?"); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 500:// winch - interpreter.sendDialogues(5002, null, "Hey, that Barrel looks heavy, do you need a hand?"); - stage++; - break; - case 501: - player("Yes please."); - stage++; - break; - case 502: - interpreter.sendDialogue("The guard comes over and helps you. He takes one end of the", "barrel."); - stage++; - break; - case 503: - interpreter.sendDialogues(5002, null, "Blimey! This is heavy!"); - stage++; - break; - case 504: - interpreter.sendDialogues(823, null, "Why you cheeky....!"); - stage++; - break; - case 505: - interpreter.sendDialogues(5002, null, "- The guard looks around surprised at Ana's outburst. -", "What was that?"); - stage++; - break; - case 506: - player("Oh, it was nothing."); - stage++; - break; - case 507: - interpreter.sendDialogues(5002, null, "I could have sworn I heard something!"); - stage++; - break; - case 508: - interpreter.sendDialogues(823, null, "Yes you did you ignoramus."); - stage++; - break; - case 509: - interpreter.sendDialogues(5002, null, "What was that you said?"); - stage++; - break; - case 510: - player("I said you were very gregarious!"); - stage++; - break; - case 511: - interpreter.sendDialogues(823, null, "You creep!"); - stage++; - break; - case 512: - interpreter.sendDialogues(5002, null, "Oh, right, how very nice of you to say so.", "-- The guard seems flattered. --"); - stage++; - break; - case 513: - interpreter.sendDialogues(5002, null, "Anyway, let's get this barrel up to the surface, plenty", "more work for you to do!"); - stage++; - break; - case 514: - interpreter.sendDialogue("The guard places the barrel carefully on the lift platform."); - stage++; - break; - case 515: - interpreter.sendDialogues(5002, null, "Oh, there's no one operating the lift up top, hope this", "barrel isn't urgent? You'd better get back to work!"); - stage = 516; - break; - case 516: - player.getInventory().remove(TouristTrap.ANNA_BARREL); - player.getBank().remove(TouristTrap.ANNA_BARREL); - player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 71); - end(); - break; - case 0: - options("What is this thing?", "Can I use this?"); - stage++; - break; - case 1: - switch (buttonId) { - case 1: - player("What is this thing?"); - stage = 10; - break; - case 2: - player("Can I use this?"); - stage = 20; - break; - } - break; - case 10: - interpreter.sendDialogues(4999, null, "It is quite clearly a lift. Any fool can see that it's used to", "transport rock to the surface."); - stage++; - break; - case 11: - case 21: - end(); - break; - case 20: - interpreter.sendDialogues(4999, null, "Of course not, you'd be doing me out of a job. Anyway", "you haven't got any barrels that need to go to", "the surface."); - stage++; - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{DialogueInterpreter.getDialogueKey("winch dialogue")}; - } - - } - - /** - * The use with handler for anna on the cart. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class AnnaCartHandler extends UseWithHandler { - - /** - * Constructs a new {@code AnnaCartHandler} {@code Object}. - */ - public AnnaCartHandler() { - super(TouristTrap.ANNA_BARREL.getId()); - } - - @Override - public Plugin newInstance(Object arg) { - addHandler(2684, OBJECT_TYPE, this); - addHandler(18958, OBJECT_TYPE, this); - return this; - } - - @Override - public boolean handle(final NodeUsageEvent event) { - final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); - if (event.getUsedWith().getId() == 18958) {// cart - if (quest.getStage(player) == 72) { - player.lock(4); - player.animate(Animation.create(5050)); - GameWorld.getPulser().submit(new Pulse(3, player) { - @Override - public boolean pulse() { - player.getInventory().remove(event.getUsedItem()); - TouristTrap.addConfig(player, 4096 + (2048 + (1 << 4))); - quest.setStage(player, 80); - player.getDialogueInterpreter().sendDialogue("You place Ana (In the barrel) carefully on the cart. This was the last", "barrel to go on the cart, but the cart driver doesn't seem to be", "any rush to get going. And the desert heat will soon get to Ana."); - return true; - } - }); - } - return true; - } - if (!event.getUsedWith().getLocation().equals(Location.create(3318, 9430, 0))) { - return false; - } - if (quest.getStage(player) != 61) { - return false; - } - player.getDialogueInterpreter().sendDialogue("You carefully place Ana in the barrel into the mine", "cart. Soon the cart moves out of sight and then it", "returns."); - player.setAttribute("ana-delay", GameWorld.getTicks() + 100000000); - ActivityManager.start(player, "ana cart", false); - return true; - } - - /** - * The ana cart cutscene plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class AnnaCartCutscene extends CutscenePlugin { - - /** - * The paths. - */ - private static final Location[][] PATHS = new Location[][]{{Location.create(3315, 9417, 0), Location.create(3317, 9417, 0), Location.create(3318, 9418, 0), Location.create(3318, 9428, 0)}, {Location.create(3318, 9430, 0), Location.create(3318, 9418, 0), Location.create(3317, 9417, 0), Location.create(3316, 9417, 0), Location.create(3314, 9417, 0), Location.create(3303, 9417, 0)}}; - - /** - * Constructs a new {@code AnnaCartCutscene} {@code Object}. - */ - public AnnaCartCutscene() { - super("ana cart"); - } - - /** - * Constructs a new {@code AnnaCartCutscene} {@code Object}. - * - * @param player the player. - */ - public AnnaCartCutscene(final Player player) { - super("ana cart"); - this.player = player; - } - - @Override - public void open() { - super.open(); - player.setAttribute("ana-delay", GameWorld.getTicks() + 100000000); - player.faceLocation(base.transform(54, 22, 0)); - GameWorld.getPulser().submit(new Pulse(1, player) { - int counter; - NPC cart; - - @Override - public boolean pulse() { - switch (++counter) { - case 1: - player.animate(Animation.create(5052)); - break; - case 3: - SceneryBuilder.remove(RegionManager.getObject(base.transform(54, 22, 0))); - cart = NPC.create(4980, base.transform(54, 22, 0)); - cart.init(); - break; - case 4: - cart.getWalkingQueue().reset(); - for (Location l : PATHS[1]) { - Location loc = base.transform(l.getLocalX(), l.getLocalY(), 0); - cart.getWalkingQueue().addPath(loc.getX(), loc.getY()); - } - break; - case 18: - cart.clear(); - break; - case 22: - cart = NPC.create(4981, base.transform(51, 9, 0)); - cart.init(); - cart.getWalkingQueue().reset(); - for (Location l : PATHS[0]) { - Location loc = base.transform(l.getLocalX(), l.getLocalY(), 0); - cart.getWalkingQueue().addPath(loc.getX(), loc.getY()); - } - break; - case 33: - player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 70); - player.getInventory().remove(TouristTrap.ANNA_BARREL); - player.removeAttribute("ana-delay"); - AnnaCartCutscene.this.stop(true); - return true; - } - return false; - } - }); - } - - @Override - public ActivityPlugin newInstance(Player p) { - return new AnnaCartCutscene(p); - } - - @Override - public Location getSpawnLocation() { - return null; - } - - @Override - public Location getStartLocation() { - return base.transform(54, 23, 0); - } - - @Override - public void configure() { - region = DynamicRegion.create(13203); - setRegionBase(); - registerRegion(region.getId()); - } - } - } - - /** - * The cart dialogue plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class CartDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code CartDialogue} {@code Object}. - * - * @param player the player. - */ - public CartDialogue(final Player player) { - super(player); - } - - /** - * Constructs a new {@code CartDialogue} {@code Object}. - */ - public CartDialogue() { - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new CartDialogue(player); - } - - @Override - public boolean open(Object... args) { - interpreter.sendDialogue("There is space on the cart for you get on, would you like to try?"); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - options("Yes, I'll get on.", "No, I've got other plans."); - stage++; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendDialogue("You decide to climb onto the cart."); - stage++; - break; - case 2: - end(); - break; - } - break; - case 2: - player.lock(); - player.animate(ClimbActionHandler.CLIMB_UP); - GameWorld.getPulser().submit(new Pulse(1, player) { - int counter; - - @Override - public boolean pulse() { - switch (counter++) { - case 1: - player.getInterfaceManager().openOverlay(new Component(115)); - break; - case 4: - player.getDialogueInterpreter().sendDialogue("As soon as you get on the cart, it starts to move.", "Before too long you are past the gates. You jump off", "the cart taking Ana with you."); - break; - case 6: - player.unlock(); - player.getInterfaceManager().closeOverlay(); - player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 95); - player.getInterfaceManager().close(); - player.getProperties().setTeleportLocation(Location.create(3258, 3029, 0)); - player.getInventory().add(TouristTrap.ANNA_BARREL); - return true; - } - return false; - } - }); - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{DialogueInterpreter.getDialogueKey("ana cart dialogue")}; - } - - } - - /** - * The minecart dialogue plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class MineCartDialogue extends DialoguePlugin { - - /** - * The failing animation of getting in the cart. - */ - private static final Animation FAIL_ANIMATION = new Animation(5048); - - /** - * The jumping animation. - */ - private static final Animation JUMP_ANIMATION = new Animation(5049); - - /** - * The cart. - */ - private Scenery cart; - - /** - * Constructs a new {@code MineCartDialogue} {@code Object}. - */ - public MineCartDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code MineCartDialogue} {@code Object}. - * - * @param player the player. - */ - public MineCartDialogue(final Player player) { - super(player); - } - - @Override - public void init() { - super.init(); - ClassScanner.definePlugin(new MiningCartCutscene()); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new MineCartDialogue(player); - } - - @Override - public boolean open(Object... args) { - cart = (Scenery) args[0]; - if (player.getInventory().containsItem(TouristTrap.ANNA_BARREL)) { - player("There's not enough room for both of us."); - stage = -1; - return true; - } - interpreter.sendDialogue("You search the mine cart..."); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case -1: - end(); - break; - case 0: - interpreter.sendDialogue("There may be just enough space to squeeze yourself into the cart.", "Would you like to try?"); - stage++; - break; - case 1: - options("Yes, of course.", "No thanks, it looks pretty dangerous."); - stage++; - break; - case 2: - switch (buttonId) { - case 1: - end(); - enterCart(player); - break; - case 2: - end(); - break; - } - break; - } - return true; - } - - /** - * Method used to enter the cart. - * - * @param player the player. - */ - public void enterCart(final Player player) { - if (RandomFunction.random(3) == 1) { - player.lock(FAIL_ANIMATION.getDelay()); - player.animate(FAIL_ANIMATION); - player.getImpactHandler().manualHit(player, 2, HitsplatType.NORMAL); - player.getPacketDispatch().sendMessages("You fail to fit yourself into the cart in time before it starts its journey.", "You bang your head on the cart as you try to jump in."); - } else { - GameWorld.getPulser().submit(new Pulse(3, player) { - @Override - public boolean pulse() { - player.animate(JUMP_ANIMATION); - return true; - } - }); - ActivityManager.start(player, "mining cart", false, cart.getLocation().getX() == 3303 ? 0 : 1); - } - } - - /** - * The mining cart cutscene plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class MiningCartCutscene extends CutscenePlugin { - - /** - * The paths. - */ - private static final Location[][] PATHS = new Location[][]{{Location.create(3303, 9417, 0), Location.create(3316, 9417, 0), Location.create(3317, 9417, 0), Location.create(3318, 9418, 0), Location.create(3318, 9430, 0)}, {Location.create(3318, 9430, 0), Location.create(3318, 9418, 0), Location.create(3317, 9417, 0), Location.create(3303, 9417, 0)}}; - - /** - * The path index. - */ - private int index; - - /** - * Constructs a new {@code MiningCartCutscene} {@code Object}. - */ - public MiningCartCutscene() { - super("mining cart"); - } - - /** - * Constructs a new {@code MiningCartCutscene} {@code Object}. - * - * @param player the player. - */ - public MiningCartCutscene(final Player player) { - super("mining cart"); - this.player = player; - } - - @Override - public boolean start(final Player player, boolean login, Object... args) { - index = (int) args[0]; - return super.start(player, login, args); - } - - @Override - public void open() { - SceneryBuilder.remove(RegionManager.getObject(base.getLocation().transform(getPath()[0].getLocalX(), getPath()[0].getLocalY(), 0))); - SceneryBuilder.remove(RegionManager.getObject(base.getLocation().transform(getPath()[getPath().length - 1].getLocalX(), getPath()[getPath().length - 1].getLocalY(), 0))); - player.getAppearance().setAnimations(Animation.create(211)); - player.getAppearance().setRidingMinecart(true); - player.getAppearance().sync(); - player.getWalkingQueue().reset(); - for (Location l : getPath()) { - Location loc = base.transform(l.getLocalX(), l.getLocalY(), 0); - player.getWalkingQueue().addPath(loc.getX(), loc.getY(), true); - } - GameWorld.getPulser().submit(new Pulse(22, player) { - @Override - public boolean pulse() { - player.setAttribute("real-end", index == 0 ? Location.create(3319, 9431, 0) : Location.create(3303, 9416, 0)); - player.setAttribute("cutscene:original-loc", index == 0 ? Location.create(3319, 9431, 0) : Location.create(3303, 9416, 0)); - MiningCartCutscene.this.stop(true); - return true; - } - }); - } - - @Override - public void end() { - super.end(); - player.getAppearance().setDefaultAnimations(); - player.getAppearance().setRidingMinecart(false); - player.getAppearance().sync(); - } - - @Override - public void fade() { - if (index == 0) { - player.getDialogueInterpreter().sendDialogue("You appear in a large open room with what looks like lots of miners", "working away. This is a very rough looking area, the miners look like", "they're on their last legs."); - } else { - player.getDialogueInterpreter().sendDialogue("You appear back in the barrel loading room. A nearby slave looks", "surprised to see you popping out of the cart."); - } - } - - @Override - public ActivityPlugin newInstance(Player p) { - return new MiningCartCutscene(p); - } - - @Override - public Location getSpawnLocation() { - return null; - } - - @Override - public Location getStartLocation() { - return base.transform(getPath()[0].getLocalX(), getPath()[0].getLocalY(), 0); - } - - @Override - public void configure() { - region = DynamicRegion.create(13203); - setRegionBase(); - registerRegion(region.getId()); - } - - /** - * Gets the path index. - * - * @return the location. - */ - public Location[] getPath() { - return PATHS[index]; - } - } - - @Override - public int[] getIds() { - return new int[]{DialogueInterpreter.getDialogueKey("cart dialogue")}; - } - - } - - /** - * The winch cutscene plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class WinchCutscene extends CutscenePlugin { - - /** - * Constructs a new {@code WinchCutscene} {@code Object}. - */ - public WinchCutscene() { - super("winch cutscene"); - } - - /** - * Constructs a new {@code WinchCutscene} {@code Object}. - * - * @param player the player. - */ - public WinchCutscene(final Player player) { - super("winch cutscene"); - this.player = player; - } - - @Override - public ActivityPlugin newInstance(Player p) { - return new WinchCutscene(p); - } - - @Override - public void open() { - super.open(); - player.getPacketDispatch().sendMessage("You try to operate the winch."); - player.faceLocation(base.transform(15, 9, 0)); - player.animate(Animation.create(5054)); - GameWorld.getPulser().submit(new Pulse(AnimationDefinition.forId(5054).getDurationTicks(), player) { - @Override - public boolean pulse() { - TouristTrap.addConfig(player, 2048 + (1 << 4)); - WinchCutscene.this.stop(true); - player.getDialogueInterpreter().open(822, true, true); - return true; - } - }); - } - - @Override - public Location getSpawnLocation() { - return null; - } - - @Override - public Location getStartLocation() { - return base.transform(16, 10, 0); - } - - @Override - public void configure() { - region = DynamicRegion.create(13103); - setRegionBase(); - registerRegion(region.getId()); - } - - } - - /** - * The use with handler on the chest. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class BedabinKeyHandler extends UseWithHandler { - - /** - * Constructs a new {@code BedabinKeyHandler} {@code Object}. - */ - public BedabinKeyHandler() { - super(TouristTrap.BEDABIN_KEY.getId()); - } - - @Override - public Plugin newInstance(Object arg) { - addHandler(2677, OBJECT_TYPE, this); - return this; - } - - @Override - public boolean handle(NodeUsageEvent event) { - final Player player = event.getPlayer(); - player.getDialogueInterpreter().open(831, RegionManager.getNpc(player, 831)); - return true; - } - - } - - /** - * The barrel dialogue plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class BarrelDialogue extends DialoguePlugin { - - /** - * The scenery barrel. - */ - private Scenery barrel; - - /** - * The quest. - */ - private Quest quest; - - /** - * Constructs a new {@code BarrelDialogue} {@code Object}. - */ - public BarrelDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code BarrelDialogue} {@code Object}. - * - * @param player the player. - */ - public BarrelDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new BarrelDialogue(player); - } - - @Override - public boolean open(Object... args) { - barrel = (Scenery) args[0]; - quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); - if ((quest.getStage(player) == 70 || quest.getStage(player) == 72) && !player.hasItem(TouristTrap.ANNA_BARREL)) { - interpreter.sendDialogue("You search the barrels and find Ana."); - stage = 400; - return true; - } - if (player.getInventory().containsItem(TouristTrap.BARREL)) { - player.getPacketDispatch().sendMessage("You can only manage to have one of these at a time."); - end(); - return true; - } - interpreter.sendItemMessage(TouristTrap.BARREL, "This barrel is quite big. but you may be able to carry one. Would you like to take one?"); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 400:// finding anna. - interpreter.sendDialogues(823, null, "Let me out!"); - stage++; - break; - case 401: - if (!player.getInventory().hasSpaceFor(TouristTrap.ANNA_BARREL)) { - end(); - return true; - } - player.getPacketDispatch().sendMessage("You pick up Ana in a Barrel."); - player.getInventory().add(TouristTrap.ANNA_BARREL); - end(); - break; - case 402: - end(); - break; - case 0: - options("Yeah, cool!", "No thanks."); - stage++; - break; - case 1: - switch (buttonId) { - case 1: - interpreter.sendItemMessage(TouristTrap.BARREL, "You take the barrel, it's not heavy, just awkward."); - stage = 3; - break; - case 2: - end(); - break; - } - break; - case 3: - end(); - player.getInventory().add(TouristTrap.BARREL, player); - SceneryBuilder.remove(barrel); - GameWorld.getPulser().submit(new Pulse(40) { - @Override - public boolean pulse() { - SceneryBuilder.add(barrel); - return true; - } - }); - break; - - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{DialogueInterpreter.getDialogueKey("barrel dialogue")}; - } - - } - - /** - * The use with handler for the bedabin anvil. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class BedabinAnvilHandler extends UseWithHandler { - - /** - * Constructs a new {@code BedabinAnvilHandler} {@code Object}. - */ - public BedabinAnvilHandler() { - super(2349); - } - - @Override - public Plugin newInstance(Object arg) { - addHandler(2672, OBJECT_TYPE, this); - ClassScanner.definePlugin(new PrototypeDartHandler()); - ClassScanner.definePlugin(new BedabinAnvilDialogue()); - return this; - } - - @Override - public boolean handle(NodeUsageEvent event) { - final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); - if (quest.getStage(player) == 54 && player.getInventory().containsItem(TouristTrap.TECHNICAL_PLANS)) { - player.getDialogueInterpreter().open("bedabin-anvil"); - return true; - } else { - player.getPacketDispatch().sendMessage("You need technical plans in order to do this."); - } - return true; - } - - /** - * The handler used to handle the anna barrel on the winch. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class AnnaWinchHandler extends UseWithHandler { - - /** - * Constructs a new {@code AnnaWinchHandler} {@code Object}. - */ - public AnnaWinchHandler() { - super(TouristTrap.ANNA_BARREL.getId()); - } - - @Override - public Plugin newInstance(Object arg) { - addHandler(18951, OBJECT_TYPE, this); - return this; - } - - @Override - public boolean handle(NodeUsageEvent event) { - final Player player = event.getPlayer(); - final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); - if (!event.getUsedWith().getLocation().equals(Location.create(3292, 9423, 0))) { - return false; - } - if (quest.getStage(player) == 70) { - player.getDialogueInterpreter().open("winch dialogue", true); - return true; - } - return false; - } - - } - - /** - * The prototype dart creation handler. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class PrototypeDartHandler extends UseWithHandler { - - /** - * Constructs a new {@code PrototypeDartHandler} {@code Object}. - */ - public PrototypeDartHandler() { - super(314); - } - - @Override - public Plugin newInstance(Object arg) { - addHandler(TouristTrap.PROTOTYPE_DART_TIP.getId(), ITEM_TYPE, this); - ClassScanner.definePlugin(new ProtoTypeDialogue()); - return this; - } - - @Override - public boolean handle(NodeUsageEvent event) { - final Player player = event.getPlayer(); - player.getDialogueInterpreter().open("prototype dart"); - return true; - } - - /** - * The prototype dialogue plugin. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class ProtoTypeDialogue extends DialoguePlugin { - - /** - * The feathers item. - */ - private static final Item FEATHERS = new Item(314, 10); - - /** - * Constructs a new {@code ProtoTypeDialogue} {@code Object}. - * - * @param player the player. - */ - public ProtoTypeDialogue(final Player player) { - super(player); - } - - /** - * Constructs a new {@code ProtoTypeDialogue} {@code Object}. - */ - public ProtoTypeDialogue() { - /** - * empty. - */ - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new ProtoTypeDialogue(player); - } - - @Override - public boolean open(Object... args) { - if (!player.getInventory().containsItem(FEATHERS)) { - interpreter.sendDialogue("You need 10 feathers in order to do this."); - stage = 10; - return false; - } - interpreter.sendItemMessage(314, "You try to attach feathers to the bronze dart tip."); - stage = 1; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 1: - interpreter.sendDialogue("Following the plans is tricky, but you persevere."); - stage++; - break; - case 2: - interpreter.sendItemMessage(TouristTrap.PROTOTYPE_DART, "You successfully attach the feathers to the dart tip."); - stage++; - break; - case 3: - player.getInventory().remove(FEATHERS, TouristTrap.PROTOTYPE_DART_TIP); - player.getInventory().add(TouristTrap.PROTOTYPE_DART); - end(); - break; - case 4: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{DialogueInterpreter.getDialogueKey("prototype dart")}; - } - - } - } - - /** - * The bedabin dialogue plugin handler. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class BedabinAnvilDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code BedabinAnvilDialogue} {@code Object}. - */ - public BedabinAnvilDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code BedabinAnvilDialogue} {@code Object}. - * - * @param player the player. - */ - public BedabinAnvilDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new BedabinAnvilDialogue(player); - } - - @Override - public boolean open(Object... args) { - if (!player.getInventory().containsItem(TouristTrap.TECHNICAL_PLANS)) { - player.getPacketDispatch().sendMessage("You need the plans to do this."); - return false; - } - player.getDialogueInterpreter().sendItemMessage(TouristTrap.TECHNICAL_PLANS, "Do you want to follow the technical plans ?"); - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - options("Yes. I'd like to try.", "No, not just yet."); - stage++; - break; - case 1: - switch (buttonId) { - case 1: - end(); - player.getPulseManager().run(new ProtoTypePulse(player)); - break; - case 2: - end(); - break; - } - break; - } - return true; - } - - /** - * The skill pulse used to make a prototype dart. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class ProtoTypePulse extends SkillPulse { - - /** - * The hammer item. - */ - private static final Item HAMMER = new Item(2347); - - /** - * The ticks passed. - */ - private int ticks; - - /** - * Constructs a new {@code ProtoTypePulse} {@code Object}. - * - * @param player the player. - */ - public ProtoTypePulse(Player player) { - super(player, null); - } - - @Override - public boolean checkRequirements() { - if (!player.getInventory().hasSpaceFor(TouristTrap.PROTOTYPE_DART_TIP)) { - player.getPacketDispatch().sendMessage("Not enough inventory space."); - return false; - } - if (!player.getInventory().containsItem(HAMMER)) { - player.getPacketDispatch().sendMessage("You need a hammer in order to work metal with."); - return false; - } - return player.getInventory().containsItem(Bar.BRONZE.getProduct()); - } - - @Override - public void animate() { - if (ticks % 4 == 0) { - player.animate(Animation.create(898)); - } - } - - @Override - public boolean reward() { - if (++ticks % 4 != 0) { - return false; - } - if (ticks == 4) { - player.getDialogueInterpreter().sendPlainMessage(true, "You begin experimenting in forging the weapon..."); - } else if (ticks == 8) { - player.getInventory().remove(Bar.BRONZE.getProduct()); - player.getInventory().add(TouristTrap.PROTOTYPE_DART_TIP); - player.getDialogueInterpreter().sendItemMessage(TouristTrap.PROTOTYPE_DART_TIP, "You follow the plans carefully, and after some careful", "work, you finally manage to forge a sharp, pointed...", "dart tip."); - return true; - } - return false; - } - - @Override - public void stop() { - super.stop(); - } - - } - - @Override - public int[] getIds() { - return new int[]{DialogueInterpreter.getDialogueKey("bedabin-anvil")}; - } - - } - } + @Override + public Plugin newInstance(Object arg) throws Throwable { + SceneryDefinition.forId(2673).getHandlers().put("option:open", this); + SceneryDefinition.forId(2674).getHandlers().put("option:open", this); + SceneryDefinition.forId(2673).getHandlers().put("option:search", this); + SceneryDefinition.forId(2674).getHandlers().put("option:search", this); + SceneryDefinition.forId(2688).getHandlers().put("option:open", this); + SceneryDefinition.forId(2688).getHandlers().put("option:search", this); + SceneryDefinition.forId(2687).getHandlers().put("option:open", this); + SceneryDefinition.forId(2687).getHandlers().put("option:search", this); + SceneryDefinition.forId(2685).getHandlers().put("option:open", this); + SceneryDefinition.forId(2685).getHandlers().put("option:open", this); + SceneryDefinition.forId(2686).getHandlers().put("option:search", this); + SceneryDefinition.forId(2686).getHandlers().put("option:search", this); + SceneryDefinition.forId(18958).getHandlers().put("option:search", this); + SceneryDefinition.forId(18958).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18959).getHandlers().put("option:search", this); + SceneryDefinition.forId(18959).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18888).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18888).getHandlers().put("option:operate", this); + SceneryDefinition.forId(36748).getHandlers().put("option:talk-to", this); + SceneryDefinition.forId(18869).getHandlers().put("option:bend", this); + SceneryDefinition.forId(18870).getHandlers().put("option:escape", this); + SceneryDefinition.forId(2689).getHandlers().put("option:open", this); + SceneryDefinition.forId(1528).getHandlers().put("option:open", this); + SceneryDefinition.forId(1529).getHandlers().put("option:close", this); + SceneryDefinition.forId(18899).getHandlers().put("option:search", this); + SceneryDefinition.forId(18899).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18878).getHandlers().put("option:search", this); + SceneryDefinition.forId(18878).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18879).getHandlers().put("option:search", this); + SceneryDefinition.forId(18879).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18898).getHandlers().put("option:search", this); + SceneryDefinition.forId(18898).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18902).getHandlers().put("option:search", this); + SceneryDefinition.forId(18871).getHandlers().put("option:climb", this); + SceneryDefinition.forId(18923).getHandlers().put("option:climb-up", this); + SceneryDefinition.forId(18924).getHandlers().put("option:climb-down", this); + SceneryDefinition.forId(2676).getHandlers().put("option:open", this); + SceneryDefinition.forId(2675).getHandlers().put("option:open", this); + SceneryDefinition.forId(2676).getHandlers().put("option:watch", this); + SceneryDefinition.forId(2675).getHandlers().put("option:watch", this); + SceneryDefinition.forId(2690).getHandlers().put("option:open", this); + SceneryDefinition.forId(2691).getHandlers().put("option:open", this); + SceneryDefinition.forId(2698).getHandlers().put("option:walk through", this); + SceneryDefinition.forId(2699).getHandlers().put("option:walk through", this); + SceneryDefinition.forId(2677).getHandlers().put("option:open", this); + SceneryDefinition.forId(2678).getHandlers().put("option:search", this); + SceneryDefinition.forId(2684).getHandlers().put("option:search", this); + SceneryDefinition.forId(2684).getHandlers().put("option:look at", this); + SceneryDefinition.forId(2680).getHandlers().put("option:search", this); + SceneryDefinition.forId(2680).getHandlers().put("option:look-in", this); + SceneryDefinition.forId(2681).getHandlers().put("option:search", this); + SceneryDefinition.forId(2681).getHandlers().put("option:look in", this); + SceneryDefinition.forId(18962).getHandlers().put("option:search", this); + SceneryDefinition.forId(18962).getHandlers().put("option:look in", this); + SceneryDefinition.forId(18963).getHandlers().put("option:search", this); + SceneryDefinition.forId(18963).getHandlers().put("option:look in", this); + SceneryDefinition.forId(18951).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18951).getHandlers().put("option:use", this); + SceneryDefinition.forId(2684).getHandlers().put("option:search", this); + SceneryDefinition.forId(2684).getHandlers().put("option:look at", this); + SceneryDefinition.forId(18875).getHandlers().put("option:inspect", this); + NPCDefinition.forId(830).getHandlers().put("option:watch", this); + NPCDefinition.forId(4975).getHandlers().put("option:talk-to", this); + NPCDefinition.forId(4976).getHandlers().put("option:talk-to", this); + NPCDefinition.forId(4977).getHandlers().put("option:talk-to", this); + NPCDefinition.forId(4978).getHandlers().put("option:talk-to", this); + NPCDefinition.forId(5002).getHandlers().put("option:talk-to", this); + TouristTrap.TECHNICAL_PLANS.getDefinition().getHandlers().put("option:read", this); + TouristTrap.ANNA_BARREL.getDefinition().getHandlers().put("option:look", this); + TouristTrap.ANNA_BARREL.getDefinition().getHandlers().put("option:drop", this); + ClassScanner.definePlugin(new BedabinKeyHandler()); + ClassScanner.definePlugin(new BedabinAnvilHandler()); + ClassScanner.definePlugin(new BarrelDialogue()); + ClassScanner.definePlugin(new WinchDialogue()); + ClassScanner.definePlugin(new MineCartDialogue()); + ClassScanner.definePlugin(new AnnaCartHandler()); + ClassScanner.definePlugin(new AnnaCartCutscene()); + ClassScanner.definePlugin(new AnnaWinchHandler()); + ClassScanner.definePlugin(new WinchCutscene()); + ClassScanner.definePlugin(new CartDialogue()); + return this; + } + + @Override + public boolean handle(final Player player, Node node, String option) { + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); + final int id = node.getId(); + switch (option) { + case "read": + player.getDialogueInterpreter().sendDialogue("The plans look very technical! But you can see that this item will", "require a bronze bar and at least 10 feathers."); + break; + case "watch": + switch (id) { + case 2676: + case 2675: + player.getDialogueInterpreter().sendDialogue("You watch the doors for some time. You notice that only slaves seem", "to do down there. You might be able to sneak down if you pass as a", "slave."); + break; + default: + player.getDialogueInterpreter().sendDialogue("You watch the Mercenary Captain for some time. He has a large", "metal key attached to his belt. You notice that he usually gets his", "men to do his dirty work."); + break; + } + break; + case "walk through": + switch (id) { + case 2698: + case 2699: + if (quest.getStage(player) < 60) { + player.getDialogueInterpreter().sendDialogues(5001, null, "Hey you! You're not allowed in there."); + break; + } + if (!TouristTrap.hasSlaveClothes(player)) { + player.getDialogueInterpreter().sendDialogues(5001, null, "Hey you're not a slave!"); + break; + } + player.getProperties().setTeleportLocation(player.getLocation().transform(player.getLocation().getX() >= 3284 ? -4 : 4, 0, 0)); + player.getPacketDispatch().sendMessages("You walk into the darkness of the cavern...", "... and emerge in a different part of this huge underground complex."); + break; + } + break; + case "look": + player.getDialogueInterpreter().sendDialogues(823, null, "Let me out of here, I feel sick!"); + break; + case "drop": + player.getDialogueInterpreter().sendDialogues(823, null, "Don't let me out!"); + break; + case "open": + switch (id) { + case 2688: + case 2687: + if (!player.getInventory().containsItem(TouristTrap.WROUGHT_IRON_KEY)) { + player.getPacketDispatch().sendMessage("This gate looks like it needs a key to open it."); + break; + } + DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); + break; + case 2686: + case 2685: + player.getDialogueInterpreter().sendDialogues(4999, null, "Hey, move away from the gate. There's nothing", "interesting for you here."); + break; + case 2677: + if (!player.getInventory().containsItem(TouristTrap.BEDABIN_KEY)) { + player.getPacketDispatch().sendMessage("This chest needs a key to unlock it."); + break; + } + if (quest.getStage(player) <= 54 && quest.getStage(player) != 53) { + player.getPacketDispatch().sendMessage("The captain spots you before you manage to open the chest..."); + player.lock(3); + GameWorld.getPulser().submit(new Pulse(2, player) { + @Override + public boolean pulse() { + player.getDialogueInterpreter().open(831, RegionManager.getNpc(player.getLocation(), 831, 16)); + return true; + } + }); + } else if (quest.getStage(player) == 53) { + if (!player.hasItem(TouristTrap.TECHNICAL_PLANS)) { + player.getDialogueInterpreter().sendItemMessage(TouristTrap.TECHNICAL_PLANS, "While the Captain's distracted, you quickly unlock the", "chest with the Bedabins' copy of the key. You take out", "the plans."); + player.getInventory().add(TouristTrap.TECHNICAL_PLANS, player); + } + } + break; + case 2690: + case 2691: + player.setAttribute("ana-delay", GameWorld.getTicks() + 2); + player.getProperties().setTeleportLocation(Location.create(3301, 3035, 0)); + break; + case 2676: + case 2675: + if (!TouristTrap.hasSlaveClothes(player)) { + player.getDialogueInterpreter().sendDialogues(4997, null, "Watch it! Only slaves can travel into the mine."); + break; + } + player.setAttribute("ana-delay", GameWorld.getTicks() + 2); + player.getProperties().setTeleportLocation(Location.create(3278, 9427, 0)); + player.getDialogueInterpreter().sendDialogue("The huge doors open into a dark, dank and smelly tunnel. The", "associated smells of a hundred sweaty miners greets your nostrils.", "And your ears ring with the 'CLANG CLANG CLANG' as metal hits", "rock."); + break; + case 2674: + case 2673: + if (quest.getStage(player) > 60 && quest.getStage(player) < 98 && player.getInventory().containsItem(TouristTrap.ANNA_BARREL)) { + player.lock(); + player.getDialogueInterpreter().sendDialogues(4999, null, true, "Would you like me to take that heavy barrel", "for you?"); + GameWorld.getPulser().submit(new Pulse(4, player) { + int counter; + + @Override + public boolean pulse() { + switch (++counter) { + case 1: + player.getDialogueInterpreter().sendDialogues(player, null, "No, please don't."); + break; + case 2: + player.getDialogueInterpreter().close(); + player.getPacketDispatch().sendMessage("The guards search you!"); + break; + case 3: + player.getPacketDispatch().sendMessage("You are roughed up by the guards and manhandled into a cell."); + break; + case 4: + player.unlock(); + player.getInventory().remove(TouristTrap.ANNA_BARREL); + TouristTrap.addConfig(player, (1 << 4)); + quest.setStage(player, 61); + player.getProperties().setTeleportLocation(Location.create(3285, 3034, 0)); + return true; + } + return false; + } + }); + return true; + } + if (node.getLocation().withinDistance(new Location(3273, 3028, 0)) && !((player.getLocation().getX() >= 3274))) { + if (!player.getInventory().containsItem(TouristTrap.METAL_KEY)) { + player.getPacketDispatch().sendMessage("The gate needs a key in order to be opened."); + return true; + } + DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); + player.getPacketDispatch().sendMessage("The guards search you thoroughly as you go through the gates."); + return true; + } + DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); + break; + case 2689: + if (!player.getInventory().containsItem(TouristTrap.CELL_DOOR_KEY)) { + player.getPacketDispatch().sendMessage("The door seems to be pretty locked."); + break; + } + DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); + break; + case 1528: + SceneryBuilder.replace((Scenery) node, ((Scenery) node).transform(1529)); + break; + } + break; + case "close": + if (id == 1529) { + SceneryBuilder.replace((Scenery) node, ((Scenery) node).transform(1528)); + } + break; + case "look-in": + case "look in": + switch (id) { + case 2681: + case 18962: + case 18963: + player.getDialogueInterpreter().sendDialogue("This looks like an empty mining barrel. Slaves use this to load up the", "rocks and stones that they're mining."); + break; + case 2680: + player.getDialogueInterpreter().sendDialogue("You search the full barrel... It's full of rocks."); + break; + } + break; + case "use": + if (id == 18951) { + player.getDialogueInterpreter().open("winch dialogue"); + } + break; + case "search": + switch (id) { + case 2688: + case 2687: + player.getDialogueInterpreter().sendDialogue("These wrought iron gates look like they're designed to keep people out.", "it looks like you'll need a key to get past these."); + break; + case 2686: + case 2685: + player.getDialogueInterpreter().sendDialogue("It looks as if this is where very difficult prisoners are sent as a", "punishment."); + break; + case 2681: + case 18962: + case 18963: + player.getDialogueInterpreter().open("barrel dialogue", node); + break; + case 2680:// barrel of rocks. + player.getDialogueInterpreter().sendDialogue("This looks like a full mining barrel. Slaves use this to load up the", "rocks and stones that they're mining. This barrel is full of rocks."); + break; + case 2684:// cart + player.getDialogueInterpreter().open("cart dialogue", node); + break; + case 2678: + if (quest.getStage(player) == 51) { + quest.setStage(player, 52); + } + player.getDialogueInterpreter().sendItemMessage(9904, "You notice several books on the subject of sailing."); + break; + case 2673: + case 2674: + player.getDialogueInterpreter().sendDialogue("You see what looks like a mining compound. There seems to be people", "mining rocks. They look as if they're chained to the rocks and they're", "being watched over by the guards. It's not a very happy place."); + break; + case 18958: + case 18959: + if (quest.getStage(player) == 90) { + player.getDialogueInterpreter().open("ana cart dialogue"); + break; + } + player.getPacketDispatch().sendMessage("This looks like a mine cart which takes barrels out of the encampment to Al Kharid."); + break; + case 18899: + case 18898: + case 18878: + case 18879: + player.getDialogueInterpreter().sendDialogue("You search the footsteps more closely. You can see that there are", "five sets of footprints. One set of footprints seem lighter than the", "others. The four other footsteps were made by heavier people", "with boots."); + break; + case 18902: + if (hasItem(player, TouristTrap.CELL_DOOR_KEY)) { + player.getInventory().add(TouristTrap.CELL_DOOR_KEY, player); + player.getDialogueInterpreter().sendItemMessage(TouristTrap.CELL_DOOR_KEY, "You find a cell door key."); + break; + } else if (hasItem(player, TouristTrap.WROUGHT_IRON_KEY) && player.getQuestRepository().isComplete(Quests.THE_TOURIST_TRAP)) { + player.getInventory().add(TouristTrap.WROUGHT_IRON_KEY, player); + player.getDialogueInterpreter().sendItemMessage(TouristTrap.WROUGHT_IRON_KEY, "You find the key to the main gate."); + break; + } + player.getPacketDispatch().sendMessage("You search the captains desk while he's not looking..."); + player.getPacketDispatch().sendMessage("...but you find nothing of interest."); + break; + } + break; + case "operate": + if (quest.getStage(player) != 71) { + player.getDialogueInterpreter().sendDialogue("There doesn't seem anything to lift."); + break; + } + ActivityManager.start(player, "winch cutscene", false); + break; + case "look at": + switch (id) { + case 18888: + player.getDialogueInterpreter().sendDialogue("This looks like a winch, it probably brings rocks up from", "underground."); + break; + case 18951: + player.getDialogueInterpreter().sendDialogue("This looks like a lift of some sort. You see barrels of rocks being", "placed on the lift and they're hauled up to the surface."); + break; + case 2684: + if (node.getLocation().getX() == 3318) { + player.getDialogueInterpreter().sendDialogue("This mine cart is being loaded up with new rocks and stone.", "It gets sent to a different section of the mine for unloading."); + break; + } + player.getDialogueInterpreter().sendDialogue("This cart is being unloaded into this section of the mine. Before being", "sent back to another section for another load."); + break; + case 18958: + case 18959: + player.getDialogueInterpreter().sendDialogue("A sturdy looking cart for carrying barrels of rocks out of ", "the mining camp."); + break; + case 18900: + case 18899: + case 18898: + case 18887: + case 18886: + case 18885: + case 18884: + case 18883: + case 18882: + case 18881: + case 18880: + case 18879: + case 18878: + case 18877: + player.getDialogueInterpreter().sendDialogue("This looks like some disturbed sand. Footsteps seem to be heading off", "towards the South."); + break; + } + break; + case "talk-to": + switch (id) { + case 5002: + ((NPC) node).sendChat("Move along please, don't want any trouble today!"); + break; + case 36748: + player.getDialogueInterpreter().sendDialogues(player, null, "Mmm... looks like that camel would make a nice kebab."); + break; + case 4975: + case 4977: + case 4978: + case 4976: + ((NPC) node).sendChat("Hey leave me alone, can't you see that i'm busy?"); + break; + } + break; + case "bend": + player.animate(Animation.create(5037)); + GameWorld.getPulser().submit(new Pulse(5, player) { + @Override + public boolean pulse() { + player.getPacketDispatch().sendMessage("You bend the bars back."); + setVarp(player, 907, getVarp(player, 907) + 1); + return true; + } + }); + break; + case "escape": + player.getPacketDispatch().sendMessage("You prepare to squeeze through the bars."); + AgilityHandler.forceWalk(player, 0, player.getLocation(), player.getLocation().transform(player.getLocation().getX() <= node.getLocation().getX() ? 1 : -1, 0, 0), Animation.create(5038), 4, 0.0, null); + break; + case "climb": + player.getPacketDispatch().sendMessage("You scrape your hands and knees as you climb up."); + AgilityHandler.forceWalk(player, 0, player.getLocation(), Location.create(3279, 3037, 0), Animation.create(5041), 10, 0, null); + GameWorld.getPulser().submit(new Pulse(3, player) { + @Override + public boolean pulse() { + player.getAnimator().reset(); + return true; + } + }); + break; + case "climb-up": + if (id == 18923) { + if (player.getLocation().getX() <= 3278) { + return true; + } + player.animate(Animation.create(5039)); + GameWorld.getPulser().submit(new Pulse(6, player) { + @Override + public boolean pulse() { + player.getAnimator().reset(); + player.getProperties().setTeleportLocation(Location.create(3278, 3037, 0)); + return true; + } + }); + } + break; + case "climb-down": + if (id == 18924) { + if (player.getLocation().getX() <= 3273) { + return true; + } + AgilityHandler.forceWalk(player, 0, player.getLocation(), Location.create(3270, 3039, 0), Animation.create(5040), 20, 0, null); + GameWorld.getPulser().submit(new Pulse(3, player) { + @Override + public boolean pulse() { + player.getAnimator().reset(); + return true; + } + }); + } + break; + case "inspect": + if (id == 18875) { + sendDialogue(player, "You remember that Irena mentioned something about Ana wearing a red scarf before she left for the desert."); + } + break; + } + return true; + } + + @Override + public boolean isWalk(final Player player, Node node) { + return !(node instanceof Item); + } + + @Override + public boolean isWalk() { + return false; + } + + @Override + public Location getDestination(Node node, Node n) { + if (n.getId() == 18923) { + return new Location(3279, 3037, 0); + } + return null; + } + + /** + * Checks if the player contains an item. + * + * @param player the player. + * @param item the item. + * @return the item. + */ + private boolean hasItem(final Player player, final Item item) { + return !player.getInventory().containsItem(item) && !player.getBank().containsItem(item); + } + + /** + * The winch dialogue plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class WinchDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code WinchDialogue} {@code Object}. + */ + public WinchDialogue() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code WinchDialogue} {@code Object}. + * + * @param player the player. + */ + public WinchDialogue(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new WinchDialogue(player); + } + + @Override + public boolean open(Object... args) { + if (args.length >= 1) { + interpreter.sendDialogue("The guard notices the barrel (with Ana in it) that you're carrying."); + stage = 500; + return true; + } + interpreter.sendDialogues(4999, null, "Hey there, what do you want?"); + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 500:// winch + interpreter.sendDialogues(5002, null, "Hey, that Barrel looks heavy, do you need a hand?"); + stage++; + break; + case 501: + player("Yes please."); + stage++; + break; + case 502: + interpreter.sendDialogue("The guard comes over and helps you. He takes one end of the", "barrel."); + stage++; + break; + case 503: + interpreter.sendDialogues(5002, null, "Blimey! This is heavy!"); + stage++; + break; + case 504: + interpreter.sendDialogues(823, null, "Why you cheeky....!"); + stage++; + break; + case 505: + interpreter.sendDialogues(5002, null, "- The guard looks around surprised at Ana's outburst. -", "What was that?"); + stage++; + break; + case 506: + player("Oh, it was nothing."); + stage++; + break; + case 507: + interpreter.sendDialogues(5002, null, "I could have sworn I heard something!"); + stage++; + break; + case 508: + interpreter.sendDialogues(823, null, "Yes you did you ignoramus."); + stage++; + break; + case 509: + interpreter.sendDialogues(5002, null, "What was that you said?"); + stage++; + break; + case 510: + player("I said you were very gregarious!"); + stage++; + break; + case 511: + interpreter.sendDialogues(823, null, "You creep!"); + stage++; + break; + case 512: + interpreter.sendDialogues(5002, null, "Oh, right, how very nice of you to say so.", "-- The guard seems flattered. --"); + stage++; + break; + case 513: + interpreter.sendDialogues(5002, null, "Anyway, let's get this barrel up to the surface, plenty", "more work for you to do!"); + stage++; + break; + case 514: + interpreter.sendDialogue("The guard places the barrel carefully on the lift platform."); + stage++; + break; + case 515: + interpreter.sendDialogues(5002, null, "Oh, there's no one operating the lift up top, hope this", "barrel isn't urgent? You'd better get back to work!"); + stage = 516; + break; + case 516: + player.getInventory().remove(TouristTrap.ANNA_BARREL); + player.getBank().remove(TouristTrap.ANNA_BARREL); + player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 71); + end(); + break; + case 0: + options("What is this thing?", "Can I use this?"); + stage++; + break; + case 1: + switch (buttonId) { + case 1: + player("What is this thing?"); + stage = 10; + break; + case 2: + player("Can I use this?"); + stage = 20; + break; + } + break; + case 10: + interpreter.sendDialogues(4999, null, "It is quite clearly a lift. Any fool can see that it's used to", "transport rock to the surface."); + stage++; + break; + case 11: + case 21: + end(); + break; + case 20: + interpreter.sendDialogues(4999, null, "Of course not, you'd be doing me out of a job. Anyway", "you haven't got any barrels that need to go to", "the surface."); + stage++; + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{DialogueInterpreter.getDialogueKey("winch dialogue")}; + } + + } + + /** + * The use with handler for anna on the cart. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class AnnaCartHandler extends UseWithHandler { + + /** + * Constructs a new {@code AnnaCartHandler} {@code Object}. + */ + public AnnaCartHandler() { + super(TouristTrap.ANNA_BARREL.getId()); + } + + @Override + public Plugin newInstance(Object arg) { + addHandler(2684, OBJECT_TYPE, this); + addHandler(18958, OBJECT_TYPE, this); + return this; + } + + @Override + public boolean handle(final NodeUsageEvent event) { + final Player player = event.getPlayer(); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); + if (event.getUsedWith().getId() == 18958) {// cart + if (quest.getStage(player) == 72) { + player.lock(4); + player.animate(Animation.create(5050)); + GameWorld.getPulser().submit(new Pulse(3, player) { + @Override + public boolean pulse() { + player.getInventory().remove(event.getUsedItem()); + TouristTrap.addConfig(player, 4096 + (2048 + (1 << 4))); + quest.setStage(player, 80); + player.getDialogueInterpreter().sendDialogue("You place Ana (In the barrel) carefully on the cart. This was the last", "barrel to go on the cart, but the cart driver doesn't seem to be", "any rush to get going. And the desert heat will soon get to Ana."); + return true; + } + }); + } + return true; + } + if (!event.getUsedWith().getLocation().equals(Location.create(3318, 9430, 0))) { + return false; + } + if (quest.getStage(player) != 61) { + return false; + } + player.getDialogueInterpreter().sendDialogue("You carefully place Ana in the barrel into the mine", "cart. Soon the cart moves out of sight and then it", "returns."); + player.setAttribute("ana-delay", GameWorld.getTicks() + 100000000); + ActivityManager.start(player, "ana cart", false); + return true; + } + + /** + * The ana cart cutscene plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class AnnaCartCutscene extends CutscenePlugin { + + /** + * The paths. + */ + private static final Location[][] PATHS = new Location[][]{{Location.create(3315, 9417, 0), Location.create(3317, 9417, 0), Location.create(3318, 9418, 0), Location.create(3318, 9428, 0)}, {Location.create(3318, 9430, 0), Location.create(3318, 9418, 0), Location.create(3317, 9417, 0), Location.create(3316, 9417, 0), Location.create(3314, 9417, 0), Location.create(3303, 9417, 0)}}; + + /** + * Constructs a new {@code AnnaCartCutscene} {@code Object}. + */ + public AnnaCartCutscene() { + super("ana cart"); + } + + /** + * Constructs a new {@code AnnaCartCutscene} {@code Object}. + * + * @param player the player. + */ + public AnnaCartCutscene(final Player player) { + super("ana cart"); + this.player = player; + } + + @Override + public void open() { + super.open(); + player.setAttribute("ana-delay", GameWorld.getTicks() + 100000000); + player.faceLocation(base.transform(54, 22, 0)); + GameWorld.getPulser().submit(new Pulse(1, player) { + int counter; + NPC cart; + + @Override + public boolean pulse() { + switch (++counter) { + case 1: + player.animate(Animation.create(5052)); + break; + case 3: + SceneryBuilder.remove(RegionManager.getObject(base.transform(54, 22, 0))); + cart = NPC.create(4980, base.transform(54, 22, 0)); + cart.init(); + break; + case 4: + cart.getWalkingQueue().reset(); + for (Location l : PATHS[1]) { + Location loc = base.transform(l.getLocalX(), l.getLocalY(), 0); + cart.getWalkingQueue().addPath(loc.getX(), loc.getY()); + } + break; + case 18: + cart.clear(); + break; + case 22: + cart = NPC.create(4981, base.transform(51, 9, 0)); + cart.init(); + cart.getWalkingQueue().reset(); + for (Location l : PATHS[0]) { + Location loc = base.transform(l.getLocalX(), l.getLocalY(), 0); + cart.getWalkingQueue().addPath(loc.getX(), loc.getY()); + } + break; + case 33: + player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 70); + player.getInventory().remove(TouristTrap.ANNA_BARREL); + player.removeAttribute("ana-delay"); + AnnaCartCutscene.this.stop(true); + return true; + } + return false; + } + }); + } + + @Override + public ActivityPlugin newInstance(Player p) { + return new AnnaCartCutscene(p); + } + + @Override + public Location getSpawnLocation() { + return null; + } + + @Override + public Location getStartLocation() { + return base.transform(54, 23, 0); + } + + @Override + public void configure() { + region = DynamicRegion.create(13203); + setRegionBase(); + registerRegion(region.getId()); + } + } + } + + /** + * The cart dialogue plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class CartDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code CartDialogue} {@code Object}. + * + * @param player the player. + */ + public CartDialogue(final Player player) { + super(player); + } + + /** + * Constructs a new {@code CartDialogue} {@code Object}. + */ + public CartDialogue() { + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new CartDialogue(player); + } + + @Override + public boolean open(Object... args) { + interpreter.sendDialogue("There is space on the cart for you get on, would you like to try?"); + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + options("Yes, I'll get on.", "No, I've got other plans."); + stage++; + break; + case 1: + switch (buttonId) { + case 1: + interpreter.sendDialogue("You decide to climb onto the cart."); + stage++; + break; + case 2: + end(); + break; + } + break; + case 2: + player.lock(); + player.animate(ClimbActionHandler.CLIMB_UP); + GameWorld.getPulser().submit(new Pulse(1, player) { + int counter; + + @Override + public boolean pulse() { + switch (counter++) { + case 1: + player.getInterfaceManager().openOverlay(new Component(115)); + break; + case 4: + player.getDialogueInterpreter().sendDialogue("As soon as you get on the cart, it starts to move.", "Before too long you are past the gates. You jump off", "the cart taking Ana with you."); + break; + case 6: + player.unlock(); + player.getInterfaceManager().closeOverlay(); + player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP).setStage(player, 95); + player.getInterfaceManager().close(); + player.getProperties().setTeleportLocation(Location.create(3258, 3029, 0)); + player.getInventory().add(TouristTrap.ANNA_BARREL); + return true; + } + return false; + } + }); + end(); + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{DialogueInterpreter.getDialogueKey("ana cart dialogue")}; + } + + } + + /** + * The minecart dialogue plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class MineCartDialogue extends DialoguePlugin { + + /** + * The failing animation of getting in the cart. + */ + private static final Animation FAIL_ANIMATION = new Animation(5048); + + /** + * The jumping animation. + */ + private static final Animation JUMP_ANIMATION = new Animation(5049); + + /** + * The cart. + */ + private Scenery cart; + + /** + * Constructs a new {@code MineCartDialogue} {@code Object}. + */ + public MineCartDialogue() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code MineCartDialogue} {@code Object}. + * + * @param player the player. + */ + public MineCartDialogue(final Player player) { + super(player); + } + + @Override + public void init() { + super.init(); + ClassScanner.definePlugin(new MiningCartCutscene()); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new MineCartDialogue(player); + } + + @Override + public boolean open(Object... args) { + cart = (Scenery) args[0]; + if (player.getInventory().containsItem(TouristTrap.ANNA_BARREL)) { + player("There's not enough room for both of us."); + stage = -1; + return true; + } + interpreter.sendDialogue("You search the mine cart..."); + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case -1: + end(); + break; + case 0: + interpreter.sendDialogue("There may be just enough space to squeeze yourself into the cart.", "Would you like to try?"); + stage++; + break; + case 1: + options("Yes, of course.", "No thanks, it looks pretty dangerous."); + stage++; + break; + case 2: + switch (buttonId) { + case 1: + end(); + enterCart(player); + break; + case 2: + end(); + break; + } + break; + } + return true; + } + + /** + * Method used to enter the cart. + * + * @param player the player. + */ + public void enterCart(final Player player) { + if (RandomFunction.random(3) == 1) { + player.lock(FAIL_ANIMATION.getDelay()); + player.animate(FAIL_ANIMATION); + player.getImpactHandler().manualHit(player, 2, HitsplatType.NORMAL); + player.getPacketDispatch().sendMessages("You fail to fit yourself into the cart in time before it starts its journey.", "You bang your head on the cart as you try to jump in."); + } else { + GameWorld.getPulser().submit(new Pulse(3, player) { + @Override + public boolean pulse() { + player.animate(JUMP_ANIMATION); + return true; + } + }); + ActivityManager.start(player, "mining cart", false, cart.getLocation().getX() == 3303 ? 0 : 1); + } + } + + /** + * The mining cart cutscene plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class MiningCartCutscene extends CutscenePlugin { + + /** + * The paths. + */ + private static final Location[][] PATHS = new Location[][]{{Location.create(3303, 9417, 0), Location.create(3316, 9417, 0), Location.create(3317, 9417, 0), Location.create(3318, 9418, 0), Location.create(3318, 9430, 0)}, {Location.create(3318, 9430, 0), Location.create(3318, 9418, 0), Location.create(3317, 9417, 0), Location.create(3303, 9417, 0)}}; + + /** + * The path index. + */ + private int index; + + /** + * Constructs a new {@code MiningCartCutscene} {@code Object}. + */ + public MiningCartCutscene() { + super("mining cart"); + } + + /** + * Constructs a new {@code MiningCartCutscene} {@code Object}. + * + * @param player the player. + */ + public MiningCartCutscene(final Player player) { + super("mining cart"); + this.player = player; + } + + @Override + public boolean start(final Player player, boolean login, Object... args) { + index = (int) args[0]; + return super.start(player, login, args); + } + + @Override + public void open() { + SceneryBuilder.remove(RegionManager.getObject(base.getLocation().transform(getPath()[0].getLocalX(), getPath()[0].getLocalY(), 0))); + SceneryBuilder.remove(RegionManager.getObject(base.getLocation().transform(getPath()[getPath().length - 1].getLocalX(), getPath()[getPath().length - 1].getLocalY(), 0))); + player.getAppearance().setAnimations(Animation.create(211)); + player.getAppearance().setRidingMinecart(true); + player.getAppearance().sync(); + player.getWalkingQueue().reset(); + for (Location l : getPath()) { + Location loc = base.transform(l.getLocalX(), l.getLocalY(), 0); + player.getWalkingQueue().addPath(loc.getX(), loc.getY(), true); + } + GameWorld.getPulser().submit(new Pulse(22, player) { + @Override + public boolean pulse() { + player.setAttribute("real-end", index == 0 ? Location.create(3319, 9431, 0) : Location.create(3303, 9416, 0)); + player.setAttribute("cutscene:original-loc", index == 0 ? Location.create(3319, 9431, 0) : Location.create(3303, 9416, 0)); + MiningCartCutscene.this.stop(true); + return true; + } + }); + } + + @Override + public void end() { + super.end(); + player.getAppearance().setDefaultAnimations(); + player.getAppearance().setRidingMinecart(false); + player.getAppearance().sync(); + } + + @Override + public void fade() { + if (index == 0) { + player.getDialogueInterpreter().sendDialogue("You appear in a large open room with what looks like lots of miners", "working away. This is a very rough looking area, the miners look like", "they're on their last legs."); + } else { + player.getDialogueInterpreter().sendDialogue("You appear back in the barrel loading room. A nearby slave looks", "surprised to see you popping out of the cart."); + } + } + + @Override + public ActivityPlugin newInstance(Player p) { + return new MiningCartCutscene(p); + } + + @Override + public Location getSpawnLocation() { + return null; + } + + @Override + public Location getStartLocation() { + return base.transform(getPath()[0].getLocalX(), getPath()[0].getLocalY(), 0); + } + + @Override + public void configure() { + region = DynamicRegion.create(13203); + setRegionBase(); + registerRegion(region.getId()); + } + + /** + * Gets the path index. + * + * @return the location. + */ + public Location[] getPath() { + return PATHS[index]; + } + } + + @Override + public int[] getIds() { + return new int[]{DialogueInterpreter.getDialogueKey("cart dialogue")}; + } + + } + + /** + * The winch cutscene plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class WinchCutscene extends CutscenePlugin { + + /** + * Constructs a new {@code WinchCutscene} {@code Object}. + */ + public WinchCutscene() { + super("winch cutscene"); + } + + /** + * Constructs a new {@code WinchCutscene} {@code Object}. + * + * @param player the player. + */ + public WinchCutscene(final Player player) { + super("winch cutscene"); + this.player = player; + } + + @Override + public ActivityPlugin newInstance(Player p) { + return new WinchCutscene(p); + } + + @Override + public void open() { + super.open(); + player.getPacketDispatch().sendMessage("You try to operate the winch."); + player.faceLocation(base.transform(15, 9, 0)); + player.animate(Animation.create(5054)); + GameWorld.getPulser().submit(new Pulse(AnimationDefinition.forId(5054).getDurationTicks(), player) { + @Override + public boolean pulse() { + TouristTrap.addConfig(player, 2048 + (1 << 4)); + WinchCutscene.this.stop(true); + player.getDialogueInterpreter().open(822, true, true); + return true; + } + }); + } + + @Override + public Location getSpawnLocation() { + return null; + } + + @Override + public Location getStartLocation() { + return base.transform(16, 10, 0); + } + + @Override + public void configure() { + region = DynamicRegion.create(13103); + setRegionBase(); + registerRegion(region.getId()); + } + + } + + /** + * The use with handler on the chest. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class BedabinKeyHandler extends UseWithHandler { + + /** + * Constructs a new {@code BedabinKeyHandler} {@code Object}. + */ + public BedabinKeyHandler() { + super(TouristTrap.BEDABIN_KEY.getId()); + } + + @Override + public Plugin newInstance(Object arg) { + addHandler(2677, OBJECT_TYPE, this); + return this; + } + + @Override + public boolean handle(NodeUsageEvent event) { + final Player player = event.getPlayer(); + player.getDialogueInterpreter().open(831, RegionManager.getNpc(player.getLocation(), 831, 16)); + return true; + } + + } + + /** + * The barrel dialogue plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class BarrelDialogue extends DialoguePlugin { + + /** + * The scenery barrel. + */ + private Scenery barrel; + + /** + * The quest. + */ + private Quest quest; + + /** + * Constructs a new {@code BarrelDialogue} {@code Object}. + */ + public BarrelDialogue() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code BarrelDialogue} {@code Object}. + * + * @param player the player. + */ + public BarrelDialogue(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new BarrelDialogue(player); + } + + @Override + public boolean open(Object... args) { + barrel = (Scenery) args[0]; + quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); + if ((quest.getStage(player) == 70 || quest.getStage(player) == 72) && !player.hasItem(TouristTrap.ANNA_BARREL)) { + interpreter.sendDialogue("You search the barrels and find Ana."); + stage = 400; + return true; + } + if (player.getInventory().containsItem(TouristTrap.BARREL)) { + player.getPacketDispatch().sendMessage("You can only manage to have one of these at a time."); + end(); + return true; + } + interpreter.sendItemMessage(TouristTrap.BARREL, "This barrel is quite big. but you may be able to carry one. Would you like to take one?"); + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 400:// finding anna. + interpreter.sendDialogues(823, null, "Let me out!"); + stage++; + break; + case 401: + if (!player.getInventory().hasSpaceFor(TouristTrap.ANNA_BARREL)) { + end(); + return true; + } + player.getPacketDispatch().sendMessage("You pick up Ana in a Barrel."); + player.getInventory().add(TouristTrap.ANNA_BARREL); + end(); + break; + case 402: + end(); + break; + case 0: + options("Yeah, cool!", "No thanks."); + stage++; + break; + case 1: + switch (buttonId) { + case 1: + interpreter.sendItemMessage(TouristTrap.BARREL, "You take the barrel, it's not heavy, just awkward."); + stage = 3; + break; + case 2: + end(); + break; + } + break; + case 3: + end(); + player.getInventory().add(TouristTrap.BARREL, player); + SceneryBuilder.remove(barrel); + GameWorld.getPulser().submit(new Pulse(40) { + @Override + public boolean pulse() { + SceneryBuilder.add(barrel); + return true; + } + }); + break; + + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{DialogueInterpreter.getDialogueKey("barrel dialogue")}; + } + + } + + /** + * The use with handler for the bedabin anvil. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class BedabinAnvilHandler extends UseWithHandler { + + /** + * Constructs a new {@code BedabinAnvilHandler} {@code Object}. + */ + public BedabinAnvilHandler() { + super(2349); + } + + @Override + public Plugin newInstance(Object arg) { + addHandler(2672, OBJECT_TYPE, this); + ClassScanner.definePlugin(new PrototypeDartHandler()); + ClassScanner.definePlugin(new BedabinAnvilDialogue()); + return this; + } + + @Override + public boolean handle(NodeUsageEvent event) { + final Player player = event.getPlayer(); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); + if (quest.getStage(player) == 54 && player.getInventory().containsItem(TouristTrap.TECHNICAL_PLANS)) { + player.getDialogueInterpreter().open("bedabin-anvil"); + return true; + } else { + player.getPacketDispatch().sendMessage("You need technical plans in order to do this."); + } + return true; + } + + /** + * The handler used to handle the anna barrel on the winch. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class AnnaWinchHandler extends UseWithHandler { + + /** + * Constructs a new {@code AnnaWinchHandler} {@code Object}. + */ + public AnnaWinchHandler() { + super(TouristTrap.ANNA_BARREL.getId()); + } + + @Override + public Plugin newInstance(Object arg) { + addHandler(18951, OBJECT_TYPE, this); + return this; + } + + @Override + public boolean handle(NodeUsageEvent event) { + final Player player = event.getPlayer(); + final Quest quest = player.getQuestRepository().getQuest(Quests.THE_TOURIST_TRAP); + if (!event.getUsedWith().getLocation().equals(Location.create(3292, 9423, 0))) { + return false; + } + if (quest.getStage(player) == 70) { + player.getDialogueInterpreter().open("winch dialogue", true); + return true; + } + return false; + } + + } + + /** + * The prototype dart creation handler. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class PrototypeDartHandler extends UseWithHandler { + + /** + * Constructs a new {@code PrototypeDartHandler} {@code Object}. + */ + public PrototypeDartHandler() { + super(314); + } + + @Override + public Plugin newInstance(Object arg) { + addHandler(TouristTrap.PROTOTYPE_DART_TIP.getId(), ITEM_TYPE, this); + ClassScanner.definePlugin(new ProtoTypeDialogue()); + return this; + } + + @Override + public boolean handle(NodeUsageEvent event) { + final Player player = event.getPlayer(); + player.getDialogueInterpreter().open("prototype dart"); + return true; + } + + /** + * The prototype dialogue plugin. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class ProtoTypeDialogue extends DialoguePlugin { + + /** + * The feathers item. + */ + private static final Item FEATHERS = new Item(314, 10); + + /** + * Constructs a new {@code ProtoTypeDialogue} {@code Object}. + * + * @param player the player. + */ + public ProtoTypeDialogue(final Player player) { + super(player); + } + + /** + * Constructs a new {@code ProtoTypeDialogue} {@code Object}. + */ + public ProtoTypeDialogue() { + /** + * empty. + */ + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new ProtoTypeDialogue(player); + } + + @Override + public boolean open(Object... args) { + if (!player.getInventory().containsItem(FEATHERS)) { + interpreter.sendDialogue("You need 10 feathers in order to do this."); + stage = 10; + return false; + } + interpreter.sendItemMessage(314, "You try to attach feathers to the bronze dart tip."); + stage = 1; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 1: + interpreter.sendDialogue("Following the plans is tricky, but you persevere."); + stage++; + break; + case 2: + interpreter.sendItemMessage(TouristTrap.PROTOTYPE_DART, "You successfully attach the feathers to the dart tip."); + stage++; + break; + case 3: + player.getInventory().remove(FEATHERS, TouristTrap.PROTOTYPE_DART_TIP); + player.getInventory().add(TouristTrap.PROTOTYPE_DART); + end(); + break; + case 4: + end(); + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{DialogueInterpreter.getDialogueKey("prototype dart")}; + } + + } + } + + /** + * The bedabin dialogue plugin handler. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class BedabinAnvilDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code BedabinAnvilDialogue} {@code Object}. + */ + public BedabinAnvilDialogue() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code BedabinAnvilDialogue} {@code Object}. + * + * @param player the player. + */ + public BedabinAnvilDialogue(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new BedabinAnvilDialogue(player); + } + + @Override + public boolean open(Object... args) { + if (!player.getInventory().containsItem(TouristTrap.TECHNICAL_PLANS)) { + player.getPacketDispatch().sendMessage("You need the plans to do this."); + return false; + } + player.getDialogueInterpreter().sendItemMessage(TouristTrap.TECHNICAL_PLANS, "Do you want to follow the technical plans ?"); + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + options("Yes. I'd like to try.", "No, not just yet."); + stage++; + break; + case 1: + switch (buttonId) { + case 1: + end(); + player.getPulseManager().run(new ProtoTypePulse(player)); + break; + case 2: + end(); + break; + } + break; + } + return true; + } + + /** + * The skill pulse used to make a prototype dart. + * + * @author 'Vexia + * @version 1.0 + */ + public static final class ProtoTypePulse extends SkillPulse { + + /** + * The hammer item. + */ + private static final Item HAMMER = new Item(2347); + + /** + * The ticks passed. + */ + private int ticks; + + /** + * Constructs a new {@code ProtoTypePulse} {@code Object}. + * + * @param player the player. + */ + public ProtoTypePulse(Player player) { + super(player, null); + } + + @Override + public boolean checkRequirements() { + if (!player.getInventory().hasSpaceFor(TouristTrap.PROTOTYPE_DART_TIP)) { + player.getPacketDispatch().sendMessage("Not enough inventory space."); + return false; + } + if (!player.getInventory().containsItem(HAMMER)) { + player.getPacketDispatch().sendMessage("You need a hammer in order to work metal with."); + return false; + } + return player.getInventory().containsItem(Bar.BRONZE.getProduct()); + } + + @Override + public void animate() { + if (ticks % 4 == 0) { + player.animate(Animation.create(898)); + } + } + + @Override + public boolean reward() { + if (++ticks % 4 != 0) { + return false; + } + if (ticks == 4) { + player.getDialogueInterpreter().sendPlainMessage(true, "You begin experimenting in forging the weapon..."); + } else if (ticks == 8) { + player.getInventory().remove(Bar.BRONZE.getProduct()); + player.getInventory().add(TouristTrap.PROTOTYPE_DART_TIP); + player.getDialogueInterpreter().sendItemMessage(TouristTrap.PROTOTYPE_DART_TIP, "You follow the plans carefully, and after some careful", "work, you finally manage to forge a sharp, pointed...", "dart tip."); + return true; + } + return false; + } + + @Override + public void stop() { + super.stop(); + } + + } + + @Override + public int[] getIds() { + return new int[]{DialogueInterpreter.getDialogueKey("bedabin-anvil")}; + } + + } + } } diff --git a/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt b/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt index 51d160974..3621ed8c6 100644 --- a/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt +++ b/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt @@ -167,7 +167,7 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { } override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10553 -> if (event.source.id in FISHING_SPOTS) { finishTask( player, @@ -204,7 +204,7 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { } override fun onNpcKilled(player: Player, event: NPCKillEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10042, 10554 -> if (event.npc.id in ROCK_CRABS) { progressIncrementalTask( player, @@ -260,7 +260,7 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { } override fun onPickedUp(player: Player, event: PickUpEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10810 -> if (event.itemId == Items.SEAWEED_401) { progressIncrementalTask( player, @@ -284,7 +284,7 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { } override fun onSummoningPointsRecharged(player: Player, event: SummoningPointsRechargeEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10552 -> if (event.obelisk.id == Scenery.SMALL_OBELISK_29944) { finishTask( player, @@ -296,7 +296,7 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { } override fun onInteracted(player: Player, event: InteractionEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10811 -> if (event.target.id == Scenery.COLLAPSED_TRAP_19233 && inBorders(player, RELLEKKA_HUNTING_AREA) && event.option == "dismantle") { finishTask( player, diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt index e7b48f9d3..95d4b1827 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/TFTInteractionListeners.kt @@ -8,8 +8,6 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.player.link.music.MusicEntry import core.game.node.entity.skill.Skills -import content.global.skill.gather.woodcutting.WoodcuttingSkillPulse -import core.game.node.scenery.Scenery import core.game.system.task.Pulse import core.game.world.map.Location import core.game.world.map.RegionManager @@ -23,6 +21,7 @@ import core.game.system.config.ItemConfigParser import core.game.world.GameWorld.Pulser import content.data.Quests import core.game.interaction.QueueStrength +import core.game.node.Node class TFTInteractionListeners : InteractionListener { @@ -74,7 +73,7 @@ class TFTInteractionListeners : InteractionListener { removeItem(player,LOW_ALC_KEG) setAttribute(player,"/save:fremtrials:keg-mixed", true) sendMessage(player,"The cherry bomb in the pipe goes off.") - RegionManager.getLocalEntitys(player).stream().forEach { e -> e.sendChat("What was THAT??") } + RegionManager.getLocalNPCs(player.location).stream().forEach { e -> e.sendChat("What was THAT??") } sendMessage(player,"You mix the kegs together.") } else { player.dialogueInterpreter?.sendDialogue("I can't do this right now. I should create","a distraction.") @@ -204,7 +203,7 @@ class TFTInteractionListeners : InteractionListener { setAttribute(player,"/save:fremtrials:maze-complete",true) DestRoom(2662, 10034, 2668, 10039).getCenter() } - else -> getRandomLocation(player) + else -> getRandomLocation(player, portal) } return@on true } @@ -280,17 +279,15 @@ class TFTInteractionListeners : InteractionListener { return Location((swx + nex) / 2, (swy + ney) / 2).transform(1,0,0) } - fun getRandomLocation(player: Player?): Location{ - var obj: Scenery? = null - - while(obj?.id != 5138) { - val objects = player?.viewport?.chunks?.random()?.random()?.objects - obj = objects?.random()?.random() - if(obj == null || obj.location?.equals(Location(0,0,0))!!){ - continue + fun getRandomLocation(player: Player, portal: Node): Location { + val objects = player.location.region.assembleObjectList(player.location.z) + objects.shuffle() + for (o in objects) { + if (o.id == 5138) { + return o.location } } - return obj.location + return portal.location } fun hasEquippableItems(player: Player?): Boolean { diff --git a/Server/src/main/content/region/fremennik/waterbirth/handlers/DagannothKingNPC.java b/Server/src/main/content/region/fremennik/waterbirth/handlers/DagannothKingNPC.java index 65f5d4e43..7a30ca024 100644 --- a/Server/src/main/content/region/fremennik/waterbirth/handlers/DagannothKingNPC.java +++ b/Server/src/main/content/region/fremennik/waterbirth/handlers/DagannothKingNPC.java @@ -10,6 +10,7 @@ import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.player.Player; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.tools.RandomFunction; /** @@ -70,7 +71,7 @@ public final class DagannothKingNPC extends AbstractNPC { state.setEstimatedHit(RandomFunction.random(type.getMaxHit() - 5, type.getMaxHit())); } if (type != DagType.REX && RandomFunction.random(5) <= 2) { - List players = RegionManager.getLocalPlayers(this, 9); + List players = RegionManager.getLocalPlayers(location, 9); if (players.size() <= 1) { return; } diff --git a/Server/src/main/content/region/fremennik/waterbirth/handlers/WaterBirthDungeonZone.java b/Server/src/main/content/region/fremennik/waterbirth/handlers/WaterBirthDungeonZone.java index 1a5a35235..6fa067f6a 100644 --- a/Server/src/main/content/region/fremennik/waterbirth/handlers/WaterBirthDungeonZone.java +++ b/Server/src/main/content/region/fremennik/waterbirth/handlers/WaterBirthDungeonZone.java @@ -17,6 +17,7 @@ import core.game.node.entity.combat.CombatStyle; import core.game.node.entity.npc.AbstractNPC; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; +import core.game.node.item.GroundItemManager; import core.game.node.scenery.SceneryBuilder; import core.game.system.task.Pulse; import core.game.world.GameWorld; @@ -71,7 +72,7 @@ public final class WaterBirthDungeonZone extends MapZone implements Plugin npcs = RegionManager.getLocalNpcs(location, 0); + List npcs = RegionManager.getLocalNPCs(location, 0); NPC npc = null; if (npcs.size() != 0) { npc = npcs.get(0); @@ -243,10 +244,10 @@ public final class WaterBirthDungeonZone extends MapZone implements Plugin 0) { + if (!RegionManager.getLocalPlayers(location, 0).isEmpty()) { return true; } - if (RegionManager.getRegionPlane(location).getItem(Items.PET_ROCK_3695,location,player) != null) { + if (GroundItemManager.get(Items.PET_ROCK_3695, location, player) != null) { return true; } return false; @@ -411,9 +412,9 @@ public final class WaterBirthDungeonZone extends MapZone implements Plugin System.currentTimeMillis()) { end(); - for (NPC npc : RegionManager.getLocalNpcs(player.getLocation(), 8)) { + for (NPC npc : RegionManager.getLocalNPCs(player.getLocation(), 8)) { if (!npc.getProperties().getCombatPulse().isAttacking() && npc.getId() == 32) { npc.sendChat("Hey! Get your hands off there!"); npc.getProperties().getCombatPulse().attack(player); diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/hazeelcult/AlomoneDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/hazeelcult/AlomoneDialogue.kt index e6c54d22a..9997bb2b1 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/hazeelcult/AlomoneDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/hazeelcult/AlomoneDialogue.kt @@ -8,6 +8,7 @@ import core.game.dialogue.* import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.world.map.Location +import core.game.world.map.RegionManager import core.plugin.Initializable import core.tools.END_DIALOGUE import org.rs09.consts.* @@ -130,12 +131,9 @@ class AlomoneDialogue(player: Player? = null) : DialoguePlugin(player) { // active dialogue or speaking to alomone, and just dealing with the fact that their hazeel is not on the map. relogging and restarting // the dialogue would get these players a new hazeel. private fun Player.findNpcInViewport(npcId: Int): NPC? { - val viewport = viewport ?: return null - for (plane in viewport.viewingPlanes) { - for (npc in plane.npcs) { - if (npc.id == npcId) { - return npc - } + for (npc in RegionManager.getLocalNPCs(location)) { + if (npc.id == npcId) { + return npc } } return null diff --git a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt index 671b7d38b..a75ae7827 100644 --- a/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt +++ b/Server/src/main/content/region/kandarin/ardougne/quest/plaguecity/dialogue/mourners/MournerKidnapDialogue.kt @@ -56,7 +56,7 @@ class MournerKidnapDialogueFile : DialogueFile(){ // Figure out who we are. It needs to be this since we can enter this dialogue from a door // Do this for the first time regardless of where we are if (stage == 0) { - RegionManager.getLocalNpcs(player!!, 2).forEach { + RegionManager.getLocalNPCs(player!!.location, 2).forEach { if (it.id == NPCs.MOURNER_3216) { closeMourner = it resetFace(closeMourner!!) @@ -78,7 +78,7 @@ class MournerKidnapDialogueFile : DialogueFile(){ 2 -> npcl(FacialExpression.HALF_WORRIED, " This is highly irregular. Please wait...").also { stage++ } 3 -> { // Look further for the other one - RegionManager.getLocalNpcs(player!!, 10).forEach { + RegionManager.getLocalNPCs(player!!.location, 10).forEach { if (it.id == NPCs.MOURNER_3216 && it != closeMourner){ farMourner = it resetFace(farMourner!!) diff --git a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt index 49a074680..36d328445 100644 --- a/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt +++ b/Server/src/main/content/region/kandarin/feldip/quest/chompybird/BloatedToadNPC.kt @@ -43,7 +43,7 @@ class BloatedToadNPC : AbstractNPC { super.handleTickActions() if (ticksToLive-- <= 0) { - val toDamage = RegionManager.getLocalEntitys(this.location, 2) + val toDamage = RegionManager.getLocalEntities(this.location, 2) for (entity in toDamage) { if (entity == this) continue diff --git a/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DMCHandler.java b/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DMCHandler.java index 9b7d2363c..d66f0b062 100644 --- a/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DMCHandler.java +++ b/Server/src/main/content/region/kandarin/quest/dwarfcannon/dmc/DMCHandler.java @@ -6,7 +6,6 @@ import core.game.node.entity.combat.ImpactHandler.HitsplatType; import core.game.node.entity.impl.Projectile; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.audio.Audio; import core.game.node.entity.skill.Skills; import core.game.node.item.Item; import core.game.node.scenery.Scenery; @@ -51,10 +50,10 @@ public final class DMCHandler implements LogoutListener { */ private DMCRevolution direction = DMCRevolution.NORTH; - private CannonTimer timer; + private CannonTimer timer; public DMCHandler() { - this.player = null; + this.player = null; } /** @@ -78,7 +77,7 @@ public final class DMCHandler implements LogoutListener { Location l = cannon.getLocation().transform(1, 1, 0); playGlobalAudio(l, Sounds.MCANNON_TURN_2877); direction = DMCRevolution.values()[(direction.ordinal() + 1) % DMCRevolution.values().length]; - for (NPC npc : RegionManager.getLocalNpcs(l, 10)) { + for (NPC npc : RegionManager.getLocalNPCs(l, 10)) { if (direction.isInSight(npc.getLocation().getX() - l.getX(), npc.getLocation().getY() - l.getY()) && npc.isAttackable(player, CombatStyle.RANGE, false) && CombatSwingHandler.isProjectileClipped(npc, l, false)) { int speed = (int) (25 + (l.getDistance(npc.getLocation()) * 10)); Projectile.create(l, npc.getLocation(), 53, 40, 36, 20, speed, 0, 128).send(); @@ -106,8 +105,8 @@ public final class DMCHandler implements LogoutListener { return; } if (timer.isFiring()) { - timer.setFiring(false); - return; + timer.setFiring(false); + return; } if (cannonballs < 1) { int amount = player.getInventory().getAmount(new Item(2)); @@ -127,7 +126,7 @@ public final class DMCHandler implements LogoutListener { player.sendMessage("Your cannon is already fully loaded."); } } - timer.setFiring(true); + timer.setFiring(true); } /** @@ -138,7 +137,7 @@ public final class DMCHandler implements LogoutListener { return; } player.sendMessage("Your cannon has " + (decay ? "decayed" : "been destroyed") + "!"); - for (Player p : RegionManager.getLocalPlayers(player)) { + for (Player p : RegionManager.getLocalPlayers(player.getLocation())) { p.getPacketDispatch().sendPositionedGraphic(189, 0, 1, cannon.getLocation()); } clear(false); @@ -194,15 +193,15 @@ public final class DMCHandler implements LogoutListener { player.getPacketDispatch().sendMessage("You add the furnace."); SceneryBuilder.remove(object); handler.configure(SceneryBuilder.add(object = object.transform(6))); - handler.timer = (CannonTimer) spawnTimer ("dmc:timer", handler); - registerTimer (player, handler.timer); + handler.timer = (CannonTimer) spawnTimer ("dmc:timer", handler); + registerTimer (player, handler.timer); return true; } playGlobalAudio(player.getLocation(), Sounds.MCANNON_SETUP_2876); - if(count != 0) { - SceneryBuilder.remove(object); - SceneryBuilder.add(object = object.transform(object.getId() + 1)); - } + if(count != 0) { + SceneryBuilder.remove(object); + SceneryBuilder.add(object = object.transform(object.getId() + 1)); + } return ++count == 4; } }); diff --git a/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt b/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt index bd9e90188..1581baeac 100644 --- a/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt +++ b/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt @@ -109,7 +109,7 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) ) } - when (player.viewport.region.id) { + when (player.location.regionId) { 10805 -> if (event.itemId == Items.FLAX_1779) { progressIncrementalTask( player, @@ -192,7 +192,7 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) } override fun onNpcKilled(player: Player, event: NPCKillEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10906 -> if (event.npc.id in WORKSHOP_ELEMENTALS) { progressFlaggedTask( player, @@ -316,7 +316,7 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) } override fun onItemPurchasedFromShop(player: Player, event: ItemShopPurchaseEvent) { - if (event.itemId == Items.CANDLE_36 && player.viewport.region.id == 11061) { + if (event.itemId == Items.CANDLE_36 && player.location.regionId == 11061) { finishTask( player, DiaryLevel.EASY, @@ -344,7 +344,7 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) } override fun onPrayerPointsRecharged(player: Player, event: PrayerPointsRechargeEvent) { - if (player.viewport.region.id == 10806) { + if (player.location.regionId == 10806) { if (event.altar.id == Scenery.ALTAR_409 || event.altar.id == Scenery.ALTAR_19145) { finishTask( player, diff --git a/Server/src/main/content/region/kandarin/seers/handlers/RangingGuildPlugin.java b/Server/src/main/content/region/kandarin/seers/handlers/RangingGuildPlugin.java index 5589a4d69..b8e504953 100644 --- a/Server/src/main/content/region/kandarin/seers/handlers/RangingGuildPlugin.java +++ b/Server/src/main/content/region/kandarin/seers/handlers/RangingGuildPlugin.java @@ -45,1168 +45,1168 @@ import static core.api.ContentAPIKt.*; @Initializable public final class RangingGuildPlugin extends OptionHandler { - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(2514).getHandlers().put("option:open", this); - SceneryDefinition.forId(2511).getHandlers().put("option:climb-up", this); - SceneryDefinition.forId(2512).getHandlers().put("option:climb-down", this); - SceneryDefinition.forId(2513).getHandlers().put("option:fire-at", this); - new RangingGuildDoorman().init(); - new GuardDialogue().init(); - new LeatherWorkerDialogue().init(); - new ArmourSalesman().init(); - new TribalWeaponSalesman().init(); - new BowArrowSalesman().init(); - new WarningInterface().newInstance(arg); - new CompetitionJudge().init(); - ClassScanner.definePlugin(new TowerArcher()); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - final int id = node instanceof Scenery ? ((Scenery) node).getId() : 0; - switch (option) { - case "fire-at": - if (player.getArcheryTargets() <= 0) { - player.getDialogueInterpreter().sendDialogues(693, null, "Sorry, you may only use the targets for the", "competition, not for practicing."); - return true; - } - if (!player.getEquipment().containsItem(new Item(882)) - || player.getEquipment().get(EquipmentContainer.SLOT_WEAPON) == null - || (!player.getEquipment().get(EquipmentContainer.SLOT_WEAPON).getDefinition().getName().toLowerCase().contains("shortbow") - && !player.getEquipment().get(EquipmentContainer.SLOT_WEAPON).getDefinition().getName().toLowerCase().contains("longbow"))) { - player.sendMessage("You must have bronze arrows and a bow equipped."); - return true; - } - player.getPulseManager().run(new ArcheryCompetitionPulse(player, (Scenery) node)); - break; - case "open": - switch (id) { - case 2514: - if (player.getLocation().getY() >= 3438) { - if (player.getSkills().getStaticLevel(Skills.RANGE) < 40) { - player.getDialogueInterpreter().sendDialogue("You need a Ranging level of 40 to enter here."); - return true; - } - } - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node, player.getLocation().getY() >= 3438 ? Location.create(2659, 3437, 0) : Location.create(2657, 3439, 0)); - break; - } - break; - case "climb-up": - switch (id) { - case 2511: - player.setAttribute("ladder", node); - player.getInterfaceManager().open(new Component(564)); - break; - } - break; - case "climb-down": - switch (id) { - case 2512: - ClimbActionHandler.climb(player, null, Location.create(2668, 3427, 0)); - break; - } - break; - } - return true; - } - - @Override - public Location getDestination(Node node, Node n) { - if (n instanceof Scenery) { - if (((Scenery) n).getDefinition().hasAction("open")) { - if (((Scenery) n).getId() == 2514) { - if (node.getLocation().getY() >= 3438) { - return Location.create(2657, 3439, 0); - } else { - return Location.create(2659, 3437, 0); - } - } - return DoorActionHandler.getDestination((Player) node, (Scenery) n); - } - if (((Scenery) n).getId() == 2513) - return Location.create(2673, 3420, 0); - } - return null; - } - - /** - * Represents the dialogue used for the ranging guild door man. - * - * @author 'Vexia - * @version 1.0 - */ - public class RangingGuildDoorman extends DialoguePlugin { - - /** - * Constructs a new {@code RangingGuildDoorman} {@code Object}. - */ - public RangingGuildDoorman() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code RangingGuildDoorman} {@code Object}. - * - * @param player the player. - */ - public RangingGuildDoorman(Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new RangingGuildDoorman(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings. If you are an experienced archer, you may", "want to visit the guild here..."); - stage = 1; - break; - case 1: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{679}; - } - } - - /** - * Represents the tribal weapon salseman dialogue. - * - * @author 'Vexia - * @version 1.0 - */ - public final class TribalWeaponSalesman extends DialoguePlugin { - - /** - * Constructs a new {@code TribalWeaponSalesman} {@code Object}. - */ - public TribalWeaponSalesman() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code TribalWeaponSalesman} {@code Object}. - * - * @param player the player. - */ - public TribalWeaponSalesman(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new TribalWeaponSalesman(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - player("Hello there."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc("Greetings, traveller. Are you interested in any throwing", "weapons?"); - stage = 1; - break; - case 1: - options("Yes I am.", "Not really."); - stage = 2; - break; - case 2: - switch (buttonId) { - case 1: - player("Yes I am."); - stage = 10; - break; - case 2: - player("Not really."); - stage = 20; - break; - } - break; - case 10: - npc("That is a good thing."); - stage = 11; - break; - case 11: - end(); - npc.openShop(player); - break; - case 20: - npc("No bother to me."); - stage = 21; - break; - case 21: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{692}; - } - - } - - /** - * Represents the guard dialogue. - * - * @author 'Vexia - * @version 1.0 - */ - public final class GuardDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code GuardDialogue} {@code Object}. - */ - public GuardDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code GuardDialogue} {@code Object}. - * - * @param player the player. - */ - public GuardDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new GuardDialogue(player); - } - - @Override - public boolean open(Object... args) { - player("Hello there."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc("Greetings, traveller. Enjoy the time at the Ranging", "Guild."); - stage = 1; - break; - case 1: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{678}; - } - - } - - /** - * Represents the leather workers dialogue. - * - * @author 'Vexia - * @version 1.0 - */ - public final class LeatherWorkerDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code LeatherWorkerDialogue} {@code Object}. - */ - public LeatherWorkerDialogue() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code LeatherWorkerDialogue} {@code Object}. - * - * @param player the player. - */ - public LeatherWorkerDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new LeatherWorkerDialogue(player); - } - - @Override - public boolean open(Object... args) { - player("Hello."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc("Can I help you?"); - stage = 1; - break; - case 1: - options("What do you do here?", "No thanks."); - stage = 2; - break; - case 2: - switch (buttonId) { - case 1: - player("What do you do here?"); - stage = 10; - break; - case 2: - player("No thanks."); - stage = 20; - break; - } - break; - case 10: - npc("Well, I can cure plain cowhides into pieces of leather", "ready for crafting."); - stage = 11; - break; - case 11: - npc("I work with ordinary, hard or dragonhide leather and", "also snakeskin."); - stage = 12; - break; - case 12: - end(); - TanningProduct.open(player, 680); - break; - case 20: - npc("Suit yourself."); - stage = 21; - break; - case 21: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{680}; - } - - } - - /** - * Represents the armour salesman dialogue. - * - * @author 'Vexia - * @version 1.0 - */ - public final class ArmourSalesman extends DialoguePlugin { - - /** - * Constructs a new {@code ArmourSalesman} {@code Object}. - */ - public ArmourSalesman() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code ArmourSalesman} {@code Object}. - * - * @param player the player. - */ - public ArmourSalesman(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new ArmourSalesman(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - player("Good day to you."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc("And to you. Can I help you?"); - stage = 1; - break; - case 1: - if (Skillcape.isMaster(player, Skills.RANGE)) { - options("What do you do here?", "I'd like to see what you sell.", "Can I buy a Skillcape of Range?", "I've seen enough, thanks."); - stage = 100; - } else { - options("What do you do here?", "I'd like to see what you sell.", "I've seen enough, thanks."); - stage = 2; - } - break; - case 2: - switch (buttonId) { - case 1: - player("What do you do here?"); - stage = 10; - break; - case 2: - player("I'd like to see what you sell."); - stage = 20; - break; - case 3: - player("I've seen enough, thanks."); - stage = 30; - break; - } - break; - case 10: - npc("I am a supplier of leather armours and accessories. Ask", "and I will tell you what I know."); - stage = 11; - break; - case 11: - options("Tell me about your armours.", "Tell me about your accessories.", "I've seen enough, thanks."); - stage = 12; - break; - case 12: - switch (buttonId) { - case 1: - player("Tell me about your armours."); - stage = 13; - break; - case 2: - player("Tell me about your accessories."); - stage = 15; - break; - case 3: - player("I've seen enough, thanks."); - stage = 30; - break; - } - break; - case 13: - npc("I have normal, studded and hard types."); - stage = 14; - break; - case 14: - case 31: - case 105: - end(); - break; - case 15: - npc("Ah yes we have a new range of accessories in stock.", "Essential items for an archer like you."); - stage = 14; - break; - case 20: - npc("Indeed, cast your eyes on my wares, adventurer."); - stage = 21; - break; - case 21: - end(); - npc.openShop(player); - break; - case 30: - npc("Very good, adventurer."); - stage = 31; - break; - case 100: - switch (buttonId) { - case 1: - player("What do you do here?"); - stage = 10; - break; - case 2: - player("I'd like to see what you sell."); - stage = 20; - break; - case 3: - player("Can I buy a Skillcape of Range?"); - stage = 101; - break; - case 4: - player("I've seen enough, thanks."); - stage = 30; - break; - } - break; - case 101: - npc("Certainly! Right when you give me 99000 coins."); - stage = 102; - break; - case 102: - options("Okay, here you go.", "No, thanks."); - stage = 103; - break; - case 103: - switch (buttonId) { - case 1: - player("Okay, here you go."); - stage = 104; - break; - case 2: - end(); - break; - } - break; - case 104: - if (Skillcape.purchase(player, Skills.RANGE)) { - npc("There you go! Enjoy."); - } - stage = 105; - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{682}; - } - - } - - /** - * Represents the dialogue plugin used for the bow and arrow salesman. - * - * @author 'Vexia - * @version 1.0 - */ - public final class BowArrowSalesman extends DialoguePlugin { - - /** - * Constructs a new {@code BowArrowSalesman} {@code Object}. - */ - public BowArrowSalesman() { - /** - * empty. - */ - } - - /** - * Constructs a new {@code BowArrowSalesman} {@code Object}. - * - * @param player the player. - */ - public BowArrowSalesman(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new BowArrowSalesman(player); - } - - @Override - public boolean open(Object... args) { - npc = (NPC) args[0]; - player("Hello."); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 0: - npc("A fair day, traveller. Would you like to see my wares?"); - stage = 1; - break; - case 1: - options("Yes please.", "No thanks."); - stage = 2; - break; - case 2: - switch (buttonId) { - case 1: - end(); - npc.openShop(player); - - break; - case 2: - end(); - break; - } - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{683}; - } - - } - - /** - * Represents the waring interface used in the guild. - * - * @author 'Vexia - * @version 1.0 - */ - public final class WarningInterface extends ComponentPlugin { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - ComponentDefinition.forId(564).setPlugin(this); - return this; - } - - @Override - public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { - switch (button) { - case 17: - ClimbActionHandler.climb(player, null, Location.create(2668, 3427, 2)); - player.getInterfaceManager().close(); - List npcs = RegionManager.getLocalNpcs(Location.create(2668, 3427, 2)); - String dir = ""; - for (NPC n : npcs) { - if (n.getId() >= 684 && n.getId() <= 687) { - switch (n.getId()) { - case 684: - dir = "north"; - break; - case 685: - dir = "east"; - break; - case 686: - dir = "south"; - break; - case 687: - dir = "west"; - break; - } - n.sendChat("The " + dir + " tower is occupied, get them!"); - } - } - break; - case 18: - player.getInterfaceManager().close(); - break; - } - return true; - } - - } - - /** - * Represents the competition judge. - * - * @author afaroutdude - */ - public final class CompetitionJudge extends DialoguePlugin { - - /** - * Constructs a new {@code CompetitionJudge} {@code Object}. - * - * @param player the player. - */ - public CompetitionJudge(final Player player) { - super(player); - } - - /** - * Constructs a new {@code CompetitionJudge} {@code Object}. - */ - public CompetitionJudge() { - /** - * empty. - */ - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new CompetitionJudge(player); - } - - @Override - public boolean open(Object... args) { - if (player.getInventory().getAmount(1464) >= 1000 - && !player.getAchievementDiaryManager().hasCompletedTask(DiaryType.SEERS_VILLAGE, 1, 7)) { - npc("Wow! I see that you've got yourself a whole load of ", "archery tickets. Well done!"); - player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 7); - stage = -1; - } else if (player.getArcheryTargets() > 0) { - npc("Hello again, do you need reminding of the rules?"); - stage = 20; - } else if (player.getArcheryTotal() == 0) { - npc("Hello there, would you like to take part in the", - "archery competition? It only costs 200 coins to", - "enter."); - stage = 0; - } else { - int reward = player.getArcheryTotal() / 10; - npc("Well done. Your score is: " + player.getArcheryTotal() + ".", - "For that score you will receive " + reward + " Archery tickets."); - player.setArcheryTargets(-1); - player.setArcheryTotal(0); - if (!player.getInventory().add(new Item(1464, reward))) { - player.getBank().add(new Item(1464, reward)); - player.sendMessage("Your reward was sent to your bank."); - } - stage = 999; - } - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 999: - end(); - break; - case -1: - if (player.getArcheryTargets() > 0) { - npc("Hello again, do you need reminding of the rules?"); - stage = 20; - } else if (player.getArcheryTotal() == 0) { - npc("Hello there, would you like to take part in the", - "archery competition? It only costs 200 coins to", - "enter."); - stage = 0; - } else { - int reward = player.getArcheryTotal() / 10; - npc("Well done. Your score is: " + player.getArcheryTotal() + ".", - "For that score you will receive " + reward + " Archery tickets."); - if (!player.getInventory().add(new Item(1464, reward))) { - player.getBank().add(new Item(1464, reward)); - player.sendMessage("Your reward was sent to your bank."); - } - stage = 999; - } - break; - case 0: - options("Sure, I'll give it a go.", "What are the rules?", "No thanks."); - stage++; - break; - case 1: - switch (buttonId) { - case 1: - player("Sure, I'll give it a go."); - stage = 2; - break; - case 2: - player("What are the rules?"); - stage = 5; - break; - case 3: - player("No thanks."); - stage = 999; - break; - } - break; - case 2: - npc("Great! That will be 200 coins then please."); - stage++; - break; - case 3: - if (player.getInventory().getAmount(995) < 200) { - player("Oops, I don't have enough coins on me..."); - stage++; - } else { - end(); - player.getPacketDispatch().sendMessage("You pay the judge and he gives you 10 bronze arrows."); - player.getInventory().remove(new Item(995, 200)); - player.getInventory().add(new Item(882, 10)); - player.setArcheryTargets(10); - player.setArcheryTotal(0); - } - break; - case 4: - npc("Never mind, come back when you've got enough."); - stage = 999; - break; - case 5: - case 22: - npc("The rules are very simple:"); - stage++; - break; - case 6: - case 23: - npc("You're given 10 shots at the targets, for each hit", "you will receive points. At the end you'll be", "rewarded 1 ticket for every 10 points."); - stage++; - break; - case 7: - npc("The tickets can be exchanged for goods from our stores.", "Do you want to give it a go? Only 200 coins."); - stage++; - break; - case 8: - options("Sure, I'll give it a go.", "No thanks."); - stage++; - break; - case 9: - switch (buttonId) { - case 1: - player("Sure, I'll give it a go."); - stage = 2; - break; - case 3: - player("No thanks."); - stage = 999; - break; - } - break; - case 20: - int arrows = player.getInventory().getAmount(Items.BRONZE_ARROW_882) - + player.getEquipment().getAmount(Items.BRONZE_ARROW_882); - if (arrows < 1) { - player("Well, I actually don't have any more arrows. Could I", "get some more?"); - stage = 25; - } else { - options("Yes please.", "No thanks, I've got it.", "How am I doing so far?"); - stage++; - } - break; - case 21: - switch (buttonId) { - case 1: - player("Yes please."); - stage++; - break; - case 2: - player("No thanks, I've got it."); - stage = 30; - break; - case 3: - player("How am I doing so far?"); - stage = 40; - break; - } - break; - case 24: - npc("The tickets can be exchanged for goods from our stores.", "Good Luck!"); - stage = 999; - break; - case 25: - npc("Ok, but it'll cost you 100 coins."); - stage++; - break; - case 26: - options("Sure, I'll take some.", "No thanks."); - stage++; - break; - case 27: - switch (buttonId) { - case 1: - player("Sure, I'll take some."); - stage++; - break; - case 2: - player("No thanks."); - stage = 999; - break; - } - break; - case 28: - if (player.getInventory().getAmount(995) < 100) { - player("Oops, I don't have enough coins on me..."); - stage++; - } else { - end(); - player.getPacketDispatch().sendMessage("You pay the judge and he gives you 10 bronze arrows."); - player.getInventory().remove(new Item(995, 100)); - player.getInventory().add(new Item(882, 10)); - } - break; - case 30: - npc("Glad to hear it, good luck!"); - stage = 999; - break; - case 40: - String msg; - if (player.getArcheryTotal() <= 0) { - msg = "You haven't started yet."; - } else if (player.getArcheryTotal() <= 80) { - msg = "Not bad, keep going."; - } else { - msg = "You're pretty good, keep it up."; - } - npc("So far your score is: " + player.getArcheryTotal(), msg); - stage = 999; - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{693}; - } - - } - - /** - * Represents the tower advisors. - * - * @author afaroutdude - */ - public final class TowerAdvisor extends DialoguePlugin { - - /** - * Constructs a new {@code TowerAdvisor} {@code Object}. - * - * @param player the player. - */ - public TowerAdvisor(final Player player) { - super(player); - } - - /** - * Constructs a new {@code TowerAdvisor} {@code Object}. - */ - public TowerAdvisor() { - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new TowerAdvisor(player); - } - - @Override - public boolean open(Object... args) { - player("Hello there, what do you do here?"); - stage = 0; - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - switch (stage) { - case 999: - end(); - case 0: - npc("Hi. We are in charge of this practice area."); - stage++; - break; - case 1: - player("This is a practice area?"); - break; - case 2: - npc("Surrounding us are four towers. Each tower contains", - "trained archers of a different level. You'll notice", - "it's quite a distance, so you'll need a longbow."); - stage++; - break; - case 3: - int rangeLevel = player.getSkills().getLevel(Skills.RANGE); - if (rangeLevel < 50) { // north - npc("As you're not very skilled, I advise you to practice", - "on the north tower. That'll provide the best", - "challenge for you."); - } else if (rangeLevel < 60) { // east - npc("You appear to be somewhat skilled with a bow, so I", - "advise you to practice on the south tower. That'll", - "provide the best challenge for you."); - } else if (rangeLevel < 70) { // south - npc("You appear to be fairly skilled with a bow, so I", - "advise you to practice on the south tower. That'll", - "provide the best challenge for you."); - } else { // west - npc("Looks like you're very skilled, so I advise you to", - "practice on the west tower. That'll provide the best", - "challenge for you."); - } - stage = 999; - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[]{684, 685, 686, 687}; - } - - } - - - /** - * Represents all the tower archers - * - * @author afaroutdude - */ - public final class TowerArcher extends AbstractNPC { - - public TowerArcher() { - super(-1, null); - } - public TowerArcher(int id, Location location) { - super(id, location); - } - - - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new TowerArcher(id, location); - } - - @Override - public int[] getIds() { - return new int[]{688, 689, 690, 691}; - } - } - - /** - * Represents the archery target pulse. - * - * @author Jamix77 - */ - public static final class ArcheryCompetitionPulse extends Pulse { - - /** - * Represents the player instance. - */ - private final Player player; - - /** - * Represents the scenery. - */ - private final Scenery object; - - /** - * Constructs a new {@code ArcheryCompetitionPulse} {@code Object}. - * - * @param player the player. - * @param object the object. - */ - public ArcheryCompetitionPulse(final Player player, final Scenery object) { - super(1, player, object); - this.player = player; - this.object = object; - } - - private void showInterface(int points, int arrowsLeft, int target, String msg) { - player.getInterfaceManager().openComponent(325); - setVarp(player, 156, 11 - arrowsLeft); - setVarp(player, 157, points); - setVarp(player, 158, target); - player.getPacketDispatch().sendString(msg, 325, 32); - } - - @Override - public boolean pulse() { - if (player.getArcheryTargets() <= 0) { - return true; - } - if (getDelay() == 1) { - setDelay(player.getProperties().getAttackSpeed()); - } - if (player.getEquipment().remove(new Item(Items.BRONZE_ARROW_882, 1))) { - Projectile p = Ammunition.get(Items.BRONZE_ARROW_882).getProjectile().transform(player, object.getLocation()); - p.setEndLocation(object.getLocation()); - p.setEndHeight(25); - p.send(); - player.animate(new Animation(426)); - player.lock(getDelay()); - - int level = player.getSkills().getLevel(Skills.RANGE); - int bonus = player.getProperties().getBonuses()[14]; - double prayer = 1.0; - prayer += player.getPrayer().getSkillBonus(Skills.RANGE); - double cumulativeStr = Math.floor(level * prayer); - /*if (player.getProperties().getAttackStyle().getStyle() == WeaponInterface.STYLE_RANGE_ACCURATE) { - cumulativeStr += 3; - } else if (player.getProperties().getAttackStyle().getStyle() == WeaponInterface.STYLE_LONG_RANGE) { - cumulativeStr += 1; - }*/ - cumulativeStr *= 1.0; - int hit = (int) ((14 + cumulativeStr + (bonus / 8) + ((cumulativeStr * bonus) * 0.016865))) / 10 + 1; - hit = hit + RandomFunction.randomSign(RandomFunction.random(3)); - - int target = Math.max(0, 13 - hit); - int points = 0; - String msg = ""; - switch (target) { - case 0: - points = 100; - msg = "Bulls-Eye!"; - break; - case 1: - points = 50; - msg = "Hit Yellow!"; - break; - case 2: - case 3: - case 4: - points = 30; - msg = "Hit Red!"; - break; - case 5: - case 6: - case 7: - case 8: - points = 20; - msg = "Hit Blue!"; - break; - case 9: - case 10: - points = 10; - msg = "Hit Black!"; - break; - case 11: - case 12: - case 13: - points = 0; - msg = "Missed!"; - break; - } - int xp = points / 2; - - player.getSkills().addExperience(Skills.RANGE, xp, true); - player.setArcheryTotal(player.getArcheryTotal() + points); - player.setArcheryTargets(player.getArcheryTargets() - 1); - player.debug("Hit: " + hit); - player.debug("You have " + player.getArcheryTargets() + " targets left."); - player.debug("You have " + player.getArcheryTotal() + " score."); - - showInterface(player.getArcheryTotal(), player.getArcheryTargets(), target, msg); - - return true; //player.getArcheryTargets() <= 0; - } else { - return true; - } - } - - } + @Override + public Plugin newInstance(Object arg) throws Throwable { + SceneryDefinition.forId(2514).getHandlers().put("option:open", this); + SceneryDefinition.forId(2511).getHandlers().put("option:climb-up", this); + SceneryDefinition.forId(2512).getHandlers().put("option:climb-down", this); + SceneryDefinition.forId(2513).getHandlers().put("option:fire-at", this); + new RangingGuildDoorman().init(); + new GuardDialogue().init(); + new LeatherWorkerDialogue().init(); + new ArmourSalesman().init(); + new TribalWeaponSalesman().init(); + new BowArrowSalesman().init(); + new WarningInterface().newInstance(arg); + new CompetitionJudge().init(); + ClassScanner.definePlugin(new TowerArcher()); + return this; + } + + @Override + public boolean handle(Player player, Node node, String option) { + final int id = node instanceof Scenery ? ((Scenery) node).getId() : 0; + switch (option) { + case "fire-at": + if (player.getArcheryTargets() <= 0) { + player.getDialogueInterpreter().sendDialogues(693, null, "Sorry, you may only use the targets for the", "competition, not for practicing."); + return true; + } + if (!player.getEquipment().containsItem(new Item(882)) + || player.getEquipment().get(EquipmentContainer.SLOT_WEAPON) == null + || (!player.getEquipment().get(EquipmentContainer.SLOT_WEAPON).getDefinition().getName().toLowerCase().contains("shortbow") + && !player.getEquipment().get(EquipmentContainer.SLOT_WEAPON).getDefinition().getName().toLowerCase().contains("longbow"))) { + player.sendMessage("You must have bronze arrows and a bow equipped."); + return true; + } + player.getPulseManager().run(new ArcheryCompetitionPulse(player, (Scenery) node)); + break; + case "open": + switch (id) { + case 2514: + if (player.getLocation().getY() >= 3438) { + if (player.getSkills().getStaticLevel(Skills.RANGE) < 40) { + player.getDialogueInterpreter().sendDialogue("You need a Ranging level of 40 to enter here."); + return true; + } + } + DoorActionHandler.handleAutowalkDoor(player, (Scenery) node, player.getLocation().getY() >= 3438 ? Location.create(2659, 3437, 0) : Location.create(2657, 3439, 0)); + break; + } + break; + case "climb-up": + switch (id) { + case 2511: + player.setAttribute("ladder", node); + player.getInterfaceManager().open(new Component(564)); + break; + } + break; + case "climb-down": + switch (id) { + case 2512: + ClimbActionHandler.climb(player, null, Location.create(2668, 3427, 0)); + break; + } + break; + } + return true; + } + + @Override + public Location getDestination(Node node, Node n) { + if (n instanceof Scenery) { + if (((Scenery) n).getDefinition().hasAction("open")) { + if (((Scenery) n).getId() == 2514) { + if (node.getLocation().getY() >= 3438) { + return Location.create(2657, 3439, 0); + } else { + return Location.create(2659, 3437, 0); + } + } + return DoorActionHandler.getDestination((Player) node, (Scenery) n); + } + if (((Scenery) n).getId() == 2513) + return Location.create(2673, 3420, 0); + } + return null; + } + + /** + * Represents the dialogue used for the ranging guild door man. + * + * @author 'Vexia + * @version 1.0 + */ + public class RangingGuildDoorman extends DialoguePlugin { + + /** + * Constructs a new {@code RangingGuildDoorman} {@code Object}. + */ + public RangingGuildDoorman() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code RangingGuildDoorman} {@code Object}. + * + * @param player the player. + */ + public RangingGuildDoorman(Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new RangingGuildDoorman(player); + } + + @Override + public boolean open(Object... args) { + npc = (NPC) args[0]; + interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there."); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Greetings. If you are an experienced archer, you may", "want to visit the guild here..."); + stage = 1; + break; + case 1: + end(); + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{679}; + } + } + + /** + * Represents the tribal weapon salseman dialogue. + * + * @author 'Vexia + * @version 1.0 + */ + public final class TribalWeaponSalesman extends DialoguePlugin { + + /** + * Constructs a new {@code TribalWeaponSalesman} {@code Object}. + */ + public TribalWeaponSalesman() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code TribalWeaponSalesman} {@code Object}. + * + * @param player the player. + */ + public TribalWeaponSalesman(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new TribalWeaponSalesman(player); + } + + @Override + public boolean open(Object... args) { + npc = (NPC) args[0]; + player("Hello there."); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + npc("Greetings, traveller. Are you interested in any throwing", "weapons?"); + stage = 1; + break; + case 1: + options("Yes I am.", "Not really."); + stage = 2; + break; + case 2: + switch (buttonId) { + case 1: + player("Yes I am."); + stage = 10; + break; + case 2: + player("Not really."); + stage = 20; + break; + } + break; + case 10: + npc("That is a good thing."); + stage = 11; + break; + case 11: + end(); + npc.openShop(player); + break; + case 20: + npc("No bother to me."); + stage = 21; + break; + case 21: + end(); + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{692}; + } + + } + + /** + * Represents the guard dialogue. + * + * @author 'Vexia + * @version 1.0 + */ + public final class GuardDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code GuardDialogue} {@code Object}. + */ + public GuardDialogue() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code GuardDialogue} {@code Object}. + * + * @param player the player. + */ + public GuardDialogue(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new GuardDialogue(player); + } + + @Override + public boolean open(Object... args) { + player("Hello there."); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + npc("Greetings, traveller. Enjoy the time at the Ranging", "Guild."); + stage = 1; + break; + case 1: + end(); + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{678}; + } + + } + + /** + * Represents the leather workers dialogue. + * + * @author 'Vexia + * @version 1.0 + */ + public final class LeatherWorkerDialogue extends DialoguePlugin { + + /** + * Constructs a new {@code LeatherWorkerDialogue} {@code Object}. + */ + public LeatherWorkerDialogue() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code LeatherWorkerDialogue} {@code Object}. + * + * @param player the player. + */ + public LeatherWorkerDialogue(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new LeatherWorkerDialogue(player); + } + + @Override + public boolean open(Object... args) { + player("Hello."); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + npc("Can I help you?"); + stage = 1; + break; + case 1: + options("What do you do here?", "No thanks."); + stage = 2; + break; + case 2: + switch (buttonId) { + case 1: + player("What do you do here?"); + stage = 10; + break; + case 2: + player("No thanks."); + stage = 20; + break; + } + break; + case 10: + npc("Well, I can cure plain cowhides into pieces of leather", "ready for crafting."); + stage = 11; + break; + case 11: + npc("I work with ordinary, hard or dragonhide leather and", "also snakeskin."); + stage = 12; + break; + case 12: + end(); + TanningProduct.open(player, 680); + break; + case 20: + npc("Suit yourself."); + stage = 21; + break; + case 21: + end(); + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{680}; + } + + } + + /** + * Represents the armour salesman dialogue. + * + * @author 'Vexia + * @version 1.0 + */ + public final class ArmourSalesman extends DialoguePlugin { + + /** + * Constructs a new {@code ArmourSalesman} {@code Object}. + */ + public ArmourSalesman() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code ArmourSalesman} {@code Object}. + * + * @param player the player. + */ + public ArmourSalesman(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new ArmourSalesman(player); + } + + @Override + public boolean open(Object... args) { + npc = (NPC) args[0]; + player("Good day to you."); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + npc("And to you. Can I help you?"); + stage = 1; + break; + case 1: + if (Skillcape.isMaster(player, Skills.RANGE)) { + options("What do you do here?", "I'd like to see what you sell.", "Can I buy a Skillcape of Range?", "I've seen enough, thanks."); + stage = 100; + } else { + options("What do you do here?", "I'd like to see what you sell.", "I've seen enough, thanks."); + stage = 2; + } + break; + case 2: + switch (buttonId) { + case 1: + player("What do you do here?"); + stage = 10; + break; + case 2: + player("I'd like to see what you sell."); + stage = 20; + break; + case 3: + player("I've seen enough, thanks."); + stage = 30; + break; + } + break; + case 10: + npc("I am a supplier of leather armours and accessories. Ask", "and I will tell you what I know."); + stage = 11; + break; + case 11: + options("Tell me about your armours.", "Tell me about your accessories.", "I've seen enough, thanks."); + stage = 12; + break; + case 12: + switch (buttonId) { + case 1: + player("Tell me about your armours."); + stage = 13; + break; + case 2: + player("Tell me about your accessories."); + stage = 15; + break; + case 3: + player("I've seen enough, thanks."); + stage = 30; + break; + } + break; + case 13: + npc("I have normal, studded and hard types."); + stage = 14; + break; + case 14: + case 31: + case 105: + end(); + break; + case 15: + npc("Ah yes we have a new range of accessories in stock.", "Essential items for an archer like you."); + stage = 14; + break; + case 20: + npc("Indeed, cast your eyes on my wares, adventurer."); + stage = 21; + break; + case 21: + end(); + npc.openShop(player); + break; + case 30: + npc("Very good, adventurer."); + stage = 31; + break; + case 100: + switch (buttonId) { + case 1: + player("What do you do here?"); + stage = 10; + break; + case 2: + player("I'd like to see what you sell."); + stage = 20; + break; + case 3: + player("Can I buy a Skillcape of Range?"); + stage = 101; + break; + case 4: + player("I've seen enough, thanks."); + stage = 30; + break; + } + break; + case 101: + npc("Certainly! Right when you give me 99000 coins."); + stage = 102; + break; + case 102: + options("Okay, here you go.", "No, thanks."); + stage = 103; + break; + case 103: + switch (buttonId) { + case 1: + player("Okay, here you go."); + stage = 104; + break; + case 2: + end(); + break; + } + break; + case 104: + if (Skillcape.purchase(player, Skills.RANGE)) { + npc("There you go! Enjoy."); + } + stage = 105; + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{682}; + } + + } + + /** + * Represents the dialogue plugin used for the bow and arrow salesman. + * + * @author 'Vexia + * @version 1.0 + */ + public final class BowArrowSalesman extends DialoguePlugin { + + /** + * Constructs a new {@code BowArrowSalesman} {@code Object}. + */ + public BowArrowSalesman() { + /** + * empty. + */ + } + + /** + * Constructs a new {@code BowArrowSalesman} {@code Object}. + * + * @param player the player. + */ + public BowArrowSalesman(final Player player) { + super(player); + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new BowArrowSalesman(player); + } + + @Override + public boolean open(Object... args) { + npc = (NPC) args[0]; + player("Hello."); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 0: + npc("A fair day, traveller. Would you like to see my wares?"); + stage = 1; + break; + case 1: + options("Yes please.", "No thanks."); + stage = 2; + break; + case 2: + switch (buttonId) { + case 1: + end(); + npc.openShop(player); + + break; + case 2: + end(); + break; + } + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{683}; + } + + } + + /** + * Represents the waring interface used in the guild. + * + * @author 'Vexia + * @version 1.0 + */ + public final class WarningInterface extends ComponentPlugin { + + @Override + public Plugin newInstance(Object arg) throws Throwable { + ComponentDefinition.forId(564).setPlugin(this); + return this; + } + + @Override + public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { + switch (button) { + case 17: + ClimbActionHandler.climb(player, null, Location.create(2668, 3427, 2)); + player.getInterfaceManager().close(); + List npcs = RegionManager.getLocalNPCs(Location.create(2668, 3427, 2)); + String dir = ""; + for (NPC n : npcs) { + if (n.getId() >= 684 && n.getId() <= 687) { + switch (n.getId()) { + case 684: + dir = "north"; + break; + case 685: + dir = "east"; + break; + case 686: + dir = "south"; + break; + case 687: + dir = "west"; + break; + } + n.sendChat("The " + dir + " tower is occupied, get them!"); + } + } + break; + case 18: + player.getInterfaceManager().close(); + break; + } + return true; + } + + } + + /** + * Represents the competition judge. + * + * @author afaroutdude + */ + public final class CompetitionJudge extends DialoguePlugin { + + /** + * Constructs a new {@code CompetitionJudge} {@code Object}. + * + * @param player the player. + */ + public CompetitionJudge(final Player player) { + super(player); + } + + /** + * Constructs a new {@code CompetitionJudge} {@code Object}. + */ + public CompetitionJudge() { + /** + * empty. + */ + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new CompetitionJudge(player); + } + + @Override + public boolean open(Object... args) { + if (player.getInventory().getAmount(1464) >= 1000 + && !player.getAchievementDiaryManager().hasCompletedTask(DiaryType.SEERS_VILLAGE, 1, 7)) { + npc("Wow! I see that you've got yourself a whole load of ", "archery tickets. Well done!"); + player.getAchievementDiaryManager().finishTask(player, DiaryType.SEERS_VILLAGE, 1, 7); + stage = -1; + } else if (player.getArcheryTargets() > 0) { + npc("Hello again, do you need reminding of the rules?"); + stage = 20; + } else if (player.getArcheryTotal() == 0) { + npc("Hello there, would you like to take part in the", + "archery competition? It only costs 200 coins to", + "enter."); + stage = 0; + } else { + int reward = player.getArcheryTotal() / 10; + npc("Well done. Your score is: " + player.getArcheryTotal() + ".", + "For that score you will receive " + reward + " Archery tickets."); + player.setArcheryTargets(-1); + player.setArcheryTotal(0); + if (!player.getInventory().add(new Item(1464, reward))) { + player.getBank().add(new Item(1464, reward)); + player.sendMessage("Your reward was sent to your bank."); + } + stage = 999; + } + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 999: + end(); + break; + case -1: + if (player.getArcheryTargets() > 0) { + npc("Hello again, do you need reminding of the rules?"); + stage = 20; + } else if (player.getArcheryTotal() == 0) { + npc("Hello there, would you like to take part in the", + "archery competition? It only costs 200 coins to", + "enter."); + stage = 0; + } else { + int reward = player.getArcheryTotal() / 10; + npc("Well done. Your score is: " + player.getArcheryTotal() + ".", + "For that score you will receive " + reward + " Archery tickets."); + if (!player.getInventory().add(new Item(1464, reward))) { + player.getBank().add(new Item(1464, reward)); + player.sendMessage("Your reward was sent to your bank."); + } + stage = 999; + } + break; + case 0: + options("Sure, I'll give it a go.", "What are the rules?", "No thanks."); + stage++; + break; + case 1: + switch (buttonId) { + case 1: + player("Sure, I'll give it a go."); + stage = 2; + break; + case 2: + player("What are the rules?"); + stage = 5; + break; + case 3: + player("No thanks."); + stage = 999; + break; + } + break; + case 2: + npc("Great! That will be 200 coins then please."); + stage++; + break; + case 3: + if (player.getInventory().getAmount(995) < 200) { + player("Oops, I don't have enough coins on me..."); + stage++; + } else { + end(); + player.getPacketDispatch().sendMessage("You pay the judge and he gives you 10 bronze arrows."); + player.getInventory().remove(new Item(995, 200)); + player.getInventory().add(new Item(882, 10)); + player.setArcheryTargets(10); + player.setArcheryTotal(0); + } + break; + case 4: + npc("Never mind, come back when you've got enough."); + stage = 999; + break; + case 5: + case 22: + npc("The rules are very simple:"); + stage++; + break; + case 6: + case 23: + npc("You're given 10 shots at the targets, for each hit", "you will receive points. At the end you'll be", "rewarded 1 ticket for every 10 points."); + stage++; + break; + case 7: + npc("The tickets can be exchanged for goods from our stores.", "Do you want to give it a go? Only 200 coins."); + stage++; + break; + case 8: + options("Sure, I'll give it a go.", "No thanks."); + stage++; + break; + case 9: + switch (buttonId) { + case 1: + player("Sure, I'll give it a go."); + stage = 2; + break; + case 3: + player("No thanks."); + stage = 999; + break; + } + break; + case 20: + int arrows = player.getInventory().getAmount(Items.BRONZE_ARROW_882) + + player.getEquipment().getAmount(Items.BRONZE_ARROW_882); + if (arrows < 1) { + player("Well, I actually don't have any more arrows. Could I", "get some more?"); + stage = 25; + } else { + options("Yes please.", "No thanks, I've got it.", "How am I doing so far?"); + stage++; + } + break; + case 21: + switch (buttonId) { + case 1: + player("Yes please."); + stage++; + break; + case 2: + player("No thanks, I've got it."); + stage = 30; + break; + case 3: + player("How am I doing so far?"); + stage = 40; + break; + } + break; + case 24: + npc("The tickets can be exchanged for goods from our stores.", "Good Luck!"); + stage = 999; + break; + case 25: + npc("Ok, but it'll cost you 100 coins."); + stage++; + break; + case 26: + options("Sure, I'll take some.", "No thanks."); + stage++; + break; + case 27: + switch (buttonId) { + case 1: + player("Sure, I'll take some."); + stage++; + break; + case 2: + player("No thanks."); + stage = 999; + break; + } + break; + case 28: + if (player.getInventory().getAmount(995) < 100) { + player("Oops, I don't have enough coins on me..."); + stage++; + } else { + end(); + player.getPacketDispatch().sendMessage("You pay the judge and he gives you 10 bronze arrows."); + player.getInventory().remove(new Item(995, 100)); + player.getInventory().add(new Item(882, 10)); + } + break; + case 30: + npc("Glad to hear it, good luck!"); + stage = 999; + break; + case 40: + String msg; + if (player.getArcheryTotal() <= 0) { + msg = "You haven't started yet."; + } else if (player.getArcheryTotal() <= 80) { + msg = "Not bad, keep going."; + } else { + msg = "You're pretty good, keep it up."; + } + npc("So far your score is: " + player.getArcheryTotal(), msg); + stage = 999; + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{693}; + } + + } + + /** + * Represents the tower advisors. + * + * @author afaroutdude + */ + public final class TowerAdvisor extends DialoguePlugin { + + /** + * Constructs a new {@code TowerAdvisor} {@code Object}. + * + * @param player the player. + */ + public TowerAdvisor(final Player player) { + super(player); + } + + /** + * Constructs a new {@code TowerAdvisor} {@code Object}. + */ + public TowerAdvisor() { + } + + @Override + public DialoguePlugin newInstance(Player player) { + return new TowerAdvisor(player); + } + + @Override + public boolean open(Object... args) { + player("Hello there, what do you do here?"); + stage = 0; + return true; + } + + @Override + public boolean handle(int interfaceId, int buttonId) { + switch (stage) { + case 999: + end(); + case 0: + npc("Hi. We are in charge of this practice area."); + stage++; + break; + case 1: + player("This is a practice area?"); + break; + case 2: + npc("Surrounding us are four towers. Each tower contains", + "trained archers of a different level. You'll notice", + "it's quite a distance, so you'll need a longbow."); + stage++; + break; + case 3: + int rangeLevel = player.getSkills().getLevel(Skills.RANGE); + if (rangeLevel < 50) { // north + npc("As you're not very skilled, I advise you to practice", + "on the north tower. That'll provide the best", + "challenge for you."); + } else if (rangeLevel < 60) { // east + npc("You appear to be somewhat skilled with a bow, so I", + "advise you to practice on the south tower. That'll", + "provide the best challenge for you."); + } else if (rangeLevel < 70) { // south + npc("You appear to be fairly skilled with a bow, so I", + "advise you to practice on the south tower. That'll", + "provide the best challenge for you."); + } else { // west + npc("Looks like you're very skilled, so I advise you to", + "practice on the west tower. That'll provide the best", + "challenge for you."); + } + stage = 999; + break; + } + return true; + } + + @Override + public int[] getIds() { + return new int[]{684, 685, 686, 687}; + } + + } + + + /** + * Represents all the tower archers + * + * @author afaroutdude + */ + public final class TowerArcher extends AbstractNPC { + + public TowerArcher() { + super(-1, null); + } + public TowerArcher(int id, Location location) { + super(id, location); + } + + + @Override + public AbstractNPC construct(int id, Location location, Object... objects) { + return new TowerArcher(id, location); + } + + @Override + public int[] getIds() { + return new int[]{688, 689, 690, 691}; + } + } + + /** + * Represents the archery target pulse. + * + * @author Jamix77 + */ + public static final class ArcheryCompetitionPulse extends Pulse { + + /** + * Represents the player instance. + */ + private final Player player; + + /** + * Represents the scenery. + */ + private final Scenery object; + + /** + * Constructs a new {@code ArcheryCompetitionPulse} {@code Object}. + * + * @param player the player. + * @param object the object. + */ + public ArcheryCompetitionPulse(final Player player, final Scenery object) { + super(1, player, object); + this.player = player; + this.object = object; + } + + private void showInterface(int points, int arrowsLeft, int target, String msg) { + player.getInterfaceManager().openComponent(325); + setVarp(player, 156, 11 - arrowsLeft); + setVarp(player, 157, points); + setVarp(player, 158, target); + player.getPacketDispatch().sendString(msg, 325, 32); + } + + @Override + public boolean pulse() { + if (player.getArcheryTargets() <= 0) { + return true; + } + if (getDelay() == 1) { + setDelay(player.getProperties().getAttackSpeed()); + } + if (player.getEquipment().remove(new Item(Items.BRONZE_ARROW_882, 1))) { + Projectile p = Ammunition.get(Items.BRONZE_ARROW_882).getProjectile().transform(player, object.getLocation()); + p.setEndLocation(object.getLocation()); + p.setEndHeight(25); + p.send(); + player.animate(new Animation(426)); + player.lock(getDelay()); + + int level = player.getSkills().getLevel(Skills.RANGE); + int bonus = player.getProperties().getBonuses()[14]; + double prayer = 1.0; + prayer += player.getPrayer().getSkillBonus(Skills.RANGE); + double cumulativeStr = Math.floor(level * prayer); + /*if (player.getProperties().getAttackStyle().getStyle() == WeaponInterface.STYLE_RANGE_ACCURATE) { + cumulativeStr += 3; + } else if (player.getProperties().getAttackStyle().getStyle() == WeaponInterface.STYLE_LONG_RANGE) { + cumulativeStr += 1; + }*/ + cumulativeStr *= 1.0; + int hit = (int) ((14 + cumulativeStr + (bonus / 8) + ((cumulativeStr * bonus) * 0.016865))) / 10 + 1; + hit = hit + RandomFunction.randomSign(RandomFunction.random(3)); + + int target = Math.max(0, 13 - hit); + int points = 0; + String msg = ""; + switch (target) { + case 0: + points = 100; + msg = "Bulls-Eye!"; + break; + case 1: + points = 50; + msg = "Hit Yellow!"; + break; + case 2: + case 3: + case 4: + points = 30; + msg = "Hit Red!"; + break; + case 5: + case 6: + case 7: + case 8: + points = 20; + msg = "Hit Blue!"; + break; + case 9: + case 10: + points = 10; + msg = "Hit Black!"; + break; + case 11: + case 12: + case 13: + points = 0; + msg = "Missed!"; + break; + } + int xp = points / 2; + + player.getSkills().addExperience(Skills.RANGE, xp, true); + player.setArcheryTotal(player.getArcheryTotal() + points); + player.setArcheryTargets(player.getArcheryTargets() - 1); + player.debug("Hit: " + hit); + player.debug("You have " + player.getArcheryTargets() + " targets left."); + player.debug("You have " + player.getArcheryTotal() + " score."); + + showInterface(player.getArcheryTotal(), player.getArcheryTargets(), target, msg); + + return true; //player.getArcheryTargets() <= 0; + } else { + return true; + } + } + + } } diff --git a/Server/src/main/content/region/karamja/diary/KaramjaAchievementDiary.kt b/Server/src/main/content/region/karamja/diary/KaramjaAchievementDiary.kt index cda31648c..927198ce5 100644 --- a/Server/src/main/content/region/karamja/diary/KaramjaAchievementDiary.kt +++ b/Server/src/main/content/region/karamja/diary/KaramjaAchievementDiary.kt @@ -83,7 +83,7 @@ class KaramjaAchievementDiary : DiaryEventHookBase(DiaryType.KARAMJA) { } override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10802 -> if (event.itemId == Items.GOLD_ORE_444) { finishTask( player, @@ -148,7 +148,7 @@ class KaramjaAchievementDiary : DiaryEventHookBase(DiaryType.KARAMJA) { } override fun onNpcKilled(player: Player, event: NPCKillEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 10899, 10900 -> if (event.npc.id in METAL_DRAGONS) { finishTask( player, diff --git a/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarFightPitsPlugin.java b/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarFightPitsPlugin.java index 5070b76ef..ea8c0cd6b 100644 --- a/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarFightPitsPlugin.java +++ b/Server/src/main/content/region/karamja/tzhaar/handlers/TzhaarFightPitsPlugin.java @@ -8,6 +8,7 @@ import java.util.Random; import core.game.component.Component; import core.game.container.impl.EquipmentContainer; import core.game.activity.ActivityPlugin; +import core.game.world.map.RegionChunk; import core.plugin.Initializable; import core.game.dialogue.FacialExpression; import core.game.node.entity.skill.Skills; @@ -30,6 +31,7 @@ import core.game.world.map.RegionManager; import core.game.world.map.zone.ZoneBorders; import core.game.world.map.zone.ZoneRestriction; import core.tools.RandomFunction; +import org.rs09.consts.NPCs; import static core.api.ContentAPIKt.*; @@ -145,7 +147,15 @@ public final class TzhaarFightPitsPlugin extends ActivityPlugin { lastVictor.getPacketDispatch().sendString("Current Champion: " + getChampionName(), INTERFACE_ID, 0); resetDamagePulse(lastVictor); } - RegionManager.forId(9552).getPlanes()[0].getNpcs().get(0).setAttribute("fp_champn", getChampionName()); + RegionChunk[][][] chunks = RegionManager.forId(9552).getChunks(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + List npcs = chunks[x][y][0].getNpcs(); + for (NPC npc : npcs) { + npc.setAttribute("fp_champn", getChampionName()); + } + } + } } minutes = 0; } @@ -180,10 +190,15 @@ public final class TzhaarFightPitsPlugin extends ActivityPlugin { * Resets the last victor. */ private void resetLastVictor() { - List npcs = new ArrayList<>(RegionManager.forId(9552).getPlanes()[0].getNpcs()); - for (NPC n : npcs) { - if (n.getId() == 2734 || n.getId() == 2739) { - n.clear(); + RegionChunk[][][] chunks = RegionManager.forId(9552).getChunks(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + List npcs = chunks[x][y][0].getNpcs(); + for (NPC npc : npcs) { + if (npc.getId() == NPCs.TZ_KIH_2734 || npc.getId() == NPCs.TOK_XIL_2739) { + npc.clear(); + } + } } } if (lastVictor == null || !lastVictor.isActive()) { @@ -355,7 +370,7 @@ public final class TzhaarFightPitsPlugin extends ActivityPlugin { } int size = (LOBBY_PLAYERS.size() + WAR_PLAYERS.size()) - 1; if (!WAR_PLAYERS.isEmpty()) { - setVarp(WAR_PLAYERS.get(0), 560, size); + setVarp(WAR_PLAYERS.get(0), 560, size); } for (Iterator it = LOBBY_PLAYERS.iterator(); it.hasNext();) { Player p = it.next(); @@ -367,7 +382,7 @@ public final class TzhaarFightPitsPlugin extends ActivityPlugin { } p.getSkullManager().setSkullCheckDisabled(true); p.getSkullManager().setWilderness(true); - setVarp(p, 560, size); + setVarp(p, 560, size); p.getProperties().setTeleportLocation(getZoneDestination()); p.getInteraction().set(Option._P_ATTACK); tokkulAmount += p.getProperties().getCurrentCombatLevel(); @@ -449,7 +464,7 @@ public final class TzhaarFightPitsPlugin extends ActivityPlugin { */ public static void sendPlayersRemaining(int value) { for (Player p : WAR_PLAYERS) { - setVarp(p, 560, value); + setVarp(p, 560, value); } } diff --git a/Server/src/main/content/region/misthalin/draynor/dialogue/DraynorBankGuard.java b/Server/src/main/content/region/misthalin/draynor/dialogue/DraynorBankGuard.java index 13275ac76..4c485d7af 100644 --- a/Server/src/main/content/region/misthalin/draynor/dialogue/DraynorBankGuard.java +++ b/Server/src/main/content/region/misthalin/draynor/dialogue/DraynorBankGuard.java @@ -1,5 +1,6 @@ package content.region.misthalin.draynor.dialogue; +import content.region.misthalin.draynor.handlers.DBRCutscene; import core.game.activity.ActivityManager; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; @@ -55,7 +56,7 @@ public final class DraynorBankGuard extends DialoguePlugin { public boolean handle(int interfaceId, int buttonId) { switch (stage) { case 0: - if (!player.getSavedData().getGlobalData().isDraynorRecording()) { + if (!player.getAttribute("draynor-recording", false)) { interpreter.sendOptions("Select an option", "Can I deposit my stuff here?", "That wall doesn't look very good.", "Sorry, I don't want anything."); stage = 1; } else { @@ -325,7 +326,7 @@ public final class DraynorBankGuard extends DialoguePlugin { */ private void startRecording(Player player) { end(); - ActivityManager.start(player, "dbr cutscene", false); + new DBRCutscene(player).start(); } @Override diff --git a/Server/src/main/content/region/misthalin/draynor/handlers/DBRCutscenePlugin.java b/Server/src/main/content/region/misthalin/draynor/handlers/DBRCutscenePlugin.java deleted file mode 100644 index 78c30fa3e..000000000 --- a/Server/src/main/content/region/misthalin/draynor/handlers/DBRCutscenePlugin.java +++ /dev/null @@ -1,896 +0,0 @@ -package content.region.misthalin.draynor.handlers; - -import core.game.component.Component; -import core.game.activity.ActivityPlugin; -import core.game.activity.CutscenePlugin; -import core.game.global.action.DoorActionHandler; -import core.plugin.Initializable; -import core.game.node.entity.skill.Skills; -import core.game.node.Node; -import core.game.node.entity.Entity; -import core.game.node.entity.combat.CombatStyle; -import core.game.node.entity.combat.ImpactHandler.HitsplatType; -import core.game.node.entity.impl.Projectile; -import core.game.node.entity.npc.AbstractNPC; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.SpellBookManager; -import core.game.node.item.GroundItem; -import core.game.node.item.GroundItemManager; -import core.game.node.item.Item; -import core.game.node.item.ItemPlugin; -import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; -import core.game.system.task.Pulse; -import core.game.world.GameWorld; -import core.game.world.map.Direction; -import core.game.world.map.Location; -import core.game.world.map.RegionManager; -import core.game.world.map.build.DynamicRegion; -import core.game.world.map.path.Pathfinder; -import core.game.world.update.flag.context.Animation; -import core.game.world.update.flag.context.Graphics; -import core.net.packet.PacketRepository; -import core.net.packet.context.CameraContext; -import core.net.packet.context.CameraContext.CameraType; -import core.net.packet.out.CameraViewPacket; -import core.plugin.Plugin; -import core.plugin.ClassScanner; - -/** - * Represents the draynor bank robbery cutscene plugin. - * - * @author 'Vexia - * @version 1.0 - */ -@Initializable -public final class DBRCutscenePlugin extends CutscenePlugin { - - /** - * Represents the cracked component. - */ - private static final Component CRACKED = new Component(385); - - /** - * Represents the stealing animation used for cool mom. - */ - private static final Animation STEAL_ANIMATION = new Animation(832); - - /** - * Represents the casting animation. - */ - private static final Animation CAST_ANIMATION = new Animation(1167); - - /** - * Represents the telekentic animation to use. - */ - private static final Animation TELEKENTIC_ANIMATION = new Animation(723); - - /** - * Represents the telekentic graphics. - */ - private static final Graphics TELEKENTIC_GRAPHIC = new Graphics(142, 96); - - /** - * Represents the casting animation. - */ - private static final Animation SECOND_CAST_ANIMATION = new Animation(1167); - - /** - * Represents the death animation to use. - */ - private static final Animation DEATH_ANIMATION = new Animation(2553); - - /** - * Represents the graphics to use. - */ - private static final Graphics SHOCK_GRAPHIC = new Graphics(432, 0, 0); - - /** - * Represents the teleport animation to use. - */ - private static final Animation TELEPORT_ANIMATION = new Animation(1816); - - /** - * Represents the graphics to use for teleother. - */ - private static final Graphics[] TELE_OTHERS = new Graphics[] { new Graphics(343), new Graphics(342) }; - - /** - * Represents the pick up animation to use. - */ - private static final Animation PICK_UP_ANIMATION = new Animation(827); - - /** - * Represents the hitting animation. - */ - private static final Animation HIT_ANIMATION = new Animation(401); - - /** - * Represents the blocking animation. - */ - private static final Animation BLOCK_ANIMATION = new Animation(425); - - /** - * Represents the thunder animation. - */ - private static final Animation THUNDER_ANIMATION = new Animation(811); - - /** - * Represents the purple graphics. - */ - private static final Graphics PURPLE_GRAPHIC = new Graphics(301, 100); - - /** - * Represents the thunder graphic. - */ - private static final Graphics THUNDER_GRAPHIC = new Graphics(76); - - /** - * Represents the animation to use for the wise old man. - */ - private static final Animation WISE_JUMP = new Animation(2555); - - /** - * Represents the market guard jump animation. - */ - private static final Animation GUARD_JUMP = new Animation(2556); - - /** - * Represents the stomp animation. - */ - private static final Animation STOMP_ANIM = new Animation(1820); - - /** - * Represents the ashes item. - */ - private static final Item ASHES = new Item(592); - - /** - * Represents the coins item. - */ - private static final Item COINS = new Item(995, 60); - - /** - * Represents the party hat item. - */ - private static final Item PARTY_HAT = new Item(2422); - - /** - * Represents the recording pulse. - */ - private final RecordingPulse recordingPulse = new RecordingPulse(); - - /** - * Represents the npcs to use in the cutscene. - */ - private static final NPC[] NPCS = new NPC[] { - /** cool mom */ - NPC.create(2579, Location.create(2120, 4916, 0), Direction.NORTH), - /** olivia */ - NPC.create(2572, Location.create(2117, 4913, 0), Direction.WEST), - /** market guard */ - NPC.create(2571, Location.create(13, 48, 0), Direction.WEST), - /** purepker */ - NPC.create(2575, new Location(2136, 4914, 0), Direction.WEST), - /** first banker */ - NPC.create(2568, new Location(2130, 4909, 0), Direction.EAST), - /** second last banker. */ - NPC.create(2569, new Location(2130, 4907, 0)), - /** last banker */ - NPC.create(2570, new Location(2130, 4906, 0)), - /** efinlocks */ - NPC.create(2578, new Location(2133, 4908, 0)), - /** 1337sp34kr */ - NPC.create(2577, new Location(2134, 4906, 0), Direction.WEST), - /** quitedoll */ - NPC.create(2576, new Location(2133, 4906, 0), Direction.EAST), - /** oldman */ - NPC.create(2566, new Location(2128, 4915, 0), Direction.SOUTH) }; - - /** - * Constructs a new {@code DBRCutscenePlugin} {@code Object}. - */ - public DBRCutscenePlugin() { - super("dbr cutscene"); - } - - /** - * Constructs a new {@code DBRCutscenePlugin} {@code Object}. - * - * @param player - * the player. - */ - public DBRCutscenePlugin(final Player player) { - super("dbr cutscene"); - this.player = player; - } - - @Override - public void open() { - setNpcs(); - GameWorld.getPulser().submit(recordingPulse); - player.lock(); - player.getLocks().lockMovement(10000000); - camera(27, 45, -14, 2, 700, 100); - } - - @Override - public ActivityPlugin newInstance(Player p) throws Throwable { - return new DBRCutscenePlugin(p); - } - - @Override - public void register() { - super.register(); - try { - new DBRecordingNPC().newInstance(null); - } catch (Throwable e) { - e.printStackTrace(); - } - ClassScanner.definePlugin(new BluePhatItem()); - } - - @Override - public Location getSpawnLocation() { - return null; - } - - @Override - public Location getStartLocation() { - return base.transform(17, 51, 0); - } - - @Override - public void configure() { - region = DynamicRegion.create(8524); - setRegionBase(); - registerRegion(region.getId()); - player.getDialogueInterpreter().sendPlainMessage(true, "You close your eyes and watch the recording..."); - } - - @Override - public void end() { - super.end(); - clearNpcs(); - player.getSavedData().getGlobalData().setDraynorRecording(true); - player.getDialogueInterpreter().sendDialogue("End of recording."); - } - - /** - * Gets the cool mom npc. - * - * @return the cool mom npc. - */ - public NPC getCoolMom() { - return getNpc(2579); - } - - /** - * Gets the olivia npc. - * - * @return the olivia npc. - */ - public NPC getOlivia() { - return getNpc(2572); - } - - /** - * Gets the market guard npc. - * - * @return the market guard. - */ - public NPC getMarketGuard() { - return getNpc(2571); - } - - /** - * Gets the pure pker npc. - * - * @return the pure pker npc. - */ - public NPC getPurePker() { - return getNpc(2575); - } - - /** - * Gets the elfinlocks npc. - * - * @return the elfinocks npc. - */ - public NPC getElfinocks() { - return getNpc(2578); - } - - /** - * Gets the 1337sp34kr npc. - * - * @return the 1337sp34kr npc. - */ - public NPC get1337() { - return getNpc(2577); - } - - /** - * Gets the quitedoll npc. - * - * @return the quitedoll npc. - */ - public NPC getQuiteDoll() { - return getNpc(2576); - } - - /** - * Gets the wise old man npc. - * - * @return the wise old man npc. - */ - public NPC getWiseOldMan() { - int size = region.getPlanes()[0].getNpcs().size(); - return region.getPlanes()[0].getNpcs().get(size - 1); - } - - /** - * Gets the first banker. - * - * @return the first banker. - */ - public NPC getFirstBanker() { - return getNpc(2568); - } - - /** - * Gets the second banker. - * - * @return the second banker. - */ - public NPC getSecondBanker() { - return getNpc(2569); - } - - /** - * Gets the last banker. - * - * @return the last banker. - */ - public NPC getLastBanker() { - return getNpc(2570); - } - - /** - * Method used to walk an npc. - * - * @param npc - * the npc. - * @param location - * the location. - */ - private void walk(NPC npc, final Location location) { - Pathfinder.find(npc, location, true, Pathfinder.DUMB).walk(npc); - } - - /** - * Method used to kill an npc. - * - * @param npc - * the npc. - */ - private void die(NPC npc) { - npc.getAnimator().reset(); - npc.animate(DEATH_ANIMATION); - npc.graphics(SHOCK_GRAPHIC); - npc.getImpactHandler().manualHit(npc, npc.getSkills().getLifepoints(), HitsplatType.NORMAL); - } - - /** - * Method used to cast a shock. - * - * @param target - * the target. - */ - private void castShock(Node target) { - getWiseOldMan().animate(CAST_ANIMATION); - getWiseOldMan().graphics(new Graphics(433)); - if (target instanceof Entity) { - Projectile.create(getWiseOldMan(), (Entity) target, 434).send(); - } else { - Projectile projectile = Projectile.create(getWiseOldMan(), null, 434, 30, 30, 41, 140, 0, 0); - projectile.setEndLocation((Location) target); - projectile.send(); - } - } - - /** - * Method used to cast the telekinetic grab spell. - */ - private void castTelekinetic() { - getWiseOldMan().animate(TELEKENTIC_ANIMATION); - getWiseOldMan().graphics(TELEKENTIC_GRAPHIC); - getWiseOldMan().getSkills().setStaticLevel(Skills.MAGIC, 99); - getWiseOldMan().getSkills().setLevel(Skills.MAGIC, 99); - SpellBookManager.SpellBook.MODERN.getSpell(19).cast(getWiseOldMan(), GroundItemManager.get(PARTY_HAT.getId(), base.transform(20, 44, 0), player)); - } - - /** - * Method used to cast the thunder shock. - */ - private void castThunderShock() { - getWiseOldMan().animate(THUNDER_ANIMATION); - getWiseOldMan().graphics(PURPLE_GRAPHIC); - } - - /** - * Method used to handle the camera. - * - * @param x - * the x offset. - * @param y - * the y offset. - * @param xRot - * the xRotation. - * @param yRot - * the yRotation. - * @Param height the height. - */ - private void camera(int x, int y, int xRot, int yRot, int height, int speed) { - Location loc = base.transform(x, y, 0); - PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.POSITION, loc.getX(), loc.getY(), height, 1, speed)); - PacketRepository.send(CameraViewPacket.class, new CameraContext(player, CameraType.ROTATION, loc.getX() + xRot, loc.getY() + yRot, height, 1, speed)); - } - - /** - * Method used to set npcs and their locations. - */ - private void setNpcs() { - for (NPC n : NPCS) { - n = NPC.create(n.getId(), n.getLocation(), n.getDirection()); - n.setLocation(base.transform(n.getLocation().getLocalX(), n.getLocation().getLocalY(), 0)); - n.setRespawn(false); - n.init(); - if (n.getName().equals("Banker")) { - n.getSkills().setStaticLevel(Skills.HITPOINTS, 15); - n.getSkills().setLevel(Skills.HITPOINTS, 15); - } - n.setWalks(false); - } - } - - /** - * Method used to clear all the npcs. - */ - private void clearNpcs() { - GameWorld.getPulser().submit(new Pulse(5) { - @Override - public boolean pulse() { - for (NPC n : region.getPlanes()[0].getNpcs()) { - n.clear(); - } - return true; - } - - }); - } - - /** - * Gets the npc. - * - * @param id - * the id. - * @return the npc. - */ - private NPC getNpc(int id) { - for (NPC n : region.getPlanes()[0].getNpcs()) { - if (n.getId() == id) { - return n; - } - } - return null; - } - - /** - * Represents the pulse used during recording. - * - * @author 'Vexia - * @version 1.0 - */ - public final class RecordingPulse extends Pulse { - - /** - * Represents the counter. - */ - private int counter; - - /** - * Constructs a new {@code FightPulse} {@code Object}. - */ - public RecordingPulse() { - super(1, player); - } - - @Override - public boolean pulse() { - switch (counter++) { - case 1: - getCoolMom().animate(STEAL_ANIMATION); - getMarketGuard().getSkills().setStaticLevel(Skills.HITPOINTS, 99); - getMarketGuard().getSkills().setLifepoints(99); - getMarketGuard().sendChat("Hey! Get your hands off there!"); - getCoolMom().getLocks().lockMovement(1000); - getMarketGuard().getProperties().getCombatPulse().attack(getCoolMom()); - break; - case 8: - walk(getPurePker(), base.transform(20, 45, 0)); - break; - case 10: - camera(27, 43, -37, -3, 600, 5); - break; - case 12: - getQuiteDoll().sendChat("Thx"); - break; - case 14: - walk(getQuiteDoll(), base.transform(20, 42, 0)); - get1337().sendChat("Yw"); - getPurePker().faceLocation(base.getLocation().transform(19, 45, 0)); - break; - case 16: - getElfinocks().sendChat("Buying 2k nats - no noob offers"); - break; - case 20: - get1337().sendChat("I h4ve n4ts"); - break; - case 22: - getElfinocks().sendChat("You sell?"); - break; - case 25: - get1337().sendChat("Tr4de"); - get1337().faceTemporary(getElfinocks(), 5); - walk(get1337(), base.transform(21, 43, 0)); - break; - case 26: - camera(23, 49, -37, 0, 500, 3); - break; - case 28: - walk(getQuiteDoll(), base.transform(20, 49, 0)); - walk(getPurePker(), base.transform(16, 49, 0)); - break; - case 29: - walk(getOlivia(), base.transform(12, 48, 0)); - break; - case 36: - DoorActionHandler.handleAutowalkDoor(getWiseOldMan(), RegionManager.getObject(base.transform(16, 51, 0))); - break; - case 37: - getQuiteDoll().sendChat("Huh?"); - getQuiteDoll().faceTemporary(getWiseOldMan(), 2); - getWiseOldMan().sendChat("Please don't block my line of fire!"); - castShock(getPurePker()); - break; - case 38: - die(getPurePker()); - break; - case 39: - getOlivia().sendChat("Hey, what are you doing?"); - getWiseOldMan().faceTemporary(getOlivia(), 2); - GroundItemManager.create(ASHES, base.transform(16, 49, 0), player); - GroundItemManager.create(COINS, base.transform(16, 49, 0), player); - break; - case 42: - getWiseOldMan().sendChat("Olivia - Please go away!"); - getWiseOldMan().animate(SECOND_CAST_ANIMATION); - getWiseOldMan().graphics(TELE_OTHERS[0]); - break; - case 43: - getOlivia().animate(TELEPORT_ANIMATION); - getOlivia().graphics(TELE_OTHERS[1]); - getOlivia().sendChat("Eeeek!"); - GroundItemManager.destroy(GroundItemManager.get(ASHES.getId(), base.transform(16, 49, 0), player)); - break; - case 45: - getOlivia().setInvisible(true); - break; - case 48: - getWiseOldMan().sendChat("Ah, now I can get on with it..."); - getWiseOldMan().faceLocation(base.transform(16, 49, 0)); - break; - case 49: - getWiseOldMan().animate(PICK_UP_ANIMATION); - break; - case 50: - GroundItemManager.destroy(GroundItemManager.get(COINS.getId(), base.transform(16, 49, 0), player)); - break; - case 53: - castShock(base.transform(16, 46, 0)); - break; - case 55: - Scenery wall = RegionManager.getObject(base.transform(16, 46, 0)); - if(wall != null) - SceneryBuilder.replace(wall, wall.transform(9151, 0, 10)); - if(getWiseOldMan() != null) { - getWiseOldMan().getWalkingQueue().reset(); - getWiseOldMan().getWalkingQueue().addPath(base.getX() + 16, base.getY() + 46); - getWiseOldMan().getWalkingQueue().addPath(base.getX() + 17, base.getY() + 46); - } - break; - case 58: - camera(21, 38, -36, 43, 495, 99); - break; - case 59: - getWiseOldMan().sendChat("Could everyone please not move?"); - break; - case 62: - getFirstBanker().sendChat("Hey - you can't come in here!"); - walk(getFirstBanker(), base.transform(18, 46, 0)); - getFirstBanker().faceTemporary(getWiseOldMan(), 2); - getWiseOldMan().faceTemporary(getFirstBanker(), 2); - break; - case 64: - getWiseOldMan().animate(HIT_ANIMATION); - getFirstBanker().animate(BLOCK_ANIMATION); - getFirstBanker().getImpactHandler().manualHit(getWiseOldMan(), getFirstBanker().getSkills().getLifepoints(), HitsplatType.NORMAL); - getSecondBanker().sendChat("Oi!"); - getLastBanker().sendChat("Uh-oh!"); - getSecondBanker().getWalkingQueue().reset(); - getSecondBanker().getWalkingQueue().addPath(base.getX() + 17, base.getY() + 43); - getSecondBanker().getWalkingQueue().addPath(base.getX() + 16, base.getY() + 43); - getSecondBanker().getWalkingQueue().addPath(base.getX() + 16, base.getY() + 46); - break; - case 70: - walk(getLastBanker(), base.transform(18, 40, 0)); - getSecondBanker().faceTemporary(getWiseOldMan(), 2); - getSecondBanker().animate(new Animation(422)); - getWiseOldMan().animate(new Animation(403)); - getWiseOldMan().faceTemporary(getSecondBanker(), 2); - break; - case 73: - getWiseOldMan().animate(new Animation(401)); - getSecondBanker().animate(new Animation(435)); - getSecondBanker().getImpactHandler().manualHit(getWiseOldMan(), 11, HitsplatType.NORMAL); - break; - case 75: - getSecondBanker().animate(new Animation(422)); - NPC npc = getWiseOldMan(); - if (npc != null) { - getWiseOldMan().sendChat("I do wish you'd just stop it!"); - getWiseOldMan().animate(new Animation(403)); - } - break; - case 78: - getWiseOldMan().animate(new Animation(401)); - walk(getLastBanker(), base.transform(16, 40, 0)); - walk(getElfinocks(), base.transform(20, 44, 0)); - break; - case 80: - getWiseOldMan().faceLocation(base.transform(17, 43, 0)); - getLastBanker().faceTemporary(getWiseOldMan(), 1); - getSecondBanker().getImpactHandler().manualHit(getWiseOldMan(), getSecondBanker().getSkills().getLifepoints(), HitsplatType.NORMAL); - break; - case 85: - getWiseOldMan().faceLocation(base.transform(17, 43, 0)); - getElfinocks().sendChat("Hey - how'd he get in there?"); - break; - case 86: - camera(26, 40, -35, 13, 545, 32); - getLastBanker().sendChat("Help! Help!"); - get1337().sendChat("Hax!"); - get1337().faceLocation(base.transform(20, 43, 0)); - break; - case 90: - getWiseOldMan().sendChat("My sincerest regrets, dear lady..."); - break; - case 92: - getWiseOldMan().faceTemporary(getElfinocks(), 1); - castShock(getElfinocks()); - break; - case 94: - die(getElfinocks()); - break; - case 96: - GroundItemManager.create(ASHES, base.transform(20, 44, 0), player); - GroundItemManager.create(PARTY_HAT, base.transform(20, 44, 0), player); - break; - case 99: - getWiseOldMan().sendChat("And also you, sir..."); - GroundItemManager.destroy(GroundItemManager.get(ASHES.getId(), base.transform(20, 44, 0), player)); - break; - case 101: - castShock(get1337()); - walk(getQuiteDoll(), base.transform(21, 44, 0)); - break; - case 103: - getQuiteDoll().faceTemporary(getWiseOldMan(), 1); - break; - case 104: - getQuiteDoll().sendChat("How you do that?"); - die(get1337()); - break; - case 107: - GroundItemManager.create(ASHES, base.transform(21, 43, 0), player); - break; - case 109: - getWiseOldMan().sendChat("Oh dear - another one..."); - walk(getWiseOldMan(), base.transform(18, 46, 0)); - getWiseOldMan().faceTemporary(getQuiteDoll(), 1); - GroundItemManager.destroy(GroundItemManager.get(ASHES.getId(), base.transform(21, 43, 0), player)); - break; - case 110: - GroundItemManager.destroy(GroundItemManager.get(ASHES.getId(), base.transform(21, 43, 0), player)); - break; - case 111: - castShock(getQuiteDoll()); - break; - case 114: - die(getQuiteDoll()); - break; - case 115: - GroundItemManager.create(ASHES, base.transform(21, 44, 0), player); - getWiseOldMan().sendChat("Ooh - a party hat?"); - getWiseOldMan().faceLocation(base.transform(20, 44, 0)); - break; - case 116: - GroundItemManager.destroy(GroundItemManager.get(ASHES.getId(), base.transform(21, 44, 0), player)); - castTelekinetic(); - break; - case 118: - getWiseOldMan().transform(2567); - if (getOlivia().isActive()) { - getOlivia().getImpactHandler().manualHit(getMarketGuard(), getOlivia().getSkills().getLifepoints(), HitsplatType.NORMAL); - } - getMarketGuard().setInvisible(true); - break; - case 120: - getWiseOldMan().sendChat("Now, my dear..."); - walk(getWiseOldMan(), base.transform(18, 42, 0)); - break; - case 121: - getLastBanker().sendChat("Eeek!"); - break; - case 124: - getWiseOldMan().sendChat("Just give me the money, please."); - break; - case 126: - getMarketGuard().setInvisible(false); - getMarketGuard().getProperties().setTeleportLocation(base.transform(18, 46, 0)); - break; - case 127: - camera(25, 42, -20, 0, 400, 4); - getMarketGuard().sendChat("Old man, you're for da cage!"); - walk(getMarketGuard(), base.transform(18, 43, 0)); - break; - case 128: - getWiseOldMan().faceTemporary(getMarketGuard(), 1); - break; - case 129: - getWiseOldMan().sendChat("Oh, am I?"); - break; - case 131: - getWiseOldMan().sendChat("Ahh!"); - break; - case 133: - castThunderShock(); - break; - case 136: - getMarketGuard().graphics(THUNDER_GRAPHIC); - getMarketGuard().getImpactHandler().manualHit(getWiseOldMan(), 40, HitsplatType.NORMAL); - getMarketGuard().sendChat("Aaargh!"); - break; - case 138: - getWiseOldMan().sendChat("Yah!"); - getWiseOldMan().animate(WISE_JUMP); - break; - case 139: - getMarketGuard().animate(GUARD_JUMP); - break; - case 142: - getMarketGuard().clear(); - camera(24, 42, -20, 0, 400, 4); - break; - case 143: - getWiseOldMan().sendChat("And YOU can stop spying on me!"); - getWiseOldMan().faceLocation(base.transform(24, 42, 0)); - break; - case 145: - getWiseOldMan().animate(STOMP_ANIM); - Projectile projectile = Projectile.create(getWiseOldMan(), null, 434, 50, 130, 41, 140, 0, 0); - projectile.setEndLocation((Location) base.transform(24, 42, 0)); - projectile.send(); - break; - case 148: - player.getInterfaceManager().open(CRACKED); - break; - case 150: - DBRCutscenePlugin.this.stop(true); - return true; - } - return !player.isActive(); - } - - @Override - public void stop() { - super.stop(); - clearNpcs(); - } - - /** - * Gets the counter. - * - * @return the counter. - */ - public int getCounter() { - return counter; - } - } - - /** - * Represents an npc during the draynor bank recording cutscene. - * - * @author 'Vexia - * @version 1.0 - */ - public static final class DBRecordingNPC extends AbstractNPC { - - /** - * Represents the ids to use. - */ - private static final int[] IDS = new int[] { 2579 }; - - /** - * Constructs a new {@code DBRecordingNPC} {@code Object}. - */ - public DBRecordingNPC() { - super(0, null, false); - } - - /** - * Constructs a new {@code DBRecordingNPC} {@code Object}. - * - * @param id - * the id. - * @param location - * the locastion. - */ - private DBRecordingNPC(int id, Location location) { - super(id, location); - } - - @Override - public AbstractNPC construct(int id, Location location, Object... objects) { - return new DBRecordingNPC(id, location); - } - - @Override - public void init() { - super.init(); - getSkills().setLevel(Skills.ATTACK, 1); - getSkills().setStaticLevel(Skills.ATTACK, 1); - getSkills().setLevel(Skills.DEFENCE, 2); - getSkills().setStaticLevel(Skills.DEFENCE, 2); - } - - @Override - public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { - return true; - } - - @Override - public int[] getIds() { - return IDS; - } - } - - public static final class BluePhatItem extends ItemPlugin { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - register(PARTY_HAT.getId()); - return this; - } - - @Override - public boolean canPickUp(Player player, GroundItem item, int type) { - if (type == 1) { - player.sendMessage("Nice try ;)"); - } - return false; - } - } -} diff --git a/Server/src/main/content/region/misthalin/draynor/handlers/DBRCutscenePlugin.kt b/Server/src/main/content/region/misthalin/draynor/handlers/DBRCutscenePlugin.kt new file mode 100644 index 000000000..ace7b3646 --- /dev/null +++ b/Server/src/main/content/region/misthalin/draynor/handlers/DBRCutscenePlugin.kt @@ -0,0 +1,564 @@ +package content.region.misthalin.draynor.handlers + +import core.api.* +import core.game.activity.Cutscene +import core.game.component.Component +import core.game.global.action.DoorActionHandler +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.node.entity.Entity +import core.game.node.entity.combat.ImpactHandler +import core.game.node.entity.impl.Projectile +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.SpellBookManager +import core.game.node.entity.skill.Skills +import core.game.node.item.GroundItemManager +import core.game.node.item.Item +import core.game.node.scenery.SceneryBuilder +import core.game.world.map.Direction +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import core.net.packet.PacketRepository +import core.net.packet.context.CameraContext +import core.net.packet.context.CameraContext.CameraType +import core.net.packet.out.CameraViewPacket +import org.rs09.consts.Items +import org.rs09.consts.NPCs + +class DBRCutscene(player: Player) : Cutscene(player) { + companion object { + // Animations + private val STEAL_ANIMATION = Animation(832) + private val CAST_ANIMATION = Animation(1167) + private val TELEKINETIC_ANIMATION = Animation(723) + private val DEATH_ANIMATION = Animation(2553) + private val TELEPORT_ANIMATION = Animation(1816) + private val PICK_UP_ANIMATION = Animation(827) + private val HIT_ANIMATION = Animation(401) + private val BLOCK_ANIMATION = Animation(425) + private val THUNDER_ANIMATION = Animation(811) + private val WISE_JUMP = Animation(2555) + private val GUARD_JUMP = Animation(2556) + private val STOMP_ANIM = Animation(1820) + + // Graphics + private val TELEKINETIC_GRAPHIC = Graphics(142, 96) + private val SHOCK_GRAPHIC = Graphics(432, 0, 0) + private val TELE_OTHER_CAST = Graphics(343) + private val TELE_OTHER_TARGET = Graphics(342) + private val PURPLE_GRAPHIC = Graphics(301, 100) + private val THUNDER_GRAPHIC = Graphics(76) + + // Components + private val CRACKED = Component(385) + } + + override fun setup() { + setExit(player.location) + loadRegion(8524) + + // Add all NPCs with their initial positions + addNPC(NPCs.COOL_MOM227_2579, 8, 52, Direction.NORTH) + addNPC(NPCs.OLIVIA_2572, 5, 49, Direction.WEST) + addNPC(NPCs.MARKET_GUARD_2571, 13, 48, Direction.WEST) + addNPC(NPCs.PUREPKER895_2575, 24, 50, Direction.WEST) + addNPC(NPCs.BANKER_2568, 18, 45, Direction.EAST) + addNPC(NPCs.BANKER_2569, 18, 43, Direction.NORTH) + addNPC(NPCs.BANKER_2570, 18, 42, Direction.NORTH) + addNPC(NPCs.ELFINLOCKS_2578, 21, 44, Direction.NORTH) + addNPC(NPCs.SP34KR_1337_2577, 22, 42, Direction.WEST) + addNPC(NPCs.QUTIEDOLL_2576, 21, 42, Direction.EAST) + addNPC(NPCs.WISE_OLD_MAN_2566, 16, 51, Direction.SOUTH) + + // Set banker HP + getNPC(NPCs.BANKER_2568)?.skills?.setStaticLevel(Skills.HITPOINTS, 15) + getNPC(NPCs.BANKER_2568)?.skills?.setLevel(Skills.HITPOINTS, 15) + getNPC(NPCs.BANKER_2569)?.skills?.setStaticLevel(Skills.HITPOINTS, 15) + getNPC(NPCs.BANKER_2569)?.skills?.setLevel(Skills.HITPOINTS, 15) + getNPC(NPCs.BANKER_2570)?.skills?.setStaticLevel(Skills.HITPOINTS, 15) + getNPC(NPCs.BANKER_2570)?.skills?.setLevel(Skills.HITPOINTS, 15) + } + + private fun camera(x: Int, y: Int, xRot: Int, yRot: Int, height: Int, speed: Int) { + val loc = base.transform(x, y, 0) + PacketRepository.send( + CameraViewPacket::class.java, + CameraContext(player, CameraType.POSITION, loc.x, loc.y, height, 1, speed) + ) + PacketRepository.send( + CameraViewPacket::class.java, + CameraContext(player, CameraType.ROTATION, loc.x + xRot, loc.y + yRot, height, 1, speed) + ) + } + + private fun castShock(target: Entity) { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(CAST_ANIMATION) + wiseOldMan.graphics(Graphics(433)) + val projectile = Projectile.create(wiseOldMan, target, 434) + projectile.send() + } + + private fun castShock(loc: Location) { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(CAST_ANIMATION) + wiseOldMan.graphics(Graphics(433)) + val projectile = Projectile.create(wiseOldMan, null, 434, 30, 30, 41, 140, 0, 0) + projectile.endLocation = loc + projectile.send() + } + + private fun castTelekinetic() { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(TELEKINETIC_ANIMATION) + wiseOldMan.graphics(TELEKINETIC_GRAPHIC) + wiseOldMan.skills.setStaticLevel(Skills.MAGIC, 99) + wiseOldMan.skills.setLevel(Skills.MAGIC, 99) + SpellBookManager.SpellBook.MODERN.getSpell(19).cast(wiseOldMan, GroundItemManager.get(Item(Items.BLUE_PARTYHAT_2422).id, base.transform(20, 44, 0), player)) + } + + private fun castThunderShock() { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(THUNDER_ANIMATION) + wiseOldMan.graphics(PURPLE_GRAPHIC) + } + + private fun die(npc: NPC) { + npc.animator.reset() + npc.animate(DEATH_ANIMATION) + npc.graphics(SHOCK_GRAPHIC) + npc.impactHandler.manualHit(npc, npc.skills.lifepoints, ImpactHandler.HitsplatType.NORMAL) + } + + override fun runStage(stage: Int) { + when (stage) { + 0 -> { + player.lock() + player.locks.lockMovement(10000000) + sendDialogue(player, "You close your eyes and watch the recording...") + fadeToBlack() + timedUpdate(3) + } + 1 -> { + fadeFromBlack() + player.isInvisible = true + teleport(player, 17, 51) + camera(27, 45, -14, 2, 700, 100) + timedUpdate(3) + } + 2 -> { + val coolMom = getNPC(NPCs.COOL_MOM227_2579)!! + val marketGuard = getNPC(NPCs.MARKET_GUARD_2571)!! + coolMom.animate(STEAL_ANIMATION) + marketGuard.skills.setStaticLevel(Skills.HITPOINTS, 99) + marketGuard.skills.setLifepoints(99) + sendChat(marketGuard, "Hey! Get your hands off there!") + coolMom.locks.lockMovement(1000) + marketGuard.properties.combatPulse.attack(coolMom) + timedUpdate(7) + } + 3 -> { + move(getNPC(NPCs.PUREPKER895_2575)!!, 20, 45) + timedUpdate(2) + } + 4 -> { + camera(27, 43, -37, -3, 600, 5) + timedUpdate(2) + } + 5 -> { + sendChat(getNPC(NPCs.QUTIEDOLL_2576)!!, "Thx") + timedUpdate(2) + } + 6 -> { + move(getNPC(NPCs.QUTIEDOLL_2576)!!, 20, 42) + sendChat(getNPC(NPCs.SP34KR_1337_2577)!!, "Yw") + getNPC(NPCs.PUREPKER895_2575)!!.faceLocation(base.transform(19, 45, 0)) + timedUpdate(2) + } + 7 -> { + sendChat(getNPC(NPCs.ELFINLOCKS_2578)!!, "Buying 2k nats - no noob offers") + timedUpdate(4) + } + 8 -> { + sendChat(getNPC(NPCs.SP34KR_1337_2577)!!, "I h4ve n4ts") + timedUpdate(2) + } + 9 -> { + sendChat(getNPC(NPCs.ELFINLOCKS_2578)!!, "You sell?") + timedUpdate(3) + } + 10 -> { + sendChat(getNPC(NPCs.SP34KR_1337_2577)!!, "Tr4de") + getNPC(NPCs.SP34KR_1337_2577)!!.faceTemporary(getNPC(NPCs.ELFINLOCKS_2578)!!, 5) + move(getNPC(NPCs.SP34KR_1337_2577)!!, 21, 43) + timedUpdate(1) + } + 11 -> { + camera(23, 49, -37, 0, 500, 3) + timedUpdate(2) + } + 12 -> { + move(getNPC(NPCs.QUTIEDOLL_2576)!!, 20, 49) + move(getNPC(NPCs.PUREPKER895_2575)!!, 16, 49) + timedUpdate(1) + } + 13 -> { + move(getNPC(NPCs.OLIVIA_2572)!!, 12, 48) + timedUpdate(7) + } + 14 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + DoorActionHandler.handleAutowalkDoor(wiseOldMan, getObject(16, 51)) + timedUpdate(1) + } + 15 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + val qutieDoll = getNPC(NPCs.QUTIEDOLL_2576)!! + val purePker = getNPC(NPCs.PUREPKER895_2575)!! + sendChat(qutieDoll, "Huh?") + qutieDoll.faceTemporary(wiseOldMan, 2) + sendChat(wiseOldMan, "Please don't block my line of fire!") + castShock(purePker) + timedUpdate(1) + } + 16 -> { + die(getNPC(NPCs.PUREPKER895_2575)!!) + timedUpdate(1) + } + 17 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + val olivia = getNPC(NPCs.OLIVIA_2572)!! + sendChat(olivia, "Hey, what are you doing?") + wiseOldMan.faceTemporary(olivia, 2) + GroundItemManager.create(Item(Items.ASHES_592), base.transform(16, 49, 0), player) + GroundItemManager.create(Item(Items.COINS_995, 60), base.transform(16, 49, 0), player) + timedUpdate(3) + } + 18 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "Olivia - please go away!") + wiseOldMan.animate(CAST_ANIMATION) + wiseOldMan.graphics(TELE_OTHER_CAST) + timedUpdate(1) + } + 19 -> { + val olivia = getNPC(NPCs.OLIVIA_2572)!! + olivia.animate(TELEPORT_ANIMATION) + olivia.graphics(TELE_OTHER_TARGET) + sendChat(olivia, "Eeeek!") + GroundItemManager.destroy(GroundItemManager.get(Item(Items.ASHES_592).id, base.transform(16, 49, 0), player)) + timedUpdate(2) + } + 20 -> { + getNPC(NPCs.OLIVIA_2572)!!.isInvisible = true + timedUpdate(3) + } + 21 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "Ah, now I can get on with it...") + wiseOldMan.faceLocation(base.transform(16, 49, 0)) + timedUpdate(1) + } + 22 -> { + getNPC(NPCs.WISE_OLD_MAN_2566)!!.animate(PICK_UP_ANIMATION) + timedUpdate(1) + } + 23 -> { + GroundItemManager.destroy(GroundItemManager.get(Item(Items.COINS_995, 60).id, base.transform(16, 49, 0), player)) + timedUpdate(3) + } + 24 -> { + castShock(base.transform(16, 46, 0)) + timedUpdate(2) + } + 25 -> { + val wall = getObject(16, 46) + if (wall != null) { + SceneryBuilder.replace(wall, wall.transform(9151, 0, 10)) + } + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566) + if (wiseOldMan != null) { + wiseOldMan.walkingQueue.reset() + wiseOldMan.walkingQueue.addPath(base.x + 16, base.y + 46) + wiseOldMan.walkingQueue.addPath(base.x + 17, base.y + 46) + } + timedUpdate(3) + } + 26 -> { + camera(21, 38, -36, 43, 495, 99) + timedUpdate(1) + } + 27 -> { + sendChat(getNPC(NPCs.WISE_OLD_MAN_2566)!!, "Could everyone please not move?") + timedUpdate(3) + } + 28 -> { + val firstBanker = getNPC(NPCs.BANKER_2568)!! + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(firstBanker, "Hey - you can't come in here!") + move(firstBanker, 18, 46) + firstBanker.faceTemporary(wiseOldMan, 2) + wiseOldMan.faceTemporary(firstBanker, 2) + timedUpdate(2) + } + 29 -> { + val firstBanker = getNPC(NPCs.BANKER_2568)!! + val secondBanker = getNPC(NPCs.BANKER_2569)!! + val lastBanker = getNPC(NPCs.BANKER_2570)!! + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(HIT_ANIMATION) + firstBanker.animate(BLOCK_ANIMATION) + firstBanker.impactHandler.manualHit(wiseOldMan, firstBanker.skills.lifepoints, ImpactHandler.HitsplatType.NORMAL) + sendChat(secondBanker, "Oi!") + sendChat(lastBanker, "Uh-oh!") + secondBanker.walkingQueue.reset() + secondBanker.walkingQueue.addPath(base.x + 17, base.y + 43) + secondBanker.walkingQueue.addPath(base.x + 16, base.y + 43) + secondBanker.walkingQueue.addPath(base.x + 16, base.y + 46) + timedUpdate(6) + } + 30 -> { + move(getNPC(NPCs.BANKER_2570)!!, 18, 40) + val secondBanker = getNPC(NPCs.BANKER_2569)!! + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + secondBanker.faceTemporary(wiseOldMan, 2) + secondBanker.animate(Animation(422)) + wiseOldMan.animate(Animation(403)) + wiseOldMan.faceTemporary(secondBanker, 2) + timedUpdate(3) + } + 31 -> { + val secondBanker = getNPC(NPCs.BANKER_2569)!! + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(Animation(401)) + secondBanker.animate(Animation(435)) + secondBanker.impactHandler.manualHit(wiseOldMan, 11, ImpactHandler.HitsplatType.NORMAL) + timedUpdate(2) + } + 32 -> { + val secondBanker = getNPC(NPCs.BANKER_2569)!! + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + secondBanker.animate(Animation(422)) + sendChat(wiseOldMan, "I do wish you'd just stop it!") + wiseOldMan.animate(Animation(403)) + timedUpdate(3) + } + 33 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(Animation(401)) + move(getNPC(NPCs.BANKER_2570)!!, 16, 40) + move(getNPC(NPCs.ELFINLOCKS_2578)!!, 20, 44) + timedUpdate(2) + } + 34 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + val lastBanker = getNPC(NPCs.BANKER_2570)!! + val secondBanker = getNPC(NPCs.BANKER_2569)!! + wiseOldMan.faceLocation(base.transform(17, 43, 0)) + lastBanker.faceLocation(wiseOldMan.location) + secondBanker.impactHandler.manualHit(wiseOldMan, secondBanker.skills.lifepoints, ImpactHandler.HitsplatType.NORMAL) + timedUpdate(5) + } + 35 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.faceLocation(base.transform(17, 43, 0)) + sendChat(getNPC(NPCs.ELFINLOCKS_2578)!!, "Hey - how'd he get in there?") + timedUpdate(1) + } + 36 -> { + camera(26, 40, -35, 13, 545, 32) + sendChat(getNPC(NPCs.BANKER_2570)!!, "Help! Help!") + sendChat(getNPC(NPCs.SP34KR_1337_2577)!!, "Hax!") + getNPC(NPCs.SP34KR_1337_2577)!!.faceLocation(base.transform(20, 43, 0)) + timedUpdate(4) + } + 37 -> { + sendChat(getNPC(NPCs.WISE_OLD_MAN_2566)!!, "My sincerest regrets, dear lady...") + timedUpdate(2) + } + 38 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.faceTemporary(getNPC(NPCs.ELFINLOCKS_2578)!!, 1) + castShock(getNPC(NPCs.ELFINLOCKS_2578)!!) + timedUpdate(2) + } + 39 -> { + die(getNPC(NPCs.ELFINLOCKS_2578)!!) + timedUpdate(2) + } + 40 -> { + GroundItemManager.create(Item(Items.ASHES_592), base.transform(20, 44, 0), player) + GroundItemManager.create(Item(Items.BLUE_PARTYHAT_2422), base.transform(20, 44, 0), player) + timedUpdate(3) + } + 41 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "And also you, sir...") + GroundItemManager.destroy(GroundItemManager.get(Item(Items.ASHES_592).id, base.transform(20, 44, 0), player)) + timedUpdate(2) + } + 42 -> { + castShock(getNPC(NPCs.SP34KR_1337_2577)!!) + move(getNPC(NPCs.QUTIEDOLL_2576)!!, 21, 44) + timedUpdate(2) + } + 43 -> { + getNPC(NPCs.QUTIEDOLL_2576)!!.faceTemporary(getNPC(NPCs.WISE_OLD_MAN_2566)!!, 1) + timedUpdate(1) + } + 44 -> { + sendChat(getNPC(NPCs.QUTIEDOLL_2576)!!, "How you do that?") + die(getNPC(NPCs.SP34KR_1337_2577)!!) + timedUpdate(3) + } + 45 -> { + GroundItemManager.create(Item(Items.ASHES_592), base.transform(21, 43, 0), player) + timedUpdate(2) + } + 46 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "Oh dear - another one...") + move(wiseOldMan, 18, 46) + wiseOldMan.faceLocation(getNPC(NPCs.QUTIEDOLL_2576)!!.location) + GroundItemManager.destroy(GroundItemManager.get(Item(Items.ASHES_592).id, base.transform(21, 43, 0), player)) + timedUpdate(1) + } + 47 -> { + GroundItemManager.destroy(GroundItemManager.get(Item(Items.ASHES_592).id, base.transform(21, 43, 0), player)) + timedUpdate(1) + } + 48 -> { + castShock(getNPC(NPCs.QUTIEDOLL_2576)!!) + timedUpdate(3) + } + 49 -> { + die(getNPC(NPCs.QUTIEDOLL_2576)!!) + timedUpdate(1) + } + 50 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + GroundItemManager.create(Item(Items.ASHES_592), base.transform(21, 44, 0), player) + sendChat(wiseOldMan, "Ooh - a party hat?") + wiseOldMan.faceLocation(base.transform(20, 44, 0)) + timedUpdate(1) + } + 51 -> { + GroundItemManager.destroy(GroundItemManager.get(Item(Items.ASHES_592).id, base.transform(21, 44, 0), player)) + castTelekinetic() + timedUpdate(2) + } + 52 -> { + GroundItemManager.destroy(GroundItemManager.get(Item(Items.BLUE_PARTYHAT_2422).id, base.transform(20, 44, 0), player)) + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + val olivia = getNPC(NPCs.OLIVIA_2572)!! + val marketGuard = getNPC(NPCs.MARKET_GUARD_2571)!! + wiseOldMan.transform(NPCs.WISE_OLD_MAN_2567) + if (olivia.isActive) { + olivia.impactHandler.manualHit(marketGuard, olivia.skills.lifepoints, ImpactHandler.HitsplatType.NORMAL) + } + marketGuard.isInvisible = true + timedUpdate(2) + } + 53 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "Now, my dear...") + move(wiseOldMan, 18, 42) + timedUpdate(1) + } + 54 -> { + sendChat(getNPC(NPCs.BANKER_2570)!!, "Eeek!") + timedUpdate(3) + } + 55 -> { + sendChat(getNPC(NPCs.WISE_OLD_MAN_2566)!!, "Just give me the money, please.") + timedUpdate(2) + } + 56 -> { + val marketGuard = getNPC(NPCs.MARKET_GUARD_2571)!! + marketGuard.isInvisible = false + marketGuard.properties.teleportLocation = base.transform(18, 46, 0) + timedUpdate(1) + } + 57 -> { + camera(25, 42, -20, 0, 400, 4) + val marketGuard = getNPC(NPCs.MARKET_GUARD_2571)!! + sendChat(marketGuard, "Old man, you're for da cage!") + move(marketGuard, 18, 43) + timedUpdate(1) + } + 58 -> { + getNPC(NPCs.WISE_OLD_MAN_2566)!!.faceTemporary(getNPC(NPCs.MARKET_GUARD_2571), 1) + timedUpdate(1) + } + 59 -> { + sendChat(getNPC(NPCs.WISE_OLD_MAN_2566)!!, "Oh, am I?") + timedUpdate(2) + } + 60 -> { + sendChat(getNPC(NPCs.WISE_OLD_MAN_2566)!!, "Ahh!") + timedUpdate(2) + } + 61 -> { + castThunderShock() + timedUpdate(3) + } + 62 -> { + val marketGuard = getNPC(NPCs.MARKET_GUARD_2571)!! + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + marketGuard.graphics(THUNDER_GRAPHIC) + marketGuard.impactHandler.manualHit(wiseOldMan, 40, ImpactHandler.HitsplatType.NORMAL) + sendChat(marketGuard, "Aaargh!") + timedUpdate(2) + } + 63 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "Yah!") + wiseOldMan.animate(WISE_JUMP) + timedUpdate(1) + } + 64 -> { + getNPC(NPCs.MARKET_GUARD_2571)!!.animate(GUARD_JUMP) + timedUpdate(3) + } + 65 -> { + getNPC(NPCs.MARKET_GUARD_2571)!!.clear() + camera(24, 42, -20, 0, 400, 4) + timedUpdate(1) + } + 66 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + sendChat(wiseOldMan, "And YOU can stop spying on me!") + wiseOldMan.faceLocation(base.transform(24, 42, 0)) + timedUpdate(2) + } + 67 -> { + val wiseOldMan = getNPC(NPCs.WISE_OLD_MAN_2566)!! + wiseOldMan.animate(STOMP_ANIM) + val projectile = Projectile.create(wiseOldMan, null, 434, 50, 130, 41, 140, 0, 0) + projectile.endLocation = base.transform(24, 42, 0) + projectile.send() + timedUpdate(3) + } + 68 -> { + player.interfaceManager.openOverlay(CRACKED) + timedUpdate(2) + } + 69 -> end { + player.isInvisible = false + setAttribute(player, "/save:draynor-recording", true) + sendDialogue(player, "End of recording.") + } + } + } +} + +class DBRCutsceneListeners : InteractionListener { + override fun defineListeners() { + on(Items.BLUE_PARTYHAT_2422, IntType.GROUNDITEM, "take") { player, _ -> + sendMessage(player, "Nice try ;)") + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorChairNPC.kt b/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorChairNPC.kt index 423e57dec..8a3227c11 100644 --- a/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorChairNPC.kt +++ b/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorChairNPC.kt @@ -9,6 +9,7 @@ import core.game.node.entity.player.Player import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.path.Pathfinder +import core.game.world.repository.Repository import core.plugin.Initializable /** @@ -78,7 +79,7 @@ class DraynorManorChairNPC(id: Int = DRAYNOR_MANOR_CHAIR_NPC_ID, location: Locat * @return The Player object representing the closest player, or null if there are no players nearby. */ fun findClosestPlayer(): Player? { - val players = RegionManager.getLocalPlayers(this, FOLLOWING_DISTANCE) + val players = RegionManager.getLocalPlayers(location, FOLLOWING_DISTANCE) if (players.isEmpty()) { return null } diff --git a/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorHouseZone.kt b/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorHouseZone.kt index 529b497a6..89e30c54a 100644 --- a/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorHouseZone.kt +++ b/Server/src/main/content/region/misthalin/draynor/handlers/DraynorManorHouseZone.kt @@ -2,7 +2,7 @@ package content.region.misthalin.draynor.handlers import core.game.node.entity.Entity import core.game.world.map.Location -import core.game.world.map.RegionManager.getLocalNpcs +import core.game.world.map.RegionManager.getLocalNPCs import core.game.world.map.path.Pathfinder import core.game.world.map.zone.MapZone import core.game.world.map.zone.ZoneBorders @@ -24,7 +24,7 @@ class DraynorManorHouseZone : MapZone("Draynor Manor House", true), Plugin } override fun move(e: Entity, loc: Location?, destination: Location): Boolean { - for (n in getLocalNpcs(e, 5)) { + for (n in getLocalNPCs(e.location, 5)) { if (n.isInvisible() || n === e) { continue } diff --git a/Server/src/main/content/region/misthalin/draynor/handlers/DraynorTreeNPC.java b/Server/src/main/content/region/misthalin/draynor/handlers/DraynorTreeNPC.java index 2bc5f6852..84c7d95f6 100644 --- a/Server/src/main/content/region/misthalin/draynor/handlers/DraynorTreeNPC.java +++ b/Server/src/main/content/region/misthalin/draynor/handlers/DraynorTreeNPC.java @@ -9,6 +9,7 @@ import core.game.node.entity.player.Player; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.tools.RandomFunction; @@ -63,8 +64,8 @@ public final class DraynorTreeNPC extends AbstractNPC { @Override public void tick() { - final List players = RegionManager.getLocalPlayers(this, 1); - if (players.size() != 0) { + final List players = RegionManager.getLocalPlayers(location, 1); + if (!players.isEmpty()) { if (attackDelay < GameWorld.getTicks()) { for (Player p : players) { faceTemporary(p, 2); diff --git a/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt b/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt index 965dcb157..1240d0d4f 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/diary/LumbridgeAchivementDiary.kt @@ -120,7 +120,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { ) override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12596 -> if (event.itemId == Items.CLAY_434) { finishTask( player, @@ -248,7 +248,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { } override fun onNpcKilled(player: Player, event: NPCKillEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12593, 12849 -> if (event.npc.id == NPCs.GIANT_RAT_86) { finishTask( player, @@ -280,7 +280,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { } override fun onFireLit(player: Player, event: LitFireEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12593, 12849 -> if (event.logId == Items.LOGS_1511) { finishTask( player, @@ -302,7 +302,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { } override fun onInteracted(player: Player, event: InteractionEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12337 -> if (event.target.id == Scenery.RAILING_37668 && event.option == "taunt-through" ) { @@ -364,7 +364,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { override fun onPickedUp(player: Player, event: PickUpEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12850, 12851 -> { if (event.itemId == Items.COWHIDE_1739) { if (inBorders(player, COW_PEN_AREA_1) @@ -382,7 +382,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { } override fun onInterfaceOpened(player: Player, event: InterfaceOpenEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12338 -> if (event.component.id == Components.BANK_V2_MAIN_762) { finishTask( player, @@ -412,7 +412,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { } override fun onJobAssigned(player: Player, event: JobAssignmentEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12849 -> if (event.employerNpc.id == NPCs.FISHING_TUTOR_4901) { finishTask( player, @@ -424,7 +424,7 @@ class LumbridgeAchivementDiary : DiaryEventHookBase(DiaryType.LUMBRIDGE) { } override fun onUsedWith(player: Player, event: UseWithEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12595 -> if (event.used == Items.EMPTY_POT_1931 && event.with == Scenery.FLOUR_BIN_36878) { finishTask( player, diff --git a/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt b/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt index f49899210..fc103a4ea 100644 --- a/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt +++ b/Server/src/main/content/region/misthalin/varrock/diary/VarrockAchivementDiary.kt @@ -120,7 +120,7 @@ class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) { ) override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12341 -> if (event.itemId == Items.RAW_TROUT_335) { finishTask( player, @@ -172,7 +172,7 @@ class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) { } override fun onInteracted(player: Player, event: InteractionEvent) { - when (player.viewport.region.id) { + when (player.location.regionId) { 12342 -> if (event.target.id == 26934) { finishTask( player, @@ -217,8 +217,8 @@ class VarrockAchivementDiary : DiaryEventHookBase(DiaryType.VARROCK) { override fun onButtonClicked(player: Player, event: ButtonClickEvent) { /* This gets fired even on the login screen, and we don't have a region there, so... */ - player.viewport.region?.let { - when (it.id) { + player.location.regionId.let { + when (it) { 12342 -> { if (event.iface == CanoeListener.CANOE_SHAPING_INTERFACE && event.buttonId == CanoeListener.CANOE_SHAPING_BUTTONS[CanoeListener.Companion.Canoes.WAKA.ordinal]) { diff --git a/Server/src/main/content/region/misthalin/varrock/handlers/StrayDogNPC.java b/Server/src/main/content/region/misthalin/varrock/handlers/StrayDogNPC.java index e2ce0867e..1d8530d2a 100644 --- a/Server/src/main/content/region/misthalin/varrock/handlers/StrayDogNPC.java +++ b/Server/src/main/content/region/misthalin/varrock/handlers/StrayDogNPC.java @@ -12,6 +12,7 @@ import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.map.path.Pathfinder; import core.game.world.map.zone.impl.BankZone; +import core.game.world.repository.Repository; import core.plugin.Initializable; import core.tools.RandomFunction; @@ -69,9 +70,9 @@ public class StrayDogNPC extends AbstractNPC { if (delay < System.currentTimeMillis() && RandomFunction.random(1, 16) == 2) { getPulseManager().clear(); target = null; - players = RegionManager.getLocalPlayers(this, 7); + players = RegionManager.getLocalPlayers(location, 7); if (players.size() != 0) { - target = players.get(RandomFunction.random(players.size())); + Player target = players.get(RandomFunction.random(players.size())); getPulseManager().run(getFollowPulse(target), PulseType.STANDARD); delay = System.currentTimeMillis() + 150000; } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java index f16658df0..3d901c408 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/dragonslayer/DragonSlayerPlugin.java @@ -36,10 +36,10 @@ import content.data.Quests; */ public final class DragonSlayerPlugin extends OptionHandler { - /** - * Represents the hammer animation. - */ - private static final Animation HAMMER_ANIM = new Animation(3676); + /** + * Represents the hammer animation. + */ + private static final Animation HAMMER_ANIM = new Animation(3676); @Override public Plugin newInstance(Object arg) throws Throwable { @@ -150,7 +150,7 @@ public final class DragonSlayerPlugin extends OptionHandler { ForceMovement movement = new ForceMovement(player, player.getLocation(), player.getLocation().transform(player.getLocation().getX() == 2845 ? 2 : -2, 0, 0), new Animation(839)); movement.run(player, 10); if (player.getLocation().getX() <= 2845) { - List npcs = RegionManager.getLocalNpcs(player); + List npcs = RegionManager.getLocalNPCs(player.getLocation()); for (NPC n : npcs) { if (n.getId() == 742) { n.getProperties().getCombatPulse().attack(player); @@ -165,18 +165,18 @@ public final class DragonSlayerPlugin extends OptionHandler { player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 1, 2); break; case 2606: - if (player.getLocation().getY() < 9600 && !player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized") && player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 100) { - player.getPacketDispatch().sendMessage("The door is securely locked."); - } else { - if (!player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized")) { - player.getPacketDispatch().sendMessage("You found a secret door."); - player.getPacketDispatch().sendMessage("You remember where the secret door is for future reference."); - } - player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 1, 1); - player.getSavedData().getQuestData().setDragonSlayerAttribute("memorized", true); - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - } - break; + if (player.getLocation().getY() < 9600 && !player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized") && player.getQuestRepository().getQuest(Quests.DRAGON_SLAYER).getStage(player) != 100) { + player.getPacketDispatch().sendMessage("The door is securely locked."); + } else { + if (!player.getSavedData().getQuestData().getDragonSlayerAttribute("memorized")) { + player.getPacketDispatch().sendMessage("You found a secret door."); + player.getPacketDispatch().sendMessage("You remember where the secret door is for future reference."); + } + player.getAchievementDiaryManager().finishTask(player, DiaryType.KARAMJA, 1, 1); + player.getSavedData().getQuestData().setDragonSlayerAttribute("memorized", true); + DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); + } + break; case 25154: ClimbActionHandler.climb(player, new Animation(828), new Location(2833, 9658, 0)); break; @@ -206,7 +206,7 @@ public final class DragonSlayerPlugin extends OptionHandler { player.getDialogueInterpreter().sendDialogue("You nail a plank over the hole, but you still need more planks to", "close the hole completely."); } else { player.getSavedData().getQuestData().setDragonSlayerAttribute("repaired", true); - setVarp(player, 177, 1967876); + setVarp(player, 177, 1967876); player.getDialogueInterpreter().sendDialogue("You nail a final plank over the hole. You have successfully patched", "the hole in the ship."); } } diff --git a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt index 1ca3002f0..8abc190ea 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt +++ b/Server/src/main/content/region/misthalin/varrock/quest/familycrest/ChronozonCaveZone.kt @@ -40,7 +40,7 @@ class ChronozonCaveZone: MapZone("FC ChronozoneZone", true), Plugin { ){ // Chronozon is allowed to spawn (quest stage right and the player doesn't have the crest part) // Now check there is not one already - if(!RegionManager.getLocalNpcs(spawnLoc, 5).contains(chronozon)){ + if(!RegionManager.getLocalNPCs(spawnLoc, 5).contains(chronozon)){ chronozon.setPlayer(e) chronozon.isRespawn = false chronozon.location = spawnLoc diff --git a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java index 80a581a22..7c26a2368 100644 --- a/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java +++ b/Server/src/main/content/region/misthalin/varrock/quest/shieldofarrav/ShieldArravPlugin.java @@ -106,7 +106,7 @@ public final class ShieldArravPlugin extends OptionHandler { } break; case 767: - List npcs = RegionManager.getLocalNpcs(player); + List npcs = RegionManager.getLocalNPCs(player.getLocation()); NPC master = null; for (NPC n : npcs) { if (n.getId() == 643) { diff --git a/Server/src/main/content/region/misthalin/wiztower/handlers/rcguild/RuneCraftingGuildObjects.java b/Server/src/main/content/region/misthalin/wiztower/handlers/rcguild/RuneCraftingGuildObjects.java deleted file mode 100644 index 600525b1a..000000000 --- a/Server/src/main/content/region/misthalin/wiztower/handlers/rcguild/RuneCraftingGuildObjects.java +++ /dev/null @@ -1,44 +0,0 @@ -package content.region.misthalin.wiztower.handlers.rcguild; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.scenery.Scenery; -import core.game.world.map.Location; -import core.plugin.Initializable; -import core.plugin.Plugin; - -/** - * Created for 2009Scape - * User: Ethan Kyle Millard - * Date: March 25, 2020 - * Time: 7:19 PM - */ -@Initializable -public class RuneCraftingGuildObjects extends OptionHandler { - - - @Override - public boolean handle(Player player, Node node, String option) { - Scenery object = ((Scenery) node); - - switch(object.getId()) { - case 38279: - if (player.getViewport().getRegion().getRegionId() == 12337) { - player.teleport(Location.create(1696, 5460, 2)); - } else { - player.teleport(Location.create(3106, 3160, 1)); - } - break; - } - - return true; - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(38279).getHandlers().put("option:enter", this); - return this; - } -} diff --git a/Server/src/main/content/region/morytania/handlers/MortMyreGhastNPC.kt b/Server/src/main/content/region/morytania/handlers/MortMyreGhastNPC.kt index cb80df540..bd94c1de3 100644 --- a/Server/src/main/content/region/morytania/handlers/MortMyreGhastNPC.kt +++ b/Server/src/main/content/region/morytania/handlers/MortMyreGhastNPC.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.launch import org.rs09.consts.Items import org.rs09.consts.NPCs import content.region.morytania.quest.naturespirit.NSUtils +import core.game.world.repository.Repository import org.rs09.consts.Sounds @Initializable @@ -36,7 +37,9 @@ class MortMyreGhastNPC : AbstractNPC { override fun handleTickActions() { super.handleTickActions() if(id == ids[0] && RandomFunction.roll(35)){ - val players = RegionManager.getLocalPlayers(this, 5).filter { !it.inCombat() } + val players = RegionManager.getLocalPlayers(location, 5).filter { + return@filter it.inCombat() + } if(players.isNotEmpty()){ val player = players.random() submitIndividualPulse(this, object : MovementPulse(this, player){ diff --git a/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java b/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java index 0b71e76e6..8330ce597 100644 --- a/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java +++ b/Server/src/main/content/region/wilderness/handlers/CorporealBeastNPC.java @@ -15,6 +15,7 @@ import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import core.plugin.Initializable; @@ -126,7 +127,7 @@ public final class CorporealBeastNPC extends NPCBehavior { public int swing(Entity entity, Entity victim, BattleState state) { // If we're below the right HP threshold, roll a chance to spawn the dark core CorporealBeastNPC corp = (CorporealBeastNPC) ((NPC) entity).behavior; - double thresh = entity.getSkills().getMaximumLifepoints() * (0.3 + (entity.getViewport().getCurrentPlane().getPlayers().size() * 0.05)); + double thresh = entity.getSkills().getMaximumLifepoints() * (0.3 + (RegionManager.getLocalPlayers(entity.getLocation()).size() * 0.05)); if (corp.forceCoreRoll || entity.getSkills().getLifepoints() < thresh) { rollDarkCore(entity, corp, victim); corp.forceCoreRoll = false; @@ -189,7 +190,7 @@ public final class CorporealBeastNPC extends NPCBehavior { int ticks = 1 + (int) Math.ceil(entity.getLocation().getDistance(location) * 0.5); GameWorld.getPulser().submit(new Pulse(ticks) { boolean secondStage = false; - List players = RegionManager.getLocalPlayers(entity); + List players = RegionManager.getLocalPlayers(entity.getLocation()); Location[] locations = null; @Override @@ -245,7 +246,7 @@ public final class CorporealBeastNPC extends NPCBehavior { public boolean doStompAttack(Entity entity) { Location l = entity.getLocation(); List stompTargets = null; - for (Player player : RegionManager.getLocalPlayers(entity, 5)) { + for (Player player : RegionManager.getLocalPlayers(entity.getLocation(), 5)) { Location p = player.getLocation(); if (p.getX() >= l.getX() && p.getY() >= l.getY() && p.getX() < l.getX() + entity.size() && p.getY() < l.getY() + entity.size()) { if (stompTargets == null) { diff --git a/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java b/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java index 0695955ba..c0768ea8d 100644 --- a/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java +++ b/Server/src/main/content/region/wilderness/handlers/DarkEnergyCoreNPC.java @@ -9,8 +9,10 @@ import core.game.node.entity.player.Player; import core.game.system.task.Pulse; import core.game.world.GameWorld; import core.game.world.map.Location; +import core.game.world.map.RegionManager; import core.game.world.map.path.Path; import core.game.world.map.path.Pathfinder; +import core.game.world.repository.Repository; import core.plugin.Initializable; import core.tools.RandomFunction; @@ -82,7 +84,7 @@ public final class DarkEnergyCoreNPC extends AbstractNPC { } if (ticks % 2 == 0) { boolean jump = true; - for (Player p : getViewport().getCurrentPlane().getPlayers()) { + for (Player p : RegionManager.getLocalPlayers(location)) { if (p.getLocation().withinDistance(getLocation(), 1)) { jump = false; int hit = 5 + RandomFunction.random(6); @@ -93,7 +95,7 @@ public final class DarkEnergyCoreNPC extends AbstractNPC { } if (jump) { Entity victim = master.getProperties().getCombatPulse().getVictim(); - if (++fails >= 3 && victim != null && victim.getViewport().getCurrentPlane() == getViewport().getCurrentPlane()) { + if (++fails >= 3 && victim != null && getLocation().withinDistance(victim.getLocation(), 8)) { Path path = Pathfinder.find(getLocation(), victim.getLocation(), 1); if (path.isSuccessful() || !path.isMoveNear()) { jump(victim.getLocation()); diff --git a/Server/src/main/content/region/wilderness/handlers/WildernessObeliskPlugin.java b/Server/src/main/content/region/wilderness/handlers/WildernessObeliskPlugin.java index 267a5b8cb..6e70c538d 100644 --- a/Server/src/main/content/region/wilderness/handlers/WildernessObeliskPlugin.java +++ b/Server/src/main/content/region/wilderness/handlers/WildernessObeliskPlugin.java @@ -47,12 +47,12 @@ public final class WildernessObeliskPlugin extends OptionHandler { if (stationObelisk == null) { return false; } - if (player.getSkullManager().isDeepWilderness()) { - if (player.getProperties().getCombatPulse().isInCombat()) { - player.sendMessage("You can't use this while in combat."); - return false; - } - } + if (player.getSkullManager().isDeepWilderness()) { + if (player.getProperties().getCombatPulse().isInCombat()) { + player.sendMessage("You can't use this while in combat."); + return false; + } + } for (int i = 0; i < 4; i++) { int x = stationObelisk.getLocation().getX(); int y = stationObelisk.getLocation().getY(); @@ -106,7 +106,7 @@ public final class WildernessObeliskPlugin extends OptionHandler { int index = RandomFunction.random(0, newObelisks.length - 1); //cutting out the last one that is now duplicated Obelisk newObelisk = newObelisks[index]; // Teleport players standing within a 3-by-3 bounding box - for (Player player : RegionManager.getLocalPlayersBoundingBox(center, 1, 1)) { + for (Player player : RegionManager.getLocalPlayersBoundingBox(center, 0)) { if (player.timers.getTimer("teleblock") == null) { player.getPacketDispatch().sendMessage("Ancient magic teleports you somewhere in the wilderness."); int xOffset = player.getLocation().getX() - center.getX(); diff --git a/Server/src/main/content/region/wilderness/handlers/revenants/RevenantNPC.java b/Server/src/main/content/region/wilderness/handlers/revenants/RevenantNPC.java index 6e0d0e6fb..ef7fdf722 100644 --- a/Server/src/main/content/region/wilderness/handlers/revenants/RevenantNPC.java +++ b/Server/src/main/content/region/wilderness/handlers/revenants/RevenantNPC.java @@ -13,6 +13,7 @@ import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.map.zone.ZoneBorders; import core.game.world.map.zone.impl.WildernessZone; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.tools.RandomFunction; @@ -117,7 +118,7 @@ public class RevenantNPC extends AbstractNPC { public void tick() { skills.pulse(); getWalkingQueue().update(); - if (this.getViewport().getRegion().isActive()) { + if (this.getLocation().getRegion().isActive()) { getUpdateMasks().prepare(this); } if (!DeathTask.isDead(this)) { @@ -128,7 +129,7 @@ public class RevenantNPC extends AbstractNPC { lock(3); getProperties().getCombatPulse().delayNextAttack(3); getSkills().heal(maxhp / 6); - for (Player p : RegionManager.getLocalPlayers(this)) { + for (Player p : RegionManager.getLocalPlayers(location)) { playAudio(p, Sounds.EAT_2393); } setAttribute("eat-delay", GameWorld.getTicks() + 6); diff --git a/Server/src/main/core/ServerConstants.kt b/Server/src/main/core/ServerConstants.kt index 8c5f493a4..178604188 100644 --- a/Server/src/main/core/ServerConstants.kt +++ b/Server/src/main/core/ServerConstants.kt @@ -108,7 +108,7 @@ class ServerConstants { //the location where new players are placed on login. @JvmField - var START_LOCATION: Location? = null + var START_LOCATION: Location = Location(2524, 5002, 0) //Location for all home teleports/respawn location @JvmField diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 7423518a7..6e905d67a 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -652,7 +652,7 @@ fun addScenery (scenery: Scenery) { * Remove a scenery from the world * @param scenery the Scenery object to remove. */ -fun removeScenery (scenery: Scenery) { +fun removeScenery(scenery: Scenery) { SceneryBuilder.remove(scenery) } @@ -1017,8 +1017,7 @@ fun playAudio(player: Player, id: Int, delay: Int = 0, loops: Int = 1, location: */ @JvmOverloads fun playGlobalAudio(location: Location, id: Int, delay: Int = 0, loops: Int = 1, radius: Int = Audio.defaultAudioRadius) { - val nearbyPlayers = RegionManager.getLocalPlayers(location, radius) - for (player in nearbyPlayers) { + for (player in RegionManager.getLocalPlayers(location, radius)) { PacketRepository.send(AudioPacket::class.java, DefaultContext(player, Audio(id, delay, loops, radius), location)) } } @@ -1106,7 +1105,7 @@ fun findNPC(refLoc: Location, id: Int): NPC? { * @returns an NPC matching the given ID or null if none is found */ fun findLocalNPC(entity: Entity, id: Int): NPC? { - return RegionManager.getLocalNpcs(entity).firstOrNull { it.id == id } + return RegionManager.getLocalNPCs(entity.location).firstOrNull { it.id == id } } /** @@ -1115,8 +1114,8 @@ fun findLocalNPC(entity: Entity, id: Int): NPC? { * @param distance The maximum distance to the entity. * @returns an NPC matching the given ID or null if none is found */ -fun findLocalNPCs(location: Location, distance: Int): MutableList { - return RegionManager.getLocalNpcs(location, distance) +fun findLocalNPCs(location: Location, distance: Int): List { + return RegionManager.getLocalNPCs(location, distance) } @@ -1126,7 +1125,7 @@ fun findLocalNPCs(location: Location, distance: Int): MutableList { * @param ids the IDs of the NPCs to look for */ fun findLocalNPCs(entity: Entity, ids: IntArray): List { - return RegionManager.getLocalNpcs(entity).filter { it.id in ids }.toList() + return RegionManager.getLocalNPCs(entity.location).filter { it.id in ids }.toList() } /** @@ -1136,7 +1135,7 @@ fun findLocalNPCs(entity: Entity, ids: IntArray): List { * @param distance The maximum distance to the entity. */ fun findLocalNPCs(entity: Entity, ids: IntArray, distance: Int): List { - return RegionManager.getLocalNpcs(entity, distance).filter { it.id in ids }.toList() + return RegionManager.getLocalNPCs(entity.location, distance).filter { it.id in ids }.toList() } /** diff --git a/Server/src/main/core/api/regionspec/contracts/FillChunkContract.kt b/Server/src/main/core/api/regionspec/contracts/FillChunkContract.kt index a26d33b92..3218207bb 100644 --- a/Server/src/main/core/api/regionspec/contracts/FillChunkContract.kt +++ b/Server/src/main/core/api/regionspec/contracts/FillChunkContract.kt @@ -1,6 +1,6 @@ package core.api.regionspec.contracts -import core.game.world.map.BuildRegionChunk +import core.game.world.map.Location import core.game.world.map.Region import core.game.world.map.RegionChunk import core.game.world.map.build.DynamicRegion @@ -19,6 +19,7 @@ open class FillChunkContract(var chunk: RegionChunk? = null) : ChunkSpecContract for(y in 0 until 8) if(replaceCondition.invoke(x,y,plane)) { val chunk = getChunk(x,y,plane,dyn) + if (chunk==null) continue dyn.replaceChunk( plane, x, @@ -31,11 +32,11 @@ open class FillChunkContract(var chunk: RegionChunk? = null) : ChunkSpecContract } } - open fun getChunk(x: Int, y: Int, plane: Int, dyn: DynamicRegion) : BuildRegionChunk? { - return chunkDelegate.invoke(x, y, plane, sourceRegion)?.copy(dyn.planes[plane]) + open fun getChunk(x: Int, y: Int, plane: Int, dyn: DynamicRegion) : RegionChunk? { + return chunkDelegate.invoke(x, y, plane, sourceRegion)?.copy() } - open fun afterSetting(chunk: BuildRegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) {} + open fun afterSetting(chunk: RegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) {} fun from(region: Region): FillChunkContract { this.sourceRegion = region diff --git a/Server/src/main/core/game/activity/ActivityPlugin.java b/Server/src/main/core/game/activity/ActivityPlugin.java index 50ea847f5..b6d7eb5a7 100644 --- a/Server/src/main/core/game/activity/ActivityPlugin.java +++ b/Server/src/main/core/game/activity/ActivityPlugin.java @@ -4,7 +4,6 @@ import core.ServerConstants; import core.game.node.entity.Entity; import core.game.node.entity.player.Player; import core.game.world.map.Location; -import core.game.world.map.Region; import core.game.world.map.build.DynamicRegion; import core.game.world.map.zone.*; import core.game.world.map.zone.impl.MultiwayCombatZone; @@ -108,7 +107,7 @@ public abstract class ActivityPlugin extends MapZone implements Plugin { l = r.getBaseLocation(); } } - ZoneBorders borders = new ZoneBorders(region.getX() << 6, region.getY() << 6, l.getX() + Region.SIZE, l.getY() + Region.SIZE); + ZoneBorders borders = new ZoneBorders(region.getX() << 6, region.getY() << 6, l.getX() + 64, l.getY() + 64); RegionZone multiZone = multicombat ? new RegionZone(MultiwayCombatZone.getInstance(), borders) : null; RegionZone zone = new RegionZone(this, borders); for (DynamicRegion r : regions) { diff --git a/Server/src/main/core/game/activity/CutscenePlugin.java b/Server/src/main/core/game/activity/CutscenePlugin.java index 043b7c179..71bce7d2b 100644 --- a/Server/src/main/core/game/activity/CutscenePlugin.java +++ b/Server/src/main/core/game/activity/CutscenePlugin.java @@ -129,12 +129,9 @@ public abstract class CutscenePlugin extends ActivityPlugin { */ public void end() { if (region != null) { - for (int i = 0; i < region.getPlanes().length; i++) { - for (NPC n : region.getPlanes()[i].getNpcs()) { - if (n == null) { - continue; - } - n.clear(); + for (int z = 0; z < 4; z++) { + for (NPC npc : region.assembleNpcList(z)) { + npc.clear(); } } } diff --git a/Server/src/main/core/game/bots/AIPlayer.java b/Server/src/main/core/game/bots/AIPlayer.java index e54fe732a..4788417ad 100644 --- a/Server/src/main/core/game/bots/AIPlayer.java +++ b/Server/src/main/core/game/bots/AIPlayer.java @@ -34,7 +34,6 @@ import java.util.*; * @author Emperor */ public class AIPlayer extends Player { - /** * The current UID. */ @@ -318,7 +317,7 @@ public class AIPlayer extends Player { int meX = this.getLocation().getX(); int meY = this.getLocation().getY(); ArrayList nodes = new ArrayList(); - for (NPC npc : RegionManager.getLocalNpcs(this, range)) { + for (NPC npc : RegionManager.getLocalNPCs(location, range)) { if (npc.getId() == entry) nodes.add(npc); } @@ -351,7 +350,7 @@ public class AIPlayer extends Player { //int meX2 = this.getLocation().getX(); ArrayList nodes = new ArrayList(); - for (NPC npc : RegionManager.getLocalNpcs(this, range)) { + for (NPC npc : RegionManager.getLocalNPCs(location, range)) { if (entrys.contains(npc.getId())) nodes.add(npc); } @@ -411,7 +410,7 @@ public class AIPlayer extends Player { public Node getClosesCreature(int radius) { int distance = radius + 1; Node npcReturn = null; - for (NPC npc : RegionManager.getLocalNpcs(this, radius)) { + for (NPC npc : RegionManager.getLocalNPCs(location, radius)) { double distanceToNpc = npc.getLocation().getDistance(this.getLocation()); if ((distanceToNpc) < distance) { distance = (int) distanceToNpc; @@ -424,7 +423,7 @@ public class AIPlayer extends Player { public Node getClosesCreature(int radius, int entry) { int distance = radius + 1; Node npcReturn = null; - for (NPC npc : RegionManager.getLocalNpcs(this, radius)) { + for (NPC npc : RegionManager.getLocalNPCs(location, radius)) { double distanceToNpc = npc.getLocation().getDistance(this.getLocation()); if (npc.getId() == entry) { if ((distanceToNpc) < distance) { @@ -439,7 +438,7 @@ public class AIPlayer extends Player { public Node getClosesCreature(int radius, ArrayList entrys) { int distance = radius + 1; Node npcReturn = null; - for (NPC npc : RegionManager.getLocalNpcs(this, radius)) { + for (NPC npc : RegionManager.getLocalNPCs(location, radius)) { double distanceToNpc = npc.getLocation().getDistance(this.getLocation()); if (entrys.contains(npc.getId())) { if ((distanceToNpc) < distance) { @@ -575,4 +574,4 @@ public class AIPlayer extends Player { public void interact(Node n) { // InteractionPacket.handleObjectInteraction(this, 0, n.getLocation(), n.getId()); } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/bots/PvMBots.java b/Server/src/main/core/game/bots/PvMBots.java index 6aef6e01e..8aeef372c 100644 --- a/Server/src/main/core/game/bots/PvMBots.java +++ b/Server/src/main/core/game/bots/PvMBots.java @@ -5,8 +5,6 @@ import java.util.List; import core.game.consumable.Consumable; import content.data.consumables.Consumables; -import core.game.consumable.Food; -import content.data.consumables.effects.HealingEffect; import core.game.node.entity.skill.Skills; import core.game.node.entity.Entity; import core.game.node.entity.npc.NPC; @@ -19,96 +17,96 @@ import core.tools.RandomFunction; public class PvMBots extends AIPlayer { - //Used so the bot doesn't spam actions - private int tick = 0; + //Used so the bot doesn't spam actions + private int tick = 0; - public PvMBots(Location l) { - super(l); - } + public PvMBots(Location l) { + super(l); + } - public PvMBots(String copyFromFile, Location l) { - super(copyFromFile, l); - } + public PvMBots(String copyFromFile, Location l) { + super(copyFromFile, l); + } - public List FindTargets(Entity entity, int radius) { - List targets = new ArrayList<>(20); - Object[] localNPCs = RegionManager.getLocalNpcs(entity,radius).toArray(); - int length = localNPCs.length; - if(length > 5){length = 5;} - for (int i = 0; i < length; i++) { - NPC npc = (NPC) localNPCs[i]; - { - if (checkValidTargets(npc)) - targets.add(npc); - } - } - if (targets.size() == 0) - return null; - return targets; - } + public List FindTargets(Entity entity, int radius) { + List targets = new ArrayList<>(20); + Object[] localNPCs = RegionManager.getLocalNPCs(entity.getLocation(), radius).toArray(); + int length = localNPCs.length; + if(length > 5){length = 5;} + for (int i = 0; i < length; i++) { + NPC npc = (NPC) localNPCs[i]; + { + if (checkValidTargets(npc)) + targets.add(npc); + } + } + if (targets.size() == 0) + return null; + return targets; + } - public boolean checkValidTargets(NPC target) { - if (!target.isActive()) { - return false; - } - if (!target.getProperties().isMultiZone() && target.inCombat()) { - return false; - } - if (!target.getDefinition().hasAction("attack")) { - return false; - } - return true; - } + public boolean checkValidTargets(NPC target) { + if (!target.isActive()) { + return false; + } + if (!target.getProperties().isMultiZone() && target.inCombat()) { + return false; + } + if (!target.getDefinition().hasAction("attack")) { + return false; + } + return true; + } - public boolean AttackNpcsInRadius(int radius) - { - return AttackNpcsInRadius(this, radius); - } + public boolean AttackNpcsInRadius(int radius) + { + return AttackNpcsInRadius(this, radius); + } - /** - * Attacks NPCs in radius of bot - * @param bot - * @param radius - * @return true if bot will be fighting - */ - public boolean AttackNpcsInRadius(Player bot, int radius) { - if (bot.inCombat()) - return true; - List creatures = FindTargets(bot, radius); - if (creatures == null) { - return false; - } - bot.attack(creatures.get(RandomFunction.getRandom((creatures.size() - 1)))); - if (!creatures.isEmpty()) { - return true; - } else { - creatures = FindTargets(bot, radius); - if (!creatures.isEmpty()) - { - bot.attack(creatures.get(RandomFunction.getRandom((creatures.size() - 1)))); - return true; - } - return false; - } - } + /** + * Attacks NPCs in radius of bot + * @param bot + * @param radius + * @return true if bot will be fighting + */ + public boolean AttackNpcsInRadius(Player bot, int radius) { + if (bot.inCombat()) + return true; + List creatures = FindTargets(bot, radius); + if (creatures == null) { + return false; + } + bot.attack(creatures.get(RandomFunction.getRandom((creatures.size() - 1)))); + if (!creatures.isEmpty()) { + return true; + } else { + creatures = FindTargets(bot, radius); + if (!creatures.isEmpty()) + { + bot.attack(creatures.get(RandomFunction.getRandom((creatures.size() - 1)))); + return true; + } + return false; + } + } - @Override - public void tick() { + @Override + public void tick() { super.tick(); this.tick++; - //Despawn - if (this.getSkills().getLifepoints() <= 5){ - //TODO: Just respawn a new bot (not sure how you'd do that :L) - // Maybe make all PvMBots know what to do if they aren't in right area? I.e. pest control bots teleport to PC - //this.teleport(new Location(500, 500)); - //Despawning not being delayed causes 3 errors in the console - this.getSkills().setLifepoints(20); - } + //Despawn + if (this.getSkills().getLifepoints() <= 5){ + //TODO: Just respawn a new bot (not sure how you'd do that :L) + // Maybe make all PvMBots know what to do if they aren't in right area? I.e. pest control bots teleport to PC + //this.teleport(new Location(500, 500)); + //Despawning not being delayed causes 3 errors in the console + this.getSkills().setLifepoints(20); + } - //Npc Combat + //Npc Combat /*if (this.tick % 10 == 0) { if (!this.inCombat()) AttackNpcsInRadius(this, 5); @@ -116,34 +114,34 @@ public class PvMBots extends AIPlayer { if (this.tick == 100) this.tick = 0; - //this.eat(); - //this.getPrayer().toggle() - } + //this.eat(); + //this.getPrayer().toggle() + } - public void CheckPrayer(PrayerType type[]) { - for (int i = 0; i < type.length; i++) - this.getPrayer().toggle(type[i]); - } + public void CheckPrayer(PrayerType type[]) { + for (int i = 0; i < type.length; i++) + this.getPrayer().toggle(type[i]); + } - public void eat(int foodId) { - Item foodItem = new Item(foodId); + public void eat(int foodId) { + Item foodItem = new Item(foodId); - if ((this.getSkills().getStaticLevel(Skills.HITPOINTS) >= this.getSkills().getLifepoints() * 3) && this.getInventory().containsItem(foodItem)) { - this.lock(3); - //this.animate(new Animation(829)); - Item food = this.getInventory().getItem(foodItem); + if ((this.getSkills().getStaticLevel(Skills.HITPOINTS) >= this.getSkills().getLifepoints() * 3) && this.getInventory().containsItem(foodItem)) { + this.lock(3); + //this.animate(new Animation(829)); + Item food = this.getInventory().getItem(foodItem); - Consumable consumable = Consumables.getConsumableById(food.getId()).getConsumable(); + Consumable consumable = Consumables.getConsumableById(food.getId()).getConsumable(); - if (consumable == null) { - return; - } + if (consumable == null) { + return; + } - consumable.consume(food, this); - this.getProperties().getCombatPulse().delayNextAttack(3); - } - if (this.checkVictimIsPlayer() == false) - if (!(this.getInventory().contains(foodId, 1))) - this.getInventory().add(new Item(foodId, 5)); //Add Food to Inventory - } + consumable.consume(food, this); + this.getProperties().getCombatPulse().delayNextAttack(3); + } + if (this.checkVictimIsPlayer() == false) + if (!(this.getInventory().contains(foodId, 1))) + this.getInventory().add(new Item(foodId, 5)); //Add Food to Inventory + } } diff --git a/Server/src/main/core/game/bots/ScriptAPI.kt b/Server/src/main/core/game/bots/ScriptAPI.kt index c2ac69649..14ed085ac 100644 --- a/Server/src/main/core/game/bots/ScriptAPI.kt +++ b/Server/src/main/core/game/bots/ScriptAPI.kt @@ -41,7 +41,6 @@ import core.game.ge.GrandExchange import core.game.ge.GrandExchangeOffer import core.game.interaction.IntType import core.game.interaction.InteractionListeners -import core.tools.SystemLogger import core.game.system.config.ItemConfigParser import core.game.world.GameWorld import core.game.world.repository.Repository @@ -134,24 +133,22 @@ class ScriptAPI(private val bot: Player) { * @author Ceikry */ fun getNearestNodeFromList(acceptedNames: List, isObject: Boolean): Node? { - if (isObject) - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].objectList, acceptedName = acceptedNames) - else - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].entities, acceptedName = acceptedNames) + val region = RegionManager.forId(bot.location.regionId) + val list = if (isObject) region.assembleObjectList(bot.location.z) else region.assembleEntityList(bot.location.z) + return processEvaluationList(list, acceptedName = acceptedNames) } /** * Gets the nearest node with matching id. * @param id the id to look for - * @param object whether or not the node we are looking for is an object. + * @param object whether the node we are looking for is an object. * @return the closest node with matching id or null. * @author Ceikry */ fun getNearestNode(id: Int, isObject: Boolean): Node? { - if (isObject) - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].objectList, acceptedId = id) - else - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].entities, acceptedId = id) + val region = RegionManager.forId(bot.location.regionId) + val list = if (isObject) region.assembleObjectList(bot.location.z) else region.assembleEntityList(bot.location.z) + return processEvaluationList(list, acceptedId = id) } /** @@ -161,25 +158,28 @@ class ScriptAPI(private val bot: Player) { * @author Ceikry */ fun getNearestNode(entityName: String): Node? { - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].entities, acceptedName = listOf(entityName)) + val region = RegionManager.forId(bot.location.regionId) + val list = region.assembleEntityList(bot.location.z) + return processEvaluationList(list, acceptedName = listOf(entityName)) } /** * Gets the nearest node with a matching name. * @param name the name to look for. - * @param object whether or not the node we are looking for is an object. + * @param object whether the node we are looking for is an object. * @return the nearest matching node or null. * @author Ceikry */ fun getNearestNode(name: String, isObject: Boolean): Node? { - if (isObject) - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].objectList, acceptedName = listOf(name)) - else - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].entities, acceptedName = listOf(name)) + val region = RegionManager.forId(bot.location.regionId) + val list = region.assembleEntityList(bot.location.z) + return processEvaluationList(list, acceptedName = listOf(name)) } fun getNearestObjectByPredicate(predicate: (Node?) -> Boolean): Node? { - return processEvaluationList(RegionManager.forId(bot.location.regionId).planes[bot.location.z].objectList, acceptedPredicate = predicate) + val region = RegionManager.forId(bot.location.regionId) + val list = region.assembleObjectList(bot.location.z) + return processEvaluationList(list, acceptedPredicate = predicate) } fun evaluateViability (e: Node?, minDistance: Double, maxDistance: Double, acceptedNames: List? = null, acceptedId: Int = -1, acceptedPredicate: ((Node?) -> Boolean)? = null): Boolean { @@ -268,12 +268,10 @@ class ScriptAPI(private val bot: Player) { fun getNearestGameObject(loc: Location, objectId: Int): Scenery? { var nearestObject: Scenery? = null val minDistance = Double.MAX_VALUE - for (o in RegionManager.forId(loc.regionId).planes[0].objects) { - for (obj in o) { - if (obj != null) { - if (distance(loc, obj) < minDistance && obj.id == objectId) { - nearestObject = obj - } + for (obj in RegionManager.forId(loc.regionId).assembleObjectList(loc.z)) { + if (obj != null) { + if (distance(loc, obj) < minDistance && obj.id == objectId) { + nearestObject = obj } } } @@ -290,7 +288,7 @@ class ScriptAPI(private val bot: Player) { */ private fun findTargets(entity: Entity, radius: Int, name: String? = null): List? { val targets: MutableList = ArrayList() - val localNPCs: Array = RegionManager.getLocalNpcs(entity, radius).toTypedArray() + val localNPCs: Array = RegionManager.getLocalNPCs(entity.location, radius).toTypedArray() var length = localNPCs.size if (length > 5) { length = 5 diff --git a/Server/src/main/core/game/global/action/DoorActionHandler.java b/Server/src/main/core/game/global/action/DoorActionHandler.java index 02234e136..26df139c5 100644 --- a/Server/src/main/core/game/global/action/DoorActionHandler.java +++ b/Server/src/main/core/game/global/action/DoorActionHandler.java @@ -137,7 +137,7 @@ public final class DoorActionHandler { return Unit.INSTANCE; }); } - GameWorld.getPulser().submit(new Pulse(1) { + GameWorld.getPulser().submit(new Pulse(1) { boolean opened = false; @Override public boolean pulse() { @@ -161,7 +161,7 @@ public final class DoorActionHandler { } // pass the al kharid gate - if (object.getId() == 35549 || object.getId() == 35551 && player.getViewport().getRegion().getId() == 13106) { + if (object.getId() == 35549 || object.getId() == 35551 && player.getLocation().getRegionId() == 13106) { player.getAchievementDiaryManager().finishTask(player, DiaryType.LUMBRIDGE, 0, 4); } @@ -425,7 +425,7 @@ public final class DoorActionHandler { } object.setCharge(IN_USE_CHARGE); second.setCharge(IN_USE_CHARGE); - GameWorld.getPulser().submit(new Pulse(1) { + GameWorld.getPulser().submit(new Pulse(1) { boolean opened = false; @Override @@ -499,18 +499,17 @@ public final class DoorActionHandler { */ public static Scenery getSecondDoor(Scenery object, Entity entity) { Location l = object.getLocation(); - Player player = entity instanceof Player ? (Player) entity : null; Scenery o = null; - if ((o = RegionManager.getObject(l.transform(-1, 0, 0))) != null && o.getName().equals(object.getName())) { + if ((o = RegionManager.getObject(l.transform(-1, 0, 0), object.getType())) != null && o.getName().equals(object.getName())) { return o; } - if ((o = RegionManager.getObject(l.transform(1, 0, 0))) != null && o.getName().equals(object.getName())) { + if ((o = RegionManager.getObject(l.transform(1, 0, 0), object.getType())) != null && o.getName().equals(object.getName())) { return o; } - if ((o = RegionManager.getObject(l.transform(0, -1, 0))) != null && o.getName().equals(object.getName())) { + if ((o = RegionManager.getObject(l.transform(0, -1, 0), object.getType())) != null && o.getName().equals(object.getName())) { return o; } - if ((o = RegionManager.getObject(l.transform(0, 1, 0))) != null && o.getName().equals(object.getName())) { + if ((o = RegionManager.getObject(l.transform(0, 1, 0), object.getType())) != null && o.getName().equals(object.getName())) { return o; } return null; diff --git a/Server/src/main/core/game/interaction/MovementPulse.java b/Server/src/main/core/game/interaction/MovementPulse.java index b378a8a1f..b9acb88fd 100644 --- a/Server/src/main/core/game/interaction/MovementPulse.java +++ b/Server/src/main/core/game/interaction/MovementPulse.java @@ -7,7 +7,6 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.npc.NPCBehavior; import core.game.node.entity.player.Player; import core.game.system.task.Pulse; -import core.game.world.GameWorld; import core.game.world.map.Direction; import core.game.world.map.Location; import core.game.world.map.Point; @@ -19,11 +18,8 @@ import core.net.packet.context.PlayerContext; import core.net.packet.out.ClearMinimapFlag; import kotlin.jvm.functions.Function2; import kotlin.Pair; -import core.tools.SystemLogger; import core.api.utils.Vector; -import content.region.wilderness.handlers.revenants.RevenantNPC; - import static core.api.ContentAPIKt.*; import java.util.Deque; @@ -206,142 +202,148 @@ public abstract class MovementPulse extends Pulse { mover.scripts.removeNormalScripts(); } - @Override - public boolean update() { - if (!mover.getViewport().getRegion().isActive()) - return false; + @Override + public boolean update() { + if (!mover.getLocation().getRegion().isActive()) + return false; - if (!isRunning()) return true; + if (!isRunning()) return true; - if (!validate()) { - stop(); - return true; - } - - clearInferiorScripts(); - - mover.face(null); - if (canInteractWithoutMoving()) { - if (interactImmediately()) { - stop(); - return true; - } - } - updatePath(); - - if (tryInteract()) { - stop(); - return true; - } - - return false; - } - - private boolean tryInteract() { - Location ml = mover.getLocation(); - // Allow being within 1 square of moving entities to interact with them. - int radius = destination instanceof Entity && ((Entity)destination).getWalkingQueue().hasPath() ? 1 : 0; - if (interactLocation == null) - return false; - boolean atInteractLocation = Math.max(Math.abs(ml.getX() - interactLocation.getX()), Math.abs(ml.getY() - interactLocation.getY())) <= radius; - // Check if already in a valid interaction position for entity destinations - boolean canInteractFromCurrentPosition = false; - if (!atInteractLocation && destination instanceof Entity) { - Entity target = (Entity) destination; - Location dl = target.getLocation(); - boolean onSameTile = ml.getX() == dl.getX() && ml.getY() == dl.getY() && ml.getZ() == dl.getZ(); - if (!onSameTile) { - canInteractFromCurrentPosition = Pathfinder.canInteract( - ml.getX(), ml.getY(), mover.size(), - dl.getX(), dl.getY(), target.size(), target.size(), - 0, // walkFlag - "can interact from any unblocked direction" - ml.getZ(), - RegionManager::getClippingFlag - ); - } - } - if (atInteractLocation || canInteractFromCurrentPosition) { - try { - if (near || pulse()) { - if (mover instanceof Player) { - if (near) { - ((Player) mover).getPacketDispatch().sendMessage("I can't reach that."); - } - PacketRepository.send(ClearMinimapFlag.class, new PlayerContext((Player) mover)); - } - stop(); - return true; - } - } catch (Exception e){ - e.printStackTrace(); - stop(); - } - } - return false; - } - - /** - * Checks if the mover can interact with an entity destination from their - * current position without needing to move. - * - * @return true if the mover can interact without moving - */ - private boolean canInteractWithoutMoving() { - if (!(destination instanceof Entity)) { - return false; - } - Entity target = (Entity) destination; - Location ml = mover.getLocation(); - Location dl = target.getLocation(); - if (ml.getX() == dl.getX() && ml.getY() == dl.getY() && ml.getZ() == dl.getZ()) { - return false; - } - if (isInsideEntity(mover.getLocation())) { - return false; - } - if (target.getWalkingQueue().hasPath()) { // For moving entities, allow interaction from 1 tile away - int distance = Math.max( - Math.abs(ml.getX() - dl.getX()), - Math.abs(ml.getY() - dl.getY()) - ); - if (distance <= target.size()) { - return true; - } - } - return Pathfinder.canInteract( - ml.getX(), ml.getY(), mover.size(), - dl.getX(), dl.getY(), target.size(), target.size(), - 0, // walkFlag - "can interact from any unblocked direction" - ml.getZ(), - RegionManager::getClippingFlag - ); - } - - /** - * Immediately performs the interaction without pathfinding. - * Called when the player is already in a valid interaction position. - * - * @return true if interaction was successful and pulse should stop - */ - private boolean interactImmediately() { - if (destination instanceof Entity) { - mover.face((Entity) destination); - } - try { - if (pulse()) { - if (mover instanceof Player) { - PacketRepository.send(ClearMinimapFlag.class, new PlayerContext((Player) mover)); + if (!validate()) { + stop(); + return true; } - return true; - } - } catch (Exception e) { - e.printStackTrace(); + + clearInferiorScripts(); + + mover.face(null); + if (canInteractWithoutMoving()) { + if (interactImmediately()) { + stop(); + return true; + } + } + updatePath(); + + if (tryInteract()) { + stop(); + return true; + } + + return false; + } + + private boolean tryInteract() { + Location ml = mover.getLocation(); + if (ml == null) { + return false; + } + // Allow being within 1 square of moving entities to interact with them. + int radius = destination instanceof Entity && ((Entity) destination).getWalkingQueue().hasPath() ? 1 : 0; + if (interactLocation == null) + return false; + boolean atInteractLocation = Math.max(Math.abs(ml.getX() - interactLocation.getX()), Math.abs(ml.getY() - interactLocation.getY())) <= radius; + // Check if already in a valid interaction position for entity destinations + boolean canInteractFromCurrentPosition = false; + if (!atInteractLocation && destination instanceof Entity) { + Entity target = (Entity) destination; + Location dl = target.getLocation(); + if (dl == null) { + return false; + } + boolean onSameTile = ml.getX() == dl.getX() && ml.getY() == dl.getY() && ml.getZ() == dl.getZ(); + if (!onSameTile) { + canInteractFromCurrentPosition = Pathfinder.canInteract( + ml.getX(), ml.getY(), mover.size(), + dl.getX(), dl.getY(), target.size(), target.size(), + 0, // walkFlag - "can interact from any unblocked direction" + ml.getZ(), + RegionManager::getClippingFlag); + } + } + if (atInteractLocation || canInteractFromCurrentPosition) { + try { + if (near || pulse()) { + if (mover instanceof Player) { + if (near) { + ((Player) mover).getPacketDispatch().sendMessage("I can't reach that."); + } + PacketRepository.send(ClearMinimapFlag.class, new PlayerContext((Player) mover)); + } + stop(); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + stop(); + } + } + return false; + } + + /** + * Checks if the mover can interact with an entity destination from their + * current position without needing to move. + * + * @return true if the mover can interact without moving + */ + private boolean canInteractWithoutMoving() { + if (!(destination instanceof Entity)) { + return false; + } + Entity target = (Entity) destination; + Location ml = mover.getLocation(); + Location dl = target.getLocation(); + if (ml == null || dl == null) { + return false; + } + if (ml.getX() == dl.getX() && ml.getY() == dl.getY() && ml.getZ() == dl.getZ()) { + return false; + } + if (isInsideEntity(ml)) { + return false; + } + if (target.getWalkingQueue().hasPath()) { // For moving entities, allow interaction from 1 tile away + int distance = Math.max( + Math.abs(ml.getX() - dl.getX()), + Math.abs(ml.getY() - dl.getY())); + if (distance <= target.size()) { + return true; + } + } + return Pathfinder.canInteract( + ml.getX(), ml.getY(), mover.size(), + dl.getX(), dl.getY(), target.size(), target.size(), + 0, // walkFlag - "can interact from any unblocked direction" + ml.getZ(), + RegionManager::getClippingFlag); + } + + /** + * Immediately performs the interaction without pathfinding. + * Called when the player is already in a valid interaction position. + * + * @return true if interaction was successful and pulse should stop + */ + private boolean interactImmediately() { + if (destination instanceof Entity) { + mover.face((Entity) destination); + } + try { + if (pulse()) { + if (mover instanceof Player) { + PacketRepository.send(ClearMinimapFlag.class, new PlayerContext((Player) mover)); + } + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; } - return false; - } private boolean validate() { - if (mover == null || destination == null || mover.getViewport().getRegion() == null || hasInactiveNode()) { + if (mover == null || destination == null || mover.getLocation().getRegion() == null || hasInactiveNode()) { return false; } return isRunning(); @@ -595,6 +597,9 @@ public abstract class MovementPulse extends Pulse { * @return {@code True} if so. */ private boolean isInsideEntity(Location l) { + if (l == null) { + return false; + } if (!(destination instanceof Entity)) { return false; } @@ -602,6 +607,9 @@ public abstract class MovementPulse extends Pulse { return false; } Location loc = destination.getLocation(); + if (loc == null) { + return false; + } int size = destination.size(); return Pathfinder.isStandingIn(l.getX(), l.getY(), mover.size(), mover.size(), loc.getX(), loc.getY(), size, size); } diff --git a/Server/src/main/core/game/node/entity/Entity.java b/Server/src/main/core/game/node/entity/Entity.java index ffaa8f461..d4d1a8f2b 100644 --- a/Server/src/main/core/game/node/entity/Entity.java +++ b/Server/src/main/core/game/node/entity/Entity.java @@ -20,7 +20,6 @@ import core.game.world.map.zone.ZoneRestriction; import org.jetbrains.annotations.NotNull; import core.game.world.GameWorld; import core.game.world.map.Location; -import core.game.world.map.Viewport; import core.game.world.map.path.Path; import core.game.world.map.path.Pathfinder; import core.game.world.map.zone.ZoneMonitor; @@ -70,11 +69,6 @@ public abstract class Entity extends Node { */ private final GameAttributes attributes = new GameAttributes(); - /** - * The entity's viewport. - */ - private final Viewport viewport = new Viewport(); - /** * The pulse manager. */ @@ -114,7 +108,7 @@ public abstract class Entity extends Node { * The mapping of event types to event hooks */ private HashMap, ArrayList> hooks = new HashMap<>(); - public TimerManager timers = new TimerManager(this); + public TimerManager timers = new TimerManager(this); /** * If the entity is invisible. @@ -205,7 +199,7 @@ public abstract class Entity extends Node { */ public void init() { active = true; - TimerRegistry.addAutoTimers (this); + TimerRegistry.addAutoTimers (this); } /** @@ -218,7 +212,7 @@ public abstract class Entity extends Node { Location old = location != null ? location.transform(0, 0, 0) : Location.create(0,0,0); walkingQueue.update(); scripts.postMovement(!Objects.equals(location, old)); - timers.processTimers(); + timers.processTimers(); updateMasks.prepare(this); } @@ -242,7 +236,6 @@ public abstract class Entity extends Node { */ public void clear() { active = false; - viewport.remove(this); pulseManager.clear(); } @@ -259,8 +252,8 @@ public abstract class Entity extends Node { */ public void fullRestore() { skills.restore(); - timers.removeTimer("poison"); - timers.removeTimer("poison:immunity"); + timers.removeTimer("poison"); + timers.removeTimer("poison:immunity"); } /** @@ -309,12 +302,12 @@ public abstract class Entity extends Node { return false; } - /** - * Should this entity prevent the mover from moving through it? - */ - public boolean shouldPreventStacking(Entity mover) { - return false; - } + /** + * Should this entity prevent the mover from moving through it? + */ + public boolean shouldPreventStacking(Entity mover) { + return false; + } /** * Checks an impact before receiving it. @@ -440,7 +433,7 @@ public abstract class Entity extends Node { * Checks if this entity is attackable by the attacking entity. * @param entity The attacking entity. * @param style The combat style used. - * @param message Whether to send the player a message indicating why the entity isn't attackable. + * @param message Whether to send the player a message indicating why the entity isn't attackable. * @return {@code True} if the attacking entity can attack this entity. */ public boolean isAttackable(Entity entity, CombatStyle style, boolean message) { @@ -651,15 +644,15 @@ public abstract class Entity extends Node { * @return {@code True} if succesful. */ public boolean face(Entity entity) { - if (entity == null) { - int ordinal = EntityFlags.getOrdinal(EFlagType.of(this), EntityFlag.FaceEntity); - if (getUpdateMasks().unregisterSynced(ordinal)) { - return getUpdateMasks().register(EntityFlag.FaceEntity, null); - } - return true; - } - return getUpdateMasks().register(EntityFlag.FaceEntity, entity, true); - } + if (entity == null) { + int ordinal = EntityFlags.getOrdinal(EFlagType.of(this), EntityFlag.FaceEntity); + if (getUpdateMasks().unregisterSynced(ordinal)) { + return getUpdateMasks().register(EntityFlag.FaceEntity, null); + } + return true; + } + return getUpdateMasks().register(EntityFlag.FaceEntity, entity, true); + } /** * Registers a new face location update flag to the update masks. @@ -667,13 +660,13 @@ public abstract class Entity extends Node { * @return {@code True} if succesful. */ public boolean faceLocation(Location location) { - if (location == null) { - int ordinal = EntityFlags.getOrdinal(EFlagType.of(this), EntityFlag.FaceLocation); - getUpdateMasks().unregisterSynced(ordinal); - return true; - } - return getUpdateMasks().register(EntityFlag.FaceLocation, location, true); - } + if (location == null) { + int ordinal = EntityFlags.getOrdinal(EFlagType.of(this), EntityFlag.FaceLocation); + getUpdateMasks().unregisterSynced(ordinal); + return true; + } + return getUpdateMasks().register(EntityFlag.FaceLocation, location, true); + } /** * Registers a new force chat update flag to the update masks. @@ -681,8 +674,8 @@ public abstract class Entity extends Node { * @return {@code True} if successful. */ public boolean sendChat(String string) { - return getUpdateMasks().register(EntityFlag.ForceChat, string); - } + return getUpdateMasks().register(EntityFlag.ForceChat, string); + } /** * Gets the current combat swing handler. @@ -879,13 +872,6 @@ public abstract class Entity extends Node { return walkingQueue; } - /** - * Gets the viewport. - * @return The viewport. - */ - public Viewport getViewport() { - return viewport; - } /** * Gets the skills. @@ -947,7 +933,7 @@ public abstract class Entity extends Node { * @return {@code True} if so. */ public boolean isTeleBlocked() { - return timers.getTimer("teleblock") != null || getLocks().isTeleportLocked() || getZoneMonitor().isRestricted(ZoneRestriction.TELEPORT); + return timers.getTimer("teleblock") != null || getLocks().isTeleportLocked() || getZoneMonitor().isRestricted(ZoneRestriction.TELEPORT); } /** @@ -966,7 +952,7 @@ public abstract class Entity extends Node { this.invisible = invisible; } - public Location getClosestOccupiedTile(@NotNull Location other) { + public Location getClosestOccupiedTile(@NotNull Location other) { List occupied = getOccupiedTiles(); Location closest = location; @@ -982,7 +968,7 @@ public abstract class Entity extends Node { } return closest; - } + } public List getOccupiedTiles() { ArrayList occupied = new ArrayList<>(); @@ -1001,7 +987,7 @@ public abstract class Entity extends Node { return scripts.getDelay() > GameWorld.getTicks(); } - public boolean isTeleporting() { - return getAttribute("tele-pulse", null) != null || properties.getTeleportLocation() != null; - } + public boolean isTeleporting() { + return getAttribute("tele-pulse", null) != null || properties.getTeleportLocation() != null; + } } diff --git a/Server/src/main/core/game/node/entity/combat/CombatPulse.kt b/Server/src/main/core/game/node/entity/combat/CombatPulse.kt index 074a656e9..7a176b1ad 100644 --- a/Server/src/main/core/game/node/entity/combat/CombatPulse.kt +++ b/Server/src/main/core/game/node/entity/combat/CombatPulse.kt @@ -19,6 +19,7 @@ import core.tools.RandomFunction import core.api.* import core.game.interaction.DestinationFlag import core.game.system.timer.impl.* +import core.game.world.map.RegionManager /** * The combat-handling pulse implementation. @@ -116,7 +117,7 @@ class CombatPulse( if (victim == null || DeathTask.isDead(entity) || DeathTask.isDead(victim)) { return true } - if (!entity!!.viewport.region.isActive || !victim!!.viewport.region.isActive) { + if (!RegionManager.forId(entity!!.location.regionId).isActive || !RegionManager.forId(victim!!.location.regionId).isActive) { return true } if (!interactable()) { diff --git a/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt b/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt index 2b151ba47..bbd951985 100644 --- a/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt +++ b/Server/src/main/core/game/node/entity/combat/CombatSwingHandler.kt @@ -17,7 +17,6 @@ import core.game.world.map.Direction import core.game.world.map.Location import core.game.world.map.RegionManager import core.game.world.map.RegionManager.getClippingFlag -import core.game.world.map.path.Pathfinder import core.game.world.map.path.Pathfinder.* import core.game.world.update.flag.context.Animation import core.tools.RandomFunction @@ -25,7 +24,6 @@ import core.game.system.config.ItemConfigParser import core.tools.Log import org.rs09.consts.Sounds import java.util.* -import kotlin.math.floor /** * Handles a combat swing. diff --git a/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java b/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java index 30cf2f238..6ac567b15 100644 --- a/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java +++ b/Server/src/main/core/game/node/entity/combat/spell/CombatSpell.java @@ -15,12 +15,14 @@ import core.game.node.entity.player.link.audio.Audio; import core.game.node.item.Item; import core.game.world.map.RegionManager; import core.game.world.map.zone.impl.WildernessZone; +import core.game.world.repository.Repository; import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Graphics; import org.rs09.consts.Sounds; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static core.api.ContentAPIKt.playGlobalAudio; @@ -108,29 +110,26 @@ public abstract class CombatSpell extends MagicSpell { } - /** - * Gets a list of valid targets for a multihitting spell. - * @param entity The caster of the spell. - * @param target The primary victim. - * @param max The maximum number of extra victims that may be hit. - * @return The list of targets (the primary target is always at index 0). - */ - public List getMultihitTargets(Entity entity, Entity target, int max) { + /** + * Gets a list of valid targets for a multihitting spell. + * @param entity The caster of the spell. + * @param target The primary victim. + * @param max The maximum number of extra victims that may be hit. + * @return The list of targets (the primary target is always at index 0). + */ + public List getMultihitTargets(Entity entity, Entity target, int max) { List victims = new ArrayList<>(20); victims.add(target); - List surrounding = new ArrayList<>(); - surrounding.addAll(RegionManager.getSurroundingPlayers(target)); - surrounding.addAll(RegionManager.getSurroundingNPCs(target)); - - for (Entity e : surrounding) { - if (e == target || e == entity) { - continue; - } - if (CombatStyle.MAGIC.getSwingHandler().canSwing(entity, e) == InteractionType.NO_INTERACT || !e.isAttackable(entity, CombatStyle.MAGIC, false)) { + List surrounding = RegionManager.getLocalEntities(target.getLocation(), 1); + for (Entity e : surrounding) { + if (e == target || e == entity) { continue; } - if (e instanceof Familiar) { + if (CombatStyle.MAGIC.getSwingHandler().canSwing(entity, e) == InteractionType.NO_INTERACT || !e.isAttackable(entity, CombatStyle.MAGIC, false)) { + continue; + } + if (e instanceof Familiar) { Player owner = ((Familiar) e).getOwner(); if (owner != entity && WildernessZone.getInstance().continueAttack(entity, owner, CombatStyle.MAGIC, true)) { victims.add(e); @@ -143,7 +142,7 @@ public abstract class CombatSpell extends MagicSpell { } } return victims; - } + } /** * Visualizes the impact. diff --git a/Server/src/main/core/game/node/entity/impl/ForceMovement.java b/Server/src/main/core/game/node/entity/impl/ForceMovement.java index 8cfc7efd6..f450b6237 100644 --- a/Server/src/main/core/game/node/entity/impl/ForceMovement.java +++ b/Server/src/main/core/game/node/entity/impl/ForceMovement.java @@ -93,7 +93,7 @@ public class ForceMovement extends Pulse { * @param unlockAfter Whether to unlock the entity after the ForceMovement completes * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public ForceMovement(Entity e, Location start, Location destination, Animation startAnim, Animation animation, Direction direction, int commenceSpeed, int pathSpeed, boolean unlockAfter) { super(1, e); this.entity = e; @@ -116,15 +116,15 @@ public class ForceMovement extends Pulse { * @param speed The path speed. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public ForceMovement(Entity e, Location start, Location end, Animation animation, int speed) { this(e, start, end, WALK_ANIMATION, animation, direction(start, end), WALKING_SPEED, speed, true); } - /** + /** * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public ForceMovement(Entity e, Location destination, int startSpeed, int animSpeed){ this(e,e.getLocation(),destination,WALK_ANIMATION,WALK_ANIMATION,direction(e.getLocation(),destination),startSpeed,animSpeed, true); } @@ -137,7 +137,7 @@ public class ForceMovement extends Pulse { * @param animation the animation. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public ForceMovement(Entity e, Location start, Location destination, Animation animation) { this(e, start, destination, WALK_ANIMATION, animation, direction(start, destination), WALKING_SPEED, WALKING_SPEED, true); } @@ -149,7 +149,7 @@ public class ForceMovement extends Pulse { * @param animation the animation. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public ForceMovement(Location start, Location destination, Animation animation) { this(null, start, destination, WALK_ANIMATION, animation, direction(start, destination), WALKING_SPEED, WALKING_SPEED, true); } @@ -161,7 +161,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location destination) { return run(e, e.getLocation(), destination, WALK_ANIMATION, WALK_ANIMATION, direction(e.getLocation(), destination), WALKING_SPEED, WALKING_SPEED, true); } @@ -174,7 +174,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination) { return run(e, start, destination, WALK_ANIMATION, WALK_ANIMATION, direction(e.getLocation(), destination), WALKING_SPEED, WALKING_SPEED, true); } @@ -188,7 +188,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation animation) { return run(e, start, destination, WALK_ANIMATION, animation, direction(start, destination), WALKING_SPEED, WALKING_SPEED, true); } @@ -203,7 +203,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation animation, int speed) { return run(e, start, destination, WALK_ANIMATION, animation, direction(start, destination), WALKING_SPEED, speed, true); } @@ -217,7 +217,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation startAnim, Animation animation) { return run(e, start, destination, startAnim, animation, direction(start, destination), WALKING_SPEED, WALKING_SPEED, true); } @@ -232,7 +232,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation startAnim, Animation animation, Direction direction) { return run(e, start, destination, startAnim, animation, direction, WALKING_SPEED, WALKING_SPEED, true); } @@ -248,15 +248,15 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation startAnim, Animation animation, Direction direction, int pathSpeed) { return run(e, start, destination, startAnim, animation, direction, WALKING_SPEED, pathSpeed, true); } - /** + /** * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation startAnim, Animation animation, Direction direction, int commenceSpeed, int pathSpeed) { return run(e, start, destination, startAnim, animation, direction, commenceSpeed, pathSpeed, true); } @@ -271,7 +271,7 @@ public class ForceMovement extends Pulse { * @return The created ForceMovement object. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location start, Location destination, Animation startAnim, Animation animation, Direction direction, int commenceSpeed, int pathSpeed, boolean unlockAfter) { if (startAnim != null) { startAnim.setPriority(Animator.Priority.VERY_HIGH); @@ -285,10 +285,10 @@ public class ForceMovement extends Pulse { GameWorld.getPulser().submit(fm); return fm; } - /* + /* * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public static ForceMovement run(Entity e, Location destination, int commenceSpeed, int pathSpeed){ return run(e,e.getLocation(),destination,WALK_ANIMATION,WALK_ANIMATION,direction(e.getLocation(),destination),commenceSpeed,pathSpeed, true); } @@ -298,7 +298,7 @@ public class ForceMovement extends Pulse { * @param e the entity. * @deprecated this is no longer the preferred way to use force movement. Use the ContentAPI forceMove method instead, please. */ - @Deprecated + @Deprecated public void run(final Entity e, final int speed) { this.entity = e; int commence = (int) start.getDistance(e.getLocation()); @@ -358,9 +358,9 @@ public class ForceMovement extends Pulse { int ticks = 1 + commenceSpeed + pathSpeed; entity.getImpactHandler().setDisabledTicks(ticks); entity.getUpdateMasks().register(EntityFlag.ForceMove, new ForceMoveCtx(start, destination, commenceSpeed * 30, pathSpeed * 30, direction)); - if(entity instanceof Player) { - entity.getWalkingQueue().updateRegion(destination, false); - } + if (entity instanceof Player) { + entity.getWalkingQueue().updateRegion(start, destination, false); + } super.start(); } diff --git a/Server/src/main/core/game/node/entity/impl/WalkingQueue.java b/Server/src/main/core/game/node/entity/impl/WalkingQueue.java index fbd9d2e36..d10215b40 100644 --- a/Server/src/main/core/game/node/entity/impl/WalkingQueue.java +++ b/Server/src/main/core/game/node/entity/impl/WalkingQueue.java @@ -62,7 +62,7 @@ public final class WalkingQueue { */ private Location footPrint; - public ArrayList routeItems = new ArrayList(); + public ArrayList routeItems = new ArrayList(); /** * Constructs a new {@code WalkingQueue} {@code Object}. @@ -80,29 +80,30 @@ public final class WalkingQueue { boolean isPlayer = entity instanceof Player; this.walkDir = -1; this.runDir = -1; - if(entity.getLocation() == null) { + Location prevLocation = entity.getLocation(); + if (prevLocation == null) { return; } if (updateTeleport()) { return; } - if (isPlayer && updateRegion(entity.getLocation(), true)) { + if (isPlayer && updateRegion(prevLocation, entity.getLocation(), true)) { return; } - if (hasTimerActive(entity, "frozen")) - return; + if (hasTimerActive(entity, "frozen")) + return; Point point = walkingQueue.poll(); - boolean drawPath = entity.getAttribute("routedraw", false); + boolean drawPath = entity.getAttribute("routedraw", false); if (point == null) { updateRunEnergy(false); - if (isPlayer && drawPath) { - for (GroundItem item : routeItems) { - if (item != null) { - RegionManager.getRegionPlane(item.getLocation()).remove(item); - } - } - routeItems.clear(); - } + if (isPlayer && drawPath) { + for (GroundItem item : routeItems) { + if (item != null) { + RegionManager.getRegionChunk(item.getLocation()).remove(item); + } + } + routeItems.clear(); + } return; } if (isPlayer && ((Player) entity).getSettings().getRunEnergy() < 1.0) { @@ -174,7 +175,7 @@ public final class WalkingQueue { } footPrint = entity.getLocation(); entity.setLocation(dest); - RegionManager.move(entity); + RegionManager.move(entity, prevLocation, dest); } this.walkDir = walkDirection; this.runDir = runDirection; @@ -190,9 +191,9 @@ public final class WalkingQueue { if (player.getSettings().getWeight() > 0.0) { rate *= 1 + (player.getSettings().getWeight() / 100); } - if (hasTimerActive(player, "hamstrung")) { - rate *= 4; - } + if (hasTimerActive(player, "hamstrung")) { + rate *= 4; + } return rate; } @@ -237,6 +238,7 @@ public final class WalkingQueue { public boolean updateTeleport() { if (entity.getProperties().getTeleportLocation() != null) { reset(false); + Location prevLocation = entity.getLocation(); entity.setLocation(entity.getProperties().getTeleportLocation()); entity.getProperties().setTeleportLocation(null); if (entity instanceof Player) { @@ -251,7 +253,7 @@ public final class WalkingQueue { p.getPlayerFlags().setUpdateSceneGraph(true); } } - RegionManager.move(entity); + RegionManager.move(entity, prevLocation, entity.getLocation()); footPrint = entity.getLocation(); entity.getProperties().setTeleporting(true); return true; @@ -264,7 +266,7 @@ public final class WalkingQueue { * return true. * @return {@code True} if the region updated, {@code false} if not. */ - public boolean updateRegion(Location location, boolean move) { + public boolean updateRegion(Location prevLocation, Location location, boolean move) { Player p = (Player) entity; Location lastRegion = p.getPlayerFlags().getLastSceneGraph(); if (lastRegion == null) { @@ -285,7 +287,7 @@ public final class WalkingQueue { p.getPlayerFlags().setUpdateSceneGraph(true); } if (move && p.getPlayerFlags().isUpdateSceneGraph()) { - RegionManager.move(entity); + RegionManager.move(entity, prevLocation, location); return true; } return false; @@ -320,13 +322,13 @@ public final class WalkingQueue { if (point == null) { return; } - boolean drawRoute = entity.getAttribute("routedraw", false); - if (drawRoute && entity instanceof Player) { - Player p = (Player) entity; - GroundItem item = new GroundItem(new Item(13444), Location.create(x, y, p.getLocation().getZ()), p); - routeItems.add (item); - RegionManager.getRegionPlane(item.getLocation()).add(item); - } + boolean drawRoute = entity.getAttribute("routedraw", false); + if (drawRoute && entity instanceof Player) { + Player p = (Player) entity; + GroundItem item = new GroundItem(new Item(13444), Location.create(x, y, p.getLocation().getZ()), p); + routeItems.add (item); + RegionManager.getRegionChunk(item.getLocation()).add(item); + } int diffX = x - point.getX(), diffY = y - point.getY(); int max = Math.max(Math.abs(diffX), Math.abs(diffY)); for (int i = 0; i < max; i++) { diff --git a/Server/src/main/core/game/node/entity/npc/NPC.java b/Server/src/main/core/game/node/entity/npc/NPC.java index 18334251e..fe04c19e1 100644 --- a/Server/src/main/core/game/node/entity/npc/NPC.java +++ b/Server/src/main/core/game/node/entity/npc/NPC.java @@ -142,7 +142,7 @@ public class NPC extends Entity { public NPCBehavior behavior; - public boolean isRespawning = false; + public boolean isRespawning = false; /** * Constructs a new {@code NPC} {@code Object}. @@ -213,8 +213,8 @@ public class NPC extends Entity { getProperties().setSpawnLocation(getLocation()); initConfig(); Repository.getNpcs().add(this); - RegionManager.move(this); - if (getViewport().getRegion().isActive()) { + getLocation().getChunk().add(this); + if (getLocation().getRegion().isActive()) { Repository.addRenderableNPC(this); } interactPlugin.setDefault(); @@ -230,9 +230,9 @@ public class NPC extends Entity { } } behavior.onCreation(this); - // FIXME: hack around MovementPulse's constructor getting run while behavior is null when behavior is set between NPC constructor and init. + // FIXME: hack around MovementPulse's constructor getting run while behavior is null when behavior is set between NPC constructor and init. // FIXME: Commented out as a fix. most npcs were not being able to attack with range/magic due to setting the combat pulse. - // getProperties().setCombatPulse(new CombatPulse(this)); + // getProperties().setCombatPulse(new CombatPulse(this)); } @Override @@ -240,9 +240,7 @@ public class NPC extends Entity { super.clear(); Repository.removeRenderableNPC(this); Repository.getNpcs().remove(this); - getViewport().setCurrentPlane(null); behavior.onRemoval(this); - // getViewport().setRegion(null); } /** @@ -329,7 +327,7 @@ public class NPC extends Entity { */ public boolean openShop(Player player) { if (getName().contains("assistant")) { - NPC n = RegionManager.getNpc(this, getId() - 1); + NPC n = RegionManager.getNpc(location, getId() - 1, 16); if (n != null) { return n.openShop(player); } @@ -425,7 +423,7 @@ public class NPC extends Entity { return false; } return true; - } + } @Override public int getDragonfireProtection(boolean fire) { @@ -434,7 +432,7 @@ public class NPC extends Entity { @Override public void tick() { - if (!getViewport().getRegion().isActive()) { + if (!getLocation().getRegion().isActive()) { onRegionInactivity(); return; } @@ -444,10 +442,10 @@ public class NPC extends Entity { return; } if (isRespawning && respawnTick <= GameWorld.getTicks()) { - behavior.onRespawn(this); + behavior.onRespawn(this); onRespawn(); - fullRestore(); - isRespawning = false; + fullRestore(); + isRespawning = false; } handleTickActions(); super.tick(); @@ -549,10 +547,10 @@ public class NPC extends Entity { nextWalk = GameWorld.getTicks() + 5 + RandomFunction.randomize(10); } - public void resetWalk() { - nextWalk = GameWorld.getTicks() - 1; - getWalkingQueue().reset(); - } + public void resetWalk() { + nextWalk = GameWorld.getTicks() - 1; + getWalkingQueue().reset(); + } /** * Called when the region goes inactive. @@ -570,7 +568,7 @@ public class NPC extends Entity { } } Repository.removeRenderableNPC(this); - if (getViewport().getRegion() instanceof DynamicRegion) { + if (getLocation().getRegion() instanceof DynamicRegion) { clear(); } } @@ -597,7 +595,7 @@ public class NPC extends Entity { Player p = !(killer instanceof Player) ? null : (Player) killer; if (p != null) { p.incrementAttribute("/save:" + STATS_BASE + ":" + STATS_ENEMIES_KILLED); - PlayerStatsCounter.incrementKills(p, originalId); + PlayerStatsCounter.incrementKills(p, originalId); } handleDrops(p, killer); if (!isRespawn()) @@ -608,9 +606,9 @@ public class NPC extends Entity { setRespawnTick(GameWorld.getTicks() + definition.getConfiguration(NPCConfigParser.RESPAWN_DELAY, 17)); } - public void setRespawnTicks (int ticks) { - definition.getHandlers().put(NPCConfigParser.RESPAWN_DELAY, ticks); - } + public void setRespawnTicks (int ticks) { + definition.getHandlers().put(NPCConfigParser.RESPAWN_DELAY, ticks); + } @Override public void commenceDeath(Entity killer) { @@ -687,9 +685,9 @@ public class NPC extends Entity { } getProperties().setAttackStyle(new WeaponInterface.AttackStyle(WeaponInterface.STYLE_CONTROLLED, index)); CombatStyle style = getDefinition().getConfiguration(NPCConfigParser.COMBAT_STYLE); - if (style != null) { - getProperties().getCombatPulse().setStyle(style); - } + if (style != null) { + getProperties().getCombatPulse().setStyle(style); + } if (style == CombatStyle.MAGIC) { getProperties().setAutocastSpell(new DefaultCombatSpell(this)); int spell = definition.getConfiguration("spell_id", -1); @@ -744,10 +742,10 @@ public class NPC extends Entity { configure(); interactPlugin.setDefault(); if (id == originalId) { - int ordinal = EntityFlags.getOrdinal (EFlagType.NPC, EntityFlag.TypeSwap); - getUpdateMasks().unregisterSynced(ordinal); + int ordinal = EntityFlags.getOrdinal (EFlagType.NPC, EntityFlag.TypeSwap); + getUpdateMasks().unregisterSynced(ordinal); } - getUpdateMasks().register(EntityFlag.TypeSwap, id, id != originalId); + getUpdateMasks().register(EntityFlag.TypeSwap, id, id != originalId); return this; } @@ -783,10 +781,10 @@ public class NPC extends Entity { Location returnToSpawnLocation = getProperties().getSpawnLocation().transform(RandomFunction.random(-radius, radius+1), RandomFunction.random(-radius, radius+1), 0); int dist = (int) Location.getDistance(location, returnToSpawnLocation); int pathLimit = 14; - if (dist > pathLimit) { - Vector normalizedDir = Vector.betweenLocs(this.location, returnToSpawnLocation).normalized(); - returnToSpawnLocation = this.location.transform (normalizedDir.times(pathLimit)); - } + if (dist > pathLimit) { + Vector normalizedDir = Vector.betweenLocs(this.location, returnToSpawnLocation).normalized(); + returnToSpawnLocation = this.location.transform (normalizedDir.times(pathLimit)); + } return returnToSpawnLocation; } Location l = movementPath[movementIndex++]; diff --git a/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java b/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java index 50f93be3f..0e8b8a1fe 100644 --- a/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java +++ b/Server/src/main/core/game/node/entity/npc/agg/AggressiveBehavior.java @@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.world.map.zone.impl.WildernessZone; import core.game.world.map.RegionManager; +import core.game.world.repository.Repository; import java.util.ArrayList; import java.util.List; @@ -116,7 +117,7 @@ public class AggressiveBehavior { */ public List getPossibleTargets(Entity entity, int radius) { List targets = new ArrayList<>(20); - for (Player player : RegionManager.getLocalPlayers(entity, radius)) { + for (Player player : RegionManager.getLocalPlayers(entity.getLocation(), radius)) { if (canSelectTarget(entity, player)) { targets.add(player); } diff --git a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java index baacc117b..ebd086000 100644 --- a/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java +++ b/Server/src/main/core/game/node/entity/npc/drop/NPCDropTables.java @@ -25,6 +25,7 @@ import core.game.world.repository.Repository; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * Holds and handles the NPC drop tables. @@ -111,9 +112,9 @@ public final class NPCDropTables { } return; } - announceIfRare(player, item); + announceIfRare(player, item); if(item.getId() == 6199 && player instanceof Player){ - player.sendMessage("A mystery box has fallen on the ground."); + player.sendMessage("A mystery box has fallen on the ground."); } sendDropMessage(player, npc.getId(), item); if (player == null) { @@ -144,7 +145,7 @@ public final class NPCDropTables { int itemId = item.getDefinition().isUnnoted() ? item.getId() : item.getNoteChange(); if (player != null && npc.getProperties().isMultiZone() && (item.getDefinition().isTradeable() || item.getName().endsWith("charm")) && player.getCommunication().getClan() != null && player.getCommunication().isLootShare() && player.getCommunication().getLootRequirement().ordinal() >= player.getCommunication().getClan().getLootRequirement().ordinal() && !player.getIronmanManager().isIronman()) { Player looter = player; - List players = RegionManager.getLocalPlayers(npc, 16); + List players = RegionManager.getLocalPlayers(npc.getLocation(), 16); List looters = new ArrayList<>(20); for (Player p : players) { if (p != null && p.getCommunication().getClan() != null && p.getCommunication().getClan() == player.getCommunication().getClan() && p.getCommunication().isLootShare() && p.getCommunication().getLootRequirement().ordinal() >= p.getCommunication().getClan().getLootRequirement().ordinal()) { diff --git a/Server/src/main/core/game/node/entity/player/Player.java b/Server/src/main/core/game/node/entity/player/Player.java index d21c591fc..cb94a83bd 100644 --- a/Server/src/main/core/game/node/entity/player/Player.java +++ b/Server/src/main/core/game/node/entity/player/Player.java @@ -131,22 +131,22 @@ public class Player extends Entity { public Boolean isAfkLogout; - private StorageState POHStorageState; + private StorageState POHStorageState; - public final Container POHStorageProxyContainer = new POHStorageProxyContainer(this); + public final Container POHStorageProxyContainer = new POHStorageProxyContainer(this); - public StorageState getPOHStorageState() { - if (POHStorageState == null) { - POHStorageState = new StorageState(this); - } - return POHStorageState; - } + public StorageState getPOHStorageState() { + if (POHStorageState == null) { + POHStorageState = new StorageState(this); + } + return POHStorageState; + } - public void setPOHStorageState(StorageState state) { - this.POHStorageState = state; - } + public void setPOHStorageState(StorageState state) { + this.POHStorageState = state; + } - /** + /** * The inventory. */ private final Container inventory = new Container(28).register(new InventoryListener(this)); @@ -854,10 +854,9 @@ public class Player extends Entity { getInterfaceManager().setChatbox(null); getPulseManager().clear(); getZoneMonitor().getZones().clear(); - getViewport().setCurrentPlane(RegionManager.forId(66666).getPlanes()[3]); playerFlags.setLastSceneGraph(null); playerFlags.setUpdateSceneGraph(false); - playerFlags.setLastViewport(new RegionChunk[Viewport.CHUNK_SIZE][Viewport.CHUNK_SIZE]); + playerFlags.setLastViewport(new RegionChunk[13][13]); renderInfo.getLocalNpcs().clear(); renderInfo.getLocalPlayers().clear(); renderInfo.setLastLocation(null); @@ -891,7 +890,7 @@ public class Player extends Entity { * @param login If the player is logging in. */ public void updateSceneGraph(boolean login) { - Region region = getViewport().getRegion(); + Region region = getLocation().getRegion(); if (region instanceof DynamicRegion || region == null && (region = RegionManager.forId(location.getRegionId())) instanceof DynamicRegion) { PacketRepository.send(BuildDynamicScene.class, new DynamicSceneContext(this, login)); } else { diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index fb50ee051..dc3fcb107 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -1,9 +1,11 @@ package core.game.node.entity.player.info.login; +import core.Server; import core.game.component.Component; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.emote.Emotes; import core.game.node.item.Item; +import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.net.packet.PacketRepository; import core.net.packet.context.InterfaceContext; @@ -37,270 +39,271 @@ import content.data.Quests; */ public final class LoginConfiguration { - /** - * The login plugins. - */ - private static final List> LOGIN_PLUGINS = new ArrayList<>(20); + /** + * The login plugins. + */ + private static final List> LOGIN_PLUGINS = new ArrayList<>(20); - /** - * The lobby pane component. - */ - private static final Component LOBBY_PANE = new Component(549); + /** + * The lobby pane component. + */ + private static final Component LOBBY_PANE = new Component(549); - /** - * The lobby interface component. - */ - private static final Component LOBBY_INTERFACE = new Component(378); + /** + * The lobby interface component. + */ + private static final Component LOBBY_INTERFACE = new Component(378); - /** - * The lobby message of the week models & constant to be set for auto selecting the models - */ - private static final int[] MESSAGE_MODEL = {15, 16, 17, 18, 19, 20, 21, 22, 23, 405, 447, 622, 623, 679, 715, 800}; - private static int messModel; + /** + * The lobby message of the week models & constant to be set for auto selecting the models + */ + private static final int[] MESSAGE_MODEL = {15, 16, 17, 18, 19, 20, 21, 22, 23, 405, 447, 622, 623, 679, 715, 800}; + private static int messModel; - /** - * Constructs a new {@Code LoginConfiguration} {@Code Object} - */ - public LoginConfiguration() { - /* - * empty. - */ - } + /** + * Constructs a new {@Code LoginConfiguration} {@Code Object} + */ + public LoginConfiguration() { + /* + * empty. + */ + } - /** - * Configures the lobby login. - * - * @param player The player. - */ - public static void configureLobby(Player player) { - player.updateSceneGraph(true); - if (!player.isArtificial() && player.getAttribute("tutorial:complete",false) && player.getAttribute("login_type", LoginType.NORMAL_LOGIN) != LoginType.RECONNECT_TYPE) { - sendLobbyScreen(player); - } else { - configureGameWorld(player); - } - } + /** + * Configures the lobby login. + * + * @param player The player. + */ + public static void configureLobby(Player player) { + player.updateSceneGraph(true); + if (!player.isArtificial() && player.getAttribute("tutorial:complete",false) && player.getAttribute("login_type", LoginType.NORMAL_LOGIN) != LoginType.RECONNECT_TYPE) { + sendLobbyScreen(player); + } else { + configureGameWorld(player); + } + } - /** - * Sends the lobby interface-related packets. - * - * @param player The player. - */ - public static void sendLobbyScreen(Player player) { - messModel = autoSelect(); - for(Player p : Repository.getLobbyPlayers()){ - if(p.getName().equals(player.getName())){ - p.clear(); - Repository.getLobbyPlayers().remove(p); - break; - } - } - Repository.getLobbyPlayers().add(player); - setInterfaceText(player, "Welcome to " + ServerConstants.SERVER_NAME, 378, 115); - setInterfaceText(player, getLastLogin(player), 378, 116); - setInterfaceText(player, "", 378, 37); - setInterfaceText(player, "Want to stay up to date with the latest news and updates? Join our discord by using the link on our website!", 378, 38); - setInterfaceText(player, "", 378, 39); - setInterfaceText(player, "Discord Invite", 378, 14); - setInterfaceText(player, "Discord Invite", 378, 129); - setInterfaceText(player, "You can gain more credits by reporting bugs and various other methods of contribution.", 378, 93); - setInterfaceText(player, player.getDetails().getCredits() + "", 378, 96); - setInterfaceText(player, "Credits", 378, 94); - setInterfaceText(player, "", 378, 229); - setInterfaceText(player, "Want to contribute to " + ServerConstants.SERVER_NAME + "? Visit the GitLab using the link on our website!", 378, 230); - setInterfaceText(player, "", 378, 231); - setInterfaceText(player, "Github", 378, 240); - setInterfaceText(player, GameWorld.getSettings().getMessage_string(), messModel, getMessageChild(messModel)); - player.getInterfaceManager().openWindowsPane(LOBBY_PANE); - player.getInterfaceManager().setOpened(LOBBY_INTERFACE); - PacketRepository.send(Interface.class, new InterfaceContext(player, LOBBY_PANE.getId(), 2, 378, true)); - PacketRepository.send(Interface.class, new InterfaceContext(player, LOBBY_PANE.getId(), 3, messModel, true));//UPDATE `configs` SET `value`=FLOOR(RAND()*(25-10)+10) WHERE key_="messageInterface" - player.getDetails().setLastLogin(System.currentTimeMillis()); - } + /** + * Sends the lobby interface-related packets. + * + * @param player The player. + */ + public static void sendLobbyScreen(Player player) { + messModel = autoSelect(); + for(Player p : Repository.getLobbyPlayers()){ + if(p.getName().equals(player.getName())){ + p.clear(); + Repository.getLobbyPlayers().remove(p); + break; + } + } + Repository.getLobbyPlayers().add(player); + setInterfaceText(player, "Welcome to " + ServerConstants.SERVER_NAME, 378, 115); + setInterfaceText(player, getLastLogin(player), 378, 116); + setInterfaceText(player, "", 378, 37); + setInterfaceText(player, "Want to stay up to date with the latest news and updates? Join our discord by using the link on our website!", 378, 38); + setInterfaceText(player, "", 378, 39); + setInterfaceText(player, "Discord Invite", 378, 14); + setInterfaceText(player, "Discord Invite", 378, 129); + setInterfaceText(player, "You can gain more credits by reporting bugs and various other methods of contribution.", 378, 93); + setInterfaceText(player, player.getDetails().getCredits() + "", 378, 96); + setInterfaceText(player, "Credits", 378, 94); + setInterfaceText(player, "", 378, 229); + setInterfaceText(player, "Want to contribute to " + ServerConstants.SERVER_NAME + "? Visit the GitLab using the link on our website!", 378, 230); + setInterfaceText(player, "", 378, 231); + setInterfaceText(player, "Github", 378, 240); + setInterfaceText(player, GameWorld.getSettings().getMessage_string(), messModel, getMessageChild(messModel)); + player.getInterfaceManager().openWindowsPane(LOBBY_PANE); + player.getInterfaceManager().setOpened(LOBBY_INTERFACE); + PacketRepository.send(Interface.class, new InterfaceContext(player, LOBBY_PANE.getId(), 2, 378, true)); + PacketRepository.send(Interface.class, new InterfaceContext(player, LOBBY_PANE.getId(), 3, messModel, true));//UPDATE `configs` SET `value`=FLOOR(RAND()*(25-10)+10) WHERE key_="messageInterface" + player.getDetails().setLastLogin(System.currentTimeMillis()); + } - /** - * Configures the game world. - * - * @param player The player. - */ - public static void configureGameWorld(final Player player) { - sendGameConfiguration(player); - Repository.getLobbyPlayers().remove(player); - player.setPlaying(true); - UpdateSequence.getRenderablePlayers().add(player); - RegionManager.move(player); - player.getMusicPlayer().init(); - player.updateAppearance(); - player.getPlayerFlags().setUpdateSceneGraph(true); - player.getPacketDispatch().sendInterfaceConfig(226, 1, true); + /** + * Configures the game world. + * + * @param player The player. + */ + public static void configureGameWorld(final Player player) { + sendGameConfiguration(player); + Repository.getLobbyPlayers().remove(player); + player.setPlaying(true); + UpdateSequence.getRenderablePlayers().add(player); + RegionManager.move(player, ServerConstants.START_LOCATION, player.getLocation()); + player.getMusicPlayer().init(); + player.updateAppearance(); + player.getPlayerFlags().setUpdateSceneGraph(true); + player.getPacketDispatch().sendInterfaceConfig(226, 1, true); - if(player.getGlobalData().getTestStage() == 3 && !player.getEmoteManager().isUnlocked(Emotes.SAFETY_FIRST)){ - player.getEmoteManager().unlock(Emotes.SAFETY_FIRST); - } + if (player.getGlobalData().getTestStage() == 3 && !player.getEmoteManager().isUnlocked(Emotes.SAFETY_FIRST)) { + //TODO: port this to save version later. when you do, please also do this for the Explore emote, which has a similar problem (e.g. player_name.json has this). + player.getEmoteManager().unlock(Emotes.SAFETY_FIRST); + } - for (Item item : player.getEquipment().toArray()) { - //Run equip hooks for all items equipped on login. - //We should have already been doing this. - //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused. - if (item == null) continue; - player.getEquipment().remove(item); - if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { - player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); - addItemOrBank(player, item.getId(), item.getAmount()); - } - } + for (Item item : player.getEquipment().toArray()) { + //Run equip hooks for all items equipped on login. + //We should have already been doing this. + //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused. + if (item == null) continue; + player.getEquipment().remove(item); + if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { + player.sendMessage(colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); + addItemOrBank(player, item.getId(), item.getAmount()); + } + } - SpellBookManager.SpellBook currentSpellBook = SpellBookManager.SpellBook.forInterface(player.getSpellBookManager().getSpellBook()); - if (currentSpellBook == SpellBookManager.SpellBook.ANCIENT && !hasRequirement(player, Quests.DESERT_TREASURE)) { - player.sendMessage(colorize("%RAs you can no longer use Ancient Magic, you have been set back to Modern.")); - player.getSpellBookManager().setSpellBook(SpellBookManager.SpellBook.MODERN); - } else if (currentSpellBook == SpellBookManager.SpellBook.LUNAR && !hasRequirement(player, Quests.LUNAR_DIPLOMACY)) { - player.sendMessage(colorize("%RAs you can no longer use Lunar Magic, you have been set back to Modern.")); - player.getSpellBookManager().setSpellBook(SpellBookManager.SpellBook.MODERN); - } - player.getSpellBookManager().update(player); + SpellBookManager.SpellBook currentSpellBook = SpellBookManager.SpellBook.forInterface(player.getSpellBookManager().getSpellBook()); + if (currentSpellBook == SpellBookManager.SpellBook.ANCIENT && !hasRequirement(player, Quests.DESERT_TREASURE)) { + player.sendMessage(colorize("%RAs you can no longer use Ancient Magic, you have been set back to Modern.")); + player.getSpellBookManager().setSpellBook(SpellBookManager.SpellBook.MODERN); + } else if (currentSpellBook == SpellBookManager.SpellBook.LUNAR && !hasRequirement(player, Quests.LUNAR_DIPLOMACY)) { + player.sendMessage(colorize("%RAs you can no longer use Lunar Magic, you have been set back to Modern.")); + player.getSpellBookManager().setSpellBook(SpellBookManager.SpellBook.MODERN); + } + player.getSpellBookManager().update(player); - // 1050 is checked client-side for making piety/chivalry disallowed sfx, likely due to the minigame requirement. - // Set it here unconditionally until the minigame is implemented. - if (hasRequirement(player, Quests.KINGS_RANSOM, false)) { - setVarbit(player, 3909, 8, false); - } - if(ServerConstants.RULES_AND_INFO_ENABLED) - RulesAndInfo.openFor(player); - /*if (TutorialSession.getExtension(player).getStage() != 73) { - TutorialStage.load(player, TutorialSession.getExtension(player).getStage(), true); - }*/ - } + // 1050 is checked client-side for making piety/chivalry disallowed sfx, likely due to the minigame requirement. + // Set it here unconditionally until the minigame is implemented. + if (hasRequirement(player, Quests.KINGS_RANSOM, false)) { + setVarbit(player, 3909, 8, false); + } + if(ServerConstants.RULES_AND_INFO_ENABLED) + RulesAndInfo.openFor(player); + /*if (TutorialSession.getExtension(player).getStage() != 73) { + TutorialStage.load(player, TutorialSession.getExtension(player).getStage(), true); + }*/ + } - /** - * Sends the game configuration packets. - * - * @param player The player to send to. - */ - public static void sendGameConfiguration(final Player player) { - player.getInterfaceManager().openWindowsPane(new Component(player.getInterfaceManager().isResizable() ? 746 : 548)); - player.getInterfaceManager().openChatbox(137); - player.getInterfaceManager().openDefaultTabs(); - welcome(player); - config(player); - for (Plugin plugin : LOGIN_PLUGINS) { - try { - plugin.newInstance(player); - } catch (Throwable e) { - e.printStackTrace(); - } - } - player.getAppearance().sync(); - } + /** + * Sends the game configuration packets. + * + * @param player The player to send to. + */ + public static void sendGameConfiguration(final Player player) { + player.getInterfaceManager().openWindowsPane(new Component(player.getInterfaceManager().isResizable() ? 746 : 548)); + player.getInterfaceManager().openChatbox(137); + player.getInterfaceManager().openDefaultTabs(); + welcome(player); + config(player); + for (Plugin plugin : LOGIN_PLUGINS) { + try { + plugin.newInstance(player); + } catch (Throwable e) { + e.printStackTrace(); + } + } + player.getAppearance().sync(); + } - /** - * Method used to welcome the player. - * - * @param player the player. Fullscreen mode Object id: - */ - public static final void welcome(final Player player) { - if (player.isArtificial()) { - return; - } - player.getPacketDispatch().sendMessage("Welcome to " + ServerConstants.SERVER_NAME + "."); - if (player.getDetails().isMuted()) { - player.getPacketDispatch().sendMessage("You are muted."); - player.getPacketDispatch().sendMessage("To prevent further mutes please read the rules."); - } - } + /** + * Method used to welcome the player. + * + * @param player the player. Fullscreen mode Object id: + */ + public static final void welcome(final Player player) { + if (player.isArtificial()) { + return; + } + player.getPacketDispatch().sendMessage("Welcome to " + ServerConstants.SERVER_NAME + "."); + if (player.getDetails().isMuted()) { + player.getPacketDispatch().sendMessage("You are muted."); + player.getPacketDispatch().sendMessage("To prevent further mutes please read the rules."); + } + } - /** - * Method used to configure all possible settings for the player. - * - * @param player the player. - */ - public static final void config(final Player player) { - if(!player.isArtificial()) - log(LoginConfiguration.class, Log.INFO, "configuring player " + player.getUsername()); - player.getInventory().refresh(); - player.getEquipment().refresh(); - player.getSkills().refresh(); - player.getSkills().configure(); - player.getSettings().update(); - player.getInteraction().setDefault(); - player.getPacketDispatch().sendRunEnergy(); - player.getFamiliarManager().login(); - player.getInterfaceManager().openDefaultTabs(); - setInterfaceText(player, "Friends List - " + ServerConstants.SERVER_NAME + " " + GameWorld.getSettings().getWorldId(), 550, 3); - setInterfaceText(player, "When you have finished playing " + ServerConstants.SERVER_NAME + ", always use the button below to logout safely.", 182, 0); - player.getQuestRepository().syncronizeTab(player); - player.getInterfaceManager().close(); - player.getEmoteManager().refresh(); - player.getInterfaceManager().openInfoBars(); - if(!player.isArtificial()) - log(LoginConfiguration.class, Log.INFO, "finished configuring player " + player.getUsername()); - } + /** + * Method used to configure all possible settings for the player. + * + * @param player the player. + */ + public static final void config(final Player player) { + if(!player.isArtificial()) + log(LoginConfiguration.class, Log.INFO, "configuring player " + player.getUsername()); + player.getInventory().refresh(); + player.getEquipment().refresh(); + player.getSkills().refresh(); + player.getSkills().configure(); + player.getSettings().update(); + player.getInteraction().setDefault(); + player.getPacketDispatch().sendRunEnergy(); + player.getFamiliarManager().login(); + player.getInterfaceManager().openDefaultTabs(); + setInterfaceText(player, "Friends List - " + ServerConstants.SERVER_NAME + " " + GameWorld.getSettings().getWorldId(), 550, 3); + setInterfaceText(player, "When you have finished playing " + ServerConstants.SERVER_NAME + ", always use the button below to logout safely.", 182, 0); + player.getQuestRepository().syncronizeTab(player); + player.getInterfaceManager().close(); + player.getEmoteManager().refresh(); + player.getInterfaceManager().openInfoBars(); + if(!player.isArtificial()) + log(LoginConfiguration.class, Log.INFO, "finished configuring player " + player.getUsername()); + } - /** - * Gets the message child for the inter id. - * @notice GameSettings.kt contains the list of what these are - * @param interfaceId The interface id. - * @return The child id. - */ - public static int getMessageChild(int interfaceId) { - if (interfaceId == 622) { - return 8; - } else if (interfaceId == 16) { - return 6; - } else if (interfaceId == 20 || interfaceId == 623) { - return 5; - } else if (interfaceId == 15 || interfaceId == 18 || interfaceId == 19 || interfaceId == 21 || interfaceId == 22 || interfaceId == 447 || interfaceId == 405) { - return 4; - } else if (interfaceId == 17 || interfaceId == 23 || interfaceId == 800) { - return 3; - } else if (interfaceId == 715) { - return 2; - } else if (interfaceId == 679) { - return 1; - } - return 0; - } + /** + * Gets the message child for the inter id. + * @notice GameSettings.kt contains the list of what these are + * @param interfaceId The interface id. + * @return The child id. + */ + public static int getMessageChild(int interfaceId) { + if (interfaceId == 622) { + return 8; + } else if (interfaceId == 16) { + return 6; + } else if (interfaceId == 20 || interfaceId == 623) { + return 5; + } else if (interfaceId == 15 || interfaceId == 18 || interfaceId == 19 || interfaceId == 21 || interfaceId == 22 || interfaceId == 447 || interfaceId == 405) { + return 4; + } else if (interfaceId == 17 || interfaceId == 23 || interfaceId == 800) { + return 3; + } else if (interfaceId == 715) { + return 2; + } else if (interfaceId == 679) { + return 1; + } + return 0; + } - /** - * Sets a random interface id for the "message of the week" models - */ - private final static int autoSelect() { - boolean contains = IntStream.of(MESSAGE_MODEL).anyMatch(x -> x == GameWorld.getSettings().getMessage_model()); - return contains ? GameWorld.getSettings().getMessage_model():MESSAGE_MODEL[new Random().nextInt(MESSAGE_MODEL.length)]; - } + /** + * Sets a random interface id for the "message of the week" models + */ + private final static int autoSelect() { + boolean contains = IntStream.of(MESSAGE_MODEL).anyMatch(x -> x == GameWorld.getSettings().getMessage_model()); + return contains ? GameWorld.getSettings().getMessage_model():MESSAGE_MODEL[new Random().nextInt(MESSAGE_MODEL.length)]; + } - /** - * Gets the last login string for the lobby. - * - * @param player the player. - * @return the last login. - */ - public static String getLastLogin(Player player) { - player.getPacketDispatch().sendLastLoginInfo(); - String string = "You last logged in @timeAgo from:"; - long time = player.getDetails().getLastLogin(); - Date lastLogin = new Date(time); - Date current = new Date(); - long diff = current.getTime() - lastLogin.getTime(); - int days = (int) TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS); - if (days < 1) { - string = string.replace("@timeAgo", "earlier today"); - } else if (days == 1) { - string = string.replace("@timeAgo", "yesterday"); - } else { - string = string.replace("@timeAgo", days + " days ago"); - } - return string; - } + /** + * Gets the last login string for the lobby. + * + * @param player the player. + * @return the last login. + */ + public static String getLastLogin(Player player) { + player.getPacketDispatch().sendLastLoginInfo(); + String string = "You last logged in @timeAgo from:"; + long time = player.getDetails().getLastLogin(); + Date lastLogin = new Date(time); + Date current = new Date(); + long diff = current.getTime() - lastLogin.getTime(); + int days = (int) TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS); + if (days < 1) { + string = string.replace("@timeAgo", "earlier today"); + } else if (days == 1) { + string = string.replace("@timeAgo", "yesterday"); + } else { + string = string.replace("@timeAgo", days + " days ago"); + } + return string; + } - /** - * Gets the loginPlugins. - * - * @return The loginPlugins. - */ - public static List> getLoginPlugins() { - return LOGIN_PLUGINS; - } + /** + * Gets the loginPlugins. + * + * @return The loginPlugins. + */ + public static List> getLoginPlugins() { + return LOGIN_PLUGINS; + } } diff --git a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt index 351c8dc34..ffac22bf9 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt +++ b/Server/src/main/core/game/node/entity/player/info/login/PlayerSaver.kt @@ -350,7 +350,6 @@ class PlayerSaver (val player: Player){ globalData.put("zafTime",player.savedData.globalData.zafTime.toString()) globalData.put("fritzGlass",player.savedData.globalData.isFritzGlass) globalData.put("wydinEmployee",player.savedData.globalData.isWydinEmployee) - globalData.put("draynorRecording",player.savedData.globalData.isDraynorRecording) globalData.put("geTutorial",player.savedData.globalData.isGeTutorial) globalData.put("essenceTeleporter",player.savedData.globalData.essenceTeleporter.toString()) globalData.put("recoilDamage",player.savedData.globalData.recoilDamage.toString()) diff --git a/Server/src/main/core/game/node/entity/player/link/GlobalData.java b/Server/src/main/core/game/node/entity/player/link/GlobalData.java index 62873b245..3565b4309 100644 --- a/Server/src/main/core/game/node/entity/player/link/GlobalData.java +++ b/Server/src/main/core/game/node/entity/player/link/GlobalData.java @@ -94,11 +94,6 @@ public final class GlobalData { */ private boolean wydinEmployee; - /** - * Represents if the draynor recording has been seen. - */ - private boolean draynorRecording; - /** * Represents if the ge tutorial has been done. */ @@ -313,7 +308,6 @@ public final class GlobalData { zafTime = Long.parseLong(data.get("zafTime").toString()); fritzGlass = (boolean) data.get("fritzGlass"); wydinEmployee = (boolean) data.get("wydinEmployee"); - draynorRecording = (boolean) data.get("draynorRecording"); geTutorial = (boolean) data.get("geTutorial"); essenceTeleporter = Integer.parseInt( data.get("essenceTeleporter").toString()); recoilDamage = Integer.parseInt( data.get("recoilDamage").toString()); @@ -661,22 +655,6 @@ public final class GlobalData { return zafTime; } - /** - * Gets the draynorRecording. - * @return The draynorRecording. - */ - public boolean isDraynorRecording() { - return draynorRecording; - } - - /** - * Sets the draynorRecording. - * @param draynorRecording The draynorRecording to set. - */ - public void setDraynorRecording(boolean draynorRecording) { - this.draynorRecording = draynorRecording; - } - /** * Gets the wydinEmployee. * @return The wydinEmployee. diff --git a/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java b/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java index de6bb8233..8f2557652 100644 --- a/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java +++ b/Server/src/main/core/game/node/entity/player/link/PacketDispatch.java @@ -2,6 +2,7 @@ package core.game.node.entity.player.link; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; +import core.game.world.repository.Repository; import core.tools.Log; import core.game.system.task.Pulse; import core.game.world.GameWorld; @@ -50,9 +51,9 @@ public final class PacketDispatch { PacketRepository.send(Config.class, new ConfigContext(player, index, value)); } - public void sendVarcUpdate(short index, int value) { - PacketRepository.send(VarcUpdate.class, new VarcUpdateContext(player, index, value)); - } + public void sendVarcUpdate(short index, int value) { + PacketRepository.send(VarcUpdate.class, new VarcUpdateContext(player, index, value)); + } /** * Send a game message. @@ -312,7 +313,7 @@ public final class PacketDispatch { * @param id The animation id. */ public void sendAnimation(int id) { - player.getUpdateMasks().register(EntityFlag.Animate, new Animation(id)); + player.getUpdateMasks().register(EntityFlag.Animate, new Animation(id)); } /** @@ -321,7 +322,7 @@ public final class PacketDispatch { * @param delay The animation delay. */ public void sendAnimation(int id, int delay) { - player.getUpdateMasks().register(EntityFlag.Animate, new Animation(id, delay)); + player.getUpdateMasks().register(EntityFlag.Animate, new Animation(id, delay)); } /** @@ -329,7 +330,7 @@ public final class PacketDispatch { * @param id The graphic id. */ public void sendGraphic(int id) { - player.getUpdateMasks().register(EntityFlag.SpotAnim, new Graphics(id)); + player.getUpdateMasks().register(EntityFlag.SpotAnim, new Graphics(id)); } /** @@ -395,7 +396,7 @@ public final class PacketDispatch { * @param height The graphic height. */ public void sendGraphic(int id, int height) { - player.getUpdateMasks().register(EntityFlag.SpotAnim, new Graphics(id, height)); + player.getUpdateMasks().register(EntityFlag.SpotAnim, new Graphics(id, height)); } public void sendVarClient(int id, int value, boolean cs2) { PacketRepository.send(Config.class, new ConfigContext(player, id, value, cs2)); diff --git a/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java b/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java index 2bda2ca57..40ba72ab1 100644 --- a/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java +++ b/Server/src/main/core/game/node/entity/player/link/emote/Emotes.java @@ -106,7 +106,7 @@ public enum Emotes { @Override public void play(Player player) { if(player.getLocation().getRegionId() == 13206 && !player.getAttribute("mistag-greeted", false)) { - RegionManager.getLocalNpcs(player).forEach(npc -> { + RegionManager.getLocalNPCs(player.getLocation()).forEach(npc -> { if (npc.getId() == 2084 && npc.getLocation().withinDistance(player.getLocation(), 3) && player.getQuestRepository().getQuest(Quests.THE_LOST_TRIBE).getStage(player) == 45) { player.getDialogueInterpreter().open(2084,npc,"greeting"); player.setAttribute("/save:mistag-greeted",true); @@ -422,4 +422,4 @@ public enum Emotes { return lockedMessage; } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/node/entity/player/link/prayer/Prayer.java b/Server/src/main/core/game/node/entity/player/link/prayer/Prayer.java index 8dcdf8265..4f2780a7b 100644 --- a/Server/src/main/core/game/node/entity/player/link/prayer/Prayer.java +++ b/Server/src/main/core/game/node/entity/player/link/prayer/Prayer.java @@ -113,14 +113,17 @@ public final class Prayer { } if (player.getProperties().isMultiZone()) { @SuppressWarnings("rawtypes") - List targets = null; + List targets; if (killer instanceof NPC) { - targets = RegionManager.getSurroundingNPCs(player, player, killer); + targets = RegionManager.getLocalNPCs(player.getLocation(), 1); } else { - targets = RegionManager.getSurroundingPlayers(player, player, killer); + targets = RegionManager.getLocalPlayers(player.getLocation(), 1); } for (Object o : targets) { Entity entity = (Entity) o; + if (entity == player) { + continue; + } if (entity.isAttackable(player, CombatStyle.MAGIC, false)) { entity.getImpactHandler().manualHit(player, 1 + RandomFunction.randomize(maximum), HitsplatType.NORMAL); } diff --git a/Server/src/main/core/game/node/entity/skill/Skills.java b/Server/src/main/core/game/node/entity/skill/Skills.java index 06a978589..5b8b30b5c 100644 --- a/Server/src/main/core/game/node/entity/skill/Skills.java +++ b/Server/src/main/core/game/node/entity/skill/Skills.java @@ -252,9 +252,9 @@ public final class Skills { staticLevels[slot] = newLevel; if (entity instanceof Player) { - player.updateAppearance(); - LevelUp.levelup(player, slot, amount); - updateCombatLevel(); + player.updateAppearance(); + LevelUp.levelup(player, slot, amount); + updateCombatLevel(); } } if (entity instanceof Player) { @@ -303,11 +303,11 @@ public final class Skills { mod *= 1.5; } //Grand Exchange region XP boost. - if(entity.getViewport().getRegion().getRegionId() == 12598){ + if(entity.getLocation().getRegion().getRegionId() == 12598){ mod += 1.5; } // Pest control, XP halved during the game - if (entity.getViewport().getRegion().getRegionId() == 10536) { + if (entity.getLocation().getRegion().getRegionId() == 10536) { mod *= .5; } if (SystemManager.getSystemConfig().isDoubleExp()) { diff --git a/Server/src/main/core/game/node/item/GroundItemManager.java b/Server/src/main/core/game/node/item/GroundItemManager.java index 464dbbe25..98bc91ee3 100644 --- a/Server/src/main/core/game/node/item/GroundItemManager.java +++ b/Server/src/main/core/game/node/item/GroundItemManager.java @@ -3,6 +3,7 @@ package core.game.node.item; import core.game.node.entity.player.Player; import core.game.world.GameWorld; import core.game.world.map.Location; +import core.game.world.map.RegionChunk; import core.game.world.map.RegionManager; import core.game.world.update.flag.chunk.ItemUpdateFlag; import core.net.packet.PacketRepository; @@ -81,7 +82,7 @@ public final class GroundItemManager { item.getPlugin().remove(item.getDropper(), item, ItemPlugin.DROP); } item.setRemoved(false); - RegionManager.getRegionPlane(item.getLocation()).add(item); + RegionManager.getRegionChunk(item.getLocation()).add(item); if (GROUND_ITEMS.add(item)) { return item; } @@ -97,7 +98,7 @@ public final class GroundItemManager { return null; } GROUND_ITEMS.remove(item); - RegionManager.getRegionPlane(item.getLocation()).remove(item); + RegionManager.getRegionChunk(item.getLocation()).remove(item); if (item.isAutoSpawn()) { item.respawn(); } @@ -112,7 +113,18 @@ public final class GroundItemManager { * @return The ground item, or {@code null} if the ground item wasn't found. */ public static GroundItem get(int itemId, Location location, Player player) { - return RegionManager.getRegionPlane(location).getItem(itemId, location, player); + RegionChunk chunk = RegionManager.getRegionChunk(location); + for (GroundItem item : chunk.getItems()) { + if (item.getId() == itemId && location.equals(item.getLocation()) && !item.isRemoved()) { + if (!item.isPrivate()) { + return item; + } + if (player != null && item.droppedBy(player)) { + return item; + } + } + } + return null; } /** @@ -155,7 +167,7 @@ public final class GroundItemManager { } } if (!item.isRemoved()) { - RegionManager.getRegionPlane(item.getLocation()).remove(item); + RegionManager.getRegionChunk(item.getLocation()).remove(item); } } else if (!item.isRemainPrivate() && item.getDecayTime() - GameWorld.getTicks() == 100) { RegionManager.getRegionChunk(item.getLocation()).flag(new ItemUpdateFlag(item, ItemUpdateFlag.CONSTRUCT_TYPE)); diff --git a/Server/src/main/core/game/node/scenery/SceneryBuilder.java b/Server/src/main/core/game/node/scenery/SceneryBuilder.java index 3dac14bf0..304403930 100644 --- a/Server/src/main/core/game/node/scenery/SceneryBuilder.java +++ b/Server/src/main/core/game/node/scenery/SceneryBuilder.java @@ -23,7 +23,7 @@ public final class SceneryBuilder { /** * Replaces a scenery. * - * @param remove The object to remove. + * @param remove The object to remove. * @param construct The object to add. * @return {@code True} if successful. */ @@ -34,9 +34,9 @@ public final class SceneryBuilder { /** * Replaces a scenery. * - * @param remove The object to remove. + * @param remove The object to remove. * @param construct The object to add. - * @param clip If clipping should be adjusted. + * @param clip If clipping should be adjusted. * @return {@code True} if successful. */ public static boolean replace(Scenery remove, Scenery construct, boolean clip, boolean permanent) { @@ -72,8 +72,8 @@ public final class SceneryBuilder { /** * Replaces the object client sided alone. * - * @param remove The object to remove. - * @param construct The object to replace with. + * @param remove The object to remove. + * @param construct The object to replace with. * @param restoreTicks The restoration ticks. * @return {@code True} if successful. */ @@ -94,8 +94,8 @@ public final class SceneryBuilder { /** * Replaces a scenery temporarily. * - * @param remove The object to remove. - * @param construct The object to add. + * @param remove The object to remove. + * @param construct The object to add. * @param restoreTicks The amount of ticks before the object gets restored. * @return {@code True} if successful. */ @@ -106,8 +106,8 @@ public final class SceneryBuilder { /** * Replaces a scenery temporarily. * - * @param remove The object to remove. - * @param construct The object to add. + * @param remove The object to remove. + * @param construct The object to add. * @param restoreTicks The amount of ticks before the object gets restored. * @return {@code True} if successful. */ @@ -164,7 +164,7 @@ public final class SceneryBuilder { * * @param object The object to add. * @param ticks The amount of ticks this object should last for (-1 for - * permanent). + * permanent). * @return {@code True} if successful. */ public static Constructed add(Scenery object, int ticks, final GroundItem... items) { @@ -189,29 +189,6 @@ public final class SceneryBuilder { return constructed; } - /** - * Removes all objects within a box - * @param objectId - the object id to remove - * @param southWest - * @param northEast - * @return - */ - public static boolean removeAll(int objectId, Location southWest, Location northEast) { - if (southWest.getX() > northEast.getX() || southWest.getY() > northEast.getY()) - return false; - - int differenceX = northEast.getX() - southWest.getX(); - int differenceY = northEast.getY() - southWest.getY(); - - for (int x = 0; x <= differenceX; x++) { - for (int y = 0; y <= differenceY; y++){ - Scenery object = new Scenery(objectId, Location.create(southWest.getX() + x, southWest.getY() + y, southWest.getZ())); - remove(object); - } - } - return true; - } - /** * Removes a scenery. * @@ -234,7 +211,7 @@ public final class SceneryBuilder { /** * Removes a scenery. * - * @param object the object. + * @param object the object. * @param respawnTicks the respawn ticks. * @return {@code True}if removed. */ diff --git a/Server/src/main/core/game/system/command/rottenpotato/RottenPotatoExtraDialogue.kt b/Server/src/main/core/game/system/command/rottenpotato/RottenPotatoExtraDialogue.kt index 5528ecf20..8281ef994 100644 --- a/Server/src/main/core/game/system/command/rottenpotato/RottenPotatoExtraDialogue.kt +++ b/Server/src/main/core/game/system/command/rottenpotato/RottenPotatoExtraDialogue.kt @@ -62,7 +62,7 @@ class RottenPotatoExtraDialogue(player: Player? = null) : core.game.dialogue.Dia end() sendInputDialogue(player, InputType.STRING_LONG,"Enter the chat message:"){ value -> val msg = value as String - RegionManager.getLocalNpcs(player).forEach { + RegionManager.getLocalNPCs(player.location).forEach { it.sendChat(msg) } } @@ -71,7 +71,7 @@ class RottenPotatoExtraDialogue(player: Player? = null) : core.game.dialogue.Dia //Kill all nearby NPCs 5 -> { end() - RegionManager.getLocalNpcs(player).forEach { + RegionManager.getLocalNPCs(player.location).forEach { it.finalizeDeath(player) } } diff --git a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt index 25ef32fef..780319bc3 100644 --- a/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/DevelopmentCommandSet.kt @@ -31,7 +31,7 @@ import core.tools.Log import core.game.node.entity.player.info.Rights import core.game.node.entity.skill.Skills import core.game.world.map.Location -import core.game.world.map.RegionManager.getLocalEntitys +import core.game.world.map.RegionManager import core.game.world.repository.Repository import org.json.simple.JSONArray import kotlin.collections.set @@ -43,6 +43,7 @@ import content.global.activity.penguinhns.PenguinManager.Companion.spawner import content.global.activity.penguinhns.PenguinManager.Companion.tagMapping import content.global.activity.penguinhns.PenguinManager.Companion.updateStoreFile import core.ServerStore.Companion.toJSONArray +import core.game.world.map.RegionManager.getLocalEntities import org.rs09.consts.NPCs @Initializable @@ -120,7 +121,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { return@define } - define("cs2", Privilege.ADMIN, "::cs2 id args", "Allows you to call arbitrary cs2 scripts during runtime") {player, args -> + define("cs2", Privilege.ADMIN, "::cs2 id args", "Allows you to call arbitrary cs2 scripts during runtime") {player, args -> var scriptArgs = ArrayList() if (args.size == 2) { runcs2(player, args[1].toIntOrNull() ?: return@define) @@ -156,7 +157,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { } define("region", Privilege.STANDARD, "", "Prints your current Region ID.") {player, args -> - sendMessage(player, "Region ID: ${player.viewport.region.regionId}") + sendMessage(player, "Region ID: ${player.location.regionId}") } define("spellbook", Privilege.ADMIN, "::spellbook book ID (0 = MODERN, 1 = ANCIENTS, 2 = LUNARS)", "Swaps your spellbook to the given book ID."){player, args -> @@ -376,6 +377,28 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { player.dialogueInterpreter.sendDialogues(player, id, "Expression ID: $id") } + define("tileinfo", Privilege.ADMIN, "::tileinfo", "Prints out your current tile's clipping flags and entities on it.") { player, args -> + if (args.size != 1) reject(player, "::tileinfo doesn't take arguments.") + sendMessage(player, "Location: ${player.location}") + sendMessage(player, "Clipping: ${RegionManager.getClippingFlag(player.location, false)}") + sendMessage(player, "Projectile: ${RegionManager.getClippingFlag(player.location, true)}") + sendMessage(player, "${player.location.chunk.players.size} players and ${player.location.chunk.npcs.size} npcs on this chunk.") + sendMessage(player, "Entities on this tile:") + for (p in RegionManager.getLocalPlayers(player.location, 0)) { + sendMessage(p, " player ${player.username}") + } + for (npc in RegionManager.getLocalNPCs(player.location, 0)) { + sendMessage(player, " npc ${npc.name}") + } + sendMessage(player, "Entities within render distance:") + for (p in RegionManager.getLocalPlayers(player.location)) { + sendMessage(p, " player ${player.username} at ${player.location}") + } + for (npc in RegionManager.getLocalNPCs(player.location)) { + sendMessage(player, " npc ${npc.name} at ${npc.location}}") + } + } + define("timers", Privilege.ADMIN, "::timers", "Print out timers") { player, args -> player.sendMessage("Active timers:") for(timer in player.timers.activeTimers) { @@ -466,7 +489,7 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { spawnedOrdinals.forEach { val peng = Penguin.values()[it] - val nearNPCs = getLocalEntitys(peng.location,1) + val nearNPCs = getLocalEntities(peng.location,1) nearNPCs.forEach { npc -> if (npc.id in penguinNPCs) { poofClear(npc as NPC) @@ -507,6 +530,5 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) { val pengCoords = peng.location player.debug("Penguin spawned at:$pengCoords") } - - } + } } diff --git a/Server/src/main/core/game/system/command/sets/FunCommandSet.kt b/Server/src/main/core/game/system/command/sets/FunCommandSet.kt index 05b59c153..c65db80df 100644 --- a/Server/src/main/core/game/system/command/sets/FunCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/FunCommandSet.kt @@ -27,7 +27,6 @@ import org.rs09.consts.Sounds import java.awt.HeadlessException import java.awt.Toolkit import java.awt.datatransfer.StringSelection -import kotlin.streams.toList @Initializable class FunCommandSet : CommandSet(Privilege.ADMIN) { @@ -99,7 +98,7 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) { if (args.size < 2) { reject(player, "Syntax error: ::npcanim ") } - npcs = RegionManager.getLocalNpcs(player.location, 10) + npcs = RegionManager.getLocalNPCs(player.location, 10) for (n in npcs) { n.lock(6) n.faceTemporary(player, 6) @@ -356,10 +355,13 @@ class FunCommandSet : CommandSet(Privilege.ADMIN) { if (args.size != 2) reject(player, "Usage: ::barrage radius[max = 50]") val radius = if (args[1].toInt() > 50) 50 else args[1].toInt() - val nearbyPlayers = RegionManager.getLocalPlayers(player, radius).stream().filter { p: Player -> p.username != player.username }.toList() + val nearbyPlayers = RegionManager.getLocalPlayers(player.location, radius) animate(player, 1978) playGlobalAudio(player.location, Sounds.ICE_CAST_171) for (p in nearbyPlayers) { + if (p.name == player.name) { + continue + } playGlobalAudio(p.location, Sounds.ICE_BARRAGE_IMPACT_168, 20) val impactAmount = if (p.skills.lifepoints < 10 ) 0 else RandomFunction.getRandom(3) impact(p, impactAmount, ImpactHandler.HitsplatType.NORMAL) diff --git a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt index 281491ae2..56ffc13df 100644 --- a/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/MiscCommandSet.kt @@ -93,7 +93,7 @@ class MiscCommandSet : CommandSet(Privilege.ADMIN){ */ define("loc", Privilege.STANDARD, "", "Prints quite a lot of information about your current location."){ player, _-> val l = player.location - val r = player.viewport.region + val r = l.region var obj: Scenery? = null notify(player,"Absolute: " + l + ", regional: [" + l.localX + ", " + l.localY + "], chunk: [" + l.chunkOffsetX + ", " + l.chunkOffsetY + "], flag: [" + RegionManager.isTeleportPermitted(l) + ", " + RegionManager.getClippingFlag(l) + ", " + RegionManager.isLandscape(l) + "].") notify(player,"Region: [id=" + l.regionId + ", active=" + r.isActive + ", instanced=" + (r is DynamicRegion) + "], obj=" + RegionManager.getObject(l) + ".") diff --git a/Server/src/main/core/game/system/command/sets/SpawnCommandSet.kt b/Server/src/main/core/game/system/command/sets/SpawnCommandSet.kt index 468bdaf96..0e2151425 100644 --- a/Server/src/main/core/game/system/command/sets/SpawnCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/SpawnCommandSet.kt @@ -3,13 +3,17 @@ package core.game.system.command.sets import core.api.log import core.api.sendMessage import core.cache.Cache -import core.game.node.scenery.Scenery -import core.game.node.scenery.SceneryBuilder import core.game.node.entity.npc.NPC import core.game.node.item.Item +import core.game.node.scenery.Constructed +import core.game.node.scenery.Scenery +import core.game.node.scenery.SceneryBuilder import core.game.system.command.CommandPlugin -import core.plugin.Initializable import core.game.system.command.Privilege +import core.game.world.map.RegionManager +import core.game.world.map.RegionManager.getObject +import core.game.world.map.RegionManager.getRegionChunk +import core.plugin.Initializable import core.tools.Log import java.awt.Toolkit import java.awt.datatransfer.StringSelection @@ -142,5 +146,55 @@ class SpawnCommandSet : CommandSet(Privilege.ADMIN){ } } } + + define("removeobject", Privilege.ADMIN, "::removeobject", "Removes the first scenery at your current coordinates (the meaning of 'the first' is currently arbitrary, do not use this in production)") { player, args -> + if (args.size != 1) reject(player, "::removeobject doesn't support arguments") + val obj = getObject(player.location) + if (obj == null) { + sendMessage(player, "All ten objects on the tile were null.") + return@define + } + sendMessage(player, "The first object found on the tile was ${obj.id}; it will now be removed.") + SceneryBuilder.remove(obj) + } + + define("objects", Privilege.STANDARD, "::objects", "Prints a list of all ten sceneries at your current coordinates") { player, args -> + if (args.size != 1) reject(player, "::objects doesn't support arguments") + val chunk = getRegionChunk(player.location) + val region = RegionManager.forId(player.location.regionId) + fun dump(label: String, objects: List) { + sendMessage(player, "--- $label ---") + val nulls = ArrayList(10) + for (i in 0 until objects.size) { + val o = objects[i] + if (o == null) { + nulls.add(i) + } else { + val c = if (o is Constructed) "C" else "" + val r = if (o.isRenderable) "R" else "" + val a = if (o.isActive) "A" else "" + var props = c + r + a + if (props.length > 0) { + props = " *$props" + } + sendMessage(player, " $i: $o$props") + } + } + if (nulls.isNotEmpty()) { + sendMessage(player, " ${nulls.joinToString()}: null") + } + } + val stat = ArrayList(10) + for (i in 0 until chunk.statObjects.size) { + val obj = chunk.statObjects[i][player.location.chunkOffsetX][player.location.chunkOffsetY] + if (obj != null) { + stat.add(obj) + } + } + dump("Chunk static objects", stat) + dump("Chunk dynamic objects", chunk.getObjects(player.location.chunkOffsetX, player.location.chunkOffsetY).asList()) + dump("RegionManager", listOf(getObject(player.location))) //getObject can only get one + sendMessage(player, "--- That's all, folks! ---") + } } } diff --git a/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt b/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt index 30e4107c9..e8d7b84f3 100644 --- a/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt @@ -100,69 +100,6 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){ player.properties.teleportLocation = Location.create(args[1].toInt(), args[2].toInt(), if (args.size > 3) args[3].toInt() else 0) } - /** - * Teleport to the first object with the given name in the given regionX regionY - */ - define("teleobj", Privilege.ADMIN, "::teleobj RX_RY OBJ NAME", "Teleports to the first object with the given name."){player, args -> - if(args.size < 3) reject(player, "Usage: regionX_regionY Object Name") - var objName = "" - for(i in 2 until args.size) objName += (args[i] + if(i + 1 == args.size) "" else " ") - - val tokens = args[1].split("_") - if(tokens.size != 2) reject(player, "Usage: regionX_regionY Object Name") - val regionX = tokens[0].toInt() - val regionY = tokens[1].toInt() - - val regionId = (regionX shl 8) or regionY - val region = RegionManager.forId(regionId) - - GlobalScope.launch { - for (plane in region.planes) { - for (objects in plane.objects.filterNotNull()) { - for (parent in objects.filterNotNull()) { - if (parent.childs != null) { - for (obj in parent.childs.filterNotNull()) { - if (obj.name.equals(objName, ignoreCase = true)) { - player.properties.teleportLocation = obj.location - return@launch - } - } - } else { - if (parent.name.equals(objName, ignoreCase = true)) { - player.properties.teleportLocation = parent.location - return@launch - } - } - } - } - } - } - } - - /** - * Finds a list of objects/sceneries in a region - */ - define("findobjs", Privilege.ADMIN, "::findobjs REGION ID SCENERY ID", "Finds all locations of scenery objects of id."){player, args -> - if(args.size < 4) reject(player, "Usage: region_id scenery_id") - val regionId = args[1].toInt() - val sceneryId = args[2].toInt() - val sceneryIdEnd = args[3].toInt() - - val region = RegionManager.forId(regionId) - - GlobalScope.launch { - for (plane in region.planes) { - for (objects in plane.objects.filterNotNull()) { - for (parent in objects.filterNotNull()) { - if (parent.id in sceneryId..sceneryIdEnd) { - println(parent.location) - } - } - } - } - } - } - /** * Teleport to a specific player */ diff --git a/Server/src/main/core/game/system/config/ConfigParser.kt b/Server/src/main/core/game/system/config/ConfigParser.kt index db7e1b0f3..00c8e72e7 100644 --- a/Server/src/main/core/game/system/config/ConfigParser.kt +++ b/Server/src/main/core/game/system/config/ConfigParser.kt @@ -16,6 +16,7 @@ class ConfigParser : Commands { ItemConfigParser().load() ObjectConfigParser().load() XteaParser().load() + ObjectOverrideParser().load() InterfaceConfigParser().load() } fun postPlugin() { @@ -31,7 +32,12 @@ class ConfigParser : Commands { } fun reloadConfigs(callback: () -> Unit) { - GlobalScope.launch { + GlobalScope.launch { + RegionManager.apply { r -> + r.addScenery.clear() + r.removeScenery.clear() + } + Repository.npcs.toTypedArray().forEach { npc -> npc.isRespawn = false npc.clear() @@ -41,7 +47,7 @@ class ConfigParser : Commands { GroundItemManager.getItems().toTypedArray().forEach {gi -> GroundItemManager.getItems().remove(gi) - RegionManager.getRegionPlane(gi.location).remove(gi) + RegionManager.getRegionChunk(gi.location).remove(gi) } prePlugin() diff --git a/Server/src/main/core/game/system/config/ObjectOverrideParser.kt b/Server/src/main/core/game/system/config/ObjectOverrideParser.kt new file mode 100644 index 000000000..68705d7ca --- /dev/null +++ b/Server/src/main/core/game/system/config/ObjectOverrideParser.kt @@ -0,0 +1,57 @@ +package core.game.system.config + +import core.ServerConstants +import core.api.log +import core.game.node.scenery.Scenery +import core.game.world.map.Location +import core.game.world.map.RegionManager +import core.tools.Log +import org.json.simple.JSONArray +import org.json.simple.JSONObject +import org.json.simple.parser.JSONParser +import java.io.FileReader + +class ObjectOverrideParser { + val parser = JSONParser() + var reader: FileReader? = null + fun load() { + var count = 0 + reader = FileReader(ServerConstants.CONFIG_PATH + "object_overrides.json") + val overridelist = parser.parse(reader) as JSONArray + for (entry in overridelist) { + val e = entry as JSONObject + + // Mandatory fields + val mode = e["mode"].toString() + val id = e["id"].toString().toInt() + val loc = Location.fromString(e["location"].toString()) + + // Optional fields + val type = e["type"]?.toString()?.toInt() ?: 10 + val direction = e["direction"]?.toString() ?: "n" + + // Now create a Scenery object and assign it to its region + val rotation = when (direction) { + "n" -> 1 + "ne" -> 2 + "nw" -> 0 + "w" -> 3 + "e" -> 4 + "sw" -> 5 + "se" -> 7 + "s" -> 6 + else -> 1 + } + val obj = Scenery(id, loc, type, rotation) + val region = RegionManager.forId(loc.regionId) + when (mode) { + "remove" -> region.removeScenery.add(obj) //type and rotation are currently ignored, but this can be changed in Region.java if needed + "add" -> region.addScenery.add(obj) + else -> log(this::class.java, Log.ERR, "Ignored unknown ObjectOverride mode $mode!") + } + count++ + } + log(this::class.java, Log.FINE, "Parsed $count object overrides.") + } +} + diff --git a/Server/src/main/core/game/world/map/BuildRegionChunk.java b/Server/src/main/core/game/world/map/BuildRegionChunk.java deleted file mode 100644 index 008937301..000000000 --- a/Server/src/main/core/game/world/map/BuildRegionChunk.java +++ /dev/null @@ -1,336 +0,0 @@ -package core.game.world.map; - - -import core.game.node.entity.player.Player; -import core.game.node.item.GroundItem; -import core.game.node.item.Item; -import core.game.node.scenery.Constructed; -import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; -import core.tools.Log; -import core.tools.SystemLogger; -import core.game.world.map.build.LandscapeParser; -import core.net.packet.IoBuffer; -import core.net.packet.out.ClearScenery; -import core.net.packet.out.ConstructGroundItem; -import core.net.packet.out.ConstructScenery; - -import static core.api.ContentAPIKt.log; - -import java.util.ArrayList; -import java.util.Arrays; - -/** - * A region chunk, used for easily modifying objects. - * @author Emperor - * - */ -public class BuildRegionChunk extends RegionChunk { - - /** - * The maximum amount of objects to be stored on one tile in the chunk. - */ - public static final int ARRAY_SIZE = 10; - - /** - * The list of changes made. - */ - private final Scenery[][][] objects; - - /** - * Constructs a new {@code BuildRegionChunk} {@code Object} - * @param base The base location. - * @param rotation The rotation. - * @param plane The region plane. - */ - public BuildRegionChunk(Location base, int rotation, RegionPlane plane) { - super(base, rotation, plane); - this.objects = new Scenery[ARRAY_SIZE][8][8]; - } - - public BuildRegionChunk(Location base, int rotation, RegionPlane plane, Scenery[][] objects) { - this(base, rotation, plane); - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - if(objects[x][y] != null) { - this.objects[0][x][y] = new Scenery(objects[x][y]); - } - } - } - } - - @Override - protected boolean appendUpdate(Player player, IoBuffer buffer) { - boolean updated = false;//super.appendUpdate(player, buffer); - for (int i = 0; i < objects.length; i++) { - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - Scenery o = objects[i][x][y]; - if (o instanceof Constructed) { - ConstructScenery.write(buffer, o); - updated = true; - } - else if (o != null && !o.isRenderable()) { - ClearScenery.write(buffer, o); - updated = true; - } - } - } - } - ArrayList totalItems = drawItems(items, player); - for (GroundItem item : totalItems) { - if (item != null && item.isActive() && item.getLocation() != null) { - if (!item.isPrivate() || item.droppedBy(player)) { - ConstructGroundItem.write(buffer, item); - updated = true; - } - } - } - return updated; - } - - @Override - public void rotate(Direction direction) { - if (rotation != 0) { - log(this.getClass(), Log.ERR, "Region chunk was already rotated!"); - return; - } - Scenery[][][] copy = new Scenery[ARRAY_SIZE][SIZE][SIZE]; - int baseX = currentBase.getLocalX(); - int baseY = currentBase.getLocalY(); - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - for (int i = 0; i < objects.length; i++) { - Scenery object = copy[i][x][y] = objects[i][x][y]; - if (object != null) { - SceneryBuilder.remove(object); - this.remove(object); - } - } - } - } - clear(); - switch(direction) { - case NORTH: rotation = 0; break; - case EAST: rotation = 1; break; - case SOUTH: rotation = 2; break; - case WEST: rotation = 3; break; - default: rotation = (direction.toInteger() + (direction.toInteger() % 2 == 0 ? 2 : 0)) % 4; - log(this.getClass(), Log.ERR, "Attempted to rotate a chunk in a non-cardinal direction - using fallback rotation code. This should be investigated!"); - break; - }; - for (int i = 0; i < objects.length; i++) { - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - Scenery object = copy[i][x][y]; - if (object != null) { - int[] pos = getRotatedPosition(x, y, object.getDefinition().getSizeX(), object.getDefinition().getSizeY(), object.getRotation(), rotation); - Scenery obj = object.transform(object.getId(), (object.getRotation() + rotation) % 4, object.getLocation().transform(pos[0] - x, pos[1] - y, 0)); - if (object instanceof Constructed) { - obj = obj.asConstructed(); - } - obj.setActive(object.isActive()); - obj.setRenderable(object.isRenderable()); - LandscapeParser.flagScenery(plane, baseX + pos[0], baseY + pos[1], obj, true, true); - } - } - } - } - } - - @Override - public BuildRegionChunk copy(RegionPlane plane) { - BuildRegionChunk chunk = new BuildRegionChunk(base, rotation, plane); - for (int i = 0; i < chunk.objects.length; i++) { - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - Scenery o = objects[i][x][y]; - if (o instanceof Constructed) { - chunk.objects[i][x][y] = o.transform(o.getId(), o.getRotation()).asConstructed(); - } - else if (o != null) { - chunk.objects[i][x][y] = o.transform(o.getId()); - chunk.objects[i][x][y].setActive(o.isActive()); - chunk.objects[i][x][y].setRenderable(o.isRenderable()); - } - } - } - } - return chunk; - } - - @Override public void rebuildFlags(RegionPlane from) { - for (int x = 0; x < 8; x++) { - for (int y = 0; y < 8; y++) { - Location loc = currentBase.transform(x,y,0); - Location fromLoc = base.transform(x,y,0); - plane.getFlags().getLandscape()[loc.getLocalX()][loc.getLocalY()] = from.getFlags().getLandscape()[fromLoc.getLocalX()][fromLoc.getLocalY()]; - plane.getFlags().clearFlag(x, y); - for (int i = 0; i < ARRAY_SIZE; i++) { - Scenery obj = objects[i][x][y]; - if (obj != null) - LandscapeParser.applyClippingFlagsFor(plane, loc.getLocalX(), loc.getLocalY(), obj); - } - } - } - } - - @Override - public void clear() { - super.clear(); - for (int i = 0; i < objects.length; i++) { - for (int x = 0; x < objects[i].length; x++) { - for (int y = 0; y < objects[i][x].length; y++) { - objects[i][x][y] = null; - } - } - } - } - - /** - * Removes the scenery. - * @param object The object to remove. - */ - public void remove(Scenery object) { - int chunkX = object.getLocation().getChunkOffsetX(); - int chunkY = object.getLocation().getChunkOffsetY(); - Scenery current = null; - int index = -1; - int i = 0; - while ((current == null || current.getId() != object.getId()) && i < objects.length) { - current = objects[i++][chunkX][chunkY]; - if ((current == null || current.getId() < 1) && index == -1) { - index = i - 1; - } - } - if (current != null && current.equals(object)) { - current.setActive(false); - object.setRenderable(false); - } - else { - objects[index][chunkX][chunkY] = object; - } - object.setActive(false); - object.setRenderable(false); - } - - /** - * Adds the scenery. - * @param object The object to add. - */ - public void add(Scenery object) { - int chunkX = object.getLocation().getChunkOffsetX(); - int chunkY = object.getLocation().getChunkOffsetY(); - Scenery current = null; - int index = -1; - int i = 0; - while ((current == null || current.getId() != object.getId()) && i < objects.length) { - current = objects[i++][chunkX][chunkY]; - if ((current == null || current.getId() < 1) && index == -1) { - index = i - 1; - } - } - if (current != null && current.equals(object)) { - current.setActive(true); - current.setRenderable(true); - } - else if (index == -1) { - throw new IllegalStateException("Insufficient array length for storing object!"); - } - else { - objects[index][chunkX][chunkY] = object = object.asConstructed(); - } - object.setActive(true); - object.setRenderable(true); - } - - /** - * Stores an object on the region chunk. - * @param object The object. - */ - public void store(Scenery object) { - if (object == null) { - return; - } - int chunkX = object.getLocation().getChunkOffsetX(); - int chunkY = object.getLocation().getChunkOffsetY(); - for (int i = 0; i < objects.length; i++) { - Scenery stat = objects[i][chunkX][chunkY]; - if (stat == null || stat.getId() < 1) { - objects[i][chunkX][chunkY] = object; - object.setActive(true); - object.setRenderable(true); - return; - } - } - System.err.print("Objects - ["); - for (int i = 0; i < objects.length; i++) { - System.err.print(objects[i][chunkX][chunkY]); - if (i < objects.length - 1) { - System.err.print(", "); - } - } - log(this.getClass(), Log.ERR, "]!"); - throw new IllegalStateException("Insufficient array length for storing all objects! "); - } - - /** - * Gets the objects index for the given object id. - * @param x The x-coordinate on the region chunk. - * @param y The y-coordinate on the region chunk. - * @param objectId The object id. - */ - public int getIndex(int x, int y, int objectId) { - for (int i = 0; i < objects.length; i++) { - Scenery o = get(x, y, i); - if (o != null && ((objectId > -1 && o.getId() == objectId) || (objectId == -1 && o.getDefinition().hasOptions(false)))) { - return i; - } - } - return 0; - } - - /** - * Gets a scenery. - * @param x The chunk x-coordinate. - * @param y The chunk y-coordinate. - * @param index The index (0 = default). - * @return The object. - */ - public Scenery get(int x, int y, int index) { - return objects[index][x][y]; - } - - @Override - public Scenery[] getObjects(int chunkX, int chunkY) { - Scenery[] objects = new Scenery[ARRAY_SIZE]; - for (int i = 0; i < ARRAY_SIZE; i++) { - objects[i] = this.objects[i][chunkX][chunkY]; - } - return objects; - } - - /** - * Gets the objects. - * @param index The index. - * @return The objects array. - */ - public Scenery[][] getObjects(int index) { - return objects[index]; - } - - @Override - public void setCurrentBase(Location currentBase) { - for (int i = 0; i < objects.length; i++) { - for (int x = 0; x < objects[i].length; x++) { - for (int y = 0; y < objects[i][x].length; y++) { - if (objects[i][x][y] != null) { - Location newLoc = currentBase.transform(x, y, 0); - objects[i][x][y].setLocation(newLoc); - } - } - } - } - super.setCurrentBase(currentBase); - } -} diff --git a/Server/src/main/core/game/world/map/Location.kt b/Server/src/main/core/game/world/map/Location.kt index a202e4a49..0d2d01bb9 100644 --- a/Server/src/main/core/game/world/map/Location.kt +++ b/Server/src/main/core/game/world/map/Location.kt @@ -101,6 +101,8 @@ class Location(var hash: LocationHash) : Node(null, null) { // Derived variables. Please note the following isn't a 1-1 representation of what is officially used. // Region - (Officially: Map Square) 64x64 + /** The region. */ + val region: Region get() = RegionManager.forId(regionId) /** Unique index "key" (Officially: region_uid) for a 64x64 area. Made of x and y joined bitwise together. Used in xteas.json. */ val regionId: Int get() = x shr 6 shl 8 or (y shr 6) // Cuts off the end 6 bits of both x y and joins them together. E.g. 10392 /** The chunk x index for this position (x/8). For sets of 8x8 area. THIS IS NAMED WRONG, THIS IS A CHUNK(8) NOT REGION(64). */ @@ -116,7 +118,14 @@ class Location(var hash: LocationHash) : Node(null, null) { fun isInRegion(region: Int): Boolean = regionId == region // Chunk - (Officially: Zones) 8x8 + /** The chunk. */ + val chunk: RegionChunk get() = region.chunks[chunkX][chunkY][z] + /** The chunk base on the world map. */ val chunkBase: Location get() = create(regionX shl 3, regionY shl 3, z) + /** The ABSOLUTE chunk x index for this position. (Same as regionX, but named correctly.) */ + val absChunkX: Int get() = x shr 3 // shr 3 is essentially divide by 8 + /** The ABSOLUTE chunk y index for this position. (Same as regionY, but named correctly.) */ + val absChunkY: Int get() = y shr 3 // shr 3 is essentially divide by 8 /** The chunk x index for this position RELATIVE to a region[localX](x/8). THIS IS NOT GLOBAL CHUNK X. */ val chunkX: Int get() = localX shr 3 // shr 3 is essentially divide by 8 (note this is localX) /** The chunk y index for this position RELATIVE to a region[localY](y/8). THIS IS NOT GLOBAL CHUNK Y. */ @@ -136,8 +145,6 @@ class Location(var hash: LocationHash) : Node(null, null) { /** @return The local scene y-coordinate relative to another location's regionY. */ fun getSceneY(loc: Location): Int = y - (loc.regionY - 6 shl 3) - - /** @return The location incremented by another location's coordinates. (POTENTIAL Z PROBLEMS HERE) */ // TODO: THE FOLLOWING TRANSFORM HAS SHIT Z HANDLING. fun transform(l: Location): Location = Location(x + l.x, y + l.y, (z + l.z) % 4) @@ -148,7 +155,6 @@ class Location(var hash: LocationHash) : Node(null, null) { /** Location transformed by a Vector. Limit usage to more complicated functionality. */ fun transform(vector: Vector): Location = create(x + floor(vector.x).toInt(), y + floor(vector.y).toInt()) - /** @return True if this location is 1 tile N, W, S, or E of the node. THIS CAN BE REFACTORED OUT. */ fun isNextTo(node: Node): Boolean { val l = node.location @@ -167,7 +173,7 @@ class Location(var hash: LocationHash) : Node(null, null) { /** @return The straight-line(Euclidean) distance between this and another location. */ fun getDistance(other: Location): Double = getDistance(this, other) - /** @returns ArrayList of the 8 cardinal and diagonal tiles. Order is important and follows [Direction] indexing **/ + /** @returns ArrayList of the 8 cardinal and diagonal tiles. Order is important and follows [Direction] indexing */ val surroundingTiles: ArrayList get() { val locations = ArrayList() locations.add(transform(-1, -1, 0)) @@ -181,7 +187,7 @@ class Location(var hash: LocationHash) : Node(null, null) { return locations } - /** @returns ArrayList of the 4 cardinal direction tiles. Order is important and follows [Direction] indexing **/ + /** @returns ArrayList of the 4 cardinal direction tiles. Order is important and follows [Direction] indexing */ val cardinalTiles: ArrayList get() { val locations = ArrayList() locations.add(transform(-1, 0, 0)) @@ -191,7 +197,6 @@ class Location(var hash: LocationHash) : Node(null, null) { return locations } - /** * Gets the directional components of a movement step. * TODO: would prefer this in the other place. This doesn't exactly belong here since this isn't a common function for other instances of Location diff --git a/Server/src/main/core/game/world/map/Region.java b/Server/src/main/core/game/world/map/Region.java index ff87d8e6b..40e455aea 100644 --- a/Server/src/main/core/game/world/map/Region.java +++ b/Server/src/main/core/game/world/map/Region.java @@ -1,9 +1,12 @@ package core.game.world.map; import core.cache.Cache; +import core.game.node.Node; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.music.MusicZone; +import core.game.node.scenery.Scenery; +import core.game.node.scenery.SceneryBuilder; import core.game.system.communication.CommunicationInfo; import core.game.system.task.Pulse; import core.game.world.map.build.DynamicRegion; @@ -29,12 +32,6 @@ import static core.api.ContentAPIKt.log; * @author Emperor */ public class Region { - - /** - * The default size of a region. - */ - public static final int SIZE = 64; - /** * The region x-coordinate. */ @@ -46,9 +43,9 @@ public class Region { private final int y; /** - * The region planes. + * The chunks in this region. */ - private final RegionPlane[] planes = new RegionPlane[4]; + protected RegionChunk[][][] chunks = new RegionChunk[8][8][4]; /** * The activity pulse. @@ -73,7 +70,7 @@ public class Region { /** * Keeps track of players and time in region for tolerance purposes */ - private final HashMap tolerances = new HashMap<>(); + private final HashMap tolerances = new HashMap(); /** * If the region is active. @@ -106,9 +103,10 @@ public class Region { private boolean build; /** - * If all planes should be updated when in this region (instead of just current one). + * Any scenery overrides for this region */ - private boolean updateAllPlanes; + private ArrayList addScenery = new ArrayList<>(); + private ArrayList removeScenery = new ArrayList<>(); /** * Constructs a new {@code Region} {@code Object}. @@ -118,8 +116,14 @@ public class Region { public Region(int x, int y) { this.x = x; this.y = y; - for (int plane = 0; plane < 4; plane++) { - planes[plane] = new RegionPlane(this, plane); + Location swCorner = getBaseLocation(); + for (x = 0; x < 8; x++) { + for (y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + Location loc = swCorner.transform(x*8, y*8, z); + chunks[x][y][z] = new RegionChunk(loc, 0); + } + } } this.activityPulse = new Pulse(50) { @Override @@ -139,79 +143,57 @@ public class Region { return Location.create(x << 6, y << 6, 0); } + /** + * Gets the chunks. + * @return The chunks. + */ + public RegionChunk[][][] getChunks() { + return chunks; + } + /** * Adds a region zone to this region. * @param zone The region zone. */ public void add(RegionZone zone) { regionZones.add(zone); - for (RegionPlane plane : planes) { - for (NPC npc : plane.getNpcs()) { - npc.getZoneMonitor().updateLocation(npc.getLocation()); - } - for (Player p : plane.getPlayers()) { - p.getZoneMonitor().updateLocation(p.getLocation()); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + for (NPC npc : chunks[x][y][z].getNpcs()) { + npc.getZoneMonitor().updateLocation(npc.getLocation()); + } + for (Player player : chunks[x][y][z].getPlayers()) { + if (player != null) { + player.getZoneMonitor().updateLocation(player.getLocation()); + } + } + } } } } public void remove(RegionZone zone) { regionZones.remove(zone); - for (RegionPlane plane : planes) { - for (NPC npc : plane.getNpcs()) { - npc.getZoneMonitor().updateLocation(npc.getLocation()); - } - for (Player p : plane.getPlayers()) { - p.getZoneMonitor().updateLocation(p.getLocation()); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + for (NPC npc : chunks[x][y][z].getNpcs()) { + npc.getZoneMonitor().updateLocation(npc.getLocation()); + } + for (Player player : chunks[x][y][z].getPlayers()) { + player.getZoneMonitor().updateLocation(player.getLocation()); + } + } } } } - /** - * Adds a player to this region. - * @param player The player. - */ - public void add(Player player) { - planes[player.getLocation().getZ()].add(player); - tolerances.put(player.getUsername(), System.currentTimeMillis()); - flagActive(); - } - - /** - * Adds an npc to this region. - * @param npc The npc. - */ - public void add(NPC npc) { - planes[npc.getLocation().getZ()].add(npc); - } - - /** - * Removes an NPC from this region. - * @param npc The NPC. - */ - public void remove(NPC npc) { - RegionPlane plane = npc.getViewport().getCurrentPlane(); - if (plane != null && plane != planes[npc.getLocation().getZ()]) { - plane.remove(npc); - } - planes[npc.getLocation().getZ()].remove(npc); - } - - /** - * Removes a player from this region. - * @param player The player. - */ - public void remove(Player player) { - player.getViewport().getCurrentPlane().remove(player); - tolerances.remove(player.getUsername()); - checkInactive(); - } - /** * Checks if player is tolerated by enemies in this region */ - public boolean isTolerated(Player player){ - return System.currentTimeMillis() - tolerances.getOrDefault(player.getUsername(), System.currentTimeMillis()) > TimeUnit.MINUTES.toMillis(10); + public boolean isTolerated(Player player) { + return System.currentTimeMillis() - tolerances.getOrDefault(player.getName(), System.currentTimeMillis()) > TimeUnit.MINUTES.toMillis(10); } /** @@ -231,9 +213,13 @@ public class Region { if (isViewed()) { return false; } - for (RegionPlane p : planes) { - if (!p.getPlayers().isEmpty()) { - return false; + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + if (!chunks[x][y][z].getPlayers().isEmpty()) { + return false; + } + } } } if (runPulse) { @@ -246,14 +232,6 @@ public class Region { return true; } - /** - * Checks if this region has the inactivity flagging pulse running. - * @return {@code True} if so. - */ - public boolean isPendingRemoval() { - return activityPulse.isRunning(); - } - /** * Flags the region as active. */ @@ -262,10 +240,14 @@ public class Region { if (!active) { active = true; load(this); - for (RegionPlane r : planes) { - for (NPC n : r.getNpcs()) { - if (n.isActive()) { - Repository.addRenderableNPC(n); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + for (NPC npc : chunks[x][y][z].getNpcs()) { + if (npc.isActive()) { + Repository.addRenderableNPC(npc); + } + } } } } @@ -285,7 +267,7 @@ public class Region { * Flags the region as inactive. */ public boolean flagInactive() { - return flagInactive(false); + return flagInactive(false); } /** @@ -299,7 +281,7 @@ public class Region { /** * Loads the flags for a region. * @param r The region. - * @param build if all objects in this region should be stored (rather than just the ones with options). + * @param build If the region can be edited. */ public static void load(Region r, boolean build) { try { @@ -318,11 +300,13 @@ public class Region { return; } - byte[][][] mapscapeData = new byte[4][SIZE][SIZE]; - for (RegionPlane plane : r.planes) { - plane.getFlags().setLandscape(new boolean[SIZE][SIZE]); - //plane.getFlags().setClippingFlags(new int[SIZE][SIZE]); - //plane.getProjectileFlags().setClippingFlags(new int[SIZE][SIZE]); + byte[][][] mapscapeData = new byte[4][64][64]; + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + r.chunks[x][y][z].getFlags().setLandscape(new boolean[8][8]); + } + } } if (mapscapeId > -1) { ByteBuffer mapscape = ByteBuffer.wrap(Cache.getIndexes()[5].getCacheFile().getContainerUnpackedData(mapscapeId)); @@ -338,50 +322,63 @@ public class Region { } r.hasFlags = true; try { - LandscapeParser.parse(r, mapscapeData, ByteBuffer.wrap(landscape), build); + LandscapeParser.parse(r, r.chunks, mapscapeData, ByteBuffer.wrap(landscape), build); } catch (Throwable t) { new Throwable("Failed parsing region " + regionId + "!", t).printStackTrace(); } } - MapscapeParser.clipMapscape(r, mapscapeData); + MapscapeParser.clipMapscape(r, r.chunks, mapscapeData); + for (Scenery object : r.removeScenery) { + // Get the actual object, not the instance that's kept in the removeScenery array + Scenery realObject = RegionManager.getObject(object.getLocation()); //can be extended to take into account type and rotation if needed + if (realObject != null) { + SceneryBuilder.remove(realObject); + } + } + for (Scenery object : r.addScenery) { + SceneryBuilder.add(object); + } } catch (Throwable e) { e.printStackTrace(); } } - public static boolean unload(Region r) { - return unload(r, false); - } - /** * Unloads a region. * @param r The region. */ - public static boolean unload(Region r, boolean force) { + public boolean unload(Region r, boolean force) { if (!force && r.isViewed()) { log(CommunicationInfo.class, Log.ERR, "Players viewing region!"); r.flagActive(); return false; } - for (RegionPlane p : r.planes) { - if (!force && !p.getPlayers().isEmpty()) { - log(CommunicationInfo.class, Log.ERR, "Players still in region!"); - r.flagActive(); - return false; - } - } - for (RegionPlane p : r.planes) { - p.clear(); - if (!(r instanceof DynamicRegion)) { - for (NPC n : p.getNpcs()) { - n.onRegionInactivity(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + if (!force && !chunks[x][y][z].getPlayers().isEmpty()) { + log(CommunicationInfo.class, Log.ERR, "Players still in region!"); + r.flagActive(); + return false; + } } } } - if (r.isBuild()) - r.setLoaded(false); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + if (!(r instanceof DynamicRegion)) { + for (NPC npc : chunks[x][y][z].getNpcs()) { + npc.onRegionInactivity(); + } + } + chunks[x][y][z].clear(); + } + } + } + r.setLoaded(false); r.activityPulse.stop(); - return true; + return true; } /** @@ -426,17 +423,6 @@ public class Region { return active; } - /** - * Sets the active. - * @param active The active to set. - * @deprecated This should not be used, instead use the {@link #flagInactive()}, - * {@link #flagActive()} & {@link #checkInactive()} methods to safely change the activity state. - */ - @Deprecated - public void setActive(boolean active) { - this.active = active; - } - /** * Gets the region id. * @return The region id. @@ -469,14 +455,6 @@ public class Region { return y; } - /** - * Gets the planes. - * @return The planes. - */ - public RegionPlane[] getPlanes() { - return planes; - } - /** * Sets the region-wide music track. */ @@ -532,14 +510,6 @@ public class Region { return hasFlags; } - /** - * Sets the hasFlags. - * @param hasFlags The hasFlags to set. - */ - public void setHasFlags(boolean hasFlags) { - this.hasFlags = hasFlags; - } - /** * Sets the region time out duration. * @param ticks The amount of ticks before the region is flagged as inactive. @@ -564,14 +534,6 @@ public class Region { this.loaded = loaded; } - /** - * Sets the viewAmount. - * @param viewAmount The viewAmount to set. - */ - public void setViewAmount(int viewAmount) { - this.viewAmount = viewAmount; - } - /** * Gets the build. * @return the build @@ -588,19 +550,70 @@ public class Region { this.build = build; } - /** - * Gets the updateAllPlanes value. - * @return The updateAllPlanes. - */ - public boolean isUpdateAllPlanes() { - return updateAllPlanes; + public List assembleObjectList(int z) { + ArrayList list = new ArrayList<>(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + RegionChunk chunk = chunks[x][y][z]; + for (int offsetX = 0; offsetX < 8; offsetX++) { + for (int offsetY = 0; offsetY < 8; offsetY++) { + for (int i = 0; i < 4; i++) { + Scenery object = chunk.getObjects()[i][offsetX][offsetY]; + if (object != null) { + list.add(object); + } + } + } + } + } + } + return list; + } + + public List assembleNpcList(int z) { + ArrayList list = new ArrayList<>(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + RegionChunk chunk = chunks[x][y][z]; + list.addAll(chunk.getNpcs()); + } + } + return list; + } + + public List assemblePlayerList(int z) { + ArrayList list = new ArrayList<>(); + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + RegionChunk chunk = chunks[x][y][z]; + list.addAll(chunk.getPlayers()); + } + } + return list; + } + + public List assembleEntityList(int z) { + ArrayList list = new ArrayList<>(assembleObjectList(z)); + list.addAll(assemblePlayerList(z)); + list.addAll(assembleNpcList(z)); + return list; } /** - * Sets the updateAllPlanes value. - * @param updateAllPlanes The updateAllPlanes to set. + * Getter for region aggro tolerances. + * @return */ - public void setUpdateAllPlanes(boolean updateAllPlanes) { - this.updateAllPlanes = updateAllPlanes; + public HashMap getTolerances() { + return tolerances; + } + + /** + * Getters for addScenery and removeScenery. + */ + public ArrayList getAddScenery() { + return addScenery; + } + public ArrayList getRemoveScenery() { + return removeScenery; } } diff --git a/Server/src/main/core/game/world/map/RegionChunk.java b/Server/src/main/core/game/world/map/RegionChunk.java index 7b3fb71c8..7ee787878 100644 --- a/Server/src/main/core/game/world/map/RegionChunk.java +++ b/Server/src/main/core/game/world/map/RegionChunk.java @@ -1,19 +1,23 @@ package core.game.world.map; +import core.game.node.Node; +import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; import core.game.node.item.GroundItem; import core.game.node.item.Item; +import core.game.node.scenery.Constructed; import core.game.node.scenery.Scenery; +import core.game.node.scenery.SceneryBuilder; +import core.game.world.map.build.ChunkFlags; +import core.game.world.update.flag.chunk.ItemUpdateFlag; +import core.net.packet.PacketRepository; +import core.net.packet.context.BuildItemContext; +import core.net.packet.out.*; import core.tools.Log; -import core.tools.SystemLogger; import core.game.world.map.build.DynamicRegion; import core.game.world.map.build.LandscapeParser; import core.game.world.update.flag.UpdateFlag; import core.net.packet.IoBuffer; -import core.net.packet.out.ClearScenery; -import core.net.packet.out.ConstructGroundItem; -import core.net.packet.out.ConstructScenery; -import core.net.packet.out.UpdateAreaPosition; import java.util.ArrayList; import java.util.List; @@ -22,10 +26,15 @@ import static core.api.ContentAPIKt.log; /** * Represents a region chunk. - * @author Emperor + * @author Emperor, Player Name * */ public class RegionChunk { + /** + * The maximum amount of objects to be stored on one tile in the chunk. + * Four objects per tile is the authentic RuneTek engine limit. + */ + public static final int ARRAY_SIZE = 4; /** * The chunk size. @@ -42,20 +51,27 @@ public class RegionChunk { */ protected Location currentBase; - /** - * The region plane. - */ - protected RegionPlane plane; - /** * The items in this chunk. */ - protected List items; + protected List items = new ArrayList<>(); /** - * The scenerys in this chunk. + * The static objects in this chunk. Only used as a reference, do not act on these unless you are the landscape- + * parsing code. + * The game protocol requires us to send separate updates for dynamically added scenery and dynamically + * removed scenery. We implement this by maintaining two lists: one of static scenery, which contains the + * reference state obtained from the cache, and one of dynamic scenery, which is the actual current state of + * the sceneries on a chunk. This means that during landscape-parsing (and, crucially, only then), we need + * to add objects to both the static and dynamic lists. All object interactions in the game, however, only + * use the dynamic list (hence why that is just called 'objects'). */ - protected Scenery[][] objects; + protected Scenery[][][] statObjects; + + /** + * The (dynamic, actual) objects in this chunk. + */ + protected Scenery[][][] objects; /** * The rotation. @@ -65,28 +81,262 @@ public class RegionChunk { /** * The update flags. */ - private List> flags = new ArrayList<>(20); + private List> updateFlags = new ArrayList<>(20); + + /** + * The region flags. + */ + private ChunkFlags flags; + + /** + * The region projectile flags. + */ + private ChunkFlags projectileFlags; + + /** + * The players on this chunk. + */ + private final List players = new ArrayList<>(); + + /** + * The NPCs on this chunk. + */ + private final List npcs = new ArrayList<>(); /** * Constructs a new {@code RegionChunk} {@code Object}. * @param base The base location of the region chunk. * @param rotation The rotation. */ - public RegionChunk(Location base, int rotation, RegionPlane plane) { + public RegionChunk(Location base, int rotation) { this.base = base; this.currentBase = base; this.rotation = rotation; - this.plane = plane; - this.objects = new Scenery[SIZE][SIZE]; + this.statObjects = new Scenery[ARRAY_SIZE][SIZE][SIZE]; + this.objects = new Scenery[ARRAY_SIZE][SIZE][SIZE]; + this.flags = new ChunkFlags(base.getX(), base.getY(), base.getZ()); + this.projectileFlags = new ChunkFlags(base.getX(), base.getY(), base.getZ(), true); + } + + /** + * Corrects objects' Locations when copying them from a template region into an instance - public version. + */ + public void rebaseObjects() { + rebaseObjects(statObjects); + rebaseObjects(objects); + } + + /** + * Corrects objects' Locations when copying them from a template region into an instance - private version. + */ + private void rebaseObjects(Scenery[][][] objects) { + for (int i = 0; i < objects.length; i++) { + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + Scenery o = objects[i][x][y]; + if (o == null) { + continue; + } + o.setLocation(getCurrentBase().transform(x, y, 0)); + } + } + } + } + + /** + * Makes a deep copy of an object list - private version. + */ + private void copyObjects(Scenery[][][] src, Scenery[][][] dest) { + for (int i = 0; i < src.length; i++) { + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + Scenery o = src[i][x][y]; + if (o == null) { + continue; + } + Scenery copy = o.transform(o.getId()); + if (o instanceof Constructed) { + dest[i][x][y] = copy.asConstructed(); + } else { + dest[i][x][y] = copy; + } + dest[i][x][y].setActive(o.isActive()); + dest[i][x][y].setRenderable(o.isRenderable()); + } + } + } } /** * Copies the region chunk. - * @param plane The region plane. - * @return The region chunk. + * @return The destination chunk. */ - public BuildRegionChunk copy(RegionPlane plane) { - return new BuildRegionChunk(base, rotation, plane, this.objects); + public RegionChunk copy() { + RegionChunk chunk = new RegionChunk(base, rotation); + copyObjects(statObjects, chunk.statObjects); //note that the objects' locations have not been repointed to the new chunk yet, since we don't know _where_ the new chunk will be at this point + copyObjects(objects, chunk.objects); + return chunk; + } + + /** + * Adds the scenery to the static and dynamic object lists. You never want this unless you are the landscape-parsing + * code. + * @param object The object to add. + * @return The slot it was added into. + */ + public int addStatDyn(Scenery object, int chunkOffsetX, int chunkOffsetY) { + for (int i = 0; i < statObjects.length; i++) { + Scenery current = statObjects[i][chunkOffsetX][chunkOffsetY]; + if (current == null) { + statObjects[i][chunkOffsetX][chunkOffsetY] = object; + objects[i][chunkOffsetX][chunkOffsetY] = object.transform(object.getId()); //deep copy so that active/renderable flags don't synchronize across multiple copies of e.g. a POH + return i; + } + if (current.getId() == object.getId()) { + // It's possible that we already have this object. One instance of this was found at 1906, 5082, 0, + // where our cache has more than one copy of the same [Scenery 15349, [1906, 5082, 0], type=22, rot=1] + // object. Since authentically, the engine can only support one of the same type of object per tile, + // if the ID matches we can be confident that this is a duplicate. + return i; + } + } + throw new IllegalStateException("RC addStatDyn insufficient array length for storing object " + object); + } + + /** + * Adds the scenery to the dynamic object list. + * @param object The object to add. + * @return The slot it was added into. + */ + public int add(Scenery object) { + int chunkOffsetX = object.getLocation().getChunkOffsetX(); + int chunkOffsetY = object.getLocation().getChunkOffsetY(); + for (int i = 0; i < objects.length; i++) { + Scenery current = objects[i][chunkOffsetX][chunkOffsetY]; + if (current == null) { + objects[i][chunkOffsetX][chunkOffsetY] = object.asConstructed(); + object.setRenderable(true); + object.setActive(true); + return i; + } + if (current.equals(object)) { + // Just reactivate the old instance + current.setRenderable(true); + current.setActive(true); + return i; + } + } + throw new IllegalStateException("RC add insufficient array length for storing object " + object); + } + + /** + * Adds an NPC to this chunk. + * @param npc The NPC to add. + */ + public void add(NPC npc) { + npcs.add(npc); + } + + /** + * Adds a player to this chunk. + * @param player The player. + */ + public void addPlayer(Player player) { + players.add(player); + Region region = getCurrentBase().getRegion(); + region.getTolerances().put(player.getName(), System.currentTimeMillis()); + } + + /** + * Adds an item to this region. + * @param item The item. + */ + public void add(GroundItem item) { + items.add(item); + if (item.isPrivate()) { + if (item.getDropper() != null) { + PacketRepository.send(ConstructGroundItem.class, new BuildItemContext(item.getDropper(), item)); + } + return; + } + flag(new ItemUpdateFlag(item, ItemUpdateFlag.CONSTRUCT_TYPE)); + } + + /** + * Removes an NPC from this chunk. + * @param npc The NPC. + */ + public void remove(NPC npc) { + npcs.remove(npc); + } + + /** + * Removes a player from this chunk. + * @param player The player. + */ + public void removePlayer(Player player) { + players.remove(player); + Region region = getCurrentBase().getRegion(); + region.getTolerances().remove(player.getName()); + } + + /** + * Removes an item from this chunk. + * @param item The ground item. + */ + public void remove(GroundItem item) { + Location l = item.getLocation(); + if (!items.remove(item)) { + return; + } + if (item.isPrivate()) { + if (item.getDropper() != null && item.getDropper().isPlaying() && item.getDropper().getLocation().withinDistance(l)) { + PacketRepository.send(ClearGroundItem.class, new BuildItemContext(item.getDropper(), item)); + } + return; + } + flag(new ItemUpdateFlag(item, ItemUpdateFlag.REMOVE_TYPE)); + } + + /** + * Gets the npcs. + * @return The npcs. + */ + public List getNpcs() { + return npcs; + } + + /** + * Assembles a flat object list. + * @return The objects. + */ + public List assembleObjectList() { + ArrayList list = new ArrayList<>(ARRAY_SIZE); + for (int offsetX = 0; offsetX < 8; offsetX++) { + for (int offsetY = 0; offsetY < 8; offsetY++) { + for (int i = 0; i < ARRAY_SIZE; i++) { + Scenery object = objects[i][offsetX][offsetY]; + if (object != null) { + list.add(object); + } + } + } + } + return list; + } + + public List getEntities() { + List entities = new ArrayList<>(assembleObjectList()); + entities.addAll(npcs); + return entities; + } + + /** + * Gets the players. + * @return The players. + */ + public List getPlayers() { + return players; } /** @@ -94,18 +344,26 @@ public class RegionChunk { * @param flag The flag. */ public void flag(UpdateFlag flag) { - flags.add(flag); + updateFlags.add(flag); } /** * Clears the region chunk. */ public void clear() { - flags.clear(); - if (items != null && plane.getRegion() instanceof DynamicRegion) { + updateFlags.clear(); + Region region = RegionManager.forId(currentBase.getRegionId()); + if (items != null && region instanceof DynamicRegion) { items.clear(); items = null; } + for (int i = 0; i < objects.length; i++) { + for (int x = 0; x < objects[i].length; x++) { + for (int y = 0; y < objects[i][x].length; y++) { + statObjects[i][x][y] = objects[i][x][y] = null; + } + } + } } /** @@ -123,29 +381,26 @@ public class RegionChunk { * Writes the region chunk update data on the buffer. * @param player The player we're updating for. * @param buffer The buffer to write on. - * @return {@code True} if an update occured. + * @return {@code True} if an update occurred. */ protected boolean appendUpdate(Player player, IoBuffer buffer) { boolean updated = false; - int baseX = currentBase.getLocalX(); - int baseY = currentBase.getLocalY(); - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - Scenery dyn = objects[x][y]; - if (dyn == null || plane.getObjects() == null) { - continue; - } - Scenery stat = plane.getObjects()[baseX + x][baseY + y]; - if (!dyn.isRenderable() && stat != null) { - ClearScenery.write(buffer, stat); - updated = true; - } - else if (dyn != stat) { + for (int i = 0; i < objects.length; i++) { + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + Scenery dyn = objects[i][x][y]; + Scenery stat = statObjects[i][x][y]; + if (dyn == stat) { + continue; + } if (stat != null) { ClearScenery.write(buffer, stat); + updated = true; + } + if (dyn != null) { + ConstructScenery.write(buffer, dyn); + updated = true; } - ConstructScenery.write(buffer, dyn); - updated = true; } } } @@ -161,7 +416,6 @@ public class RegionChunk { return updated; } - public ArrayList drawItems(List items, Player player) { ArrayList totalItems = items != null ? new ArrayList(items) : new ArrayList(); @@ -225,89 +479,16 @@ public class RegionChunk { public void update(Player player) { if (isUpdated()) { IoBuffer buffer = UpdateAreaPosition.getChunkUpdateBuffer(player, currentBase); - Object[] flagsArray = flags.toArray(); + Object[] flagsArray = updateFlags.toArray(); int size = flagsArray.length; - for (int i = 0; i < size; i++) { - UpdateFlag flag = (UpdateFlag) flagsArray[i]; + for (Object o : flagsArray) { + UpdateFlag flag = (UpdateFlag) o; flag.writeDynamic(buffer, player); } player.getSession().write(buffer); } } - /** - * Rotates the chunk. - * @param direction The direction. - */ - public void rotate(Direction direction) { - if (rotation != 0) { - log(this.getClass(), Log.ERR, "Region chunk was already rotated!"); - return; - } - Scenery[][] copy = new Scenery[SIZE][SIZE]; - Scenery[][] staticCopy = new Scenery[SIZE][SIZE]; - int baseX = currentBase.getLocalX(); - int baseY = currentBase.getLocalY(); - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - copy[x][y] = objects[x][y]; - staticCopy[x][y] = plane.getObjects()[baseX + x][baseY + y]; - objects[x][y] = plane.getObjects()[baseX + x][baseY + y] = null; - plane.getFlags().clearFlag(baseX + x, baseY + y); - } - } - rotation = direction.toInteger(); - for (int x = 0; x < SIZE; x++) { - for (int y = 0; y < SIZE; y++) { - Scenery object = copy[x][y]; - Scenery stat = staticCopy[x][y]; - boolean match = object == stat; - if (stat == null) { - continue; - } - int[] pos = getRotatedPosition(x, y, stat.getDefinition().getSizeX(), stat.getDefinition().getSizeY(), stat.getRotation(), rotation); - if (object != null) { - object = object.transform(object.getId(), (object.getRotation() + rotation) % 4, object.getLocation().transform(pos[0] - x, pos[1] - y, 0)); - LandscapeParser.flagScenery(plane, baseX + pos[0], baseY + pos[1], object, true, true); - } - if (match) { - stat = object; - } else { - stat = stat.transform(stat.getId(), (stat.getRotation() + rotation) % 4, stat.getLocation().transform(pos[0] - x, pos[1] - y, 0)); - } - plane.getObjects()[baseX + pos[0]][baseY + pos[1]] = stat; - } - } - } - - /** - * Gets the new coordinates for an object/chunk tile when rotating. - * @param x The current x-coordinate. - * @param y The current y-coordinate. - * @param sizeX The x-size of the object. - * @param sizeY The y-size of the object. - * @param rotation The object rotation. - * @param chunkRotation The chunk rotation. - * @return The new x-coordinate. - */ - public static int[] getRotatedPosition(int x, int y, int sizeX, int sizeY, int rotation, int chunkRotation) { - if ((rotation & 0x1) == 1) { - int s = sizeX; - sizeX = sizeY; - sizeY = s; - } - if (chunkRotation == 0) { - return new int[] { x, y }; - } - if (chunkRotation == 1) { - return new int[] { y, 7 - x - (sizeX - 1) }; - } - if (chunkRotation == 2) { - return new int[] { 7 - x - (sizeX - 1), 7 - y - (sizeY - 1) }; - } - return new int[] { 7 - y - (sizeY - 1), x }; - } - /** * Gets the items. * @return The items. @@ -328,29 +509,64 @@ public class RegionChunk { } /** - * Gets the scenerys located on the coordinates in this chunk. + * Gets the sceneries located on the coordinates in this chunk. * @param chunkX The chunk x-coordinate (0-7). * @param chunkY The chunk y-coordinate (0-7). * @return The objects. */ public Scenery[] getObjects(int chunkX, int chunkY) { - return new Scenery[] { objects[chunkX][chunkY] }; + Scenery[] result = new Scenery[ARRAY_SIZE]; + for (int i = 0; i < objects.length; i++) { + result[i] = objects[i][chunkX][chunkY]; + } + return result; + } + + /** + * Gets the static objects. + * @return The static objects. + */ + public Scenery[][][] getStatObjects() { + return statObjects; } /** * Gets the objects. * @return The objects. */ - public Scenery[][] getObjects() { + public Scenery[][][] getObjects() { return objects; } /** - * Sets the objects. - * @param objects The objects to set. + * Gets the objects index for the given object id and/or scenery type. + * @param x The x-coordinate on the region chunk. + * @param y The y-coordinate on the region chunk. + * @param objectId The object id. + * @param type The scenery type. */ - public void setObjects(Scenery[][] objects) { - this.objects = objects; + public int getIndex(int x, int y, int objectId, int type) { + for (int i = 0; i < objects.length; i++) { + Scenery o = objects[i][x][y]; + if (o != null) { + if (objectId < 0) { + if (type >= 0 && o.getType() != type) { + continue; + } + // Caller didn't ask for anything specific, so we assume they want whatever *interactable-excluding-examine* object is in here + // We should probably discourage this and instead make functions calling this function more specific + if (o.getDefinition().hasOptions(false)) { + return i; + } + } else { + if (o.getId() == objectId) { + // TODO: what if there are multiple instances of the same object? Hopefully this is only a theoretical possibility in this game + return i; + } + } + } + } + return 0; } /** @@ -390,22 +606,14 @@ public class RegionChunk { * @return The updated. */ public boolean isUpdated() { - return !flags.isEmpty(); + return !updateFlags.isEmpty(); } /** * Resets the flags. */ public void resetFlags() { - flags.clear(); - } - - /** - * Gets the region plane. - * @return The plane. - */ - public RegionPlane getPlane() { - return plane; + updateFlags.clear(); } /** @@ -424,18 +632,124 @@ public class RegionChunk { this.currentBase = currentBase; } - public void rebuildFlags(RegionPlane from) { + /** + * Reinitializes the clipping flags; used when a region is copied into a new dynamic region. + */ + public void syncFlagsToRegionManager() { + flags = new ChunkFlags(currentBase.getX(), currentBase.getY(), currentBase.getZ()); + projectileFlags = new ChunkFlags(currentBase.getX(), currentBase.getY(), currentBase.getZ(), true); + } + + /** + * Rebuilds the clipping flags based on those of a source chunk (used when a chunk is being replaced). + * @param from The region plane to get the new clipping flags from. + */ + public void rebuildFlags(RegionChunk from) { for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { - Location loc = currentBase.transform(x,y,0); - Location fromLoc = base.transform(x,y,0); - plane.getFlags().getLandscape()[loc.getLocalX()][loc.getLocalY()] = from.getFlags().getLandscape()[fromLoc.getLocalX()][fromLoc.getLocalY()]; - plane.getFlags().clearFlag(x, y); - Scenery obj = objects[x][y]; - if (obj != null) - LandscapeParser.flagScenery(plane, loc.getLocalX(), loc.getLocalY(), obj, false, true); + // Import the landscape flags from the template chunk to the new chunk + flags.getLandscape()[x][y] = from.getFlags().getLandscape()[x][y]; + projectileFlags.getLandscape()[x][y] = from.getProjectileFlags().getLandscape()[x][y]; + // Reflag any objects + for (int i = 0; i < objects.length; i++) { + Scenery obj = objects[i][x][y]; + if (obj != null) { + LandscapeParser.flagScenery(this, x, y, obj, false, true); + } + } } } } + /** + * Rotates the chunk. + * @param direction The direction. + */ + public void rotate(Direction direction) { + if (rotation != 0) { + log(this.getClass(), Log.ERR, "Region chunk was already rotated!"); + return; + } + Scenery[][][] copy = new Scenery[ARRAY_SIZE][SIZE][SIZE]; + int baseX = currentBase.getLocalX(); + int baseY = currentBase.getLocalY(); + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + for (int i = 0; i < objects.length; i++) { + Scenery object = copy[i][x][y] = objects[i][x][y]; + if (object != null) { + SceneryBuilder.remove(object); + objects[i][x][y] = null; + } + } + } + } + clear(); + switch(direction) { + case NORTH: rotation = 0; break; + case EAST: rotation = 1; break; + case SOUTH: rotation = 2; break; + case WEST: rotation = 3; break; + default: rotation = (direction.toInteger() + (direction.toInteger() % 2 == 0 ? 2 : 0)) % 4; + log(this.getClass(), Log.ERR, "Attempted to rotate a chunk in a non-cardinal direction - using fallback rotation code. This should be investigated!"); + break; + }; + for (int i = 0; i < objects.length; i++) { + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + Scenery object = copy[i][x][y]; + if (object != null) { + int[] pos = getRotatedPosition(x, y, object.getDefinition().getSizeX(), object.getDefinition().getSizeY(), object.getRotation(), rotation); + Scenery obj = object.transform(object.getId(), (object.getRotation() + rotation) % 4, object.getLocation().transform(pos[0] - x, pos[1] - y, 0)); + if (object instanceof Constructed) { + obj = obj.asConstructed(); + } + obj.setActive(object.isActive()); + obj.setRenderable(object.isRenderable()); + LandscapeParser.flagScenery(this, pos[0], pos[1], obj, true, true); + } + } + } + } + } + + /** + * Gets the new coordinates for an object/chunk tile when rotating. + * @param x The current x-coordinate. + * @param y The current y-coordinate. + * @param sizeX The x-size of the object. + * @param sizeY The y-size of the object. + * @param rotation The object rotation. + * @param chunkRotation The chunk rotation. + * @return The new x-coordinate. + */ + public static int[] getRotatedPosition(int x, int y, int sizeX, int sizeY, int rotation, int chunkRotation) { + if ((rotation & 0x1) == 1) { + int s = sizeX; + sizeX = sizeY; + sizeY = s; + } + if (chunkRotation == 0) { + return new int[] { x, y }; + } + if (chunkRotation == 1) { + return new int[] { y, 7 - x - (sizeX - 1) }; + } + if (chunkRotation == 2) { + return new int[] { 7 - x - (sizeX - 1), 7 - y - (sizeY - 1) }; + } + return new int[] { 7 - y - (sizeY - 1), x }; + } + + public ChunkFlags getFlags() { + return flags; + } + + public ChunkFlags getProjectileFlags() { + return projectileFlags; + } + + public Region getRegion() { + return RegionManager.forId(currentBase.getRegionId()); + } } diff --git a/Server/src/main/core/game/world/map/RegionManager.kt b/Server/src/main/core/game/world/map/RegionManager.kt index 9fb7b848b..b58cb17f6 100644 --- a/Server/src/main/core/game/world/map/RegionManager.kt +++ b/Server/src/main/core/game/world/map/RegionManager.kt @@ -9,11 +9,9 @@ import core.game.node.scenery.Scenery import core.game.world.map.zone.ZoneBorders import core.tools.Log import core.tools.RandomFunction -import core.tools.SystemLogger import java.util.* import java.util.concurrent.TimeUnit import java.util.concurrent.locks.ReentrantLock -import kotlin.collections.HashMap /** * Manages the regions. @@ -27,7 +25,7 @@ object RegionManager { @JvmStatic val CLIPPING_FLAGS = HashMap>() @JvmStatic val PROJECTILE_FLAGS = HashMap>() - public val LOCK = ReentrantLock() + val LOCK = ReentrantLock() /** * Gets the region for the given region id. @@ -36,7 +34,7 @@ object RegionManager { */ @JvmStatic fun forId(regionId: Int): Region { - if(LOCK.tryLock() || LOCK.tryLock(10000, TimeUnit.MILLISECONDS)) { + if (LOCK.tryLock() || LOCK.tryLock(10000, TimeUnit.MILLISECONDS)) { var region = REGION_CACHE[regionId] if (region == null) { region = Region((regionId shr 8) and 0xFF, regionId and 0xFF) @@ -45,21 +43,19 @@ object RegionManager { LOCK.unlock() return REGION_CACHE[regionId]!! } - log(this::class.java, Log.ERR, "UNABLE TO OBTAIN LOCK WHEN GETTING REGION BY ID. RETURNING BLANK REGION.") - return Region(0,0) + log(this::class.java, Log.ERR, "UNABLE TO OBTAIN LOCK WHEN GETTING REGION BY ID. RETURNING BLANK REGION.") + return Region(0, 0) } /** - * Pulses the active regions. + * Applies a function to all active regions */ @JvmStatic - fun pulse() { - if(LOCK.tryLock() || LOCK.tryLock(10000,TimeUnit.MILLISECONDS)) { + fun apply(callback: (r: Region) -> Unit) { + if (LOCK.tryLock() || LOCK.tryLock(10000,TimeUnit.MILLISECONDS)) { for (r in REGION_CACHE.values) { if (r.isActive) { - for (p in r.planes) { - p.pulse() - } + callback(r) } } LOCK.unlock() @@ -67,13 +63,19 @@ object RegionManager { } /** - * Gets the clipping flag on the given location. - * @param l The location. - * @return The clipping flag. + * Pulses the active regions. */ @JvmStatic - fun getClippingFlag(l: Location): Int { - return getClippingFlag(l.z, l.x, l.y) + fun pulse() { + apply { r -> + for (x in 0 until 8) { + for (y in 0 until 8) { + for (z in 0 until 4) { + r.chunks[x][y][z]?.resetFlags() + } + } + } + } } /** @@ -85,56 +87,36 @@ object RegionManager { */ @JvmStatic fun getClippingFlag(z: Int, x: Int, y: Int): Int { - val regionX = x shr 6 - val regionY = y shr 6 - val localX = x and 63 - val localY = y and 63 - return getClippingFlag(z, regionX, regionY, localX, localY) + return getClippingFlag(Location(x, y, z)) } /** - * Gets the clipping flags using Jagex-style coords - * e.g 0_50_50_13_13 gets plane 0, region 50-50 (12850), (13, 13) which is in lumbridge. + * Gets the clipping flag. + * @param loc The location. + * @param projectile Clipping flags or projectile flags. */ @JvmStatic - fun getClippingFlag(z: Int, regionX: Int, regionY: Int, localX: Int, localY: Int, projectile: Boolean = false) : Int { - val (region, index) = getFlagIndex(z, regionX, regionY, localX, localY) - var flag = getFlags(region, projectile)[index] - - if (flag == -1) { - val r = forId((regionX shr 8) or regionY) - if (!r.isLoaded) - Region.load(r) - if (!r.isHasFlags) - return -1 - flag = getFlags(region, projectile)[index] + fun getClippingFlag(loc: Location, projectile: Boolean = false) : Int { + val region = forId(loc.regionId) + Region.load(region) + if (!region.isHasFlags) { + return -1 } - - return flag + // Index by absChunkX and absChunkY coordinates; these give the position of the chunk on the world map. Together with chunkOffsetX and chunkOffsetY, they identify individual tiles. + val (key, index) = getFlagIndex(loc.absChunkX, loc.absChunkY, loc.z, loc.chunkOffsetX, loc.chunkOffsetY) + return getFlags(key, projectile)[index] } - private fun getFlagIndex(z: Int, regionX: Int, regionY: Int, localX: Int, localY: Int) : Pair { - return Pair((regionX shl 8) or regionY, (z * 64 * 64) + (localX * 64) + localY) + private fun getFlagIndex(absChunkX: Int, absChunkY: Int, z: Int, chunkOffsetX: Int, chunkOffsetY: Int) : Pair { + return Pair((z shl 22) or (absChunkX shl 11) or absChunkY, (chunkOffsetX * 8) + chunkOffsetY) } @JvmStatic - fun getFlags(regionX: Int, regionY: Int, projectile: Boolean) : Array { - val region = (regionX shl 8) or regionY - return getFlags(region, projectile) - } - - @JvmStatic - fun getFlags(regionId: Int, projectile: Boolean) : Array { + fun getFlags(chunkId: Int, projectile: Boolean) : Array { return if (projectile) - PROJECTILE_FLAGS.getOrPut (regionId) {Array(16384){0}} + PROJECTILE_FLAGS.getOrPut(chunkId) { Array(64){0} } else - CLIPPING_FLAGS.getOrPut (regionId) {Array(16384){-1}} - } - - @JvmStatic - fun resetFlags(regionId: Int) { - PROJECTILE_FLAGS.put (regionId, Array(16384){0}) - CLIPPING_FLAGS.put (regionId, Array(16384){-1}) + CLIPPING_FLAGS.getOrPut(chunkId) { Array(64){-1} } } /** @@ -144,41 +126,37 @@ object RegionManager { */ @JvmStatic fun getWaterClipFlag(z: Int, x: Int, y: Int): Int { - val flag = getClippingFlag(z, x, y) - return if (!isClipped(z, x, y)) { + return getWaterClipFlag(Location(x, y, z)) + } + + /** + * Gets the water variant of a tile's clipping flag + * Essentially strips the landscape flag off a tile and keeps other flags, and makes normally walkable tiles unwalkable. + */ + @JvmStatic + fun getWaterClipFlag(loc: Location): Int { + val flag = getClippingFlag(loc) + return if (!isClipped(loc)) { flag or 0x100 } else flag and 0x200000.inv() } /** * Checks if the tile is part of the landscape. - * @param l The location. + * @param loc The location. * @return `True` if so. */ @JvmStatic - fun isLandscape(l: Location): Boolean { - return isLandscape(l.z, l.x, l.y) - } - - /** - * Checks if the tile is part of the landscape. - * @param z The plane. - * @param x The absolute x-coordinate. - * @param y The absolute y-coordinate. - * @return `True` if so. - */ - @JvmStatic - fun isLandscape(z: Int, x: Int, y: Int): Boolean { - var x = x - var y = y - val region = forId(((x shr 6) shl 8) or (y shr 6)) + fun isLandscape(loc: Location): Boolean { + val region = forId(loc.regionId) Region.load(region) - if (!region.isHasFlags || region.planes[z].flags.landscape == null) { + if (!region.isHasFlags) { return false } - x -= x shr 6 shl 6 - y -= y shr 6 shl 6 - return region.planes[z].flags.landscape[x][y] + if (loc.chunk.flags.landscape == null) { + return false + } + return loc.chunk.flags.landscape[loc.chunkOffsetX][loc.chunkOffsetY] } /** @@ -191,24 +169,31 @@ object RegionManager { */ @JvmStatic fun addClippingFlag(z: Int, x: Int, y: Int, projectile: Boolean, flag: Int) { - var x = x - var y = y - val region = forId(((x shr 6) shl 8) or (y shr 6)) - Region.load(region) - if (!region.isHasFlags) { - return - } - x -= (x shr 6) shl 6 - y -= (y shr 6) shl 6 - if (projectile) { - region.planes[z].projectileFlags.flag(x, y, flag) - } else { - region.planes[z].flags.flag(x, y, flag) - } + return addClippingFlag(Location(x, y, z), projectile, flag) } /** * Adds a clipping flag. + * @param loc The location. + * @param projectile If the flag is being set for projectile pathfinding. + * @param flag The clipping flag. + */ + @JvmStatic + fun addClippingFlag(loc: Location, projectile: Boolean, flag: Int) { + val region = forId(loc.regionId) + Region.load(region) + if (!region.isHasFlags) { + return + } + if (projectile) { + loc.chunk.projectileFlags.flag(loc.chunkOffsetX, loc.chunkOffsetY, flag) + } else { + loc.chunk.flags.flag(loc.chunkOffsetX, loc.chunkOffsetY, flag) + } + } + + /** + * Removes a clipping flag. * @param z The plane. * @param x The absolute x-coordinate. * @param y The absolute y-coordinate. @@ -217,24 +202,31 @@ object RegionManager { */ @JvmStatic fun removeClippingFlag(z: Int, x: Int, y: Int, projectile: Boolean, flag: Int) { - var x = x - var y = y - val region = forId(((x shr 6) shl 8) or (y shr 6)) + return removeClippingFlag(Location(x, y, z), projectile, flag) + } + + /** + * Removes a clipping flag. + * @param loc The location. + * @param projectile If the flag is being set for projectile pathfinding. + * @param flag The clipping flag. + */ + @JvmStatic + fun removeClippingFlag(loc: Location, projectile: Boolean, flag: Int) { + val region = forId(loc.regionId) Region.load(region) if (!region.isHasFlags) { return } - x -= (x shr 6) shl 6 - y -= (y shr 6) shl 6 if (projectile) { - region.planes[z].projectileFlags.unflag(x, y, flag) + loc.chunk.projectileFlags.unflag(loc.chunkOffsetX, loc.chunkOffsetY, flag) } else { - region.planes[z].flags.unflag(x, y, flag) + loc.chunk.flags.unflag(loc.chunkOffsetX, loc.chunkOffsetY, flag) } } /** - * Gets the clipping flag. + * Gets the projectile flag. * @param z The plane. * @param x The absolute x-coordinate. * @param y The absolute y-coordinate. @@ -242,62 +234,34 @@ object RegionManager { */ @JvmStatic fun getProjectileFlag(z: Int, x: Int, y: Int): Int { - val regionX = x shr 6 - val regionY = y shr 6 - val localX = x and 63 - val localY = y and 63 - return getClippingFlag(z, regionX, regionY, localX, localY, true) + return getClippingFlag(Location(x, y, z), true) } /** - * Gets the clipping flag - * @param location the Location - * @return the clipping flag + * Checks if teleport is permitted. + * @param loc The Location. + * @return If teleport is permitted. */ @JvmStatic - fun isTeleportPermitted(location: Location): Boolean { - return isTeleportPermitted(location.z, location.x, location.y) - } - - /** - * Gets the clipping flag. - * @param z The plane. - * @param x The absolute x-coordinate. - * @param y The absolute y-coordinate. - * @return The clipping flags. - */ - @JvmStatic - fun isTeleportPermitted(z: Int, x: Int, y: Int): Boolean { - if (!isLandscape(z, x, y)) { + fun isTeleportPermitted(loc: Location): Boolean { + if (!isLandscape(loc)) { return false } - val flag = getClippingFlag(z, x, y) + val flag = getClippingFlag(loc) return flag and 0x12c0102 == 0 || flag and 0x12c0108 == 0 || flag and 0x12c0120 == 0 || flag and 0x12c0180 == 0 } /** * Checks if the location has any clipping flags. - * @param location The location. + * @param loc The location. * @return `True` if a clipping flag disables access for this location. */ @JvmStatic - fun isClipped(location: Location): Boolean { - return isClipped(location.z, location.x, location.y) - } - - /** - * Checks if the location has any clipping flags. - * @param z The plane. - * @param x The x-coordinate. - * @param y The y-coordinate. - * @return `True` if a clipping flag disables access for this location. - */ - @JvmStatic - fun isClipped(z: Int, x: Int, y: Int): Boolean { - if (!isLandscape(z, x, y)) { + fun isClipped(loc: Location): Boolean { + if (!isLandscape(loc)) { return true } - val flag = getClippingFlag(z, x, y) + val flag = getClippingFlag(loc) return flag and 0x12c0102 != 0 || flag and 0x12c0108 != 0 || flag and 0x12c0120 != 0 || flag and 0x12c0180 != 0 } @@ -355,6 +319,17 @@ object RegionManager { return getObject(l.z, l.x, l.y) } + /** + * Gets the scenery on the current location of the same type as a different piece of scenery. + * @param l The location. + * @param type The scenery type. + * @return The scenery, or `null` if no object was found. + */ + @JvmStatic + fun getObject(l: Location, type: Int): Scenery? { + return getObject(l.z, l.x, l.y, -1, type) + } + /** * Gets the scenery on the current absolute coordinates. * @param z The height. @@ -377,28 +352,30 @@ object RegionManager { */ @JvmStatic fun getObject(z: Int, x: Int, y: Int, objectId: Int): Scenery? { - var x = x - var y = y - val regionId = ((x shr 6) shl 8) or (y shr 6) - x -= (x shr 6) shl 6 - y -= (y shr 6) shl 6 - val region = forId(regionId) - Region.load(region) - val `object`: Scenery? = region.planes[z].getChunkObject(x, y, objectId) - return if (`object` != null && !`object`.isRenderable) { - null - } else `object` + return getObject(z, x, y, objectId, -1) } /** - * Gets the region plane for this location. - * @param l The location. - * @return The region plane. + * Gets the object on the given absolute coordinates. + * @param z The height. + * @param x The x-coordinate. + * @param y The y-coordinate. + * @param objectId The object id. May be -1, which means 'any'. + * @param type The scenery type. May be -1, which means 'any'. + * @return The scenery, or `null` if no object was found. */ @JvmStatic - fun getRegionPlane(l: Location): RegionPlane { - val regionId = ((l.x shr 6) shl 8) or (l.y shr 6) - return forId(regionId).planes[l.z] + fun getObject(z: Int, x: Int, y: Int, objectId: Int, type: Int): Scenery? { + val loc = Location(x, y, z) + val region = forId(loc.regionId) + Region.load(region) + val chunk = region.chunks[loc.chunkX][loc.chunkY][loc.z] + val index = chunk.getIndex(loc.chunkOffsetX, loc.chunkOffsetY, objectId, type) + val obj = chunk.objects[index][loc.chunkOffsetX][loc.chunkOffsetY] + if (obj != null && !obj.isRenderable) { + return null + } + return obj } /** @@ -408,247 +385,75 @@ object RegionManager { */ @JvmStatic fun getRegionChunk(l: Location): RegionChunk { - val plane = getRegionPlane(l) - return plane.getRegionChunk(l.localX / RegionChunk.SIZE, l.localY / RegionChunk.SIZE) + val regionId = ((l.x shr 6) shl 8) or (l.y shr 6) + return forId(regionId).chunks[l.chunkX][l.chunkY][l.z] } /** - * Moves the entity from the current region to the new one. + * Moves the entity from the current chunk to the new one. * @param entity The entity. */ @JvmStatic - fun move(entity: Entity) { - val player = entity is Player - val regionId = ((entity.location.regionX shr 3) shl 8) or (entity.location.regionY shr 3) - val viewport = entity.viewport - val current = forId(regionId) - val z = entity.location.z - val plane = current.planes[z] - viewport.updateViewport(entity) - if (plane == viewport.currentPlane) { - entity.zoneMonitor.updateLocation(entity.walkingQueue.footPrint) - return - } - viewport.remove(entity) - if (player) { - current.add(entity as Player) - } else { - current.add(entity as NPC) - } - viewport.region = current - viewport.currentPlane = plane - val view: MutableList = LinkedList() - for (regionX in ((entity.location.regionX shr 3) - 1)..((entity.location.regionX shr 3) + 1)) { - for (regionY in ((entity.location.regionY shr 3) - 1)..((entity.location.regionY shr 3) + 1)) { - if (regionX < 0 || regionY < 0) { - continue + fun move(entity: Entity, src: Location, dst: Location) { + if (src.chunk != dst.chunk) { + when (entity) { + is Player -> { + src.chunk.removePlayer(entity) + src.region.decrementViewAmount() + dst.chunk.addPlayer(entity) + dst.region.incrementViewAmount() + dst.region.flagActive() } - val region = forId((regionX shl 8) or regionY) - val p = region.planes[z] - if (player) { - region.incrementViewAmount() - region.flagActive() + is NPC -> { + src.chunk.remove(entity) + dst.chunk.add(entity) + } + else -> { + throw (IllegalStateException("Tried to move an Entity that was neither Player nor NPC")) } - view.add(p) } } - viewport.viewingPlanes = view entity.zoneMonitor.updateLocation(entity.walkingQueue.footPrint) } /** - * Gets the list of local NPCs with a maximum distance of 16. - * @param n The entity. - * @return The list of local NPCs. - */ - @JvmStatic - fun getLocalNpcs(n: Entity): List { - return getLocalNpcs(n, MapDistance.RENDERING.distance) - } - - /** - * Gets the location entitys. + * Gets local entities. You never call the below function directly (it's inlined); instead, you use one of the typed helpers defined directly below this function. * @param location the location. * @param distance the distance. + * @param maximum the maximum number of entities to return. + * @param ignore an entity to exclude (may be null). * @return the list. */ - @JvmStatic - fun getLocalEntitys(location: Location, distance: Int): List { - val entitys: MutableList = ArrayList(20) - entitys.addAll(getLocalNpcs(location, distance)) - entitys.addAll(getLocalPlayers(location, distance)) - return entitys - } - - /** - * Gets the location entitys. - * @param entity the entity. - * @param distance the distance. - * @return the list. - */ - @JvmStatic - fun getLocalEntitys(entity: Entity, distance: Int): List { - return getLocalEntitys(entity.location, distance) - } - - /** - * Gets the local entitys. - * @param entity the entity. - * @return the entitys. - */ - @JvmStatic - fun getLocalEntitys(entity: Entity): List { - return getLocalEntitys(entity.location, MapDistance.RENDERING.distance) - } - - /** - * Gets the list of local NPCs. - * @param n The entity. - * @param distance The distance to the entity. - * @return The list of local NPCs. - */ - @JvmStatic - fun getLocalNpcs(n: Entity, distance: Int): List { - val npcs: MutableList = LinkedList() - for (r in n.viewport.viewingPlanes) { - for (npc in r.npcs) { - if (npc.location.withinDistance(n.location, distance)) { - npcs.add(npc) + inline fun getLocalEntities(location: Location, distance: Int, maximum: Int, ignore: Entity?): List { + val entities: MutableList = ArrayList(20) + for (cx in (location.absChunkX - 2)..(location.absChunkX + 2)) { + for (cy in (location.absChunkY - 2)..(location.absChunkY + 2)) { + val chunk = Location(cx shl 3, cy shl 3, location.z).chunk + if (Player::class.java.isAssignableFrom(T::class.java)) { + entities.addAll(chunk.players as Collection) + } + if (NPC::class.java.isAssignableFrom(T::class.java)) { + entities.addAll(chunk.npcs as Collection) } } } - return npcs - } - - /** - * Gets the list of local players with a maximum distance of 15. - * @param n The entity. - * @return The list of local players. - */ - @JvmStatic - fun getLocalPlayers(n: Entity): List { - return getLocalPlayers(n, MapDistance.RENDERING.distance) - } - - /** - * Gets the list of local players. - * @param n The entity. - * @param distance The distance to the entity. - * @return The list of local players. - */ - @JvmStatic - fun getLocalPlayers(n: Entity, distance: Int): List { - val players: MutableList = LinkedList() - for (r in n.viewport.viewingPlanes) { - for (p in r.players) { - if (p.location.withinDistance(n.location, distance)) { - players.add(p) - } - } + val b = ZoneBorders(location.x - distance, location.y - distance, location.x + distance, location.y + distance) + var filtered = entities.filter { it != ignore && b.insideBorder(it.location.x, it.location.y) } + if (maximum > 0 && filtered.size > maximum) { + filtered = filtered.slice(0 until maximum) } - return players - } - - /** - * Gets the surrounding players. - * @param n The node the players should be surrounding. - * @param ignore The nodes not to add to the list. - * @return The list of players. - */ - @JvmStatic - fun getSurroundingPlayers(n: Node, vararg ignore: Node): List { - return getSurroundingPlayers(n, 9, *ignore) - } - - /** - * Gets the surrounding players. - * @param n The node the players should be surrounding. - * @param ignore The nodes not to add to the list. - * @return The list of players. - */ - @JvmStatic - fun getSurroundingPlayers(n: Node, maximum: Int, vararg ignore: Node): List { - val players = getLocalPlayers(n.location, 2) - var count = 0 - val it = players.iterator() - while (it.hasNext()) { - val p = it.next() - if(p.isInvisible()) { - it.remove() - } - if(!p.location.withinMaxnormDistance(n.location, 1)) { - it.remove() - continue - } - if (++count >= maximum) { - it.remove() - continue - } - for (node in ignore) { - if (p === node) { - count-- - it.remove() - break - } - } - } - return players - } - - /** - * Gets the surrounding players. - * @param n The node the players should be surrounding. - * @param ignore The nodes not to add to the list. - * @return The list of players. - */ - @JvmStatic - fun getSurroundingNPCs(n: Node, vararg ignore: Node): List { - return getSurroundingNPCs(n, 9, *ignore) - } - - /** - * Gets the surrounding players. - * @param n The node the npcs should be surrounding. - * @param ignore The nodes not to add to the list. - * @return The list of npcs. - */ - @JvmStatic - fun getSurroundingNPCs(n: Node, maximum: Int, vararg ignore: Node): List { - val npcs = getLocalNpcs(n.location, 2) - var count = 0 - val it = npcs.iterator() - while (it.hasNext()) { - val p = it.next() - if(p.properties.teleportLocation != null && !p.properties.teleportLocation.withinMaxnormDistance(n.location, 1)) { - it.remove() - continue - } - if(p.getAttribute("state:death", false)) { - it.remove() - continue - } - if(p.isInvisible()) { - it.remove() - continue - } - if(!p.location.withinMaxnormDistance(n.location, 1)) { - it.remove() - continue - } - if (++count > maximum) { - it.remove() - continue - } - for (node in ignore) { - if (p === node) { - count-- - it.remove() - break - } - } - } - return npcs + return filtered } + @JvmStatic fun getLocalEntities(location: Location, distance: Int): List = getLocalEntities(location, distance, 0, null) + @JvmStatic fun getLocalPlayers(location: Location, distance: Int): List = getLocalEntities(location, distance, 0, null) + @JvmStatic fun getLocalNPCs(location: Location, distance: Int): List = getLocalEntities(location, distance, 0, null) + @JvmStatic fun getLocalPlayers(location: Location): List = getLocalEntities(location, MapDistance.RENDERING.distance, 0, null) + @JvmStatic fun getLocalNPCs(location: Location): List = getLocalEntities(location, MapDistance.RENDERING.distance, 0, null) + @JvmStatic fun getSurroundingPlayers(player: Entity, maximum: Int): List = getLocalEntities(player.location, 1, maximum, null) + @JvmStatic fun getSurroundingNPCs(npc: Entity, maximum: Int): List = getLocalEntities(npc.location, 1, maximum, null) + @JvmStatic fun getLocalPlayersBoundingBox(location: Location, maximum: Int): List = getLocalEntities(location, 1, maximum, null) + @JvmStatic fun getLocalNPCBoundingBox(location: Location, maximum: Int): List = getLocalEntities(location, 1, maximum, null) + @JvmStatic fun getLocalEntitys(location: Location, distance: Int): List = getLocalEntities(location, distance, 0, null) //typoed version to avoid merge conflict with !2269 /** * Gets a random teleport location in the radius around the given location. @@ -701,162 +506,14 @@ object RegionManager { } /** - * Gets the current viewport for the location. - * @param l The location. - * @return The viewport. - */ - @JvmStatic - fun getViewportPlayers(l: Location): List { - var l = l - val players: MutableList = LinkedList() - l = l.chunkBase.transform(-8, -8, 0) - val b = ZoneBorders(l.x, l.y, l.x + 24, l.y + 24) - for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) { - for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) { - for (player in forId(regionX shl 8 or regionY).planes[l.z].players) { - l = player.location - if (b.insideBorder(l.x, l.y)) { - players.add(player) - } - } - } - } - return players - } - - /** - * Gets a list of players in the given region. - * @param regionId The region id. - * @return The list of players in this region. - */ - @JvmStatic - fun getRegionPlayers(regionId: Int): List { - val r = forId(regionId) - val players: MutableList = ArrayList(20) - for (plane in r.planes) { - players.addAll(plane.players) - } - return players - } - - /** - * Gets a list of local players within rendering distance of the location. - * @param l The location. - * @return The list of players. - */ - @JvmStatic - fun getLocalPlayers(l: Location): List { - return getLocalPlayers(l, MapDistance.RENDERING.distance) - } - - /** - * Gets a list of local players. - * @param l The location. - * @param distance The distance to that location. - * @return The list of players. - */ - @JvmStatic - fun getLocalPlayers(l: Location, distance: Int): MutableList { - val players: MutableList = LinkedList() - for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) { - for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) { - for (player in forId((regionX shl 8) or regionY).planes[l.z].players) { - if (player.location.withinDistance(l, distance)) { - players.add(player) - } - } - } - } - return players - } - - /** - * Gets a list of local players within a symmetric bounding box. - * @param l The location. - * @param xdist The distance from the location on the x plane that is considered within bounds. - * @param ydist The distance from the location on the y plane that is considered within bounds. - * @return The list of players. - */ - @JvmStatic - fun getLocalPlayersBoundingBox(l: Location, xdist: Int, ydist: Int): MutableList { - val players: MutableList = LinkedList() - for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) { - for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) { - for (player in forId((regionX shl 8) or regionY).planes[l.z].players) { - if (player.location.x >= l.x - xdist && - player.location.x <= l.x + xdist && - player.location.y >= l.y - ydist && - player.location.y <= l.y + ydist) { - players.add(player) - } - } - } - } - return players - } - - /** - * Gets a list of local players. - * @param l The location. - * @param distance The distance to that location. - * @return The list of players. - */ - @JvmStatic - fun getLocalPlayersMaxNorm(l: Location, distance: Int): MutableList { - val players: MutableList = LinkedList() - for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) { - for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) { - for (player in forId((regionX shl 8) or regionY).planes[l.z].players) { - if (player.location.withinMaxnormDistance(l, distance)) { - players.add(player) - } - } - } - } - return players - } - - /** - * Gets a list of local players within 16 tile distance of the location. - * @param l The location. - * @return The list of players. - */ - @JvmStatic - fun getLocalNpcs(l: Location): List { - return getLocalNpcs(l, MapDistance.RENDERING.distance) - } - - /** - * Gets the npc. - * @param entity the entity. - * @param id the id. - */ - @JvmStatic - fun getNpc(entity: Entity, id: Int): NPC? { - return getNpc(entity, id, 16) - } - - /** - * Gets the npc. - * @param entity the entity. - * @param id the id. + * Gets an npc near a location. + * @param id the id, * @param distance the distance. * @return the npc. */ @JvmStatic - fun getNpc(entity: Entity, id: Int, distance: Int): NPC? { - return getNpc(entity.location, id, distance) - } - - /** - * Gets an npc near the entity. - * @param id the id, - * @param distance the dinstance. - * @return the npc. - */ - @JvmStatic fun getNpc(location: Location, id: Int, distance: Int): NPC? { - val npcs: List = getLocalNpcs(location, distance) + val npcs: List = getLocalNPCs(location, distance) for (n in npcs) { if (n.id == id) { return n @@ -865,27 +522,6 @@ object RegionManager { return null } - /** - * Gets a list of local players. - * @param l The location. - * @param distance The distance to that location. - * @return The list of players. - */ - @JvmStatic - fun getLocalNpcs(l: Location, distance: Int): MutableList { - val npcs: MutableList = LinkedList() - for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) { - for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) { - for (n in forId(regionX shl 8 or regionY).planes[l.z].npcs) { - if (n.location.withinDistance(l, (n.size() shr 1) + distance)) { - npcs.add(n) - } - } - } - } - return npcs - } - @JvmStatic fun addRegion(id: Int, region: Region){ if(lock.tryLock() || LOCK.tryLock(10000, TimeUnit.MILLISECONDS)) { diff --git a/Server/src/main/core/game/world/map/RegionPlane.java b/Server/src/main/core/game/world/map/RegionPlane.java deleted file mode 100644 index f83724ec0..000000000 --- a/Server/src/main/core/game/world/map/RegionPlane.java +++ /dev/null @@ -1,444 +0,0 @@ -package core.game.world.map; - -import core.game.node.Node; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.game.node.item.GroundItem; -import core.game.node.item.Item; -import core.game.node.scenery.Scenery; -import core.game.world.map.build.DynamicRegion; -import core.game.world.map.build.RegionFlags; -import core.game.world.update.flag.chunk.ItemUpdateFlag; -import core.net.packet.PacketRepository; -import core.net.packet.context.BuildItemContext; -import core.net.packet.out.ClearGroundItem; -import core.net.packet.out.ConstructGroundItem; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * Represents one of the 4 planes of a region. - * @author Emperor - * - */ -public final class RegionPlane { - - /** - * The region size. - */ - public static final int REGION_SIZE = 64; - - /** - * The amount of chunks in this plane. - */ - public static final int CHUNK_SIZE = REGION_SIZE >> 3; - - /** - * Represents a removed scenery. - */ - public static final Scenery NULL_OBJECT = new Scenery(0, Location.create(0, 0, 0)); - - /** - * The plane. - */ - private final int plane; - - /** - * The region. - */ - private final Region region; - - /** - * The region flags. - */ - private final RegionFlags flags; - - /** - * The region projectile flags. - */ - private final RegionFlags projectileFlags; - - /** - * The region chunks. - */ - private final RegionChunk[][] chunks; - - /** - * The list of NPCs in this region. - */ - private final List npcs; - - /** - * The list of players in this region. - */ - private final List players; - - /** - * The scenerys. - */ - private Scenery[][] objects; - - /** - * Constructs a new {@code RegionPlane} {@code Object}. - * @param region The region. - * @param plane The plane. - */ - public RegionPlane(Region region, int plane) { - this.plane = plane; - this.region = region; - this.players = new CopyOnWriteArrayList(); - this.npcs = new CopyOnWriteArrayList(); - Location base = region.getBaseLocation(); - this.flags = new RegionFlags(plane, base.getX(), base.getY()); - this.projectileFlags = new RegionFlags(plane, base.getX(), base.getY(), true); - this.objects = new Scenery[REGION_SIZE][REGION_SIZE]; - this.chunks = new RegionChunk[CHUNK_SIZE][CHUNK_SIZE]; - } - - /** - * Called at the end of the update sequence, if the region is active. - */ - public void pulse() { - Arrays.stream(chunks).forEach(regionChunks -> {Arrays.stream(regionChunks).filter(Objects::nonNull).forEach(RegionChunk::resetFlags);}); - } - - /** - * Adds a scenery. - * @param object The object to add. - * @param x The x-coordinate. - * @param y The y-coordinate. - * @param landscape If this object is added through landscape parsing. - */ - public void add(Scenery object, int x, int y, boolean landscape) { - setChunkObject(x, y, object); - if (landscape) { - objects[x][y] = object; - } - if (object != null) { - object.setRenderable(true); - } - } - - /** - * Gets the region chunk. - * @param chunkX The chunk base x-coordinate. - * @param chunkY The chunk base y-coordinate. - * @return The region chunk. - */ - public RegionChunk getRegionChunk(int chunkX, int chunkY) { - RegionChunk r = chunks[chunkX][chunkY]; - if (r != null) { - return r; - } - if (region.isBuild()) { - return chunks[chunkX][chunkY] = new BuildRegionChunk(region.getBaseLocation().transform(chunkX << 3, chunkY << 3, plane), 0, this); - } - return chunks[chunkX][chunkY] = new RegionChunk(region.getBaseLocation().transform(chunkX << 3, chunkY << 3, plane), 0, this); - } - - public void setRegionChunk(int chunkX, int chunkY, RegionChunk chunk) { - chunks[chunkX][chunkY] = chunk; - } - - /** - * Removes a scenery. - * @param x The x-coordinate. - * @param y The y-coordinate. - */ - public void remove(int x, int y) { - remove(x, y, -1); - } - - /** - * Removes a scenery. - * @param x The x-coordinate. - * @param y The y-coordinate. - * @param objectId The object id. - */ - public void remove(int x, int y, int objectId) { - int chunkX = x / CHUNK_SIZE; - int chunkY = y / CHUNK_SIZE; - int offsetX = x - chunkX * CHUNK_SIZE; - int offsetY = y - chunkY * CHUNK_SIZE; - RegionChunk chunk = getRegionChunk(chunkX, chunkY); - Scenery remove = new Scenery(0, region.getBaseLocation().transform(x, y, plane), 22, 0); - remove.setRenderable(false); - if (chunk instanceof BuildRegionChunk) { - int index = ((BuildRegionChunk) chunk).getIndex(offsetX, offsetY, objectId); - ((BuildRegionChunk) chunk).getObjects(index)[offsetX][offsetY] = remove; - return; - } - chunk.getObjects()[offsetX][offsetY] = remove; - } - - /** - * Sets an object on a chunk. - * @param x The regional x-coordinate. - * @param y The regional y-coordinate. - * @param object The object to set. - */ - private void setChunkObject(int x, int y, Scenery object) { - int chunkX = x / CHUNK_SIZE; - int chunkY = y / CHUNK_SIZE; - int offsetX = x - chunkX * CHUNK_SIZE; - int offsetY = y - chunkY * CHUNK_SIZE; - RegionChunk r = getRegionChunk(chunkX, chunkY); - if (r instanceof BuildRegionChunk) { - ((BuildRegionChunk) r).store(object); - return; - } - r.getObjects()[offsetX][offsetY] = object; - } - - /** - * Gets the scenerys. - * @return The scenerys. - */ - public Scenery[][] getObjects() { - return objects; - } - - public List getObjectList() { - ArrayList list = new ArrayList(); - for (int x = 0; x < REGION_SIZE; x++) { - for (int y = 0; y < REGION_SIZE; y++) { - if (objects[x][y] != null) - list.add(objects[x][y]); - } - } - return list; - } - - /** - * Clears this region plane. - */ - public void clear() { - for (RegionChunk[] c : chunks) { - for (RegionChunk chunk : c) { - if (chunk != null) { - chunk.clear(); - } - } - } - if (region instanceof DynamicRegion && objects != null) { - for (int x = 0; x < REGION_SIZE; x++) { - for (int y = 0; y < REGION_SIZE; y++) { - objects[x][y] = null; - } - } - objects = null; - } - } - - /** - * Adds an NPC to this region. - * @param npc The NPC to add. - */ - public void add(NPC npc) { - npcs.add(npc); - } - - /** - * Adds a player to this region. - * @param player The player. - */ - public void add(Player player) { - players.add(player); - } - - /** - * Adds an item to this region. - * @param item The item. - */ - public void add(GroundItem item) { - Location l = item.getLocation(); - RegionChunk c = getRegionChunk(l.getLocalX() / RegionChunk.SIZE, l.getLocalY() / RegionChunk.SIZE); - // This adds it to the chunk to be interactable with. - if (!c.getItems().add(item)) { - return; - } - GroundItem g = (GroundItem) item; - if (g.isPrivate()) { - if (g.getDropper() != null) { - // Limit it to the region(8x8 square) you are in +/-2 regions, as the chunk loader will load it all over again. - // This is based on MapChunkRenderer which seems to "update" 2 chunks away. - // Look at RegionChunk.java ConstructGroundItem.write(buffer, item); - if (Math.abs(g.getDropper().getLocation().getRegionX() - l.getRegionX()) <= 2 && - Math.abs(g.getDropper().getLocation().getRegionY() - l.getRegionY()) <= 2 && - g.getDropper().getLocation().getZ() == l.getZ()) { - PacketRepository.send(ConstructGroundItem.class, new BuildItemContext(g.getDropper(), item)); - } - } - return; - } - c.flag(new ItemUpdateFlag(g, ItemUpdateFlag.CONSTRUCT_TYPE)); - } - - /** - * Removes an NPC from this region. - * @param npc The NPC. - */ - public void remove(NPC npc) { - npcs.remove(npc); - } - - /** - * Removes a player from this region. - * @param player The player. - */ - public void remove(Player player) { - players.remove(player); - } - - /** - * Removes an item from this region. - * @param item The ground item. - */ - public void remove(GroundItem item) { - Location l = item.getLocation(); - RegionChunk c = getRegionChunk(l.getLocalX() / RegionChunk.SIZE, l.getLocalY() / RegionChunk.SIZE); - if (!c.getItems().remove(item)) { - return; - } - if (item.isPrivate()) { - if (item.getDropper() != null && item.getDropper().isPlaying() && item.getDropper().getLocation().withinDistance(l)) { - PacketRepository.send(ClearGroundItem.class, new BuildItemContext(item.getDropper(), item)); - } - return; - } - c.flag(new ItemUpdateFlag(item, ItemUpdateFlag.REMOVE_TYPE)); - } - - /** - * Gets the region flags. - * @return The flags. - */ - public RegionFlags getFlags() { - return flags; - } - - /** - * Gets the projectileFlags. - * @return The projectileFlags. - */ - public RegionFlags getProjectileFlags() { - return projectileFlags; - } - - /** - * Gets the npcs. - * @return The npcs. - */ - public List getNpcs() { - return npcs; - } - - public List getEntities() - { - List entities = new ArrayList<>(npcs); - Arrays.stream(getObjects()).forEach(o -> entities.addAll(Arrays.asList(o))); - return entities; - } - - /** - * Gets the players. - * @return The players. - */ - public List getPlayers() { - return players; - } - - /** - * Gets the plane. - * @return The plane. - */ - public int getPlane() { - return plane; - } - - /** - * Gets the region. - * @return The region. - */ - public Region getRegion() { - return region; - } - - /** - * Gets an object from a region chunk. - * @param x The region x-coordinate. - * @param y The region y-coordinate. - * @return The scenery. - */ - public Scenery getChunkObject(int x, int y) { - return getChunkObject(x, y, -1); - } - - /** - * Gets an object from a region chunk. - * @param x The region x-coordinate. - * @param y The region y-coordinate. - * @param objectId The object id. - * @return The scenery. - */ - public Scenery getChunkObject(int x, int y, int objectId) { - int chunkX = x / CHUNK_SIZE; - int chunkY = y / CHUNK_SIZE; - int offsetX = x - chunkX * CHUNK_SIZE; - int offsetY = y - chunkY * CHUNK_SIZE; - RegionChunk chunk = getRegionChunk(chunkX, chunkY); - if (chunk instanceof BuildRegionChunk) { - BuildRegionChunk brc = (BuildRegionChunk) chunk; - return brc.get(offsetX, offsetY, brc.getIndex(offsetX, offsetY, objectId)); - } - return getRegionChunk(chunkX, chunkY).getObjects()[offsetX][offsetY]; - } - - /** - * Gets an object from a region chunk. - * @param x The region x-coordinate. - * @param y The region y-coordinate. - * @return The scenery. - */ - public List getChunkItems(int x, int y) { - int chunkX = x / CHUNK_SIZE; - int chunkY = y / CHUNK_SIZE; - return getRegionChunk(chunkX, chunkY).getItems(); - } - - /** - * Gets a ground item from this plane. - * @param itemId The item id. - * @param l The location. - * @param player The player. - * @return The item. - */ - public GroundItem getItem(int itemId, Location l, Player player) { - GroundItem groundItem = null; - for (Item item : getChunkItems(l.getLocalX(), l.getLocalY())) { - GroundItem g = (GroundItem) item; - if (g.getId() == itemId && l.equals(g.getLocation()) && !g.isRemoved()) { - if (groundItem != null && (!g.isPrivate() || player == null)) { - continue; - } - if ((!g.isPrivate() || player == null || g.droppedBy(player))) { - groundItem = g; - } - } - } - return groundItem; - } - - /** - * Gets the region chunks. - * @return The chunks. - */ - public RegionChunk[][] getChunks() { - return chunks; - } - -} diff --git a/Server/src/main/core/game/world/map/Viewport.java b/Server/src/main/core/game/world/map/Viewport.java deleted file mode 100644 index d563b0357..000000000 --- a/Server/src/main/core/game/world/map/Viewport.java +++ /dev/null @@ -1,155 +0,0 @@ -package core.game.world.map; - -import core.game.node.entity.Entity; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; - -import java.util.LinkedList; -import java.util.List; - -/** - * Represents an entity's viewport. - * @author Emperor - */ -public final class Viewport { - - /** - * The amount of chunks in a viewport. - */ - public static final int CHUNK_SIZE = 5; - - /** - * The region region. - */ - private Region region; - - /** - * The region chunks. - */ - private RegionChunk[][] chunks = new RegionChunk[CHUNK_SIZE][CHUNK_SIZE]; - - /** - * The region region plane. - */ - private RegionPlane currentPlane; - - /** - * The region planes the entity can see. - */ - private List viewingPlanes = new LinkedList<>(); - - /** - * Constructs a new {@code Viewport} {@code Object}. - */ - public Viewport() { - /* - * empty. - */ - } - - /** - * Updates the entity's viewport. - * @param entity The entity. - */ - public void updateViewport(Entity entity) { - RegionChunk chunk = RegionManager.getRegionChunk(entity.getLocation()); - int center = chunks.length >> 1; - if (chunks[center][center] == chunk) { - return; - } - int offset = center * -8; - Location l = chunk.getCurrentBase(); - for (int x = 0; x < chunks.length; x++) { - for (int y = 0; y < chunks[x].length; y++) { - chunks[x][y] = RegionManager.getRegionChunk(l.transform(offset + (8 * x), offset + (8 * y), 0)); - } - } - } - - /** - * Removes the entity from the viewingPlanes. - * @param entity The entity. - */ - public void remove(Entity entity) { - if (region == null) { - return; - } - if (entity instanceof Player) { - region.remove((Player) entity); - Region region = null; - for (RegionPlane r : viewingPlanes) { - if (region != r.getRegion()) { - region = r.getRegion(); - region.decrementViewAmount(); - region.checkInactive(); - } - } - } else { - region.remove((NPC) entity); - } - } - - /** - * Gets the region. - * @return The region. - */ - public Region getRegion() { - return region; - } - - /** - * Sets the region. - * @param region The region to set. - */ - public void setRegion(Region region) { - this.region = region; - } - - /** - * Gets the chunks. - * @return The chunks. - */ - public RegionChunk[][] getChunks() { - return chunks; - } - - /** - * Sets the chunks. - * @param chunks The chunks to set. - */ - public void setChunks(RegionChunk[][] chunks) { - this.chunks = chunks; - } - - /** - * Gets the viewingPlanes. - * @return The viewingPlanes. - */ - public List getViewingPlanes() { - return viewingPlanes; - } - - /** - * Sets the viewingPlanes. - */ - public void setViewingPlanes(List regions) { - this.viewingPlanes = regions; - } - - /** - * Gets the currentPlane. - * @return The currentPlane. - */ - public RegionPlane getCurrentPlane() { - return currentPlane; - } - - /** - * Sets the currentPlane. - * @param currentPlane The currentPlane to set. - */ - public void setCurrentPlane(RegionPlane currentPlane) { - this.currentPlane = currentPlane; - } - -} diff --git a/Server/src/main/core/game/world/map/build/RegionFlags.java b/Server/src/main/core/game/world/map/build/ChunkFlags.java similarity index 92% rename from Server/src/main/core/game/world/map/build/RegionFlags.java rename to Server/src/main/core/game/world/map/build/ChunkFlags.java index 177da33c9..a41cb9368 100644 --- a/Server/src/main/core/game/world/map/build/RegionFlags.java +++ b/Server/src/main/core/game/world/map/build/ChunkFlags.java @@ -10,7 +10,7 @@ import static java.lang.Math.max; * @author Emperor * */ -public final class RegionFlags { +public final class ChunkFlags { public static final int TILE_OBJECT = 0x40000; public static final int EMPTY_TILE = 0; @@ -20,7 +20,7 @@ public final class RegionFlags { /** * The plane. */ - private final int plane; + private final int baseZ; /** * If the region is members only. @@ -49,23 +49,25 @@ public final class RegionFlags { /** * Constructs a new {@code RegionFlags} {@code Object}. - * @param x The base x-coordinate (absolute). + * @param x The base x-coordinate (absolute). * @param y The base y-coordinate (absolute). - */ - public RegionFlags(int plane, int x, int y) { - this(plane, x, y, false); + * @param z The base z-coordinate (absolute). + */ + public ChunkFlags(int x, int y, int z) { + this(x, y, z, false); } /** * Constructs a new {@code RegionFlags} {@code Object}. - * @param x The base x-coordinate (absolute). + * @param x The base x-coordinate (absolute). * @param y The base y-coordinate (absolute). - */ - public RegionFlags(int plane, int x, int y, boolean projectile) { - this.plane = plane; + */ + public ChunkFlags(int x, int y, int z, boolean projectile) { this.baseX = x; this.baseY = y; + this.baseZ = z; this.projectile = projectile; + this.landscape = new boolean[8][8]; //all false by default, thanks Java } /** @@ -126,10 +128,10 @@ public final class RegionFlags { * @param clipdata The clip data. */ public void flag(int x, int y, int clipdata) { - if (x > -1 && x < 64 && y > -1 && y < 64) { + if (x > -1 && x < 8 && y > -1 && y < 8) { addFlag(x, y, clipdata); } else { - RegionManager.addClippingFlag(plane, baseX + x, baseY + y, projectile, clipdata); + RegionManager.addClippingFlag(baseZ, baseX + x, baseY + y, projectile, clipdata); } } @@ -160,15 +162,15 @@ public final class RegionFlags { * @param clipdata The clip data. */ public void unflag(int x, int y, int clipdata) { - if (x > -1 && x < 64 && y > -1 && y < 64) { + if (x > -1 && x < 8 && y > -1 && y < 8) { removeFlag(x, y, clipdata); } else { - RegionManager.removeClippingFlag(plane, baseX + x, baseY + y, projectile, clipdata); + RegionManager.removeClippingFlag(baseZ, baseX + x, baseY + y, projectile, clipdata); } } private Pair getFlagIndex(int x, int y) { - return new Pair<>(((baseX >> 6) << 8) | (baseY >> 6), (plane * 64 * 64) + (x * 64) + y); + return new Pair<>((baseZ << 22) | ((baseX >> 3) << 11) | (baseY >> 3), (x * 8) + y); } public int getFlag(int x, int y) { @@ -349,7 +351,7 @@ public final class RegionFlags { } /** - * Unlags a door object (type 0-3). + * Unflags a door object (type 0-3). * @param x The x-coordinate * @param y The y-coordinate. * @param rotation The rotation. @@ -515,8 +517,8 @@ public final class RegionFlags { * Gets the plane. * @return The plane. */ - public int getPlane() { - return plane; + public int getBaseZ() { + return baseZ; } /** @@ -534,4 +536,4 @@ public final class RegionFlags { public void setLandscape(boolean[][] landscape) { this.landscape = landscape; } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/world/map/build/DynamicRegion.java b/Server/src/main/core/game/world/map/build/DynamicRegion.java index 2ccbabc69..6e0d06031 100644 --- a/Server/src/main/core/game/world/map/build/DynamicRegion.java +++ b/Server/src/main/core/game/world/map/build/DynamicRegion.java @@ -5,7 +5,6 @@ import core.game.node.entity.player.Player; import core.game.node.entity.player.link.music.MusicZone; import core.game.node.item.GroundItem; import core.game.node.item.GroundItemManager; -import core.game.node.scenery.Scenery; import core.game.world.map.*; import core.game.world.map.zone.RegionZone; import core.game.world.map.zone.ZoneBorders; @@ -13,7 +12,6 @@ import core.game.world.map.zone.impl.MultiwayCombatZone; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -24,7 +22,6 @@ import java.util.List; * @author Emperor */ public final class DynamicRegion extends Region { - /** * The reserved areas. */ @@ -35,11 +32,6 @@ public final class DynamicRegion extends Region { */ private final int regionId; - /** - * The region chunks. - */ - private final RegionChunk[][][] chunks; - /** * The zone borders. */ @@ -76,14 +68,25 @@ public final class DynamicRegion extends Region { public DynamicRegion(int regionId, int x, int y) { super(x, y); this.regionId = regionId; - this.chunks = new RegionChunk[4][SIZE >> 3][SIZE >> 3]; - RegionManager.resetFlags(getId()); + // Reset any stale flags at this region's chunk coordinates + for (int chunkX = 0; chunkX < 8; chunkX++) { + for (int chunkY = 0; chunkY < 8; chunkY++) { + for (int cz = 0; cz < 4; cz++) { + RegionChunk chunk = chunks[chunkX][chunkY][cz]; + for (int chunkOffsetX = 0; chunkOffsetX < 8; chunkOffsetX++) { + for (int chunkOffsetY = 0; chunkOffsetY < 8; chunkOffsetY++) { + chunk.getFlags().invalidateFlag(chunkOffsetX, chunkOffsetY); //the 'invalid' value of -1 triggers reloading + chunk.getProjectileFlags().clearFlag(chunkOffsetX, chunkOffsetY); //the 'clear' value of 0 is the default state + } + } + } + } + } } public DynamicRegion(@NotNull ZoneBorders borders) { this(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6); setBorders(borders); - setUpdateAllPlanes(true); RegionManager.addRegion(getId(), this); } @@ -95,7 +98,7 @@ public final class DynamicRegion extends Region { public static DynamicRegion create(int regionId) { int x = (regionId >> 8) << 6; int y = (regionId & 0xFF) << 6; - return create(new ZoneBorders(x, y, x + SIZE, y + SIZE))[0]; + return create(new ZoneBorders(x, y, x + 64, y + 64))[0]; } /** @@ -109,7 +112,7 @@ public final class DynamicRegion extends Region { int y = (regionOne & 0xFF) << 6; int x1 = (regionTwo >> 8) << 6; int y1 = (regionTwo & 0xFF) << 6; - return create(new ZoneBorders(x, y, x1 + SIZE, y1 + SIZE))[0]; + return create(new ZoneBorders(x, y, x1 + 64, y1 + 64))[0]; } /** @@ -129,23 +132,18 @@ public final class DynamicRegion extends Region { for (int y = copy.getSouthWestY() >> 6; y < copy.getNorthEastY() >> 6; y++) { int regionId = x << 8 | y; Location loc = l.transform((x - baseX) << 6, (y - baseY) << 6, 0); - DynamicRegion region = copy(regionId, loc); - region.setBorders(border); - Region r = RegionManager.forId(region.getId()); - if (r != null) { - for (int z = 0; z < 4; z++) { - region.getPlanes()[z].getPlayers().addAll(r.getPlanes()[z].getPlayers()); - region.getPlanes()[z].getNpcs().addAll(r.getPlanes()[z].getNpcs()); - } - } - RegionManager.addRegion(region.getId(), region); - regions.add(region); + DynamicRegion dest = copy(regionId, loc); + dest.setBorders(border); + RegionManager.addRegion(dest.getId(), dest); + regions.add(dest); } } for (Region r : regions) { for (int z = 0; z < 4; z++) { - for (Player p : r.getPlanes()[z].getPlayers()) { - p.updateSceneGraph(false); + for (Player player : r.assemblePlayerList(z)) { + if (player != null) { + player.updateSceneGraph(false); + } } } } @@ -222,11 +220,13 @@ public final class DynamicRegion extends Region { int x = regionX + (offsetX << 3); int y = regionY + (offsetY << 3); for (int plane = 0; plane < 4; plane++) { - RegionChunk c = base.getPlanes()[plane].getRegionChunk(offsetX, offsetY); + RegionChunk c = base.getChunks()[offsetX][offsetY][plane]; if (c == null) { - region.chunks[plane][offsetX][offsetY] = c = new RegionChunk(Location.create(0, 0, 0), 0, region.getPlanes()[plane]); + c = new RegionChunk(Location.create(0, 0, 0), 0); + region.chunks[offsetX][offsetY][plane] = c; } else { - region.replaceChunk(plane, offsetX, offsetY, (c = c.copy(region.getPlanes()[plane])), base); + c = c.copy(); + region.replaceChunk(plane, offsetX, offsetY, c, base); } c.setRotation(0); c.setBase(Location.create(x, y, plane)); @@ -274,72 +274,25 @@ public final class DynamicRegion extends Region { getMusicZones().add(new MusicZone(musicId, borders)); } - /** - * Rotates the region 90% clockwise. - * TODO: Finish this - */ - public void rotate() { - for (int z = 0; z < 4; z++) { - RegionChunk[][] c = Arrays.copyOf(chunks[z], 8); - for (int x = 0; x < 8; x++) { - for (int y = 0; y < 8; y++) { - RegionChunk r = chunks[z][x][y] = c[8 - y - 1][x]; - if (r != null) { - r.setRotation(r.getRotation() + 1); - } - } - } - } - } - - /** - * Sets a region chunk (without setting objects/clipping flags). - * @param z The plane. - * @param x The chunk x (0-8). - * @param y The chunk y (0-8). - * @param chunk The chunk to set. - */ - public void setChunk(int z, int x, int y, RegionChunk chunk) { - chunks[z][x][y] = chunk; - getPlanes()[z].getChunks()[x][y] = chunk; - if (chunk != null) { - chunk.setCurrentBase(getBaseLocation().transform(x << 3, y << 3, 0)); - } - } - /** * Replaces a region chunk. * @param z The plane. * @param x The x-coordinate of the chunk. (0-7) * @param y The y-coordinate of the chunk. (0-7) - * @param chunk The chunk to replace with. + * @param replacement The chunk to replace with. * @param fromRegion The region the chunk is copied from. */ - public void replaceChunk(int z, int x, int y, RegionChunk chunk, Region fromRegion) { + public void replaceChunk(int z, int x, int y, RegionChunk replacement, Region fromRegion) { Region.load(DynamicRegion.this); - RegionPlane p = getPlanes()[z]; - chunks[z][x][y] = chunk; - p.getChunks()[x][y] = chunk; - if (chunk == null) { - for (int i = x << 3; i < (x + 1) << 3; i++) { - for (int j = y << 3; j < (y + 1) << 3; j++) { - p.getFlags().invalidateFlag(i, j); - p.getProjectileFlags().invalidateFlag(i, j); - Scenery object = p.getObjects()[i][j]; - if (object != null) { - LandscapeParser.removeScenery(object); - } else { - p.add(null, i, j, true); - } - } - } - } else { - Region.load(fromRegion); - Location l = chunk.getBase(); - RegionPlane rp = fromRegion.getPlanes()[l.getZ()]; - chunk.setCurrentBase(getBaseLocation().transform(x << 3, y << 3, z)); - chunk.rebuildFlags(rp); - } + chunks[x][y][z] = replacement; + Region.load(fromRegion); + RegionChunk orig = fromRegion.getChunks()[x][y][z]; + Location currentBase = getBaseLocation().transform(x << 3, y << 3, z); + replacement.setCurrentBase(currentBase); + replacement.rebaseObjects(); + replacement.rebuildFlags(orig); + replacement.syncFlagsToRegionManager(); + replacement.getNpcs().addAll(orig.getNpcs()); //DO NOT create a copy npc, because it won't be initialized! } @Override @@ -356,20 +309,18 @@ public final class DynamicRegion extends Region { } } } - if(!super.flagInactive(force)) { - return false; - } - for (RegionPlane plane : getPlanes()) { - for (int i = 0; i < plane.getNpcs().size(); i++) { - NPC npc = plane.getNpcs().get(0); - npc.clear(); - } - for (RegionChunk[] chunks : getChunks()[plane.getPlane()]) { - for (RegionChunk chunk : chunks) { - if (chunk != null) { - for (Iterator it = chunk.getItems().iterator(); it.hasNext();) { - GroundItemManager.getItems().remove(it.next()); - } + if (!super.flagInactive(force)) { + return false; + } + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + for (int z = 0; z < 4; z++) { + RegionChunk chunk = chunks[x][y][z]; + for (NPC npc : chunk.getNpcs()) { + npc.clear(); + } + for (GroundItem item : chunk.getItems()) { + GroundItemManager.destroy(item); } } } @@ -378,16 +329,16 @@ public final class DynamicRegion extends Region { if (multicombat) { toggleMulticombat(); } - boolean allLinkedInactive = true; + boolean allLinkedInactive = true; if (linked != null) { for (DynamicRegion r : linked) { allLinkedInactive &= r.flagInactive(force); } } - return allLinkedInactive; + return allLinkedInactive; } else { - return true; - } + return true; + } } @Override @@ -395,14 +346,6 @@ public final class DynamicRegion extends Region { return regionId; } - /** - * Gets the chunks. - * @return The chunks. - */ - public RegionChunk[][][] getChunks() { - return chunks; - } - /** * Gets the borders. * @return The borders. diff --git a/Server/src/main/core/game/world/map/build/LandscapeParser.java b/Server/src/main/core/game/world/map/build/LandscapeParser.java index 81025e7d6..3c6f44cec 100644 --- a/Server/src/main/core/game/world/map/build/LandscapeParser.java +++ b/Server/src/main/core/game/world/map/build/LandscapeParser.java @@ -3,11 +3,7 @@ package core.game.world.map.build; import core.cache.def.impl.SceneryDefinition; import core.cache.misc.buffer.ByteBufferUtils; import core.game.node.scenery.Scenery; -import core.game.world.map.Location; -import core.game.world.map.Region; -import core.game.world.map.RegionManager; -import core.game.world.map.RegionPlane; -import core.game.system.config.ObjectConfigParser; +import core.game.world.map.*; import java.nio.ByteBuffer; @@ -17,14 +13,13 @@ import java.nio.ByteBuffer; * */ public final class LandscapeParser { - /** * Parses the landscape. * @param r The region. * @param mapscape The mapscape data. * @param storeObjects If all objects should be stored (rather than just the objects with options). */ - public static void parse(Region r, byte[][][] mapscape, ByteBuffer buffer, boolean storeObjects) { + public static void parse(Region r, RegionChunk[][][] chunks, byte[][][] mapscape, ByteBuffer buffer, boolean storeObjects) { int objectId = -1; for (;;) { int offset = ByteBufferUtils.getBigSmart(buffer); @@ -39,23 +34,25 @@ public final class LandscapeParser { break; } location += offset - 1; - int y = location & 0x3f; - int x = location >> 6 & 0x3f; + int localY = location & 0x3f; + int localX = location >> 6 & 0x3f; int configuration = buffer.get() & 0xFF; int rotation = configuration & 0x3; int type = configuration >> 2; int z = location >> 12; r.setObjectCount(r.getObjectCount() + 1); - if (x < 0 || y < 0 || x >= 64 || y >= 64) { - - } else { - if ((mapscape[1][x][y] & 0x2) == 2) { - z--; - } - if (z >= 0 && z <= 3) { - Scenery object = new Scenery(objectId, Location.create((r.getX() << 6) + x, (r.getY() << 6) + y, z), type, rotation); - flagScenery(r.getPlanes()[z], x, y, object, true, storeObjects); - } + if ((mapscape[1][localX][localY] & 0x2) == 2) { + z--; + } + if (z >= 0 && z <= 3) { + Location loc = Location.create((r.getX() << 6) + localX, (r.getY() << 6) + localY, z); + Scenery object = new Scenery(objectId, loc, type, rotation); + int chunkX = loc.getChunkX(); + int chunkY = loc.getChunkY(); + int chunkOffsetX = loc.getChunkOffsetX(); + int chunkOffsetY = loc.getChunkOffsetY(); + RegionChunk chunk = chunks[chunkX][chunkY][z]; + flagScenery(chunk, chunkOffsetX, chunkOffsetY, object, true, storeObjects); } } } @@ -76,34 +73,34 @@ public final class LandscapeParser { */ public static void addScenery(Scenery object, boolean landscape) { Location l = object.getLocation(); - flagScenery(RegionManager.getRegionPlane(l), l.getLocalX(), l.getLocalY(), object, landscape, false); + flagScenery(RegionManager.getRegionChunk(l), l.getChunkOffsetX(), l.getChunkOffsetY(), object, landscape, false); } /** * Flags a scenery on the plane's clipping flags. - * @param plane The plane. + * @param chunk The chunk. * @param object The object. * @param landscape If we are adding this scenery permanent. * @param storeObjects If all objects should be stored (rather than just the objects with options). */ - public static void flagScenery(RegionPlane plane, int localX, int localY, Scenery object, boolean landscape, boolean storeObjects) { - Region.load(plane.getRegion()); + public static void flagScenery(RegionChunk chunk, int chunkOffsetX, int chunkOffsetY, Scenery object, boolean landscape, boolean storeObjects) { + Region r = chunk.getRegion(); + Region.load(r); SceneryDefinition def = object.getDefinition(); object.setActive(true); + object.setRenderable(true); boolean add = storeObjects || !landscape || def.getChildObject(null).hasActions(); if (add) { - addPlaneObject(plane, object, localX, localY, landscape, storeObjects); - } - - if (!applyClippingFlagsFor(plane, localX, localY, object)) - return; - - if (!storeObjects && !add && (!def.getChildObject(null).getName().equals("null"))) { - addPlaneObject(plane, object, localX, localY, landscape, false); + if (landscape) { + chunk.addStatDyn(object, chunkOffsetX, chunkOffsetY); + } else { + chunk.add(object); + } } + applyClippingFlagsFor(chunk, chunkOffsetX, chunkOffsetY, object); } - public static boolean applyClippingFlagsFor(RegionPlane plane, int localX, int localY, Scenery object) { + public static boolean applyClippingFlagsFor(RegionChunk chunk, int chunkOffsetX, int chunkOffsetY, Scenery object) { SceneryDefinition def = object.getDefinition(); int sizeX; int sizeY; @@ -116,27 +113,27 @@ public final class LandscapeParser { } int type = object.getType(); if (type == 22) { //Tile - plane.getFlags().getLandscape()[localX][localY] = true; + chunk.getFlags().getLandscape()[chunkOffsetX][chunkOffsetY] = true; if (def.interactable != 0 || def.clipType == 1 || def.secondBool) { if (def.clipType == 1) { - plane.getFlags().flagTileObject(localX, localY); + chunk.getFlags().flagTileObject(chunkOffsetX, chunkOffsetY); if (def.isProjectileClipped()) { - plane.getProjectileFlags().flagTileObject(localX, localY); + chunk.getProjectileFlags().flagTileObject(chunkOffsetX, chunkOffsetY); } } } } else if (type >= 9) { //Default objects if (def.clipType != 0) { - plane.getFlags().flagSolidObject(localX, localY, sizeX, sizeY, def.projectileClipped); + chunk.getFlags().flagSolidObject(chunkOffsetX, chunkOffsetY, sizeX, sizeY, def.projectileClipped); if (def.isProjectileClipped()) { - plane.getProjectileFlags().flagSolidObject(localX, localY, sizeX, sizeY, def.projectileClipped); + chunk.getProjectileFlags().flagSolidObject(chunkOffsetX, chunkOffsetY, sizeX, sizeY, def.projectileClipped); } } } else if (type >= 0 && type <= 3) { //Doors/walls if (def.clipType != 0) { - plane.getFlags().flagDoorObject(localX, localY, object.getRotation(), type, def.projectileClipped); + chunk.getFlags().flagDoorObject(chunkOffsetX, chunkOffsetY, object.getRotation(), type, def.projectileClipped); if (def.isProjectileClipped()) { - plane.getProjectileFlags().flagDoorObject(localX, localY, object.getRotation(), type, def.projectileClipped); + chunk.getProjectileFlags().flagDoorObject(chunkOffsetX, chunkOffsetY, object.getRotation(), type, def.projectileClipped); } } } else { @@ -145,24 +142,6 @@ public final class LandscapeParser { return true; } - /** - * Adds an object to the region plane. - * @param plane The region plane. - * @param object The object to add. - * @param localX The local x-coordinate. - * @param localY The local y-coordinate. - * @param landscape The landscape. - */ - private static void addPlaneObject(RegionPlane plane, Scenery object, int localX, int localY, boolean landscape, boolean storeAll) { - if (landscape && !storeAll) { - Scenery current = plane.getObjects()[localX][localY]; - if (current != null && current.getDefinition().getChildObject(null).hasOptions(!object.getDefinition().getChildObject(null).hasOptions(false))) { - return; - } - } - plane.add(object, localX, localY, landscape && !storeAll); - } - /** * Removes a scenery. * @param object The object. @@ -172,18 +151,23 @@ public final class LandscapeParser { if (!object.isRenderable()) { return null; } - RegionPlane plane = RegionManager.getRegionPlane(object.getLocation()); - Region.load(plane.getRegion()); - int localX = object.getLocation().getLocalX(); - int localY = object.getLocation().getLocalY(); - Scenery current = plane.getChunkObject(localX, localY, object.getId()); + + // Get and remove the object + Location loc = object.getLocation(); + Region region = RegionManager.forId(loc.getRegionId()); + Region.load(region); + RegionChunk chunk = region.getChunks()[loc.getChunkX()][loc.getChunkY()][loc.getZ()]; + int index = chunk.getIndex(loc.getChunkOffsetX(), loc.getChunkOffsetY(), object.getId(), object.getType()); + Scenery current = chunk.getObjects()[index][loc.getChunkOffsetX()][loc.getChunkOffsetY()]; if (current == null || current.getId() != object.getId()) { return null; } current.setActive(false); object.setActive(false); - plane.remove(localX, localY, object.getId()); + chunk.getObjects()[index][loc.getChunkOffsetX()][loc.getChunkOffsetY()] = null; SceneryDefinition def = object.getDefinition(); + + // Remove its clipping flags int sizeX; int sizeY; if (object.getRotation() % 2 == 0) { @@ -193,28 +177,30 @@ public final class LandscapeParser { sizeX = def.sizeY; sizeY = def.sizeX; } + int chunkOffsetX = loc.getChunkOffsetX(); + int chunkOffsetY = loc.getChunkOffsetY(); int type = object.getType(); if (type == 22) { //Tile if (def.interactable != 0 || def.clipType == 1 || def.secondBool) { if (def.clipType == 1) { - plane.getFlags().unflagTileObject(localX, localY); + chunk.getFlags().unflagTileObject(chunkOffsetX, chunkOffsetY); if (def.isProjectileClipped()) { - plane.getProjectileFlags().unflagTileObject(localX, localY); + chunk.getProjectileFlags().unflagTileObject(chunkOffsetX, chunkOffsetY); } } } } else if (type >= 9) { //Default objects if (def.clipType != 0) { - plane.getFlags().unflagSolidObject(localX, localY, sizeX, sizeY, def.projectileClipped); + chunk.getFlags().unflagSolidObject(chunkOffsetX, chunkOffsetY, sizeX, sizeY, def.projectileClipped); if (def.isProjectileClipped()) { - plane.getProjectileFlags().unflagSolidObject(localX, localY, sizeX, sizeY, def.projectileClipped); + chunk.getProjectileFlags().unflagSolidObject(chunkOffsetX, chunkOffsetY, sizeX, sizeY, def.projectileClipped); } } } else if (type >= 0 && type <= 3) { //Doors/walls if (def.clipType != 0) { - plane.getFlags().unflagDoorObject(localX, localY, object.getRotation(), type, def.projectileClipped); + chunk.getFlags().unflagDoorObject(chunkOffsetX, chunkOffsetY, object.getRotation(), type, def.projectileClipped); if (def.isProjectileClipped()) { - plane.getProjectileFlags().unflagDoorObject(localX, localY, object.getRotation(), type, def.projectileClipped); + chunk.getProjectileFlags().unflagDoorObject(chunkOffsetX, chunkOffsetY, object.getRotation(), type, def.projectileClipped); } } } diff --git a/Server/src/main/core/game/world/map/build/MapscapeParser.java b/Server/src/main/core/game/world/map/build/MapscapeParser.java index 7ecc4c81c..567b308cb 100644 --- a/Server/src/main/core/game/world/map/build/MapscapeParser.java +++ b/Server/src/main/core/game/world/map/build/MapscapeParser.java @@ -1,6 +1,7 @@ package core.game.world.map.build; import core.game.world.map.Region; +import core.game.world.map.RegionChunk; import java.nio.ByteBuffer; @@ -17,10 +18,25 @@ public final class MapscapeParser { * @param buffer The buffer. */ public static void parse(Region r, byte[][][] mapscape, ByteBuffer buffer) { + if (r.getChunks() == null) { + return; //this is a DynamicRegion that has been cleared + } + // The cache is packed by region, so we need to parse it along the local-x/y coordinates for (int z = 0; z < 4; z++) { - boolean[][] landscape = r.getPlanes()[z].getFlags().getLandscape(); - for (int x = 0; x < 64; x++) { - for (int y = 0; y < 64; y++) { + for (int localX = 0; localX < 64; localX++) { + for (int localY = 0; localY < 64; localY++) { + int chunkX = localX >> 3; + int chunkY = localY >> 3; + int chunkOffsetX = localX & 7; + int chunkOffsetY = localY & 7; + RegionChunk chunk = r.getChunks()[chunkX][chunkY][z]; + boolean[][] landscape; + if (chunk == null) { + // Still need to consume the buffer data even for null chunks + landscape = new boolean[8][8]; + } else { + landscape = chunk.getFlags().getLandscape(); + } while (true) { int value = buffer.get() & 0xFF; if (value == 0) { @@ -33,16 +49,14 @@ public final class MapscapeParser { if (value <= 49) { //Overlay data int val = buffer.get() & 0xFF; if (val != 42 && val > 0) { - landscape[x][y] = true; + landscape[chunkOffsetX][chunkOffsetY] = true; } - } - else if (value <= 81) { - mapscape[z][x][y] = (byte) (value - 49); - } - else { + } else if (value <= 81) { + mapscape[z][localX][localY] = (byte) (value - 49); + } else { int val = (byte) (value - 81) & 0xFF; //Underlay data if (val != 42 && val > 0) { - landscape[x][y] = true; + landscape[chunkOffsetX][chunkOffsetY] = true; } } } @@ -56,22 +70,30 @@ public final class MapscapeParser { * @param r The region. * @param mapscape The mapscape. */ - public static void clipMapscape(Region r, byte[][][] mapscape) { + public static void clipMapscape(Region r, RegionChunk[][][] chunks, byte[][][] mapscape) { for (int z = 0; z < 4; z++) { - for (int x = 0; x < 64; x++) { - for (int y = 0; y < 64; y++) { - r.getPlanes()[z].getFlags().flagEmptyTile(x,y); - if ((mapscape[z][x][y] & 0x1) == 1) { - int plane = z; - if ((mapscape[1][x][y] & 0x2) == 2) { - plane--; - } - if (plane > -1) { - r.getPlanes()[plane].getFlags().flagSolidTile(x, y); + for (int chunkX = 0; chunkX < 8; chunkX++) { + for (int chunkY = 0; chunkY < 8; chunkY++) { + RegionChunk chunk = chunks[chunkX][chunkY][z]; + for (int x = 0; x < 8; x++) { + for (int y = 0; y < 8; y++) { + chunk.getFlags().flagEmptyTile(x, y); + int chunkOffsetX = chunkX*8 + x; + int chunkOffsetY = chunkY*8 + y; + if ((mapscape[z][chunkOffsetX][chunkOffsetY] & 0x1) == 1) { + int plane = z; + if ((mapscape[1][chunkOffsetX][chunkOffsetY] & 0x2) == 2) { + plane--; + } + if (plane > -1) { + RegionChunk chunkToFlag = r.getChunks()[chunkX][chunkY][plane]; + chunkToFlag.getFlags().flagSolidTile(x, y); + } + } } } } } } } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java index 65b4a0322..1fe68e486 100644 --- a/Server/src/main/core/game/world/map/zone/ZoneMonitor.java +++ b/Server/src/main/core/game/world/map/zone/ZoneMonitor.java @@ -160,9 +160,9 @@ public final class ZoneMonitor { } if (entity instanceof Player && target instanceof Player) { if (!((Player) entity).getSkullManager().isWilderness() || !((Player) target).getSkullManager().isWilderness()) { - if(message) { - ((Player) entity).getPacketDispatch().sendMessage("You can only attack other players in the wilderness."); - } + if(message) { + ((Player) entity).getPacketDispatch().sendMessage("You can only attack other players in the wilderness."); + } return false; } } @@ -362,7 +362,7 @@ public final class ZoneMonitor { it.remove(); } } - for (RegionZone zone : entity.getViewport().getRegion().getRegionZones()) { + for (RegionZone zone : entity.getLocation().getRegion().getRegionZones()) { if (!zone.getBorders().insideBorder(entity)) { continue; } @@ -403,7 +403,7 @@ public final class ZoneMonitor { } } } - Region r = player.getViewport().getRegion(); + Region r = player.getLocation().getRegion(); for (MusicZone zone : r.getMusicZones()) { if (zone.getBorders().insideBorder(l.getX(), l.getY())) { zone.enter(player); diff --git a/Server/src/main/core/game/world/map/zone/impl/ModeratorZone.java b/Server/src/main/core/game/world/map/zone/impl/ModeratorZone.java index 1c8b113dd..d44cc9f7c 100644 --- a/Server/src/main/core/game/world/map/zone/impl/ModeratorZone.java +++ b/Server/src/main/core/game/world/map/zone/impl/ModeratorZone.java @@ -11,6 +11,7 @@ import core.game.world.map.Location; import core.game.world.map.RegionManager; import core.game.world.map.zone.MapZone; import core.game.world.map.zone.ZoneBorders; +import core.game.world.repository.Repository; /** * Represents the moderator zone. @@ -66,8 +67,6 @@ public class ModeratorZone extends MapZone { @Override public boolean interact(Entity entity, Node target, Option option) { - if (entity instanceof Player) { - } return super.interact(entity, target, option); } @@ -82,11 +81,11 @@ public class ModeratorZone extends MapZone { * @param on the toggle switch. */ public static final void toggle(final Player player, final boolean on) { - open = on ? true : false; + open = on; player.getPacketDispatch().sendMessage(getToggleMessage()); if (!open) { for (Player p : RegionManager.getLocalPlayers(center)) { - if (p == null || p.getDetails().getRights() == Rights.ADMINISTRATOR) { + if (p.getDetails().getRights() == Rights.ADMINISTRATOR) { continue; } home(p); @@ -123,10 +122,7 @@ public class ModeratorZone extends MapZone { * @return return True if so. */ public static boolean isOpen() { - if (!open) { - return false; - } - return true; + return open; } } diff --git a/Server/src/main/core/game/world/map/zone/impl/MultiwayCombatZone.java b/Server/src/main/core/game/world/map/zone/impl/MultiwayCombatZone.java index 77477b3b1..3723dcf70 100644 --- a/Server/src/main/core/game/world/map/zone/impl/MultiwayCombatZone.java +++ b/Server/src/main/core/game/world/map/zone/impl/MultiwayCombatZone.java @@ -3,7 +3,6 @@ package core.game.world.map.zone.impl; import core.game.node.entity.Entity; import core.game.node.entity.npc.NPC; import core.game.node.entity.player.Player; -import core.game.world.map.Direction; import core.game.world.map.Location; import core.game.world.map.MapDistance; import core.game.world.map.RegionManager; @@ -127,21 +126,21 @@ public final class MultiwayCombatZone extends MapZone { if (e.getProperties().isNPCWalkable()) { return true; } - for (NPC n : RegionManager.getLocalNpcs(e, MapDistance.RENDERING.getDistance() / 2)) { - if (n.isInvisible() || !n.getDefinition().hasAttackOption() || n == e) { - continue; - } - if(n.shouldPreventStacking(e)) { - int s1 = e.size(); - int s2 = n.size(); - int x = destination.getX(); - int y = destination.getY(); - Location l = n.getLocation(); - if(Pathfinder.isStandingIn(x, y, s1, s1, l.getX(), l.getY(), s2, s2)) { - return false; - } - } - } + for (NPC n : RegionManager.getLocalNPCs(e.getLocation(), MapDistance.RENDERING.getDistance() / 2)) { + if (n.isInvisible() || !n.getDefinition().hasAttackOption() || n == e) { + continue; + } + if(n.shouldPreventStacking(e)) { + int s1 = e.size(); + int s2 = n.size(); + int x = destination.getX(); + int y = destination.getY(); + Location l = n.getLocation(); + if(Pathfinder.isStandingIn(x, y, s1, s1, l.getX(), l.getY(), s2, s2)) { + return false; + } + } + } return true; } diff --git a/Server/src/main/core/game/world/objectparser/ObjectParser.java b/Server/src/main/core/game/world/objectparser/ObjectParser.java deleted file mode 100644 index 39b445e31..000000000 --- a/Server/src/main/core/game/world/objectparser/ObjectParser.java +++ /dev/null @@ -1,101 +0,0 @@ -package core.game.world.objectparser; - -import core.api.StartupListener; -import core.ServerConstants; -import core.game.node.scenery.Scenery; -import core.game.world.map.build.LandscapeParser; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import java.io.File; - -public class ObjectParser implements StartupListener { - - public void parseObjects(){ - if(ServerConstants.OBJECT_PARSER_PATH == null) return; - File f = new File(ServerConstants.OBJECT_PARSER_PATH); - if(!f.exists()){ - - return; - } - - try{ - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(f); - - NodeList parseList = doc.getElementsByTagName("ObjectAction"); - - - - for(int i = 0; i < parseList.getLength(); i++){ - Node parseNode = parseList.item(i); - if(parseNode.getNodeType() == Node.ELEMENT_NODE){ - Element parseElement = (Element) parseNode; - String type = parseElement.getAttribute("mode"); - switch(type){ - case "add": { - int id = Integer.parseInt(parseElement.getAttribute("id")); - int x = Integer.parseInt(parseElement.getAttribute("x")); - int y = Integer.parseInt(parseElement.getAttribute("y")); - int z = Integer.parseInt(parseElement.getAttribute("z")); - int objType = 10; - if (parseElement.hasAttribute("type")) { - objType = Integer.parseInt(parseElement.getAttribute("type")); - } - String rawDir = parseElement.getAttribute("direction"); - int dir = 1; - switch (rawDir) { - case "n": - dir = 1; - break; - case "ne": - dir = 2; - break; - case "nw": - dir = 0; - break; - case "w": - dir = 3; - break; - case "e": - dir = 4; - break; - case "sw": - dir = 5; - break; - case "se": - dir = 7; - break; - case "s": - dir = 6; - break; - } - LandscapeParser.addScenery(new Scenery(id, x, y, z, objType, dir)); - break; - } - case "remove": { - int id = Integer.parseInt(parseElement.getAttribute("id")); - int x = Integer.parseInt(parseElement.getAttribute("x")); - int y = Integer.parseInt(parseElement.getAttribute("y")); - int z = Integer.parseInt(parseElement.getAttribute("z")); - int objType = 10; - LandscapeParser.removeScenery(new Scenery(id,x,y,z)); - } - } - } - } - } catch (Exception e){ - e.printStackTrace(); - } - } - - @Override - public void startup() { - parseObjects(); - } -} diff --git a/Server/src/main/core/game/world/repository/Repository.kt b/Server/src/main/core/game/world/repository/Repository.kt index 0b97f197c..d2b09a4bd 100644 --- a/Server/src/main/core/game/world/repository/Repository.kt +++ b/Server/src/main/core/game/world/repository/Repository.kt @@ -127,7 +127,7 @@ object Repository { */ @JvmStatic fun findNPC(l: Location): NPC? { - for (n in RegionManager.getRegionPlane(l).npcs) { + for (n in RegionManager.getRegionChunk(l).npcs) { if (n.location == l) { return n } diff --git a/Server/src/main/core/game/world/update/MapChunkRenderer.kt b/Server/src/main/core/game/world/update/MapChunkRenderer.kt index b9e20112a..47e93ff53 100644 --- a/Server/src/main/core/game/world/update/MapChunkRenderer.kt +++ b/Server/src/main/core/game/world/update/MapChunkRenderer.kt @@ -6,6 +6,7 @@ import core.net.packet.PacketRepository import core.net.packet.context.ClearChunkContext import core.net.packet.out.ClearRegionChunk import java.util.* +import kotlin.math.abs /** * Handles the rendering of the player's surrounding map chunks. @@ -18,10 +19,20 @@ object MapChunkRenderer { */ @JvmStatic fun render(player: Player) { - val v = player.viewport val last = player.playerFlags.lastViewport val updated: MutableList = ArrayList() - val current = v.chunks + val current: MutableList> = ArrayList() + + val buildAreaDepth = 6 + for (dcx in -buildAreaDepth..+buildAreaDepth) { + val addX = ArrayList() + for (dcy in -buildAreaDepth..+buildAreaDepth) { + val newloc = player.location.chunkBase.transform(dcx*8, dcy*8, 0) + addX.add(newloc.chunk) + } + current.add(addX) + } + var sizeX = last.size for (x in 0 until sizeX) { val sizeY: Int = last[x].size @@ -55,7 +66,7 @@ object MapChunkRenderer { * @param c The region chunk. * @return `True` if so. */ - private fun containsChunk(list: Array>, c: RegionChunk): Boolean { + private fun containsChunk(list: MutableList>, c: RegionChunk): Boolean { val sizeList = list.size for (x in 0 until sizeList) { val chunkSize: Int = list[x].size diff --git a/Server/src/main/core/game/world/update/NPCRenderer.kt b/Server/src/main/core/game/world/update/NPCRenderer.kt index dbb2fd01c..815066844 100644 --- a/Server/src/main/core/game/world/update/NPCRenderer.kt +++ b/Server/src/main/core/game/world/update/NPCRenderer.kt @@ -30,7 +30,7 @@ object NPCRenderer { val it: Iterator = localNPCs.iterator() while (it.hasNext()) { val npc = it.next() - val withinDistance = player.location.withinDistance(npc.location) + val withinDistance = player.location.withinDistance(npc.location, 15) if (npc.isHidden(player) || !withinDistance || npc.properties.isTeleporting) { buffer.putBits(1, 1).putBits(2, 3) toRemove.add(npc) @@ -51,7 +51,7 @@ object NPCRenderer { } } localNPCs.removeAll(toRemove) - for (npc in RegionManager.getLocalNpcs(player)) { + for (npc in RegionManager.getLocalNPCs(player.location, 15)) { if (localNPCs.size >= 255) { break } diff --git a/Server/src/main/core/game/world/update/PlayerRenderer.kt b/Server/src/main/core/game/world/update/PlayerRenderer.kt index e192463d7..b20ab8dd5 100644 --- a/Server/src/main/core/game/world/update/PlayerRenderer.kt +++ b/Server/src/main/core/game/world/update/PlayerRenderer.kt @@ -3,6 +3,7 @@ package core.game.world.update import core.game.node.entity.player.Player import core.game.node.entity.player.info.RenderInfo import core.game.world.map.RegionManager +import core.game.world.repository.Repository import core.net.packet.IoBuffer import core.net.packet.PacketHeader @@ -39,7 +40,7 @@ object PlayerRenderer { renderLocalPlayer(player, other, buffer, flags) } var count = 0 - for (other in RegionManager.getLocalPlayers(player, 15)) { + for (other in RegionManager.getLocalPlayers(player.location, 15)) { if (other === player || !other.isActive || info.localPlayers.contains(other) || other.isInvisible) { continue } @@ -177,4 +178,4 @@ object PlayerRenderer { player.updateMasks.write(local, player, flags) } } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/world/update/flag/PlayerFlags.java b/Server/src/main/core/game/world/update/flag/PlayerFlags.java index c67408a65..41d0cb441 100644 --- a/Server/src/main/core/game/world/update/flag/PlayerFlags.java +++ b/Server/src/main/core/game/world/update/flag/PlayerFlags.java @@ -2,7 +2,6 @@ package core.game.world.update.flag; import core.game.world.map.Location; import core.game.world.map.RegionChunk; -import core.game.world.map.Viewport; /** * A class holding a player's updating flags. @@ -18,11 +17,11 @@ public final class PlayerFlags { /** * The last viewport. */ - private RegionChunk[][] lastViewport = new RegionChunk[Viewport.CHUNK_SIZE][Viewport.CHUNK_SIZE]; + private RegionChunk[][] lastViewport = new RegionChunk[13][13]; /** * The location the player was standing on when last scene graph update - * occured. + * occurred. */ private Location lastSceneGraph; diff --git a/Server/src/main/core/game/worldevents/holiday/christmas/randoms/SnowStormHolidayRandomNPC.kt b/Server/src/main/core/game/worldevents/holiday/christmas/randoms/SnowStormHolidayRandomNPC.kt index c10d937f2..9482068c7 100644 --- a/Server/src/main/core/game/worldevents/holiday/christmas/randoms/SnowStormHolidayRandomNPC.kt +++ b/Server/src/main/core/game/worldevents/holiday/christmas/randoms/SnowStormHolidayRandomNPC.kt @@ -69,4 +69,4 @@ class SnowStormHolidayRandomNPC : HolidayRandomEventNPC(NPCs.SNOW_6740) { override fun talkTo(npc: NPC) { } -} \ No newline at end of file +} diff --git a/Server/src/main/core/net/packet/PacketProcessor.kt b/Server/src/main/core/net/packet/PacketProcessor.kt index c05798490..7a05cc549 100644 --- a/Server/src/main/core/net/packet/PacketProcessor.kt +++ b/Server/src/main/core/net/packet/PacketProcessor.kt @@ -1,6 +1,5 @@ package core.net.packet -import content.global.ame.events.maze.MazeInterface import content.global.handlers.iface.ge.StockMarket import content.global.skill.magic.SpellListener import content.global.skill.magic.SpellListeners @@ -580,7 +579,7 @@ object PacketProcessor { } else if (pkt is Packet.UseWithScenery) { item = pkt.player.inventory[pkt.slot] ?: return sendClearMinimap(pkt.player) - node = RegionManager.getObject(pkt.player.location.z, pkt.x, pkt.y) ?: return sendClearMinimap(pkt.player) + node = RegionManager.getObject(pkt.player.location.z, pkt.x, pkt.y, pkt.sceneryId) ?: return sendClearMinimap(pkt.player) childNode = node.asScenery().getChild(pkt.player) itemId = pkt.itemId nodeId = node.id @@ -690,11 +689,6 @@ object PacketProcessor { if (pkt.id == 6899) scenery = Scenery(6899, Location(3221, 9618)) - // Random Event Maze chests are overridden by the walls, which needs to be hacked in. - if ((scenery?.id == 3626 || scenery?.id == 3635) && (objId in 3635..3636)) { - scenery = MazeInterface.overrideScenery(scenery, objId) - } - // Family crest levers don't have varps associated with them, so their state is validated with attributes // instead, and they always appear as their down/odd variant in the server's map if (objId in 2421..2426 && objId % 2 == 0) { diff --git a/Server/src/main/core/net/packet/out/BuildDynamicScene.java b/Server/src/main/core/net/packet/out/BuildDynamicScene.java index 3cea2b5db..f9719651f 100644 --- a/Server/src/main/core/net/packet/out/BuildDynamicScene.java +++ b/Server/src/main/core/net/packet/out/BuildDynamicScene.java @@ -29,17 +29,15 @@ public final class BuildDynamicScene implements OutgoingPacket> 3) << 8 | (y >> 3)); + for (int x = baseX; x <= player.getLocation().getRegionX() + 6; x++) { + for (int y = baseY; y <= player.getLocation().getRegionY() + 6; y++) { + for (int z = 0; z < 4; z++) { + Region r = RegionManager.forId((x >> 3) << 8 | (y >> 3)); if (r instanceof DynamicRegion) { - DynamicRegion dr = (DynamicRegion) r; - chunks[z][x - baseX][y - baseY] = dr.getChunks()[z][x - (dr.getX() << 3)][y - (dr.getY() << 3)]; + chunks[x - baseX][y - baseY][z] = r.getChunks()[x - (r.getX() << 3)][y - (r.getY() << 3)][z]; } } } @@ -47,7 +45,7 @@ public final class BuildDynamicScene implements OutgoingPacket - base.planes[destPlane].getRegionChunk(destChunkX, destChunkY) + base.chunks[destchunkX][destChunkY][destPlane] }.from(base).onPlanes(0, 1, 2, 3) ) val region = specification.build() @@ -94,7 +93,7 @@ class RegionSpecificationTests { @Test fun shouldAllowUseExistingDynamicRegion() { val base = RegionManager.forId(12850) Region.load(base) - val chunk = base.planes[0].getRegionChunk(2, 2) + val chunk = base.getChunks()[2][2][0] val dyn = DynamicRegion.create(12850) val specification = RegionSpecification ( using(dyn), @@ -109,13 +108,13 @@ class RegionSpecificationTests { @Test fun fillChunkContractShouldAllowChunkSetCallback() { class TemporaryFillContract(chunk: RegionChunk) : FillChunkContract(chunk) { var callBackRan = false - override fun afterSetting(chunk: BuildRegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) { + override fun afterSetting(chunk: RegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) { callBackRan = true } } val base = RegionManager.forId(12850) Region.load(base) - val chunk = base.planes[0].getRegionChunk(2, 2) + val chunk = base.getChunks()[2][2][0] val dyn = DynamicRegion.create(12850) val fillTemporary = TemporaryFillContract(chunk) val specification = RegionSpecification ( diff --git a/Server/src/test/kotlin/RegionTests.kt b/Server/src/test/kotlin/RegionTests.kt index 7e48c338a..68f0b428a 100644 --- a/Server/src/test/kotlin/RegionTests.kt +++ b/Server/src/test/kotlin/RegionTests.kt @@ -1,14 +1,8 @@ -import core.cache.Cache import core.game.world.map.Region -import core.game.world.map.RegionChunk import core.game.world.map.RegionManager import core.game.world.map.build.DynamicRegion -import core.game.world.map.build.LandscapeParser -import org.junit.Assert import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test -import core.game.system.config.ServerConfigParser -import core.game.system.config.XteaParser class RegionTests { companion object { @@ -67,8 +61,8 @@ class RegionTests { Region.load(dynamic) val targetLoc = dynamic.baseLocation.transform(23, 17, 0) Assertions.assertEquals(null, RegionManager.getObject(targetLoc), "Object exists pre-copy?") - val replacement = base.planes[0].getRegionChunk(2, 2) - dynamic.replaceChunk(0, 2, 2, replacement.copy(dynamic.planes[0]), base) + val replacement = base.getChunks()[2][2][0] + dynamic.replaceChunk(0, 2, 2, replacement.copy(), base) Assertions.assertEquals(36782, RegionManager.getObject(targetLoc)?.id ?: -1, "Object does not exist at expected location!") } @@ -79,8 +73,8 @@ class RegionTests { Region.load(dynamic, true) val targetLoc = dynamic.baseLocation.transform(23, 17, 0) Assertions.assertEquals(null, RegionManager.getObject(targetLoc), "Object exists pre-copy?") - val replacement = base.planes[0].getRegionChunk(2, 2) - dynamic.replaceChunk(0, 2, 2, replacement.copy(dynamic.planes[0]), base) + val replacement = base.getChunks()[2][2][0] + dynamic.replaceChunk(0, 2, 2, replacement.copy(), base) Assertions.assertEquals(36782, RegionManager.getObject(targetLoc)?.id ?: -1, "Object does not exist at expected location!") } @@ -89,11 +83,10 @@ class RegionTests { val borders = DynamicRegion.reserveArea(8,8) val dynamic = DynamicRegion(-1, borders.southWestX shr 6, borders.southWestY shr 6) dynamic.borders = borders - dynamic.isUpdateAllPlanes = true RegionManager.addRegion(dynamic.id, dynamic) val targetLoc = dynamic.baseLocation.transform(23, 17, 0) - val replacement = base.planes[0].getRegionChunk(2,2) - dynamic.replaceChunk(0, 2, 2, replacement.copy(dynamic.planes[0]), base) + val replacement = base.getChunks()[2][2][0] + dynamic.replaceChunk(0, 2, 2, replacement.copy(), base) Assertions.assertEquals(36782, RegionManager.getObject(targetLoc)?.id ?: -1, "Object does not exist at expected location!") } @@ -102,11 +95,10 @@ class RegionTests { val borders = DynamicRegion.reserveArea(8,8) val dynamic = DynamicRegion(-1, borders.southWestX shr 6, borders.southWestY shr 6) dynamic.borders = borders - dynamic.isUpdateAllPlanes = true RegionManager.addRegion(dynamic.id, dynamic) val targetLoc = dynamic.baseLocation.transform(23, 17, 0) - val replacement = base.planes[0].getRegionChunk(2,2) - dynamic.replaceChunk(0, 2, 2, replacement.copy(dynamic.planes[0]), base) + val replacement = base.getChunks()[2][2][0] + dynamic.replaceChunk(0, 2, 2, replacement.copy(), base) base.link(dynamic) Assertions.assertEquals(36782, RegionManager.getObject(targetLoc)?.id ?: -1, "Object does not exist at expected location!") } diff --git a/Server/src/test/kotlin/TestUtils.kt b/Server/src/test/kotlin/TestUtils.kt index b8d8d45cd..5f672e627 100644 --- a/Server/src/test/kotlin/TestUtils.kt +++ b/Server/src/test/kotlin/TestUtils.kt @@ -146,10 +146,13 @@ class MockPlayer(name: String, val isBot: Boolean) : Player(PlayerDetails(name)) finishClear() } - override fun setLocation(location: Location?) { + override fun setLocation(location: Location) { super.setLocation(location) - RegionManager.move(this) + location.chunk.addPlayer(this) + location.region.incrementViewAmount() + location.region.flagActive() this.playerFlags.lastSceneGraph = location + zoneMonitor.updateLocation(walkingQueue.footPrint) } fun relog(ticksToWait: Int = -1) { diff --git a/Server/src/test/kotlin/content/activity/blastfurnace/BlastFurnaceAreaTests.kt b/Server/src/test/kotlin/content/activity/blastfurnace/BlastFurnaceAreaTests.kt index 8926443f1..870d1b265 100644 --- a/Server/src/test/kotlin/content/activity/blastfurnace/BlastFurnaceAreaTests.kt +++ b/Server/src/test/kotlin/content/activity/blastfurnace/BlastFurnaceAreaTests.kt @@ -242,4 +242,4 @@ class BlastFurnaceAreaTests { BlastFurnaceListeners().defineListeners() } } -} \ No newline at end of file +} diff --git a/Server/src/test/kotlin/core/PathfinderTests.kt b/Server/src/test/kotlin/core/PathfinderTests.kt index 84f6c640c..eebeb5219 100644 --- a/Server/src/test/kotlin/core/PathfinderTests.kt +++ b/Server/src/test/kotlin/core/PathfinderTests.kt @@ -116,6 +116,22 @@ class PathfinderTests { } } + @Test fun entityTargetMovementPulseShouldTolerateMissingTargetLocation() { + TestUtils.getMockPlayer("missingtargetloc").use { p -> + p.location = ServerConstants.HOME_LOCATION + val npc = NPC.create(0, NPC_TEST_LOC) + npc.setLocation(null) + + val pulse = object : MovementPulse(p, npc) { + override fun pulse(): Boolean { + return true + } + } + + Assertions.assertDoesNotThrow { pulse.update() } + } + } + @Test fun entityTargetMovementPulseShouldNotStopOnSameTileAsEntity() { TestUtils.getMockPlayer("entitystoptest").use {p -> p.location = ServerConstants.HOME_LOCATION @@ -257,4 +273,4 @@ class PathfinderTests { Assertions.assertEquals(true, npc.location.getDistance(ServerConstants.HOME_LOCATION!!) <= 5) } } -} \ No newline at end of file +} diff --git a/Server/worldprops/default.conf b/Server/worldprops/default.conf index 308db7417..645811200 100644 --- a/Server/worldprops/default.conf +++ b/Server/worldprops/default.conf @@ -22,7 +22,7 @@ noauth_default_admin = true #NOTE: If we are not using auth, this determines whe #------------------------------------------------------------------------------------------------------ #The limit on how many different accounts a player can log into per day. daily_accounts_per_ip = 3 -watchdog_enabled = true +watchdog_enabled = false connectivity_check_url = "https://google.com,https://2009scape.org" connectivity_timeout = 500 # Enables a websocket listener for browser clients. The websocket stream carries the